The following code snippet produces different results in different compilers:
#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
Reproducible with older standards and older compiler versions as well.
g++ 13
default
ref
list
clang++ 15, vc++ 2022
default
gcc seem to deduce object type to be Foo
and selects priority constructor with std::initializer_list
altering argument accordingly while other compilers just materialize prvalue.
Additional context: This problem arises in boost.json, json
here is an (json) array in gcc and an (json) object in clang / vc.
::boost::json::value json{::boost::json::parse(R"({"param1": "foo", "param3": "bar"})")};
related question: C++ How to check if json key exists using boost::json::value?