При звонке std::sort()
на 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));
}
И gcc, и clang возвращают ошибку в сортировке std::array
- clang говорит
ошибка: использование необъявленного идентификатора 'sort'; Вы имели в виду 'std :: sort'?
Изменение, чтобы std::sort(begin(foo2), end(foo2))
исправить проблему.
MSVC компилирует код выше, как написано.
Почему разница в лечении между std::vector
а std::array
; а какой компилятор правильный?
sort(...
->std::sort(...
. Я предполагаю, что ADL (поиск, зависящий от аргумента) - это то, что сбивает вас с толку. Это, или руководство по выводу. В любом слючае; всегда уточняйте функции, которые вы вызываете.std::sort
которая приводит к зависимому от аргумента поиску (как у вас уже есть дляstd::begin
иstd::end
)?namespace std
даже там, где работал бы простой тип указателя. Я полагаю, что это вставка проверок отладочной сборки для обнаружения переполнений и других распространенных ошибок.Ответы:
Это сводится к типу, который
begin
иend
результат и как это работает с Argument Dependent Lookup .В
ты получаешь
и так
std::vector<int>::iterator
как членstd
ADL находитsort
вstd
и вызов успешно.С
Ты получаешь
и потому что
int*
не является членомstd
, ADL не будет смотреть,std
и вы не можете найтиstd::sort
.Это работает в MSVC, потому что
становится
и так как
std::_Array_iterator
является частьюstd
ADL находокsort
.Оба компилятора верны с таким поведением.
std::vector
иstd::array
не предъявляют никаких требований к тому, какой тип используется для итератора, за исключением того, что он удовлетворяет требованию LegacyRandomAccessIterator, а в C ++ 17 дляstd::array
этого типа также должен быть LiteralType, а в C ++ 20 - в качестве ConstexprIterator.источник
std::array
итератор или это может быть тип класса? Точно так же было бы уместно ответить на вопрос, должен ли итератор быть типом класса, на котором будет работать ADL, или это также может быть .int*
std::vector
int*
std::iterator
что-то еще или просто указатель.int*
для,std::array
но не дляstd::vector
.std::array
иstd::vector
не определены, то есть реализации допускаются определять их в качестве сырья указателей (код не скомпилируется) или обертки класса типа (код скомпилируется , только если тип класса имеетstd
как ADL связанное пространство имена).std::vector<T>::iterator
это псевдоним.