Here is a possible implementation.
First we'll start off with a simple trait to add a std::size_t onto the front of a std::index_sequence:
template <std::size_t First, typename Seq>
struct sequence_cat;
template <std::size_t First, std::size_t... Seq>
struct sequence_cat <First, std::index_sequence<Seq...>> {
using type = std::index_sequence<First, Seq...>;
};
//helper
template <std::size_t First, typename Seq>
using sequence_cat_t = typename sequence_cat<First, Seq>::type;
Now we'll define a trait called not_in_sequence which will recursively check the fronts of two std::index_sequences and filter off any from the first which occur in the second:
//empty first sequence
template <class First, class Second>
struct not_in_sequence {
using type = std::index_sequence<>;
};
//helper
template <class First, class Second>
using not_in_sequence_t = typename not_in_sequence<First, Second>::type;
//filter and recurse
template <std::size_t... First, std::size_t... Second,
std::size_t FirstHead, std::size_t SecondHead>
struct not_in_sequence <std::index_sequence<FirstHead, First...>,
std::index_sequence<SecondHead, Second...>> {
using seq1 = std::index_sequence<First...>;
using seq2 = std::index_sequence<Second...>;
using type =
std::conditional_t<
(FirstHead == SecondHead),
not_in_sequence_t<seq1, seq2>,
sequence_cat_t<
FirstHead,
not_in_sequence_t<seq1, sequence_cat_t<SecondHead, seq2>>
>
>;
};
//empty second sequence
template <std::size_t... First, std::size_t FirstHead>
struct not_in_sequence <std::index_sequence<FirstHead, First...>,
std::index_sequence<>> {
using type = std::index_sequence<FirstHead, First...>;
};
You can use not_in_sequence_t like so:
not_in_sequence_t<std::make_index_sequence<3>, std::index_sequence<0,2>>
//same as std::index_sequence<1>
There might be some edge-cases I've missed, but feel free to edit this as you like.
Live Demo