【问题标题】:ostream operator << in Namespace hides other ostream::operator [duplicate]ostream operator << 在命名空间中隐藏其他 ostream::operator [重复]
【发布时间】:2018-08-09 12:49:19
【问题描述】:

使用 gcc 版本 5.2.0 (GCC) 和 --std=c++14,如果取消注释命名空间 MyNamespace 中注释掉的运算符 ostream,则以下代码不再编译。这是错误还是功能? (用g++ -c --std=c++14 x.cxx编译)

#include <string>
#include <iostream>

typedef std::pair<std::string, std::string> StringPair;

std::ostream& operator<<( std::ostream&, const StringPair &pair) {
  std::cout <<pair.first<<"."<<pair.second;
}

namespace MyNamespace {
  class MyClass {};
  //std::ostream& operator<< (std::ostream&, const MyClass &);
  void xxx ();
}

void MyNamespace::xxx () {
  StringPair pair;pair.first="1";pair.second="2";
  std::cout <<pair<<std::endl;
}

我使用运算符

x.cxx: In function ‘void MyNamespace::xxx()’:
x.cxx:18:13: error: no match for ‘operator<<’ (operand types are ‘std::ostream {aka std::basic_ostream<char>}’ and ‘StringPair {aka std::pair<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >}’)
std::cout <<pair<<std::endl;
         ^

【问题讨论】:

  • 首先您可能应该删除代码中的未定义行为,您需要从全局operator&lt;&lt; 函数中返回一些内容以获取该对。您可能应该使用作为参数传递的流而不是硬编码std::cout。不能解决你的问题,但不相关的问题往往会隐藏实际问题。
  • @Someprogrammerdude 我刚刚尝试并重现了报告的错误。我认为未定义的行为与它没有任何关系 - 这发生在编译期间
  • 这与运行代码无关。这是关于编译它。当然这种行为没有意义,但这就是我得到的:-)
  • 链接到 ideone 复制行为:ideone.com/Lgg5oL
  • @pbhd 我通过将using ::operator&lt;&lt; 添加到命名空间来编译它。但我不确定为什么需要它。您可以查看ideone.com/01ypI9

标签: c++ g++ operator-overloading language-lawyer ostream


【解决方案1】:

here 所述,这是name hiding 的一个示例。通过在命名空间MyNamespace 中定义operator&lt;&lt;,所有来自更高命名空间(如全局)的定义都被隐藏了。

请注意,如上所述here

[...]此功能不会干扰 Koenig 查找 [...],因此仍会找到来自 std:: 的 IO 运算符。

(details about Koenig lookup)

解决方案是使用using 指令引用另一个命名空间中的重载,如herehere 所述。 Michael Nastenko 在 cmets 中提到了这一点。

因此using ::operator&lt;&lt;;:: 指的是全局命名空间。

因此代码将变为:

#include <string>
#include <iostream>

typedef std::pair<std::string, std::string> StringPair;

std::ostream& operator<<(std::ostream& os, const StringPair &pair) {
    os << pair.first << '.' << pair.second;
    return os;
}

namespace MyNamespace {
    class MyClass {};
    using ::operator<<;
    std::ostream& operator<< (std::ostream&, const MyClass &);
    void xxx();
}

void MyNamespace::xxx() {
    StringPair pair("1","2");
    std::cout<<pair<<std::endl;
}

int main() {
    MyNamespace::xxx();
    return 0;
}

example on Coliru

【讨论】:

    猜你喜欢
    • 2015-02-17
    • 1970-01-01
    • 1970-01-01
    • 2013-07-28
    • 1970-01-01
    • 2011-10-17
    • 1970-01-01
    • 2016-08-15
    • 2023-03-21
    相关资源
    最近更新 更多