Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is optional assignment constexpr in C++ 20?

To the internal content of an optional, doesn't the optional require placement new in order to reconstruct the internal in place storage or union? Is there some new feature like placement new in C++ 20 that allows for constexpr assignment of std::optional?

template< class U = T >
optional& operator=( U&& value );
(since C++17)
(until C++20)
template< class U = T >
constexpr optional& operator=( U&& value );
(since C++20)
like image 577
Andreas Loanjoe Avatar asked Feb 27 '26 17:02

Andreas Loanjoe


1 Answers

To the internal content of an optional, doesn't the optional require placement new in order to reconstruct the internal in place storage or union?

For assignment, yes it does.

But while we still cannot do actual placement new during constexpr time, we did get a workaround for its absence: std::construct_at (from P0784). This is a very limited form of placement new, but it's enough to get optional assignment working.

The other change was that we also needed to be able to actually change the active member of a union - since it wouldn't matter if we could construct the new object if we couldn't actually switch. That also happened in C++20 (P1330).

Put those together, and you get a functional implementation of optional assignment: P2231. An abbreviated implementation would look like this:

template <typename T>
struct optional {
    union {
        T value;
        char empty;
    };
    bool has_value;

    constexpr optional& operator=(T const& rhs) {
        if (has_value) {
            value = rhs;
        } else {
            // basically ::new (&value) T(rhs);
            // except blessed for constexpr usage
            std::construct_at(&value, rhs); 
        }
        has_value = true;
        return *this;
    }
};
like image 112
Barry Avatar answered Mar 01 '26 09:03

Barry



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!