Added etl::index_sequence_cat, etl::index_sequence_pop_front, etl::index_sequence_pop_back, etl::index_sequence_at

This commit is contained in:
John Wellbelove 2026-02-21 09:02:14 +00:00
parent 5f5633796e
commit 8f02514390
2 changed files with 185 additions and 31 deletions

View File

@ -623,36 +623,6 @@ namespace etl
template <typename... TTypes>
using index_sequence_for = typename etl::make_index_sequence_for<TTypes...>;
//************************************
/// Pushes an index to the front of an index_sequence.
//************************************
template <typename TIndexSequence, size_t Index>
struct index_sequence_push_front;
template <size_t... Indices, size_t Index>
struct index_sequence_push_front<etl::index_sequence<Indices...>, Index>
{
using type = etl::index_sequence<Indices..., Index>;
};
template <typename TIndexSequence, size_t Index>
using index_sequence_push_front_t = typename index_sequence_push_front<TIndexSequence, Index>::type;
//************************************
/// Pushes an index to the back of an index_sequence.
//************************************
template <typename TIndexSequence, size_t Index>
struct index_sequence_push_back;
template <size_t... Indices, size_t Index>
struct index_sequence_push_back<etl::index_sequence<Indices...>, Index>
{
using type = etl::index_sequence<Indices..., Index>;
};
template <typename TIndexSequence, size_t Index>
using index_sequence_push_back_t = typename index_sequence_push_back<TIndexSequence, Index>::type;
//************************************
/// Concatenates two index_sequences.
//************************************
@ -667,6 +637,131 @@ namespace etl
template <typename TIndexSequence1, typename TIndexSequence2>
using index_sequence_cat_t = typename index_sequence_cat<TIndexSequence1, TIndexSequence2>::type;
//************************************
/// Pushes an index to the front of an index_sequence.
//************************************
template <typename TIndexSequence, size_t Index>
struct index_sequence_push_front;
template <size_t... Indices, size_t Index>
struct index_sequence_push_front<etl::index_sequence<Indices...>, Index>
{
// Adds the new index to the front of the sequence.
using type = etl::index_sequence<Index, Indices...>;
};
template <typename TIndexSequence, size_t Index>
using index_sequence_push_front_t = typename index_sequence_push_front<TIndexSequence, Index>::type;
//************************************
/// Pop an index from the front of an index_sequence.
//************************************
template <typename TIndexSequence>
struct index_sequence_pop_front;
template <>
struct index_sequence_pop_front<etl::index_sequence<>>
{
using type = etl::index_sequence<>;
};
template <size_t Index, size_t... Indices>
struct index_sequence_pop_front<etl::index_sequence<Index, Indices...>>
{
// Removes the front index by declaring the type to be the tail of the sequence.
using type = etl::index_sequence<Indices...>;
};
template <typename TIndexSequence>
using index_sequence_pop_front_t = typename index_sequence_pop_front<TIndexSequence>::type;
//************************************
/// Pushes an index to the back of an index_sequence.
//************************************
template <typename TIndexSequence, size_t Index>
struct index_sequence_push_back;
template <size_t... Indices, size_t Index>
struct index_sequence_push_back<etl::index_sequence<Indices...>, Index>
{
// Adds the new index to the back of the sequence by concatenating the new index with the sequence.
using type = etl::index_sequence<Indices..., Index>;
};
template <typename TIndexSequence, size_t Index>
using index_sequence_push_back_t = typename index_sequence_push_back<TIndexSequence, Index>::type;
//************************************
/// Pop an index from the back of an index_sequence.
//************************************
template <typename TIndexSequence>
struct index_sequence_pop_back;
// Pop back of and empty sequence is an empty sequence.
template <>
struct index_sequence_pop_back<etl::index_sequence<>>
{
using type = etl::index_sequence<>;
};
// Pop back of a single element sequence is an empty sequence.
// The single element is never added to the result, so is effectively removed.
// This is the terminating specialisation for the general case.
template <size_t Index>
struct index_sequence_pop_back<etl::index_sequence<Index>>
{
using type = etl::index_sequence<>;
};
// Multi element sequence. Pop back is the front element concatenated with the pop back of the tail.
template <size_t Index, size_t... Indices>
struct index_sequence_pop_back<etl::index_sequence<Index, Indices...>>
{
// Removes the last index by concatenating the front index with the pop back of the tail.
// The last index is never added to the result, so is effectively removed.
using type = etl::index_sequence_cat_t<etl::index_sequence<Index>,
typename index_sequence_pop_back<etl::index_sequence<Indices...>>::type>;
};
template <typename TIndexSequence>
using index_sequence_pop_back_t = typename index_sequence_pop_back<TIndexSequence>::type;
//************************************
/// Gets the index at the Nth position in an index_sequence.
//************************************
template <typename TIndexSequence, size_t Nth>
struct index_sequence_at;
template <size_t Nth>
struct index_sequence_at<etl::index_sequence<>, Nth>
{
template <size_t>
struct dependent_false : etl::false_type {};
static_assert(dependent_false<Nth>::value, "Nth out of range for index_sequence_at");
};
// When Nth is 0, the index at the Nth position is the front index of the sequence.
template <size_t Index, size_t... Indices>
struct index_sequence_at<etl::index_sequence<Index, Indices...>, 0>
{
static constexpr size_t value = Index;
};
// When Nth is greater than 0, recurse with the tail of the sequence and Nth - 1.
template <size_t Index, size_t... Indices, size_t Nth>
struct index_sequence_at<etl::index_sequence<Index, Indices...>, Nth>
{
static_assert(Nth < sizeof...(Indices) + 1U, "Nth out of range for index_sequence_at");
static constexpr size_t value = index_sequence_at<etl::index_sequence<Indices...>, Nth - 1U>::value;
};
#if ETL_USING_CPP17
template <typename TIndexSequence, size_t Nth>
inline constexpr size_t index_sequence_at_v = index_sequence_at<TIndexSequence, Nth>::value;
#endif
#endif
//***************************************************************************

View File

@ -936,7 +936,21 @@ namespace
using result0 = etl::index_sequence_push_front_t<seq0, 5U>;
using result1 = etl::index_sequence_push_front_t<seq1, 0U>;
using expect0 = etl::index_sequence<5U>;
using expect1 = etl::index_sequence<1U, 2U, 0U>;
using expect1 = etl::index_sequence<0U, 1U, 2U>;
CHECK_TRUE((std::is_same<result0, expect0>::value));
CHECK_TRUE((std::is_same<result1, expect1>::value));
}
//*********************************
TEST(test_index_sequence_pop_front_matches_expected)
{
using seq0 = etl::index_sequence<>;
using seq1 = etl::index_sequence<1U, 2U>;
using result0 = etl::index_sequence_pop_front_t<seq0>;
using result1 = etl::index_sequence_pop_front_t<seq1>;
using expect0 = etl::index_sequence<>;
using expect1 = etl::index_sequence<2U>;
CHECK_TRUE((std::is_same<result0, expect0>::value));
CHECK_TRUE((std::is_same<result1, expect1>::value));
@ -956,6 +970,20 @@ namespace
CHECK_TRUE((std::is_same<result1, expect1>::value));
}
//*********************************
TEST(test_index_sequence_pop_back_matches_expected)
{
using seq0 = etl::index_sequence<>;
using seq1 = etl::index_sequence<1U, 2U>;
using result0 = etl::index_sequence_pop_back_t<seq0>;
using result1 = etl::index_sequence_pop_back_t<seq1>;
using expect0 = etl::index_sequence<>;
using expect1 = etl::index_sequence<1U>;
CHECK_TRUE((std::is_same<result0, expect0>::value));
CHECK_TRUE((std::is_same<result1, expect1>::value));
}
//*********************************
TEST(test_index_sequence_cat_matches_expected)
{
@ -970,5 +998,36 @@ namespace
CHECK_TRUE((std::is_same<result0, expect0>::value));
CHECK_TRUE((std::is_same<result1, expect1>::value));
}
//*********************************
TEST(test_index_sequence_at_matches_expected)
{
using seq0 = etl::index_sequence<>;
using seq1 = etl::index_sequence<1U, 2U, 3U>;
//using result0 = etl::index_sequence_at<seq0, 0>; // This should fail to compile as seq0 is empty
//auto ignore0 = result0; // Uses result0
size_t result1a = etl::index_sequence_at<seq1, 0>::value;
size_t result1b = etl::index_sequence_at<seq1, 1>::value;
size_t result1c = etl::index_sequence_at<seq1, 2>::value;
//size_t result1d = etl::index_sequence_at<seq1, 3>::value; // This should fail to compile as seq1 only has 3 elements
//auto ignore1d = result1d; // Uses result1d
size_t expect1a = 1U;
size_t expect1b = 2U;
size_t expect1c = 3U;
CHECK_EQUAL(expect1a, result1a);
CHECK_EQUAL(expect1b, result1b);
CHECK_EQUAL(expect1c, result1c);
#if ETL_USING_CPP17
size_t result1e = etl::index_sequence_at_v<seq1, 0>;
size_t result1f = etl::index_sequence_at_v<seq1, 1>;
size_t result1g = etl::index_sequence_at_v<seq1, 2>;
CHECK_EQUAL(expect1a, result1e);
CHECK_EQUAL(expect1b, result1f);
CHECK_EQUAL(expect1c, result1g);
#endif
}
}
}