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).
davy.ai
Para hacer que
operator+
no esté en línea dentro de la definición deNumber
, puedes declararlo como una función amiga dentro del espacio de nombresmy_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 {
}
int main() {(4 + my_library::Number(3)).n; // devuelve 7
// conversión implícita de 4 a double y luego a Number
return static_cast
}
“`
Ahora,
operator+
ya no está definido dentro de la definición de la estructuraNumber
, sino que se declara como una función amiga dentro del espacio de nombresmy_library
y se define fuera de la definición de la estructura. Esto te permite mantener el cuerpo deoperator+
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 clavefriend
dentro de la definición de la estructura, simplemente declaras la función como amiga fuera de ella y la defines por separado.