Я написал класс multi_array
который является расширением std::array
для нескольких измерений.
template <typename T, std::size_t... N>
class multi_array {
template <std::size_t... I, typename... Idx>
constexpr std::size_t linearized_index(meta::index_sequence<I...>,
Idx... idx) const {
std::size_t index = 0;
using unpack = std::size_t[];
(void)unpack{0UL,
((void)(index = (index + unpack{std::size_t(idx)...}[I]) *
meta::pack_element<I + 1, N...>::value),
0UL)...};
return index + unpack{std::size_t(idx)...}[sizeof...(idx) - 1];
}
// Storage
T m_data[meta::product<N...>::value];
//...
};
Мне удалось получить constexpr
элементу constexpr
но только в С++ 14. Проблема заключается в функции linearized_index
. Он вычисляет линеаризованный индекс во время компиляции. Для этого он определенным образом сводит кортеж индексов и кортеж измерения. Для этого сокращения мне нужна локальная переменная внутри функции, но это не разрешено в С++ 11. Моя среда не позволяет использовать С++ 14. Могу ли я каким-то образом переписать эту функцию для работы с С++ 11?
Я подготовил полный (не очень минимальный) пример, который компилируется в С++ 14.
#include <cstddef> // std::size_t
namespace meta {
// product
template <std::size_t...>
struct product;
template <std::size_t head, std::size_t... dim>
struct product<head, dim...> {
static constexpr std::size_t const value = head * product<dim...>::value;
};
template <>
struct product<> {
static constexpr std::size_t const value = 1;
};
// pack_element
template <std::size_t index, std::size_t head, std::size_t... pack>
struct pack_element {
static_assert(index < sizeof...(pack) + 1, "index out of bounds");
static constexpr std::size_t const value =
pack_element<index - 1, pack...>::value;
};
template <std::size_t head, std::size_t... pack>
struct pack_element<0, head, pack...> {
static constexpr std::size_t const value = head;
};
// index_sequence
// https://stackoverflow.com/a/24481400
template <std::size_t... I>
struct index_sequence {};
template <std::size_t N, std::size_t... I>
struct make_index_sequence : public make_index_sequence<N - 1, N - 1, I...> {};
template <std::size_t... I>
struct make_index_sequence<0, I...> : public index_sequence<I...> {};
} // namespace meta
template <typename T, std::size_t... N>
class multi_array {
template <std::size_t... I, typename... Idx>
constexpr std::size_t linearized_index(meta::index_sequence<I...>,
Idx... idx) const {
std::size_t index = 0;
using unpack = std::size_t[];
(void)unpack{0UL,
((void)(index = (index + unpack{std::size_t(idx)...}[I]) *
meta::pack_element<I + 1, N...>::value),
0UL)...};
return index + unpack{std::size_t(idx)...}[sizeof...(idx) - 1];
}
// Storage
T m_data[meta::product<N...>::value];
public:
constexpr multi_array() {}
template <typename... U>
constexpr multi_array(U... data) : m_data{T(data)...} {}
template <typename... Idx>
constexpr T operator()(Idx... idx) const noexcept {
std::size_t index = linearized_index(
meta::make_index_sequence<sizeof...(idx) - 1>{}, idx...);
return m_data[index];
}
};
int main() {
constexpr multi_array<double, 2, 2> const b = {0, 0, 0, 1};
static_assert(b(1, 1) == 1, "!");
}