【发布时间】:2012-03-08 16:15:10
【问题描述】:
考虑这段代码:
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)。但是如果我取消注释B 的定义,则会出现以下错误(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
我知道(好吧,我想我知道)它给出这个错误的原因。
所以我的问题是:
友元函数模板类内定义如何避免重定义错误?
只要我在类中提供主模板(不是特化)的定义,我就会得到这个错误。以这种方式定义主模板还有另一个问题:它使f 函数模板的所有实例化friend 的所有Base 类模板的实例化,我也想避免。我想让f<T> 成为Base<T> 的朋友,但不是f<U> 成为Base<T> 的朋友,如果U 和T 不一样。同时,我也想提供类内部的定义。有可能吗?
【问题讨论】:
-
我看不出编译器为什么会出错,而且似乎clang人也没有看到原因,因为它是用clang编译的。
-
如果我取消注释
B的定义,GCC 和 MSVC10 都会出错。 -
@PlasmaHH:因为友元函数不是成员函数,因此可以不依赖于类模板的参数。
标签: c++ templates friend function-templates class-template