I have the following code
template <typename T>
void my_func(T& /*var*/)
{
};
auto my_types = hana::make_map(
hana::make_pair(hana::type_c<std::uint32_t>, hana::integral_c<std::uint8_t, 1>),
hana::make_pair(hana::type_c<std::uint16_t>, hana::integral_c<std::uint8_t, 1>)
);
using my_variant = std::variant<std::uint32_t, std::uint16_t>;
auto to_factory = [](auto map)
{
return hana::transform(map, [](auto pair)
{
return [](my_variant& value)
{
using T = typename decltype(hana::first(pair))::type;
T v;
my_func(v);
value = v;
};
});
};
auto factory = to_factory(my_types);
but I always get the error message
error: 'boost::hana::type_impl<short unsigned int>::_&' is not a class, struct, or union type
when I use hana::pair
in my_tuple
. All works fine when I just use
auto my_types = hana::make_map(
hana::type_c<std::uint32_t>,
hana::type_c<std::uint16_t>
);
and obviously no call to hana::first
Why do I get back kind of a reference when using hana::first
?
It's not clear why you are trying to use hana::map
. hana::map
is not a Functor
and has no implementation for hana::transform
. It is, however Foldable
so you could use hana::unpack
and return a new tuple of lambdas if you needed to.
As for hana::first
along with other accessors including hana::at
, hana::at_key
, etc.; They all return reference types so to access members you must strip the reference somehow.
For this you can use the provided hana::type
unary +
operator:
using type = typename decltype(+hana::first(x))::type;
Or you can use hana::typeid_
which is a bit more readable in my opinion:
using type = typename decltype(hana::typeid_(hana::first(x)))::type;
I'm not sure if hana::map
fits with your use case, but here is how you could "transform" it into a tuple of lambdas:
#include <boost/hana.hpp>
#include <cstdint>
#include <variant>
namespace hana = boost::hana;
auto my_types = hana::make_map(
hana::make_pair(hana::type_c<std::uint32_t>, hana::integral_c<std::uint8_t, 1>),
hana::make_pair(hana::type_c<std::uint16_t>, hana::integral_c<std::uint8_t, 1>)
);
using my_variant = std::variant<std::uint32_t, std::uint16_t>;
auto make_lambda = [](auto pair) {
return [](my_variant value) {
using T = typename decltype(hana::typeid_(hana::first(pair)))::type;
// do stuff
};
};
auto to_factory = [](auto map) {
return hana::unpack(map, [](auto ...pairs) {
return hana::make_tuple(make_lambda(pairs)...);
});
};
// erm.. you could also do this
auto to_factory_2 = [](auto map) {
return hana::unpack(map, [](auto ...pairs) {
return hana::make_tuple(((void)pairs, [](my_variant value) {
using T = typename decltype(hana::typeid_(hana::first(pairs)))::type;
// do stuff
})...);
});
}
From your code example, note that you might also run into issues taking a mutable reference to a variant that is being implicitly cast from a different type so I just removed that.