4

タイプのリストがあり、そこから 2 つの要素を持つすべての組み合わせのリストを作成します。例えば:

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>

4

3 に答える 3

6

単一のタイプ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);

編集:2番目の質問に答える:

(あなたが言及した意味で)一意の要素のみを含む結果を作成することは、もう少し複雑です。最初に、2 つの要素を比較して mpl::true_/mpl::false_ を返すメタ関数を定義する必要があります。

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;

これはすべて私の頭の上からのものであるため、あちこちで微調整が必​​要になる場合があります。しかし、その考えは正しいはずです。


EDIT:@rafakによって概説されたマイナーな修正

于 2010-07-23T23:02:04.380 に答える
2

素晴らしい質問です。これを解決する興味深い方法がたくさんあります。これが1つです。

type_traits ライブラリにあるとにあるとをmpl除いて、すべての非修飾名は名前空間にあります。最初のテンプレートは、単一の要素と指定されたシーケンスの各要素で構成されるすべてのペアのリストを生成するヘルパー クラスです。2 番目のテンプレートは、すべての結果をまとめて、最終的なシーケンスを形成します。結果はベクトルではないことに注意してください。これは、mpl::copy を使用して簡単に行うことができます。_1_2mpl::placeholdersboost::is_same

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;

補足: これを読んで挑戦したい場合は、この質問に自分で答えてみてください。これは、MPL への素晴らしい突入です。

于 2010-07-24T00:52:50.510 に答える
0

私は最近自分でメタプログラミングを行っていますが、boost::mpl::set について調べましたか? それは重複を排除します。組み合わせに関しては、マッピングのように思えますが、boost::mpl::map はどうですか? シーケンスが取ることができる型の制限に課されるライブラリ制限があることに注意してください。これはマクロで調整できますが、必要な型の数に応じて、コンパイラの上限に翻弄されます。扱う。

于 2010-07-23T23:47:30.733 に答える