C++ Logo

std-proposals

Advanced search

Re: [std-proposals] std::elide

From: Jens Maurer <jens.maurer_at_[hidden]>
Date: Sun, 10 Mar 2024 12:55:11 +0100
On 09/03/2024 23.37, Frederick Virchanza Gotham via Std-Proposals wrote:
> 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.

Maybe [temp.deduct.general] p8 or so would be a more appropriate place
to talk about SFINAE stuff.

>> 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< . . . >",

Why do you need an extra function instead of using class template
argument deduction for std::elide_t directly?

> 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,

So, without the core language change, if AwkwardClass ever wants to
participate in no-copy creation, it would need to add a requires-clause.
Seems a small price to pay.

I'd like to point out that we already have std::piecewise_construct for
a similar purpose.

> 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.

Thanks for the explanation.

For the avoidance of doubt, I'm opposed to the core language change.

Jens

Received on 2024-03-10 11:55:19