2011-04-11 27 views
7

tengo una estructura sencilla Wrapper, que se distingue por dos sobrecargas de operadores de asignación con plantilla:Plantilla operador de asignación sobrecarga misterio

template<typename T> 
struct Wrapper { 

    Wrapper() {} 

    template <typename U> 
    Wrapper &operator=(const Wrapper<U> &rhs) { 
    cout << "1" << endl; 
    return *this; 
    } 
    template <typename U> 
    Wrapper &operator=(Wrapper<U> &rhs) { 
    cout << "2" << endl; 
    return *this; 
    } 
}; 

continuación, declaro a y b:

Wrapper<float> a, b; 
a = b; 

asignar b-a utilizará la sobrecarga del operador de asignación de plantilla no const desde arriba, y se muestra el número "2".

Lo que me intriga es la siguiente: Si Declaro c y d,

Wrapper<float> c; 
const Wrapper<float> d; 
c = d; 

y asigno a dc, se utiliza ninguno de los dos sobrecargas de operadores de asignación, y no se muestra ninguna salida; por lo que se invoca el operador de asignación de copia predeterminado. ¿Por qué la asignación de d a c no utiliza el operador de asignación de sobrecarga const proporcionado? O bien, ¿por qué la asignación de b a ano usa el operador de asignación de copia predeterminado?

Respuesta

18

¿Por qué la asignación de d a c no utiliza el operador de asignación const sobrecargado?

El operador de asignación de copia declarada implícitamente, que se declara de la siguiente manera, se sigue generando:

Wrapper& operator=(const Wrapper&); 

plantilla Un operador no suprime la generación del operador de asignación de copia declarada implícitamente. Dado que el argumento (un const-qualified Wrapper) es una coincidencia exacta para el parámetro de este operador (const Wrapper&), se selecciona durante la resolución de sobrecarga.

La plantilla de operador no está seleccionada y no hay ambigüedad porque, en igualdad de condiciones, una no aplicación es una mejor coincidencia durante la resolución de sobrecarga que una plantilla.

¿Por qué la asignación de b a a no utiliza el operador de asignación de copia predeterminado?

El argumento (un no-const cualificado Wrapper) presenta una mejor coincidencia para la plantilla del operador que toma un Wrapper<U>& que para el operador de asignación de copia declarada implícitamente-(que tiene un const Wrapper<U>&.

+1

+1 por * Una plantilla de operador no suprime la generación del operador de asignación de copias implícitamente declarado *. – Nawaz

6

Desde el C++ 03 estándar, §12.8/9:

una copia operador de asignación-declarado usuario X::operator= es un no plantilla de función miembro no estático de la clase X con exactamente un parámetro del tipo X, X&, const X&, volatile X& o const volatile X&.

Y §12.8/10:

Si la definición de clase no declara explícitamente un operador de asignación de copia, se declara implícitamente.

El hecho de que su operator= es una plantilla hace que sea no un operador de asignación de copia, por lo que el operador de asignación de copia implícita clase todavía es generado por el compilador.

+0

¿Qué es entonces si no es un operador de asignación de copias? Entonces, ¿qué se supone que debes hacer, solo crear una plantilla de función CopyFrom o algo así? –

+0

@DavidDoria: Es un operador de asignación, simplemente no es un operador de asignación _copy_. – ildjarn