C++ Logo

std-proposals

Advanced search

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

From: Marcin Jaczewski <marcinjaczewski86_at_[hidden]>
Date: Mon, 21 Aug 2023 17:56:26 +0200
pon., 21 sie 2023 o 16:33 Breno Guimarães via Std-Proposals
<std-proposals_at_[hidden]> 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_at_[hidden]> 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_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

Received on 2023-08-21 15:56:36