Шаблонно-зависимое разрешение имен не должно находить объявления без связи?

В стандарте C++ [temp.point] написано:

Контекст создания выражения, который зависит от аргументов шаблона, представляет собой набор объявлений с внешней связью, объявленных до момента создания специализации шаблона в том же модуле перевода.

Затем в [temp.dep.candidate]:

Для части поиска с использованием связанных пространств имен ([basic.lookup.argdep]) обнаруживаются только объявления функций, найденные либо в контексте определения шаблона, либо в контексте создания экземпляра шаблона.

Означает ли это, что следующий код должен дать сбой:

namespace A{
    struct S{};
}

template<class T>
void g(T a){
    f(a); //f will be found by argument dependent lookup
}

namespace A{
    static void f(S); //but f doesn't have external linkage
}

void test(A::S i){
    g(i);
}
//point of instantiation of g
//A::f(S) doesn't have external linkage 
//=> so it's not in the instantiation context of template g ??

Этот код на самом деле компилируется, так что означает этот стандартный абзац?

1 ответ

Решение

Это дефект в стандарте. Первоначально рассмотрены в основной проблеме 561, где комитет решил, что

Примечания от апрельской встречи 2006 года:

Группа пришла к согласию [...], что функции внутренней связи должны быть найдены при поиске (хотя они могут привести к ошибкам, если они выбраны разрешением перегрузки).

К сожалению, соответствующее исправление было недостаточным, как описано в основной проблеме 1258:

C++ 11 расширил правила поиска для вызовов зависимых функций (17.7.4.2 [temp.dep.candidate] параграф 1 bullet 2), чтобы включить функции с внутренней связью; ранее рассматривались только функции с внешней связью. Однако в пункте 6 пункта 17.7.4.1 [temp.point] все еще говорится:

Контекст создания выражения, который зависит от аргументов шаблона, представляет собой набор объявлений с внешней связью, объявленных до момента создания специализации шаблона в том же модуле перевода.

Предположительно эта формулировка была упущена из виду и должна быть приведена в соответствие с новой спецификацией.

То есть предыдущая формулировка вашего второго цитируемого абзаца была

Для части поиска, использующей связанные пространства имен (3.4.2), найдены только объявления функций с внешней связью, найденные либо в контексте определения шаблона, либо в контексте создания шаблона.

... который был изменен для C++11, но это изменение пропустило вашу первую цитату, что сделало его довольно бессмысленным. Смысл в том, что функции с внутренней связью не различаются.

Другие вопросы по тегам