当在命名空间中类并且使用模板化类型作为返回类型时,全局作用域友元运算符声明



我正在为模板化运算符和命名空间的友元语句而苦苦挣扎。如果我有点长,很抱歉,但我想好好描述一下我的问题。

首先,一些背景。暂时忘记命名空间。我有一个类A和一个需要访问其私有成员的公共运算符:

template<typename U>
struct B { U valb; };
template<typename U>
struct C { U valc; };
template<typename U,typename V>
struct A
{ 
private:
U v1; V v2;
template<typename T1,typename T2>
friend A<T1,T2> operator * ( const B<T2>&, const C<T1>& );
};
template<typename T1,typename T2>
A<T1,T2>
operator * ( const B<T2>& b, const C<T1>& c )
{
A<T1,T2> a;
a.v1 = c.valc * b.valb; // dummy
return a;
}
int main()
{
B<float> b;
C<int> c;
auto a = b * c;
}

这构建得很好。

现在,出于某种原因,我想将类A放在名称空间中(主要是为了将其从公共API中删除,用户代码将使用"sub"类型,用using声明声明(。现在麻烦开始了。

我在这个答案的基础上,这个答案涵盖了这个主题,效果很好。它解释了我需要转发声明类,然后声明运算符,在友元声明中,用::作为运算符的前缀。

该关联问题中描述的情况与我的情况之间的唯一区别是返回类型。在我的例子中,它是一个模板化的类型。这似乎是的问题(或者是吗?(

所以我尝试了一下(在线(:

template<typename U>
struct B { U valb; };
template<typename U>
struct C { U valc; };
// forward declaration of class A
namespace ns {
template<typename U,typename V> struct A;
}
// forward declaration of operator
template<typename T1,typename T2>
ns::A<T1,T2>
operator * ( const B<T2>&, const C<T1>& );
namespace ns {
template<typename U,typename V>
struct A                            // class declaration
{
template<typename T1,typename T2>
friend A<T1,T2> ::operator * ( const B<T2>&, const C<T1>& );
private:
U v1; V v2;
};
} // namespace 
// operator definition
template<typename T1,typename T2>
ns::A<T1,T2> operator * ( const B<T2>& b, const C<T1>& c )
{
ns::A<T1,T2> a;
a.v1 = c.valc * b.valb; // dummy
return a;
}
int main()
{
B<float> b;
C<int> c;
auto a = b * c;
}

这无法用构建

error: ISO C++ forbids declaration of 'operator*' with no type [-fpermissive]    
23 |         friend A<T1,T2> ::operator * ( const B<T2>&, const C<T1>& );

如果我删除::,那么操作员就不会被识别为朋友。

我做错了什么?我该如何处理这个问题?

除非friend函数模板已经声明,否则我不认为您在类定义之外定义这个函数模板:本质上,没有办法实际命名运算符。更有趣的是,操作的两种参数类型实际上在不同的命名空间中,即operator*()确实需要在与ns不同的命名空间下定义。这似乎奏效了:

template<typename U> struct B { U valb; };
template<typename U> struct C { U valc; };
// declaration of ns::A to declare the operator*
namespace ns { template<typename U,typename V> struct A; }
template<typename T1,typename T2>
ns::A<T1,T2> operator * ( const B<T2>&, const C<T1>& );
namespace ns {
template<typename U,typename V>
struct A {
template<typename T1,typename T2>
friend auto ::operator * ( const B<T2>&, const C<T1>& ) -> A<T1, T2>;
private:
U v1; V v2;
};
}
template<typename T1,typename T2>
ns::A<T1,T2> operator * ( const B<T2>& b, const C<T1>& c ) {
ns::A<T1,T2> a;
a.v1 = c.valc * b.valb; // dummy
return a;
}
int main()
{
B<float> b;
C<int> c;
auto a = b * c;
}

有关实时演示,请参阅"编译器资源管理器"链接。

最新更新