0

私は単純なハッシュテーブルテンプレートを持っています.

template <class K, class V, long H(K)>
class HashTableAbs{/* .... */}
//where K is key type, V is value type, H gives hash code for K value

単純な継承クラス

template <class K, class V, long H(K)>
class HashTable:public HashTableAbs<K, V, H> {}; 

そして、デフォルトのハッシュ関数を使用して、このテンプレートを文字列に特化したいと考えています

template <class V> 
class HashTable<std::string, V, strSimpleHash>:public HashTableAbs<std::string, V, strSimpleHash> {};
//where strSimpleHash is long strSimpleHash(std::string)

しかし、このコンパイラをコンパイルしようとすると、これを書きます

test.o: In function `strSimpleHash(std::string)':
test.cpp:(.text+0x0): multiple definition of `strSimpleHash(std::string)'
/tmp/main-i7yPhc.o:main.cc:(.text+0x0): first defined here
clang: error: linker command failed with exit code 1 (use -v to see invocation)

(テストには HashTable が定義されている hashtable.h が含まれます) strSimpleHash は hashtable.h でのみ定義されます

抜け道はありますか?PS 書き間違い失礼しました。私の母国語ではない英語

4

1 に答える 1

3

このエラーは、実際にはテンプレートとは関係ありません。関数の多重定義です。strSimpleHash使用せずにヘッダーで定義したと思いますinline(この関数を定義するコードを追加しませんでした)。

HashTableコメントで、次のような使用方法を尋ねました。

HashTable<std::string, int> // (ie, without passing the 3rd argument)

これは直接可能ではありません。テンプレート引数のデフォルト値を指定することはできますが (特殊化では指定できません)、たとえば次のようになります。

template<int n = 0> struct dummy {};
dummy<> obj;

あなたの場合、テンプレートの一般的なケースは type の関数のみを受け入れないため、それを行うことはできませんlong(std::string)。ただし、可能なタイプごとにデフォルト関数を割り当てることで、これを回避することができます。コードが少し明確になるため、関数へのポインタを使用する必要があることに注意してください。

// A C++03-style template typedef
template<typename K>
struct HashFunc
{
    typedef long (*type)(K);
};

// The default value. Defined only for some cases,
// compile error for not handled cases
template<typename K>
struct DefaultHash;

template<>
struct DefaultHash<std::string>
{
    // Static constant pointer-to-function, pointing to the hash func.
    static constexpr HashFunc<std::string>::type func = &strSimpleHash;
};

// The HashTable class
template <class K, class V, typename HashFunc<K>::type H = DefaultHash<K>::func>
class HashTable
{
};

template <class V> 
class HashTable<std::string, V, strSimpleHash>
{
};

その後、3 番目のテンプレート パラメーターを省略して、必要に応じて使用できます。このコードは gccではコンパイルされますが、clang ではコンパイルされないことに注意してください。(実際、どのコンパイラが正しいかはわかりません...)

于 2013-04-07T18:45:26.970 に答える