Add more features to etl::type_list (#1307)

* Remove AppVeyor build status badge

Removed AppVeyor build status badge from README.

* Update README.md

* Update CONTRIBUTING.md

Updated the instructions for contributing.

* Added etl::type_list to etl::observer

* Added etl::type_list to etl::nth_type

* Added missing 'typename' to type_list nth_type

* Fix for issue 1276 "Data corruption in the etl::bip_buffer_spsc_atomic" (#1277)

* Reproduce data corruption bug in the `etl::bip_buffer_spsc_atomic`.

* Fix data corruption bug in the `etl::bip_buffer_spsc_atomic`.

* Added type_list definitions for nth_type and observer

* Added etl::type_list to etl::variant

* Updated comments

* Addedetl::type~_list to message_router, observer, visitor

# Conflicts:
#	include/etl/observer.h
#	test/vs2022/etl.vcxproj.filters

* Added member type_list type to tuple

* Work in progress

* Copy changes from other source

* Removed unused tests

* Fix iter_swap namespace

* Add type_list functionality to etl::variant using etl::variant_from_type_list

* Add type_list functionality to etl::message_packet using etl::message_packet_from_type_list

* Add type_list functionality to etl::message_router using etl::message_router_from_type_list

* Add type_list functionality to etl::observer using etl::observer_from_type_list

* Add type_list functionality to etl::tuple using etl::tuple_from_type_list

* Allow etl::make_index_sequence to be created from an etl::type_list

* Add type_list functionality to etl::visitor using etl::visitor_from_type_list

* Fix iter_swap namespace

* Allow creation of a message_packet with no message types

* Allow creation of a message_router with no message types

* Updated VS2022 project files

* Added missing test files CMakeLists.txt

* Fix C++03 compatibility

Fixed unused aregument warnings

* Synced message_packet generator to updated code

* Synced message_router generator to updated code

* Synced message_router generator to updated code

# Conflicts:
#	include/etl/generators/message_router_generator.h
#	include/etl/message_router.h

* Fixed missing zero message specialisation for <= C++14

* Fixed missing zero message specialisation for <= C++14

* Fix year_month arithmetic and correct chrono API behavior (#1257)

* Fix & add more tests for year_month arithmetic

* Minor addtions to previous commit

* More missing values to be uninitialized

* Update the default constructors to = default and correct default constructor tests accordingly

* Fix & add more tests for year_month arithmetic

* Minor addtions to previous commit

* More missing values to be uninitialized

* Update the default constructors to = default and correct default constructor tests accordingly

* Restore default constructor behavior for chrono calender

* Suppress warnings from std in optimized builds (#1259)

When testing with ./run-tests.sh 23 3 10, some warnings from
std surfaced which resulted in build errors.

* Add template deduction guide for span from vector (#1264)

* Create span from vector deduction

* Use ivector for deduction.  Add vector_ext to test

* Add vector pointer to test

* Finish tests

* Initialize pdata_ext and others

* Document how to implement platform specifics (#1262)

Some interfaces need to be implemented in every project
or platform using the ETL:

* etl_get_high_resolution_clock
* etl_get_system_clock
* etl_get_steady_clock
* etl_putchar

Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>

* Fix etl::as_bytes for etl::span<const T> (#1266)

A missing 'const' in the etl::as_bytes implementation was causing a
compile-time error when etl::as_bytes was called on a span of const
values.

Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>

* Remove some UB in test_vector_non_trivial.cpp (#1268)

Some of the tests' UB are detectable by Gcc15 and thus give a compile error due to warnings-as-error flag.

Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>

* Update C++26 deprecated constructs to ensure future standard compliance (#1267)

* Update C++26 deprecated constructs to ensure future standard compliance

I replaced std::is_trivial with a combination of std::is_trivially_default_constructible and std::is_trivially_copyable. Additionally, I added the required comma before the ellipsis in variadic functions to match updated language specifications.

* Some additional is_trivial related changes not found directly when compiling tests in C++26

---------

Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>

* Fix return value of get_token_list (#1271)

Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>

* Fix etl::tuple template signature error in pair assignment operator (#1265)

* Fix etl::tuple template signature error in pair assignment operator

* Remove AppVeyor build status badge

Removed AppVeyor build status badge from README.

* Update README.md

* Update etl::tuple to explicitly use etl::pair or std::pair in assignment operator

* Added tests for etl::tuple assignment from pair

---------

Co-authored-by: Bryton Flecker <bflecker@swe.com>
Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>

* Remove advance() on static spans (#1281)

* Remove AppVeyor build status badge

Removed AppVeyor build status badge from README.

* Update README.md

* Update CONTRIBUTING.md

Updated the instructions for contributing.

* Fix for issue 1276 "Data corruption in the etl::bip_buffer_spsc_atomic" (#1277)

* Reproduce data corruption bug in the `etl::bip_buffer_spsc_atomic`.

* Fix data corruption bug in the `etl::bip_buffer_spsc_atomic`.

* Remove advance() on static spans

Since the size of a static span is constant, we can't reasonably
advance() on it.

---------

Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>
Co-authored-by: Sergei <sergej.shirokov@gmail.com>

* Add missing includes (#1286)

* Remove AppVeyor build status badge

Removed AppVeyor build status badge from README.

* Update README.md

* Update CONTRIBUTING.md

Updated the instructions for contributing.

* Fix for issue 1276 "Data corruption in the etl::bip_buffer_spsc_atomic" (#1277)

* Reproduce data corruption bug in the `etl::bip_buffer_spsc_atomic`.

* Fix data corruption bug in the `etl::bip_buffer_spsc_atomic`.

* Add missing includes

Before this change, the includes needed to be done explicitly by
files using basic_string_stream.h, and be included first. This
was error prone, especially if includes are reordered (e.g. via
the currently defined clang-format rules).

---------

Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>
Co-authored-by: Sergei <sergej.shirokov@gmail.com>

* Move comparison operators of etl::expected to namespace etl (#1287)

* Remove AppVeyor build status badge

Removed AppVeyor build status badge from README.

* Update README.md

* Update CONTRIBUTING.md

Updated the instructions for contributing.

* Fix for issue 1276 "Data corruption in the etl::bip_buffer_spsc_atomic" (#1277)

* Reproduce data corruption bug in the `etl::bip_buffer_spsc_atomic`.

* Fix data corruption bug in the `etl::bip_buffer_spsc_atomic`.

* Move comparison operators of etl::expected to namespace etl

---------

Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>
Co-authored-by: Sergei <sergej.shirokov@gmail.com>

* Make typed_storage constructor constexpr (#1291)

* Remove AppVeyor build status badge

Removed AppVeyor build status badge from README.

* Update README.md

* Update CONTRIBUTING.md

Updated the instructions for contributing.

* Fix for issue 1276 "Data corruption in the etl::bip_buffer_spsc_atomic" (#1277)

* Reproduce data corruption bug in the `etl::bip_buffer_spsc_atomic`.

* Fix data corruption bug in the `etl::bip_buffer_spsc_atomic`.

* Make typed_storage constructor constexpr

---------

Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>
Co-authored-by: Sergei <sergej.shirokov@gmail.com>

* Add basic_format_arg constructor for ibasic_string (#1288)

* Allow string as format arg

* Remove AppVeyor build status badge

Removed AppVeyor build status badge from README.

* Update README.md

* Update CONTRIBUTING.md

Updated the instructions for contributing.

* Fix for issue 1276 "Data corruption in the etl::bip_buffer_spsc_atomic" (#1277)

* Reproduce data corruption bug in the `etl::bip_buffer_spsc_atomic`.

* Fix data corruption bug in the `etl::bip_buffer_spsc_atomic`.

* Added test string escaped

* Add temporary string test

---------

Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>
Co-authored-by: Sergei <sergej.shirokov@gmail.com>

* QR Code for Github

* Added etl::visitor_from_type_list

* accepts(id) for empty router passes on to a sucessor

* Fixed incorrect comment from 'tuple' to 'message_router'

* PR review changes

* PR review changes

* Fixed internal constexptr flag in message_packet

* Fixed unused variable in unti test

* Added new type_list features

Added make_index_sequence_with_offset

* Renamed type_list_select_from_sequence to type_list_select_from_index_sequence

* Replaced type_list_size<TTypeList>::value with TTypeList::size internally for better clarity.

* Added etl::type_list_remove, etl::type_list_remove_if, etl::type_list_unique, etl::type_list_pop_front, etl::type_list_pop_back

* Add ref-qualifiers to basic_format_spec (#1292)

* Remove AppVeyor build status badge

Removed AppVeyor build status badge from README.

* Update README.md

* Update CONTRIBUTING.md

Updated the instructions for contributing.

* Fix for issue 1276 "Data corruption in the etl::bip_buffer_spsc_atomic" (#1277)

* Reproduce data corruption bug in the `etl::bip_buffer_spsc_atomic`.

* Fix data corruption bug in the `etl::bip_buffer_spsc_atomic`.

* feat: use ref-qualifiers for basic_format_spec

Converted the l-value methods to ref-qualified and also added r-value ref-qualified methods.

---------

Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>
Co-authored-by: Sergei <sergej.shirokov@gmail.com>

* Add support for size_t and unsigned long to etl::format (#1290)

* Remove AppVeyor build status badge

Removed AppVeyor build status badge from README.

* Update README.md

* Update CONTRIBUTING.md

Updated the instructions for contributing.

* Fix for issue 1276 "Data corruption in the etl::bip_buffer_spsc_atomic" (#1277)

* Reproduce data corruption bug in the `etl::bip_buffer_spsc_atomic`.

* Fix data corruption bug in the `etl::bip_buffer_spsc_atomic`.

* Add support for size_t and unsigned long to etl::format

* Document list of supported types in etl::supported_format_types

* Add further types and tests for etl::format

---------

Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>
Co-authored-by: Sergei <sergej.shirokov@gmail.com>

* Deduce underlying storage size when constructing string_ext from char[]. (#1269)

* Deduce underlying storage size when constructing string_ext from char[].

This removes the need for passing sizeof(storage) to the constructor.

* Add array constructors for the other string types.

- u16string_ext
- u32string_ext
- u8string_ext
- wstring_ext

* Add additional constructors to match existing API.

* Fix inconsistent test argument order.

---------

Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>

* Added etl::type_list_all_of, etl::type_list_any_of, and etl::type_list_none_of

* Added etl::type_list_is_unique

* Added type_list_is_empty

* indentation fix

* Fix merge error

* Renamed type_list_prepend & type_list_append to type_list_push_front & type_list_push_back respectively

* Added tests for make_index_sequence & make_index_sequence_with_offset

* Resolve coderabbit review issues

* Resolve coderabbit review issues

* Resolve coderabbit review issues

* Resolve coderabbit review issues

* Added  etl::type_list_indices_of_type which create an etl::index_sequence of all of the indexes of a specified type in an etl::type_list

* Updated comments

* Resolve coderabbit review issues

Added index_sequence utility to support type_list utilities. Added additional index_sequence utilities for completeness

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

* Fix 'unused variable' error in index_sequence tests

---------

Co-authored-by: John Wellbelove <john.wellbelove@etlcpp.co.uk>
Co-authored-by: Sergei <sergej.shirokov@gmail.com>
Co-authored-by: John Wellbelove <john.wellbelove@etlcpp.com>
Co-authored-by: Bo Rydberg <2945606+bolry@users.noreply.github.com>
Co-authored-by: Roland Reichwein <Roland.Reichwein@bmw.de>
Co-authored-by: Mike Bloom <91038685+mike919192@users.noreply.github.com>
Co-authored-by: taltenbach <92919739+taltenbach@users.noreply.github.com>
Co-authored-by: Bryton Flecker <fleckerbr@gmail.com>
Co-authored-by: Bryton Flecker <bflecker@swe.com>
Co-authored-by: Drew Rife <drew.rife95@gmail.com>
Co-authored-by: Marco Nilsson <marco@zyax.se>
This commit is contained in:
John Wellbelove 2026-02-21 09:36:48 +00:00 committed by GitHub
parent 58b5bf5190
commit 7a8944224b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 469 additions and 72 deletions

View File

@ -177,8 +177,10 @@ namespace etl
using type_list_type_at_index_t = typename type_list_type_at_index<TTypeList, Index>::type;
//***************************************************************************
/// Defines an integral constant that is the index of the specified type in the type_list.
/// Defines an integral constant that is the index of the <i>first</i> instance of specified type in the type_list.
/// If the type is not in the type_list, then defined as etl::type_list_npos.
/// Useful for type lists that do not contain duplicates, otherwise use type_list_indices_of_type.
/// Static asserts if TTypeList is not an etl::type_list.
//***************************************************************************
template <typename TTypeList, typename T>
struct type_list_index_of_type
@ -200,6 +202,56 @@ namespace etl
inline constexpr size_t type_list_index_of_v = etl::type_list_index_of_type<TTypeList, T>::value;
#endif
//***************************************************************************
/// Defines an index_sequence of indices where T appears in the type_list.
/// If the type is not in the type_list, then defined as an empty index_sequence.
/// Useful for type lists that contain duplicates, otherwise use type_list_index_of_type.
/// Static asserts if TTypeList is not an etl::type_list.
//***************************************************************************
namespace private_type_list
{
template <typename TTypeList, typename T, size_t Index, typename TResult>
struct type_list_indices_of_type_impl;
// The general case, check the head type, then recurse with the rest of the types.
template <typename Head, typename... Tail, typename T, size_t Index, typename TResult>
struct type_list_indices_of_type_impl<etl::type_list<Head, Tail...>, T, Index, TResult>
{
private:
// If Head is the same as T then append a new index to the result, otherwise no change.
using next_result = etl::conditional_t<etl::is_same<Head, T>::value,
etl::index_sequence_push_back_t<TResult, Index>,
TResult>;
public:
// Recurse with the rest of the type_list, passing on the current result.
using type = typename type_list_indices_of_type_impl<etl::type_list<Tail...>, T, Index + 1U, next_result>::type;
};
// Specialisation for an empty type_list.
// This is the terminating specialisation for the general case.
template <typename T, size_t Index, typename TResult>
struct type_list_indices_of_type_impl<etl::type_list<>, T, Index, TResult>
{
using type = TResult;
};
}
template <typename TTypeList, typename T>
struct type_list_indices_of_type
{
ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
using type = typename private_type_list::type_list_indices_of_type_impl<TTypeList, T, 0U, etl::index_sequence<>>::type;
};
#if ETL_USING_CPP11
template <typename TTypeList, typename T>
using type_list_indices_of_type_t = typename type_list_indices_of_type<TTypeList, T>::type;
#endif
//***************************************************************************
/// Defines a bool constant that is true if the type_list contains the specified type, otherwise false.
//***************************************************************************
@ -318,7 +370,7 @@ namespace etl
#endif
//***************************************************************************
/// Declares a new type_list by selecting types from a given type_list, according to an index sequence.
/// Declares a new type_list by selecting types from a given type_list, according to a list if indices.
//***************************************************************************
template <typename TTypeList, size_t... Indices>
struct type_list_select
@ -379,14 +431,8 @@ namespace etl
using type = type_list<T, TTypes...>;
};
template <typename T>
struct type_list_push_front<T>
{
using type = etl::type_list<T>;
};
template <typename TypeList, typename T>
using type_list_prepend_t = typename type_list_push_front<TypeList, T>::type;
using type_list_push_front_t = typename type_list_push_front<TypeList, T>::type;
//***************************************************************************
/// Add a type to the end of a type_list.
@ -400,14 +446,8 @@ namespace etl
using type = type_list<TTypes..., T>;
};
template <typename T>
struct type_list_push_back<T>
{
using type = etl::type_list<T>;
};
template <typename TypeList, typename T>
using type_list_append_t = typename type_list_push_back<TypeList, T>::type;
using type_list_push_back_t = typename type_list_push_back<TypeList, T>::type;
//***************************************************************************
/// Insert a type at an index in a type_list.
@ -420,7 +460,7 @@ namespace etl
private:
ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
ETL_STATIC_ASSERT(Index <= TTypeList::size, "Index out of range");
ETL_STATIC_ASSERT(Index <= TTypeList::size, "Index out of range");
using index_sequence_for_prefix = etl::make_index_sequence<Index>;
using index_sequence_for_suffix = etl::make_index_sequence_with_offset<Index, TTypeList::size - Index>;
@ -492,7 +532,7 @@ namespace etl
using type = typename etl::conditional<TPredicate<Head>::value,
rest,
etl::type_list_prepend_t<rest, Head>>::type;
etl::type_list_push_front_t<rest, Head>>::type;
};
}
@ -582,7 +622,7 @@ namespace etl
using next_result = etl::conditional_t<etl::type_list_contains<TResult, Head>::value,
TResult,
etl::type_list_append_t<TResult, Head>>;
etl::type_list_push_back_t<TResult, Head>>;
public:
@ -661,7 +701,7 @@ namespace etl
template <template <typename> class TPredicate>
struct type_list_all_of<etl::type_list<>, TPredicate>
: etl::bool_constant<false>
: etl::bool_constant<true>
{
};
@ -771,7 +811,7 @@ namespace etl
//*********************************
// Ensure that the list is sorted.
// Recursively the head to the next to ensure that the list is sorted.
// Recursively compare the head to the next element to ensure that the list is sorted.
template <typename Head, typename Next, typename... Tail, template <typename, typename> class TCompare>
struct type_list_is_sorted_impl<etl::type_list<Head, Next, Tail...>, TCompare>
: etl::bool_constant<!TCompare<Next, Head>::value &&
@ -841,7 +881,7 @@ namespace etl
template <typename Head, typename T, template <typename, typename> class TCompare, typename... Tail>
struct insert_sorted_impl<false, Head, T, TCompare, Tail...>
{
using type = etl::type_list_prepend_t<typename type_list_insert_sorted_impl<etl::type_list<Tail...>, T, TCompare>::type, Head>;
using type = etl::type_list_push_front_t<typename type_list_insert_sorted_impl<etl::type_list<Tail...>, T, TCompare>::type, Head>;
};
}

View File

@ -532,13 +532,13 @@ namespace etl
class integer_sequence
{
public:
ETL_STATIC_ASSERT(etl::is_integral<T>::value, "Integral types only");
typedef T value_type;
static ETL_CONSTEXPR size_t size() ETL_NOEXCEPT
{
static ETL_CONSTEXPR size_t size() ETL_NOEXCEPT
{
return sizeof...(Integers);
}
};
@ -577,7 +577,7 @@ namespace etl
using make_index_sequence = typename private_integer_sequence::make_index_sequence<Count, etl::integer_sequence<size_t>>::type;
//***********************************
/// Make an integer sequence with an offset.
/// Make an integer sequence with an offset.
//***********************************
template <size_t Offset, size_t Count>
using make_index_sequence_with_offset = typename private_integer_sequence::offset_index_sequence<Offset, etl::make_index_sequence<Count>>::type;
@ -604,16 +604,164 @@ namespace etl
};
}
// Accepts either a parameter pack of types or a single etl::type_list<T...>
//***********************************
/// Make an index sequence for a parameter pack of types or an etl::type_list<T...>.
/// Accepts either a parameter pack of types or a single etl::type_list<T...>
//***********************************
template <typename... TTypes>
using make_index_sequence_for = typename private_make_index_sequence_for::impl<TTypes...>::type;
//***********************************
/// An index sequence.
//***********************************
template <size_t... Indices>
using index_sequence = etl::integer_sequence<size_t, Indices...>;
//************************************
/// Alias for make_index_sequence_for.
//************************************
template <typename... TTypes>
using index_sequence_for = typename etl::make_index_sequence_for<TTypes...>;
//************************************
/// Concatenates two index_sequences.
//************************************
template <typename TIndexSequence1, typename TIndexSequence2>
struct index_sequence_cat;
template <size_t... Indices1, size_t... Indices2>
struct index_sequence_cat<etl::index_sequence<Indices1...>, etl::index_sequence<Indices2...>>
{
using type = etl::index_sequence<Indices1..., Indices2...>;
};
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
//***************************************************************************
@ -651,9 +799,9 @@ namespace etl
//***************************************************************************
/// in_place disambiguation tags.
//***************************************************************************
//*************************
struct in_place_t
struct in_place_t
{
explicit ETL_CONSTEXPR in_place_t() {}
};
@ -661,9 +809,9 @@ namespace etl
#if ETL_USING_CPP17
inline constexpr in_place_t in_place{};
#endif
//*************************
template <typename T> struct in_place_type_t
template <typename T> struct in_place_type_t
{
explicit ETL_CONSTEXPR in_place_type_t() {}
};
@ -674,7 +822,7 @@ namespace etl
#endif
//*************************
template <size_t Index> struct in_place_index_t
template <size_t Index> struct in_place_index_t
{
explicit ETL_CONSTEXPR in_place_index_t() {}
};
@ -767,7 +915,7 @@ namespace etl
// Creates a static member 'call' that calls the specified functor.
//*****************************************************************************
template <auto& Instance>
struct functor_as_static
struct functor_as_static
{
template <typename... TArgs>
static constexpr auto call(TArgs&&... args)
@ -781,7 +929,7 @@ namespace etl
// Creates a static member 'call' that calls the specified member function.
//*****************************************************************************
template <auto Method, auto& Instance>
struct member_function_as_static
struct member_function_as_static
{
template <typename... TArgs>
static constexpr auto call(TArgs&&... args)

View File

@ -58,7 +58,7 @@ namespace
// Convenience comparator for types that expose a constexpr integral ID (ascending)
template <typename T1, typename T2>
struct by_ascencding_id : etl::bool_constant<(T1::id < T2::id)>
struct by_ascending_id : etl::bool_constant<(T1::id < T2::id)>
{
};
@ -223,6 +223,22 @@ namespace
#endif
}
//*************************************************************************
TEST(test_type_list_indices_of_type)
{
using t1 = etl::type_list<char, int, char, uint32_t, char, char>;
using t2 = etl::type_list<>;
using indices1 = etl::type_list_indices_of_type_t<t1, char>;
using expected1 = etl::index_sequence<0U, 2U, 4U, 5U>;
using indices2 = etl::type_list_indices_of_type_t<t2, char>;
using expected2 = etl::index_sequence<>;
CHECK_TRUE((etl::is_same<indices1, expected1>::value));
CHECK_TRUE((etl::is_same<indices2, expected2>::value));
}
//*************************************************************************
TEST(test_type_list_type_at_index)
{
@ -311,7 +327,7 @@ namespace
TEST(test_type_list_sort_empty_list)
{
using list = etl::type_list<>;
using result = etl::type_list_sort_t<list, by_ascencding_id>;
using result = etl::type_list_sort_t<list, by_ascending_id>;
using expected = etl::type_list<>;
CHECK((etl::is_same<result, expected>::value));
@ -322,7 +338,7 @@ namespace
TEST(test_type_list_sort_single_list)
{
using list = etl::type_list<A>;
using result = etl::type_list_sort_t<list, by_ascencding_id>;
using result = etl::type_list_sort_t<list, by_ascending_id>;
using expected = etl::type_list<A>;
CHECK((etl::is_same<result, expected>::value));
@ -333,7 +349,7 @@ namespace
TEST(test_type_list_sort_multiple_list)
{
using list = etl::type_list<B, C, A>;
using result = etl::type_list_sort_t<list, by_ascencding_id>;
using result = etl::type_list_sort_t<list, by_ascending_id>;
using expected = etl::type_list<A, B, C>;
CHECK((etl::is_same<result, expected>::value));
@ -341,32 +357,86 @@ namespace
}
//*************************************************************************
TEST(test_type_list_prepend_to_empty_list)
{
using list = etl::type_list<>;
using result = etl::type_list_prepend_t<list, A>;
using expected = etl::type_list<A>;
CHECK((etl::is_same<result, expected>::value));
CHECK_EQUAL(1U, etl::type_list_size<result>::value);
}
//*************************************************************************
TEST(test_type_list_prepend_to_non_empty_list)
{
using list = etl::type_list<B, C>;
using result = etl::type_list_prepend_t<list, A>;
using expected = etl::type_list<A, B, C>;
CHECK((etl::is_same<result, expected>::value));
CHECK_EQUAL(3U, etl::type_list_size<result>::value);
}
//*************************************************************************
TEST(test_type_list_append_to_empty_list)
TEST(test_type_list_is_sorted_for_empty_list)
{
using list = etl::type_list<>;
using result = etl::type_list_append_t<list, A>;
CHECK((etl::type_list_is_sorted<list, by_ascending_id>::value));
}
//*************************************************************************
TEST(test_type_list_is_sorted_for_single_list)
{
using list = etl::type_list<A>;
CHECK((etl::type_list_is_sorted<list, by_ascending_id>::value));
}
//*************************************************************************
TEST(test_type_list_is_sorted_for_sorted_list)
{
using list = etl::type_list<A, B, C>;
CHECK((etl::type_list_is_sorted<list, by_ascending_id>::value));
}
//*************************************************************************
TEST(test_type_list_is_sorted_for_unsorted_list)
{
using list = etl::type_list<B, C, A>;
CHECK((!etl::type_list_is_sorted<list, by_ascending_id>::value));
}
//*************************************************************************
TEST(test_type_list_insert_sorted_into_empty_list)
{
using list = etl::type_list<>;
using result = etl::type_list_insert_sorted_t<list, B, by_ascending_id>;
using expected = etl::type_list<B>;
CHECK((etl::is_same<result, expected>::value));
CHECK_EQUAL(1U, etl::type_list_size<result>::value);
}
//*************************************************************************
TEST(test_type_list_insert_sorted_before_head)
{
using list = etl::type_list<B, C>;
using result = etl::type_list_insert_sorted_t<list, A, by_ascending_id>;
using expected = etl::type_list<A, B, C>;
CHECK((etl::is_same<result, expected>::value));
CHECK_EQUAL(3U, etl::type_list_size<result>::value);
}
//*************************************************************************
TEST(test_type_list_insert_sorted_in_middle)
{
using list = etl::type_list<A, C>;
using result = etl::type_list_insert_sorted_t<list, B, by_ascending_id>;
using expected = etl::type_list<A, B, C>;
CHECK((etl::is_same<result, expected>::value));
CHECK_EQUAL(3U, etl::type_list_size<result>::value);
}
//*************************************************************************
TEST(test_type_list_insert_sorted_at_end)
{
using list = etl::type_list<A, B>;
using result = etl::type_list_insert_sorted_t<list, C, by_ascending_id>;
using expected = etl::type_list<A, B, C>;
CHECK((etl::is_same<result, expected>::value));
CHECK_EQUAL(3U, etl::type_list_size<result>::value);
}
//*************************************************************************
TEST(test_type_list_push_front_to_empty_list)
{
using list = etl::type_list<>;
using result = etl::type_list_push_front_t<list, A>;
using expected = etl::type_list<A>;
CHECK((etl::is_same<result, expected>::value));
@ -374,10 +444,32 @@ namespace
}
//*************************************************************************
TEST(test_type_list_append_to_non_empty_list)
TEST(test_type_list_push_front_to_non_empty_list)
{
using list = etl::type_list<B, C>;
using result = etl::type_list_push_front_t<list, A>;
using expected = etl::type_list<A, B, C>;
CHECK((etl::is_same<result, expected>::value));
CHECK_EQUAL(3U, etl::type_list_size<result>::value);
}
//*************************************************************************
TEST(test_type_list_push_back_to_empty_list)
{
using list = etl::type_list<>;
using result = etl::type_list_push_back_t<list, A>;
using expected = etl::type_list<A>;
CHECK((etl::is_same<result, expected>::value));
CHECK_EQUAL(1U, etl::type_list_size<result>::value);
}
//*************************************************************************
TEST(test_type_list_push_back_to_non_empty_list)
{
using list = etl::type_list<A, B>;
using result = etl::type_list_append_t<list, C>;
using result = etl::type_list_push_back_t<list, C>;
using expected = etl::type_list<A, B, C>;
CHECK((etl::is_same<result, expected>::value));
@ -532,7 +624,7 @@ namespace
// Uncomment to generate static_assert error.
//using list = etl::type_list<>;
//using result1 = etl::type_list_pop_front_t<list>;
//using result1 = etl::type_list_pop_back_t<list>;
}
//*************************************************************************
@ -583,14 +675,14 @@ namespace
{
using list1 = etl::type_list<>;
CHECK_FALSE((etl::type_list_all_of<list1, is_type_a>::value));
CHECK_FALSE((etl::type_list_all_of<list1, is_type_b>::value));
CHECK_FALSE((etl::type_list_all_of<list1, is_type_c>::value));
CHECK_TRUE((etl::type_list_all_of<list1, is_type_a>::value));
CHECK_TRUE((etl::type_list_all_of<list1, is_type_b>::value));
CHECK_TRUE((etl::type_list_all_of<list1, is_type_c>::value));
#if ETL_USING_CPP17
CHECK_FALSE((etl::type_list_all_of_v<list1, is_type_a>));
CHECK_FALSE((etl::type_list_all_of_v<list1, is_type_b>));
CHECK_FALSE((etl::type_list_all_of_v<list1, is_type_c>));
CHECK_TRUE((etl::type_list_all_of_v<list1, is_type_a>));
CHECK_TRUE((etl::type_list_all_of_v<list1, is_type_b>));
CHECK_TRUE((etl::type_list_all_of_v<list1, is_type_c>));
#endif
}
@ -713,6 +805,21 @@ namespace
#endif
}
//*************************************************************************
TEST(test_type_list_is_unique_for_non_empty_list)
{
using list1 = etl::type_list<A, B, C>;
using list2 = etl::type_list<A, B, A>;
CHECK_TRUE((etl::type_list_is_unique<list1>::value));
CHECK_FALSE((etl::type_list_is_unique<list2>::value));
#if ETL_USING_CPP17
CHECK_TRUE((etl::type_list_is_unique_v<list1>));
CHECK_FALSE((etl::type_list_is_unique_v<list2>));
#endif
}
//*************************************************************************
TEST(test_type_list_is_empty)
{

View File

@ -927,5 +927,107 @@ namespace
CHECK_TRUE((std::is_same<seq2, expect2>::value));
CHECK_TRUE((std::is_same<seq4, expect4>::value));
}
//*********************************
TEST(test_index_sequence_push_front_matches_expected)
{
using seq0 = etl::index_sequence<>;
using seq1 = etl::index_sequence<1U, 2U>;
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<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));
}
//*********************************
TEST(test_index_sequence_push_back_matches_expected)
{
using seq0 = etl::index_sequence<>;
using seq1 = etl::index_sequence<1U, 2U>;
using result0 = etl::index_sequence_push_back_t<seq0, 5U>;
using result1 = etl::index_sequence_push_back_t<seq1, 3U>;
using expect0 = etl::index_sequence<5U>;
using expect1 = etl::index_sequence<1U, 2U, 3U>;
CHECK_TRUE((std::is_same<result0, expect0>::value));
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)
{
using seq0 = etl::index_sequence<>;
using seq1 = etl::index_sequence<0U, 1U>;
using seq2 = etl::index_sequence<2U, 3U>;
using result0 = etl::index_sequence_cat_t<seq0, seq1>;
using result1 = etl::index_sequence_cat_t<seq1, seq2>;
using expect0 = etl::index_sequence<0U, 1U>;
using expect1 = etl::index_sequence<0U, 1U, 2U, 3U>;
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<>; // This should fail to compile as seq0 is empty
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
}
}
}