为什么我在循环boost::hana::元组时得到意外的索引?

问题描述 投票:0回答:2

以下是我的代码

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!

这里有什么问题?

c++ lambda c++17 variant boost-hana
2个回答
2
投票

你的问题与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);
    });
}

0
投票

问题是你的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);
}
© www.soinside.com 2019 - 2024. All rights reserved.