C ++方法扩展

时间:2020-03-05 18:53:55  来源:igfitidea点击:

我们可以在不专门化类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