Asked  7 Months ago    Answers:  5   Viewed   49 times

I am writing a small matrix library in C++ for matrix operations. However my compiler complains, 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. :-)

 Answers

78

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.

Tuesday, June 1, 2021
 
Blacksonic
answered 7 Months ago
53

The problem is that you define it inside the class, which

a) means the second argument is implicit (this) and

b) it will not do what you want it do, namely extend std::ostream.

You have to define it as a free function:

class A { /* ... */ };
std::ostream& operator<<(std::ostream&, const A& a);
Saturday, July 10, 2021
 
juananrey
answered 5 Months ago
17

The easier solution is to use the operator() as it allows multiple parameters.

class M
{
    public:
       int& operator()(int x,int y)  {return at(x,y);}
    // .. Stuff to hold data and implement at()
};


M   a;
a(1,2) = 4;

The easy way is that the first operator[] returns an intermediate object that the second operator[] returns the value from the array.

class M
{
    public:
    class R
    {
         private:
             friend class M; // Only M can create these objects.
             R(M& parent,int row): m_parent(parent),m_row(row) {}
         public:
              int& operator[](int col) {return m_parent.at(m_row,col);}
         private:
              M&  m_parent;
              int m_row;
    };

    R operator[](int row) {return R(*this,row);}

    // .. Stuff to hold data and implement at()
};

M   b;
b[1][2] = 3;   // This is shorthand for:

R    row = b[1];
int& val = row[2];
val      = 3;
Friday, July 23, 2021
 
barden
answered 5 Months ago
26

You can't do that. You can only provide overloaded operators for classes and structs you define -- and at least one of the parameters should be of type of the class or struct itself. That is, you can declare an overloaded addition operator that adds a MyClass to MyEnum but you can never do that with two MyEnum values.

Friday, July 23, 2021
 
rblarsen
answered 5 Months ago
15

I think you've answered your own question! The stream operator

QDataStream& operator<<( QDataStream&, const Compound& )

will work fine. In the implementation you just use the existing stream operators on QDataStream to serialise the individual bits of your Compound. Some Qt classes define non-member QDataStream operators too. QString is one and so is QList so it looks like you're sorted!

Friday, July 30, 2021
 
xrock
answered 5 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share