2016-12-29 2 views
6
void f() {} 

namespace test 
{ 
void f(int) {}  
void g() { f(); } // error in gcc 6.2.0 
} 

int main() 
{ 
    test::g(); 
} 

Собирать с г ++ -std = C++ 1z main.cpp, выход заключается в следующем:Почему gcc скрывает перегруженные функции в глобальном пространстве имен?

main.cpp: In function 'void test::g()': 
main.cpp:9:4: error: too few arguments to function 'void test::f(int)' 
    f(); // error in gcc 
    ^
main.cpp:5:6: note: declared here 
void f(int) {} 

Мой компилятор GCC 6.2.0.

Почему gcc скрывает перегруженные функции в глобальном пространстве имен? Соответствует ли это стандарту C++?

ответ

12

Почему gcc скрывает перегруженные функции в глобальном пространстве имен? Соответствует ли это стандартам C++?

Да. Короче говоря, вы не можете перегружать функции через разные области. Согласно правилу unqualified name lookup, для вызова f() в g() имя f может быть найдено внутри пространства имен test, после чего поиск имени прекращается; overload resolution происходит после этого (на основании найденных названий). Это означает, что f() в глобальном пространстве имен вообще не рассматривается, даже если он выглядит более уместным.

(курсив мой)

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

Для того, чтобы скомпилировать вызов функции, компилятор должен сначала выполнить поиск имени, которое, для функций, может привлечь аргумент-зависимого поиска, и для шаблонов функций может сопровождаться шаблон аргумента дедукцией. Если эти шаги производят более одного кандидата , то выполняется разрешение перегрузки, чтобы выбрать функцию , которая будет фактически вызвана.

Вы можете использовать using ввести имена в том же объеме, т.е., чтобы сделать их фактические перегруженные функции.

namespace test 
{ 
    using ::f;  // introduce the name from global namespace 
    void f(int) {}  
    void g() { f(); } // fine 
} 
+2

TL; др: это известная C++, галтель, и по той же причине, что [ «перегруженных» в производном классе вариантов скрытия в базовом классе] (http://stackoverflow.com/q/1628768/560648), требуя 'using Base :: foo' при некоторых обстоятельствах. –

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