【问题标题】:Use derived class for template constructor将派生类用于模板构造函数
【发布时间】:2015-09-03 20:18:36
【问题描述】:

我有一个带有模板构造函数的类:

class TCons {
    template <typename T> TCons(T t);
}

专门用于实现的:

template <> TCons::TCons(int i) { doMyStuff(i); }

我也有一个基类的特化:

template <> TCons::Tcons(TBase &t) { doMyStuff(t); }

但是当我尝试使用派生对象作为参数初始化 TCons 对象时,这似乎不起作用。

class TDeriv: public TBase { };
TDeriv td;
TCons tc = td;

我无法使用指针来解决此问题(因为所有内容都包含在宏中)。问题出现在链接阶段。

只是错了,还是我遗漏了什么?

【问题讨论】:

  • 修正错别字和语法,以便您的代码编译。
  • 为什么使用专门化而不是简单的重载?
  • template&lt;&gt;

标签: c++ templates


【解决方案1】:

当我们尝试在这里构造tc时:

TCons tc = td;

我们有一个构造函数的选择:

template <typename T> TCons(T t);

当我们进行模板推导时,我们推导T = TDeriv。这与您的 TBase 显式特化(也不是 int 之一)匹配,因此我们坚持使用主模板。您没有为其提供定义,这就是您遇到链接器错误的原因。

如果您希望在所有从 TBase 继承的类型上调用您的 TBase 构造函数,则必须针对这些情况禁用构造函数模板。我们可以通过 SFINAE 做到这一点:

template <typename T,
          typename = std::enable_if_t<!std::is_base_of<TBase, T>::value>>
TCons(T );

同时使您的其他构造函数成为非模板重载:

TCons(int );
TCons(TBase& );

仅在需要时进行专门化 - 重载会变得更简单。

【讨论】:

  • 已解决,但clang语法有点不同:template ::value>::type>
  • @GB 这不是“clang 语法”,而是 C++11。即使您没有 C++14 编译器,您也应该自己添加类型特征别名 - 使代码更简洁。
  • c++ 概念确实会让代码更干净。现在它看起来就像火车残骸......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-23
  • 2021-08-09
  • 1970-01-01
  • 2016-07-19
相关资源
最近更新 更多