C++ Boost Hana实现自定义序列

C++ Boost Hana实现自定义序列,c++,boost-hana,C++,Boost Hana,我面临的情况是,我通常会通过继承boost::hana::tuple来创建自定义类。例如,通过使用以下代码 template<typename ... args> struct my_nonworking_custom_tuple_t : public boost::hana::tuple<args ...> //not working!!! { using base = boost::hana::tuple<args ...>; //...

我面临的情况是,我通常会通过继承
boost::hana::tuple
来创建自定义类。例如,通过使用以下代码

template<typename ... args>
struct my_nonworking_custom_tuple_t : public boost::hana::tuple<args ...> //not working!!!
{
    using base = boost::hana::tuple<args ...>;
    //... all other stuff

    auto my_getter() const { return base::operator[](1_c); }
};
但是,一旦我这样做,结果类就不再对Hana概念“序列”建模,因此我无法应用所有方便的Hana方法


要将
我的自定义元组\u t
转换为Hana序列,我需要做些什么?

通常您不需要这样做,但这里有一个指南,用于实现您自己的
序列以及满足Boost.Hana中其他概念的要求。(后者对于不提供自己的元组实现的最终用户应该很有用。)

从以下文档中的最小完整定义(MCD)开始

在这里,您将看到,要实现
序列
,您的数据类型必须实现
make
功能,并满足和的要求

因此,必须为其提供实现的Hana函数的完整列表如下:

  • at
  • drop\u front
  • 为空
  • make
  • 解包
另外,请注意Boost.Hana有两种元组类型
tuple
basic\u tuple
basic\u tuple
重量更轻,因此您应该将其用于存储

要使用Boost.Hana的标记分派,您可以实现
Hana::tag_of
,或者只需提供
Hana_标记
类型别名作为类的成员

#include <boost/hana.hpp>
#include <utility>

namespace mine {
    struct my_custom_tuple_tag { };

    template<typename ... args>
    struct my_custom_tuple_t {
        using hana_tag = my_custom_tuple_tag;
        //... all other stuff
        boost::hana::basic_tuple<args ...> tup;

        auto my_getter() const {
            return boost::hana::at_c<1>(tup);
        }
    };
}

namespace boost::hana {
    // Iterable

    template <>
    struct at_impl<mine::my_custom_tuple_tag> {
        template <typename Xs, typename N>
        static constexpr decltype(auto) apply(Xs&& xs, N const&) {
            return at_impl<basic_tuple_tag>(std::forward<Xs>(xs).tup, N{});
        }
    };

    template <>
    struct drop_front_impl<mine::my_custom_tuple_tag> {
        template <typename Xs, typename N>
        static constexpr auto apply(Xs&& xs, N const&) {
            return drop_front_impl<basic_tuple_tag>(std::forward<Xs>(xs).tup);
        }
    };

    template <>
    struct is_empty_impl<mine::my_custom_tuple_tag> {
        template <typename Xs>
        static constexpr auto apply(Xs const& xs) {
            return is_empty_impl<basic_tuple_tag>(xs).tup;
        }
    };

    // Foldable

    template <>
    struct unpack_impl<mine::my_custom_tuple_tag> {
        template <typename Xs, typename F>
        static constexpr auto apply(Xs&& xs, F&& f) {
            return unpack_impl<basic_tuple_tag>(std::forward<Xs>(xs).tup,
                                                std::forward<F>(f));
        }
    };

    // Sequence

    template <>
    struct make_impl<mine::my_custom_tuple_tag> {
        template <typename ...Args>
        static constexpr auto apply(Args&& ...args) {
            return make_impl<basic_tuple_tag>(std::forward<Args>(args)...);
        }
    };

    template <>
    struct Sequence<mine::my_custom_tuple_tag> : std::true_type { };
}
#包括
#包括
名称空间地雷{
结构my_custom_tuple_tag{};
模板
构造我的自定义元组{
使用hana_标记=我的_自定义_元组_标记;
//…所有其他东西

boost::hana::basic_tuple

谢谢你的回答。使用
basic_tuple
而不是
tuple
的原因是什么?
hana::tuple
std::tuple
具有相同的构造函数,这使得实例化速度非常慢。作者创建了
basic_tuple
,作为自hana以来的轻量级等价物lready拥有
make
。甚至
hana::tuple
本身也使用
basic\u tuple
作为存储空间(我想)。是的,它有:。谢谢你的赏金!:D
#include <boost/hana.hpp>
#include <utility>

namespace mine {
    struct my_custom_tuple_tag { };

    template<typename ... args>
    struct my_custom_tuple_t {
        using hana_tag = my_custom_tuple_tag;
        //... all other stuff
        boost::hana::basic_tuple<args ...> tup;

        auto my_getter() const {
            return boost::hana::at_c<1>(tup);
        }
    };
}

namespace boost::hana {
    // Iterable

    template <>
    struct at_impl<mine::my_custom_tuple_tag> {
        template <typename Xs, typename N>
        static constexpr decltype(auto) apply(Xs&& xs, N const&) {
            return at_impl<basic_tuple_tag>(std::forward<Xs>(xs).tup, N{});
        }
    };

    template <>
    struct drop_front_impl<mine::my_custom_tuple_tag> {
        template <typename Xs, typename N>
        static constexpr auto apply(Xs&& xs, N const&) {
            return drop_front_impl<basic_tuple_tag>(std::forward<Xs>(xs).tup);
        }
    };

    template <>
    struct is_empty_impl<mine::my_custom_tuple_tag> {
        template <typename Xs>
        static constexpr auto apply(Xs const& xs) {
            return is_empty_impl<basic_tuple_tag>(xs).tup;
        }
    };

    // Foldable

    template <>
    struct unpack_impl<mine::my_custom_tuple_tag> {
        template <typename Xs, typename F>
        static constexpr auto apply(Xs&& xs, F&& f) {
            return unpack_impl<basic_tuple_tag>(std::forward<Xs>(xs).tup,
                                                std::forward<F>(f));
        }
    };

    // Sequence

    template <>
    struct make_impl<mine::my_custom_tuple_tag> {
        template <typename ...Args>
        static constexpr auto apply(Args&& ...args) {
            return make_impl<basic_tuple_tag>(std::forward<Args>(args)...);
        }
    };

    template <>
    struct Sequence<mine::my_custom_tuple_tag> : std::true_type { };
}