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

1

2

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}}?

Averell answered 13/10, 2021 at 6:1 Comment(5)
Issue might be reduced to MyStruct(42) Demo.Consumerism
@Jarod42: I was going to ask what you meant, but then I took the reference, so I guess the answer is not meant to be taken seriously...Averell
In C++20, aggregate initialization can be used with (..) instead of {..}. And internally std containers (as std::optional) use () (and not {}) to construct user-object.Consumerism
I may be dense, but I still don't see that this explains how my issue can be reduced @Jarod42. The issue is still that initializing optional like this is impossible with clang for now, isn't it?Averell
Yes, it is not possible, as for std::vector, std::map, ... std::optional would do something like new (&buffer) MyStruct(args...). So main issue is that MyStruct(42) is a C++20 feature, not yet implemented by Clang. std::optional didn't change in that regards.Consumerism
M
7

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.

Metametabel answered 13/10, 2021 at 6:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.