在类内定义友元函数模板时如何避免重定义错误?

2024-01-09

考虑这段代码:

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(使用前将#替换为@)

在类内定义友元函数模板时如何避免重定义错误? 的相关文章

随机推荐