包装Boost.Fusion序列

时间:2012-08-30 20:40:04

标签: c++ boost-fusion

我正在寻找一种方法来创建一个 Boost.Fusion 序列包装器,它本身就是一个 Fusion 序列,并将所有'调用'转发到它的包装序列。

中的某些内容
template< typename Sequence >
struct sequence_wrapper
{
    explicit sequence_wrapper( Sequence const& s ) : seq( s ){}

    Sequence seq;
};

其中sequence_wrapper< Sequence >也是 Fusion 序列,并且与Sequence一样。我需要这个的原因是我有几个函数在 Fusion 序列上运行(其中所有元素都满足一些特殊要求),我想添加一些语法糖,我需要一个自定义类型添加重载运算符。我不需要sequence_wrapper上的操作结果来返回sequence_wrapper,只有语法糖相关的调用才会返回(手动)包装的序列。例如,使用逗号运算符将元素附加到序列(某些 Boost.Assign 用于 Fusion 序列):

template< typename Sequence, typename T >
sequence_wrapper<
    typename boost::fusion::result_of::push_back<
        Sequence const&
      , T
    >::type
> operator ,( Sequence const& seq, T const& v )
{
    return
        sequence_wrapper<
            typename boost::fusion::result_of::push_back<
                Sequence const&
              , T
            >::type
        >( boost::fusion::push_back( seq, v ) )
        ;
}

实现这一目标的最佳方式是什么(如果图书馆确实支持它)?我特别想避免从头开始创建 Fusion 序列,因为我想使用 Fusion 操作返回的任何序列。继承+ tag_of的特化会返回包装序列的标签吗?或者我是否需要定义自己的标签并实现所有必需的功能才能转发呼叫?

1 个答案:

答案 0 :(得分:4)

这就是我最终做的事情:

template<
    typename Derived
  , typename Sequence
  , typename TraversalTag = 
        typename boost::fusion::traits::category_of< Sequence >::type
  , typename IsView =
        typename boost::fusion::traits::is_view< Sequence >::type
>
class fusion_sequence_wrapper
  : public boost::fusion::sequence_facade< Derived, TraversalTag, IsView >
{
    typedef Sequence base_sequence_type;

public:
    explicit fusion_sequence_wrapper( base_sequence_type const& sequence )
      : _seq( sequence )
    {}

    base_sequence_type const& base() const
    {
        return _seq;
    }
    base_sequence_type& base()
    {
        return _seq;
    }

public:
    template< typename Seq >
    struct begin
    {
        typedef
            typename boost::fusion::result_of::begin<
                typename boost::mpl::if_<
                    boost::is_const< Seq >
                  , base_sequence_type const
                  , base_sequence_type
                >::type
            >::type type;

        static type call( Seq& s ){ return boost::fusion::begin( s._seq ); }
    };

    template< typename Seq >
    struct end
    {
        typedef
            typename boost::fusion::result_of::end<
                typename boost::mpl::if_<
                    boost::is_const< Seq >
                  , base_sequence_type const
                  , base_sequence_type
                >::type
            >::type type;

        static type call( Seq& s ){ return boost::fusion::end( s._seq ); }
    };

    template< typename Seq >
    struct size
    {
        typedef
            typename boost::fusion::result_of::size<
                typename boost::mpl::if_<
                    boost::is_const< Seq >
                  , base_sequence_type const
                  , base_sequence_type
                >::type
            >::type type;

        static type call( Seq& s ){ return boost::fusion::size( s._seq ); }
    };

    template< typename Seq >
    struct empty
    {
        typedef
            typename boost::fusion::result_of::empty<
                typename boost::mpl::if_<
                    boost::is_const< Seq >
                  , base_sequence_type const
                  , base_sequence_type
                >::type
            >::type type;

        static type call( Seq& s ){ return boost::fusion::empty( s._seq ); }
    };

    template< typename Seq, typename N >
    struct at
    {
        typedef
            typename boost::fusion::result_of::at<
                typename boost::mpl::if_<
                    boost::is_const< Seq >
                  , base_sequence_type const
                  , base_sequence_type
                >::type
              , N
            >::type type;

        static type call( Seq& s ){ return boost::fusion::at( s._seq ); }
    };

    template< typename Seq, typename N >
    struct value_at
    {
        typedef
            typename boost::fusion::result_of::value_at<
                typename boost::mpl::if_<
                    boost::is_const< Seq >
                  , base_sequence_type const
                  , base_sequence_type
                >::type
              , N
            >::type type;
    };

private:
    base_sequence_type _seq;
};