I know how to select first parameter of variadic template:
template< class...Args> struct select_first;
template< class A, class ...Args> struct
Same approach as last time, O(logN) instantiation depth. Using only one overload, so it should consume less resources.
Warning: it currently removes references from the tuple types.
Note: Removed the reference from pack::declval. I think it still works in every case.
indices trick in O(log(N)) instantiations, by Xeo; modified to use std::size_t instead of unsigned
#include
// using aliases for cleaner syntax
template using Invoke = typename T::type;
template struct seq{ using type = seq; };
template struct concat;
template
struct concat, seq>
: seq{};
template
using Concat = Invoke>;
template struct gen_seq;
template using GenSeq = Invoke>;
template
struct gen_seq : Concat, GenSeq>{};
template<> struct gen_seq<0> : seq<>{};
template<> struct gen_seq<1> : seq<0>{};
Today, I realized there's a different, simpler and probably faster (compilation time) solution to get the nth type of a tuple (basically an implementation of std::tuple_element). Even though it's a direct solution of another question, I'll also post it here for completeness.
namespace detail
{
template
struct Any
{
template Any(T&&) {}
};
template
struct wrapper {};
template
struct get_nth_helper
{
template
static T deduce(Any..., wrapper, ...);
};
template
auto deduce_seq(seq, wrapper... pp)
-> decltype( get_nth_helper::deduce(pp...) );
}
#include
template
struct tuple_element;
template
struct tuple_element>
{
using type = decltype( detail::deduce_seq(gen_seq{},
detail::wrapper()...) );
};
Helper for last element:
template
struct tuple_last_element;
template
struct tuple_last_element>
{
using type = typename tuple_element> :: type;
};
Usage example:
#include
#include
int main()
{
std::tuple t{42, true, 'c'};
tuple_last_element::type x = 'c'; // it's a reference
static_assert(std::is_same{}, "!");
}
Original version:
#include
#include
namespace detail
{
template
struct get_last_helper;
template
struct get_last_helper< seq, TT... >
{
template
struct pack {};
template
struct pack
{
T declval();
};
// this needs simplification..
template
struct exp : TTpacked...
{
static auto declval_helper()
-> decltype(std::declval().declval());
using type = decltype(declval_helper());
};
using type = typename exp...>::type;
};
}
template< typename Tuple >
struct get_last;
template< typename... TT >
struct get_last>
{
template
static seq helper(seq);
using seq_t = decltype(helper(gen_seq()));
using type = typename detail::get_last_helper::type;
};
int main()
{
using test_type = std::tuple;
static_assert(std::is_same::type>::value, "!");
// fails:
static_assert(std::is_same::type>::value, "!");
}