Pregunta

¿Se supone que los constructores variádicos ocultan los generados implícitamente, es decir, el constructor predeterminado y el constructor de copias?

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 imprima nada después de leer esta respuesta, pero se imprime inside the variadic constructor Dos veces en G ++ 4.5.0 :( ¿Este comportamiento es correcto?


También sucede sin plantillas variádicas:

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);
}

Nuevamente, ambas líneas están impresas.

¿Fue útil?

Solución

La declaración del constructor de copias declarado implícitamente no se suprime, de hecho,. Simplemente no se llama debido a las reglas de resolución de sobrecarga.

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

a no es const, por lo que la plantilla de constructor de usuario no converst-declared se prefiere sobre el constructor de copias implícitamente decolorado. Para llamar al constructor de copia implícitamente decolorado, puede hacer a constante:

const Foo a;
Foo b(a);

o puedes 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 del C ++ 0x FCD. Este escenario particular, con una combinación de referencias de Lvalue y Rvalue, se describe por los diversos ejemplos en la página 303.


Una plantilla de constructor variádico suprimirá el constructor predeterminado declarado implícitamente porque una plantilla de constructor variádica se decela el usuario y el constructor predeterminado declarado implícitamente solo se proporciona si no hay constructores decorados por el usuario (C ++ 0x FCD §12.1/5):

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

Una plantilla de constructor variádico no suprimirá el constructor de copias declarado implícitamente porque solo un constructor no plantilla puede ser un constructor de copias (C ++ 0x FCD §12.8/2, 3 y 8):

Un constructor no de plantilla para la clase X es un constructor de copias si su primer parámetro es de tipo X&, const X&, volatile X& o const volatile X&, y no hay otros parámetros o de lo contrario todos los demás parámetros tienen argumentos predeterminados.

Un constructor no de plantilla para la clase X es un constructor de movimiento si su primer parámetro es de tipo X&&, const X&&, volatile X&&, o const volatile X&&, y no hay otros parámetros o de lo contrario todos los demás parámetros tienen argumentos predeterminados.

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top