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 f
into the class? If you define it outside, your problem disappears and you can also enforce the one-to-one relationship you want (i.e. only f<T>
is a friend of Base<T>
):
template <typename T> class Base;
template <typename U>
void f(void *ptr) {
static_cast<Base<U>*>(ptr)->run();
}
template<typename T>
class Base
{
friend void f<T>(void *ptr); //only one instanciation is a friend
protected:
virtual void run() = 0;
};
However, note that the fact that only f<T>
is a friend of Base<T>
will not prevent the following code from compiling:
B b;
f<A>(&b); // compiles, f<A> calls Base<A>::run, but the cast is wrong