【问题标题】:C++ method expansionC++ 方法扩展
【发布时间】:2010-09-09 00:49:08
【问题描述】:

您能否在不专门化类模板参数的情况下专门化模板类中的模板方法?

请注意,特化是模板参数的,而不是它的类型。

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

如果标准不支持,谁能告诉我为什么?

【问题讨论】:

    标签: c++ templates


    【解决方案1】:

    标准不支持它(这显然是 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);
    };
    

    【讨论】:

    • 这使得场景。但是,我们的示例专注于模板参数的 ,而不是它的类型。
    【解决方案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,我告诉他们如何使用模板检查类中成员函数的存在。或者你可以使用boost,但是记得把enable_if改成enable_if_c

    【讨论】:

      【解决方案3】:

      这是另一种解决方法,当您需要对函数进行部分特化(这是不允许的)时也很有用。创建一个模板仿函数类(即,其唯一目的是执行单个成员函数的类,通常命名为 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;
      }
      

      【讨论】:

      • 这也是我们想出的解决方案。感谢您的回答。
      【解决方案4】:

      我从来没有听说过这是可能的;如果所有编译器都支持它,这对我来说是有意义的。所以这里有一个解决方法的想法:

      在你的类之外实现一个模板函数,它采取与方法相同的动作。然后你可以专门化这个函数,它从方法中调用它。当然,你还必须传入它需要的任何成员变量(如果你想修改它们的值,还需要指向它的指针)。

      您还可以创建另一个模板类作为子类,并专门化该模板类,尽管我自己从未这样做过,也不能 100% 确定它会起作用。 (如果您知道第二种方法是否可行,请发表评论以补充此答案!)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-18
        • 2014-05-13
        • 2016-10-30
        • 2020-04-15
        • 2010-12-03
        相关资源
        最近更新 更多