为什么不可以emplace_back({1, 2})?

在cpp代码中,我们可以写出如下的代码:

1
2
vector<pair<int, int>> vec;
vec.push_back({1, 2});

然而,vec.emplace_back({1, 2})会报错,我们只能vec.emplace_back(1, 2)

why push_back works?

对于void push_back( T&& value ),由于下面这两条规则,我们可以使用一个braced-init-list作为函数的参数(所谓的braced-init-list就是大括号)。

https://vinci-897.github.io/cppwp/n4868/dcl.init.list#1.5

https://vinci-897.github.io/cppwp/n4868/dcl.init.list#3.7

由于下面这一条规则,我们最终找到了这一条构造函数

https://vinci-897.github.io/cppwp/n4868/over.match#list-1.2

why emplace_back not works with a braced-list?

对于vec.emplace_back(1, 2),只是一个std::forward参数转发,vector会调用allocator_trait的construct函数执行一个placement new来构造参数。

https://en.cppreference.com/w/cpp/container/vector/emplace_back

而对于vec.emplace_back({1, 2}),由于emplace_back的函数签名是

在cpp中,由于以下的规则,不支持在函数参数中由一个大括号的参数把一个完全空白的模版参数T推断成完整的initializer_list<int>,因此clang会给出类似template deduction failed的报错(然而auto是支持这种推导的),如果把emplace_back的参数改为initializer_list<T>则可行。

谜题解开了。

为什么不可以emplace_back({1, 2})?

https://vinci-897.github.io/why-emplace_back-not-works/

Author

vinci

Posted on

2023-10-22

Updated on

2023-11-30

Licensed under

Comments