繁体   English   中英

运算符<<重载决议(C++)

[英]operator<< overload resolution (C++)

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

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

#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中找到 operator<< 并停止查找,甚至不考虑在a中正确的那个。 当您将其注释掉时,它在b中找不到它,并继续搜索a并找到它。 您可以通过在命名空间 b 中添加它来解决此问题:

using a::operator<<; 

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM