C++ 层次结构中的反向可变模板参数

C++ 层次结构中的反向可变模板参数,c++,c++11,C++,C++11,我目前有一个使用typelist的类: template<class AbstractF, template<class, class > class Creator, class TList> class A: public B<typename Reverse<TList>::Result, Creator, AbstractF> { }; 我试图使代码更为c++11友好,用可变模板参数替换类型列表 template<class Abs

我目前有一个使用typelist的类:

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的用法,但在本例中,我无法理解如何解包,因为可变参数不是简单模板函数的一部分,而是用作类层次结构中的参数。

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

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的一部分,因此必须以不同的方式实现类型索引。这是一种可能的实现

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

如果您使用旧的类型列表方式,则链接类型列表 然后在C++11中,您甚至可以在std::tuple或类似文件中使用未打包的可变模板参数,或打包的可变模板参数

解包方式在操作转换、跳头、连接等方面存在局限性,可能需要先使用打包方式

对于重新订购,包装方式可能是:

template <typename TypeList, typename Seq> struct ReverseImpl;

template <typename TypeList, std::size_t ... Is>
struct ReverseImpl<TypeList, std::index_sequence<Is...>>
{
    using type = std::tuple<typename std::tuple_element<sizeof...(Is) - 1 - Is, TypeList>::type...>;
};


template <typename TypeList> struct Reverse
{
    using Result =
        typename ReverseImpl<TypeList,
                             std::make_index_sequence<std::tuple_size<TypeList>::value>>::type;
};
template <template<class, class > class Creator, class AbstractF, typename TypeList>
struct BUnpack;

template<template<class, class > class Creator, class AbstractF, typename ... Ts>
class BUnpack<Creator, AbstractF, std::tuple<Ts...>>
{
    using type = B<Creator, AbstractF, Ts...>;
};

template<class AbstractF, template<class, class > class Creator, typename ... Ts>
class A: public BUnpack<Creator, AbstractF, typename Reverse<std::tuple<Ts...>>::Result>::type {
};

这回答了你的问题吗@不,事实上,正如我所说的,所有的东西都适用于一个函数,但在这种情况下,没有涉及函数,只是类层次结构中使用的类型列表。如果所有类型都是不同的,那么有一个简单的解决方案。如果不是,你不能没有间接寻址。@Evg它们应该是有区别的,只需添加std::tuple_元素\u t是c++14非强制性的,但我希望代码即使在旧版本上也能工作compilers@greywolf82,则应使用类模板重新实现类型索引。我更新了答案。