Как преобразовать boost::hana::map в лямбды

У меня есть следующий код

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);

но я всегда получаю сообщение об ошибке

error: 'boost::hana::type_impl<short unsigned int>::_&' is not a class, struct, or union type

когда я использую hana::pair в my_tuple. Все работает нормально, когда я просто использую

auto my_types = hana::make_map(
  hana::type_c<std::uint32_t>,
  hana::type_c<std::uint16_t>
);

и, очевидно, никакого звонка на hana::first

Почему я получаю ссылку при использовании hana::first?


person Reza    schedule 20.05.2020    source источник
comment
@dfri оооооооооооооооооооооооооооооооооо бы обходной путь?   -  person Reza    schedule 20.05.2020
comment
Это я теперь знаю, иначе я бы опубликовал ответ вместо комментария;)   -  person dfrib    schedule 20.05.2020
comment
нашел эту информацию в документации По этой причине типы обеспечивают перегрузку унарного оператора +, который можно использовать для преобразования lvalue в rvalue. Таким образом, при использовании результата, который может быть ссылкой на объект типа, можно использовать +, чтобы убедиться, что значение r получено до извлечения его вложенного ::type:, но оно все еще не работает.   -  person Reza    schedule 20.05.2020
comment
Итак, using T = typename decltype(+hana::first(pair))::type; не дало того, что вы ожидаете?   -  person dfrib    schedule 20.05.2020
comment
@dfri заработало, контейнер не может быть hana::map, он должен быть hana::tuple   -  person Reza    schedule 20.05.2020
comment
stackoverflow.com /вопросы/36155645/   -  person Jason Rice    schedule 20.05.2020


Ответы (1)


Непонятно, почему вы пытаетесь использовать hana::map. hana::map не является Functor и не имеет реализации для hana::transform. Однако это Foldable, поэтому вы можете использовать hana::unpack и вернуть новый кортеж лямбда-выражений, если вам нужно.

Что касается hana::first вместе с другими средствами доступа, включая hana::at, hana::at_key и т. д.; Все они возвращают ссылочные типы, поэтому для доступа к членам вы должны каким-то образом удалить ссылку.

Для этого вы можете использовать предоставленный hana::type унарный + оператор:

using type = typename decltype(+hana::first(x))::type;

Или вы можете использовать hana::typeid_, что, на мой взгляд, более читабельно:

using type = typename decltype(hana::typeid_(hana::first(x)))::type;

Я не уверен, подходит ли hana::map к вашему варианту использования, но вот как вы можете «преобразовать» его в кортеж лямбда-выражений:

#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
        })...);
    });
}

https://godbolt.org/z/KMdrzS

Из вашего примера кода обратите внимание, что вы также можете столкнуться с проблемами, связанными с изменяемой ссылкой на вариант, который неявно приводится к другому типу, поэтому я просто удалил это.

person Jason Rice    schedule 20.05.2020
comment
Спасибо за ответ! У меня действительно проблема с вариантом, см. этот вопрос, есть идеи, как его обойти? - person Reza; 21.05.2020