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