1

why it works only if the second argument is greater than 3. And how can I fix it? if I do the same with copy_if it works! Task: Examine the effect of the functor std :: bind. Try using it to form the conditions of the standard functor std :: greater ( module).

#include <set>
#include <algorithm>
#include <iostream>
#include <vector>
#include <list>
#include <map>
#include <iterator>
#include <string>
#include <functional>
using namespace std;

template<typename T>
static void PrintVector(const std::vector<T> &v)
{
    for (auto iterator = v.begin(); iterator != v.end(); ++iterator)
    {
        std::cout << *iterator << " ";
    }
    std::cout << std::endl;
}

int main()
{
    std::cout << "Task_3: greater with std::bind\n";
    ostream_iterator<int> out_it(cout, " ");
    vector<int> v = { 1, 8, 7, 4, 3, 6, 2, 5 };
    PrintVector(v);
    auto greater_binded = bind(greater<int>(), placeholders::_1, 3);
    sort(v.begin(), v.end(), greater_binded);
    PrintVector(v);
    return 0;
}
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • 3
    `sort` does comparisons between two elements at a time. Doesn't make sens to use `bind` here at all. You should just be using `greater` – NathanOliver Feb 16 '17 at 15:28

2 Answers2

1

As stated in documentation for std::copy_if it expects unary predicate ie function with one argument, on another side std::sort needs compare function, that must meet requirement of Compare concept. So is is completely unclear why you expect the same function used for std::copy_if work with std::sort.

And how can I fix it?

Just pass std::greater<int> without binding second argument to constant. If you do need to use std::bind you can just pass both arguments:

auto greater_binded = bind(greater<int>(), placeholders::_1, placeholders::_2);

but that would have the same effect as passing greater<int>() directly.

Slava
  • 43,454
  • 1
  • 47
  • 90
0

sort's comparator requirement is:

Comparison function object (i.e. an object that satisfies the requirements of Compare) which returns ​true if the first argument is less than (i.e. is ordered before) the second

The greater functor takes 2 arguments, but you are using bind to make it into a functor that takes 1 argument and compares it to 3. This no longer satisfies sort's requirement.

If you're trying to move all the elements that are greater than 3 to the front of v you could use partition with greater_binded. Calling partition(begin(v), end(v), greater_binded) results in:

5 8 7 4 6 3 2 1

You could also go further using the return of partition which is an:

Iterator to the first element of the second group

Using that to sort or reverse-sort the 1st or 2nd groups with sort.

Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
  • @АсяФилатова 3 instead of 7 where? In `v`? As in: `vector v = { 1, 8, 3, 4, 3, 6, 2, 5 };`? Are you saying `partition` doesn't work with that? Cause [it gives me](http://ideone.com/Kuhnv1) "5 8 6 4 3 3 2 1", exactly as I'd expect. – Jonathan Mee Feb 16 '17 at 18:38
  • @ Jonathan Mee there partition(begin(v), end(v), bind(greater(), placeholders::_1, 7)); – Ася Филатова Feb 16 '17 at 18:41
  • @АсяФилатова I suspect that you're saying `partition(begin(v), end(v), bind(greater(), placeholders::_1, 7))` doesn't work because [it gives you](http://ideone.com/cz4GBW): "8 1 7 4 3 6 2 5" Which is in fact correct by the definition of `partition` which states: "Reorders the elements in the range [`first`, `last`) in such a way that all elements for which the predicate `p` returns `true` precede the elements for which predicate `p` returns `false`." Since `7` is not greater than `7` `greater_binded` will return `false`. You seem to be seeking the `greater_equal` functor. – Jonathan Mee Feb 16 '17 at 18:59
  • @ Jonathan Mee my question is why 8 and 1 stand before 7 if 1 <7 – Ася Филатова Feb 16 '17 at 19:07
  • @АсяФилатова Because the only `8` returns `true` for the predicate (which is greater than 7). So it is moved into the first group, everything else goes in the second group. Which happens to have `1` as the first element. Again `partition`, by definition: "Reorders the elements in the range [`first`, `last`) in such a way that all elements for which the predicate `p` returns `true` precede the elements for which predicate `p` returns `false`. Relative order of the elements is not preserved." As stated in the answer if you need to sort either of those groups use the iterator `partition` returns. – Jonathan Mee Feb 16 '17 at 19:41