【问题标题】:C++ template specialization of constructor构造函数的 C++ 模板特化
【发布时间】:2010-12-26 13:07:06
【问题描述】:

我有一个模板类 A 和两个 typedef A 和 A。 如何覆盖 A 的构造函数?以下方法不起作用:

template <typename T, int M> class A;
typedef  A<std::string, 20> one_type;
typedef  A<std::string, 30> second_type;


template <typename T, int M>
class A {
public:
  A(int m) {test= (m>M);}

  bool test;

};


template<>
one_type::one_type() { cerr << "One type" << endl;}

我希望 A<:string> 类做其他类不做的事情。如何在不更改构造函数 A:A(int) 的情况下做到这一点?

【问题讨论】:

  • 你想让这些课程做什么?
  • 问题不清楚。顺便说一句,one_type 没有空构造函数,它有带 int 参数的构造函数。

标签: c++ templates constructor specialization


【解决方案1】:

您唯一不能做的就是使用typedef 来定义构造函数。除此之外,您应该像这样专门化 A&lt;string,20&gt; 构造函数:

template<> A<string,20>::A(int){}

如果您希望A&lt;string,20&gt; 具有与通用A 不同的构造函数,则需要专门化整个A&lt;string,20&gt; 类:

template<> class A<string,20> {
public:
   A(const string& takethistwentytimes) { cerr << "One Type" << std::endl; }
};

【讨论】:

    【解决方案2】:

    假设您的 真的 意味着 A::test 可以公开访问,您可以执行以下操作:

    #include <iostream>
    
    
    template <int M>
    struct ABase
    {
      ABase(int n) : test_( n > M )
      {}
    
      bool const test_;
    };
    
    
    template <typename T, int M>
    struct A : ABase<M>
    {
      A(int n) : ABase<M>(n)
      {}
    };
    
    
    template <typename T>
    A<T, 20>::A(int n)
      : ABase<20>(n)
      { std::cerr << "One type" << std::endl; }
    

    踢轮胎:

    int main(int argc, char* argv[])
    {
      A<int, 20> a(19);
      std::cout << "a:" << a.test_ << std::endl;
      A<int, 30> b(31);
      std::cout << "b:" << b.test_ << std::endl;
      return 0;
    }
    

    【讨论】:

    • 好答案,类型系统发疯了:P
    【解决方案3】:

    迟到但非常优雅的解决方案: C++ 2020 引入了Constraints and Concepts。您现在可以有条件地启用和禁用构造函数和析构函数!

    #include <iostream>
    #include <type_traits>
    
    template<class T>
    struct constructor_specialized
    {
        constructor_specialized() requires(std::is_same_v<T, int>)
        {
            std::cout << "Specialized Constructor\n";
        };
    
        constructor_specialized()
        {
            std::cout << "Generic Constructor\n";
        };
    };
    
    int main()
    {
        constructor_specialized<int> int_constructor;
        constructor_specialized<float> float_constructor;
    };
    

    运行代码here

    【讨论】:

      【解决方案4】:

      这可能有点晚了,但如果您可以访问c++11,您可以使用SFINAE 来完成您想要的操作:

        template <class = typename std::enable_if< 
          std::is_same<A<T,M>, A<std::string, 20>>::value>::type // Can be called only on A<std::string, 20>
        > 
        A() {
          // Default constructor
        }
      

      Working example

      【讨论】:

        【解决方案5】:

        怎么样:

        template<typename T, int M, bool dummy = (M > 20) >
        class A {
        public:
          A(int m){
              // this is true
          }
        
        };
        
        template<typename T, int M>
        class A<T,M,false> {
        public:
            A(int m) {
            //something else
            }
        };
        

        【讨论】:

          【解决方案6】:

          你不能用你目前的方法。 one_type 是特定模板特化的别名,因此它获取模板具有的任何代码。

          如果要添加特定于 one_type 的代码,则必须将其声明为 A 特化的子类,如下所示:

            class one_type:
              public A<std::string, 20>
            {
              one_type(int m)
                : A<str::string, 20>(m)
              {
                cerr << "One type" << endl;
              }
            };
          

          【讨论】:

          • 是这样想的。构造函数不能专门化为成员函数,你能提供一个论据吗?
          【解决方案7】:

          对于这种情况,我能想到的最佳解决方案是使用“构造函数辅助函数”:

          template <typename T, int M> class A;
          typedef  A<std::string, 20> one_type;
          typedef  A<std::string, 30> second_type;
          
          template <typename T, int M>
          class A {
          private:
            void cons_helper(int m) {test= (m>M);}
          public:
            A(int m) { cons_helper(m); }
          
            bool test;
          };
          
          template <>
          void one_type::cons_helper(int) { cerr << "One type" << endl;}
          

          【讨论】:

            猜你喜欢
            • 2016-12-04
            • 1970-01-01
            • 1970-01-01
            • 2011-05-08
            • 1970-01-01
            • 2011-02-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多