2016-12-04 2 views
0

私はboost :: hanaに慣れようとしています。練習として、ユーザーが提供する比較関数を使ってhana :: tupleから重複を削除する関数を作成したいと思います。私が直面している問題は、タイプをオブジェクトとして格納するためにhana::type_cを使用することに関連しています。ここでは、私がhana::type<pair<X,Y>>から抽出するいかなる2番目の要素は存在しないとして最後の行が問題を作成boostahを使用してタイプリストから重複を削除する一貫した方法

#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>> > 
} 

を持っているものです。これがうまくいくには、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はそれをあなたのために行います。

達成しようとしているものには2つのオプションがあります。最初のソリューションは、それがペア自体をアンラップするように、あなたの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'関数が、タプルのすべての要素が' type 'でラップされていると仮定することを望んでいました。これは 'my_tuple1'ではうまくいきましたが、 'tuple 、type >と全く違う方法でラップしなければならない' my_tuple2'ではうまくいきませんでした。( '' type'は 'ペア)。 'comp_pair'関数を作成したのと同じように、私はこれを一般的なやり方の一般的な考え方にしています。ところでこのライブラリをありがとう!すごいもの – linuxfever

関連する問題