微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

运算符<< 重载解析 (C++)

如何解决运算符<< 重载解析 (C++)

下面的代码给出了 a::b::print 函数中的错误Invalid operands to binary expression ('std::ostream' (aka 'basic_ostream<char>') and 'Foo')

如果我注释掉命名空间 operator<< 中的 b 重载,错误就会消失。但我不明白为什么这会有所不同,因为它与 namspace operator<< 中的 a 重载具有不同的签名。怎么回事?!

#include <iostream>

class Foo {};

namespace a {

  std::ostream &operator<<(std::ostream &os,Foo &foo);
  void print(Foo& foo) {
    std::cout << foo;
  }

  namespace b {
    std::ostream &operator<<(std::ostream &os,double d); // uncomment to resolve error
    void print(Foo& foo) {
      std::cout << foo; // error here
    }
  }
}

解决方法

由于命名空间 b 嵌套在命名空间 a 内,b 中声明的名称将隐藏 a 中声明的名称。在 a::b::print 中进行名称查找时,它会搜索 b如果没有找到它要查找的内容,则继续在 a 中搜索。所以它确实在 b 中找到 operatora 中的正确操作符。当您将其注释掉时,它不会在 b 中找到它,而是继续搜索 a 并找到它。你可以通过在命名空间 b 中添加它来解决这个问题:

using a::operator<<; 

但是,您的代码的真正问题是您没有正确使用 ADL(参数相关查找)。操作用户定义类型的操作符应该与它们操作的类型位于相同的命名空间中。 ADL 所做的是添加额外的名称空间以进行搜索,以便调用涉及的任何参数(或模板参数)都将自动考虑其名称空间。 (这就是为什么当您的代码位于 std 之外时,您可以将 std 命名空间中提供的运算符用于内置类型。)

因此将 operator<< 移出命名空间 a 并移入 Foo 所在的相同(全局)命名空间。或者,也许更好,将 Foo 移到命名空间 a 中。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。