C++ Logo

std-proposals

Advanced search

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

From: Breno Guimarães <brenorg_at_[hidden]>
Date: Mon, 21 Aug 2023 13:40:25 -0300
Awesome! Thanks for this tip.

On Mon, Aug 21, 2023 at 12:56 PM Marcin Jaczewski <
marcinjaczewski86_at_[hidden]> wrote:

> 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 16:40:38