diff --git a/include/EASTL/array.h b/include/EASTL/array.h index 05d5d32f..cb8ed5c6 100644 --- a/include/EASTL/array.h +++ b/include/EASTL/array.h @@ -478,9 +478,96 @@ namespace eastl return internal::to_array(eastl::move(a), eastl::make_index_sequence{}); } +#if EASTL_TUPLE_ENABLED + + template + class tuple_size> : public integral_constant + { + }; + + template + class tuple_size> : public integral_constant + { + }; + + template + class tuple_element> + { + public: + using type = T; + }; + + template + class tuple_element> + { + public: + using type = const T; + }; + + template + struct GetArray + { + template + static EA_CONSTEXPR T& getInternal(array& a) + { + return a[I]; + } + + template + static EA_CONSTEXPR const T& getInternal(const array& a) + { + return a[I]; + } + + template + static EA_CONSTEXPR T&& getInternal(array&& a) + { + return eastl::forward(a[I]); + } + }; + + template + EA_CONSTEXPR tuple_element_t>& get(array& p) + { + return GetArray::getInternal(p); + } + + template + EA_CONSTEXPR const tuple_element_t>& get(const array& p) + { + return GetArray::getInternal(p); + } + + template + EA_CONSTEXPR tuple_element_t>&& get(array&& p) + { + return GetArray::getInternal(eastl::move(p)); + } + +#endif // EASTL_TUPLE_ENABLED + } // namespace eastl +/////////////////////////////////////////////////////////////// +// C++17 structured binding support for eastl::array +// +#ifndef EA_COMPILER_NO_STRUCTURED_BINDING + #include + + template + class std::tuple_size<::eastl::array> : public ::eastl::integral_constant + { + }; + + template + struct std::tuple_element> + { + static_assert(I < N, "index is out of bounds"); + using type = T; + }; +#endif // EA_COMPILER_NO_STRUCTURED_BINDING + #endif // Header include guard diff --git a/test/source/TestArray.cpp b/test/source/TestArray.cpp index 3db95b95..f9f448e0 100644 --- a/test/source/TestArray.cpp +++ b/test/source/TestArray.cpp @@ -132,6 +132,37 @@ int TestArray() static_assert(eastl::is_same_v, "deduced array value_type mismatch"); VERIFY(deduced.size() == 5); #endif + + // structured binding + + { + eastl::array aCopy = a; + auto&& [a0, a1, a2, a3, a4] = aCopy; + + VERIFY(a0 == aCopy[0]); + VERIFY(a1 == aCopy[1]); + VERIFY(a2 == aCopy[2]); + VERIFY(a3 == aCopy[3]); + VERIFY(a4 == aCopy[4]); + + a0 = 100; + VERIFY(aCopy[0] == 100); + + a4 = 0; + VERIFY(aCopy[4] == 0); + + // The deduced type may or may not be a reference type; it is an aliased type, + // as per https://en.cppreference.com/w/cpp/language/structured_binding: + // > Like a reference, a structured binding is an alias to an existing object. Unlike a reference, + // the type of a structured binding does not have to be a reference type. + // Any reference specifier is thus removed to check only the type & its const qualifier + static_assert(eastl::is_same_v, int>); + + const eastl::array aConstCopy = a; + auto&& [aConst0, aConst1, aConst2, aConst3, aConst4] = aConstCopy; + + static_assert(eastl::is_same_v, const int>); + } } // constexpr tests