C++ Logo

std-proposals

Advanced search

[std-proposals] Copy-construct, move-construct, and PR-construct

From: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Date: Mon, 21 Aug 2023 15:16:41 +0100
The following is currently impossible in C++26:

    extern std::mutex FuncThatReturnsMutex(void);

    int main(void)
    {
        std::optional<std::mutex> om;
        om = FuncThatReturnsMutex();
    }

It's impossible because a mutex must be either copiable or movable in order
to assign it to an 'optional'. We have the same problem with
'std::variant', 'std::any', and lots of classes in other libraries like
Boost.

Currently we can write constructors and assignment operators that take:
• an Lvalue ref
• an Rvalue ref

What if we had a third kind whose argument must be a prvalue? An
implementation of 'optional' would look something like as follows:

template <typename T>
class optional {
    bool bool_has_value = false;
    alignas(T) char unsigned buf[sizeof(T)];
public:
    optional(T ^^arg) : buf(arg)
    {

    }

    optional &operator=(T ^^arg) : buf(arg)
    {
        if ( this->bool_has_value )
        {
            static_cast<T*>(static_cast<void*>(&buf))->~T();
            this->bool_has_value = false;
        }

        __emplace;

        this->bool_has_value = true;

        return *this;
    }
};

In the case of the constructor, if 'FuncThatReturnsMutex' throws an
exception, then the 'optional' constructor as a whole will throw an
exception, so no problem there.

But in the case of the assignment operator, we have a problem if
'FuncThatReturnsMutex' throws, so we need control over when the prvalue
gets generated -- and that's why I have the '__emplace' keyword there.

Received on 2023-08-21 14:16:44