Support structured bindings for array

This commit is contained in:
Roland Reichwein 2026-07-09 20:41:10 +02:00
parent 875c9782d7
commit bdb1ce31fe
3 changed files with 162 additions and 0 deletions

View File

@ -314,3 +314,42 @@ operator >=
```
**Description**
`true` if the contents of the lhs are lexicographically greater than or equal to the contents of the rhs, otherwise `false`.
---
```cpp
template <size_t Index, typename T, size_t Size>
T& get(etl::array<T, Size>& a)
template <size_t Index, typename T, size_t Size>
const T& get(const etl::array<T, Size>& a)
```
**Description**
Gets a reference to the element at `Index` in the array.
## Structured bindings
`etl::array` provides the tuple-like interface required for C++17 structured bindings.
```cpp
etl::array<int, 3> a = { 1, 2, 3 };
auto& [x, y, z] = a; // x, y, z are references to a[0], a[1], a[2]
```
```cpp
template <typename T, size_t Size>
struct tuple_size<etl::array<T, Size>>
```
**Description**
Gets the number of elements in the array.
Specialised in namespaces `etl` and `std` (the `std` specialisation allows the use of C++ structured bindings).
---
```cpp
template <size_t Index, typename T, size_t Size>
struct tuple_element<Index, etl::array<T, Size>>
```
**Description**
Gets the type of the element at `Index` in the array.
Specialised in namespaces `etl` and `std` (the `std` specialisation allows the use of C++ structured bindings).

View File

@ -40,6 +40,9 @@ SOFTWARE.
#include "static_assert.h"
#include "type_traits.h"
#include "private/tuple_element.h"
#include "private/tuple_size.h"
#include <stddef.h>
///\defgroup array array
@ -1206,7 +1209,70 @@ namespace etl
ETL_STATIC_ASSERT(Index < Size, "Index out of bounds");
return static_cast<const T&&>(a[Index]);
}
//*************************************************************************
/// Gets the number of elements in an array.
///\tparam T The type.
///\tparam Size The array size.
//*************************************************************************
template <typename T, size_t Size>
struct tuple_size<etl::array<T, Size> > : etl::integral_constant<size_t, Size>
{
};
//*************************************************************************
/// Gets the type of the element at Index in an array.
///\tparam Index The index.
///\tparam T The type.
///\tparam Size The array size.
//*************************************************************************
template <size_t Index, typename T, size_t Size>
struct tuple_element<Index, etl::array<T, Size> >
{
ETL_STATIC_ASSERT(Index < Size, "Index out of bounds");
using type = T;
};
#endif
} // namespace etl
#if ETL_USING_CPP11
namespace std
{
// libc++ already declares std::tuple_size / std::tuple_element in its inline
// namespace (std::__1), so re-declaring them here would make the name
// ambiguous. Detect libc++ via _LIBCPP_VERSION and skip the forward
// declarations in that case, even when not using the STL.
#if ETL_NOT_USING_STL && !defined(_LIBCPP_VERSION) \
&& !((defined(ETL_DEVELOPMENT_OS_APPLE) || (ETL_COMPILER_FULL_VERSION >= 190000) && (ETL_COMPILER_FULL_VERSION < 210000)) \
&& defined(ETL_COMPILER_CLANG))
template <typename T>
struct tuple_size;
template <size_t Index, typename TType>
struct tuple_element;
#endif
//***************************************************************************
/// Specialisation of tuple_size to allow the use of C++ structured bindings.
//***************************************************************************
template <typename T, size_t Size>
struct tuple_size<etl::array<T, Size> > : etl::integral_constant<size_t, Size>
{
};
//***************************************************************************
/// Specialisation of tuple_element to allow the use of C++ structured
/// bindings.
//***************************************************************************
template <size_t Index, typename T, size_t Size>
struct tuple_element<Index, etl::array<T, Size> >
{
ETL_STATIC_ASSERT(Index < Size, "Index out of bounds");
using type = T;
};
} // namespace std
#endif
#endif

View File

@ -35,6 +35,9 @@ SOFTWARE.
#include <algorithm>
#include <array>
#include <iterator>
#if ETL_USING_CPP11
#include <tuple>
#endif
#include <type_traits>
#include "etl/integral_limits.h"
@ -436,6 +439,60 @@ namespace
CHECK_EQUAL(3, result);
}
#if ETL_USING_CPP11
//*************************************************************************
TEST(test_tuple_size)
{
CHECK_EQUAL(SIZE, (etl::tuple_size<Data>::value));
CHECK_EQUAL(SIZE, (std::tuple_size<Data>::value));
#if ETL_USING_CPP17
CHECK_EQUAL(SIZE, (etl::tuple_size_v<Data>));
CHECK_EQUAL(SIZE, (std::tuple_size_v<Data>));
#endif
}
//*************************************************************************
TEST(test_tuple_element)
{
CHECK_TRUE((std::is_same<int, etl::tuple_element_t<0, Data>>::value));
CHECK_TRUE((std::is_same<int, etl::tuple_element_t<SIZE - 1, Data>>::value));
CHECK_TRUE((std::is_same<int, std::tuple_element<0, Data>::type>::value));
CHECK_TRUE((std::is_same<int, std::tuple_element<SIZE - 1, Data>::type>::value));
}
#endif
#if ETL_USING_CPP17
//*************************************************************************
TEST(test_structured_bindings)
{
etl::array<int, 3> data = {1, 2, 3};
// Bind by reference and modify.
auto& [a, b, c] = data;
CHECK_EQUAL(1, a);
CHECK_EQUAL(2, b);
CHECK_EQUAL(3, c);
a = 10;
b = 20;
c = 30;
CHECK_EQUAL(10, data[0]);
CHECK_EQUAL(20, data[1]);
CHECK_EQUAL(30, data[2]);
// Bind by const reference.
const auto& [x, y, z] = data;
CHECK_EQUAL(10, x);
CHECK_EQUAL(20, y);
CHECK_EQUAL(30, z);
}
#endif
//*************************************************************************
TEST(test_assign)
{