As described here C++11 style SFINAE and function visibility on template instantiation class member functions overshadow free functions. Using a fully qualified name usually works, however I am having a hard time with friend functions of other classes which are declared in-line. Consider the following example:
namespace N {
struct C {
friend int f(const C& c) {
return 1;
}
friend int g(const C& c) {
return 2;
}
};
struct D {
void f() {
g(C{}); // ADL finds this
::N::f(C{}); // not found dispite full qualification
}
};
}
I think I understand what the problem is, as described here What's the scope of inline friend functions? inline friend function are usually found using ADL and not really visible in the enclosing namespace.
So my question is how should I change my code to make this work (aside from renaming one of the f's)?
It's because of the friendliness:
[C++11: 7.3.1.2/3]: 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 simple name lookup until a matching declaration is provided in that namespace scope [...]. If a friend function is called, its name may be found by the name lookup that considers function from namespaces and classes associated with the types of the function arguments (3.4.2) [i.e. ADL].
The fix is to simply provide that declaration:
namespace N {
struct C {
friend int f(const C& c) {
return 1;
}
friend int g(const C& c) {
return 2;
}
};
int f(const C& c);
int g(const C& c);
struct D {
void f() {
g(C{});
::N::f(C{});
}
};
}
(live demo)
Related
Why does defining user defined literal inside the class give error?
class test
{
long double x;
public:
friend test operator""_UNIT(long double v)
{
test t;
t.x = v;
return t;
}
};
int main()
{
test T = 10.0_UNIT;
return 0;
}
ERROR:
unable to find numeric literal operator 'operator""_UNIT'
Note: It is possible to define any friend function inside the class.
class test
{
int x;
public:
test():x(10) {}
friend std::ostream& operator<< (std::ostream& o, test t)
{
o << t.x ;
return o;
}
};
int main() {
test T;
std::cout << T;
return 0;
}
The same friend user defined literal can be defined outside the class.
class test
{
long double x;
public:
friend test operator""_UNIT(long double v);
};
test operator""_UNIT(long double v)
{
test t;
t.x = v;
return t;
}
int main()
{
test T = 10.0_UNIT;
return 0;
}
Does this quote from the standard have an impact?
A friend function defined in a class is in the (lexical) scope of the
class in which it is defined. A friend function defined outside the
class is not
The issue you're running into is that, from [namespace.memdef]:
The friend declaration does not by
itself make the name visible to unqualified lookup (3.4.1) or qualified lookup (3.4.3).
The way they are found is through argument dependent lookup, [basic.lookup.argdep]:
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).
std::ostream& operator<< (std::ostream& o, test t) is found due to argument-dependent lookup on the second argument.
When you define _UNIT externally to the class, it makes the function visible.
However, when you define _UNIT inline - it's not visible to normal lookup and the only argument (double) does not have any associated namespaces so there's no way for it to be found with argument-dependent lookup either.
I am trying to list all the differences between helper friend free function defined outside class and helper friend free function defined inside the class.
I am thinking about following the rule: declare all helper function as friend inside the body of the class but it is not wide spreaded so I wonder if I have not missed some drawbacks.
Let's consider we have a namespace containing tens of classes wich are ranges, for this example we put the begin inside the body of the class and end outside the body of the class (obviously the aim is not to comment this inconsistance)
namespace nm
{
struct A
{
// ...
auto begin();
auto end();
friend auto
begin(const A& a)
{
return a.begin();
}
friend auto
end(const A&);
};
inline auto
end(const A& a)
{
return a.end();
}
// And tens of other class declaring `begin` and `end`.
}
Pros:
if a user state begin(x); and x does not implement begin the program compiler will not list all the overloaded begin, since begin is only accessible if x actualy implement begin helper function. (begin is not visible at namespace scope: [classes.friends],item 7 in N4659, A friend function defined in a class is in the (lexical) scope of the class in which it is defined). If a user declare end(x) and the type of x is declared in the namespace nm the compiler will list all the tens of end declaration ad potential overloads.
begin() is not accessible through user defined conversion functions which could be unwanted.
Cons:
if a user state begin(x) and x does not implement begin the user will not be informed that begin actualy exists for other class of the namespace.
begin() is not accessible through user defined conversion functions which could be wanted.
Have I missed some implications? What about if the helper fonction takes two arguments? If it is operator== for exemple?
What "A friend function defined in a class is in the (lexical) scope of the class in which it is defined" means is that any friend function declared in the body of A belongs to A's namespace (the lexical scope of A).
In other words:
namespace ns {
class A
{
static int bar()
{
return 21;
}
public:
inline friend int foo(A& a)
{
return A::bar();
}
friend int foo2(A& a);
};
} // namespace ns
int foo2(ns::A& a) // this will fail, since only ns::foo2() is friend of A
{
return foo(a);
}
namespace ns {
int foo2(ns::A& a) // this works
{
return foo(a);
}
} // namespace ns
int main(int, const char**, const char**)
{
ns::A var;
return ns::foo(var) + ns::foo2(var);
}
I'm currently reading "Effective C++" and there is a chapter that contains code similiar to this:
template <typename T>
class Num {
public:
Num(int n) { ... }
};
template <typename T>
Num<T> operator*(const Num<T>& lhs, const Num<T>& rhs) { ... }
Num<int> n = 5 * Num<int>(10);
The book says that this won't work (and indeed it doesn't) because you can't expect the compiler to use implicit typecasting to specialize a template.
As a soluting it is suggested to use the "friend" syntax to define the function inside the class.
//It works
template <typename T>
class Num {
public:
Num(int n) { ... }
friend
Num operator*(const Num& lhs, const Num& rhs) { ... }
};
Num<int> n = 5 * Num<int>(10);
And the book suggests to use this friend-declaration thing whenever I need implicit conversion to a template class type. And it all seems to make sense.
But why can't I get the same example working with a common function, not an operator?
template <typename T>
class Num {
public:
Num(int n) { ... }
friend
void doFoo(const Num& lhs) { ... }
};
doFoo(5);
This time the compiler complaints that he can't find any 'doFoo' at all.
And if i declare the doFoo outside the class, i get the reasonable mismatched types error. Seems like the "friend ..." part is just being ignored.
So is there a problem with my understanding? What is the difference between a function and an operator in this case?
The reason is that here
doFoo(5);
the compiler has no way of finding foo, given an int parameter. This would be the equivalent of calling your friend operator like this:
Num<int> n = 5 * 10;
This will "work", but not by calling the friend operator* defined in your Num class, but by calling the built-in operator* for integers, and then using the implicit conversion from Num's converting constructor.
The core problem is lookup. A friend declaration provides a declaration of a namespace level function, but the declaration is only available inside the class that is befriending it. In the example the book provides that is not an issue: the function takes two arguments of the enclosing type, as long as one of them is of the enclosing type, Argument Dependent Lookup will look inside the definition of the class and find the operator. In your case that is not the case, since there is a single argument and that needs a conversion, the compiler will not look inside the definition of the class.
Note that this is regardless of templates and conversions:
class A {
friend void f( int ) {}
friend void g( int, A ) {}
};
int main() {
f(5); // Error: lookup cannot find 'f' declared *only* inside A
g(5,A()); // Ok, one argument is 'A', lookup will find the function
}
In the case above, where there are no templates involved, you could potentially add a declaration at namespace level to fix it, but that is not really an option for template classes.
class A {
friend void f() { std::cout << "inside A\n"; }
};
void f(int); // only declaration
int main() {
f(5); // "inside A"
}
This cannot be done for a template (and for all instantiating types) as the friend declaration is a declaration of a non-templated function. Although you could can play with the code just for the sake of testing:
template <typename T>
struct Num {
Num(int x) ...
friend void f( Num const & );
};
Num<int> f(Num<int> const &); // only declaration
int main() {
f(5);
}
Yes these code compiler do not know how to work with it .
like
doFoo(5)
compiler do not know 5 is int
I was trying to implement the copy-and-swap idiom in my custom Matrix class, and I ran into some trouble with the implementation of swap() in the way suggested in the linked-to question:
(The compiler I used is the one from MS VS2010 IDE, dialect is good old-fashioned C++03.)
// matrix.h
namespace my_space
{
template<typename T> class Matrix
{
public:
/* ... */
friend void swap(Matrix<T> &first, Matrix<T> &second)
{
using std::swap;
swap(first.width_, second.width_);
swap(first.height_, second.height_);
swap(first.data_, second.data_);
}
};
} // namespace
Now I have trouble reaching regular std::swap() in the code for functions residing in this namespace:
// some_code.cpp:
#include "matrix.h"
#include <algorithm>
using namespace my_space;
using namespace std;
// SomeClass is part of my_space!
void SomeClass::some_function()
{
int a = 3, b = 7;
swap(a,b); // I wan't std::swap!
}
Unfortunately, for some reason, my_space::swap() for Matrix seems to alias all other calls to std::swap(), and I've no idea why since the arguments don't fit and ADL should favor std::swap:
1>f:\src\some_code.cpp(653): error C3767: 'swap': candidate function(s) not accessible
1> could be the friend function at 'f:\src\matrix.h(63)' : 'swap' [may be found via argument-dependent lookup]
(The error repeats 10 times for every line where I'm trying to use std::swap)
Does my_space::swap() always overrule std::swap() in my_space, even if the arguments don't fit? It's not as if std::swap() is not visible, and it worked OK before my_space::swap() was created.
The approach taken by STL containers uses a member function and then overload the static function. For example:
template<class T, class Alloc=std::allocator<T> >
class vector
{
T *data;
size_t n;
size_t max_n;
public:
void swap(vector<T, Alloc> &other)
{
swap(this->data, other.data);
swap(this->n, other.n);
swap(this->max_n, other.max_n);
}
};
template<class T, class A>
void swap(vector<T, A> &lhs, vector<T, A> &rhs)
{
lhs.swap(rhs);
}
In the suggested Matrix class, simply take the same approach...
namespace my_space
{
template<typename T>
class Matrix
{
unsigned width_;
unsigned height_;
std::vector<T> data_;
public:
void swap(Matrix<T> &other)
{
std::swap(this->width_, other.width_);
std::swap(this->height_, other.height_);
std::swap(this->data_, other.data_); // calls this->data_.swap(other.data_);
}
};
}
namespace std
{
template<typename T>
void swap(my_space::Matrix<T> &lhs, my_space::Matrix<T> &rhs)
{
lhs.swap(rhs);
}
}
Include the following line in Matrix:
template<typename U> friend void swap(Matrix<U> &first, Matrix<U> &second);
and define the swap outside of the class. The reason you are getting the error function template has already been defined, is because each instantiation of Matrix<unsigned short> and Matrix<char> will contain the same defintion of your swap function since you defined the friend function inside of the Matrix template.
The following builds cleanly for me with VC++ 2010 SP1:
Matrix.h:
#pragma once
#include <algorithm>
#include <vector>
namespace my_space
{
template<typename T>
class Matrix
{
public:
Matrix(unsigned const w, unsigned const h)
: width_(w), height_(h), data_(w * h)
{ }
private:
unsigned width_;
unsigned height_;
std::vector<T> data_;
friend void swap(Matrix& lhs, Matrix& rhs)
{
using std::swap;
swap(lhs.width_, rhs.width_);
swap(lhs.height_, rhs.height_);
swap(lhs.data_, rhs.data_);
}
};
}
.cpp:
#include "Matrix.h"
int main()
{
using namespace my_space;
using std::swap;
int a(0), b(1);
swap(a, b);
Matrix<int> c(2, 3), d(4, 5);
swap(c, d);
Matrix<short> e(6, 7), f(8, 9);
swap(e, f);
}
Since you didn't post an SSCCE (hint, hint), it's very difficult to see exactly where you're going wrong, but you can use this as a starting point to narrow down your issue.
If the code is really like what you posted, that is an issue with the compiler. The code compiles fine in clang++, as it should.
Friend declarations are strange in that they declare a function that has namespace scope, but the declaration is only available though ADL, and even then, only if at least one of the arguments is of the type of the class that has the friend declaration. Unless there is a namespace level declaration, the function is not available in the namespace scope.
Test 1
(function not available at namespace level with out an explicit declaration):
namespace A {
struct B {
friend void f(); // [1]
};
// void f(); // [2]
}
void A::f() {} // [3]
In [1] we add a friend declaration, that declares void A::f() as a friend of A::B. Without the additional declaration in [2] at namespace level, the definition in [3] will fail to compile, since being outside of the A namespace that definition is not also a self-declaration.
The implication here is that, because the function is not available for lookup at namespace level, but only through ADL on Matrix<T> (for some particular instantiating type T), the compiler cannot possibly find that as a match to a swap of two int values.
In his answer, Jesse Good states that each instantiation of Matrix and Matrix will contain the same defintion of your swap function since you defined the friend function inside of the Matrix template which is completely absurd.
A friend function that is defined inside the class will declare and define a namespace level function, and again, the declaration will only be available inside the class and accessible through ADL. When this is done inside a template it will define a non-templated free function at namespace level for each instantiation of the template that uses the function. That is, it will generate different definitions. Note that inside the class template scope, the name of the template identifies the specialization that is being instantiated, that is, inside Matrix<T>, the identifier Matrix does not name the template, but one instantiation of the template.
Test 2
namespace X {
template <typename T>
struct A {
friend void function( A ) {}
};
template <typename T>
void funcTion( A<T> ) {}
}
int main() {
using namespace X;
A<int> ai; function(ai); funcTion(ai);
A<double> ad; function(ad); funcTion(ad);
}
$ make test.cpp
$ nm test | grep func | c++filt
0000000100000e90 T void X::funcTion<double>(A<double>)
0000000100000e80 T void X::funcTion<int>(A<int>)
0000000100000e70 T X::function(A<double>)
0000000100000e60 T X::function(A<int>)
The output of nm is the list of symbols, and c++filt will translate the mangled names into the equivalent in C++ syntax. The output of the program clearly shows that X::funcTion is a template that has been instantiated for two types, while X::function are two overloaded non-templated functions. Again: two non-templated functions.
Claiming that it would generate the same function makes little sense, consider that it had a function call, say std::cout << lhs, the code must pick the correct overload of operator<< for the current instantiation of the function. There is no single operator<< that can take say a int and an unsigned long or std::vector<double> (Nothing inhibits you from instantiating the template with any type.
The answer by ildjarn proposes an alternative, but provides no explanation of the behavior. The alternative works because a using-directive is completely different from a using-declaration. In particular, the former (using namespace X;) modifies lookup so that the identifiers in namespace X are available at namespace level in one of the enclosing namespaces of the current piece of code (if you build a tree of namespaces, the declarations would be available where the branch containing X meets the branch containing the code where the using-directive is used).
On the other hand, a using-declaration (using std::swap;) provides a declaration of the function std::swap in the context where the using-declaration is present. This is why you must use using-declarations and not using-directives to implement your swap functions:
Test 3
namespace Y { struct Z {}; void swap( Z&,Z& ); }
namespace X {
struct A { int a; Y::Z b; };
void swap( A& lhs, A& rhs ) {
//using namespace std; // [1]
using std::swap; // [2]
swap( lhs.a, rhs.a ); // [3]
swap( lhs.b, rhs.b ); // [4]
}
}
If we had used a using-directive [1], the symbols from the ::std namespace would be available for lookups performed inside the function ::X::swap(X::A&,X::A&) as if they had been declared in :: (which is the common ancestor of ::std and ::X). Now the swap in [3] will not find any swap function through ADL, so it will start searching for swap functions in the enclosing namespace. The first enclosing namespace is X, and it does contain a swap function, so lookup will stop and overload resolution will kick in, but X::swap is not a valid overload for swap(int&,int&), so it will fail to compile.
By using a using-declaration we bring std::swap declaration to the scope of X::swap (inside the function!). Again, ADL will not be applied in [3], and lookup will start. In the current scope (inside the function) it will find the declaration of std::swap and will instantiate the template. In [4], ADL does kick in, and it will search for a swap function defined inside the ::Y::Z function and/or in ::Y, and add that to the set of overloads found in the current scope (again, ::std::swap). At this point, ::Z::swap is a better match than std::swap (given a perfect match, a non-templated function is a better match than a templated one) and you get the expected behavior.
I got this example from my book, but I have no idea how to actually call the ticket function. This is the code:
#include <iostream>
class Manager {
public:
template<typename T>
friend int ticket() {
return ++Manager::counter;
}
static int counter;
};
int main()
{
Manager m;
std::cout << "ticket: " << ticket<int>() << std::endl;
}
I get the "candidate function(s) not accessible" error message.
A few points will help you figure out what's going on here:
I) Friend function definitions within classes can only be found by Argument dependent lookup when called from outside the class definition.
II) Function templates that are supplied explicit template arguments do not undergo ADL unless the compiler is given some explicit help in identifying the call as a function call.
III) Argument dependent lookup (ADL) only works for user defined types.
A few examples will better illustrate each of the above points:
//------------------------
struct S
{
friend int f(int) { return 0; } // 1
friend int f(S) { return 0; } // 2
};
S s;
int i = f(3); // error - ADL does not work for ints, (III)
int j = f(s); // ok - ADL works for UDTs and helps find friend function - calls 2 (III)
// so how do we call function 1? If the compiler won't find the name via ADL
// declare the function in the namespace scope (since that is where the friend function
// gets injected)
int f(int); // This function declaration refers to the same function as #1
int k = f(3); // ok - but not because of ADL
// ok now lets add some friend templates and make this interesting
struct S
{
friend int f(int) { return 0; } // 1
friend int f(S) { return 0; } // 2
template<class T> friend int g(int) { return 0; } // 3
template<class T> friend int g(S) { return 0; } // 4
template<class T> friend int g() { return 0; } // 5
};
S s;
int k = g(5); // error - no ADL (III)
int l = g(s); // ok - ADL - calls 4
int m = g<int>(s); // should call 4 - but no ADL (point II above)
// ok so point II above says we have to give the compiler some help here
// We have to tell the compiler that g<int> identifies a function
// The way to do that is to add a visible dummy template function declaration
template<class /*Dummy*/, class /*TriggerADL*/> void g();
int m = g<int>(s); // ok - compiler recognizes fun call, ADL triggered - calls 4
int n = g<int>(3); // still not ok - no ADL for ints
// so how do we call either function 3 or 5 since we cannot rely on ADL?
// Remember friend functions are injected into the outer namespace
// so lets just declare the functions in the outer namespace (as we did above)
// both these declarations of g below refer to their counterparts defined in S
template<class T> int g(int);
template<class T> int g();
int o = g<int>(3); // ok
int p = g<int>(); // ok
// Of course once you have these two declarations at namespace scope
// you can get rid of the Dummy, TriggerADL declaration.
Ok so now lets return to the Vandevoorde example that you quoted, and now this should be easy:
#include <iostream>
class Manager {
public:
template<typename T>
friend int ticket() {
return ++Manager::counter;
}
static int counter;
};
int Manager::counter;
template<class T> int ticket(); // <-- this should work with a conformant compiler
int main()
{
Manager m;
std::cout << "ticket: " << ticket<int>() << std::endl;
}
Hope that helps :)
Hotfix
There is a hot-fix available, but read the below explanation if you want to understand what's going on.
#include <iostream>
template<typename T> int ticket();
class Manager {
public:
template<typename T>
friend int ticket() {
return ++Manager::counter;
}
static int counter;
};
int Manager::counter; // don't forget the definition
int main() {
Manager m;
std::cout << "ticket: " << ticket<int>() << std::endl;
}
As the snippet shows, you have to declare the template to make it visible when you call it.
Friend function definitions
This is confusing, since there are some rules in the way in this case. Some basic points, and then some other points.
struct A {
friend void f(A*) { std::cout << "hello"; }
};
What does it do? It defines a friend function. Such a function is a member of the enclosing namespace. It's not a class member, even though it is defined within a class! The fact that it's defined within a class only changes the lexical scope of that function: It can refer to that class' members directly, without preceding the class-name.
Most importantly, though, the function is not visible after being declared. You cannot take its address doing something like this, for example
&f
The only way that the function would work is using argument dependent lookup. A lookup that ends up having that class as its associated class will consider that friend function. That means that the following works:
f((A*)0);
It works because the call includes an argument with type that has the class included. In that case, the class is an associated class, and the friend declaration will be considered.
The following won't work, for example
f(0);
Because it has no idea that it should look within A to find a friend declaration. A friend function definition of a function without an argument won't be found, because there is no argument dependent lookup happening, then.
Friend function definition for templates
In addition to the fact that your call does not include arguments, it has another problem. If you define a friend function template, the matter is more complicated. There is a rule that says that if the compiler sees T<A1, A2, A3>, that this only refers to a template specialization if T actually resolves to a template. Consider
ticket < int > ()
The compiler can't resolve ticket, because it is not visible to normal lookup. Therefor, the rule says that ticket<int> does not refer to a function. It has to be parsed as a relational expression, yielding to the following
(ticket < int) > ()
That will be a syntax error, because int is not a value, and () is neither a value.
Example
Here is an example where it matters.
struct A {
template<int I> friend void f(A*) { }
};
// try to comment this out
template<typename Dummy> void f();
int main() {
f<1>((A*)0);
}
That compiles. It compiles because f resolves to a template (although a completely different one that can't even accept a non-type template argument - but that doesn't matter!). But a Standard conforming compiler will not compile the snippet once you comment out the second declaration, because it's compiled as a relational expression (less-than and smaller-than) and it will not find symbol f.
Read this thread for further information: What am I missing in this template toy example?.
I do get the same error using the MS VS++ compiler. According to the docs on MSDN:
http://msdn.microsoft.com/en-us/library/h2x4fzdz(VS.80).aspx
Friends are not in the class's scope,
and they are not called using the
member-selection operators (. and –>)
unless they are members of another
class. A friend function is declared
by the class that is granting access.
So friend functions are not actually part of the class and should therefore not be defined in class scope. Define the function outside of the class:
#include <iostream>
class Manager {
public:
template<typename T>
friend int ticket();
static int counter;
};
template<typename T>
int ticket() {
return ++Manager::counter;
}
int Manager::counter;
int main()
{
Manager m;
std::cout << "ticket: " << ticket<int>() << std::endl;
}
Why not make it static instead?
#include <iostream>
class Manager {
public:
template<typename T>
static int ticket()
{
return ++Manager::counter;
}
static int counter;
};
int main()
{
Manager m;
std::cout << "ticket: " << Manager::ticket<int>() << std::endl;
}
Though really, it doesn't have to be a template either. I assume you needed information specifically about friend templates?