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
}
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):
plog (plog::Record)plog::detail (using namespace plog::detail;)std (std::ostringstream out)ns (ns::A)other::operator<< is not considered, and you don't have valid match, so compile error.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With