C ++方法扩展

时间:2008-09-15 16:35:37

标签: c++ templates

您是否可以在模板类中专门化模板方法而无需专门化类模板参数?

请注意,专业化位于模板参数的,而不是其类型。

这似乎是在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类'中的显式特化”

如果标准不支持,有人可以告诉我原因吗?

4 个答案:

答案 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%肯定它会起作用。 (如果您知道第二种方法是否有效,请发表评论以增加此答案!)