9

我在另一个模板类中有以下嵌套模板类:

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==我已经实际实现的声明,就像刚才显示的那样。

现场演示

4

2 回答 2

0

错误并不算太远,因为您确实需要模板关键字,而且还需要 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 关键字,因为解析器在处理时会变得非常混乱<and >这个答案很好地解释了原因:

在名称查找 (3.4) 发现一个名称是一个模板名称后,如果这个名称后跟一个 <,则 < 总是被视为模板参数列表的开头,而不是一个名称后跟 less-比运营商。

现在我们回到与 typename 相同的问题。如果我们在解析代码时还不知道名称是否是模板怎么办?我们需要在模板名称之前插入模板,如 14.2/4 所指定。这看起来像:

t::template f<int>(); // call a function template

于 2019-06-28T17:15:16.233 回答
-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,这将迫使它成为A也的朋友。

于 2018-10-18T09:51:45.503 回答