2016-12-04 73 views
0

我想熟悉boost :: hana。作爲一個練習,我想創建一個函數,使用用戶提供的比較函數從hana :: tuple中移除重複項。我面臨的問題與使用hana::type_c將類型存儲爲對象有關。以下是我有統一的方式來刪除使用助推hana的類型列表重複

#include <boost/hana/equal.hpp> 
#include <boost/hana/tuple.hpp> 
#include <boost/hana/unpack.hpp> 
#include <boost/hana/pair.hpp> 
#include <boost/hana/any_of.hpp> 
#include <boost/hana/second.hpp> 
#include <boost/hana/fold.hpp> 
#include <boost/hana/core/make.hpp> 
#include <boost/hana/core/tag_of.hpp> 

#include <iostream> 

template <class> 
struct what_is; 

namespace hana = boost::hana; 

// simply push back an element to the sequence 
auto push_back = [](auto seq, auto t) { 

    using namespace boost::hana; 
    return unpack(seq, [&](auto&&... element){return make<typename tag_of<decltype(seq)>::type>(element..., t);}); 
}; 

// this is the main function 
auto remove_duplicates = [](auto seq, auto comp) { 

    using namespace boost::hana; 

    auto f = [&](auto state, auto el){ 
     return if_(any_of(state, partial(comp, el)), 
        [=](){return state;}, 
        [=](){return push_back(state, el);})(); 
    }; 

    return fold(seq, make<typename tag_of<decltype(seq)>::type>(), f); 
}; 

// user-defined comparison function 
// elements are considered equal if only second element of pairs are equal 
auto comp_pair = [](auto&& t1, auto&& t2) { 

    using namespace boost::hana; 
    return equal(second(t1), second(t2)); 
}; 


int main() { 

    auto my_tuple1 = hana::tuple_t<int, float, double, int, float>; 
    auto no_dups1 = remove_duplicates(my_tuple1, hana::equal); // this is fine, decltype(no_dups1) -> tuple< type<int>, type<float>, type<double> > 

    auto my_tuple2 = hana::tuple_t< hana::pair<int, int>, hana::pair<float, int>, hana::pair<float, float> >; 
// auto no_dups2 = remove_duplicates(my_tuple2, comp_pair); // what I want here is tuple< type<pair<int, int>>, type<pair<float, float>> > 
} 

最後一行產生的問題有從hana::type<pair<X,Y>>提取沒有第二個元素。爲了這個工作,我將不得不創建一個非常難看的序列,如tuple< pair<type<int>, type<int>>, pair<type<double>, type<int>>, pair<type<float>, type<double>> >。正如你可以想象的那樣,這可能會很快變壞,例如,如果我有一個序列tuple<int, pair<X,Y>, double, float>等等。有什麼辦法可以創建一個統一的方式來處理這個問題嗎?我來自MPL /融合背景,我可以直接使用這些類型而不需要包裝類型。謝謝

回答

2

與Fusion不同,Hana不會隱式地將值轉換爲類型。一般來說,這很好,因爲這意味着你可以使用更具表現力的值語法。另一方面,對於一些真正想要提取包裝類型的用例,您必須使用Hana明確執行此操作,而Fusion則爲您提供底層操作。

我看到兩個選項,你想要實現的。第一個解決方案是改變你的comp_pair功能,使得它解開了對自身:

template <typename T1, typename U1, typename T2, typename U2> 
constexpr auto comp_pair(hana::basic_type<hana::pair<T1, U1>>, 
         hana::basic_type<hana::pair<T2, U2>>) 
{ 
    return hana::type_c<U1> == hana::type_c<U2>; 
} 

... 

auto no_dups2 = remove_duplicates(my_tuple2, [](auto pair1, auto pair2) { 
    return comp_pair(pair1, pair2); 
}); 

第二個解決方案,我覺得這更地道,是實際持有你的類型爲對象:

// This could arguably be part of Hana, just like we provide tuple_t 
template <typename T, typename U> 
constexpr auto pair_t = hana::make_pair(hana::type_c<T>, hana::type_c<U>); 

auto tuple2 = hana::make_tuple(pair_t<int, int>, pair_t<double, int>, pair_t<float, double>); 
auto nodups2 = remove_duplicates(tuple2, [](auto p1, auto p2) { 
    return hana::second(p1) == hana::second(p2); 
}); 

但是,你說:

正如你可以想像,如果我有一個序列tuple<int, pair<X,Y>, double, float>等。這能夠生長不好的真的很快,比如有什麼辦法,我可以創造一個統一的方式去有這個?

我不確定我在這裏。你是說你可能想要像tuple<type<int>, pair<type<X>, type<Y>>, type<double>, type<float>>這樣的東西,並且正在尋找一種達到此目的的通用方式?如果是這樣,那麼我必須說,我高度懷疑有一個更好的方法來實現你想要做的任何事情。如果您提供更多上下文,我可以嘗試提供幫助。

希望這會有所幫助!

+0

謝謝,這是做到了。通過統一,我的意思是我希望我的'remove_duplicates'函數假定元組中的所有元素都被''類型包裝。現在,這對'my_tuple1'很好,但對'my_tuple2'沒有用,它必須以與'元組,類型> ...>一樣的完全不同的方式進行包裝''(注意,沒有'type'包裝' pair's)。我認爲按照你的方式創建'comp_pair'函數給了我一般的想法,即如何做到這一點。順便謝謝你的圖書館!真棒的東西 – linuxfever