首页 > 解决方案 > 在层次结构中反转可变参数模板参数

问题描述

我目前有这个使用类型列表的类:

template<class AbstractF, template<class, class > class Creator, class TList>
class A: public B<typename Reverse<TList>::Result, Creator, AbstractF> {
};

我试图使代码对 c++11 更友好,用可变参数模板参数替换类型列表。

template<class AbstractF, template<class, class > class Creator, class TList...>
class A: public B<Creator, AbstractF, TList...> { //<---how to reverse here?
};

问题是:如何反转可变参数列表?查看其他问题,我看到了 的用法std::tuple,但在这种情况下,我无法理解如何“解包”它,因为可变参数不是简单模板函数的一部分,而是用作类层次结构中的参数。

标签: c++c++11

解决方案


如果包中的所有类型都是不同的,则可以index从类型本身计算类型。剩下的就是N - 1 - index从包中提取 'th 类型:

template<std::size_t index, class... Ts>
using Nth_type = std::tuple_element_t<index, std::tuple<Ts...>>;

template<class S, class... Ts>
inline constexpr std::size_t type_index = 0;

template<class S, class T, class... Ts>
inline constexpr std::size_t type_index<S, T, Ts...> = 
    std::is_same_v<S, T> ? 0 : 1 + type_index<S, Ts...>;

template<class T, class... Ts>
using Reverser = Nth_type<sizeof...(Ts) - 1 - type_index<T, Ts...>, Ts...>;

简单的例子:

template<class... Ts>
class B;

template<class... Ts>
using RB = B<Reverser<Ts, Ts...>...>;   // two pack expansions here

static_assert(std::is_same<RB<>, B<>>());
static_assert(std::is_same<RB<int>, B<int>>());
static_assert(std::is_same<RB<int, float, double>, B<double, float, int>>());

如果允许包包含相同的类型,则此技巧将不起作用。

此代码使用了一些 C++14/17 功能。变量模板不是 C++11 的一部分,因此type_index必须以不同的方式实现。是一个可能的实现。


推荐阅读