invoke and unpacking tuple-like type instances

102 views
Skip to first unread message

Vicente J. Botet Escriba

unread,
Jan 9, 2016, 12:50:43 PM1/9/16
to std-pr...@isocpp.org
Hi,


I would like to have some feedback on a function that acts as unpacking
tuple-like classes in the context of the invoke function. This was
presented already with the name args(t) as an alternative library
solution to unpack tuple in the thread "[std-discussion] Distinction
between Argument packs and tuples" [1] where an operator... on tuple was
proposed. The proposed operator... introduced breaking changes and so
another operator would be needed.

make_tuple packs some elements in a tuple. It seem natural to think of
unpacking a tuple into its elements, so that

make_tuple(unpack(t)) == t // that is (pack . unpack = id)

The same applies to forward_as_tuple:

forward_as_tuple(unpack(g())) == g()

The result of unpack could be a wrapper unpacked<T> as ref wraps a
reference in a reference wrapper.

Having this, we can adapt invoke so that, if some of its args are
unpacked<T>, invoke would work as if

invoke(f, a, b, unpack(t1), d, unpack(t2)) =
apply(f, tuple_cat(forward_as_tuple(a), forward_as_tuple(b),
forward_as_tuple(unpack(t1)), forward_as_tuple(d),
forward_as_tuple(unpack(t2))))
apply(f, tuple_cat(forward_as_tuple(a), forward_as_tuple(b), t1,
forward_as_tuple(d), t2))
apply(f, tuple{a, b, get<0>(t1), ..., get<N1-1>(t1), d, get<0>(t2),
..., get<N2-1>(t2}));
invoke(f, a, b, get<0>(t1), ..., get<N1-1>(t1), d, get<0>(t2), ...,
get<N2-1>(t2));
f(a, b, get<0>(t1), ..., get<N1-1>(t1), d, get<0>(t2), ...,
get<N2-1>(t2));

where Ni is the tuple_size<decltype(ti)>::value


Definition when one of Args is unpacked<T>

template <class F, class ...Args>
auto invoke(F&& f, Args args...) {
return apply(forward<F>(f), forward_as_tuple(forward<Args>(args)...);
}


unpack shoudl works with lvalue and rvalues

template <class TL>
unpacked<reference_wrapper<TL>> unpack(TL & tl);

template <class TL>
unpacked<decay<TL>> unpack(TL && tl);


and unpack on unpacked doesn't changes anything as ref with
reference_wrapper

template <class T>
unpacked<T>& unpack(unpacked<T> & tl);

template <class T>
unpacked<T> const& unpack(unpacked<T> const& tl);

template <class T>
unpacked<T> && unpack(unpacked<T> && tl);

In addition, given a tuple t, what could be the meaning of *t? Well t is
not a pointer, but it contains things as optional does, so we can define
tuple::operator*() as if we unpacked it

std::tuple<int, string> t;
...
invoke(f, a, b, *t1, d) == f(a, b, get<0>(t1), ..., get<N1-1>(t1), d);

Note that if as_const is accepted there is no need for a specific
cunpack function as unpack(as_const(t)).

Note also that unpack would works not only for std::tuple, but with any
tuple-like type providing get<I> access.
However the operator* need to be defined explicitly for each tuple-like
type :(

Bike-shading:
unpack/unpacked
unpack/tuple_like_wrapper
...

Waiting for a language-based proposal, is there an interest in a library
proposal providing a partial solution (unpack needs invoke to be expanded)?

Best,
Vicente

P.S. Any

[1]
https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/qsM_4DijZFM

Matthew Woehlke

unread,
Jan 14, 2016, 12:00:42 PM1/14/16
to std-pr...@isocpp.org
On 2016-01-09 12:50, Vicente J. Botet Escriba wrote:
> I would like to have some feedback on a function that acts as unpacking
> tuple-like classes in the context of the invoke function. This was
> presented already with the name args(t) as an alternative library
> solution to unpack tuple in the thread "[std-discussion] Distinction
> between Argument packs and tuples" [1] where an operator... on tuple was
> proposed. The proposed operator... introduced breaking changes and so
> another operator would be needed.
>
> [...bunches of examples...]

Ugh, is the benefit of not adding a language feature *really* worth all
the ugliness, difficulties, and limitations entailed in using the
suggested library feature? Not to mention that there is now a magic type
that behaves differently in certain functions?

In a post-unpacking world, the compiler already knows how to transform a
tuple-like into a value sequence. Surely, then, it is not so terrible to
add the ability to do this in place:

make_tuple([*]t); == t, if 't' is a std::tuple
f(a, b, [*]t1, d, [*]t2);

I fail to see why it is difficult for the compiler to transform these into:

auto&& __t0 = t; // if 't' is an expression rather than a variable
make_tuple(get<0>(__t0), get<1>(__t0), ...);

auto&& __t1 = t1; // let's say t1 is a 3-tuple
auto&& __t2 = t2; // ...and t2 is a 2-tuple
f(a, b, get<0>(__t1), get<1>(__t1), get<2>(__t1),
d, get<0>(__t2), get<1>(__t2);

This way, there is no magic unpacking type, and unpacking can be used in
any context where a value sequence is permitted; not just contexts that
have been special cased for the magic unpacking type.

Just as one offhand example, why shouldn't I be able to unpack a
tuple-like into an initializer list? Or ctor arguments? (This neatly
solves the issue previously discussed of converting between types with
similar layouts that don't otherwise have any knowledge of each other.)

> Waiting for a language-based proposal, is there an interest in a library
> proposal providing a partial solution (unpack needs invoke to be expanded)?

Per above, I think a library solution is inferior, and I don't like
adding one when we "know that we need" a language-based solution, as we
end up with multiple ways to do the same thing, one of which is
superfluous. I also think the library solution is actually *harder* to
specify.

Do I need to (co?)write a proposal for a language feature?

--
Matthew

Vicente J. Botet Escriba

unread,
Jan 14, 2016, 5:17:50 PM1/14/16
to std-pr...@isocpp.org
Le 14/01/2016 18:00, Matthew Woehlke a écrit :
> On 2016-01-09 12:50, Vicente J. Botet Escriba wrote:
>> I would like to have some feedback on a function that acts as unpacking
>> tuple-like classes in the context of the invoke function. This was
>> presented already with the name args(t) as an alternative library
>> solution to unpack tuple in the thread "[std-discussion] Distinction
>> between Argument packs and tuples" [1] where an operator... on tuple was
>> proposed. The proposed operator... introduced breaking changes and so
>> another operator would be needed.
>>
>> [...bunches of examples...]
> Ugh, is the benefit of not adding a language feature *really* worth all
> the ugliness, difficulties, and limitations entailed in using the
> suggested library feature?
I will be happy to review a concrete proposal ;-)
> Not to mention that there is now a magic type
> that behaves differently in certain functions?
Which type?
>
> In a post-unpacking world, the compiler already knows how to transform a
> tuple-like into a value sequence. Surely, then, it is not so terrible to
> add the ability to do this in place:
>
> make_tuple([*]t); == t, if 't' is a std::tuple
> f(a, b, [*]t1, d, [*]t2);
>
> I fail to see why it is difficult for the compiler to transform these into:
>
> auto&& __t0 = t; // if 't' is an expression rather than a variable
> make_tuple(get<0>(__t0), get<1>(__t0), ...);
>
> auto&& __t1 = t1; // let's say t1 is a 3-tuple
> auto&& __t2 = t2; // ...and t2 is a 2-tuple
> f(a, b, get<0>(__t1), get<1>(__t1), get<2>(__t1),
> d, get<0>(__t2), get<1>(__t2);
>
> This way, there is no magic unpacking type, and unpacking can be used in
> any context where a value sequence is permitted; not just contexts that
> have been special cased for the magic unpacking type.
>
> Just as one offhand example, why shouldn't I be able to unpack a
> tuple-like into an initializer list? Or ctor arguments? (This neatly
> solves the issue previously discussed of converting between types with
> similar layouts that don't otherwise have any knowledge of each other.)

See my proposal as an incentive for you to write the language-like based
unpack proposal.
>
>> Waiting for a language-based proposal, is there an interest in a library
>> proposal providing a partial solution (unpack needs invoke to be expanded)?
> Per above, I think a library solution is inferior, and I don't like
> adding one when we "know that we need" a language-based solution, as we
> end up with multiple ways to do the same thing, one of which is
> superfluous. I also think the library solution is actually *harder* to
> specify.
>
> Do I need to (co?)write a proposal for a language feature?
>
For the time being, it is you that have raised this possibility, so yes,
I believe the answer is yes, you should.

Vicente

Matthew Woehlke

unread,
Jan 15, 2016, 9:48:06 AM1/15/16
to std-pr...@isocpp.org
On 2016-01-14 17:17, Vicente J. Botet Escriba wrote:
> Le 14/01/2016 18:00, Matthew Woehlke a écrit :
>> On 2016-01-09 12:50, Vicente J. Botet Escriba wrote:
>>> I would like to have some feedback on a function that acts as unpacking
>>> tuple-like classes in the context of the invoke function. This was
>>> presented already with the name args(t) as an alternative library
>>> solution to unpack tuple in the thread "[std-discussion] Distinction
>>> between Argument packs and tuples" [1] where an operator... on tuple was
>>> proposed. The proposed operator... introduced breaking changes and so
>>> another operator would be needed.
>>>
>>> [...bunches of examples...]
>>
>> Ugh, is the benefit of not adding a language feature *really* worth all
>> the ugliness, difficulties, and limitations entailed in using the
>> suggested library feature?
>
> I will be happy to review a concrete proposal ;-)

Yeah... I should probably write one...

>> Not to mention that there is now a magic type
>> that behaves differently in certain functions?
>
> Which type?

unpacked<T>... or did I completely misunderstand your approach?

> See my proposal as an incentive for you to write the language-like based
> unpack proposal.

:-)

--
Matthew

Reply all
Reply to author
Forward
0 new messages