2011-08-01 66 views
3

我有一個與運算符< <相結合的命名空間的問題。我看了相關的帖子,但還是不明白什麼是我的情況怎麼回事..過載運算符<<與命名空間

下面的代碼編譯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 ::操作< <的;需要線 - 沒有它,我得到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運營商自身,因爲該參數是類型VecMat :: MatrixD

我的主要問題,但是,開始時我添加一個新的類都有自己的運營商< <到主要命名空間:

文件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」from the two original files,the .cpp file will not compile,with the same error as above,only in the last line of the last line of test2()

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

如果我把到不同的命名空間(無論是VecMat或一個新的),它編譯OK。這是否意味着編譯器首先進入主要,在那裏找到一個運算符< <(因爲Foo),因此停止搜索並且抱怨它找到了錯誤的運算符?再次,我會認爲它會首先考慮到VecMat,因爲參數的類型是VecMat :: MatrixD

我希望能夠解釋發生了什麼,並建議如何以最簡潔的方式解決問題。

非常感謝。
米哈爾

PS:我張貼的問題在其他地方也有與會者建議(http://www.cplusplus.com/forum/general/47766/#msg259246)使用VecMat ::操作< <添加;行內還有主要的命名空間。這解決了它 - 但我仍然想知道爲什麼我需要這些線路以及這是否是最佳/推薦的解決方案。

回答

1

typedef沒有引入新的類型。因此VecMat::MatrixD不是新類型,它是boost::numeric::ublas::matrix<double>的別名,因此ADL中使用的關聯名稱空間是boost::numeric::ublas::matrix<double>的名稱空間。