Re: Problem with namespace lookup
Am 10.12.2010 22:03, schrieb dragoncoder:
Hi, I have the following code in a.cpp, which failes to compile on
Solaris' native compiler CC
#include<iostream>
#include<utility>
namespace A
{
class AA
{
public:
void print(std::ostream& o) const { o<< "From AA "<< a; }
private:
int a;
};
class AB
{
public:
void print(std::ostream& o) const { o<< "From AB "<< a; }
private:
int a;
};
inline std::ostream& operator<<(std::ostream& o, const AA& obj)
{
obj.print(o);
return o;
}
inline std::ostream& operator<<(std::ostream& o, const AB& obj)
{
obj.print(o);
return o;
}
} // end namespace
namespace B
{
typedef std::pair<A::AA, A::AB> BA;
inline std::ostream& operator<<(std::ostream& o, const BA& obj)
{
o<< "[ "<< obj.first<< ", "<< obj.second<< " ]";
return o;
}
} // end namespace AB
int main()
{
B::BA obj;
std::cout<< obj<< std::endl;
}
Here is the error reported by the compiler
"a.cpp", line 51: Error: The operation "std::ostream<<bsl::pair<A::AA,
A::AB>" is illegal.
I think I understand the problem is because it is not looking at the
correct place for the function. How can I fix it? Please note that
everything inside namespace A is virtually untouchable, but I own
namespace B and the main().
You analyzed the problem correctly. The compiler will not consider to
search in namespace B for an operator<< overload. According to ADL rules
it will consider the associated namespaces of the argument types.
Problem is: The typedef B::BA is not a separate type, it is just an
alias for std::pair<A::AA, A::AB>. The effect is, that the associated
namespaces are only namespace std (because of pair) and namespace A
(because of A::AA and A::AB). If you cannot extend namespace A - by
reopening this namespace and to add the declaration
std::ostream& operator<<(std::ostream&, const BA&);
- you have only limited choices:
1) Instead of the typedef to std::pair use your own pair-like B::my_pair
(I don't recommend that, though).
2) Use an IO manipulator instead.
Approach (2) is much more general and allows to reuse the manipulator
for other occasions too. It also leads to less surprises by clients of
your library who are aware that std::pair does not provide an operator<<
overload, but for some reasons your special std::pair specialization does.
A very simple way of realizing that goes like this (I have not invested
much energy to invent a good name for the manipulator. Usually you would
assign a short but descriptive name):
namespace X {
template<class T, class U>
struct pair_io_manip {
const std::pair<T, U>& p;
explicit pair_io_manip(const std::pair<T, U>& p) : p(p) {}
};
template<class T, class U>
inline pair_io_manip<T, U> io(const std::pair<T, U>& p) {
return pair_io_manip<T, U>(p);
}
template<class T, class U>
inline std::ostream&
operator<<(std::ostream& o, const pair_io_manip<T, U>& pm)
{
o<< "[ "<< pm.p.first<< ", "<< pm.p.second<< " ]";
return o;
}
}
Usage is now like this:
int main()
{
B::BA obj;
std::cout<< X::io(obj) << std::endl;
}
HTH & Greetings from Bremen,
Daniel Kr?gler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]