重载运算符<<与命名空间

overloading operator<< vs. namespaces

本文关键字:lt 命名空间 运算符 重载      更新时间:2023-10-16

我有一个重载操作符问题<<与名称空间结合使用。我已经读了相关的帖子,但仍然不明白我的情况是怎么回事。

以下代码可以正常编译:

文件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)上得到一个错误:

test_op .cpp||In function 'void test1()':|
test_op .cpp|22|错误:在'((std::basic_ostream*)std::operator<<

由于参数类型为VecMat::MatrixD,编译器不应该使用ADL找到操作符self吗?

然而,我的主要问题开始于我添加一个带有自己的操作符<<的新类。到命名空间:

文件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_op .cpp||在函数'void Main::test2()':|test_op .cpp|29|错误:在'((std::basic_ostream*)std::operator<<

如果我把Foo放到一个不同的名称空间(VecMat或一个新的名称空间),它可以正常编译。这是否意味着编译器首先查找Main,找到一个操作符<<那里(对于Foo),因此停止搜索并抱怨它找到了错误的操作符?再一次,我本以为它会首先查看VecMat,因为参数的类型是VecMat::MatrixD?

如果你能解释一下发生了什么,并建议如何以最干净的方式解决这个问题,我将非常感激。

非常感谢。
米甲

PS:我也在其他地方发布了这个问题,有人建议(http://www.cplusplus.com/forum/general/47766/#msg259246)使用VecMat::operator<<;行也在Main命名空间中添加。这解决了它-但我仍然想知道为什么我需要这些行,这是否是最好的/推荐的解决方案。

typepedef不引入新类型。因此,VecMat::MatrixD不是新类型,它是boost::numeric::ublas::matrix<double>的别名,因此ADL中使用的关联命名空间是boost::numeric::ublas::matrix<double>的命名空间。