overloading operator<< and namespaces

Hello, I have a problem with overloading operator<< combined with namespaces. The following code compiles OK:

file test_matrix.hpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#ifndef TEST_MATRIX_HPP
#define TEST_MATRIX_HPP

#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/matrix_expression.hpp>
namespace ublas = boost::numeric::ublas; // shortcut name

namespace VecMat {
	typedef ublas::matrix<double> MatrixD; // matrix of doubles

	template<class MT>
	std::ostream & operator<< (std::ostream & os,
	                           const ublas::matrix_expression<MT> & M)
	{
		// Note: the matrix_expression<MT> has only one method "()", which
		// returns "& MT" or "const & MT" - a ref. to the included matrix object.
		typename MT::const_iterator1 it1;
		typename MT::const_iterator2 it2;
		for (it1 = M().begin1(); it1 != M().end1(); ++it1) {
			for (it2 = it1.begin(); it2 != it1.end(); ++it2) {
				os << *it2 << "\t";
			}
			os << std::endl;
		}
		return os;
	}
}; // namespace Math
#endif 

file test_oper.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include "test_matrix.hpp"
using std::cout;
using std::endl;
using VecMat::MatrixD;
using VecMat::operator<<;

// ---------------------------------------------------------------------------
// would be in a header file
void test1 ();
namespace Main {
	void test2 ();
}
// ---------------------------------------------------------------------------

void test1 ()
{
	MatrixD X(10,3);
	VecMat::operator<<(cout << endl, X) << endl;
	cout << "X =" << endl << X << endl;
}

void Main::test2 ()
{
	MatrixD X(10,3);
	VecMat::operator<<(cout << endl, X) << endl;
	cout << "X =" << endl << X << endl;
}


However, when I add another class in another namespace, with its own operator<<, then the code stops working.

file test_other.hpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
#ifndef TEST_OTHER_HPP
#define TEST_OTHER_HPP
#include <ostream>
using std::ostream;

namespace Main {
	class Foo {
		int n;
	};

	ostream & operator<< (ostream & os, Foo const & foo);
}
#endif 

If I then '#include "test_other.hpp"' from either of the two original files, the .cpp file won't compile with the following message (gcc):

test_oper.cpp||In function 'void Main::test2()':|
test_oper.cpp|29|error: no match for 'operator<<' in '((std::basic_ostream<char>*)std::operator<< [with _Traits = std::char_traits<char>](((std::basic_ostream<char>&)(& std::cout)), ((const char*)"X =")))->std::basic_ostream<_CharT, _Traits>::operator<< [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>](std::endl [with _CharT = char, _Traits = std::char_traits<char>]) << X'|
lib\gcc\mingw32\4.5.2\include\c++\ostream|108|note: candidates are: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>::__ostream_type& (*)(std::basic_ostream<_CharT, _Traits>::__ostream_type&)) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]|
...
||=== Build finished: 19 errors, 0 warnings (0 minutes, 1 seconds) ===|


The code fails on the last line, i.e. the explicit call of operator<<() on the next-to-last line works OK - as does using the overloaded operator outside the namespace (in test1()).

Can anyone explain what is going on here and/or help me to fix this, please?

Thanks in advance.
Michal
Isn't this complaining that MatrixD doesn't have an operator << of the correct type (or any at all?)
I don't think so - the compiler finds error on the last line of test_oper.cpp. In other words, the operator<< exists and works OK, if I use the explicit call by VecMat::operator<<().

Since the operator works also for test1(), my guess is that the problem is that test2() is in namespace Main, while the operator is in namespace VecMat. But why should this depend on existence of the extra operator<< in test_other.hpp, I really have no idea :-(

But that is what type X is, is it not?
closed account (DSLq5Di1)
@Michal That sounds about right, seems when Main::operator<< is defined your overload in the other namespace is hidden. I think the best you could do is put using VecMat::operator<<; inside your Main namespace.

Also, it wouldnt hurt to create a test case and open a question over @stackoverflow.

-edit-
http://en.wikipedia.org/wiki/Argument-dependent_lookup
Last edited on
Thanks, putting the using line inside the Main namespace solved the problem - though I still do not fully understand what is going on.

Thanks for the tip about stackoverflow - I have posted it there now: http://stackoverflow.com/questions/6895993/overloading-operator-vs-namespaces.

Marking the post as solved..
Topic archived. No new replies allowed.