c++ - 重载 operator<< 与命名空间

标签 c++ namespaces operator-overloading

我在重载 operator<< 和命名空间时遇到了问题。我已经阅读了相关帖子,但仍然不明白我的情况是怎么回事..

以下代码编译成功:

文件 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;
}

请注意,using VecMat::operator<<; 行是必需的 - 没有它,我在 test1() 的最后一行(使用 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<<

编译器不应该使用 ADL 找到运算符 self,因为参数是 VecMat::MatrixD 类型吗?

然而,当我将一个带有自己的 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

如果我然后从两个原始文件中的任何一个中“#include "test_other.hpp"',.cpp 文件将不会编译,并出现与上述相同的错误,仅在 test2( )

test_oper.cpp||In function 'void Main::test2()':| test_oper.cpp|29|error: no match for 'operator<<' in '((std::basic_ostream*)std::operator<<

如果我将 Foo 放入不同的命名空间(VecMat 或新的命名空间),它编译正常。这是否意味着编译器首先查看 Main,在那里找到一个运算符 <<(对于 Foo),然后停止搜索并提示它找到了错误的运算符?同样,我认为它会首先查看 VecMat,因为参数的类型是 VecMat::MatrixD?

我将不胜感激对正在发生的事情的解释以及如何以尽可能干净的方式解决它的建议。

非常感谢。
迈克尔

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

最佳答案

typedef 不引入新类型。所以VecMat::MatrixD不是新类型,它是 boost::numeric::ublas::matrix<double> 的别名,因此 ADL 中使用的关联 namespace 是 boost::numeric::ublas::matrix<double> 的 namespace .

关于c++ - 重载 operator<< 与命名空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6895993/

相关文章:

c++ - 命名空间引用和包含的顺序影响编译结果

C#:为什么尽管使用了完全限定名称?

C++ 为任意集合重载 ostream <<

c++ - 关键字 using 的功能是什么?

c++ - 如何用无限循环停止QThread

c++ - 使用模板切换 SSE 内在函数

javascript - 带有 ECMAScript 6 类的命名空间

c++ - QDataStream : Overloading >> for decorated QVector

运算符重载的 C++ 错误

c++ - 模板的部分特化