拆分参数包

use*_*460 5 c++ templates template-inheritance template-meta-programming variadic-templates

我想拆分模板参数包。像这样的东西。我怎么能去做这件事?

template< typename... Pack >
struct TypeB : public TypeA< get<0, sizeof...(Pack)/2>(Pack...) >
             , public TypeA< get<sizeof...(Pack)/2, sizeof...(Pack)>(Pack...) > 
{
};
Run Code Online (Sandbox Code Playgroud)

这是我对为什么这个问题不重复的看法:我正在寻找一种通用的方法来做到这一点,当将拆分包传递给其他模板类时,该方法将起作用 - 如上所示。以及将其传递给函数。

max*_*x66 1

我想有很多方法可以做到这一点。

如果您至少可以使用 C++14,我建议使用decltype()和的功能std::tuple_cat(),如下所示:

(1) 声明(没有定义的原因,因为通过decltype()几个重载(和 SFINAE 启用/禁用)使用,如下所示

template <std::size_t Imin, std::size_t Imax, std::size_t I, typename T>
std::enable_if_t<(Imin <= I) && (I < Imax), std::tuple<T>> getTpl ();

template <std::size_t Imin, std::size_t Imax, std::size_t I, typename>
std::enable_if_t<(I < Imin) || (Imax <= I), std::tuple<>> getTpl ();
Run Code Online (Sandbox Code Playgroud)

std::tuple<T>这个想法是当索引在正确的范围内时返回 a ,std::tuple<>否则返回 a。

(2)定义一个辅助类,将a转换std::tuple<Ts...>为aTypeA<Ts...>

template <typename>
struct pta_helper2;

template <typename ... Ts>
struct pta_helper2<std::tuple<Ts...>>
 { using type = TypeA<Ts...>; };
Run Code Online (Sandbox Code Playgroud)

(3) 定义一个辅助类,仅将正确范围内的类型连接到元组中

template <std::size_t, std::size_t, typename ... Ts>
struct pta_helper1;

template <std::size_t I0, std::size_t I1, std::size_t ... Is, typename ... Ts>
struct pta_helper1<I0, I1, std::index_sequence<Is...>, Ts...>
 : public pta_helper2<decltype(std::tuple_cat(getTpl<I0, I1, Is, Ts>()...))>
 { };
Run Code Online (Sandbox Code Playgroud)

这个想法是连接一系列std::tuple<>std::tuple<T>,其中T类型是请求范围内的类型;结果类型( 的模板参数pta_helper2)是 a std::tuple<Us...>,其中Us...正是所请求范围内的类型。

(4) 定义一个using类型以更简单的方式使用前面的辅助类

template <std::size_t I0, std::size_t I1, typename ... Ts>
using proTypeA = typename pta_helper1<
   I0, I1, std::make_index_sequence<sizeof...(Ts)>, Ts...>::type;
Run Code Online (Sandbox Code Playgroud)

(5) 现在你TypeB就变成了

template <typename ... Ts>
struct TypeB : public proTypeA<0u, sizeof...(Ts)/2u, Ts...>,
               public proTypeA<sizeof...(Ts)/2u, sizeof...(Ts), Ts...>
 { };
Run Code Online (Sandbox Code Playgroud)

以下是完整编译C++14示例

#include <tuple>
#include <type_traits>

template <typename ...>
struct TypeA
 { };

template <std::size_t Imin, std::size_t Imax, std::size_t I, typename T>
std::enable_if_t<(Imin <= I) && (I < Imax), std::tuple<T>> getTpl ();

template <std::size_t Imin, std::size_t Imax, std::size_t I, typename>
std::enable_if_t<(I < Imin) || (Imax <= I), std::tuple<>> getTpl ();

template <typename>
struct pta_helper2;

template <typename ... Ts>
struct pta_helper2<std::tuple<Ts...>>
 { using type = TypeA<Ts...>; };

template <std::size_t, std::size_t, typename ... Ts>
struct pta_helper1;

template <std::size_t I0, std::size_t I1, std::size_t ... Is, typename ... Ts>
struct pta_helper1<I0, I1, std::index_sequence<Is...>, Ts...>
 : public pta_helper2<decltype(std::tuple_cat(getTpl<I0, I1, Is, Ts>()...))>
 { };

template <std::size_t I0, std::size_t I1, typename ... Ts>
using proTypeA = typename pta_helper1<
   I0, I1, std::make_index_sequence<sizeof...(Ts)>, Ts...>::type;


template <typename ... Ts>
struct TypeB : public proTypeA<0u, sizeof...(Ts)/2u, Ts...>,
               public proTypeA<sizeof...(Ts)/2u, sizeof...(Ts), Ts...>
 { };

int main()
 {
   using tb  = TypeB<char, short, int, long, long long>;
   using ta1 = TypeA<char, short>;
   using ta2 = TypeA<int, long, long long>;

   static_assert(std::is_base_of<ta1, tb>::value, "!");
   static_assert(std::is_base_of<ta2, tb>::value, "!");
 }
Run Code Online (Sandbox Code Playgroud)