While writing a test suite, I needed to provide an implementation of operator<<(std::ostream&... for Boost unit test to use.
This worked:
namespace theseus { namespace core {
std::ostream& operator<<(std::ostream& ss, const PixelRGB& p) {
return (ss << "PixelRGB(" << (int)p.r << "," << (int)p.g << "," << (int)p.b << ")");
}
}}
This didn’t:
std::ostream& operator<<(std::ostream& ss, const theseus::core::PixelRGB& p) {
return (ss << "PixelRGB(" << (int)p.r << "," << (int)p.g << "," << (int)p.b << ")");
}
Apparently, the second wasn’t included in the candidate matches when g++ tried to resolve the use of the operator. Why (what rule causes this)?
The code calling operator<< is deep within the Boost unit test framework, but here’s the test code:
BOOST_AUTO_TEST_SUITE(core_image)
BOOST_AUTO_TEST_CASE(test_output) {
using namespace theseus::core;
BOOST_TEST_MESSAGE(PixelRGB(5,5,5)); // only compiles with operator<< definition inside theseus::core
std::cout << PixelRGB(5,5,5) << "\n"; // works with either definition
BOOST_CHECK(true); // prevent no-assertion error
}
BOOST_AUTO_TEST_SUITE_END()
For reference, I’m using g++ 4.4 (though for the moment I’m assuming this behaviour is standards-conformant).
In argument dependent lookup (the correct name for koenig lookup) the compiler adds to the overloaded function set the functions which are declared in the namespaces of each parameter.
In your case, the first
operator<<is declared in the namespacethesus::core,which is the type of the argument you call the operator with. Therefore thisoperator<<is considered for ADL because it’s declared in an associated namespaceIn the second case, the
operator<<seems to be declared in the global namespace which is not an associated namespace as parameter one is of type from namespacestdand param 2 is of type from namespacetheseus::core.Actually, probably your 2nd
operator<<isn’t declared in global namespace as that would be found through looking in parent scopes.. maybe you’ve got something more like this? If you can post more code we can give a better answer.Ok I remembered, ADL doesn’t lookup in parent scopes when it finds a name in the current scope. So the boost macro
BOOST_TEST_MESSAGEexpands to include anoperator<<and there is some in the scope tree a non-viableoperator<<between the expression and global scope. I updated code to illustrate this (hopefully).