Создайте кортеж ханы с неперемещаемыми/некопируемыми типами

Я пытаюсь осмыслить великолепный boost::hana и попытаться понять, как перевести какой-нибудь старый школьный код кортежа.

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

Думаю, я просто не понимаю, как создать кортеж хана в мире значений. То, как я пытаюсь, не работает, потому что make<Tuple>(CompT{}...) нужны типы, которые можно копировать или, по крайней мере, перемещать.

Так что, скорее всего, это просто не способ сделать это. Или это ограничение ханы?

Спасибо!

struct NonMoveable
{
    NonMoveable() = default;
    NonMoveable(const NonMoveable& other) = delete;

    int val;
};

struct Simple { int val; };

template <typename ...CompT>
struct OldSchoolContainer
{
    template <int I>
    auto& getComponent()
    {
        return std::get<I>(components);
    }

    std::tuple<CompT...> components;
};

template <typename ...CompT>
struct HanaContainer
{
    using Args_t = decltype(make<Tuple>(CompT{}...));

    template <int I>
    auto& getComponent()
    {
        return components[int_<I>];
    }

    Args_t components;
};

int main()
{
    OldSchoolContainer<Simple> simpleOsc;
    static_assert(std::is_same<Simple&, decltype(simpleOsc.getComponent<0>())>::value, "");

    HanaContainer<Simple> simpleHanaC;
    static_assert(std::is_same<Simple&, decltype(simpleHanaC.getComponent<0>())>::value, "");


    OldSchoolContainer<NonMoveable> nonmoveableOsc;
    static_assert(std::is_same<NonMoveable&, decltype(nonmoveableOsc.getComponent<0>())>::value, "");

    // !!! this does not compile because hana's tuple closure needs to either move or copy
    HanaContainer<NonMoveable> nonmoveableHanaC;
    static_assert(std::is_same<NonMoveable&, decltype(nonmoveableHanaC.getComponent<0>())>::value, "");

    return 0;
}

person Daniel Doubleday    schedule 22.07.2015    source источник


Ответы (1)


Вы можете использовать тип hana::_tuple<...> почти так же, как std::tuple. Итак, следующие работы:

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


struct NonMoveable
{
    NonMoveable() = default;
    NonMoveable(const NonMoveable& other) = delete;

    int val;
};

struct Simple { int val; };

template <typename ...CompT>
struct HanaContainer
{
    template <int I>
    auto& getComponent()
    {
        return components[hana::int_<I>];
    }

    hana::_tuple<CompT...> components;
};

int main()
{
    HanaContainer<Simple> simpleHanaC;
    static_assert(std::is_same<Simple&, decltype(simpleHanaC.getComponent<0>())>::value, "");

    HanaContainer<NonMoveable> nonmoveableHanaC;
    static_assert(std::is_same<NonMoveable&, decltype(nonmoveableHanaC.getComponent<0>())>::value, "");

    return 0;
}
person Louis Dionne    schedule 24.07.2015
comment
Это было легко :-) Большое спасибо, Луи! Это было недостающее звено. Возможно, стоит добавить раздел в вашу замечательную документацию. Когда вы это знаете, это легко найти в примерах, но легко пропустить, так как в документах все делается автоматически и используются только заводские функции. Действительно отличная работа! - person Daniel Doubleday; 24.07.2015
comment
Без проблем! Я готовлю довольно большое обновление для библиотеки после официального обзора Boost, и это будет лучше задокументировано. - person Louis Dionne; 24.07.2015