您是否可以在模板类中专门化模板方法而无需专门化类模板参数?
请注意,专业化位于模板参数的值,而不是其类型。
这似乎是在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类'中的显式特化”
如果标准不支持,有人可以告诉我原因吗?
答案 0 :(得分:4)
标准中不支持它(显然,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);
};
答案 1 :(得分:2)
这是你如何做到的:
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
我告诉他们如何使用模板检查成员函数是否存在于类中。或者您可以使用提升,但请记住将enable_if
更改为enable_if_c
然后。
答案 2 :(得分:1)
这是另一种解决方法,当您需要对某个函数进行部分特化时(这是不允许的)也很有用。创建一个模板仿函数类(即,其唯一目的是执行单个成员函数的类,通常名为operator()),对其进行特化,然后从模板函数中调用。
我想我从Herb Sutter那里学到了这个技巧,但是不记得是哪本书(或文章)。根据您的需要,它可能有点过头了,但是......但是......
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;
}
答案 3 :(得分:0)
我从未听说过这是可能的;如果所有编译器都支持不,那对我来说是有意义的。所以这是一个解决方法的想法:
在类之外实现模板函数,该函数采用与方法相同的操作。然后你可以专门化这个函数,并从方法中调用它。当然,你还必须传入它需要的任何成员变量(如果你想修改它们的值,还要指向它)。
你也可以创建另一个模板类作为子类,并专门化那个,虽然我自己从来没有这样做,并不是100%肯定它会起作用。 (如果您知道第二种方法是否有效,请发表评论以增加此答案!)