У меня проблема с перегрузкой оператора << в сочетании с пространствами имен. Я прочитал соответствующие посты, но до сих пор не понимаю, что происходит в моем случае .. </p>
Следующий код компилирует OK:
файл 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;
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 VecMat
#endif
файл 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;
}
Обратите внимание, что необходима строка с использованием VecMat :: operator <<; </em> - без нее я получаю сообщение об ошибке в последней строке test1 () (при использовании gcc 4.5) :
test_oper.cpp || В функции 'void test1 ()': |
test_oper.cpp | 22 | ошибка: нет совпадения для 'operator <<' in '((std :: basic_ostream *) std :: operator << </p>
Разве компилятор не должен сам находить оператор, используя ADL, поскольку аргумент имеет тип VecMat :: MatrixD ?
Моя основная проблема, однако, начинается, когда я добавляю новый класс с собственным оператором << в пространство имен <em>Main :
файл 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
Если я затем "#include" test_other.hpp "" из любого из двух исходных файлов, файл .cpp не будет компилироваться с той же ошибкой, что и выше, только в последней строке test2 ( )
test_oper.cpp || В функции 'void Main :: test2 ()': |
test_oper.cpp | 29 | ошибка: нет совпадения для 'operator <<' in '((std :: basic_ostream *) std :: operator << </p>
Если я помещу Foo в другое пространство имен (либо VecMat , либо в новое), оно компилируется в порядке. Означает ли это, что компилятор сначала просматривает Main , находит там один оператор << (для Foo) и поэтому прекращает поиск и жалуется, что нашел неправильный оператор? Опять же, я бы подумал, что сначала он будет изучать <em>VecMat , поскольку аргумент имеет тип VecMat :: MatrixD ?
Буду признателен как за объяснение происходящего, так и за рекомендацию, как решить его самым чистым способом.
Большое спасибо.
Михал
PS : я разместил вопрос также в другом месте, и там было предложено (http://www.cplusplus.com/forum/general/47766/#msg259246) добавить , используя VecMat :: operator <<; </em> также внутри строки Main namespace. Это решает это, но я все еще хотел бы знать, зачем мне эти строки и является ли это лучшим / рекомендуемым решением.