es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Cómo hacer que la inicialización de copia sea privada en C++17?

En la siguiente simplificación de un ejemplo del mundo real, la intención es garantizar que un usuario de la clase A solo pueda obtener referencias temporales a sus objetos (en mi ejemplo real, la clase A es una clase de proxy utilizada para sobrecargar operadores en los valores de retorno de otras clases):

struct A {
    static A foo() {
        return A();
    }
private:
    A() {}
    A(const A&) = default;
};

Espero que la asignación a a falle, y esto es lo que sucede en C++14 y versiones anteriores:

main.cpp:11:11: error: calling a private constructor of class 'A'
    A a = A::foo();
          ^
main.cpp:7:5: note: declared private here
    A(const A&) = default;
    ^

Sin embargo, en C++17, esto no es un error ya que no hay una asignación ocurriendo, solamente a está siendo inicializado mediante una copia. En este caso, ¿cómo puedo garantizar la semántica anterior? ¿Hay alguna forma de declarar que la inicialización por copia de A también sea privada (preferiblemente sin modificar el tipo de retorno de foo)?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Una forma de hacer cumplir la semántica anterior en C ++17 es declarar que el constructor de copia de A esté eliminado, además de hacerlo privado. Esto evitará cualquier intento de inicialización por copia de un objeto de clase A, y por lo tanto, hará cumplir la restricción de obtener solo referencias temporales a objetos A.

    El código modificado se vería así:

    struct A {
        static A foo() {
            return A();
        }
    private:
        A() {}
    
        A(const A&) = delete;
        // se elimina el constructor de copia
    
    };
    
    int main() {
        A a = A::foo(); // Error: no se permite la inicialización por copia
    }
    

    Al agregar el especificador = delete al constructor de copia, cualquier intento de inicialización por copia de un objeto de tipo A resultará en un error de compilación. Esto incluye el caso en que la inicialización por copia se realiza utilizando el resultado de una llamada de función, como en A a = A::foo();.

    Tenga en cuenta que esta solución no requiere modificar el tipo de retorno de foo(), y por lo tanto no afecta la interfaz proporcionada por A.

Comments are closed.