This question is based on C++11 Standard (N3092).
3.4.2-1 Argument-dependent name lookup says
When the postfix-expression in a function call (5.2.2) is an unqualified-id, other namespaces not considered during the usual unqualified lookup (3.4.1) may be searched, and in those namespaces, namespace-scope friend function declarations (11.4) not otherwise visible may be found. These modifications to the search depend on the types of the arguments (and for template template arguments, the namespace of the template argument). [ Example:
namespace N {
struct S { };
void f(S);
}
void g() {
N::S s;
f(s); // OK: calls N::f
(f)(s); // error: N::f not considered; parentheses
// prevent argument-dependent lookup
}
— end example ]
, but I don't understand why (f)(s)
suppresses ADL(argument-dependent lookup). This is what I would like to ask.
According to 5.2.2-1 Function call,
A function call is a postfix expression followed by parentheses containing a possibly empty, comma-separated list of expressions which constitute the arguments to the function.
so in that case, f
or (f)
are a postfix expression.
Then the syntax category of postfix-expression is defined as
postfix-expression:
primary-expression
postfix-expression [ expression ]
postfix-expression [ braced-init-list ]
postfix-expression ( expression-list opt )
simple-type-specifier ( expression-list opt )
typename-specifier ( expression-list opt )
simple-type-specifier braced-init-list
typename-specifier braced-init-list
postfix-expression . template opt id-expression
postfix-expression -> template opt id-expression
postfix-expression . pseudo-destructor-name
postfix-expression -> pseudo-destructor-name
postfix-expression ++
postfix-expression --
dynamic_cast < type-id > ( expression )
static_cast < type-id > ( expression )
reinterpret_cast < type-id > ( expression )
const_cast < type-id > ( expression )
typeid ( expression )
typeid ( type-id )
In this case, only primary-expression is relevant. It is defined as
primary-expression:
literal
this
( expression )
id-expression
lambda-expression
In this case, only id-expression is relevant, and it is defined as
id-expression:
unqualified-id
qualified-id
So f
and (f)
are one of these. If (f)
is not an unqualified-id (because ADL is suppressed), it should be one of qualified-id. But it is defined as
qualified-id:
:: opt nested-name-specifier template opt unqualified-id
:: identifier
:: operator-function-id
:: literal-operator-id
:: template-id
I think (f)
is not one of these. If so, why (f)(s)
suppresses ADL?
Supplement:
This answer (which was given in this comment) says
As is detailed in Annex A of the Standard, a
post-fix expression
of the form(expression)
is aprimary expression
, but not anid-expression
, and therefore not anunqualified-id
. This means that argument-dependent name lookup is prevented in function calls of the form(fun)(arg)
compared to the conventional formfun(arg)
.
but it is correct? The syntax category of expression is defined as
expression:
assignment-expression
expression , assignment-expression
in Annex A. I don't think f
in (f)
is one of expression.