0

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 a primary expression, but not an id-expression, and therefore not an unqualified-id. This means that argument-dependent name lookup is prevented in function calls of the form (fun)(arg) compared to the conventional form fun(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.

Community
  • 1
  • 1
ynn
  • 3,386
  • 2
  • 19
  • 42
  • 1
    Answered [here](https://stackoverflow.com/questions/24116817/when-do-extra-parentheses-have-an-effect-other-than-on-operator-precedence). Trying to see if there is a better target – NathanOliver Mar 21 '19 at 16:28

1 Answers1

1

(f) is ( expression ), not unqualified-id, therefore ADL doesn't apply. A parenthesized unqualified-id is no longer an unqualified-id. In some cases, the standard says that "possibly parenthesized" X is equivalent to X. Argument-dependent lookup is not one of those cases.

Brian Bi
  • 111,498
  • 10
  • 176
  • 312
  • Thank you for your answer. Could you please see my supplement? I don't think `f` belongs to the syntax category of *expression*. – ynn Mar 21 '19 at 16:42
  • 1
    @ynn `f` is an *expression* because it is an *assignment-expression*, which is because it's a *conditional-expression*, which is because it's a *logical-or-expression*, and so on. – Brian Bi Mar 21 '19 at 16:44
  • Thank you. I finally returned to *postfix-expression* (to which `f` belongs) after many jumps. – ynn Mar 21 '19 at 16:48