Today I met with a wired problem with my C++ code. It tooks me several hours to fix it and it turns out it is related to Koeing Lookup and Name Hidding.
Problem
Here is the sample code that has problem.
#include <iostream>
namespace A {
struct Foo { int data; };
}
namespace B {
template<typename T>
void output(const T& t) { std::cout << t; }
struct Bar { int data; };
std::ostream& operator<< (std::ostream& stream, const Bar& bar) {
return stream << bar.data;
}
}
std::ostream& operator<< (std::ostream& stream, const A::Foo& foo) {
return stream << foo.data;
}
int main() {
A::Foo foo;
B::output(foo);
}
I got the following compilation error with it. Basially the compiler complains that it can’t find the operator<<(std::ostream&, const A::Foo&)
function.
c:\path\main.cpp:9: error: C2679: binary '<<' : no operator found which takes a right-hand operand of type 'const A::Foo' (or there is no acceptable conversion)
Solution
The fix is simply moving operator<<(std::ostream&, const A::Foo&)
into namespace A.
Why?
Listed below are why the error occurs, and why the fix works.
Basically speaking, when C++ compiler tries to find an unqualified function, it will search in two different ways:
- A: Search the namespacs from the one where the function is called up to the global namespace (also take into account of
using namespace
andusing
) until found.
- For example, in the sample code, it will search for the
operator<<(std::ostream&, const A::Foo&)
function bothB
and global namespaces.
- For example, in the sample code, it will search for the
B: Koenig lookup - search in the set of associated namespaces of all its argument types.
For example, in the sample code, it will search for the
operator<<(std::ostream&, const A::Foo&)
function in the following two namespaces:std
, the namespace of the first argument type ostreamA
, the namespace of the second argument Foo
Here is the definition on Wikipedia of Koenig Lookup.
In the C++ programming language, argument-dependent lookup (ADL), or argument-dependent name lookup, applies to the lookup of an unqualified function name depending on the types of the arguments given to the function call.
In the sample code, since the function operator<<(std::ostream&, const A::Foo&)
can be found using method A, then it should work. But it does not!!!
The problem is that there is already a function operator<<
in namespace B. Though it has different signature from the one we are looking for, compiler simply stop searching up. That is why the function can’t be found. Basically, it is because of Name Hiding.
The reason why the fix works is that once we move the function into namespace A, then it can be found using method B. So basically it is because of Koenig Lookup.
No comments:
Post a Comment