C++模板部分特化

3
这可能是有人之前提出的问题,但我找不到它...
我在一个.hpp文件中有一个类:
class A{
    public:
        A(){//constructor}
        ~A(){//destructor}
        //some public methods and arguments

        template<typename Type>
            void func(Type t){//do something for numbers}

    private:
        //some private methods and arguments
}

模板方法应该适用于int, double等数据类型,但不适用于字符串。因此在我的.hpp文件中,我定义了func对数字的操作,在我的.cpp文件中写入:

template<>
void A::func(std::string t){ // do something in that case}

但是当我使用带有 std::string 的函数 func 时,程序会调用数字的方法... 因此我将 .hpp 文件替换为:

class A{
    public:
        A(){//constructor}
        ~A(){//destructor}
        //some public methods and arguments

        template<typename Type>
            void func(Type t){//do something for numbers}
        void func(std::string s);

    private:
        //some private methods and arguments
}

我的.cpp文件变成了:

void A::func(std::string t){ // do something in that case}

然后一切都正常工作!

我的问题是,这是正确的做法吗?


我猜第二个大块是hpp,而不是cpp?对吗? - Bruce
是的,我已经更正了那个错误...抱歉。 - PinkFloyd
没问题,我只是不确定所以没有自己编辑。 - Bruce
2个回答

3
这不是部分特化(没有未特化的模板参数),而是显式特化。
模板必须对使用它们的代码可见,如果您不在头文件中声明特化,则尝试使用 string 调用 A::func 的代码将实例化主模板(数字模板)并使用它,因为它们不知道 `string` 特化甚至存在。
因此,为了使其在 .cpp 文件之外可用,您必须(至少)在头文件中声明特化。
template<>
void A::func(std::string t);

然而,使用重载的替代方法更简单,完全可行。这是因为string的重载在头文件中声明,所以调用它的代码知道要调用哪个函数。


如果我理解正确,头文件应该包含 template<> void func(std::string s){//to something} 或者 void func(std::string s){//do something} - PinkFloyd
不,你理解错了。那些是定义。头文件只需要包含声明,而不是定义(如果它们被标记为“inline”,则也可以包含定义)。 - Jonathan Wakely
但对于模板,定义在头文件里...是吧?! - PinkFloyd
头文件可以包含定义,如果它们是直接给出的,我的意思是在类定义内部...对吧? - PinkFloyd
1
对于类模板、非特化函数模板和内联函数,定义必须在头文件中。类定义中的成员函数定义隐式地是内联的。 - Jonathan Wakely

0

重载是许多目的的好方法。然而,我怀疑您原始的模板方法也可以工作,只要您为const char *添加一个专门化。这样,您就可以传递字符串文字,而不会解析为数字版本。


我不确定我理解你的意思... "resolving to the numbers version" 是什么意思? - PinkFloyd
在原问题中,您指出调用了数字方法而不是专门针对字符串的方法。我可能错了,但我猜测您传递了一个字符串字面值?字符串字面值解析为const char *,这是一种数值类型,这就是为什么它调用了数字方法而不是字符串方法的原因。 - Peter Bloomfield
像这样:func("blalba")?不,我传递了一个字符串,就像这样:std::string s("blabla"); func(s) - PinkFloyd
哦,我明白了。我的错误。我看到问题已经在其他答案中得到解决了。 :) - Peter Bloomfield

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接