代码之家  ›  专栏  ›  技术社区  ›  rafak

使用boost::mpl的类型组合

  •  4
  • rafak  · 技术社区  · 14 年前

    我有一个类型列表,我想从中构造包含两个元素的所有组合的列表。例如:

    namespace mpl = boost::mpl;
    typedef mpl::vector<int, long> typelist;
    // mpl magic...
    // the wanted list is equivalent to:
    typedef mpl::vector<pair<int, int>, pair<int, long>,
                        pair<long, int>, pair<long, long> > combinations;
    

    pair<T1,T2> 可以是 std::pair<T1,T2> mpl::vector<T1,T2> . 怎么做? pair<T1, T2> == pair<T2, T1>

    3 回复  |  直到 14 年前
        1
  •  6
  •   hkaiser    14 年前

    单一类型的组合列表 int 类型列表 mpl::vector<int, long> 可以通过调用 mpl::fold

    typedef fold<
        mpl::vector<int, long>, vector<>, 
        push_back<mpl::_1, std::pair<int, mpl::_2> > 
    >::type list_of_pairs;
    

    现在,如果我们把它包装成一个单独的元函数,并对初始类型列表的所有类型调用它,我们得到:

    typedef mpl::vector<int, long> typelist;
    
    template <typename T, typename Result>
    struct list_of_pairs
      : mpl::fold<typelist, Result, 
            mpl::push_back<mpl::_1, std::pair<T, mpl::_2> > > 
    {};
    
    typedef mpl::fold<
        typelist, mpl::vector<>, mpl::lambda<list_of_pairs<mpl::_2, mpl::_1> >
    >::type result_type;
    
    BOOST_MPL_ASSERT(
        mpl::equal<result_type, 
            mpl::vector4<
                std::pair<int, int>, std::pair<int,long>,
                std::pair<long,int>, std::pair<long,long> 
            > >::value);
    

    编辑:回答第二个问题:

    template <typename P1, typename P2>
    struct pairs_are_equal
      : mpl::or_<
            mpl::and_<
                is_same<typename P1::first_type, typename P2::first_type>,
                is_same<typename P1::second_type, typename P2::second_type> >,
            mpl::and_<
                is_same<typename P1::first_type, typename P2::second_type>, 
                is_same<typename P1::second_type, typename P2::first_type> > >
    {};
    

    然后我们需要定义一个元函数,它试图在给定的列表中找到给定的元素:

    template <typename List, typename T>
    struct list_doesnt_have_element
      : is_same<
            typename mpl::find_if<List, pairs_are_equal<mpl::_1, T> >::type, 
            typename mpl::end<List>::type>
    {};
    

    现在,可以利用它来构建一个新列表,确保没有插入重复的列表:

    typedef mpl::fold<
        result_type, mpl::vector<>,
        mpl::if_<
            mpl::lambda<list_doesnt_have_element<mpl::_1, mpl::_2> >, 
            mpl::push_back<mpl::_1, mpl::_2>, mpl::_1>
    
    >::type unique_result_type;
    


    编辑:如@rafak概述的轻微更正

        2
  •  2
  •   John    14 年前

    好问题。有很多有趣的方法可以解决这个问题。这里有一个。

    所有不合格的名字都在 mpl _1 _2 哪些在 mpl::placeholders boost::is_same ,可在类型库中找到。第一个模板是一个helper类,用于生成由单个元素和给定序列的每个元素组成的所有对的列表。第二个模板将所有结果聚合在一起,形成最终的序列。请注意,结果不是在向量中。使用mpl::copy可以很容易地做到这一点。

    template <class Elem, class Seq>
    struct single_combo {
        typedef typename transform<Seq
                ,lambda< std::pair<Elem, _1> >
            >::type type;
    };
    
    template <class Seq>
    struct combo {
        typedef typename unique<Seq, is_same<_1,_2> >::type U;
        typedef typename fold<
            typename transform<U
                ,lambda< single_combo<_1, U> >
                >::type
            ,empty_sequence
            ,lambda< joint_view<_1,_2> >
        >::type type;
    };
    
    typedef typename combo<typelist>::type combinations;
    

        3
  •  0
  •   Geoff    14 年前

    我最近也在做一些元编程,你有没有研究过boost::mpl::set?这将消除重复。至于组合,这听起来像映射,那么boost::mpl::map呢?请注意,对序列可以接受的类型的限制有一些库限制,尽管这可以用宏进行调整,但您仍然受编译器上限的支配,具体取决于需要处理的类型数。

    推荐文章