代码之家  ›  专栏  ›  技术社区  ›  Resurrection

为嵌套模板类声明运算符==

  •  9
  • Resurrection  · 技术社区  · 6 年前

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

    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来解析源代码,它要求我提供 操作员== 我已经像刚才展示的那样在适当的地方实现了。

    LIVE DEMO

    1 回复  |  直到 6 年前
        1
  •  0
  •   Community CDub    5 年前

    这个错误并不遥远,因为您确实需要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关键字,因为解析器在处理 < > . This answer 很好地解释了原因:

    在名称查找(3.4)发现某个名称是模板名称后,如果该名称后跟一个<,则<始终作为模板参数列表的开头,而不会作为名称后跟小于运算符。

    现在我们回到了typename的问题。如果我们在解析代码时还不知道名称是否是模板呢?我们需要在模板名称前插入模板,如14.2/4所述。这看起来像:

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

        2
  •  -1
  •   Caleth    6 年前

    您可以有一个内联好友声明和一个大纲定义

    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 也。