C++ Logo

std-proposals

Advanced search

Re: [std-proposals] std::elide

From: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Date: Sat, 9 Mar 2024 22:37:13 +0000
On Sat, Mar 9, 2024 at 10:14 PM Jens Maurer wrote:
>
> Regarding the core language change: We generally don't special-case
> library types in the core language, unless the library types are
> needed for implementation of a core language feature (e.g.
> std::initializer_list).


I know, it's better to have total separation between language and
library, but this is an instance in which cooperation is necessary
between the two.


> Also, the wording uses "shall", causing the situation to be ill-formed.


I don't want the code to be ill-formed. I was more so aiming for
something along the lines of SFINAE i.e., instead of the compiler
failing, I want it to try find another way of compiling it. I'm not
sure what terminology to use to write that in English in the standard.


> Also, I don't understand how template argument deduction should
> work for the AwkwardClass constructor shown in the paper.
> What's the value of the Args... template parameter type, and
> how do the rules achieve that result?


Here's the code copy-pasted:

    class AwkwardClass {
        std::mutex m; // cannot move, cannot copy
    public:
        template<typename T>
        AwkwardClass(T &&arg) noexcept
        {
            std::printf("T = %s\n", typeid(T).name());
        }
    };

    AwkwardClass ReturnAwkwardClass(int const arg)
    {
        return AwkwardClass(arg);
    }

    void Func(void)
    {
        std::optional<AwkwardClass> var;
        var.emplace( std::elide(ReturnAwkwardClass, -1) );
    }

The invocation of the function "std::elide" returns a prvalue of type
"elide_t< . . . >", and this object is passed by Rvalue reference to
'std::optional::emplace'. Inside the implementation of 'emplace', we
have the following line:

    ::new(buffer) T( forward<Params>(args)... );

which after substitution becomes:

    ::new(buffer) T( std::elide_t< . . . >( . . . ) );

Without the change to the core language, the constructor belonging to
'AwkwardClass' will have its template parameter T set to
'std::elide_t< . . . >', but this is not what we want. With the core
language change, std::elide_t< . . . > cannot be substituted in for T
because constructors aren't allowed to have any parameter that is a
specialisation of std::elide_t, and so the compiler continues looking
for a way to compile it -- and the next thing it tries to do is find a
conversion operator, and it finds a conversion operator to go from
std::elide_t< . . . >( . . . ) to AwkwardClass, so we're left with:

    ::new(buffer) AwkwardClass( AwkwardClass() );

and because it's a PRvalue, all of the copy/move operations are elided.

Received on 2024-03-09 22:37:23