鉴于:
struct X {
int m;
std::string s;
};
Run Code Online (Sandbox Code Playgroud)
我可以:
X x; // invokes automatically defined default ctor
X y = { 5 }; // invokes whatever became of the original struct initialization but now maybe runs through C++ initializer-lists?
X z = { 5, "yolo" }; // I assume this is an initializer-list that is being handled by some rule for structs that either runs through a compiler created ctor or copy-from-initializer-list that is similarly compiler-created
Run Code Online (Sandbox Code Playgroud)
乃至...
std::vector<X> vx;
vx.push_back({ 99, "yo" }); // okay
Run Code Online (Sandbox Code Playgroud)
但不是...
vx.emplace_back(99, "yo"); // error VS 2017 v. 15.7.4
vx.emplace_back({99, "yo"}); // error VS 2017 v. 15.7.4
Run Code Online (Sandbox Code Playgroud)
我不理解初始化列表,隐式定义(或编译器定义)ctors和转发函数之间的规则 emplace_back()
有人会非常友好地指出标准的必要部分,或者是一篇关于结构和隐式构造以及其他编译器提供的成员(如copy /)的所有规则的深入讨论的好文章.移动运营商?
我似乎需要一个更全面的规则课 - 因为它似乎emplace_back()应该适用于其中之一emplace_back(int, std::string),或者emplace_back(initializer-list)- 不 - 不是吗?
X是一个聚合.虽然聚合的具体定义在每个标准中都有所改变,但您的类型是所有标准中的聚合.
聚合的列表初始化在此处进行聚合初始化.这里没有构造函数 - 没有"auto"构造函数,没有合成构造函数.聚合初始化不会创建构造函数或通过该机制.我们直接从braced-init-list中的相应初始化程序初始化每个类成员.这就是你y和你z正在做的事情.
现在,第二部分.相关部分vector看起来像:
template <typename T>
struct vector {
void push_back(T&&);
template <typename... Args>
void emplace_back(Args&&...);
};
Run Code Online (Sandbox Code Playgroud)
一个支撑,初始化列表,比如{99, "yo"},没有一个类型.而且你不能为它推断出一种类型.它们只能在特定情况下使用.push_back({99, "yo"})工作正常,因为push_back它X&&- 它不是一个功能模板 - 我们知道如何进行初始化.
但它emplace_back()是一个函数模板 - 它需要Args...从其参数的类型推断出来.但我们没有类型,没有什么可推断的!这里有一些例外(特别是std::initializer_list<T>可以推断),但在这里,我们被卡住了.你必须写emplace_back(X{99, "yo"})- 这会X在调用方的旁边创建.
同样,emplace_back(99, "yo")因为emplace使用()s来初始化,所以()不起作用,但是你不能 - 初始化聚合.它没有构造函数!
| 归档时间: |
|
| 查看次数: |
69 次 |
| 最近记录: |