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>
{
};

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

于 2013-04-07T18:45:26.970 回答