Search code examples
c++boostmetaprogrammingboost-hana

Boost Hana Compile-Time List Transformation


I'm trying to figure out how to transform a list of integer constants at compile time using boost:hana.

I have my list as:

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

I want to apply the function:

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

However

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

produces a type for res of hana::tuple<int, int, int>. I'm not seeing how to move the argument to the lambda into a template argument for 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>{};
}

Solution

  • In ...

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

    ...i is a runtime integer. It is not a "compile-time-friendly" parameter, as its value is not stored as part of its type. You should pass in a int_ instead:

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

    Usage:

    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 example


    Obviously, you can also do this with a lambda. Additionally, boost::hana::int_ has an operator<< overload that returns an int_:

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

    wandbox example