Преобразование списка времени компиляции Boost Hana

Я пытаюсь понять, как преобразовать список целочисленных констант во время компиляции с помощью boost:hana.

У меня есть список как:

constexpr auto vals = hana::to<hana::tuple_tag>(hana::range_c<int, 0, 3>);

Я хочу применить функцию:

constexpr auto Pow2(int i) { return 1 << i; }

Однако

constexpr auto res = hana::transform(list, Pow2);

создает тип для res hana::tuple<int, int, int>. Я не вижу, как переместить аргумент лямбда в аргумент шаблона для hana::int_c

// Compiler error: Non-type template argument is not a constant expression
constexpr auto Pow2(int i)
{
    return hana::int_c<1 << i>{};
}

person wes    schedule 23.02.2017    source источник


Ответы (1)


In ...

constexpr auto Pow2(int i) { return 1 << i; } 

...i – это целое число времени выполнения. Это не параметр "удобный для компиляции", поскольку его значение не сохраняется как часть его типа. Вместо этого вы должны передать int_:

template <int X>
constexpr auto Pow2(hana::int_<X>) { return hana::int_c<1 << X>; }

Использование:

constexpr auto vals = hana::to<hana::tuple_tag>(hana::range_c<int, 0, 3>);
constexpr auto res = hana::transform(vals, [](auto x){ return Pow2(x); });

static_assert(std::is_same_v<
    std::decay_t<decltype(res)>,
    hana::tuple<hana::int_<1>, hana::int_<2>, hana::int_<4>>
>);

пример wandbox


Очевидно, вы также можете сделать это с лямбдой. Кроме того, boost::hana::int_ имеет перегрузку operator<<, которая возвращает int_:

hana::transform(vals, [](auto x){ return hana::int_c<1> << x; });

пример wandbox

person Vittorio Romeo    schedule 23.02.2017
comment
Спасибо. Мне было интересно, был ли это хороший подход, и это был просто мой компилятор, который не поддерживал каноническую технику. Переключение вашего примера на clang 3.9.1 prog.cc:12:20: error: constexpr variable 'res' must be initialized by a constant expression constexpr auto res = hana::transform(vals, [](auto x){ return hana::int_c<1> << x; }); Есть ли способ заставить его работать с clang 3.9.1? - person wes; 23.02.2017
comment
@ user78145: да, просто избавься от constexpr в constexpr res - person Vittorio Romeo; 24.02.2017
comment
Причина, по которой это не работает, заключается в том, что лямбда-выражения не могут быть constexpr в C++14, глупое ограничение, снятое в C++17. - person Louis Dionne; 25.02.2017