overloading operator<< vs. namespaces
I have a problem with overloading operator<< combined with namespaces. I have read the related posts, but still do not understand what is going on in my case..
The following code compiles OK:
file test_matrix.hpp:
#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;
开发者_如何学Gofor (it1 = M().begin1(); it1 != M().end1(); ++it1) {
for (it2 = it1.begin(); it2 != it1.end(); ++it2) {
os << *it2 << "\t";
}
os << std::endl;
}
return os;
}
}; // namespace VecMat
#endif
file test_oper.cpp:
#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;
}
Note that the using VecMat::operator<<; line is needed - without it, I get an error on the last line of test1() (using gcc 4.5):
test_oper.cpp||In function 'void test1()':|
test_oper.cpp|22|error: no match for 'operator<<' in '((std::basic_ostream*)std::operator<<
Should not the compiler find the operator self using ADL, since the argument is of type VecMat::MatrixD?
My main problem, however, starts when I add a new class with its own operator<< to the Main namespace:
file test_other.hpp:
#ifndef TEST_OTHER_HPP
#define TEST_OTHER_HPP
#include <ostream>
namespace Main {
class Foo {
int n;
};
std::ostream & operator<< (std::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 same error as above, only in the last line of test2()
test_oper.cpp||In function 'void Main::test2()':| test_oper.cpp|29|error: no match for 'operator<<' in '((std::basic_ostream*)std::operator<<
If I put Foo into a different namespace (either VecMat or a new one), it compiles OK. Does it mean that the compiler looks first into Main, finds one operator<< there (for Foo), and therefore stop searching and complains that it has found the wrong operator? Again, I would have thought that it would look into VecMat first, since the argument is of type VecMat::MatrixD?
I would appreciate both an explanation of what is going on and a recommendation how to resolve it in a cleanest possible way.
Thanks a lot.
MichalPS: I posted the question also elsewhere and there it was suggested (http://www.cplusplus.com/forum/general/47766/#msg259246) to add the using VecMat::operator<<; line also inside the Main namespace. This solves it - but I would still like to know why do I need those lines and whether this is the best/recommended solution.
typedef doesn't introduce a new type. So VecMat::MatrixD
is not a new type, it's an alias to boost::numeric::ublas::matrix<double>
, therefore the associated namespaces used in ADL are those of boost::numeric::ublas::matrix<double>
.
精彩评论