c++ - overload - ostream operator<<




¿Cómo sobrecargar correctamente el operador<< para un ostream? (4)

En C ++ 14 puede usar la siguiente plantilla para imprimir cualquier objeto que tenga una const. T :: print (std :: ostream &); miembro.

template<class T>
auto operator<<(std::ostream& os, const T& t) -> decltype(t.print(os), os) 
{ 
    t.print(os); 
    return os; 
} 

Estoy escribiendo una pequeña biblioteca matricial en C ++ para operaciones matriciales. Sin embargo mi compilador se queja, donde antes no lo hacía. Este código se dejó en un estante durante 6 meses y, entre tanto, actualicé mi computadora de debian etch a lenny (g ++ (Debian 4.3.2-1.1) 4.3.2) sin embargo, tengo el mismo problema en un sistema Ubuntu con el mismo g ++ .

Aquí está la parte relevante de mi clase de matriz:

namespace Math
{
    class Matrix
    {
    public:

        [...]

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

Y la "implementación":

using namespace Math;

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

    [...]

}

Este es el error dado por el compilador:

matrix.cpp: 459: error: 'std :: ostream & Math :: Matrix :: operator << (std :: ostream &, const Math :: Matrix &)' debe tomar exactamente un argumento

Estoy un poco confundido por este error, pero nuevamente, mi C ++ se ha oxidado un poco después de hacer muchos Java esos 6 meses. :-)


Has declarado tu función como friend . No es un miembro de la clase. Debe eliminar Matrix:: de la implementación. friend significa que la función especificada (que no es un miembro de la clase) puede acceder a las variables de miembro privado. La forma en que implementó la función es como un método de instancia para la clase Matrix que está mal.


Solo te cuento sobre otra posibilidad: me gusta usar definiciones de amigos para eso:

namespace Math
{
    class Matrix
    {
    public:

        [...]

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

La función se enfocará automáticamente en el espacio de nombres adyacente Math (aunque su definición aparezca dentro del alcance de esa clase), pero no estará visible a menos que llame al operador << con un objeto Matrix, lo que hará que la búsqueda dependiente de los argumentos encuentre esa definición de operador. A veces, esto puede ayudar con llamadas ambiguas, ya que es invisible para los tipos de argumentos que no sean Matrix. Al escribir su definición, también puede referirse directamente a los nombres definidos en Matrix y a Matrix, sin calificar el nombre con un prefijo posiblemente largo y proporcionar parámetros de plantilla como Math::Matrix<TypeA, N> .


Suponiendo que estamos hablando de operator << sobrecarga operator << para todas las clases derivadas de std::ostream para manejar la clase Matrix (y no sobrecarga << para la clase Matrix ), tiene más sentido declarar la función de sobrecarga fuera del espacio de nombres Math en el encabezado

Utilice una función de amigo solo si la funcionalidad no se puede lograr a través de las interfaces públicas.

Matriz.h

namespace Math { 
    class Matrix { 
        //...
    };  
}
std::ostream& operator<<(std::ostream&, const Math::Matrix&);

Tenga en cuenta que la sobrecarga del operador se declara fuera del espacio de nombres.

Matriz.cpp

using namespace Math;
using namespace std;

ostream& operator<< (ostream& os, const Matrix& obj) {
    os << obj.getXYZ() << obj.getABC() << '\n';
    return os;
}

Por otro lado, si su función de sobrecarga necesita ser un amigo, es decir, necesita acceso a miembros privados y protegidos.

Matemáticas.h

namespace Math {
    class Matrix {
        public:
            friend std::ostream& operator<<(std::ostream&, const Matrix&);
    };
}

Es necesario que incluya la definición de la función con un bloque de espacio de nombres en lugar de using namespace Math; solo el using namespace Math; .

Matriz.cpp

using namespace Math;
using namespace std;

namespace Math {
    ostream& operator<<(ostream& os, const Matrix& obj) {
        os << obj.XYZ << obj.ABC << '\n';
        return os;
    }                 
}




ostream