Split error std :: index_sequence

I am trying to split index_sequenceinto two halves. To do this, I create index_sequencewith the bottom half and use it to skip the leading elements in full index_sequence. Below is a minimal test case that is what I am trying to achieve:

template <int ...I>
struct index_sequence {};

template <int ...I, int ...J>
void foo(index_sequence<I...>, index_sequence<I..., J...>)
{}

int main()
{
    foo(index_sequence<0>{}, index_sequence<0, 1>{});
}

I tried this with the latest versions of Clang, GCC and MSVC, and all of them could not output J.... Is this permitted by the standard? If not, then why and what would be a good way to achieve my intentions?

+4
source share
4 answers

14.8.2.5/9... P , , - ...

, index_sequence<I..., J...> index_sequence<0, 1>{} I..., J....

+6

std::index_sequence std::index_sequence s, , slice std::index_sequence .

std::index_sequence , N3658, .

make_index_range

slice, make_integer_range. std::index_sequence, [Begin, End] [0, End]. std::make_integer_sequence, :

template <typename T, typename Seq, T Begin>
struct make_integer_range_impl;

template <typename T, T... Ints, T Begin>
struct make_integer_range_impl<T, std::integer_sequence<T, Ints...>, Begin> {
  using type = std::integer_sequence<T, Begin + Ints...>;
};

/* Similar to std::make_integer_sequence<>, except it goes from [Begin, End)
   instead of [0, End). */
template <typename T, T Begin, T End>
using make_integer_range = typename make_integer_range_impl<
    T, std::make_integer_sequence<T, End - Begin>, Begin>::type;

/* Similar to std::make_index_sequence<>, except it goes from [Begin, End)
   instead of [0, End). */
template <std::size_t Begin, std::size_t End>
using make_index_range = make_integer_range<std::size_t, Begin, End>;

std::get - std::index_sequence , std::array, std::get. .

template <std::size_t... Indices, std::size_t... I>
constexpr decltype(auto) slice_impl(
      std::index_sequence<Indices...>,
      std::index_sequence<I...>) {
  using Array = std::array<std::size_t, sizeof...(Indices)>;
  return std::index_sequence<std::get<I>(Array{{Indices...}})...>();
}

template <std::size_t Begin, std::size_t End, std::size_t... Indices>
constexpr decltype(auto) slice(std::index_sequence<Indices...> idx_seq) {
  return slice_impl(idx_seq, make_index_range<Begin, End>());
}

split_at

slice, , split_at. , std::index_sequence, std::index_sequence .

template <std::size_t At, std::size_t... Indices>
constexpr decltype(auto) split_at(index_sequence<Indices...> idx_seq) {
    return std::make_pair(slice<0, At>(idx_seq), 
                          slice<At, sizeof...(Indices)>(idx_seq));
}

split_at:

static_assert(std::is_same<
                decltype(split_at<2>(index_sequence<1, 4, 2>())),
                std::pair<index_sequence<1, 4>, index_sequence<2>>>(), "");

static_assert(std::is_same<
                decltype(split_at<1>(index_sequence<1, 4, 2, 3>())),
                std::pair<index_sequence<1>, index_sequence<4, 2, 3>>>(), "");
+6

, - :

template<int ... I> struct get_suffix_helper {
    template<int ... J> static index_sequence<J...> foo(index_sequence<I..., J...>);
};

template<typename T1, typename T2> struct get_suffix;

template<int ... Is1, int ... Is2>
struct get_suffix<index_sequence<Is1...>, index_sequence<Is2...>> :
    public decltype(get_suffix_helper<Is1...>::foo(std::declval<index_sequence<Is2...>>())) {};

static_assert(std::is_base_of<index_sequence<>,
                              get_suffix<index_sequence<1, 2>,
                                         index_sequence<1, 2>>>::value, "error");

static_assert(std::is_base_of<index_sequence<42>,
                              get_suffix<index_sequence<1, 2>,
                                         index_sequence<1, 2, 42>>>::value, "error");

, :

template <typename T1, typename T2> struct get_suffix;

template<int ...Is>
struct get_suffix<index_sequence<>, index_sequence<Is...>>
{
    typedef index_sequence<Is...> type;
    static const bool valid = true;
};

template<int ...Is>
struct get_suffix<index_sequence<Is...>, index_sequence<>>
{
    typedef void type;
    static const bool valid = false;
};

template<>
struct get_suffix<index_sequence<>, index_sequence<>>
{
    typedef index_sequence<> type;
    static const bool valid = true;
};

template<int N, int ...Is, int... Js>
struct get_suffix<index_sequence<N, Is...>, index_sequence<N, Js...>>
{
    typedef typename get_suffix<index_sequence<Is...>, index_sequence<Js...>>::type type;
    static const bool valid = get_suffix<index_sequence<Is...>, index_sequence<Js...>>::valid;
};

template<int N1, int N2, int ...Is, int... Js>
struct get_suffix<index_sequence<N1, Is...>, index_sequence<N2, Js...>>
{
    typedef void type;
    static const bool valid = false;
};

static_assert(std::is_same<index_sequence<>,
                           get_suffix<index_sequence<1, 2>,
                                      index_sequence<1, 2>>::type>::value, "error");

static_assert(!get_suffix<index_sequence<1, 2, 42>, index_sequence<1, 2>>::valid, "error");
static_assert(!get_suffix<index_sequence<0, 2, 1>, index_sequence<0, 1, 2>>::valid, "error");

static_assert(std::is_same<index_sequence<42>,
                           get_suffix<index_sequence<1, 2>,
                                      index_sequence<1, 2, 42>>::type>::value, "error");
+2
source

Not an answer, but a workaround: recursively crop leading a la elements:

template <typename, typename> struct remove_prefix;

template <std::size_t... I>
struct remove_prefix<index_sequence<>, index_sequence<I...>> {
  using type = index_sequence<I...>;
};

template <std::size_t First, std::size_t... I, std::size_t... J>
struct remove_prefix<index_sequence<First, I...>,
                     index_sequence<First, J...>> {
  using type = typename remove_prefix<index_sequence<I...>,
                                      index_sequence<J...>>::type;
};

Demo at Coliru .

0
source

All Articles