c++ - ¿Se supone que los constructores variados esconden los generados implícitamente?
templates c++11 (1)
La declaración del constructor de copia implícitamente declarado no está, de hecho, siendo suprimida. Simplemente no se llama debido a las reglas de resolución de sobrecarga.
El constructor de copia declarado implícitamente tiene la forma 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 no const es preferida sobre el constructor de copia implicitly-declarated. Para llamar al constructor de copia implícitamente declarado, puede crear a
const:
const Foo a;
Foo b(a);
o puede usar static_cast
para obtener una referencia constante a a
:
Foo a;
Foo b(static_cast<const Foo&>(a));
Las reglas de resolución de sobrecarga que describen esto se encuentran principalmente en §13.3.3.2 / 3 de C ++ 0x FCD. Este escenario particular, con una combinación de referencias lvalue y rvalue, es una especie de descripción de los diversos ejemplos en la página 303.
Una plantilla de constructor variable suprimirá el constructor predeterminado implícitamente declarado porque una plantilla de constructor variadic es declarada por el usuario y el constructor predeterminado declarado implícitamente solo se proporciona si no hay constructores declarados por el usuario (C ++ 0x FCD §12.1 / 5):
Si no hay un constructor declarado por el usuario para la clase
X
, un constructor que no tiene parámetros se declara implícitamente como predeterminado.
Una plantilla de constructor variadic no suprimirá el constructor de copia declarado implícitamente porque solo un constructor que no sea una plantilla puede ser un constructor de copia (C ++ 0x FCD §12.8 / 2, 3 y 8):
Un constructor sin plantilla para la clase
X
es un constructor de copia si su primer parámetro es de tipoX&
,const X&
,volatile X&
const volatile X&
, o bien no hay otros parámetros o bien todos los demás parámetros tienen argumentos predeterminados.Un constructor sin plantilla para la clase
X
es un constructor de movimiento si su primer parámetro es del tipoX&&
,const X&&
,volatile X&&
, oconst volatile X&&
, y si no hay otros parámetros o 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.
¿Se supone que los constructores variados ocultan los generados implícitamente, es decir, el constructor predeterminado y el constructor de copia?
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 esperaba que esto no imprimiera nada después de leer esta respuesta , pero se imprime inside the variadic constructor
dos veces en g ++ 4.5.0 :( ¿Es 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);
}
De nuevo, ambas líneas están impresas.