I'm reading a book. Obviously there are some failures in it.
In the code below, how can I access plant::operator<<
in run()
and plant::debug::operator<<
in diagnostic()
? The compiler can't decide between multiple operator<<
in method diagnostic()
. How can I tell it which one to use?
#include <iostream>
#include <string>
namespace plant {
class Tree
{
std::string name_;
public:
explicit Tree(const std::string_view name) : name_{name} {}
void print(std::ostream& os) const { os << name_; }
};
std::ostream& operator<<(std::ostream& os, const Tree& arg)
{
arg.print(os); return os;
}
namespace examples {
}
namespace debug {
std::ostream& operator<<(std::ostream& os, const Tree& arg)
{
os << "DEBUG: .."; arg.print(os); return os;
}
}
}
plant::Tree baum{"Mein Baum"};
void run()
{
using namespace plant;
std::cout << baum << "\n";
}
void diagnostic()
{
using namespace plant::debug;
std::cout << baum << "\n";
}
int main() {
run();
diagnostic();
}
Inside of diagnostic()
, both operator<<
's are found as candidates, hence the ambiguity. plant::operator<<
is found due to Argument-Dependent Lookup (which makes the using
in run()
redundant), and plant::debug::operator<<
is found due to its using
statement.
To resolve the ambiguity, you could call the debug::operator<<
directly, eg:
void diagnostic()
{
//using namespace plant::debug;
plant::debug::operator<<(std::cout, baum) << "\n";
}
However, that kind of defeats the purpose of defining an operator<<
in the first place, rather than a standalone function.
One option is you can instead simply move plant::operator<<
into its own namespace, and then update run()
to use that namespace, eg:
namespace plant {
class Tree
{
...
};
namespace no_debug {
std::ostream& operator<<(std::ostream& os, const Tree& arg)
{
...
return os;
}
}
namespace debug {
std::ostream& operator<<(std::ostream& os, const Tree& arg)
{
os << "DEBUG: ..";
...
return os;
}
}
}
...
void run()
{
using namespace plant::no_debug;
std::cout << baum << "\n";
}
void diagnostic()
{
using namespace plant::debug;
std::cout << baum << "\n";
}