C++ Logo


Advanced search

Re: [std-proposals] Defect report for std::apply (or apply_perfectly)

From: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Date: Mon, 11 Mar 2024 10:07:41 +0000
On Sun, Mar 10, 2024 at 2:07 PM Jonathan Wakely wrote:
> But this is exactly the same behaviour you get with
> Func(std::get<0>(t), std::get<1>(t), std::get<2>(t)),
> or equivalently with std::move(t) for each argument.

But I wouldn't call a function like that. Nor do I think would anyone
else. If I were calling a function called 'Func' with a list of
arguments, I wouldn't pass the Rvalues as Lvalues. Therefore if I were
to write out "std::get" by myself, I would use 'static_cast' or 'move'
or 'forward' to pass the arguments properly. __Unless__ I didn't want
perfect forwarding for some reason or other.

> For the hundredth time, stop showing how to code something and demonstrate
> why it's needed. Your motivation is "when I use tuple in a way that's not expected
> to work, it doesn't work".

The reason I coded it was to show that I thought the following made more sense:

(1) Lvalue references get passed as Lvalue references
(2) Rvalue references get passed as Rvalue references
(3) Non-reference types get passed by reference (the same kind of
reference as how the tuple was passed)

Your suggestion to pass the tuple by Rvalue reference helps me to
achieve (1) and (2), but not (3). When it comes to (3), your
suggestion makes the non-reference types get passed by Rvalue
reference -- but I don't want this.

It makes more sense to me, when it comes to (3), that the L-or-Rness
of the non-reference types should be determined by the L-or-Rness of
the tuple itself, and that's why I coded it as:

    #define tElem tuple_element_t< I, remove_reference_t<Tuple> >
    #define tElem_NoRef remove_reference_t< tElem >
    #define vElem_IsRef (!is_same_v< tElem , tElem_NoRef >)
    #define vElem_ShouldBeR (is_rvalue_reference_v< tElem > ||
    (!vElem_IsRef && !is_lvalue_reference_v<Tuple>))
    #define tElem_CastTo conditional_t< vElem_ShouldBeR ,
    tElem_NoRef&&, tElem_NoRef& >

    return invoke( forward<F>(f), static_cast< tElem_CastTo >( get<I>(t) )... );

Although maybe I could have written a lambda or a template class to do
away with the preprocessor macroes.

Received on 2024-03-11 10:07:50