[英]Redefinition error when defining friend function inside class template
[英]Friend operator in template struct raises redefinition error
考虑以下代码:
template<typename T,typename K>
struct A{
friend std::ostream& operator<<(std::ostream& out, K x) {
// Do some output
return out;
}
};
int main(){
A<int,int> i;
A<double,int> j;
}
它不编译,因为A的两个实例化实例化operator<<
两次具有相同的签名,所以我收到此错误:
test.cpp:26:25: error: redefinition of ‘std::ostream& operator<<(std::ostream&, int)’
friend std::ostream& operator<<(std::ostream& out, K x) { return out; }
^
test.cpp:26:25: error: ‘std::ostream& operator<<(std::ostream&, int)’ previously defined here
如何解决这个问题? 如果该运算符可能具有两个不同实例的相同签名,那么如何在模板中拥有友元运算符? 如何在不触发重新定义错误的情况下解决此问题?
我觉得在宣布这样的朋友时没有任何用处,不过这就是你如何做到的:
template<typename T, typename K>
struct A{
template<typename L>
friend std::ostream& operator<<(std::ostream& out, L const &x);
};
template<typename T>
std::ostream& operator<<(std::ostream& out, T const &x) {
// ...
return out;
}
编辑:
另一种选择可能更接近你想要的是:
template<typename T>
std::ostream& operator<<(std::ostream& out, T const &x);
template<typename T, typename K>
struct A{
friend std::ostream& operator<<<K>(std::ostream& out, K const &x);
};
template<typename T>
std::ostream& operator<<(std::ostream& out, T const &x) {
// ...
return out;
}
但是真的不确定你为什么要这样。 恕我直言,你的设计有严重的缺陷。
您的问题以下列方式出错。
假设它是一个存根,你的类有一些私有的东西,它需要声明一个朋友,这样做的目的是朋友是类本身的外部,但可以访问其中的私有。
在您的情况下,您将参数的流功能声明为朋友。 那也行。 这意味着如果有人创建了一个类Bar
并且想要定义一个Bar
如何流式传输,那么它们的实现可以访问任何类型T
A<T,Bar>
中的任何内容。
模板与operator<<( ostream&, int)
的冲突实际上并不是问题,因为编译器知道要选择哪一个。 它总是会选择非模板化的精确匹配。 你的问题是你有两个模板化的,编译器不能在它们之间进行选择,因为它们都是同等有效的。
也许这样的事情是你真正想要实现的目标
template< typename X, typename Y >
struct A
{
friend void a_print( std::ostream& Y const & ); // foo external function with Y as parameter, can access this
};
std::ostream & operator<<( std::ostream & out, Bar const& bar )
{
a_print( out, bar );
return out;
}
void a_print( Bar const& bar, std::ostream & out )
{
// implement and call private members of A<Foo, Bar>
return out;
}
您可以将流模板设为朋友,并使用特定实现实现Bar的流式传输。
将方法分解为基类:
template <typename K>
struct ABase
{
friend std::ostream& operator<<(std::ostream& out, K x) {
// Do some output
return out;
}
};
template <typename T,typename K>
struct A : public ABase<K>
{};
如果要流式传输A
对象,则应该使用正确的签名
template<typename T,typename K>
struct A{
friend std::ostream& operator<<(std::ostream& out, const A& x) {
// Do some output
return out;
}
};
拿A<T,K>
你可以访问私人会员,而不是K
如果没有办法从K获得A(并且如果K
是int
则不能),使<<(ostream&,K)
成为A
的朋友没有任何好处。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.