重载运算符<<与命名空间 [英] overloading operator<< vs. namespaces

查看:223
本文介绍了重载运算符<<与命名空间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对重载运算符有疑问<<与名称空间结合.我已经阅读了相关文章,但仍然不了解我的情况.

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..

以下代码可以编译:

文件test_matrix.hpp:

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;
        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:

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

请注意,需要使用VecMat :: operator<<< ;; 行-如果没有它,我会在 test1()的最后一行出现错误(使用gcc 4.5):

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 ||在函数'void test1()':|
test_oper.cpp | 22 |错误:"operator<<"不匹配在'(((std :: basic_ostream *)std :: operator<<

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

由于参数的类型为 VecMat :: MatrixD

但是,我的主要问题开始于当我添加一个具有自己的运算符的新类时.到 Main 名称空间:

My main problem, however, starts when I add a new class with its own operator<< to the Main namespace:

文件test_other.hpp:

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

如果我随后从两个原始文件中的任何一个中"#include"test_other.hpp"",则仅在 test2( )

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 ||在函数'void Main :: test2()':|中 test_oper.cpp | 29 |错误:"operator<<"不匹配在'(((std :: basic_ostream *)std :: operator<<

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 ?

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.
Michal

PS :我还在其他地方发布了该问题,并提出了建议( http://www.cplusplus.com/forum/general/47766/#msg259246 ),也可以在VecMat :: operator<< ;; 行中添加 Main 名称空间.可以解决问题-但我仍然想知道为什么需要这些行以及这是否是最佳/推荐的解决方案.

PS: 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不引入新类型.因此VecMat::MatrixD不是新类型,它是boost::numeric::ublas::matrix<double>的别名,因此ADL中使用的关联命名空间是boost::numeric::ublas::matrix<double>的命名空间.

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>.

这篇关于重载运算符&lt;&lt;与命名空间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆