Loading

emplace_back无法支持<brace-enclosed initializer list>吗?

问题

vector使用emplace_back()无法添加元素,使用push_back()却可以。
难道emplace_back()与列表初始化不兼容?非也!

复现

代码片段

std::vector<std::array<int, 4> > vec;
vec.emplace_back({1,2,3,4}); // error
vec.push_back({1,2,3,4}); // pass

报错信息

<source>:8:31: error: no matching function for call to 'std::vector<std::array<int, 4> >::emplace_back(<brace-enclosed initializer list>)'
    8 |     vec.emplace_back({1,2,3,4});
      |                               ^
include/c++/11/bits/stl_vector.h:1212:2: note: candidate template ignored: substitution failure: deduced incomplete pack <(no value)> for template parameter '_Args'
        emplace_back(_Args&&... __args);
        ^

深究

分析std::vector的成员函数:

文档指出emplace_back()本质上是一个模板函数,具体形式为

template< class... Args >
void emplace_back( Args&&... args );

对于简单的结构我们一般省略模板参数让编译器自行推导。对于复杂类型,
模板意味若不确定传入args类型,编译器无法推导缺省模板参数Args的值,
进而无法使用std::forward<Args>(args)...转发参数进行构造。

说的好,但还是没有解释为什么push_back()可以调用?

从实现上push_back()并非模板函数,且其实现存在拷贝而非直接构造

void push_back( const T& value );

编译器将隐式调用std::array::operator=()处理传入的参数完成类型转换。

解决

只需将上述代码改为:

vec.emplace_back<std::array<int, 4>>({1,2,3,4});
// or
vec.emplace_back(std::array<int, 4>{{1, 2, 3, 4}});

即可通过编译!

参考

std::vector<T,Allocator>::emplace_back - cppreference.com
std::vector<T,Allocator>::push_back - cppreference.com

posted @   azureology  阅读(1037)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示