Это означает, что синтаксический анализатор сначала определяет, является ли выражение перед круглыми скобками id или postfix-expression .В этом случае он видит f
, а ближайший f
определен typedef int f
- поэтому он приходит к выводу, что выражение интерпретируется как int(a)
, и поиск Кенига не выполняется.
Давайте этот код(попробуйте онлайн: http://ideone.com/clone/eRKvP)
typedef int f;
namespace x {
struct A {
friend void f(A &);
//friend void f(); // # 1
operator int();
void g(A a) {
//void f(); // # 2
(void)f(a); // # 3
}
};
}
Если бы вы объявили (не связанную) функцию f
видимой из g
, она была бы интерпретирована как вызов функции, и поиск Кенига нашел быправильная перегрузка (см. строку #2
).
Декларация друга f
не должна применяться здесь, поскольку
11.4 / 1: ... Имя другане входит в сферу действия класса,
Однако, что меня беспокоит, так это то, что раскомментирование #1
заставляет компилятор (в данном случае gcc) также вызывать x::f(A&)
. Не уверен, почему это так. [В компиляторе Comeau Online он работает должным образом (например, #1
не влияет на строку #3
). Однако в последней бета-версии возникли проблемы при компиляции этого кода.]
PS: как отмеченопо litb, правила в C ++ 0x немного отличаются:
3.4.2 / 3:
Пусть X будет поисковым набором, созданным безусловным поиском (3.4.1), и пусть Y будет поисковым набором, созданным зависимым от аргумента поиском (определяется следующим образом).Если X содержит
- объявление члена класса, или
- объявление функции блока области , которое не является объявлением использования, или
- объявление, которое не является ни функцией, ни шаблоном функции
, тогда Y пусто.В противном случае Y - это набор объявлений, найденных в пространствах имен, связанных с
Элемент, выделенный жирным шрифтом, заставит компилятор учитывать только void f()
и завершится ошибкой при слишком большом количестве аргументов.был введен решением вопрос 218 .