Probably been asked before, but all this is approaching the limit of my comprehension and cognizance of C++, so I\'m a little slow in understanding what\'s being talked about an
The problem is not with friend
.
The problem is with this function itself:
template
void swap(typename Foo::Bar& b1, typename Foo::Bar& b2) {} // line 26
Deducing template parameter T
from nested class is not possible, see: Output a nested class inside a template or even better this answer: https://stackoverflow.com/a/4092248/1463922
To give example why it cannot be done, consider this function:
template
void foo(typename A::Bar);
And this A definition:
template
struct A { typedef int Bar; };
And this call:
int a;
foo(a);
What is T
in this example? Is it int
because A
is int
, OR float
because
A
is int
too OR whatever you want.... The question is what function you are calling foo
or foo
or ...
Or to give example more closer to question:
template
struct Foo {
struct Bar {};
};
It seems that compiler should have no problems with resolving this:
template
void resolve(typename Foo::Bar*);
But compiler even here has problems because it is not sure if specialization of some other class will not use inner struct of other class, like this:
template
struct Foo {
typedef Foo::Bar Bar;
};
So for:
Foo::Bar b;
resolve(&b);
Compiler has no chance to know which version to call:
resolve(Foo::Bar*);
// or
resolve(Foo::Bar*);
// ^
What can I advice you - use inline friend - but implement it with some other template class. This works - but I am sure this is a little over-engineered:
template
class ImplementSwap;
template
class Foo {
public:
struct Bar {
int a;
Bar() {}
~Bar() {}
friend class ImplementSwap>;
friend void swap(Foo::Bar& b1, Foo::Bar& b2)
{ ImplementSwap>::doSwap(b1, b2); }
Bar(Bar&& b) { swap(*this, b); }
};
};
template
class ImplementSwap> {
public:
static void doSwap(typename Foo::Bar&,typename Foo::Bar&);
};
template
void ImplementSwap>::doSwap(typename Foo::Bar&,typename Foo::Bar&)
{
// this one is not inline....
}
I made Bar public to do this test:
Foo::Bar a = Foo::Bar(); // move constructor
int main() {
swap(a,a); // explicit swap
}
[OLD]
My previous answer was completely wrong, and first comments refer to it.
friend void swap<>(typename Foo::Bar&, typename Foo::Bar&);
// ^^
[/OLD]