2010-06-10 101 views
4

是否有可能做这种专业化?
如果是这样,怎么样?C++模板成员专业化 - 这是一个编译器限制吗?

有问题的专门标记//这种专业化将无法编译 我使用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; 
} 
+0

如果您将专业化更改为'void klass :: func (string B);'?这样它就是一个功能模板的全面专业化(在模板类中)。至少,我想,我现在没有编译器。 – Pieter 2010-06-10 14:55:26

+0

用g ++示例编译器没有错误。 – sth 2010-06-10 15:01:26

回答

3

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

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

当谈到成员函数模板时,当模板参数与某个函数参数(如你的情况)相关联时,你可以经常用重载来替换显式的特化,正如泰勒的答案所建议的。在其他情况下,您必须使用其他解决方法。

6

只是使string版本的func与模板版本超载常规非模板成员函数:

#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专门klass::func

+0

这不起作用,k.func(“hello”);将调用模板函数而不是重载函数。 – LoudNPossiblyWrong 2010-06-10 15:02:55

+1

由于'“hello”'是一个'const char *',而不是'string'。为'const char *'添加另一个重载,或者调用为'k.func(string(“hello”))''。 – 2010-06-10 15:04:39