According to [namespace.memdef]#3:
If a friend declaration in a non-local class first declares a class, function, class template or function template the friend is a member of the innermost enclosing namespace.
I think the compiler has to perform name lookup to determine if the friend declaration first declares a function. That is, the compiler will try to find the entity corresponding to the friend declaration. But I didn't find anything in the standard describing that lookup rule.
The text following the above in the standard says
If the name in a friend declaration is neither qualified nor a template-id and the declaration is a function or an elaborated-type-specifier, the lookup to determine whether the entity has been previously declared shall not consider any scopes outside the innermost enclosing namespace.
From cppreference:
For a friend declaration, the lookup to determine whether it refers to a previously declared entity proceeds as above except that it stops after the innermost enclosing namespace.
where "above" refers to the lookup rules for unqualified names in class definitions.
So I wrote a small example to test my idea:
struct A {
static void fun(A) { }
friend void fun(A);
};
fun(A{});
Here the call to fun will find the friend function fun within the struct A via ADL. I tested the code on clang and it throws a linker error(godbolt):
undefined reference to `fun(A)'
This proves that the friend function fun is not related to the static member function fun.
However, according to cppreference, the name fun should be looked up within the class first. I don't know why the static member fun cannot be found here. Well, I agree that this is a ridiculous explanation, but I can't find a standard text that refutes that explanation.
So what rules does the compiler follow to find the entity corresponding to the friend declaration?
Related
What is the fully qualified name of a friend function defined inside of a class?
I recently saw an example analogous to the following. What is the fully qualified name of val() below?
#include <iostream>
namespace foo {
class A {
int x;
public:
A(int x = 0) : x(x) { }
friend int val(const A &a) { return a.x; }
};
}
int main() {
foo::A a(42);
// val() found using ADL:
std::cout << val(a) << std::endl;
// foo::val(a); // error: 'val' is not a member of 'foo'
// foo::A::val(a); // error: 'val' is not a member of 'foo::A'
return 0;
}
Is argument-dependent lookup the only way val() can be found?
Admittedly, this does not stem from a practical problem. I am simply looking to gain a better understanding.
Is argument-dependent lookup the only way val() can be found?
Yes, it is the only way. To quote the holy standard at [namespace.memdef]/3:
If a friend declaration in a non-local class first declares a class,
function, class template or function template the friend is a member
of the innermost enclosing namespace. The friend declaration does not
by itself make the name visible to unqualified lookup or qualified lookup.
So while val is a member of foo, it's not visible to lookup from the friend declaration alone. An out of class definition (which is also a declaration) is required to make it visible. For an inline definition (and no out-of-class declaration) it means ADL is the only way to call the function.
As an added bonus, C++ did once have a concept of "friend name injection". That however has been removed, and the rules for ADL adjusted as a replacement. A more detailed overview can be found in WG21 paper N0777 (pdf).
C++ Standard [7.3.1.2/3 (of ISO/IEC 14882:2011)]:
Every name first declared in a namespace is a member of that
namespace. If a friend declaration in a non-local class first declares
a class or function the friend class or function is a member of the
innermost enclosing namespace. The name of the friend is not found by
unqualified lookup (3.4.1) or by qualified lookup (3.4.3) until a
matching declaration is provided in that namespace scope (either
before or after the class definition granting friendship). If a friend
function is called, its name may be found by the name lookup that
considers functions from namespaces and classes associated with the
types of the function arguments (3.4.2). If the name in a friend
declaration is neither qualified nor a template-id and the declaration
is a function or an elaborated-type-specifier, the lookup to determine
whether the entity has been previously declared shall not consider any
scopes outside the innermost enclosing namespace.
Consider the following clause in [namespace.memdef]/3:
If the name in a friend declaration is neither
qualified nor a template-id and the declaration is a function or an elaborated-type-specifier, the lookup to determine whether the entity has been previously declared shall not consider any scopes outside the innermost
enclosing namespace.
Is there a reason for the exception for template-id along with the qualified name? For that matter, is there a reason for the lookup of an unqualified name that isn't a template-id to be restricted to the innermost enclosing namespace? Is there a specific problem or use-case that this clause solves?
Why doesn't the restriction apply to qualified names and template-ids?
Qualified names and template-ids cannot introduce new members into the enclosing namespace, this is what the note in [namespace.memdef]p3 tries to say:
[ Note: The other forms of friend declarations cannot declare a new
member of the innermost enclosing namespace and thus follow the usual
lookup rules. — end note ]
Therefore, no such restriction is necessary for qualified names and template-ids.
Note that template-ids lack the declaration of the template-parameters, and qualified-ids could introduce names into distant, unrelated namespaces.
Why is there a restriction at all?
This part of the answer is still incomplete, but represents the current state of "research". Feel free to contribute.
The restriction has (probably?) been introduced due to N0783 - Namespace Issues and Proposed Resolutions which "attempts to clarify a number of namespace issues that are currently either undefined or incompletely specified".
This paper from 1995 contains two enlightening discussions of issues related to declarations of entities introduced via friend-declarations. Bear in mind that the name lookup rules back then were different:
Argument-dependent lookup had not yet been introduced(*)
Names introduced via friend-declarations are not found via pure unqualified lookup (no ADL) according to current rules, see [namespace.memdef]p3 and CWG 1477. The examples from N0878 suggest that those names could be found via pure unqualified lookup at that time.
(*) The best I could find was N0878 from March 1996, which says "A change was recently made to the working paper to add the “Koenig lookup rule”"
First, the example from N0783 for functions:
void f(char);
namespace A {
class B {
friend void f(char); // ::f(char) is a friend
friend void f(int); // A::f(int) is a friend
void bf();
};
void B::bf()
{
f(1); // calls A::f(int);
f('x'); // also calls A::f(int) because ::f is hidden
}
}
The second friend declaration must introduce a new function. N0783 tries to specify in which scope this declaration is introduced. It suggests
All friend declarations for a given name must declare entities in one
particular scope.
as a general rule, to avoid the surprises of situations such as the above.
So the question is, which scope do they declare entities in? There are
two possibilities, either
When looking for a previous declaration of the function, look until the nearest enclosing namespace is reached, or
When looking for a previous declaration, look in all enclosing scopes for the name of the function that was declared. If a previous
use of the name is found, the declaration is injected into that scope.
If no previous use of the name is found the friend is injected into
the nearest enclosing namespace scope.
Rule #2 would mean that the presence of any function called f in an
enclosing scope, whether or not the types match, would be enough to
cause a friend declaration to inject into that scope.
I believe that rule #2 is clearly unacceptable. A friend declaration
in a namespace would be affected by any global declaration of that
name. Consider what this would mean for operator functions! The
presence of any operator+ function in the global scope would force
all friend operator+ operators to appear in the global scope too!
The presence of a template in the global scope would have the same
effect.
For class types:
namespace N {
class A { void f(); };
}
using namespace N;
namespace M {
class B {
friend class A; // Without this rule
// makes N::A a friend
B();
};
class A { void f(); };
}
void N::A::f() { M::B b; } // A friend under current rules
void M::A::f() { M::B b; } // A friend under proposed rules
Both examples are not as interesting under the current rules because names introduced via friend declarations are only found via ADL. It is possible this restriction is a historical artefact. More "research" is required to follow the development of this restriction after the introduction of ADL.
I have no idea, why gcc compiles this code
#include <type_traits>
template<class Type, class ValueT>
class ImplAdd
{
template<typename T>
friend typename std::enable_if<std::is_same<T, ValueT>::value, Type>::type
operator+(T, T)
{
return Type{};
}
};
enum class FooValueT { ONE, ZERO };
class Foo : ImplAdd<Foo, FooValueT>
{
public:
Foo() {}
Foo(FooValueT) {}
};
struct A {};
int main()
{
Foo f = FooValueT::ONE + FooValueT::ZERO;
}
clang and msvc doesn't compile, and it seems to me, that they are right. Is it bug in GCC compiler? Version of gcc is 4.8.2.
Question is caused by my answer in question: In-class friend operator doesn't seem to participate in overload resolution, there is quote from standard in answer, that points, that such definition should be in class-scope, and if function is not template - gcc reject this code, that is right. Thanks for answers, and quotes from standard, that proves, that gcc is right (or not) are very appreciated.
I would say GCC accepts this incorrectly. Quoting C++11, emphasis mine:
Namespace membership, 7.3.1.2/3
Every name first declared in a namespace is a member of that namespace. If a friend declaration in a nonlocal
class first declares a class or function the friend class or function is a member of the innermost enclosing
namespace. The name of the friend is not found by unqualified lookup (3.4.1) or by qualified lookup (3.4.3) until a matching declaration is provided in that namespace scope (either before or after the class definition
granting friendship). If a friend function is called, its name may be found by the name lookup that considers
functions from namespaces and classes associated with the types of the function arguments (3.4.2). ...
Argument-dependent lookup, 3.4.2/2:
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).
Typedef names and using-declarations used to specify the types do not contribute to this set. The sets of
namespaces and classes are determined in the following way:
...
If T is an enumeration type, its associated namespace is the namespace in which it is defined. If it is
class member, its associated class is the member’s class; else it has no associated class.
...
3.4.2/4:
When considering an associated namespace, the lookup is the same as the lookup performed when the
associated namespace is used as a qualifier (3.4.3.2) except that:
...
Any namespace-scope friend functions or friend function templates declared in associated classes are
visible within their respective namespaces even if they are not visible during an ordinary lookup (11.3).
...
Based on the above, I reason that FooValueT (the type of FooValueT::ONE and FooValueT::TWO) has :: as an associated namespace, but has no associated classes (since it's an enumeration). Therefore, friend functions defined in class template ImplAdd should not be considered during ADL.
Suppose we have this code, copied from a separate question:
namespace x
{
void f()
{
}
class C
{
void f()
{
using x::f;
f(); // <==
}
};
}
The name f on the indicated line unambiguously refers to x::f (at least according to both gcc and clang). Why is x::f preferred over x::C::f in this case? Shouldn't it be ambiguous as both names are visible?
Because the using declaration brings x::f into the scope of f, which is narrower than that of C. Unqualified lookup considers the local block scope, finds a match, and stops before considering the wider class scope. There is no argument-dependent lookup since there are no function arguments, so no further scopes are considered.
#MikeSeymour's answer is spot on; here are the relevant standard quotes (C++11, emphasis mine):
13.3.1.1.1/3:
In unqualified function calls, the name is not qualified by an -> or . operator and has the more general form
of a primary-expression. The name is looked up in the context of the function call following the normal rules
for name lookup in function calls (3.4). The function declarations found by that lookup constitute the set of
candidate functions. Because of the rules for name lookup, the set of candidate functions consists (1) entirely
of non-member functions or (2) entirely of member functions of some class T. ...
3.4.1/1:
In all the cases listed in 3.4.1, 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. If no declaration is
found, the program is ill-formed.
3.4.1/8
A name used in the definition of a member function (9.3) of class X following the function'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 (6.3), or
shall be a member of class X or be a member of a base class of X (10.2), or
...
From 3.4.1/8, we see that a declaration for the name f (such as the declaration using x::f;) in the block in which it's used is listed earlier than f as the member of class C. As per 3.4.1/1, the earlier one is chosen, so the entire lookup resolves to x::f introduced by the using declaration.
I think that these quotes from the C++ Standard will be relevant:
From the C++ Standard (7.3.3 The using declaration)
13 Since a using-declaration is a declaration, the restrictions on
declarations of the same name in the same declarative region (3.3)
also apply to using-declarations.
And (3.3.7 Class scope)
4) A name declared within a member function hides a declaration of the
same name whose scope extends to or past the end of the member
function’s class.
I have next code:
void f(int){}
struct A
{
void f()
{
f(1);
}
};
This code is not well-formed with the error message (GCC): error: no matching function for call to ‘A::f(int)’ or (clang) Too many arguments to function call, expected 0, have 1; did you mean '::f'?
Why do I need to use :: to call the non-member function with the same name as the member function, but with different signature? What is the motivation for this requirement?
I think the compiler should be able to figure it out I want to call the non-member function as the signature is different (clang even puts that in the error message!).
Please don't mark this as duplicate - it is a different question from this Calling in C++ a non member function inside a class with a method with the same
Why do I need to use :: to call the non-member function with the same name as the member function, but with different signature
Because those are the rules. Names in a nested scope hide entities with the same name in a wider scope.
What is the motivation for this requirement?
Consider the case where a member function calls another member with a signature that doesn't quite match:
struct A {
void f(double);
void g() {f(42);} // requires int->double conversion
};
Now suppose someone adds an unrelated function in the surrounding namespace
void f(int);
If this were included in the set of overloads within the scope of A, then suddenly the behaviour of A::g would change: it would call this instead of A::f. Restricting the overload set to names in the narrowest available scope prevents this kind of unexpected breakage.
As you (and your helpful compiler) say, the outer name is still available (with qualification) if you need it.
The compiler performs unqualified name lookup, for f, specified in §3.4.1 [basic.lookup.unqual] (thankfully, there's no ADL here):
1 In all the cases listed in 3.4.1, 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. If no
declaration is found, the program is ill-formed.
8 For the members of a class X, a name used in a member function
body, in a default argument, in an exception-specification, in the
brace-or-equal-initializer of a non-static data member (9.2), or in the definition of a class member outside of the definition of X,
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 (6.3), or
shall be a member of class X or be a member of a base class of X (10.2), or
if X is a nested class of class Y (9.7), shall be a member of Y, or shall be a member of a base class of Y (this lookup applies
in turn to Y’s enclosing classes, starting with the innermost
enclosing class), or
if X is a local class (9.8) or is a nested class of a local class, before the definition of class X in a block enclosing the definition
of class X, or
if X is a member of namespace N, or is a nested class of a class that is a member of N, or is a local class or a nested class within
a local class of a function that is a member of N, before the use of
the name, in namespace N or in one of N’s enclosing namespaces.
Name lookup stops as soon as a declaration is found. So once it finds the member f() at the second bullet point it stops and never searches elsewhere.
Rejection of nonviable functions are done after name lookup, at overload resolution.
Why do I need to use :: to call the non-member function with the same name as the member function, but with different signature? What is the motivation for this requirement?
That is the whole point of having namespaces. A local (closer-scoped) name is preferred and more visible over a global name. Since a struct is again a scope, its f is shadowing the visibility of ::f. When you've to have the global one, you've to say you do. Why?
This is provided as a feature to make sure you can peacefully call functions you defined assuming they would get called, and when you need one from a different namespace, say the standard library, you'd state that explicitly, like std::. It's just a clean form of disambiguation, without leaving room for chance to play its part.
To understand the reason of your error and why you need to explicitly use the ::f() syntax, you may want to consider some aspects of the C++ compiler process:
The first thing the compiler does is name lookup.
Unqualified name lookup starts from the current scope, and then moves outwards; it stops as soon as it finds a declaration for the name of the function, even if this function will be later determined to not be a viable candidate for the function call.
Then, overload resolution is executed over the set of the functions that name lookup found.
(And, finally, access check is executed on the function that overload resolution picked up.)