Разрешение перегрузки во вложенном пространстве имен с родительским пространством имен - PullRequest
3 голосов
/ 04 августа 2020

Я думал, что во вложенном пространстве имен все, что является частью родительского (или глобального) пространства имен, одинаково рассматривается для разрешения перегрузки, но этот пример, похоже, показывает иное.

Это отлично работает:

#include <iostream>

void foo(int) { std::cout << "int\n"; }
void foo(float) { std::cout << "float\n"; }

namespace NS {
    void bar() {
        foo(0);
    }
}

int main() {
    NS::bar();
}

Вызов foo(0) соответствует foo(int), так как это лучший вариант, и все работает, как ожидалось. Однако, если я перенесу объявление foo(float) в пространство имен:

#include <iostream>

void foo(int) { std::cout << "int\n"; }

namespace NS {
    void foo(float) { std::cout << "float\n"; }
    void bar() {
        foo(0);
    }
}

int main() {
    NS::bar();
}

Теперь вызов foo(0) вызывает foo(float)!

Я искал через https://en.cppreference.com/w/cpp/language/overload_resolution и многие другие подобные страницы, чтобы найти правило, объясняющее это, но мне кажется, что я его упускаю. Может кто-нибудь объяснить, какое из многих сложных правил разрешения перегрузки вызывает это, или это что-то еще?

EDIT Я только что обнаружил, что это еще более странно. Даже если foo внутри пространства имен совсем не соответствует , он все равно не будет использовать его снаружи. Это просто полностью не компилируется:

#include <iostream>

void foo(int) { std::cout << "int\n"; }

namespace NS {
    void foo(float, float) { std::cout << "float\n"; }
    void bar() {
        foo(0);
    }
}

int main() {
    NS::bar();
}

1 Ответ

7 голосов
/ 04 августа 2020

Речь идет о поиск имени , который происходит до разрешения перегрузки.

Когда имя foo найдено в пространстве имен NS, поиск имени останавливается, дальнейшие области выигрывают не проверяется, глобальный foo вообще не будет найден. Тогда есть только один кандидат в разрешении перегрузки, и int может неявно преобразовать в float, тогда наконец вызывается NS::foo(float).

(выделено мной)

name поиск проверяет области действия, как описано ниже, пока не найдет хотя бы одно объявление любого типа, в это время поиск прекращается и никакие другие области не проверяются .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...