Topic: Argument dependent lookup on function-names within parantheses
Author: s.hesp@oisyn.nl ("Sylvester Hesp")
Date: Tue, 8 May 2007 17:54:27 GMT Raw View
During a discussion on comp.lang.c++, the following issue arose
namespace na
{
template<class T> struct A { };
template<class T> void foo(T);
template<class T> void func(A<T> n)
{
foo(n); // #1
}
}
namespace nb
{
struct B { };
template<class T> void foo(T);
}
int main()
{
func(na::A<nb::B>()); // #2
}
During instantiation of na::func() at #2, the call to foo() is ambiguous
because both na::foo and nb::foo are considered because of ADL. The
topicstarter didn't want this ambiguity, and he/she found that, after
replacing #1 with '(foo)(n)', it worked as he/she wanted.
While this struck me as weird at first, I did found it pretty reasonable,
because, for example, when taking a function's address, ADL isn't performed
either (as that isn't possible as there are no parameters to perform ADL
on). A function name nested in parantheses is semantically very similar.
Nevertheless, I decided to dig through the standard to see what it said
about it, and what I found out confused me a bit.
There are 3 paragraphs about this that refer to each other. 3.4.2 (argument
depending name lookup), 5.2.2 (function call expression) and 13.3.1.1
(function call syntax).
----------------
3.4.2/1 When an unqualified name is used as the postfix-expression in a
function call (5.2.2), other namespaces not considered during the usual
unqualified lookup (3.4.1) may be searched [...]
5.2.2/1 There are two kinds of function call: ordinary function call and
member 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. For an ordinary function
call, the postfix expression shall be either an lvalue that refers to a
function (in which case the function-to-pointer standard conversion (4.3) is
suppressed on the postfix expression), or it shall have pointer to function
type.
13.3.1.1/1 Recall from 5.2.2, that a function call is a postfix-expression,
possibly nested arbitrarily deep in parentheses, followed by
an optional expression-list enclosed in parentheses: ( ... (opt
postfix-expression ) ... )opt ( expression-listopt )
Overload resolution is required if the postfix-expression is the name of a
function, a function template (14.5.5), an object of class type, or a set of
pointers-to-function.
----------------
5.2.2 does only mention postfix-expressions followed by parantheses, not the
nested parantheses in which the postfix-expression might be situated. This
is probably intentional (?) and is consistent with what most compilers I've
tried it on are doing. However, 13.3.1.1 (a paragraph that essentially has
nothing to do with name lookup itself) does refer back to 5.2.2 as if it was
mentioned in 5.2.2 that the postfix-expression might be enclosed in nested
parantheses.
Which leads to my question: is it really intentional that 5.2.2 does not
mention the postfix-expression being possibly enclosed in parantheses, thus
allowing the programmer to circumvent ADL by putting parantheses around the
function name? Or should ADL be performed no matter any enclosing
parantheses? Either way, in my opinion one of the paragraphs listed here
might need some clarification. (Btw, I know ADL is an active topic, but the
papers I've read about it so far don't seem to be tackling this issue)
- Sylvester Hesp
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Thu, 10 May 2007 03:58:20 GMT Raw View
===================================== MODERATOR'S COMMENT:
(Apologies for this comment, which is present to bypass broken
spam filtering implemented by Cox.)
===================================== END OF MODERATOR'S COMMENT
Sylvester Hesp ha scritto:
> ----------------
> 3.4.2/1 When an unqualified name is used as the postfix-expression in a
> function call (5.2.2), other namespaces not considered during the usual
> unqualified lookup (3.4.1) may be searched [...]
>
> 5.2.2/1 There are two kinds of function call: ordinary function call and
> member 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. For an ordinary function
> call, the postfix expression shall be either an lvalue that refers to a
> function (in which case the function-to-pointer standard conversion (4.3) is
> suppressed on the postfix expression), or it shall have pointer to function
> type.
>
> 13.3.1.1/1 Recall from 5.2.2, that a function call is a postfix-expression,
> possibly nested arbitrarily deep in parentheses, followed by
> an optional expression-list enclosed in parentheses: ( ... (opt
> postfix-expression ) ... )opt ( expression-listopt )
> Overload resolution is required if the postfix-expression is the name of a
> function, a function template (14.5.5), an object of class type, or a set of
> pointers-to-function.
>
> ----------------
>
> 5.2.2 does only mention postfix-expressions followed by parantheses, not the
> nested parantheses in which the postfix-expression might be situated. This
> is probably intentional (?) and is consistent with what most compilers I've
> tried it on are doing. However, 13.3.1.1 (a paragraph that essentially has
> nothing to do with name lookup itself) does refer back to 5.2.2 as if it was
> mentioned in 5.2.2 that the postfix-expression might be enclosed in nested
> parantheses.
>
> Which leads to my question: is it really intentional that 5.2.2 does not
> mention the postfix-expression being possibly enclosed in parantheses, thus
> allowing the programmer to circumvent ADL by putting parantheses around the
> function name?
What 5.2.2 is saying is that a function call has, by definition, the form:
A) postfix-expression ( expression-list opt )
Because of the grammar rules, any expression enclosed in parentheses is
a postfix-expression, so we can rewrite any expression originally in
form A into this form:
B) ( ... (opt postfix-expression ) ... )opt ( expression-list opt )
possibly in multiple ways.
Now, 13.3.1.1/1 is saying that *if* we can rewrite a function call in
form B *so that* the postfix-expression happens to be the name of a
function or blah blah, then overload resolution occurs.
So there is no inconsistency between the two paragraphs. Notice that
*none* of them have anything to do with ADL.
> function name? Or should ADL be performed no matter any enclosing
> parantheses? Either way, in my opinion one of the paragraphs listed here
> might need some clarification. (Btw, I know ADL is an active topic, but the
> papers I've read about it so far don't seem to be tackling this issue)
The key point is in paragraph 3.4.2/1 above. It says (with added
emphasis): "When an unqualified name is used *as* the postfix-expression
in a function call [...]". Notice that here we are definitely referring
to the definition form A! So if I write:
(foo)(n);
the postfix-expression 3.4.2/1 is referring to is "(foo)". As "(foo)" is
*not* an unqualified name, ADL doesn't apply. The fact the "(foo)"
contains, nested in parentheses, an unqualified name is irrelevant.
HTH,
Ganesh
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: s.hesp@oisyn.nl ("Sylvester Hesp")
Date: Thu, 10 May 2007 16:28:16 GMT Raw View
"Alberto Ganesh Barbati" <AlbertoBarbati@libero.it> wrote in message
news:5vr0i.3297$U01.49313@twister1.libero.it...
> The key point is in paragraph 3.4.2/1 above. It says (with added
> emphasis): "When an unqualified name is used *as* the postfix-expression
> in a function call [...]". Notice that here we are definitely referring
> to the definition form A! So if I write:
>
> (foo)(n);
>
> the postfix-expression 3.4.2/1 is referring to is "(foo)". As "(foo)" is
> *not* an unqualified name, ADL doesn't apply. The fact the "(foo)"
> contains, nested in parentheses, an unqualified name is irrelevant.
Wow I completely misinterpreted that subtle 'as'. Thank you for the clear
explanation :)
- Sylvester Hesp
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]