Путаница по поводу зависимого от аргумента поиска и определения функции друга

0

У меня есть следующая программа:

struct Foo {
    friend void foo (int) {}
    operator int () const { return 0; }
};

int main() {
    foo(Foo());  // This compiles fine
    foo(0);      // This fails to find 'foo()'
    return 0;
}

Я не мог понять, какая часть стандарта определяет правило ADL, которое говорит, что вызов foo(0) должен завершиться неудачно, а вызов foo(Foo()) должен завершиться успешно. Может кто-то пролил свет?

  • 0
    Вам понятно, почему foo(0) должен потерпеть неудачу, или вы тоже спрашиваете об этом?
  • 0
    @juanchopanza: я спрашиваю об обоих.
Показать ещё 2 комментария
Теги:
c++11
language-lawyer
argument-dependent-lookup

2 ответа

1
Лучший ответ

Открыто за мое собственное удаление, а? Ну, после некоторого побуждения от juanchopanza, я более внимательно прочитал соответствующую часть стандарта С++ 11 §3.4.2. Я просмотрел его слишком быстро раньше. В частности, в параграфе 2 говорится:

Для каждого типа аргумента T в вызове функции существует набор нулевых или более связанных пространств имен и набор нулевых или более связанных классов для рассмотрения. Наборы пространств имен и классов полностью определяются типами аргументов функции (и пространства имен любого аргумента шаблона шаблона). Названия Typedef и используемые объявления-декларации, используемые для указания типов, не вносят вклад в этот набор. Наборы пространств имен и классов определяются следующим образом:

  • Если T является фундаментальным типом, его ассоциированные множества пространств имен и классов являются пустыми.
  • Если T - тип класса (включая объединения), его ассоциированные классы: сам класс; класс которого он является членом, если таковой имеется; и его прямые и косвенные базовые классы. Его связанные пространства имен - это пространства имен, членами которых являются ассоциированные классы. Кроме того, если T является специализацией шаблона класса, его связанные пространства имен и классы также включают: пространства имен и классы, связанные с типами аргументов шаблона, предоставленными для параметров типа шаблона (за исключением параметров шаблона шаблона); пространства имен, членами которых являются аргументы шаблона шаблона; и классы, в которых любые шаблоны-члены, используемые в качестве аргументов шаблона шаблона, являются членами.

...

Первый пучок объясняет, почему сбой в аргументе int терпит неудачу. Вторая пуля объясняет, почему работает в экземпляре Foo.

0

Глядя на ваш код:

int main() {
    foo(Foo());  // This declares a global function "foo" taking a "Foo" as an argument
    foo(0);      // "foo" takes a "Foo" above, and theres no way to convert an int to a Foo...
  • 0
    Вы претендуете на неприятный разбор. Но: ideone.com/bMvYIC

Ещё вопросы

Сообщество Overcoder
Наверх
Меню