Je veux obtenir les éléments uniques d'un vector<foo>
basé sur un membre de foo
. J'utilise boost::adaptors::transform
pour sélectionner le membre, puis le tri, puis en utilisant boost::adaptors::unique
. J'ai du mal à faire marcher le tri. Laissant de côté l'appel unique
pour l'instant, j'ai essayé le code ci-dessous sur .Comment boost :: range :: sort() un boost :: processed_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;
}
La section #if
ne fonctionne pas:
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);
Alors que le std::sort
avec le type de base iterator dans la section #else
fonctionne. Je ne comprends pas pourquoi. Dans mon cas d'utilisation réel, j'utilise aussi boost::adaptors::indirect
et boost::adaptors::filter
(et je préférerais faire le filtrage avant de faire le tri, ou au moins essayer de le faire et voir comment ça fonctionne), c'est pourquoi je ne suis pas simplement trier words
avec un prédicat lambda avant de faire la transformation.
'boost :: swap (* asString.begin(), * asString.begin());' a échoué. – Jarod42
Vous ne pouvez pas. Le tri nécessite un accès aléatoire. – sehe
@sehe La documentation de transform() prétend qu'elle renvoie le même type de plage que celui qu'elle utilise, donc ce devrait être un accès aléatoire, n'est-ce pas? –