Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use hana::transform to transform types inside tuple in C++14

I'm trying to use Boost's hana::transform to change the types inside a hana::tuple. As an example, say I have

constexpr auto some_tuple = hana::tuple_t<int, char *, bool>;

and I want to produce

constexpr auto transformed_tuple = hana::tuple_t<std::vector<int>,
                                                 std::vector<char *>, 
                                                 std::vector<bool>>;

Attempt 1

The solution seemed easy to me: Use hana::transform and make the applied function return hana::type_c<std::vector<decltype(T)::type>>. However, I can't make this work:

constexpr auto transformed_tuple = hana::transform(some_tuple, [](auto T) {
    using inner_type = typename decltype(T)::type;
    return hana::type_c<std::vector<inner_type>>;
});

This has the problem that the lambda expression is not a constexpr - and I want to stay in C++14, i.e., lambdas can't be constexpr.

Attempt 2

My next thought: What if I wrapped the hana::transform into a decltype, and then use hana::type_c on that? This way, the lambda never needs to be evaluated (only its return type must be deduced), and constexprness should not matter:

constexpr auto transformed_tuple = 
    hana::type_c<decltype(hana::transform(some_tuple, [](auto T) {
        using inner_type = typename decltype(T)::type;
        return hana::type_c<std::vector<inner_type>>;
    }))>;

However, now I run into the problem that lambda-expressions may not appear in an "unevaluated context".

Is my approach completely wrong? Should I use something else than hana::transform?

Thanks for any help.

Edit:

Sample code:

#include <boost/hana.hpp>
#include <boost/hana/tuple.hpp>
#include <boost/hana/type.hpp>
namespace hana = boost::hana;

#include <vector>

constexpr auto some_tuple = hana::tuple_t<int, char *, bool>;

/** What I want:
 *
 *   constexpr auto transformed_tuple 
 *       = hana::tuple_t<std::vector<int>,
 *           std::vector<char *>, 
 *           std::vector<bool>>;
**/

#if ATTEMPT1
    constexpr auto transformed_tuple = hana::transform(some_tuple, [](auto T) {
        using inner_type = typename decltype(T)::type;
        return hana::type_c<std::vector<inner_type>>;
    });

#elif ATTEMPT2
    constexpr auto transformed_tuple = hana::type_c<decltype(hana::transform(some_tuple, [](auto T) {
        using inner_type = typename decltype(T)::type;
        return hana::type_c<std::vector<inner_type>>;
    }))>;

#endif
like image 537
Lukas Barth Avatar asked Apr 11 '18 14:04

Lukas Barth


1 Answers

Boost.Hana has hana::template_ for applying types to a template which returns a type.

#include <boost/hana/assert.hpp>
#include <boost/hana/equal.hpp>
#include <boost/hana/transform.hpp>
#include <boost/hana/tuple.hpp>
#include <boost/hana/type.hpp>
#include <vector>

namespace hana = boost::hana;


int main() {
    constexpr auto some_tuple = hana::tuple_t<int, char *, bool>;
    constexpr auto expected_tuple = hana::tuple_t<std::vector<int>,
                                                  std::vector<char*>,
                                                  std::vector<bool>>;

    constexpr auto transformed_tuple = hana::transform(some_tuple, hana::template_<std::vector>);

    BOOST_HANA_CONSTANT_CHECK(transformed_tuple == expected_tuple);
}
like image 164
Jason Rice Avatar answered Oct 22 '22 14:10

Jason Rice