C ++模板成员专门化 - 这是编译器限制吗?

时间:2010-06-10 14:48:11

标签: c++ templates

是否可以进行这种专业化?
如果是这样,怎么样?

有问题的专业标记为 //此专业化不会编译 我使用过VS2008,VS2010,gcc 4.4.3,但都不能编译它。

我知道我可以通过重载 func 来避免这种情况,但我想知道是否有办法通过模板特化来实现这一点。 (尽管可能是不切实际的/不可取的)

#include<iostream>
#include<string>

using namespace std;

template <typename ALPHA>
class klass{
    public:
        template <typename BETA>
        void func(BETA B);
};

template <typename ALPHA> template <typename BETA>
void klass<ALPHA>::func(BETA B){
    cout << "I AM A BETA FUNC: " << B <<endl;
}

//THIS SPECIALIZATION WILL NOT COMPILE
template <typename ALPHA> template <>
void klass<ALPHA>::func(string B){
    cout << "I AM A SPECIAL BETA FUNC: " << B <<endl;
}

int main(){
    klass<string> k;
    k.func(1);
    k.func("hello");
    return 0;
}

2 个答案:

答案 0 :(得分:6)

只需使stringfunc版本为模板版本重载的常规非模板成员函数:

#include<iostream>
#include<string>

using namespace std;

template <typename ALPHA>
class klass{
    public:
        template <typename BETA>
        void func(BETA B);
        void func(string b);
};

template <typename ALPHA> template <typename BETA>
void klass<ALPHA>::func(BETA B){
    cout << "I AM A BETA FUNC: " << B <<endl;
}

template <typename ALPHA>
void klass<ALPHA>::func(string B){
    cout << "I AM A SPECIAL BETA FUNC: " << B <<endl;
}

int main(){
    klass<string> k;
    k.func(1);
    k.func("hello");
    return 0;
}

除了编译之外,还有另一个好处,即您将获得更直观的行为。请参阅"Why Not Specialize Function Templates?" from GOTW

编辑:要直接回答原始问题,这不是编译器限制,它是C ++标准不允许的内容。

C ++标准,14.7.3 / 18(部分)说:

  

明确的专业化   一个班级成员的声明   模板或成员模板   出现在命名空间作用域中的成员   模板和它的一些封闭   类模板可能会保留   非专业,除了   声明不得明确   如果要专门化一个类成员模板   它的封闭类模板不是   也明确专业。

这意味着由于klass是一个模板,因此如果不专门设置klass::func,则无法专门化klass

答案 1 :(得分:3)

要回答标题中提出的问题:不,这不是编译器限制。这是一种语言限制。在C ++中,为了明确地专门化嵌套模板(是类模板或成员函数模板),您还必须明确地专门化封闭模板。

您正在尝试显式专门化嵌套模板而不专门化封闭模板。这不会编译。

当涉及到成员函数模板时,当模板参数与某个函数参数相关联时(如在您的情况下),您通常可以使用重载替换显式特化,如Tyler的答案中所建议的那样。在其他情况下,您必须使用不同的解决方法。