【问题标题】:How to add Template class as member within a normal class如何将模板类添加为普通类中的成员
【发布时间】:2019-09-17 17:40:10
【问题描述】:

我有一个模板类:templClass,它接受一个类型并像常规模板类一样工作。我希望该班级成为另一个普通班级regClass 的成员。 regClass 有一个成员变量var,我希望在此基础上创建templClasstype1type2: 所以如下

template <class T>
class templClass
{
  //constructor  
};

class regClass
{
public:
    regClass()
    {
        // constructor for other members
    }
    int var;
    templClass templClass_;
    // if (var == 0)
    // {I want templClass<type1>}
    // else
    // {I want templClass<type2>}
};

我怎样才能做到这一点? 上面的实现抛出编译器错误error: invalid use of template-name 'templClass' without an argument list

【问题讨论】:

  • 你不能这样做。
  • 也许告诉你要做什么会更好?看起来像 XY problem 的一个强案例。

标签: c++ class c++11 templates c++14


【解决方案1】:

这是不可能的。

您必须使用类模板的显式实例化。例如

templClass<int> templClass_;

templClass<double> templClass_;

另一种选择是使regClass 也成为类模板,其中var 是模板参数而不是成员变量。

template <int> struct MemberTypeSelector;
template <> struct MemberTypeSelector<0>
{
   using type = templClass<int>;
};

template <> struct MemberTypeSelector<1>
{
   using type = templClass<double>;
};

// Add more specializations of MemberTypeSelector as needed.

template <int var>
class regClass
{
   public:

      using MemberType = typename MemberTypeSelector<var>::type;
      regClass()
      {
         // constructor for other members
      }

      MemberType member;
};

【讨论】:

  • 或者std::variant&lt;templClass&lt;int&gt;, templClass&lt;double&gt;&gt; templClass_;然后处理std::variant成员变量的打包和解包。
【解决方案2】:

正如@Eljay 在 cmets 中所说,正确的解决方案是使用std::variant

using AnyTemplClass = std::variant<templClass<int>, templClass<double>>;

class regClass
{
public:
    regClass()
    {
        if (var == 0) {
            templClass_ = templClass<int>{};
        } else {
            templClass_ = templClass<double>{};
        } 
    }
    int var = 0;
    AnyTemplClass templClass_;
};

【讨论】:

    【解决方案3】:

    简而言之,如果我们记得模板不是类型,而是可能类型家族的名称,那么很明显,我们不能使用类型作为模板名称的类型声明数据成员。我们需要明确定义整个家族中的哪种类型是成员的类型。原因,您显然不想按类型参数化 regClass,否则您将再次拥有模板,具体取决于您使用的编译器,解决方案可以使用 union 或 std::variant 作为成员类型,但是,您需要指定所有可能的类型提前。我更喜欢按类型 T 参数化 regClass 而不是成员类型 临时类

    【讨论】:

      【解决方案4】:

      这是不可能的。

      解释这一点的最简单方法可能是实例化时刻。当你写:

      regClass instance;
      

      那么编译器无法推断出嵌入模板templClass&lt;T&gt; 类的T 类型。 templClass 本身并不是一个完整的类型。

      因此你有两个选择:

      1. 直接在regClass类定义中指定类型:
          class regClass
          {
          public:
              regClass()
              {
                  // constructor for other members
              }
              int var;
              templClass<int> templClass_;
              // [...]
          };
      

      这样你可以写regClass instance;,但嵌入的对象类型总是templClass&lt;int&gt;

      1. 使外部类成为模板类:
          template <class T>
          class regClass
          {
          public:
              regClass()
              {
                  // constructor for other members
              }
              int var;
              templClass<T> templClass_;
              // [...]
          };
      

      这样你可以在实例化的时候决定类型,例如regClass&lt;std::string&gt; instance;.

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-10
        • 1970-01-01
        • 2010-12-02
        • 1970-01-01
        • 2022-01-06
        相关资源
        最近更新 更多