C ++方法扩展
我们可以在不专门化类template参数的情况下专门化模板类中的模板方法吗?
请注意,专业化是基于template参数的值,而不是其类型。
这似乎可以在Visual Studio 2008 SP1编译器下进行编译,但不能在GCC 4.2.4下进行编译。
#include <iostream> using namespace std; template <typename T> class A { private: template <bool b> void testme(); template <> void testme<true>() { cout << "true" << endl; }; template <> void testme<false>() { cout << "false" << endl; }; public: void test(); }; template<typename T> struct select {}; template<> struct select<int> { static const bool value = true; }; template<> struct select<double> { static const bool value = false; }; template <class T> void A<T>::test() { testme<select<T>::value>(); } int main(int argc, const char* argv[]) { A<int> aInt; A<double> aDouble; aInt.test(); aDouble.test(); return 0; }
GCC告诉我:"错误:非命名空间范围类A中的显式专门化"
如果标准不支持该功能,谁能告诉我为什么?
解决方案
回答
该标准不支持它(显然,我们可以使用Visual Studio的已知错误来做到这一点)。
该标准不允许内部模板(成员函数或者类)被专门化,而外部模板也不被专门化。原因之一是我们通常可以只重载该函数:
template<typename ty> class A { public: void foo(bool b); void foo(int i); };
等效于:
template<typename ty> class A { public: template<typename ty2> void foo(ty2); template<> void foo(bool b); template<> void foo(int i); };
回答
我从未听说过这种可能性。如果不是所有编译器都支持的话,这对我来说很有意义。因此,这里有一个解决方法:
在类之外实现一个模板函数,该模板函数将执行与方法相同的操作。然后,我们可以专门化此函数,然后从方法中调用它。当然,我们还必须传入所需的任何成员变量(如果要修改其值,则指向其指针)。
我们也可以创建另一个模板类作为子类,并对其进行专门化,尽管我自己从未做过,并且不能100%地确定它会起作用。 (如果我们知道第二种方法是否可行,请发表评论以扩大此答案!)
回答
这是另一种解决方法,当我们需要对函数进行部分专业化(不允许使用)时,此方法也很有用。创建一个模板函子类(即,其唯一目的是执行单个成员函数(通常称为operator())的类),对其进行专门化,然后从模板函数中进行调用。
我想我从Herb Sutter学到了这个技巧,但不记得那是哪本书(或者文章)。对于需求,这可能是矫over过正,但是...
template <typename T> struct select; template <bool B> struct testme_helper { void operator()(); }; template <typename T> class A { private: template <bool B> void testme() { testme_helper<B>()(); } public: void test() { testme<select<T>::value>(); } }; template<> void testme_helper<true>::operator()() { std::cout << "true" << std::endl; } template<> void testme_helper<false>::operator()() { std::cout << "false" << std::endl; }
回答
这是操作方法:
template<typename A> struct SomeTempl { template<bool C> typename enable_if<C>::type SomeOtherTempl() { std::cout << "true!"; } template<bool C> typename enable_if<!C>::type SomeOtherTempl() { std::cout << "false!"; } };
我们可以从我的其他答案中获得enable_if
,我告诉他们如何使用模板检查类中成员函数的存在。或者我们可以使用boost,但是请记住,然后将enable_if
更改为enable_if_c
。