Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unqualified sort() -- why does it compile when used on std::vector and not on std::array, and which compiler is correct?

Tags:

c++

c++17

When calling std::sort() on a std::array:

#include <vector>
#include <array>
#include <algorithm>

int main() {
    std::vector<int> foo{4, 1, 2, 3};
    sort(begin(foo), end(foo));

    std::array<int, 4> foo2{4, 1, 2, 3};
    sort(begin(foo2), end(foo2));
}

Both gcc and clang return an error on the sort on the std::array -- clang says

error: use of undeclared identifier 'sort'; did you mean 'std::sort'?

Changing to std::sort(begin(foo2), end(foo2)) fixes the problem.

MSVC compiles the code above as written.

Why the difference in treatment between std::vector and std::array; and which compiler is correct?

like image 671
Guy Middleton Avatar asked Jan 03 '20 18:01

Guy Middleton


1 Answers

This is comes down to the type that begin and end result to and how that works with Argument Dependent Lookup.

In

sort(begin(foo), end(foo));

you get

sort(std::vector<int>::iterator, std::vector<int>::iterator)

and since std::vector<int>::iterator is a member of std ADL finds sort in std and the call succeeds.

With

sort(begin(foo2), end(foo2));

You get

sort(int*, int*)

and because int* is not a member of std, ADL will not look into std and you can't find std::sort.

This works in MSVC because

sort(begin(foo2), end(foo2));

becomes

sort(std::_Array_iterator, std::_Array_iterator)

and since std::_Array_iterator is part of std ADL finds sort.

Both compilers are correct with this behavior. std::vector and std::array don't have any requirement on what type is used for the iterator except that it satisfies the LegacyRandomAccessIterator requirement and in C++ 17 for std::array that the type also be a LiteralType and in C++20 that it be a ConstexprIterator

like image 89
NathanOliver Avatar answered Sep 23 '22 00:09

NathanOliver