Support indexing util::array with arbitrary array-like types
This commit is contained in:
parent
8571bc9c6d
commit
249ca33aab
1 changed files with 75 additions and 10 deletions
|
|
@ -9,6 +9,38 @@
|
||||||
namespace psemek::util
|
namespace psemek::util
|
||||||
{
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename T, typename = void>
|
||||||
|
struct is_array : std::false_type {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_array<T, std::void_t<decltype(std::declval<T&>()[0])>>
|
||||||
|
: std::true_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
constexpr bool is_array_v = is_array<T>::value;
|
||||||
|
|
||||||
|
template <typename ... Ts>
|
||||||
|
struct is_index;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct is_index<>
|
||||||
|
: std::false_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
template <typename T, typename ... Ts>
|
||||||
|
struct is_index<T, Ts...>
|
||||||
|
: std::bool_constant<!is_array_v<T>>
|
||||||
|
{};
|
||||||
|
|
||||||
|
template <typename ... Ts>
|
||||||
|
constexpr bool is_index_v = is_index<Ts...>::value;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T, std::size_t N>
|
template <typename T, std::size_t N>
|
||||||
struct array
|
struct array
|
||||||
{
|
{
|
||||||
|
|
@ -62,14 +94,27 @@ namespace psemek::util
|
||||||
return dims_[2];
|
return dims_[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
T & operator()(dims_type const & index);
|
template <typename Index>
|
||||||
T const & operator()(dims_type const & index) const;
|
std::enable_if_t<detail::is_array_v<Index>, T &>
|
||||||
|
operator()(Index const & index);
|
||||||
|
|
||||||
|
template <typename Index>
|
||||||
|
std::enable_if_t<detail::is_array_v<Index>, T const &>
|
||||||
|
operator()(Index const & index) const;
|
||||||
|
|
||||||
template <typename ... Ixs>
|
template <typename ... Ixs>
|
||||||
T & operator()(Ixs ... ixs);
|
std::enable_if_t<detail::is_index_v<Ixs...>, T &>
|
||||||
|
operator()(Ixs ... ixs);
|
||||||
|
|
||||||
template <typename ... Ixs>
|
template <typename ... Ixs>
|
||||||
T const & operator()(Ixs ... ixs) const;
|
std::enable_if_t<detail::is_index_v<Ixs...>, T const &>
|
||||||
|
operator()(Ixs ... ixs) const;
|
||||||
|
|
||||||
|
template <typename I>
|
||||||
|
T & operator()(std::initializer_list<I> const & index);
|
||||||
|
|
||||||
|
template <typename I>
|
||||||
|
T const & operator()(std::initializer_list<I> const & index) const;
|
||||||
|
|
||||||
array copy() const;
|
array copy() const;
|
||||||
|
|
||||||
|
|
@ -127,8 +172,8 @@ namespace psemek::util
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <std::size_t N>
|
template <std::size_t N, typename Index>
|
||||||
std::size_t index(std::array<std::size_t, N> const & i, std::array<std::size_t, N> const & dims)
|
std::size_t index(Index const & i, std::array<std::size_t, N> const & dims)
|
||||||
{
|
{
|
||||||
std::size_t r = 0;
|
std::size_t r = 0;
|
||||||
for (std::size_t d = N; d --> 0;)
|
for (std::size_t d = N; d --> 0;)
|
||||||
|
|
@ -278,20 +323,25 @@ namespace psemek::util
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, std::size_t N>
|
template <typename T, std::size_t N>
|
||||||
T & array<T, N>::operator()(dims_type const & index)
|
template <typename Index>
|
||||||
|
std::enable_if_t<detail::is_array_v<Index>, T &>
|
||||||
|
array<T, N>::operator()(Index const & index)
|
||||||
{
|
{
|
||||||
return data_[detail::index(index, dims_)];
|
return data_[detail::index(index, dims_)];
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, std::size_t N>
|
template <typename T, std::size_t N>
|
||||||
T const & array<T, N>::operator()(dims_type const & index) const
|
template <typename Index>
|
||||||
|
std::enable_if_t<detail::is_array_v<Index>, T const &>
|
||||||
|
array<T, N>::operator()(Index const & index) const
|
||||||
{
|
{
|
||||||
return data_[detail::index(index, dims_)];
|
return data_[detail::index(index, dims_)];
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, std::size_t N>
|
template <typename T, std::size_t N>
|
||||||
template <typename ... Ixs>
|
template <typename ... Ixs>
|
||||||
T & array<T, N>::operator()(Ixs ... ixs)
|
std::enable_if_t<detail::is_index_v<Ixs...>, T &>
|
||||||
|
array<T, N>::operator()(Ixs ... ixs)
|
||||||
{
|
{
|
||||||
dims_type dims{static_cast<std::size_t>(ixs)...};
|
dims_type dims{static_cast<std::size_t>(ixs)...};
|
||||||
return (*this)(dims);
|
return (*this)(dims);
|
||||||
|
|
@ -299,12 +349,27 @@ namespace psemek::util
|
||||||
|
|
||||||
template <typename T, std::size_t N>
|
template <typename T, std::size_t N>
|
||||||
template <typename ... Ixs>
|
template <typename ... Ixs>
|
||||||
T const & array<T, N>::operator()(Ixs ... ixs) const
|
std::enable_if_t<detail::is_index_v<Ixs...>, T const &>
|
||||||
|
array<T, N>::operator()(Ixs ... ixs) const
|
||||||
{
|
{
|
||||||
dims_type dims{static_cast<std::size_t>(ixs)...};
|
dims_type dims{static_cast<std::size_t>(ixs)...};
|
||||||
return (*this)(dims);
|
return (*this)(dims);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T, std::size_t N>
|
||||||
|
template <typename I>
|
||||||
|
T & array<T, N>::operator()(std::initializer_list<I> const & index)
|
||||||
|
{
|
||||||
|
return data_[detail::index(std::data(index), dims_)];
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, std::size_t N>
|
||||||
|
template <typename I>
|
||||||
|
T const & array<T, N>::operator()(std::initializer_list<I> const & index) const
|
||||||
|
{
|
||||||
|
return data_[detail::index(std::data(index), dims_)];
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T, std::size_t N>
|
template <typename T, std::size_t N>
|
||||||
array<T, N> array<T, N>::copy() const
|
array<T, N> array<T, N>::copy() const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue