C++ Logo

std-proposals

Advanced search

Re: [std-proposals] std::elide

From: Robert A.H. Leahy <rleahy_at_[hidden]>
Date: Thu, 30 May 2024 19:28:14 +0000
Why would we create a new interface for invocation, and then add it to each and every container type, duplicating each and every API which defers responsibility for construction, when the language gives us a mechanism (this one) that works just fine for the purpose?

Note that there's no difference between deferring construction and using the proposed std::elide, and constructing the class directly. The class is directly constructible from the proposed std::elide because the proposed std::elide implicitly converts thereto.

The only issue I have with the paper is the core language addition/change. If people want to support std::elide and CTAD there are ways to do that which don't involve changing the core language to special case a library type.

--Robert
________________________________
From: Std-Proposals <std-proposals-bounces_at_lists.isocpp.org> on behalf of Tiago Freire via Std-Proposals <std-proposals_at_[hidden]>
Sent: Thursday, May 30, 2024 15:05
To: std-proposals_at_[hidden] <std-proposals_at_[hidden]>; Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Cc: Tiago Freire <tmiguelf_at_[hidden]>; std-proposals_at_[hidden] <std-proposals_at_[hidden]>
Subject: Re: [std-proposals] std::elide

The reasons for this class to exist are extremely hacky.
emplace semantics in std::optional are such that you would be able to pass in arguments as you would while instantiating the class itself, and it should be anything else.
Instead of creating a new interface for invocation, it instead tries to hijack an existing interface for an rvo hackery which cannot even be done.
This paper should be killed with fire.

________________________________
From: Std-Proposals <std-proposals-bounces_at_[hidden]> on behalf of Gašper Ažman via Std-Proposals <std-proposals_at_[hidden]>
Sent: Thursday, May 30, 2024 5:55:27 PM
To: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Cc: Gašper Ažman <gasper.azman_at_[hidden]>; std-proposals_at_[hidden] <std-proposals_at_[hidden]>
Subject: Re: [std-proposals] std::elide

The transparent conversion is useful because I have classes that are
*only* constructible from an elider - a named one. It's sort of like
saying that you only have std::in_place_type constructors but you
didn't care to make them variadic.

A lot of these classes *forward* their construction argument further
until it gets to where it actually needs to construct an object. This
matters when you've got expression templates that construct some
immovable tree of stuff at the end. If I have a component that
understands std::elide as an elider, but doesn't understand my elider
as an elider, I can still just construct std::elide from my elider
directly instead of having to rewrap in a lambda; and vice versa.

The only reason I think having std::elide in the library would be to
have a common vocabulary type that's better than std::in_place_type +
variadic forwarding of arguments.

On Thu, May 30, 2024 at 4:35 PM Arthur O'Dwyer
<arthur.j.odwyer_at_[hidden]> wrote:
>
> On Thu, May 30, 2024 at 11:14 AM Frederick Virchanza Gotham via Std-Proposals <std-proposals_at_[hidden]> wrote:
>>
>> On Thu, May 30, 2024 at 1:26 PM Gašper Ažman wrote:
>> >
>> > Both call a function to generate the returned type. Why
>> > can't an elider *be that function* directly? That way I can
>> > nest them either way and it still works.
>>
>> I have made the following two additions:
>> template<typename NestedF, typename... NestedParams>
>> constexpr decltype(auto) operator()(NestedF &&fN, NestedParams&&... argsN)
>> {
>> return forward<NestedF>(fN)( forward<NestedParams>(argsN)... );
>> }
>
>
> IIUC, this isn't right; what you want here is simply
> // https://godbolt.org/z/7he9b6GW6
>
> constexpr operator R()
> noexcept(noexcept(apply(static_cast<F_ref>(f),std::move(args_tuple))))
> {
> return apply( static_cast<F_ref>(f), std::move(args_tuple) );
> }
>
> constexpr R operator()()
> noexcept(noexcept(apply(static_cast<F_ref>(f),std::move(args_tuple))))
> {
> return *this;
> }
>
> as well as the const-qualified versions of those.
> The idea, IIUC, is to make the following code work.
> We suppose that the codebase already has their own `std::elide`-alike — which, btw, isn't even a seven-liner; it's now a five-liner.
>
> template<class F>
> struct SCSE {
> F f_;
> operator decltype(f_())() const { return f_(); }
> };
>
> Then we have these two calls working already:
>
> ocs8.emplace(std::elide([]{ return counting_semaphore<8>(5); }));
> ocs8.emplace(SCSE([]{ return counting_semaphore<8>(5); }));
>
> and Gasper is asking for this call to work as well:
>
> ocs8.emplace(SCSE(std::elide([]{ return counting_semaphore<8>(5); }))); // Gasper's request, IIUC
>
> Adding the `operator()` gets us that. Although, I still don't see why we want SCSE to be constructible from std::elide. I don't see how this helps with "interop." What's a scenario where I'd already have a `std::elide` object — whose sole purpose is to be treated like a `T` — and, instead of treating it like a `T`, I'm going to try to construct an `SCSE` out of it? That seems wrong. An `SCSE` expects a callable `C`, and so my `std::elide` should implicitly convert to `C` iff `T=C`, but otherwise it should stay aloof, IMHO. I don't see a concrete scenario where I'd want to be cavalier about the meaning of `elide` — like, "Please convert to `T` if you can, or otherwise convert to `SCSE`." Those are two different "parts of speech," IMO.
>
> (But, just to be clear, I consider this all academic, because the STL should not have `std::elide`.)
>
> –Arthur
--
Std-Proposals mailing list
Std-Proposals_at_[hidden]
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

Received on 2024-05-30 19:28:19