今天写STL中 rb_tree 的时候意外的发现一个问题:模板类的模板成员函数不能在类定义外部进行特化,特化必须放在类定义内,否则将报错:error C2244: “X<Val>::test”: 无法将函数定义与现有的声明匹配
经过写如下的简单代码可以看出问题所在:(错误版本)
//定义模板类X。其中拥有模板成员 test template<class Val> class X { public: X(){} template<class Type> void test(Type); }; //定义模板函数 template<class Val> template<class Type> void X<Val>::test(Type x) { cout << "in common " << endl; } //特化模板函数 template<class Val> template<> void X<Val>::test(int x) { cout << "in int " << endl; }
上述代码中,在编译时将报错,错误处在特化模板函数时,报错为无法将函数定义与现有声明匹配。若将特化模板函数的部分去掉,则程序正常编译。
若将模板成员函数的特化放置在类定义中,则将不会再报错。即:正确代码如下:
//定义模板类 template<class Val> class X { public: X(){} template<class Type> void test(Type); //声明模板成员函数 //在模板类定义内部特化模板成员函数(正确编译) template<> void test(int x) { cout << "in int " << endl; } }; //在模板类外部定义模板成员函数(正确编译) template<class Val> template<class Type> void X<Val>::test(Type x) { cout << "in common " << endl; }由此可以看出 ,报声明与定义不匹配的错误出错的原因是模板成员函数在类定义外部进行了特化。 但是目前还不知道为什么这样的操作会不能通过编译 。但同时需要注意,对于非模板类的模板成员函数,可以在类定义外部进行特化 。
class X { public: template<class T> void test(T t); //非模板类中模板成员函数的声明 }; //模板成员函数的定义 template<class T> void X::test(T t) { cout << "in common" << endl; } //非模板成员函数中模板成员函数的特化(正常编译) template<> void X::test<int>(int x) { cout << "in int" << endl; }