简体   繁体   English

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

[英]Why type deduction fails for a class member?

Let's assume that we have this small code:让我们假设我们有这个小代码:

template<typename T>
struct Test {
    Test(T t) : m_t(t) {}
    T m_t;
};

int main() {
    Test t = 1;
}

This code easily compiles with [T=int] for Test class. Now if I write a code like this:这段代码很容易用[T=int]编译,用于Test class。现在如果我写这样的代码:

template<typename T>
struct Test {
    Test(T t) : m_t(t) {}
    T m_t;
};

struct S {
    Test t = 1;
};

int main() {
    S s;
}

This code fails to compile with the following error:此代码无法编译并出现以下错误:

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

I need to write it like Test<int> t = 1;我需要像Test<int> t = 1;这样写as a class member to work.作为class会员上班。 Any idea why this happens?知道为什么会这样吗?

The reason原因

struct S {
    Test t = 1;
};

does not work is because you aren't actually doing Test t = 1;不起作用是因为你实际上并没有在做Test t = 1; . . An in class initializer is just a convenient way to tell the compiler what value to initialize t with when one is not provided. in class 初始化器只是一种方便的方式,可以告诉编译器在未提供时用什么值初始化t What "actually" gets generated is “实际”生成的是

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

and here you can more easily see that t isn't specified with an initializer until you call the constructor.在这里你可以更容易地看到t在你调用构造函数之前没有用初始化器指定。

There is a difference between your two snippets - first Test t = 1 declares, defines, and initializes a new variable while the second only declares a member variable and specifies how it might be initialized.您的两个片段之间存在差异 - 第一个Test t = 1声明、定义和初始化一个新变量,而第二个仅声明一个成员变量并指定如何初始化它。

The default member initializer is relevant only in the context of a constructor without t in its member initializer list and there can easily be multiple constructors, each initializing t in different way.默认成员初始值设定项仅在其成员初始值设定项列表中没有t的构造函数的上下文中相关,并且很容易有多个构造函数,每个构造函数都以不同的方式初始化t

The following is valid C++, what should type of t be deduced to?以下是有效的C++, t的类型应该推导成什么?

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

If this were to be supported, you hit the implementation issue of making type/size/layout of the class dependent on the definition of constructors which are likely in different translation units.如果要支持这一点,您会遇到使 class 的类型/大小/布局依赖于可能在不同翻译单元中的构造函数的定义的实现问题。 Therefore it would make it impossible to define include classes such as S (if one moved the definitions to some.cpp) via header files.因此,将无法通过 header 文件定义包含类,例如S (如果将定义移至 some.cpp)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM