定义模板类的友元运算符时不一致

Inconsistency when defining friend operators of template class

提问人:user13840624 提问时间:7/6/2023 最后编辑:user13840624 更新时间:7/6/2023 访问量:75

问:

下面是一个涉及两个友元算子的 MRE 示例: 和 :operator<<operator-

#include <ostream>

template <typename T>
class container;
template <typename T>
std::ostream operator<<(std::ostream & os, const container<T> & data);
template <typename T>
container<T> operator-(const int & first, const container<T> & second);

template <typename T>
class container
{
    public:
        container<T> operator-(const container<T> & other);
        friend std::ostream operator<< <>(std::ostream & os, const container<T> & data); // this one works
        friend container<T> operator- <>(const int & first, const container<T> & second); // error: declaration of 'operator-' as non-function
};

运算符的实际定义不在这里(也不相关)。如注释所示,编译但结果为:operator<<operator-

g++:

<source>:16:29: error: declaration of 'operator-' as non-function
   16 |         friend container<T> operator- <>(const int & first, const container<T> & second); // error: declaration of 'operator-' as non-function
      |                             ^~~~~~~~
<source>:16:37: error: expected ';' at end of member declaration
   16 |         friend container<T> operator- <>(const int & first, const container<T> & second); // error: declaration of 'operator-' as non-function
      |                                     ^
      |                                      ;
<source>:16:39: error: expected unqualified-id before '<' token
   16 |         friend container<T> operator- <>(const int & first, const container<T> & second); // error: declaration of 'operator-' as non-function
      |                                       ^

咔嚓++:

<source>:16:29: error: friends can only be classes or functions
        friend container<T> operator- <>(const int & first, const container<T> & second); // error: declaration of 'operator-' as non-function
                            ^
<source>:16:38: error: expected ';' at end of declaration list
        friend container<T> operator- <>(const int & first, const container<T> & second); // error: declaration of 'operator-' as non-function
                                     ^
                                     ;
2 errors generated.

(非友元)已被声明的事实使该友元成为“非函数”。operator-operator-

为什么有效而无效?我该如何解决?朋友是否需要额外的模板参数(不是)?operator<<operator-operator-Toperator-

编辑

该问题与 密切相关。它显然在 上编译良好。

17 C ++20 模板 好友

评论

0赞 HolyBlackCat 7/6/2023
这真的是MRE吗?在我实例化模板之前,我不会遇到错误。即便如此,Clang 也不会给我任何错误,只有 GCC 会。
2赞 NathanOliver 7/6/2023
我认为这可能是一个语法问题,后来已经解决了。使用 C++ 模式编译时,代码使用最新的 GCC 和 Clang 进行编译,但在 C++17 模式下失败。godbolt.org/z/sT3n98PrG
0赞 user13840624 7/6/2023
@HolyBlackCat立即收到错误: godbolt.org/z/d9xaP4PhE
0赞 HolyBlackCat 7/6/2023
啊,我正在测试.-std=c++20
0赞 foragerDev 7/6/2023
使用最新的 CLANG 和 GCC 版本,它使用 C++20 进行编译。godbolt.org/z/4GErs18E7

答:

2赞 Ruh Roh Raggy 7/6/2023 #1

我认为你以不正确的方式宣布了它。

尝试这样做:

template <typename T>
class container;

template <typename T>
std::ostream& operator<<(std::ostream & os, const container<T> & data) { return os; }

template <typename T>
container<T> operator-(const int & first, const container<T> & second) {return second;}

template <typename T>
class container
{
    public:
        container<T> operator-(const container<T> & other);

        template <typename>
        friend std::ostream& operator<<(std::ostream & os, const container<T> & data);
        
        template <typename>
        friend container<T> operator- (const int & first, const container<T> & second);
};

现场演示:godbolt.org/z/Tbz1Yvf5T

编辑: 我注意到,如果您更改顺序(先联系操作员)。它编译得很好。 自c++11c++20

template <typename T>
class container;

template <typename T>
std::ostream operator<<(std::ostream & os, const container<T> & data);

template <typename T>
container<T> operator-(const int & first, const container<T> & second);

template <typename T>
class container
{
    public:
        friend std::ostream operator<< <>(std::ostream & os, const container<T> & data); // this one works
        friend container<T> operator- <>(const int & first, const container<T> & second); // error: declaration of 'operator-' as non-function

        // now it compiles
        container<T> operator-(const container<T> & other);
};

评论

0赞 user13840624 7/6/2023
你为什么使用 ?我正在关注 en.cppreference.com/w/cpp/language/friend(“模板好友运算符”部分)。我相信定义正确(就像在 cppreference 中一样)。template <typename>operator<<
0赞 foragerDev 7/6/2023
代码没有问题。OP 的代码与最新版本的 clang 和 gcc 编译器编译良好。可能是一些编译器语法问题。
0赞 Ruh Roh Raggy 7/6/2023
@user13840624,因为这表明您实际上声明了模板友元函数。
0赞 Ruh Roh Raggy 7/6/2023
@foragerDev 我认为这是不正确的。我不认为这与 c++17 有很大关系。而且我不认为编写需要更高语言标准才能编译的代码是好代码。我提供了用 c++11、c++14、c++17 和 c++20 编译的示例。而 OP 只能在 c++20 中编译。它不言自明。
0赞 user13840624 7/7/2023
为什么交换 es 有效?operator-()