2015-05-24 2 views
1

Я реализую алгоритм сортировки как личное обучение (без домашней работы!). У меня есть следующий код (за исключением импорта и т.д.):шаблон программирования: неоднозначный вызов перегруженной функции

 template<class RandomIt, class Compare> 
     void sort(RandomIt first, RandomIt last, Compare comp) 
     { 
      /* actual sorting code is here */ 
     } 

     template<class RandomIt> 
     void sort(RandomIt first, RandomIt last) 
     { 
      std::function<bool(decltype(*first), decltype(*last))> comp = [](decltype(*first) a, decltype(*last) b) 
      { 
       return a < b; 
      }; 

      sort (first, last, comp); 
     } 

Попытка вызвать этот код с помощью тестового массива

auto test_array_1 = std::make_unique <std::array < uint64_t,SORTING_TEST_LENGTH >>(); 
    std::copy(std::cbegin(*template_array), std::cend(*template_array), std::begin(*test_array_1)); 

    sort(std::begin(*test_array_1), std::end(*test_array_1)); 

Компилятор жалуется на «неоднозначной вызове перегруженной функции» (VC++ C2668). По моему мнению, звонок не должен быть неоднозначным. Кроме того, при вызове второй функции сортировки параметры шаблона для первой функции сортировки не имеют никакого эффекта.

Что мне здесь не хватает? Почему компилятор считает второй вызов «неоднозначным»?

+0

Попробуйте дать всю ошибку ... любая помощь с нашей стороны будет просто стрелять в темноте. – Puppy

+1

Это может произойти, если у вас есть '' using namespace foo'' ('' std'' является очевидным виновником '' foo''), который уже имеет '' sort''. –

+0

Интересно, что у меня нет '' 'использования пространства имен std''' в любом месте моего кода (я ненавижу загрязнение пространства имен). –

ответ

6

проблема 2 раз.

Во-первых, sort находится через ADL, поэтому вы получаете две перегрузки, и они оба совпадают. В общем, функции именования такие же, как и функции std, когда вы не пытаетесь перегружать ADL, чревато из-за возможности неоднозначности ADL.

Теперь это происходит только при передаче типов из namespace std; Иногда итераторы из этого пространства имен, но не в этом случае: array использует итераторы raw-указателя. Триггер для определения ADL std::sort - это std::function.

Который подводит меня к следующей проблеме: в приведенном выше коде есть очень мало того, что нужно получить, и многое, что нужно утерять, в std::function. Замените его на auto. Проведите алгоритмы сортировки низкого уровня как встроенный объект сравнения.

Вы по-прежнему не хотите называть его sort. Если вы его назовете sort, вам необходимо квалифицировать вызовы с помощью пространства имен или (sort) для блокировки ADL.

Правило ADL заключается в том, что для разрешения перегрузки рассматриваются как «обычные» функции, так и функции в пространстве имен аргументов, а также пространство имен аргументов и аргументы аргументов аргументов и т. Д. Это зависящий от аргумента поиск, или ADL, или поиск Koenig. Это означает, что загрязнение пространства имен может происходить при использовании типов из другого пространства имен (что печально), но также приводит к некоторой приятной магии (например, std :: cout < < «hello world \ n»; `)

+0

Хорошее объяснение. Просто хочу указать, что выбор имени '' 'sort''' был преднамеренным, так как я хочу придерживаться стандартного интерфейса библиотеки. Я знаю, что стандартная реализация библиотеки будет лучше, но, как уже упоминалось, весь проект - это упражнение для меня, чтобы стать лучше в некоторых аспектах C++. –

Смежные вопросы