c++ - 名称查找和运算符重载如何工作?

标签 c++ operator-overloading overloading name-lookup

我想输出一些私有(private)库 class ns::Aplog ,所以我添加了 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;
     ~~~~^~~~

但是改变命名空间otherns , plog , plog::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 )将查看 namespace (使用 ADL):

  • 全局命名空间
  • 命名空间 plog ( plog::Record )
  • 命名空间 plog::detail ( using namespace plog::detail; )
  • 命名空间 std ( std::ostringstream out )
  • 命名空间 ns ( ns::A )

other::operator<<没有被考虑,你没有有效的匹配,所以编译错误。

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

相关文章:

c++ - 将 std::list 扩展为循环列表

c++ - 删除使用 "new"创建的对象

c++ - 在另一个类中实现一个类的对象

C语言重载

c# 泛型重载方法分派(dispatch)不明确

java - 为什么 Java PrintStream 必须重载其 print() 函数?

c++ - 通过*.dll 文件调用*.exe 文件并提交参数

c++ - 这段代码有什么问题?它在第二个 cin 可以执行之前终止

c++ - 为什么编译器不为模板类提供默认的 operator=?

c++ - 为什么std::string的成员运算符=左值引用不合格