6

Вот пример:Аргумент-зависимый поиск и шаблоны функций

#include <string> 
#include <algorithm> 
#include <memory> 

using std::string; 

int main() 
{ 
    string str = "This is a string"; 

    // ok: needn't using declaration, ADL works 
    auto it = find(str.begin(), str.end(), 'i'); 

    // error: why ADL doesn't work? 
    std::shared_ptr<string> sp = make_shared<string>(str); 
} 

Когда я пытался скомпилировать эту программу, компилятор жаловался:

error: no template named 'make_shared'; did you mean 'std::make_shared'? 
     std::shared_ptr<string> sp = make_shared<string>(str); // error... 
            ^~~~~~~~~~~ 
            std::make_shared 

Я предполагаю, что первая функция find не делает требуется using декларация из-за зависимого от аргумента поиска (ADL): компилятор будет искать пространство имен, где string проживает (т.е. std) для определения find. Но для второй функции make_shared, кажется, что ADL не работает: вместо этого я должен использовать декларацию или using. Я знаю, что определения двух шаблонов функций различны: первый принимает один из своих шаблонных параметров (typename T или что-то в этом роде) как тип параметра функции и возвращает тот же тип. Последний принимает пакет параметров функции как параметр функции, а его возвращаемый тип является другим параметром шаблона. Разница в том, что отключает ADL? Или вы могли бы ответить на вопрос и предложить некоторые рекомендации?

+1

Первое использование - хрупкое. Вы полагаетесь на неопределенное обстоятельство, что тип итератора живет в 'std'. Если в другой день тип итератора будет 'const char *', он не будет компилироваться. –

+0

Я знаю, что это хрупкий способ пропустить объявление 'using'. Точно так же, как сравнение со вторым> _ <|||. – chihyang

+0

@chihyang: Лучшим примером будет 'begin (str)'. – Jarod42

ответ

1

Аргумент-зависимый поиск работает для неквалифицированных выражений вызова функций. Это справедливо для «нормальных» функций так же, как и для специализированных шаблонов функций.

Однако, если вы предоставите явный параметр шаблона для функции шаблона, то выражение не синтаксический выглядит как вызов функции:

foo<3>(x) // "foo less than three?" 

Вот почему эти случаи не вызывают ADL. Однако, как только имя будет известным, чтобы стать шаблоном, ADL действительно применяется!

template <int> void foo(); 

foo<double, 5, T>(x); // uses ADL 
+0

[demo] (https://ideone.com/SKc0Sh) –

+0

Ну ... Я пробовал в вашем ответе, и все получилось отлично! Но это действительно странно: объявите еще один шаблон функции, который мы никогда не будем использовать, чтобы уведомить компилятор, имя, которое мы используем, является шаблоном! Почему ADL так странно? На C++ Primer требуется менее 3 страниц. Но теперь это похоже на огромную ловушку! – chihyang

+0

@chihyang: Да. Но я надеюсь, что со временем вы обнаружите, что это обычное дело не в реальных приложениях. –

0

Методы шаблонов не используют ADL, когда явным образом указываю его аргумент шаблона с <>, за исключением случаев, когда в сфере видимости (с тем же именем) существует видимый метод шаблона.

+0

Не совсем. Во-первых, это относится только к вызовам функций с явно заданными параметрами шаблона. Во-вторых, если у вас также есть другой шаблон функции в области, ADL действительно применяется. Ограничение по существу является синтаксическим, а не глубоким: без существующего объявления выражение вызова не синтаксически выглядит как вызов функции. –

+0

@ KerrekSB: Действительно. перефразировать. – Jarod42