我在另一个模板类中有以下嵌套的模板类:
template<typename T>
struct A
{
template<typename V>
struct B {};
};
嵌套类型operator==
的非成员B
的签名是什么?以下朴素的尝试不起作用:
template<typename T, typename V>
bool operator==(A<T>::B<V> left, A<T>::B<V> right);
Clang,GCC和MSVC会给出各种不同的错误和/或提示出了什么问题,例如缺少template
关键字,但我没有解决该错误的尝试。
请注意,这显然可行:
template<typename T>
struct A
{
template<typename V>
struct B {};
template<typename V>
friend bool operator==(B<V> left, B<V> right)
{
return true;
}
};
但是,我需要行外非成员声明的原因是要使用qdoc对其进行记录。 qdoc使用clang解析源代码,它要求我提供实际上已经实现的operator==
的声明,如所示。
答案 0 :(得分:0)
错误距离还不太远,因为您确实需要template关键字,但也需要typename来表示依赖类型。一个有效的示例的格式为:
template <typename T, typename V>
bool operator==(typename A<T>::template B<V> left,
typename A<T>::template B<V> right) {...}
尽管我会建议:
template <typename T, typename V>
using operator_type = typename A<T>::template B<V>;
template <typename T, typename V>
bool operator==(operator_type<T, V> left,
operator_type<T, V> right) {...}
作为减轻某些所需的深奥语法的一种手段。这是一种奇怪的事情,您可能希望typename足以表示:: B是A的从属名称,但是您仍然需要template关键字,因为解析器在处理{{1}时非常混乱}和<
。 This answer很好地解释了原因:
在名称查找(3.4)发现名称是模板名称之后,如果此名称后跟<,则始终将<视为模板参数列表的开头,而绝不作为其后的名称小于运算符。
现在,我们回到与typename相同的问题。如果在解析代码时我们还不知道名称是否是模板怎么办?根据14.2 / 4的指定,我们需要在模板名称之前插入模板。看起来像:
>
答案 1 :(得分:-1)
您可以有一个内联朋友声明和一个大纲定义
template<typename T>
struct A
{
template<typename V>
struct B
{
friend bool operator==(B left, B right);
};
};
template <typename T, typename V>
bool operator==(typename A<T>::template B<V> left, typename A<T>::template B<V> right)
{
return true;
}
但是gcc警告
警告:朋友声明
bool operator==(A<T>::B<V>, A<T>::B<V>)
声明一个非模板函数[-Wnon-template-friend]注意:(如果这不是您想要的,请确保该功能 模板已经声明,并在函数后添加
<>
在这里命名)
要解决该警告,我们必须在operator==(B left, B right)
的定义之前转发声明B
,该定义只能在A
内,这将迫使它成为{的朋友{1}}。