g++版本变更致std::pair初始化失败的原因及解决方案咨询
std::pair初始化在GCC 12+编译失败的问题解答
1. 版本变更原因
GCC 12及后续版本对std::pair的模板构造函数做了合规性修复,严格遵循C++标准的模板参数推导规则:
- 在GCC 10中,编译器允许将初始化列表
{2}作为模板参数推导的依据,匹配std::pair的完美转发构造函数,用2(构造vector的size)和{2}(构造含单个元素的vector)分别初始化pair的两个成员。 - GCC 12开始,按照标准要求,初始化列表无法参与模板参数推导,导致
std::pair<V,V>{2, {2}}中的第二个参数{2}无法推导U2的类型,完美转发构造函数无法被选中。同时,std::pair的非模板构造函数要求参数必须是const V&,无法直接接受int类型的2,最终没有匹配的构造函数,编译失败。
这次变更本质是修复了旧版本GCC中不符合标准的推导行为,让std::pair的构造函数重载决议严格符合C++标准。
2. 无需提前构建vector的解决方法
std::piecewise_construct正是解决这类场景的标准方案,它允许我们分别为pair的两个成员传递构造参数,直接在pair的内存空间中构造成员,完全避免临时对象的复制或移动:
#include <utility> #include <vector> #include <tuple> using V = std::vector<int>; int main() { std::pair<int, V> p1{1, 2}; std::pair<int, V> p2{1, {2}}; std::pair<V, V> p3{2, 2}; std::pair<V, V> p4{{2}, {2}}; // 正确编译的p5写法 std::pair<V, V> p5{ std::piecewise_construct, std::forward_as_tuple(2), // 传递给p5.first的构造参数:size为2 std::forward_as_tuple(std::initializer_list<int>{2}) // 传递给p5.second的构造参数:元素为2的初始化列表 }; }
如果觉得初始化列表的写法繁琐,也可以用显式构造的方式传递参数,同样不会产生额外复制:
std::pair<V, V> p5{ std::piecewise_construct, std::make_tuple(2), std::make_tuple(V{2}) };
前者更贴合“不提前构建vector”的要求,因为std::initializer_list仅传递构造参数,vector直接在pair内部完成初始化。
内容的提问来源于stack exchange,提问作者Svalorzen
相关产品推荐
相关产品推荐

