2016-02-07 5 views
4
#include <iostream> 
#include <string> 

class X {}; 

namespace N 
{ 

std::string to_string(X) 
{ 
    return "foo"; 
} 

void foo() 
{ 
    //using std::to_string; // will break the build if uncommented... 
    //using N::to_string; // ...unless this is uncommented as well 
    std::cout << to_string(X()) << std::endl; 
} 

} 

int main() 
{ 
    N::foo(); 
    return 0; 
} 

Либо я наткнулся на одну из многих C++ arcana, которую я не осваиваю, или мне не хватает чего-то очевидного здесь.Как декларация использования уменьшает имена, доступные для поиска без ADL?

Как может using std::to_string, по-видимому, уменьшить набор имен, доступных во время неквалифицированного поиска, только для тех, которые доступны через ADL? Хотя я могу догадаться, проблема может заключаться в том, что to_string(X) объявлен в другом пространстве имен, чем X. Не могу не заметить, что без using std::to_string, N::to_string(X) просто доступен для N::foo() с помощью «обычных», интуитивно понятных правил поиска, к которым я привык.

ответ

5

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

Вы также можете использовать локальную переменную int to_string; в foo. Это также скроет N::to_string.

+0

Справедливо, спасибо. – gd1

+0

Я заметил, однако, что аналогия с объявлением 'int to_string' не * всегда * выполняется: на самом деле' using std :: to_string' не скрывает функцию 'to_string (X)', объявленную в 'X'' пространство имен, которое должно быть найдено из ADL, тогда как 'int to_string' вызовет ошибку компилятора. Аналогия выполняется, если я объявляю 'std :: string to_string (int)', например, в 'foo()'. – gd1

+1

Да, это другой случай. ADL заставит компилятор рассматривать функцию из связанных с ними пространств имен, даже если это не будет видно иначе. Но это не относится к коду в вопросе, так как «X» находится за пределами пространства имен. –