2010-06-01 18 views
26

¿Se supone que los constructores variados ocultan los generados implícitamente, es decir, el constructor predeterminado y el constructor de copia?¿Se supone que los constructores variados ocultan los generados implícitamente?

struct Foo 
{ 
    template<typename... Args> Foo(Args&&... x) 
    { 
     std::cout << "inside the variadic constructor\n"; 
    } 
}; 

int main() 
{ 
    Foo a; 
    Foo b(a); 
} 

De alguna manera me esperaba esto para imprimir nada después de leer this answer, pero se imprime dos veces en inside the variadic constructor g ++ 4.5.0 :(¿Este comportamiento correcto


También sucede sin plantillas variadic?:

struct Foo 
{ 
    Foo() 
    { 
     std::cout << "inside the nullary constructor\n"; 
    } 

    template<typename A> Foo(A&& x) 
    { 
     std::cout << "inside the unary constructor\n"; 
    } 
}; 

int main() 
{ 
    Foo a; 
    Foo b(a); 
} 

Una vez más, se imprimen ambas líneas.

+1

Acabo de ejecutar una prueba rápida en gcc45, y un constructor de plantilla regular, no variadic impide la creación de un constructor predeterminado generado por el compilador también. Mi sospecha es que las reglas cambiaron en C++ 0x. –

+2

@Dennis: Me sorprendería _realmente_ si C++ 0x cambiara las reglas que se introducirán con C++ 0x. ':)' – sbi

+0

@Dennis ¿Entonces la respuesta vinculada es falsa? Dice que "un constructor de plantilla o un operador de asignación no suprimirán el compilador generado". – fredoverflow

Respuesta

19

La declaración del constructor de copia declarado implícitamente no está, de hecho, siendo suprimida. Simplemente no se llama debido a las reglas de resolución de sobrecarga.

El constructor de copias declarado implícitamente tiene el formato Foo(const Foo&). La parte importante de esto es que requiere una referencia constante. Su plantilla de constructor toma una referencia no constante.

a no es const, por lo que la plantilla de constructor declarada por el usuario es preferible al constructor de copia implícitamente declarado. Para llamar al constructor de copia declarada implícitamente, puede hacer a const:

const Foo a; 
Foo b(a); 

o puede utilizar static_cast para obtener una referencia constante a a:

reglas de resolución
Foo a; 
Foo b(static_cast<const Foo&>(a)); 

La sobrecarga que describen este se encontrado principalmente en §13.3.3.2/3 de C++ 0x FCD. Este escenario particular, con una combinación de lvalue y rvalue referencias, es una especie de descrito por los diversos ejemplos en la página 303.


Una plantilla constructor variadic suprimirá el constructor por defecto declarado implícitamente debido a una plantilla constructor es variadic usuario -declarado y el constructor por defecto declarado implícitamente se proporciona solamente si no hay constructores declarados por el usuario (C++ 0x FCD §12.1/5):

Si no hay un constructor de la clase declarada de usuario para X, una El constructor que no tiene parámetros se declara implícitamente como predeterminado.

Una plantilla constructor variadic no suprimir el constructor de copia implícitamente declarado porque sólo un constructor no molde puede ser un constructor de copia (C++ 0x FCD §12.8/2, 3, y 8):

un constructor no molde para la clase X es un constructor de copia si su parámetro de primera es de tipo X&, const X&, volatile X& o const volatile X&, y, o bien no hay otros parámetros o también todos los otros parámetros tienen argumentos predeterminados.

Un constructor no molde para la clase X es un constructor movimiento si su parámetro de primera es de tipo X&&, const X&&, volatile X&&, o const volatile X&&, y, o bien no hay otros parámetros o también todos los otros parámetros tienen argumentos predeterminados.

Si la definición de clase no declara explícitamente un constructor de copia y no hay un constructor de movimiento declarado por el usuario, un constructor de copia se declara implícitamente como predeterminado.

+0

@James "un constructor de [...] plantillas nunca es un constructor de copias" -> entonces g ++ 4.5.0 es defectuoso y la segunda línea no debe imprimir nada? ¿Y por FCD te refieres a n3090? – fredoverflow

+0

@Fred: el FCD es n3092; Tuve que actualizar las comillas porque tenía n3035 abierto por alguna razón y hay algunos cambios en n3092 ... lo siento. –

+0

@James Sucede también con plantillas no variadic, ¡he actualizado mi pregunta! – fredoverflow

Cuestiones relacionadas