c++language-lawyerc++20aggregate-initialization

Is std::make_optional with an aggregate type legal in C++20?


Assume the following code snippet:

#include <optional>

struct MyStruct
{
//    MyStruct(int a) : a(a) {}
    int a;
};

int main()
{
   std::optional<MyStruct> ms1 = std::make_optional<MyStruct>(1);  

   std::optional<MyStruct> ms2{2};

   std::optional<MyStruct> ms3;
   ms3.emplace(3);

   std::optional<MyStruct> ms4(std::in_place, 4);
}

This works as intended using c++20 with gcc 11.2, all of those four creation methods fail compilation on clang (Compiler explorer link)

To make it work with clang, I need to uncomment the constructor.

My main question is: Which compiler is correct, clang or gcc?

Follow-up question: If clang is correct, is there any way to create a struct without constructor in an optional, without copying the struct into it, e.g. std::optional<MyStruct> ms{MyStruct{3}}?


Solution

  • My main question is: Which compiler is correct, clang or gcc?

    GCC is correct. Since Clang has not yet implemented P0960, this will cause the following assert to fail and disable the optional's constructor:

    static_assert(std::is_constructible_v<MyStruct, int>);
    

    is there any way to create a struct without constructor in an optional, without copying the struct into it?

    Before Clang completes the P0960, I think there is no way. But since MyStruct{3} is an rvalue, it will move into optional.