es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Clase de plantilla con conversión implícita y sobrecarga de operador sin estar en línea.

Basado en la respuesta en https://stackoverflow.com/questions/8890051/implicit-conversion-when-overloading-operators-for-template-classes pude escribir el siguiente código que funciona perfectamente bien (ejemplo simplificado):

“`c++
namespace my_library {

template <typename t="">
struct Number {
T n;

<pre><code>inline Number(T n) : n(n) { }

friend Number<t> operator+(const Number<t> &a, const Number<t> &b) {
return Number<t>(a.n + b.n);
}
</code></pre>

};

}

int main() {
return (int) (4 + my_library::Number<double>(3)).n; // devuelve 7
}
“`

Todo lo que quiero hacer es asegurarme de que operator+ no se defina en línea dentro de la definición de Number (pero aún se mantenga en el archivo de encabezado) mientras todo siga funcionando de la misma manera, como se muestra en la expresión en la función main. Nótese que requiere que el entero 4 se convierta implícitamente a double y luego a Number<double>. Seguí un comentario que enlaza a https://stackoverflow.com/questions/962599/binary-operator-overloading-on-a-templated-class?rq=1 pero esa solución no funcionó: el operador sobrecargado ya no se corresponde. ¿Existe alguna forma de hacer que esto funcione y que el cuerpo del operador esté fuera de la definición de struct? (Sin complicar la interfaz del operador ni añadir más sobrecargas; en esos casos preferiría mantenerlo en línea).

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Para hacer que operator+ no esté en línea dentro de la definición de Number, puedes declararlo como una función amiga dentro del espacio de nombres my_library, pero definirlo fuera de la definición de la estructura. Así es cómo puedes modificar el código para lograr esto:

    “`c++
    namespace my_library {

    template <typename t="">
    struct Number {
        T n;
    
        Number(T n) : n(n) { }
    
        // declarar operator+ como función amiga dentro del espacio de nombres
        friend Number operator+(const Number& a, const Number& b);
    };
    
    // definir operator+ fuera de la definición de la estructura
    template <typename t="">
    Number<t> operator+(const Number<t>& a, const Number<t>& b) {
        return Number<t>(a.n + b.n);
    }
    

    }

    int main() {
    // conversión implícita de 4 a double y luego a Number
    return static_cast(4 + my_library::Number(3)).n; // devuelve 7
    }
    “`

    Ahora, operator+ ya no está definido dentro de la definición de la estructura Number, sino que se declara como una función amiga dentro del espacio de nombres my_library y se define fuera de la definición de la estructura. Esto te permite mantener el cuerpo de operator+ en el archivo de encabezado, al mismo tiempo que permite que las conversiones implícitas funcionen como antes. Nota que en lugar de usar la palabra clave friend dentro de la definición de la estructura, simplemente declaras la función como amiga fuera de ella y la defines por separado.

Comments are closed.