我想将一些私有(private)库class ns::A输出到plog中,因此我将operator <<重载添加到ns::A中。

以下代码无法编译。

error: no match for ‘operator<<’ (operand types are ‘std::ostringstream’ {aka ‘std::__cxx11::basic_ostringstream<char>’} and ‘const ns::A’)
     out << t;
     ~~~~^~~~

但是将命名空间other更改为nsplogplog::detailstd可以使编译错误消失,为什么?
无论如何,std::cout<<std::ostringstream<<可以正常工作。
#include <iostream>
#include <sstream>

namespace plog {
namespace detail {}
struct Record {
  template <typename T>
  Record& operator<<(const T& t) {
    using namespace plog::detail;

    out << t;
    return *this;
  }
  std::ostringstream out;
};
}

namespace ns {
struct A {};
}

namespace other {}

namespace other { // changing other to ns, plog, plog::detail or std will fix compiling error
inline std::ostream& operator<<(std::ostream& os, const ns::A& a) { return os; }
}

int main() {
  ns::A a;
  using namespace plog;
  using namespace plog::detail;
  using namespace ns;
  using namespace other;
  std::cout << a;
  std::ostringstream oss;
  oss << a;
  plog::Record s;
  s << a; // compiling error
}

最佳答案

在你main:

int main() {
  ns::A a;
  using namespace plog;
  using namespace plog::detail;
  using namespace ns;
  using namespace other;
  std::cout << a;
  std::ostringstream oss;
  oss << a;
  plog::Record s;
  s << a; // compiling error
}

您的using namespace仅适用于main的范围,而不能“传播”(适用于plog::Record::operator<< (const T& t))。

然后s << a;将使用plog::Record::operator<< (const T& t) = T调用ns::A

所以,在
Record& operator<<(const T& t)
{
    using namespace plog::detail;

    out << t;
    return *this;
}
out << t;(使用T = ns::A)将查看命名空间(使用ADL):
  • 全局 namespace
  • namespace plog(plog::Record)
  • namespace plog::detail(using namespace plog::detail;)
  • namespace std(std::ostringstream out)
  • namespace ns(ns::A)

  • 不考虑使用other::operator<<,并且您没有有效的匹配项,因此编译错误。

    关于c++ - 名称查找和运算符重载如何工作?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50811985/

    10-10 06:03