Функции с аргументами класса просочились из пространства имен? - PullRequest
22 голосов
/ 03 февраля 2011

У меня есть небольшой кусочек кода для вашего рассмотрения, который меня довольно озадачивает. Странно то, что он компилируется как в Sun Studio, так и в GCC, хотя я думаю, что не должен.

Учтите это:

namespace name
{
  class C
    {
      int a;
    };

  void f(C c);
  void g(int a);
}

int main(int argc, char** argv)
{
  name::C c;

  name::f(c); 
  f(c);  // <--- this compiles, strangely enough

  name::g(42);
  // g(42);  <--- this does not, as I expected
}

Аргумент класса из того же пространства имен заставляет функцию f "вытекать" из пространства имен и быть доступной без name::.

У кого-нибудь есть объяснение этому? Это, конечно, я, а не компилятор, который ошибается здесь.

Ответы [ 4 ]

29 голосов
/ 03 февраля 2011

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

12 голосов
/ 03 февраля 2011

Это Поиск имени в зависимости от аргумента , a.k.a. ADL, a.k.a. Поиск Кенига. Это было изобретено для того, чтобы операторы работали должным образом, например ::1003 *

namespace fu {
    struct bar { int i; };
    inline std::ostream& operator<<( std::ostream& o, const bar& b ) {
        return o << "fu::bar " << b.i;
    }
}

fu::bar b;
b.i = 42;
std::cout << b << std::endl; // works via ADL magic

Без ADL вам пришлось бы либо явно привести оператор вывода с уродливым using fu::operator<<;, либо использовать еще более страшный явный вызов:

fu::operator<<( std::cout, b ) << std::endl;
7 голосов
/ 03 февраля 2011

Это связано с «поиском, зависящим от аргумента». Удаление const не изменит поведение, которое вы видите. Чтобы продемонстрировать, что это ADL, попробуйте переместить структуру St за пределы пространства имен ...

struct St
{
   int a;
};

namespace name
{
  void f(const St& st);
  void g(int a);
}

int main(int argc, char** argv)
{
  St st;

  name::f(st); 
  f(st);  // <--- now you will get the expected compile error

  name::g(42);
  // g(42);  <--- this does not, as I expected
}
1 голос
/ 03 февраля 2011

Это вызвано зависимым от аргумента поиском .

...