views:

2966

answers:

3

I am writing a small matrix library in C++ for matrix operations. However my compiler complaints, where before it did not. This code was left on a shelf for 6 months and in between I upgraded my computer from debian etch to lenny (g++ (Debian 4.3.2-1.1) 4.3.2 ) however I have the same problem on a Ubuntu system with the same g++.

Here is the relevant part of my matrix class:

namespace Math
{
    class Matrix
    {
    public:

     [...]

     friend std::ostream& operator<< (std::ostream& stream, const Matrix& matrix);
    }
}

And the "implementation":

using namespace Math;

std::ostream& Matrix::operator <<(std::ostream& stream, const Matrix& matrix) {

    [...]

}

This is the error given by the compiler:

matrix.cpp:459: error: 'std::ostream& Math::Matrix::operator<<(std::ostream&, const Math::Matrix&)' must take exactly one argument

I'm a bit confused by this error, but then again my C++ has gotten a bit rusty after doing lots of Java those 6 months. :-)

+12  A: 

You have declared your function as friend. It's not a member of the class. You should remove Matrix:: from the implementation. friend means that the specified function (which is not a member of the class) can access private member variables. The way you implemented the function is like an instance method for Matrix class which is wrong.

Mehrdad Afshari
I knew it was something stupid, thanks!
Matthias van der Vlies
And you should also declare it inside the Math namespace (not just with an using namespace Math).
David Rodríguez - dribeas
+5  A: 

To add to Mehrdad answer ,

namespace Math
{
    class Matrix
    {
       public:

       [...]


    }   
    std::ostream& operator<< (std::ostream& stream, const Math::Matrix& matrix);
}

In your implementation

std::ostream& operator<<(std::ostream& stream, 
                     const Math::Matrix& matrix) {
    matrix.print(stream); //assuming you define print for matrix 
    return stream;
 }
kal
I don't understand why is this a down vote, this clarifies that you can declare operator to be in the namespace and not even as a friend and how you can possibly declare the operator.
kal
Mehrdad answer did not have any snippet of code so I just added what might work by moving it outside the class in the namespace itself.
kal
I understand your point, I only looked at your second snippet. But now I see you took the operator out of the class. Thanks for the suggestion.
Matthias van der Vlies
Not only it is out of the class, but it is properly defined _inside_ the Math namespace. Also it has the added advantage (maybe not for a Matrix, but with other classes) that 'print' can be virtual and thus printing will happen at the most derived level of inheritance.
David Rodríguez - dribeas
+8  A: 

Just telling you about one other possibility: I like using friend definitions for that:

namespace Math
{
    class Matrix
    {
    public:

        [...]

        friend std::ostream& operator<< (std::ostream& stream, const Matrix& matrix) {
            [...]
        }
    };
}

The function will be automatically targeted into the surrounding namespace Math (even though its definition appears within the scope of that class) but will not be visible unless you call operator<< with a Matrix object which will make argument dependent lookup find that operator definition. That can sometimes help with ambiguous calls, since it's invisible for argument types other than Matrix. When writing its definition, you can also refer directly to names defined in Matrix and to Matrix itself, without qualifying the name with some possibly long prefix and providing template parameters like Math::Matrix<TypeA, N>.

Johannes Schaub - litb