为嵌套模板类声明operator ==

时间:2018-10-18 08:06:26

标签: c++ templates clang qdoc

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

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==的声明,如所示。

LIVE DEMO

2 个答案:

答案 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}}。