我有一个带有模板构造函数的类:
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;
我无法使用指针来解决此问题(因为所有内容都包含在宏中)。问题出现在链接阶段。
这是错的,还是我错过了什么?
答案 0 :(得分:5)
当我们尝试在此构建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& );
只在需要时专门化 - 重载变得更简单。