2016-12-04 5 views
0

Я пытаюсь ознакомиться с boost :: hana. В качестве упражнения я хочу создать функцию, которая удалит дубликаты из hana :: tuple, используя предоставленную пользователем функцию сравнения. Проблема, с которой я сталкиваюсь, связана с использованием hana::type_c для хранения типов как объектов. Вот что у меня естьЕдиный способ удаления дубликатов из списка с помощью boost 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/fusion, и там я могу работать непосредственно с типами без необходимости обертывания типов. Спасибо

ответ

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' предполагала, что все элементы в корте завершены« type ». Теперь это отлично работало с 'my_tuple1', но не для' my_tuple2', которое пришлось бы обернуть совсем по-другому как 'tuple , введите > ...> '(обратите внимание, что' '' wrap' pair's). Я думаю, что создание функции 'comp_pair' так, как вы делали, дает мне общее представление о том, как это сделать в целом. Спасибо за эту библиотеку кстати! Удивительный материал – linuxfever

 Смежные вопросы

  • Нет связанных вопросов^_^