c++ - 有什么方法可以访问除最后一个模板参数之外的所有内容吗?

标签 c++ c++11

可以按如下方式使用模板参数包:

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;

最佳答案

您可以采用使用 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>;
};

关于c++ - 有什么方法可以访问除最后一个模板参数之外的所有内容吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55465961/

相关文章:

c++ - 如何有条件地实例化具有多个模板参数的模板类?

c++ - 使用作为类成员的类模板

c++ - 在 Mac 上将 GCC 4.4 与 NetBeans 集成

c++ - 如何在类成员互斥锁上使用 std::lock_guard

c++ - Final 说明符对单独的声明和定义没有影响

c++ - 使用 decltype 访问静态字段

c++ - 成员函数的模板特化

c++ - 在类中访问 malloc'd 二维数组时出现段错误

c++ - C++ 运算符 "*"是左关联还是右关联?

c++ - 类型删除和可变参数模板化成员函数