Reputation: 5097
I was reading Stroustrup's blog on c++ (http://isocpp.org/blog/2014/12/myths-3) when I found an intersting piece of code:
void do_my_sort(vector<double>& v)
{
sort(v,[](double x, double y) { return x>y; }); // sort v in decreasing order
}
int main()
{
vector<double> vd;
// ... fill vd ...
do_my_sort(v);
// ...
}
Notice that the sort
does not use the traditional sort(v.begin(), v.end(), ...)
which Stroustrup explains:
I used a container version of
sort()
to avoid being explicit about the iterators.
However, I tried the same code on my C++11 compiler but it fails to compile. I also tried the same on a C++14 compiler using ideone but it too fails to compile, saying that there is no matching call to sort.
Why is this?
Also, Stroustrup next mentions:
I could go further and use a C++14 comparison object:
sort(v,greater<>()); // sort v in decreasing order
I have used comparators like great<>()
for sort
in C++11 also. Why is he stating that this is a C++14 comparison object?
Upvotes: 5
Views: 398
Reputation: 39633
Bjarne explains what this sort()
is in the blog:
I used a container version of
sort()
to avoid being explicit about the iterators. That is, to avoid having to write:std::sort(v.begin(), v.end(), [](double x, double y) { return x > y; });
Nowadays, C++20 has std::ranges::sort
to offer, which can do this as well:
std::vector<double> vd{ /* ... */ };
std::ranges::sort(vd);
// equivalent to ...
std::ranges::sort(vd.begin(), vd.end());
Note that this solution works for all ranges, such as std::array
, std::span
, std::vector
, etc.
A way to imitate it in C++14 would be:
// std::less<void> can be implemented in C++11 too
template <class Container, class Comp = std::less<void>>
void sort(Container&& cont, Comp comp = {}) {
using std::begin;
using std::end;
std::sort(begin(cont), end(cont), std::move(comp));
}
Note: this is very similar to @BaummitAugen's solution, however, it takes a forwarding reference to allow sorting containers which are not passed as lvalues.
Note: calling std::sort
with cont.begin()
and cont.end()
would not work if Container
is an array.
Upvotes: 1
Reputation: 96810
I have used comparators like
great<>()
for sort in C++11 also. Why is he stating that this is a C++14 comparison object?
The C++14 comparison functors have the added ability to take forwarding references for its operator()
method and deduced return types. The template argument for the Function Objects collection has been changed to have a default argument of type void
and using specialization for that type.
template< class T = void >
struct greater
{
constexpr bool operator()(const T &lhs, const T &rhs) const;
};
template<>
struct greater<void>
{
template< class T, class U>
constexpr auto operator()( T&& lhs, U&& rhs ) const
-> decltype(std::forward<T>(lhs) > std::forward<U>(rhs));
};
Upvotes: 4
Reputation: 50053
He wrote that himself, it is not standard. Thus you cannot find it in the standard library. You could implement it like this:
template <class Container, class Comp>
void sort (Container& cont, Comp comp) {
using std::begin;
using std::end;
std::sort(begin(cont), end(cont), comp);
}
As Clukester pointed out, there is also boost::sort that offers this functionality.
Upvotes: 10
Reputation: 132
Perhaps he is using Boost's sort, not the standard sort as one would expect. So it's boost::sort
, not std::sort
.
Upvotes: 1