Использование std:: sort() без префикса "std", а также без "использования пространства имен std;" успешно компилируется
Как sort()
определяется в namespace std
, он всегда должен использоваться как std::sort
. Но следующий код компилируется правильно даже без std
.
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> nums = {4,3,1,7,2,0};
sort(nums.begin(),nums.end());
}
ideone.com
Но этот код не работает.
#include <array>
#include <algorithm>
int main()
{
std::array<int,5> nums = {4,1,8,9,6};
sort(nums.begin(),nums.end());
}
Использование gcc 4.8.4
с флагом -std=c++11
.
Из обоих этих фрагментов кода ясно, что std::vector
имеет какое-то отношение к этому. Но я не могу понять это.
Ответы
Ответ 1
Это зависимый от аргументов поиск. Если вы используете typeid
для изучения типов задействованных итераторов:
#include <iostream>
#include <typeinfo>
#include <vector>
#include <array>
int main() {
std::cout << typeid(std::vector<int>::iterator).name() << '\n';
std::cout << typeid(std::array<int, 5>::iterator).name() << std::endl;
return 0;
}
по крайней мере на Ideone, вы получите следующий результат:
N9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEE
Pi
С помощью справки Revolver_Ocelot в комментариях мы видим, что эти типы __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >
и int*
.
Для вектора, после неудачного поиска обычного имени, компилятор ищет пространства имен __gnu_cxx
и std
для функции sort
, __gnu_cxx
, потому что это пространство имен __gnu_cxx::normal_iterator
и std
, потому что оно пространство имен одного из аргументов шаблона, std::vector<int, std::allocator<int> >
. Он находит std::sort
.
Для std::array
итераторы - это всего лишь int*
s, поэтому зависящий от аргументов поиск не ищет дополнительных пространств имен и не находит функцию sort
.
Ответ 2
Это зависимый от аргумента поиск. Согласно Stroustroup Язык программирования С++: 4-е издание, здесь применяются два правила:
1) Если аргумент является членом пространства имен, соответствующие пространства имен являются охватывающими пространствами имен.
2) Если аргумент является встроенным типом, не существует связанных пространств имен.
В первом и втором случаях begin() и end() возвращают итераторы. Однако стандарт С++ определяет итератор как любую переменную любого типа, на которой может выполняться операция итерации. (Иными словами, итератор представляет собой концепцию дизайна, которая применяется через шаблон.)
В соответствии с другим ответом итераторы в первом случае являются переменными типа данных, которые принадлежат к тому же пространству имен, что и sort(). Однако итераторы во втором случае имеют примитивный тип данных. По правилу №2 эти итераторы не имеют связанного пространства имен.