Consider this code:
template<typename T>
class Base
{
template<typename U>
friend void f(void *ptr) {
static_cast<Base<U>*>(ptr)->run();
}
protected:
virtual void run() = 0;
};
class A : public Base<A>
{
protected:
virtual void run() {}
};
/*
class B : public Base<B>
{
protected:
virtual void run() {}
};
*/
It compiles fine now (ideone). But if I uncomment the definition of B, then it gives the following error (ideone):
prog.cpp: In instantiation of ‘Base<B>’:
prog.cpp:20: instantiated from here
prog.cpp:6: error: redefinition of ‘template<class U> void f(void*)’
prog.cpp:6: error: ‘template<class U> void f(void*)’ previously defined here
I know (well,I think I know) the reason why it gives this error.
So my question is :
How to avoid redefinition error in case of in-class definition of friend function template?
As long as I provide the definition of the primary template (not specialization) inside the class, I will get this error. There is also another problem with defining primary template in this way: it makes all instantiations of f function template friend of all instantiations of Base class template, which I also would like to avoid. I want to make f<T> a friend of Base<T> but not f<U> a friend of Base<T> if U and T are not same. At the same time, I also want to provide the definition inside the class. Is it possible?
Do you really need to define
finto the class? If you define it outside, your problem disappears and you can also enforce the one-to-one relationship you want (i.e. onlyf<T>is a friend ofBase<T>):However, note that the fact that only
f<T>is a friend ofBase<T>will not prevent the following code from compiling: