2017-03-10 6 views
1

fooに基づいてvector<foo>からユニークな要素を取得したいと考えています。 boost::adaptors::transformを使用してメンバーを選択し、次にソートしてからboost::adaptors::uniqueを使用しています。並べ替えの手順がうまくいかない。今度はuniqueを呼び出す以外は、Coliruで以下のコードを試してみました。私はどのようにboost :: range :: sort()boost :: transformed_rangeですか?

#include <iostream> 
#include <string> 
#include <vector> 
#include <boost/range/adaptor/transformed.hpp> 
#include <boost/range/algorithm/sort.hpp> 

struct foo 
{ 
    foo(std::string a) : bar(a) {} 

    std::string bar; 
    bool operator<(const foo& rhs) const {return bar < rhs.bar;} 
}; 

int main() 
{ 
    std::vector<foo> words = { foo("z"), foo("d"), foo("b"), foo("c") }; 

    #if 1 
    { 
     auto asString = boost::adaptors::transform(words, +[](const foo& x) {return x.bar;}); 
     auto sortedStrings = boost::range::sort(asString); 
     for (const auto& el : sortedStrings) 
      std::cout << el << std::endl; 
    } 
    #else 
    { 
     auto asString = boost::adaptors::transform(words, +[](const foo& x) {return x.bar;}); 
     std::sort(asString.begin().base(), asString.end().base()); 
     for (const auto& el : asString) 
      std::cout << el << std::endl; 
    } 

    { 
     auto sortedStrings = boost::range::sort(words); 
     for (const auto& el : sortedStrings) 
      std::cout << el.bar << std::endl; 
    } 
    #endif 


    return 0; 
} 

#if部が動作しない:ベースイテレータ型とstd::sort一方

In file included from /usr/local/include/c++/6.3.0/bits/char_traits.h:39:0, 
       from /usr/local/include/c++/6.3.0/ios:40, 
       from /usr/local/include/c++/6.3.0/ostream:38, 
       from /usr/local/include/c++/6.3.0/iostream:39, 
       from main.cpp:1: 
/usr/local/include/c++/6.3.0/bits/stl_algobase.h: In instantiation of 'void std::iter_swap(_ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = boost::iterators::transform_iterator<std::__cxx11::basic_string<char> (*)(const foo&), __gnu_cxx::__normal_iterator<foo*, std::vector<foo> >, boost::iterators::use_default, boost::iterators::use_default>; _ForwardIterator2 = boost::iterators::transform_iterator<std::__cxx11::basic_string<char> (*)(const foo&), __gnu_cxx::__normal_iterator<foo*, std::vector<foo> >, boost::iterators::use_default, boost::iterators::use_default>]': 
/usr/local/include/c++/6.3.0/bits/stl_algo.h:84:20: required from 'void std::__move_median_to_first(_Iterator, _Iterator, _Iterator, _Iterator, _Compare) [with _Iterator = boost::iterators::transform_iterator<std::__cxx11::basic_string<char> (*)(const foo&), __gnu_cxx::__normal_iterator<foo*, std::vector<foo> >, boost::iterators::use_default, boost::iterators::use_default>; _Compare = __gnu_cxx::__ops::_Iter_less_iter]' 
/usr/local/include/c++/6.3.0/bits/stl_algo.h:1918:34: required from '_RandomAccessIterator std::__unguarded_partition_pivot(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = boost::iterators::transform_iterator<std::__cxx11::basic_string<char> (*)(const foo&), __gnu_cxx::__normal_iterator<foo*, std::vector<foo> >, boost::iterators::use_default, boost::iterators::use_default>; _Compare = __gnu_cxx::__ops::_Iter_less_iter]' 
/usr/local/include/c++/6.3.0/bits/stl_algo.h:1950:38: required from 'void std::__introsort_loop(_RandomAccessIterator, _RandomAccessIterator, _Size, _Compare) [with _RandomAccessIterator = boost::iterators::transform_iterator<std::__cxx11::basic_string<char> (*)(const foo&), __gnu_cxx::__normal_iterator<foo*, std::vector<foo> >, boost::iterators::use_default, boost::iterators::use_default>; _Size = long int; _Compare = __gnu_cxx::__ops::_Iter_less_iter]' 
/usr/local/include/c++/6.3.0/bits/stl_algo.h:1965:25: required from 'void std::__sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = boost::iterators::transform_iterator<std::__cxx11::basic_string<char> (*)(const foo&), __gnu_cxx::__normal_iterator<foo*, std::vector<foo> >, boost::iterators::use_default, boost::iterators::use_default>; _Compare = __gnu_cxx::__ops::_Iter_less_iter]' 
/usr/local/include/c++/6.3.0/bits/stl_algo.h:4707:18: required from 'void std::sort(_RAIter, _RAIter) [with _RAIter = boost::iterators::transform_iterator<std::__cxx11::basic_string<char> (*)(const foo&), __gnu_cxx::__normal_iterator<foo*, std::vector<foo> >, boost::iterators::use_default, boost::iterators::use_default>]' 
/usr/local/include/boost/range/algorithm/sort.hpp:33:14: required from 'RandomAccessRange& boost::range::sort(RandomAccessRange&) [with RandomAccessRange = boost::range_detail::transformed_range<std::__cxx11::basic_string<char> (*)(const foo&), std::vector<foo> >]' 
main.cpp:27:57: required from here 
/usr/local/include/c++/6.3.0/bits/stl_algobase.h:148:11: error: no matching function for call to 'swap(boost::iterators::detail::iterator_facade_base<boost::iterators::transform_iterator<std::__cxx11::basic_string<char> (*)(const foo&), __gnu_cxx::__normal_iterator<foo*, std::vector<foo> >, boost::iterators::use_default, boost::iterators::use_default>, std::__cxx11::basic_string<char>, boost::iterators::random_access_traversal_tag, std::__cxx11::basic_string<char>, long int, false, false>::reference, boost::iterators::detail::iterator_facade_base<boost::iterators::transform_iterator<std::__cxx11::basic_string<char> (*)(const foo&), __gnu_cxx::__normal_iterator<foo*, std::vector<foo> >, boost::iterators::use_default, boost::iterators::use_default>, std::__cxx11::basic_string<char>, boost::iterators::random_access_traversal_tag, std::__cxx11::basic_string<char>, long int, false, false>::reference)' 
     swap(*__a, *__b); 

#elseセクションでは、作業を行います。なぜか分からない。私の実際のユースケースでは、boost::adaptors::indirectboost::adaptors::filterも使用しています(ソートを行う前にフィルタリングを行うか、少なくともそのようにして、それがどのように実行されるかを確認することをお勧めします)。変換を行う前にラムダ述語でwordsをソートする。

+0

'boost :: swap(* asString.begin()、* asString.begin());'が失敗しました。 – Jarod42

+0

できません。ソートにはランダムアクセスが必要です。 – sehe

+0

@sehe transform()ドキュメントでは、取得するのと同じ範囲の型を返すと主張しているため、ランダムアクセスでなければなりません。 –

答えて

2

問題は、スワップできない一時的な文字列のビューがあることです。次であなたのコードを修正することがあります。

auto asString = boost::adaptors::transform(words, +[](foo& x) -> std::string& {return x.bar;}); 

Demo

ことで、あなたは直接文字列を並べ替えることに注意してください、とないクラスを。

+0

ああ、それは 'const foo&x'が' bar'への非const参照を返すことができないことを意味します。明示的な 'std :: string&'は必要ですか?それはデフォルトで値によって返されますか?私の実際のユースケースでは、別の理由でconstの問題を発見しました。私の本当の使用例は、イテレータのベクトルに対して 'boost :: adapters :: unique'をセットしてというセットにすることです。もちろん、セット内の文字列を入れ替えられないので、' .base() 'アプローチで仕事はありません。今度はiteratorsのコピーをsort/uniqueで取ります。 –

+0

@MattChambers: 'sort'にはランダムアクセッサーのイテレータも必要なので、' filter'や 'unique'ビューでは使用できません。 – Jarod42

+0

これはすごいですが、人々が必要とするものである可能性は非常に低いです:http://coliru.stacked-crooked.com/a/31653bbd316a795b – sehe

関連する問題