Skip to content

Commit

Permalink
Merge pull request #411 from Razakhel/array_structured_binding
Browse files Browse the repository at this point in the history
Added structured binding support for eastl::array
  • Loading branch information
james-moran-ea authored Feb 9, 2022
2 parents d1c2a9c + 8d5eb9e commit ca6b871
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 0 deletions.
87 changes: 87 additions & 0 deletions include/EASTL/array.h
Original file line number Diff line number Diff line change
Expand Up @@ -478,9 +478,96 @@ namespace eastl
return internal::to_array(eastl::move(a), eastl::make_index_sequence<N>{});
}

#if EASTL_TUPLE_ENABLED

template <typename T, size_t N>
class tuple_size<array<T, N>> : public integral_constant<size_t, N>
{
};

template <typename T, size_t N>
class tuple_size<const array<T, N>> : public integral_constant<size_t, N>
{
};

template <size_t I, typename T, size_t N>
class tuple_element<I, array<T, N>>
{
public:
using type = T;
};

template <size_t I, typename T, size_t N>
class tuple_element<I, const array<T, N>>
{
public:
using type = const T;
};

template <size_t I>
struct GetArray
{
template <typename T, size_t N>
static EA_CONSTEXPR T& getInternal(array<T, N>& a)
{
return a[I];
}

template <typename T, size_t N>
static EA_CONSTEXPR const T& getInternal(const array<T, N>& a)
{
return a[I];
}

template <typename T, size_t N>
static EA_CONSTEXPR T&& getInternal(array<T, N>&& a)
{
return eastl::forward<T>(a[I]);
}
};

template <size_t I, typename T, size_t N>
EA_CONSTEXPR tuple_element_t<I, array<T, N>>& get(array<T, N>& p)
{
return GetArray<I>::getInternal(p);
}

template <size_t I, typename T, size_t N>
EA_CONSTEXPR const tuple_element_t<I, array<T, N>>& get(const array<T, N>& p)
{
return GetArray<I>::getInternal(p);
}

template <size_t I, typename T, size_t N>
EA_CONSTEXPR tuple_element_t<I, array<T, N>>&& get(array<T, N>&& p)
{
return GetArray<I>::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 <tuple>

template <typename T, size_t N>
class std::tuple_size<::eastl::array<T, N>> : public ::eastl::integral_constant<size_t, N>
{
};

template <size_t I, typename T, size_t N>
struct std::tuple_element<I, ::eastl::array<T, N>>
{
static_assert(I < N, "index is out of bounds");
using type = T;
};
#endif // EA_COMPILER_NO_STRUCTURED_BINDING


#endif // Header include guard

Expand Down
31 changes: 31 additions & 0 deletions test/source/TestArray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,37 @@ int TestArray()
static_assert(eastl::is_same_v<decltype(deduced)::value_type, int>, "deduced array value_type mismatch");
VERIFY(deduced.size() == 5);
#endif

// structured binding

{
eastl::array<int, 5> 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<eastl::remove_reference_t<decltype(a0)>, int>);

const eastl::array<int, 5> aConstCopy = a;
auto&& [aConst0, aConst1, aConst2, aConst3, aConst4] = aConstCopy;

static_assert(eastl::is_same_v<eastl::remove_reference_t<decltype(aConst0)>, const int>);
}
}

// constexpr tests
Expand Down

0 comments on commit ca6b871

Please sign in to comment.