如何将模板类添加为普通类中的成员
Posted
技术标签:
【中文标题】如何将模板类添加为普通类中的成员【英文标题】:How to add Template class as member within a normal class 【发布时间】:2019-09-17 17:40:10 【问题描述】:我有一个模板类:templClass
,它接受一个类型并像常规模板类一样工作。我希望该班级成为另一个普通班级regClass
的成员。
regClass
有一个成员变量var
,我希望在此基础上创建templClass
或type1
或type2
:
所以如下
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 的一个强案例。 【参考方案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<templClass<int>, templClass<double>> 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<T>
类的T
类型。 templClass
本身并不是一个完整的类型。
因此你有两个选择:
-
直接在
regClass
类定义中指定类型:
class regClass
public:
regClass()
// constructor for other members
int var;
templClass<int> templClass_;
// [...]
;
这样你可以写regClass instance;
,但嵌入的对象类型总是templClass<int>
。
-
使外部类成为模板类:
template <class T>
class regClass
public:
regClass()
// constructor for other members
int var;
templClass<T> templClass_;
// [...]
;
这样你可以在实例化的时候决定类型,例如regClass<std::string> instance;
.
【讨论】:
以上是关于如何将模板类添加为普通类中的成员的主要内容,如果未能解决你的问题,请参考以下文章