可以如下使用模板参数包:
template <int T1, int... Ts>
struct Test {
static constexpr int sizes[] = {Ts...};
};
template <int T1, int... Ts>
constexpr int Test<T1, Ts...>::sizes[];
但是,如here所述,模板参数包必须是最后一个模板参数。因此,我们不能有这样的代码:
template <int T1, int... Ts, int Tn>
struct Test {
static constexpr int sizes[] = {Ts...};
Foo<Ts...> foo;
};
template <int T1, int... Ts, int Tn>
constexpr int Test<T1, Ts..., Tn>::sizes[];
在许多情况下,我们需要访问一组模板参数的最后一个元素。我的问题是,实现以上代码的最佳实践是什么?
编辑:
这不是this question的重复项。我正在尝试获取除最后一个参数(而不是最后一个参数本身)以外的所有内容,因为我需要如下定义Foo
:
Foo<Ts...> foo;
答案 0 :(得分:3)
您可以使用使用std::index_sequence
template<template<auto...> typename Tmp, size_t... Is, typename... Args>
constexpr auto take_as(std::index_sequence<Is...>, Args...)
{
using Tup = std::tuple<Args...>;
return Tmp<std::tuple_element_t<Is, Tup>{}...>{};
}
template<auto... Vals>
struct except_last
{
template<template<auto...> typename Tmp>
using as = decltype(take_as<Tmp>(std::make_index_sequence<sizeof...(Vals) - 1>{},
std::integral_constant<decltype(Vals), Vals>{}...));
};
您用作哪个
using F = except_last<1, 2, 3, 4>::as<Foo>; // F is Foo<1, 2, 3>
这既易于实现和读取,但有可能获得O(n)实例化深度。如果您迷恋效率,可以通过滥用折叠表达式来达到O(1)实例化深度
template<typename T>
struct tag
{
using type = T;
};
template<typename F, typename... Ts>
using fold_t = decltype((F{} + ... + tag<Ts>{}));
template<size_t N, typename... Ts>
struct take
{
template<typename T>
auto operator+(tag<T>) -> take<N - 1, Ts..., T>;
};
template<typename... Ts>
struct take<0, Ts...>
{
template<template<auto...> typename Tmp>
using as = Tmp<Ts{}...>;
template<typename T>
auto operator+(tag<T>) -> take<0, Ts...>;
};
template<auto... Vals>
struct except_last
{
template<template<auto...> typename Tmp>
using as = fold_t<take<sizeof...(Vals) - 1>,
std::integral_constant<decltype(Vals), Vals>...>::template as<Tmp>;
};
答案 1 :(得分:0)
访问最后一个模板参数的最有效方法是什么?
您可以使用一个小帮手将参数包转换为数组。
template<int... Args>
struct pack {
static constexpr std::array as_array{ Args... };
};
然后可以使用数组索引获取最后一个参数:
template <int T1, int... Ts>
struct Test {
static constexpr int last = pack<Ts...>::as_array[sizeof...(Ts) - 1];
答案 2 :(得分:0)
integer_sequence
是一种方式:
template <typename SeqN, typename Seq> struct TestImpl;
template <int... Ns, std::size_t ... Is>
struct TestImpl<std::integer_sequence<int, Ns...>, std::index_sequence<Is...>>
{
private:
using SeqTuple = std::tuple<std::integral_constant<int, Ns>...>;
public:
static constexpr int sizes[] = {std::tuple_element_t<Is, SeqTuple>::value...};
Foo<std::tuple_element_t<Is, SeqTuple>::value...> foo;
};
template <int N1, int N2, int... Ns> // At least 2 numbers
using Test = TestImpl<std::integer_sequence<int, N1, N2, Ns...>,
std::make_index_sequence<1 + sizeof...(Ns)>>;