【发布时间】:2021-07-13 13:28:32
【问题描述】:
下面的代码有两个可能相关的问题。
它只是分别定义了Type1 和Type2 两种类型,以及继承自这两种类型的“聚合”类型Types。
我的最终目标是让注释的构造函数工作以避免临时变量初始化。如果我取消注释Types 下的代码,编译器会给我一个错误:
error: class ‘Types<Args>’ does not have any field named ‘Args’
我试图克服这个问题并想出了可以编译的代码。但是它没有给出预期的输出。
预期的输出是
Type1:1
Type2:0
实际输出为
Type1:0
Type2:0
我不知道我的两个问题是否相互关联。 我想它们都是由于我可能缺乏对参数包和继承的理解而引起的,因此我将它们都发布了。
如果有人能阐明这两个问题,我将不胜感激。
struct Type1 {
Type1() = default;
template <typename T>
Type1() : init_{std::is_same<Type1, T>::value} {};
template <typename T>
Type1(T t) : init_{std::is_same<Type1, T>::value} {}
void Print() const { std::cout << "Type1:" << init_ << std::endl; }
bool init_{false};
};
struct Type2 {
Type2() = default;
template <typename T>
Type2() : init_{std::is_same<Type2, T>::value} {};
template <typename T>
Type2(T) : init_{std::is_same<Type2, T>::value} {}
void Print() const { std::cout << "Type2:" << init_ << std::endl; }
bool init_{false};
};
template <typename... Args>
class Types : public Args... {
public:
// error: class ‘Types<Args>’ does not have any field named ‘Args’
//
//template <typename T>
//Types()
// : Args<T>()... {}
template <typename T>
Types(T t)
: Args(t)... {}
};
int main() {
Types<Type1, Type2> types(Type1{});
static_cast<Type1>(types).Print();
static_cast<Type2>(types).Print();
}
更新:
感谢Igor Tandetnik 和mattlangford,我认为这个问题可以解决
正如现实生活中发生的那样,如果您认为自己不了解某件事,您经常会错过不止一个。
- 如果
T == T1编译器不调用模板构造函数,而是调用复制构造函数。应该记住,仅下面的构造函数显然不足以解决通用情况。评论中提到了here
template <typename T>
Type1(T t) : init_{std::is_same<Type1, T>::value} {}
- 根据评论here,必须在下面的静态转换中使用引用
static_cast<Type1>(types).Print();
static_cast<Type2>(types).Print();
template <typename T>
Type1() : init_{std::is_same<Type1, T>::value} {};
【问题讨论】:
-
关闭顶部:
template <typename T> Type1()永远不能使用,因为在调用构造函数时没有提供显式模板参数的语法,也没有参数可以从中推断出它们。 -
static_cast<Type1>(types)创建一个类型为Type1的临时对象,使用带有types作为其参数的模板化构造函数。它相当于Type1{types}。当然types的类型不是Type1。您在该临时对象上调用Print(),而不是在types内的Type1子对象上调用 -
@IgorTandetnik 非常感谢您帮助我解决这个问题。我用原始代码存在的所有问题更新了原始帖子。
标签: c++ templates inheritance constructor c++17