3.4.2 Поиск имени, зависящего от аргумента, из черновика n3290

#c #c 11 #argument-dependent-lookup #name-lookup

#c #c 11 #поиск, зависящий от аргумента #поиск имени

Вопрос:

Точка из проекта ISO n3290, раздел 3.4.2, параграф 1:

Когда постфиксное выражение в вызове функции является неквалифицированным идентификатором, может выполняться поиск в других пространствах имен, не учитываемых при обычном неквалифицированном поиске, и в этих пространствах имен могут быть найдены объявления дружественных функций области имен, которые иначе не видны. Эти изменения в поиске зависят от типов аргументов (а для аргументов шаблона template — от пространства имен аргумента шаблона).

Здесь они сказали о том, что «эти изменения в поиске зависят от типов аргументов / аргументов шаблона шаблона / пространства имен аргумента шаблона » …Может ли кто-нибудь привести пример, пожалуйста? Я пробовал с типами argumetn..пожалуйста, расширяйте с использованием типов аргументов шаблона и пространства имен типа аргумента шаблона

Ответ №1:

Рассмотрим простой неквалифицированный вызов функции:

 foo(x);
  

ADL означает, что foo выполняется поиск не только во включающей области видимости и пространстве имен, в котором находится вызов, но также в пространстве имен типа x . например, если x является std::vector<int> , то также выполняется поиск в пространстве имен std . Таким образом:

 int main() {
    std::vector<int> x,y;
    swap(x,y);
}
  

все в порядке, и он будет вызван std::swap() .

Поиск также зависит от пространства имен любых аргументов шаблона, поэтому, если x есть std::vector<mynamespace::myclass> , то mynamespace также включается в поиск. Таким образом

 namespace mynamespace {
    struct myclass {};
    void foo(std::vector<mynamespace::myclass> constamp;){}
}

int main() {
    std::vector<mynamespace::myclass> x;
    foo(x);
}
  

вызовет mynamespace::foo() .

Наконец, поиск также распространяется на пространства имен любых шаблонов, используемых в качестве параметров шаблона. например

 namespace mynamespace {
    template<typename T>
    struct mytemplate
    {};

    template<typename T>
    void bar(T constamp;) {}
}

template<template<typename> class T>
struct wrapper {};

int main() {
    wrapper<mynamespace::mytemplate> x;
    bar(x);
}
  

Даже несмотря на то, что wrapper оно находится в глобальном пространстве имен, mynamespace::bar будет найдено, потому что параметр шаблона шаблона, используемый для x является mynamespace::mytemplate .