У меня есть следующая программа:
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())
должен завершиться успешно. Может кто-то пролил свет?
Открыто за мое собственное удаление, а? Ну, после некоторого побуждения от juanchopanza, я более внимательно прочитал соответствующую часть стандарта С++ 11 §3.4.2. Я просмотрел его слишком быстро раньше. В частности, в параграфе 2 говорится:
Для каждого типа аргумента T в вызове функции существует набор нулевых или более связанных пространств имен и набор нулевых или более связанных классов для рассмотрения. Наборы пространств имен и классов полностью определяются типами аргументов функции (и пространства имен любого аргумента шаблона шаблона). Названия Typedef и используемые объявления-декларации, используемые для указания типов, не вносят вклад в этот набор. Наборы пространств имен и классов определяются следующим образом:
- Если T является фундаментальным типом, его ассоциированные множества пространств имен и классов являются пустыми.
- Если T - тип класса (включая объединения), его ассоциированные классы: сам класс; класс которого он является членом, если таковой имеется; и его прямые и косвенные базовые классы. Его связанные пространства имен - это пространства имен, членами которых являются ассоциированные классы. Кроме того, если T является специализацией шаблона класса, его связанные пространства имен и классы также включают: пространства имен и классы, связанные с типами аргументов шаблона, предоставленными для параметров типа шаблона (за исключением параметров шаблона шаблона); пространства имен, членами которых являются аргументы шаблона шаблона; и классы, в которых любые шаблоны-члены, используемые в качестве аргументов шаблона шаблона, являются членами.
...
Первый пучок объясняет, почему сбой в аргументе int
терпит неудачу. Вторая пуля объясняет, почему работает в экземпляре Foo
.
Глядя на ваш код:
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...
foo(0)
должен потерпеть неудачу, или вы тоже спрашиваете об этом?