考虑这段代码:
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() {}
};
*/
现在编译得很好(ideone http://ideone.com/VU72N)。但如果我取消注释定义B
,然后它给出以下错误(ideone http://ideone.com/Plwrr):
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 (好吧,我想我知道)给出此错误的原因。
所以我的问题是:
在类内定义友元函数模板时如何避免重定义错误?
只要我提供定义主模板(不是专业化)在课堂上,我会得到这个错误。以这种方式定义主模板还存在另一个问题:它使所有实例化f
函数模板friend
的所有实例Base
类模板,我也想避免。我要实现f<T>
的朋友Base<T>
但不是f<U>
的朋友Base<T>
if U
and T
不一样。同时我也想提供类内部的定义。是否可以?
你真的需要定义吗f
进班级?如果您在外部定义它,您的问题就会消失,并且您还可以强制执行您想要的一对一关系(即仅f<T>
是...的朋友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;
};
但请注意,事实是仅f<T>
是...的朋友Base<T>
不会阻止以下代码的编译:
B b;
f<A>(&b); // compiles, f<A> calls Base<A>::run, but the cast is wrong
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)