шаблоны — C ++: использование полностью определенного имени с функцией сортировки — противоречивое поведение

У меня есть следующий код C ++, который вычисляет медиану контейнера, взятого из Accelerated C ++ Кенигом.

median.h

#ifndef GUARD_median_h
#define GUARD_median_h

#include <stdexcept>
#include <algorithm>
#include <cstddef>

template<class T, class Iterator>
T median (Iterator begin, Iterator end)
{
size_t size = end - begin;
if (size == 0)
throw std::domain_error("median of an empty vector");

sort(begin, end);

size_t mid = size/2;

return size%2 == 0 ? (begin[mid] + begin[mid-1])/2 : begin[mid];
}
#endif

median_test.cpp

#include <vector>
#include <iostream>
#include "median.h"
using std::vector;  using std::cin;
using std::cout;    using std::endl;

int main()
{
vector<double> myVec;

cout << "Please enter integers: ";

double val;
while (cin >> val) {
myVec.push_back(val);
}

cout << "The median is: " << median<double>(myVec.begin(), myVec.end()) << endl;

return 0;
}

Этот код компилируется и работает просто отлично. Но если я сделаю небольшую модификацию, чтобы проверить медианную функцию с массивом, а не с вектором, как это …

median_test_array.cpp

#include <iostream>
#include "median.h"
using std::cin;
using std::cout;    using std::endl;

int main()
{
double myVec[1000];

cout << "Please enter integers: ";

double val;
size_t i = 0;
while (cin >> val) {
myVec[i++] = val;
}

cout << "The median is: " << median<double>(myVec, myVec+i) << endl;

return 0;
}

Я получаю следующую ошибку компиляции:

| => g++-6 -I. median_test_array.cpp
In file included from median_test_array.cpp:2:0:
median.h: In instantiation of 'T median(Iterator, Iterator) [with T = double; Iterator = double*]':
median_test_array.cpp:19:60:   required from here
median.h:15:9: error: 'sort' was not declared in this scope
sort(begin, end);
~~~~^~~~~~~~~~~~
median.h:15:9: note: suggested alternative:
In file included from /usr/local/Cellar/gcc/6.2.0/include/c++/6.2.0/algorithm:62:0,
from median.h:5,
from median_test_array.cpp:2:
/usr/local/Cellar/gcc/6.2.0/include/c++/6.2.0/bits/stl_algo.h:4727:5: note:   'std::sort'
sort(_RandomAccessIterator __first, _RandomAccessIterator __last,
^~~~

Эта ошибка исчезнет, ​​если я дам полное имя для сортировки (std :: sort), но я хотел бы знать, почему в этом случае мне нужно полное имя, а не в векторном примере.

2

Решение

Это ADL вопрос.

Для вашего первого примера кода кажется, что реализация объявляет std::vector::iterator как класс внутри пространства имен stdтогда ADL вступает в силу, std::sort находится для вызова с аргументами типа std::vector::iterator,

Для вашего второго примера кода аргумент передается sort просто double*, ADL больше не вступает в силу, то имя sort не может быть найден

Обратите внимание, что такое поведение не гарантируется; стандарт не указывает где std::vector::iterator должен быть реализован, он даже не должен быть классом, поэтому лучше указать спецификатор std::или используйте его с using std::sort;,

1

Другие решения

Первый код был скомпилирован из-за так называемого Argument Dependent Lookup. Как std::vector<double>::iterator принадлежит пространству имен std тогда функция sort был также найден в этом пространстве имен.

Когда вы используете указатели, то нет ADL. Таким образом, компилятор не может найти объявление имени sort,

Используйте полное имя std::sort,

2

По вопросам рекламы [email protected]