На самом деле нет проблем с использованием std::make_tuple
в константном выражении в C ++ 14 или более поздних версиях, поскольку C ++ 14 изменил его на constexpr
.Таким образом, это допустимое константное выражение, если любые конструкторы классов, используемые для инициализации элементов кортежа, оцениваются как допустимые константные выражения (и таких конструкторов нет, если все типы элементов являются скалярами, такими как std::uint32_t
).
Но лучше взгляните на сообщение об ошибке.Функция, на которую он жалуется, это (извлечение некоторых деталей) tuple& tuple::operator=(tuple&&)
.Оказывается, операторы присваивания из std::tuple
не помечены constexpr
в текущих версиях C ++, что означает, что любое присвоение объекта tuple
не является допустимым константным выражением.(cppreference.com отмечает, что они будут помечены constexpr
в C ++ 20; это обычно отражает изменения по сравнению с предложением, уже принятым соответствующей рабочей группой C ++.)
Итак, чтобы обойти это, вы 'Вам нужно будет инициализировать array
сразу, а не назначать его элементы в цикле.Вероятно, самый простой способ сделать это с помощью std::make_integer_sequence
:
#include <tuple>
#include <array>
#include <cstdint>
#include <utility>
template <std::uint32_t ... I>
constexpr std::array<std::tuple<std::uint32_t, std::uint32_t, std::uint32_t>,
sizeof...(I)>
GenArrayTuple_helper(std::integer_sequence<std::uint32_t, I...>) {
return { std::make_tuple(I, I * 2, I * 3 + 1) ... };
}
template <std::size_t SIZE>
constexpr std::array<std::tuple<std::uint32_t, std::uint32_t, std::uint32_t>,
SIZE>
GenArrayTuple() {
return GenArrayTuple_helper(std::make_integer_sequence<std::uint32_t, SIZE>{});
}