我在运用命名空间时,遇到了与重载运算符<<相关的问题。我已经阅读了相关帖子,但仍然不理解我的情况发生了什么。
以下代码编译没有问题:
文件test_matrix.hpp:
请注意,需要使用 VecMat::operator<<; 行 - 如果没有它,在最后一行的 test1() 中会出现错误(使用 gcc 4.5):
然而,当我添加一个新的类并将其自己的 operator<< 添加到 Main 命名空间时,我的主要问题开始了:
文件 test_other.hpp:
如果我从两个原始文件中的任何一个中包含“test_other.hpp”,那么.cpp文件将无法编译,出现与上述相同的错误,仅在test2()的最后一行。
我希望能够解释发生了什么,并推荐以最干净的方式解决它。
非常感谢。 Michal
以下代码编译没有问题:
文件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<<; 行 - 如果没有它,在最后一行的 test1() 中会出现错误(使用 gcc 4.5):
编译器不应该通过自适应限定查找类型为 VecMat::MatrixD 的参数来找到运算符自身吗?test_oper.cpp||在函数 'void test1()' 中:|
test_oper.cpp|22|错误:在 '((std::basic_ostream*)std::operator<<' 中没有匹配的运算符
然而,当我添加一个新的类并将其自己的 operator<< 添加到 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
如果我从两个原始文件中的任何一个中包含“test_other.hpp”,那么.cpp文件将无法编译,出现与上述相同的错误,仅在test2()的最后一行。
如果我将放入不同的命名空间(VecMat或新的命名空间),它可以正常编译。这是否意味着编译器首先查找Main,在那里找到一个operator<<(用于Foo),因此停止搜索并抱怨找到了错误的运算符?再次说,我本以为它会首先查找VecMat,因为参数的类型是VecMat :: MatrixD?test_oper.cpp||在函数'void Main::test2()':| test_oper.cpp|29|错误:没有匹配'operator<<' in '((std::basic_ostream*)std::operator<<
我希望能够解释发生了什么,并推荐以最干净的方式解决它。
非常感谢。 Michal
PS: 我也在其他地方发布了这个问题,那里建议我(http://www.cplusplus.com/forum/general/47766/#msg259246)在Main命名空间中添加using VecMat::operator<<;这行代码。这解决了问题 - 但我仍然想知道为什么需要这些代码以及是否这是最佳/推荐的解决方案。