Re: argument packs manipulations
On 24 Aug., 23:04, Marc <marc.gli...@gmail.com> wrote:
First, thanks a lot for this very detailed and useful answer.
You are welcome.
Note that the hom function was later replaced with:
template <class...> struct Last_type; // bug 39653
template <class T,class... U> struct Last_type<T,U...> {
typedef typename Last_type<U...>::type type;};
template <class T> struct Last_type<T> {
typedef T type;
};
Occasionally I also found use for the more
general tool:
template<std::size_t I, class...> struct ith;
template<class T, class... Ts>
struct ith<0, T, Ts...> {
typedef T type;
};
template<std::size_t I, class T, class... Ts>
struct ith<I, T, Ts...> {
typedef typename ith<I - 1, Ts...>::type type;
};
template <class T> T && last_arg(T && t) {
return std::forward<T>(t);}
template <class T,class... U>
typename Last_type<U&&...>::type last_arg(T&&, U&&... u)
// bug 44175
//auto last_arg(T&&, U&&... u)
//->decltype(last_arg(std::forward<U>(u)...))
{
return last_arg(std::forward<U>(u)...);
}
Yes, that should also work. In fact, it is possible
to define a set of free get functions, tuple_element,
and tuple_size for parameter packs (I did that a while
ago). The disadvantage of such an approach is, that
the compiler needs to expand the pack recursively (with
one element less each time). So, I think that forwarding
such a pack once is *in general* the more effective
approach.
One thing though: std::get seems to lose the rvalue-ness of arguments
(not that it's hard to get the i-th type and cast appropriately
afterwards).
Indeed, this is reflected by the following library issue:
http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#1191
template<class T, int D>
struct VecBase {
T tab[D];
template<std::size_t... I, class Tuple>
VecBase(eq_tag, indices<I...>, Tuple&& t) :
tab({static_cast<T>(std::get<I>(t))...})
{
}
With code like this, do I get a conversion followed by a copy/move, or
can the compiler do the conversion directly into tab[i]? And if I
replace std::get with something more std::forward-like and pass a
temporary to the constructor, do I still stand a chance that tab[i]
may be directly move-initialized from it?
static_cast indeed performs a conversion and may construct a
temporary, see [expr.static.cast]/4. You can get rid of
the static_cast, but that would have the effect that you
couldn't initialize a double array with int values because
narrowing conversions strike back. Assuming that rvalue-
reference overloads of get are provided as described in LWG
issue #1191, you would probably want to replace this by:
template<std::size_t... I, class Tuple>
VecBase(eq_tag, indices<I...>, Tuple&& t) :
tab({static_cast<T>(std::get<I>(std::forward<Tuple>(t)))...})
{
}
If you can live without support for int -> double
support, you can remove the static_cast of-course,
but you should test that (when possible). In a more
complicated - but potentially more efficient -
implementation you could type-switch between
using static_cast (e.g. for conversions among
scalar types) and not using so (all other cases).
HTH & Greetings from Bremen,
Daniel Kr?gler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]