Awesome! Thanks for this tip.

On Mon, Aug 21, 2023 at 12:56 PM Marcin Jaczewski <marcinjaczewski86@gmail.com> wrote:
pon., 21 sie 2023 o 16:33 Breno Guimarães via Std-Proposals
<std-proposals@lists.isocpp.org> napisał(a):
>
> What about: https://godbolt.org/z/1ebe9E3a3
> #include <mutex>
> #include <optional>
>
> extern std::mutex FuncThatReturnsMutex();
>
> template<class T, class Fn>
> void reemplace(std::optional<T>& opt, Fn&& fn)
> {
>     if (!opt)
>         opt.emplace();
>
>     T* buf = std::addressof(*opt);
>     buf->~T();
>     new (buf) T(fn());
> }
>
> int main()
> {
>     std::optional<std::mutex> om;
>     reemplace(om, FuncThatReturnsMutex);
>     // om = FuncThatReturnsMutex();
> }
> Breno G.
>

There is simpler solution, as far I understand conversion operators
can handle RVO:

https://gcc.godbolt.org/z/eser57EeG
```
struct F
{
    F() = default;
    F(const F&) = delete;
};

template<typename T>
struct CastFunc
{
    CastFunc(T f) : callback{f} { }

    T callback;
    operator F(){ return callback(); }
};

template<typename T>
void emplace(T t)
{
    F temp = F(t); //no copy there
}

int main()
{
    emplace(CastFunc{[&]{ return F(); }});
}
```

It could probably work with current std types.

> On Mon, Aug 21, 2023 at 11:16 AM Frederick Virchanza Gotham via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
>>
>> 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.
>> --
>> Std-Proposals mailing list
>> Std-Proposals@lists.isocpp.org
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
> --
> Std-Proposals mailing list
> Std-Proposals@lists.isocpp.org
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals