[英]Combination of types using boost::mpl
我有一個類型列表,我想從中構建具有兩個元素的所有組合的列表。 例如:
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>
時,我也有興趣刪除重復項。
謝謝。
可以通過調用mpl::fold
來計算單個類型int
與類型列表mpl::vector<int, long>
的組合列表:
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);
編輯:回答第二個問題:
使結果只包含唯一元素(在您提到的意義上)更多涉及。 首先,您需要定義一個比較兩個元素並返回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;
所有這一切都來自我的頭腦,因此可能需要在這里或那里進行一些調整。 但這個想法應該是正確的。
編輯:@rafak概述的小修正
好問題。 有很多有趣的方法可以解決這個問題。 這是一個。
所有非限定名稱都在mpl
名稱空間中,除了_1
和_2
,它們位於mpl::placeholders
boost::is_same
和boost::is_same
,可以在type_traits庫中找到。 第一個模板是一個輔助類,用於生成由單個元素和給定序列的每個元素組成的所有對的列表。 第二個模板將所有結果聚合在一起以形成最終序列。 請注意,結果不在矢量中。 你可以使用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;
旁注:如果您正在閱讀本文並想要挑戰,請嘗試自己回答這個問題。 這是對MPL的一次重大嘗試。
我最近自己做了一些元編程,你看過boost :: mpl :: set嗎? 這將消除重復。 至於組合,聽起來像是映射,那么boost :: mpl :: map呢? 請注意,對序列可以采用的類型限制存在庫限制,盡管可以使用宏進行調整,但仍然受編譯器上限的限制,具體取決於您需要的類型數量處理。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.