3

I want to output some private library class ns::A to the plog, so I add the operator << overload to ns::A.

The following code cannot be compiled.

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

But changing the namespace other to ns, plog, plog::detail or std can make the compiling error go away, why? The std::cout<< and std::ostringstream<< works fine anyway.

#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
}
DeiDei
  • 10,205
  • 6
  • 55
  • 80
user2709407
  • 460
  • 1
  • 4
  • 11

1 Answers1

1

In you 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
}

Your using namespace only applies to main's scope and doesn't "propagate" (to plog::Record::operator<< (const T& t)).

Then s << a; would call plog::Record::operator<< (const T& t) with T = ns::A.

So, in

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

    out << t;
    return *this;
}

out << t; (with T = ns::A) will look at namespace (With ADL):

  • global namespace
  • namespace plog (plog::Record)
  • namespace plog::detail (using namespace plog::detail;)
  • namespace std (std::ostringstream out)
  • namespace ns (ns::A)

other::operator<< is not considered, and you don't have valid match, so compile error.

Jarod42
  • 203,559
  • 14
  • 181
  • 302