On Thu, May 30, 2024 at 11:14 AM Frederick Virchanza Gotham via Std-Proposals <std-proposals@lists.isocpp.org> 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