Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't std::sort use my operator< implementation

Why doesn't std::sort use my operator< implementation in this code

#include <iostream>
#include <vector>
#include <tuple>
#include <algorithm>
using namespace std;

bool operator<(
    const tuple<int, int>& t1,
    const tuple<int, int>& t2
) {
    return get<1>(t1) > get<1>(t2);// `>` so that it gets sorted in reverse
}

int main() {
    vector<tuple<int, int>> v;
    for (int i = 0; i < 10; ++i) {
        v.push_back(make_tuple(0, i));
    }
    cout << "before sort: ";
    for (auto& x : v) { cout << get<1>(x) << ", "; }
    cout << endl;

    auto v2 = v;
    sort(v2.begin(), v2.end());
    cout << "after sort(begin, end): ";
    for (auto& x : v2) { cout << get<1>(x) << ", "; }
    cout << endl;

    sort(v.begin(), v.end(), [](auto& t1, auto& t2) {
        return get<1>(t1) > get<1>(t2);// `>` so that it gets sorted in reverse
    });
    cout << "after sort(begin, end, comparator): ";
    for (auto& x : v) { cout << get<1>(x) << ", "; }
    cout << endl;

    return 0;
}

The output is:

before sort: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 
after sort(begin, end): 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 
after sort(begin, end, comparator): 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,

The output I expected is:

before sort: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 
after sort(begin, end): 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 
after sort(begin, end, comparator): 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
like image 440
nawfel bgh Avatar asked Apr 10 '16 22:04

nawfel bgh


People also ask

How is std::sort implemented?

The std::sort is a sorting function that uses the Introsort algorithm and have the complexity of O(N log(N)) where N= std::distance(first, last) since C++11 and the order of equal elements is not guaranteed to be preserved[3]. The gcc-libstdc++ also uses Introsort algorithm.

Why does std :: list need a special sort method?

std::sort is a generic algorithm that's supposed to work for anything that provides iterators. However, it really expects a random access iterator to sort efficiently. std::list , being a linked list, cannot provide random access to its elements efficiently. That's why it provides its own specialized sort algorithm.

Why does the std::sort receive a function?

std::sort() is a built-in function in C++'s Standard Template Library. The function takes in a beginning iterator, an ending iterator, and (by default) sorts the iterable in ascending order. The function can also​ be used for custom sorting by passing in a comparator function that returns a boolean.

Can you use std::sort with a list?

std::sort requires random access iterators and so cannot be used with list .


1 Answers

This has to do with how name lookup works in function templates (commonly referred to as two-phase lookup). std::sort is defined in <algorithm>, and the lookup for < will find those names in scope at the point of the template definition (which yours is not) and those names in the associated namespaces of the dependent function arguments (which for std::tuple would be namespace std, which also does not include yours).

Since the arguments in question are in namespace std, it's actually undefined behavior to add your overload into that namespace. So your options are to either stick with the default behavior (which would be lexicographical <) or to provide your own custom comparator (as you do in your question).

like image 172
Barry Avatar answered Nov 03 '22 00:11

Barry