从std :: tuple <some_types ...>开始创建子元组

Ili*_*llo 4 c++ templates variadic-templates c++11 stdtuple

让我们假设std::tuple<some_types...>给出了一个.我想创建一个新std::tuple的类型是索引的类型[0, sizeof...(some_types) - 2].例如,让我们假设起始元组是std::tuple<int, double, bool>.我想获得一个定义为的子元组std::tuple<int, double>.

我对可变参数模板很新.作为第一步,我试着写一个struct负责存储不同类型的原始文件std::tuple,目的是创建一个同类的新元组(如std::tuple<decltype(old_tuple)> new_tuple).

template<typename... types>
struct type_list;

template<typename T, typename... types>
struct type_list<T, types...> : public type_list<types...>  {
    typedef T type;
};


template<typename T>
struct type_list<T> {
    typedef T type;
};
Run Code Online (Sandbox Code Playgroud)

我想做的是:

std::tuple<type_list<bool, double, int>::type...> new_tuple // this won't work
Run Code Online (Sandbox Code Playgroud)

下一步是丢弃参数包中的最后一个元素.如何访问type存储的几个type_list?以及如何丢弃其中一些?

谢谢.

Cas*_*sey 6

使用索引序列技术可以很容易地进行这种操作:生成一个比元组少两个索引的索引序列,并使用该序列从原始字段中选择字段。std::make_index_sequence从C ++ 14 使用并返回类型推导:

template <typename... T, std::size_t... I>
auto subtuple_(const std::tuple<T...>& t, std::index_sequence<I...>) {
  return std::make_tuple(std::get<I>(t)...);
}

template <int Trim, typename... T>
auto subtuple(const std::tuple<T...>& t) {
  return subtuple_(t, std::make_index_sequence<sizeof...(T) - Trim>());
}
Run Code Online (Sandbox Code Playgroud)

在C ++ 11中:

#include <cstddef>     // for std::size_t

template<typename T, T... I>
struct integer_sequence {
  using value_type = T;

  static constexpr std::size_t size() noexcept {
    return sizeof...(I);
  }
};

namespace integer_sequence_detail {
template <typename, typename> struct concat;

template <typename T, T... A, T... B>
struct concat<integer_sequence<T, A...>, integer_sequence<T, B...>> {
  typedef integer_sequence<T, A..., B...> type;
};

template <typename T, int First, int Count>
struct build_helper {
  using type = typename concat<
    typename build_helper<T, First,           Count/2>::type,
    typename build_helper<T, First + Count/2, Count - Count/2>::type
  >::type;
};

template <typename T, int First>
struct build_helper<T, First, 1> {
  using type = integer_sequence<T, T(First)>;
};

template <typename T, int First>
struct build_helper<T, First, 0> {
  using type = integer_sequence<T>;
};

template <typename T, T N>
using builder = typename build_helper<T, 0, N>::type;
} // namespace integer_sequence_detail

template <typename T, T N>
using make_integer_sequence = integer_sequence_detail::builder<T, N>;

template <std::size_t... I>
using index_sequence = integer_sequence<std::size_t, I...>;

template<size_t N>
using make_index_sequence = make_integer_sequence<size_t, N>;

#include <tuple>

template <typename... T, std::size_t... I>
auto subtuple_(const std::tuple<T...>& t, index_sequence<I...>) 
  -> decltype(std::make_tuple(std::get<I>(t)...))
{
  return std::make_tuple(std::get<I>(t)...);
}

template <int Trim, typename... T>
auto subtuple(const std::tuple<T...>& t)
  -> decltype(subtuple_(t, make_index_sequence<sizeof...(T) - Trim>()))
{
  return subtuple_(t, make_index_sequence<sizeof...(T) - Trim>());
}
Run Code Online (Sandbox Code Playgroud)

住在Coliru


Yak*_*ont 6

这是一种直接解决问题的方法.

template<unsigned...s> struct seq { typedef seq<s...> type; };
template<unsigned max, unsigned... s> struct make_seq:make_seq<max-1, max-1, s...> {};
template<unsigned...s> struct make_seq<0, s...>:seq<s...> {};

template<unsigned... s, typename Tuple>
auto extract_tuple( seq<s...>, Tuple& tup ) {
  return std::make_tuple( std::get<s>(tup)... );
}
Run Code Online (Sandbox Code Playgroud)

您可以按如下方式使用:

std::tuple< int, double, bool > my_tup;
auto short_tup = extract_tuple( make_seq<2>(), my_tup );
auto skip_2nd = extract_tuple( seq<0,2>(), my_tup );
Run Code Online (Sandbox Code Playgroud)

decltype在需要结果类型时使用.

一种完全不同的方法是编写append_type,它接受一个类型和一个tuple<...>,并将该类型添加到最后.然后添加到type_list:

template<template<typename...>class target>
struct gather {
  typedef typename type_list<types...>::template gather<target>::type parent_result;
  typedef typename append< parent_result, T >::type type;
};
Run Code Online (Sandbox Code Playgroud)

这为您提供了一种方法,可以将您的类型累积type_list到任意参数包中template.但这不是您的问题所必需的.