GCC与Clang初始化列表构造解析差异:哪个编译器合规?
C++编译器初始化列表构造函数的行为差异
问题重现
以下代码在不同编译器中执行结果不一致:
#include <initializer_list> #include <iostream> struct Foo; struct FooRef { FooRef(Foo const &) { ::std::cout << "ref\n"; } }; struct Foo { Foo() { ::std::cout << "default\n"; } Foo(Foo const &) { ::std::cout << "copy\n"; } Foo(::std::initializer_list<FooRef>) { ::std::cout << "list\n"; } }; Foo Make() { return Foo{}; } int main() { [[maybe_unused]] auto foo{Make()}; }
编译选项:
--std=c++20 -Wall -Wextra -Wpedantic
编译器输出差异
- GCC 13输出:
default
ref
list
- Clang++ 15、VC++ 2022输出:
default
行为分析
GCC会推导目标类型为Foo,优先匹配接受std::initializer_list<FooRef>的构造函数,将Make()返回的prvalue转换为FooRef以满足参数要求;而Clang和VC则直接将prvalue物化到目标对象,省略了额外的转换和构造调用。该差异在旧C++标准及旧版本编译器中同样存在。
实际业务影响
该差异在Boost.JSON库中引发了实际问题:
::boost::json::value json{::boost::json::parse(R"({"param1": "foo", "param3": "bar"})")};
- GCC环境下,代码会生成JSON数组(优先匹配接受initializer_list的构造函数)
- Clang/VC环境下,代码生成JSON对象(直接调用value的拷贝/移动构造)
相关问题
C++如何使用boost::json::value检查JSON键是否存在?
内容的提问来源于stack exchange,提问作者user7860670
相关产品推荐
相关产品推荐

