2013-04-07 78 views
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.h) strSimpleHash仅被定义在hashtable.h

有没有出路? PS抱歉我写错了。英语不是我的母语

+0

您是否在模板特化之前或之后定义了strSimpleHash?它需要在之前。 – Dave 2013-04-07 18:42:24

+0

我将它定义模板和模板特 – 2013-04-07 18:44:55

+0

之前,请表现出更多,代码,尤其是在其中定义'strSimpleHash',更完整的答案的一部分。 – Synxis 2013-04-07 18:46:26

回答

3

此错误是不是真的涉及到的模板。它是一个函数的多重定义。我想你已经在头文件中定义了strSimpleHash而没有使用inline(你没有在你定义这个函数的地方添加代码)。

您在您的评论中问道,一种使用HashTable类似如下:

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

这是不能直接成为可能。 Althought你可以指定一个模板参数的默认值(而不是在一个专门化),例如:

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

你的情况,你不能这样做,因为你的模板,一般情况下不接受的唯一功能类型为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> 
{ 
}; 

然后你可以使用它作为你想,省略了第三个模板参数。请注意,此代码为compiles on gcc,但是not on clang(实际上,我不确定哪个编译器是正确的......)

+0

太棒了!我将内联添加到strSimpleHash并编译。但是,当我试图定义HashTable *表,编译器写入:test.cpp:126:17:错误:类模板太少的模板参数'HashTable' void printTable(HashTable * table) – 2013-04-07 18:52:07

+0

太棒了!对于你在注释中的内容,你忘了传递函数:'HashTable * table;'。 – Synxis 2013-04-07 18:54:28

+0

我可以专注我的模板,使这个(哈希表<的std :: string,int>的*表)是否有效? – 2013-04-07 18:59:02