Unqualified name lookup applied instead of argument-dependent name lookup - c++

Consider an example from the standard sec 3.4.1/3:
typedef int f;
namespace N
{
struct A
{
friend void f(A &);
operator int();
void g(A a)
{
int i = f(a);// f is the typedef, not the friend
// function: equivalent to int(a)
}
};
}
f(a) is postfix expression. How does compiler determine that f(a) is not a function call? I'm wondering when we have no error like f previously declared of typedef int f; as in the following example:
#include <stdio.h>
typedef int foo; //error: previous declaration of ‘typedef int foo’
class B
{
public:
friend void foo(B b){ printf("3"); } //error: ‘void foo(B)’ redeclared as different kind of symbol
static const int c=42;
};
int main(){ }

(In my version of the C++11 document the example is presented in 3.4.1/3).
The 3.4.1/3 clearly states that for the purposes of parsing, in order to perform the initial determination of whether this is a postfix expression or function call, a usual name lookup is performed. "Usual" means that the lookup is performed as described in the rest of 3.4.1 and no ADL is used at that initial stage. 3.4.1/3 explicitly says that "The rules in 3.4.2 have no effect on the syntactic interpretation of an expression." (3.4.2 is ADL).
In this example, while parsing f(a) the usual lookup is used to look for name f. It finds the global typedef-name ::f and nothing else. This means that f(a) is treated as a postfix expression (a cast), not as a function call. Note, that friend declaration of function f inside A refers to function N::f, but it does not introduce a declaration of N::f into N. Since N::f function is not explicitly declared in N (it is not visible in N), the usual lookup does not see it. It only sees the global ::f, which is a typedef-name.
If you want the usual name lookup to find the function in the first example, you have to declare that function in N explicitly
typedef int f;
namespace N
{
struct A; // <- added
void f(A &); // <- added
struct A
{
friend void f(A &);
...
Now the declaration of N::f is visible in N. Now the usual name lookup will find N::f and treat that f(a) as a function call from the very beginning.
Your second example is seriously different from the first. You have no extra namespace there. Because of that the friend function declaration in B refers to the global ::foo and claims that foo is a function. But the global ::foo is already declared as a typedef-name. This contradiction is exactly what causes the error.
(Amusingly, C++03 version of the standard contained an example in 3.4.1/3, which was essentially equivalent to your second example. I.e. the example in the standard was ill-formed. This is reported as Defect #139 of the standard.)

Related

ADL lookup inside a class (template) member function body

struct B {};
struct C : B {};
void f(B){} // worse match than A::f<C>
struct A {
template<class T>
void f(T v) {
f(v); // #1
}
};
int main()
{
A{}.f(C{});
}
Activating ADL lookup in line #1 is as simple as
{
using ::f;
f(v);
}
I think the rule that makes the code fail without the using directive is:
[basic.lookup.argdep]/3 Let X be the lookup set produced by unqualified lookup and let Y be
the lookup set produced by argument dependent lookup (defined as
follows). If X contains
(3.1) a declaration of a class member, or
(3.2) a block-scope function declaration that is not a using-declaration, or
(3.3) a declaration that is neither a function nor a function template
then Y is empty. [...]
So, since a call to f found by non-ADL lookup will find A::f, which is a class member, overloads found by ADL-lookup are discarded.
Which C++ rule allows to ignore the restriction in 3.1 with the using declaration, to make the above code compile?
I think I'm completely misunderstanding the context where the rule [basic.lookup.argdep]/3 must be applied, or maybe I have a bigger and hidden hole in my understanding of the name lookup process.
First paragraph on unqualified name lookup:
In all the cases listed in [basic.lookup.unqual], the scopes are
searched for a declaration in the order listed in each of the
respective categories; name lookup ends as soon as a declaration is
found for the name.
In particular,
For the members of a class X, a name used in a member function body […], following
the member's declarator-id, shall be declared in one of the
following ways:
before its use in the block in which it is used or in an enclosing
block ([stmt.block]), or
shall be a member of class X or be a member
of a base class of X ([class.member.lookup]), or ...
A local (re)declaration of a name is prioritised and shadows all extrinsic declarations.

Interesting behavior of compiler with namespaces

Assume the following code:
#include <iostream>
using namespace std;
namespace X
{
class A{};
void f(A a){}
void g(int a){}
}
int main()
{
X::A a;
f(a);
g(5);
}
When I compile the code, the following compile error occurs:
main.cpp: In function 'int main()':
main.cpp: error: 'g' was not declared in this scope
So the function f is compiled perfectly, but g isn't. How? Both of them belong to the same namespace. Does the compiler deduce that function f belongs to the X namespace from the argument of type X::A? How does compiler behave in such cases?
X::A a;
f(a);
works because of Argument-Dependent Lookup (Also known as Koenig Lookup). a is an object of class A inside namespace X, when compiler searches a match-able function f, it will look into namespace X in this case. See Argument Dependent Lookup for more information.
This works for the function call expression:
f(a);
because the namespace that X::A belongs to is included in the lookup for the function f due to argument dependent lookup(ADL), cppreference explains ADL as follows:
Argument-dependent lookup, also known as ADL, or Koenig lookup, is the
set of rules for looking up the unqualified function names in
function-call expressions, including implicit function calls to
overloaded operators. These function names are looked up in the
namespaces of their arguments in addition to the scopes and namespaces
considered by the usual unqualified name lookup.
Argument-dependent lookup makes it possible to use operators defined
in a different namespace
This is covered in the draft C++ standard section 3.4.2 Argument-dependent name lookup:
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 or function template declarations (11.3) not otherwise visible may be found
and goes on to say:
For each argument type T in the function call, there is a set of zero or more associated namespaces and a
set of zero or more associated classes to be considered. The sets of namespaces and classes is determined
entirely by the types of the function arguments (and the namespace of any template template argument).
and includes the following bullet:
If T is a class type (including unions), its associated classes are: the class itself; the class of which it is a
member, if any; and its direct and indirect base classes. Its associated namespaces are the namespaces
of which its associated classes are members.[...]
and further down provides a similar example to your problem:
namespace NS {
class T { };
void f(T);
void g(T, int);
}
NS::T parm;
void g(NS::T, float);
int main() {
f(parm); // OK: calls NS::f
extern void g(NS::T, float);
g(parm, 1); // OK: calls g(NS::T, float)
}
The function call expression:
g(5);
does not work because ADL does not add any namespaces for arguments that are fundamental types.
Herb Sutter covers ADL in Gotw #30 and in What's In a Class? - The Interface Principle.
When the code f(a), the compiler finds the function void f(A a){} in the namespace X because of the ADL (argument dependent lookup, also known as Koenig lookup).
A is declared in the namespace X, hence when the compiler needs to look up the definition of f, it includes possibilities from that namespace because the object a of type A is in that namespace (as declared X::A a;).
On the other hand, int is not declared in the namespace X, so the namespace X is not included in the lookup. Since no corresponding function for f is found, it fails to compile.

Why does unqualified name lookup find all overloaded declarations

Here is an example which I'm trying to understand how does unqualified name look up work for overloaded declarations:
int foo(char a){ return 0; }
namespace A
{
int foo(int a){ return a; }
int foo(){ return 2; }
extern int j;
extern int i;
}
int A::j=foo('a'); //97
int A::i=foo(); //2
It means that int foo(char); does not found by unqualified name look up but int foo(int); and int foo() can be found. So I assume that unqualified name look up for overloaded declaration ends as soon as all overloaded declarations is found for the name. I can't find this into the standard, I can find only the following (sec. 3.4.1):
name look up ends as soon as a declaration is found for the name.
This quote doesn't say anything about overloaded declaration look up.
You're mixing up name lookup with overload resolution. There is no such thing as "unqualified name look up for overloaded declaration". Name lookup and overload resolution are separate.
Name lookup means determining which scope the name is found in. Once that is completed, overload resolution determines which of the declarations visible in that scope should be used.
In your code, name lookup determines that foo means A::foo. Then overload resolution selects between A::foo() and A::foo(int). The ::foo is not considered for overload resolution because it is not a definition of A::foo.
Another example:
namespace C { void f(); }
namespace B { void f(); void f(float); }
namespace C { void f(long); }
using namespace C;
int main()
{
f(1.0);
}
When processing the line f(1.0), name lookup sees void f(); and stops. The result is that f means C::f.
Then overload resolution kicks in, and all declarations of C::f are considered for overload resolution. void f(long) is chosen.
In a declaration in which the declarator-id is a qualified-id, names used before the qualified-id being declared
are looked up in the defining namespace scope; names following the qualified-id are looked up in the scope
of the member’s class or namespace.
(C++11 §3.4.3/3)
So in both of
int A::j=foo('a');
int A::i=foo();
the name foo is looked up in the scope of A just because you have A::j and A::i to the left, in the declarator.
Note that if you do
int k = foo();
only the global foo will be found, and you'll get an error.
You said
It means that int foo(char); does not found by unqualified name look up but int foo(int); and int foo() can be found. So I assume that unqualified name look up for overloaded declaration ends as soon as all overloaded declarations is found for the name.
A similar question was asked in another SO post
There is from 3.4.1/14:
If a variable member of a namespace is defined outside of the scope of its namespace then any name that appears in the definition of the member (after the declarator-id) is looked up as if the definition of the member occurred in its namespace.
Your posted code is equivalent to:
int foo(char a){ return 0; }
namespace A
{
int foo(int a){ return a; }
int foo(){ return 2; }
extern int j;
extern int i;
}
namespace A
{
int j=foo('a');
int i=foo();
}
When the definitions and initializations are put under the namespace, it becomes clear why functions used to initialize the variables are looked up in namespace A first. If an unambiguous match can be found for a function in namespace A, the search for it stops. That means, when compiling the line,
int A::j=foo('a');
The lookup for foo starts in namespace A, is resolved to int A::foo(int); and the search for foo stops.
Hope this clears the confusion.
In the standard (§3.4/1)
Name lookup shall
find an unambiguous declaration for the name (see 10.2). Name lookup may associate more than one declaration with a name if it finds the name to be a function name; the declarations are said to form a set
of overloaded functions (13.1). Overload resolution (13.3) takes place after name lookup has succeeded.
The access rules (Clause 11) are considered only once name lookup and function overload resolution (if
applicable) have succeeded.
Which means the steps are as follows for methods:
First collect all the matching names
Do overload resolution
Check for accessibility
For method, name lookup does not return after finding first match, rather it searches for all matching names. It is clear from the statement Name lookup may associate more than one declaration with a name if it finds the name to be a function name.

Should the name of a function template be visible during lookup of a name preceding ::?

Both clang and gcc reject this code:
template<int i>
struct ambiguous
{
static const int value = i;
};
namespace N
{
template<int i>
void ambiguous();
int i = ambiguous<3>::value; // finds the function template name
}
However, they both accept the following code:
struct ambiguous
{
static const int value = 0;
};
namespace N
{
void ambiguous();
int i = ambiguous::value;
}
The standard says that name lookup of a name preceding :: "considers only namespaces, types, and templates whose specializations are types". Are clang and gcc correct in rejecting this code? If so, what am I missing?
From C++ Working Draft Standard n3337
3.4.3 Qualified name lookup [basic.lookup.qual]
The name of a class or namespace member or enumerator can be referred to after the :: scope resolution
operator (5.1) applied to a nested-name-specifier that denotes its class, namespace, or enumeration. If a ::
scope resolution operator in a nested-name-specifier is not preceded by a decltype-specifier, lookup of the
name preceding that :: considers only namespaces, types, and templates whose specializations are types.
If the name found does not designate a namespace or a class, enumeration, or dependent type, the program
is ill-formed.
14.2 Names of template specializations [temp.names]
For a template-name to be explicitly qualified by the template arguments, the name must be known to refer
to a template.
After name lookup (3.4) finds that a name is a template-name or that an operator-function-id or a literal-operator-id refers to a set of overloaded functions any member of which is a function template if this is
followed by a <, the < is always taken as the delimiter of a template-argument-list and never as the less-than
operator.
Edit
To avoid confusion of this issue with the ambiguity between an expression and a declaration, here is the original code with the templates using a type parameter instead of a non-type parameter.
template<class>
struct ambiguous
{
static const int value = 0;
};
namespace N
{
template<class>
void ambiguous();
int i = ambiguous<int>::value; // finds the function template name
}
This results in the same error in all cases. The < cannot be interpreted as an operator.
ambiguous is unambiguously a template-name, but could either be a type or a function. It's possible to parse the entire template-id without knowing whether it names a function or a type, and resolve the ambiguity later on. Does the standard excuse the implementor from doing this?
The problem is that the paragraph you quote ends up being
applied too late. Before getting there, the compiler must
determine that in ambiguous<3>::value, the < and > are
template argument delimiters, and not greater than and less
than. (Consider:
int ambiguous;
int value:
// ...
int i = ambiguous<3>::value;
, which parses as (ambiguous < 3) > ::value, where the < and
> are less than and greater than, respectively.) This
involves a lookup of ambiguous as an unqualified name, and
binds the symbol to N::ambiguous. Afterwards, you're stuck
with the instantiated template N::ambiguous<3> to the left of
::, which isn't legal.
EDIT:
This issue isn't as clear as one might like: the standard only
refers to section 3.4 in section 14.2, where it discusses this,
and section 3.4 discusses all of the possible rules of name
lookup. On the other hand, there is really only one way to
interpret it: the compiler cannot parse anything further until
it knows whether ambiguous names a template or not, and can
decide whether the following < is greater than, or opens
a template argument list. And of course, it cannot "rebind" the
argument later, once it has parsed the following tokens, since
in the general case, rebinding could change the meaning of the
<, invalidating the parse. In practice, although the standard
doesn't say so as clearly as it probably should, the name lookup
in this case must be unqualified name lookup (or class member
access, if the name is preceded by a . or a -> operator).
Seem templates in the inner namespace hide the names of the outer.
template<int i>
struct A
{
static const int value = 0;
};
struct B
{
static const int value = 0;
};
typedef A<0> C;
namespace N
{
// The local function A is not declaced, yet, but the global A is:
int early_e = A<3>::value; // Ok: The A in the global namespace. [simple-template-id}
template<int i>
int A() { return 0; }
int B() { return 0; }
int C() { return 0; }
int a = A<3>(); // Ok: The A in the namespace. [simple-template-id}
int b = N::A<3>(); // Ok: The A in the namespace. [N::simple-template-id]
int c = ::N::A<3>(); // Ok: The A in the namespace. [::N::simple-template-id]
int d = ::A<3>::value; // Ok: The A in the global namespace. ::simple-template-id::identifier]
// The local function A is no type: "templates whose specializations are types"
int e = A<3>::value; // Error: The namespace has the function name A,
// which hides the global A. [simple-template-id::identifier]
// The local function B is no type, but the global B is a type:
int f = B::value; // Ok: The B in the global namespace. [class-name::identifier]
// The local function C is no type, but the global typedef C is a type:
int g = C::value; // Ok: The C in the global namespace. [typedef-name::identifier]
}
int main() {
return 0;
}

friend function

What does the following mean (especially the highlighted portion)? Why is the expression 'f(a)' treated as a 'cast expression'?
C++03 $3.4./3- "The lookup for an unqualified name
used as the postfix-expression of a
function call is described in 3.4.2.
[Note: for purposes of determining
(during parsing) whether an expression
is a postfix-expression for a function
call, the usual name lookup rules
apply. The rules in 3.4.2 have no
effect on the syntactic interpretation
of an expression. For example,
typedef int f;
struct A {
friend void f(A &);
operator int();
void g(A a) {
f(a);
}
};
The expression f(a) is a cast-expression equivalent to int(a). Because the expression is not a function call, the argument-dependent name lookup (3.4.2) does not apply and the friend function f is not found. ]"
Any thoughts?
It means that the parser first determines whether the expression before the parentheses is an id or a postfix-expression. In this case, it sees f, and the nearest f defined is typedef int f - therefore it concludes the expression is interpreted as int(a) and no Koenig lookup is performed.
Let's have this code (you an try it online: 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
}
};
}
Had you declared an (unrelated) function f visible from g, it would be interpreted as a function call and Koenig lookup would find the correct overload (see line #2).
The friend declaration of f should not apply here, because
11.4/1: ... The name of a friend is not in the scope of the class,
However, what's disturbing me, is that uncommenting #1 makes the compiler (gcc in this case) call x::f(A&) too. Not sure why is that. [In Comeau Online compiler, it works as expected (eg. #1 doesn't influence line #3). The latest beta version has problems compiling this code, though.]
PS: As noted by litb, the rules in C++0x are a little different:
3.4.2/3:
Let X be the lookup set produced by
unqualified lookup (3.4.1) and let Y be
the lookup set produced by argument
dependent lookup (defined as follows).
If X contains
a declaration of a class member, or
a block-scope function declaration that is not a using-declaration, or
a declaration that is neither a function or a function template
then Y is empty. Otherwise Y is the
set of declarations found in the
namespaces associated with the
The bold item will make the compiler only consider void f() and fail for too many arguments.
It seems to have been introduced by the resolution of issue 218.