显式的模板类成员函数的特化
我需要专门化一些types的模板成员函数(比方说double )。 它工作正常,而类X
本身不是一个模板类,但是当我做模板GCC开始给编译时错误。
#include <iostream> #include <cmath> template <class C> class X { public: template <class T> void get_as(); }; template <class C> void X<C>::get_as<double>() { } int main() { X<int> x; x.get_as(); }
这里是错误信息
source.cpp:11:27: error: template-id 'get_as<double>' in declaration of primary template source.cpp:11:6: error: prototype for 'void X<C>::get_as()' does not match any in class 'X<C>' source.cpp:7:35: error: candidate is: template<class C> template<class T> void X::get_as()
我怎样才能解决这个问题,这里有什么问题?
提前致谢。
这种方式不行。 你需要说以下内容,但这是不正确的
template <class C> template<> void X<C>::get_as<double>() { }
明确专业化的成员也需要他们周围的类模板。 所以你需要说下面的内容,这将只针对X<int>
的成员。
template <> template<> void X<int>::get_as<double>() { }
如果你想保持周围的模板非专业化,你有几个select。 我更喜欢重载
template <class C> class X { template<typename T> struct type { }; public: template <class T> void get_as() { get_as(type<T>()); } private: template<typename T> void get_as(type<T>) { } void get_as(type<double>) { } };
如果有人能够使用std::enable_if
我们可以依靠SFINAE(replace失败不是一个错误)
那会像这样工作:
#include <iostream> #include <type_traits> template <class C> class X { public: template <class T, typename std::enable_if< ! std::is_same<double,T>::value>::type * = nullptr > void get_as(){ std::cout << "get as T" << std::endl; } template <class T, typename std::enable_if< std::is_same<double,T>::value>::type * = nullptr > void get_as(){ std::cout << "get as double" << std::endl; } }; int main() { X<int> d; d.get_as<double>(); return 0; }
丑陋的是,所有这些enable_if只有一个专业化需要可用的编译器,否则消除歧义的错误将出现。 这就是为什么默认行为“得到T”还需要启用if。
首先:您的类模板中未声明get_as专用,以便稍后在代码中进行定义。 所以首先你需要这样做:
template <class C> class X { public: template <class T> void get_as(); template <> void get_as<double>(); };
然后定义专业化:
template <class C> template <> void X<C>::get_as<double>() { .... }
但我会这样定义它:
template <class C> class X { public: template <class T> void get_as() { // default implementation } template <> void get_as<double>() { // specialized implementation } };
抱怨上面不行!
编辑:
事实certificate,function模板专门化是不允许在非命名空间范围,即在类,类模板等。
所以你可以把它作为命名空间范围的函数模板:
template <class C> class X { public: } template <class T, class C> void get_as( X<C>& obj ) { // default implementation } template <class C> void get_as<double,C>( X<C>& obj ) { // specialized implementation }