为什么类成员的类型推断失败?

  • 本文关键字:失败 类型 成员 c++ c++17
  • 更新时间 :
  • 英文 :


让我们假设我们有这个小代码:

template<typename T>
struct Test {
Test(T t) : m_t(t) {}
T m_t;
};
int main() {
Test t = 1;
}

此代码很容易使用[T=int]forTest类进行编译。现在,如果我编写这样的代码:

template<typename T>
struct Test {
Test(T t) : m_t(t) {}
T m_t;
};
struct S {
Test t = 1;
};
int main() {
S s;
}

此代码编译失败,并出现以下错误:

invalid use of template-name 'Test' without an argument list

我需要像Test<int> t = 1;一样写它作为类成员才能工作。知道为什么会这样吗?

原因

struct S {
Test t = 1;
};

不起作用是因为您实际上没有做Test t = 1;. 类内初始值设定项只是一种方便的方法,用于告诉编译器在未提供时要初始化t的值。 "实际"生成的是

struct S {
S() : t(1) {} // created by the compiler
Test t;
};

在这里,您可以更轻松地看到,在调用构造函数之前,t未使用初始值设定项指定。

两个代码片段之间存在差异 - 第一个代码片段Test t = 1声明、定义和初始化一个新变量,而第二个片段仅声明一个成员变量并指定如何初始化它。

默认成员初始值设定项仅在构造函数的上下文中相关,其成员初始值设定项列表中没有t,并且可以轻松地有多个构造函数,每个构造函数以不同的方式初始化t

以下为有效C++,应推导出哪些t类型?

struct S {
Test t = 1;
S(){}
S(int):t(1){}
S(double):t(true){}
};

如果要支持这一点,您就会遇到实现问题,即使类的类型/大小/布局依赖于可能位于不同转换单元中的构造函数的定义。因此,无法通过头文件定义包含类,例如S(如果将定义移动到某些.cpp)。

相关内容

最新更新