无法正确获取方法模板专门化

时间:2013-12-16 00:15:04

标签: c++ templates specialization

我有一个模板类,否则可以正常工作,除非我需要在类型T为字符串的情况下重载insert方法。

template <class T> 
class hashtable{
 public:
    void insert(T item){
        /* Do Stuff */          
        };
    template<> void insert(string item){
        /* Do different stuff */
        };
}

这是抛出错误C2912:显式特化; 'void hashtable :: insert(std :: string)'不是函数模板的特化。

我不确定我做错了什么,或者我怎么解决这个问题。根据T是否为字符串,我需要的是一种不同地调用insert函数的方法。

6 个答案:

答案 0 :(得分:2)

您根本不需要添加template字。你只需重载模板功能。

class hashtable{
 public:
    template <typename T>
    void insert(T item){
        /* Do Stuff */          
    };

    void insert(string item){
        /* Do different stuff.
        Implementation can go to *.cpp file if necessary. 
        */
    };
};

请注意,无论设计如何,当您尝试insert可隐式转换为std :: string的类型(包括const std::string &const char*)时,您都会遇到麻烦。信不信由你,在C ++ 03中,std :: string甚至有来自int的隐式构造函数!

这就是为什么人们通常更喜欢将散列表类化身,而不是函数。

答案 1 :(得分:0)

您需要在模板括号中指定专门化:

template<class string> void insert(string item) ...

模板&lt;&gt;消除类专门化中的所有参数时使用。这里有一个例子:

http://www.cplusplus.com/doc/tutorial/templates/#template_specialization

答案 2 :(得分:0)

在类定义之外编写专门化:

template <typename T> class hashtable { /* ... */ };

template <> void hashtable<std::string>::insert(std::string item)
{
    // ...
}

答案 3 :(得分:0)

我不确定这堂课的重点。你在T类中有一个内部对象吗?如果没有,我会做以下事情:

class hashtable{
 public:
    template <typename T>
    void insert(T item){
        /* Do Stuff */          
        };

    template<>
    void insert(string item){
        /* Do different stuff */
        };
}

如果你在课堂上确实有T型,那么也许你正在寻找这个:

template <typename T>
class hashtable{
 public:
    template <typename P>
    void insert(P item){
        /* Do Stuff */          
        };

    template<>
    void insert(string item){
        /* Do different stuff */
        };
}

你需要详细说明你想要做的事情。

答案 4 :(得分:0)

最简单的方法是标记dispstching /

创建一个继承自std::true_typestd::false_type的traits类,具体取决于您要使用的实现。

然后使用implture_type参数编写两个false_type方法,如下所示:

 template<typename T> void insert(T&& t) { insert_impl(std::forward<T>(t), traits_test<T>() ); }

template<typename T> void insert_impl(T t, std::true_type descriptive_name ){ code }
template<typename T> void insert_impl(T t, std::false_type another_desc_name ){ code }
通过这样做,你可以避免不必要的专业化样板,只需调整traits类就可以轻松扩展代码。

方法专业化有点古怪,甚至比功能模板专业化更多。通过使用标签调度,根据我的经验,对发生的事情的推理变得更容易。

答案 5 :(得分:0)

好吧,也许最好以另一种方式思考 - 你有模板数据结构,所以你应该专注于整个结构而不仅仅是一个函数 - 因为如果你需要专门化这种类型的另一种方法(这里 - 对于字符串),你会把它专门化在同一个类中 - 它会破坏代码。我的解决方案的变体如上:

template <class T> 
class hashtable{
 public:
    void insert(T item){
        /* Do Stuff */          
        };
}
template <string> 
class hashtable{
 public:
    void insert(string item){
        /* Do different stuff */          
    };
}

作为版本 - 您可以使用模板散列函数编写散列表 - 这将删除任何特化。但显然,你需要为字符串编写自己的函数。 int和hashtable的示例:

 template <class T>
 LinearHashFunction {
     int a,b;
     static const int prime = /* some big prime number */
     LinearHashFunction(int a, int b):a(a), b(b) {}
     int operator()(T item) {
         return static_cast<int>(item)*a + b;
     }
 };

 template <class T, class THashFunction> 
 class hashtable{
 private:
    THashFunction<T> hash;
 public:
    void insert(T item){
            /* Do Stuff */
            // get hash:
            int elementsHash = hash(item);          
            };
    template<> void insert(string item){
            /* Do different stuff */
            };
    };