2

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

online compiler

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?

user7860670
  • 35,849
  • 4
  • 58
  • 84

1 Answers1

3

(I'll assume C++17 or later.)

GCC is correct and Clang/MSVC are incorrect.

However, this is probably a defect in the standard. Initialization with braces of non-aggregate class types was missed in mandatory copy elision.

The rules for list-initialization, i.e. initialization with braces, are separated from non-list-initialization and the rules of list-initialization only contain a specific copy elision rule for aggregate types. Otherwise normal constructor overload resolution is used for class types and those will always prefer an std::initializer_list constructor. (And even if they would chose a copy/move constructor instead, it would still need to be called.)

See the open CWG issue 2311.

If you use a non-braced initializer, i.e. auto foo(Make()); or auto foo = Make();, instead of braced initialization, copy elision is allowed and mandatory.

user17732522
  • 53,019
  • 2
  • 56
  • 105