以下是我的代码
using my_variant = std::variant<std::uint32_t, std::int32_t>;
auto my_types_map = hana::make_tuple(
hana::make_pair(hana::type_c<std::uint32_t>, hana::integral_c<std::uint8_t, 0>),
hana::make_pair(hana::type_c<std::int32_t>, hana::integral_c<std::uint8_t, 1>)
);
template <typename T>
void my_func(T& value)
{
value = 32;
};
auto factory(std::uint8_t code, my_variant& value)
{
std::function<void(my_variant&)> sub_fun;
hana::for_each(my_types_map, [&](const auto& x)
{
if (code == hana::second(x))
{
using T = typename decltype(+hana::first(x))::type;
sub_fun = [](my_variant& v){ my_func(std::get<T>(v)); };
}
});
sub_fun(value);
}
当我调用第一种类型时,所有工作正常,但当我调用第二种类型时,我得到一个 unexpected index
在运行时出现异常。
my_variant v;
factory(0, v);
assert(32 == std::get<std::uint32_t>(v)); // all fine
factory(1, v);
assert(32 == std::get<std::int32_t>(v)); // unexpected index!
这里有什么问题?
你的问题与Boost.Hana无关。
这里有一个较短的重现。
std::variant<int, char> v;
std::get<char>(v) = 'X'; // this throws
std::get
在... variant
是类型安全的。你要么得到一个 T&
至 T
储存在 variant
...或者你得到一个例外。你不能使用 std::get
来改变变体的基本类型。您只能通过将变体的类型分配给 variant
或调用 emplace
. 在你的程序中,没有任何东西能做到这一点,所以当你试图访问它本来不需要的类型时,你会得到一个异常。
所以你必须重新考虑这个程序的工作方式。
然后只需使用 Boost.Mp11因为你使用的 hana::map 只是在手动重建你的变量。
auto factory(std::uint8_t code, my_variant& value)
{
mp_with_index<mp_size<my_variant>::size>(code, [&](auto I){
value.emplace<I>(32);
});
}
问题是你的setter期望变量已经有了预期的类型。
你应该有。
auto factory(std::uint8_t code, my_variant& value)
{
std::function<void(my_variant&)> sub_fun;
hana::for_each(my_types_map, [&](const auto& x)
{
if (code == hana::second(x))
{
using T = typename decltype(+hana::first(x))::type;
sub_fun = [](my_variant& v){ T t; my_func(t); v = t; };
}
});
sub_fun(value);
}