mirror of
https://github.com/ETLCPP/etl.git
synced 2026-04-30 19:09:10 +08:00
Added etl::index_sequence_cat, etl::index_sequence_pop_front, etl::index_sequence_pop_back, etl::index_sequence_at
This commit is contained in:
parent
5f5633796e
commit
8f02514390
@ -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
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user