Si tiene que almacenar una referencia const
a alguna instancia de tipo B
en su clase A
, entonces seguramente desea ser asegurado, que la vida de A
instancia será superado por el tiempo de vida de B
ejemplo:
B b{};
A a1{b}; // allowed
A a2{B{}}; // should be denied
B const f() { return B{}; } // const result type may make sense for user-defined types
A a3{f()}; // should also be denied!
Para que sea posible, debe explícitamente = delete;
todas las sobrecargas del constructor, que pueden aceptar valores r (tanto const &&
como &&
). Para lograr esto, debe simplemente = delete;
solo const &&
versión del constructor.
struct B {};
struct A
{
B const & b;
A(B const & bb) : b(bb) { ; } // accepts only `B const &` and `B &`
A(B const &&) = delete; // prohibits both `B &&` and `B const &&`
};
Este enfoque le permite prohibir pasar al constructor todo tipo de valores.
Esto también funciona para escalares incorporados.Por ejemplo, double const f() { return 0.01; }
, aunque provocar una advertencia como:
advertencia: 'const' calificador de tipo de tipo de retorno no tiene ningún efecto [-Wignored-calificadores]
todavía puede tiene efecto si simplemente = delete;
única &&
versión del constructor:
struct A
{
double const & eps;
A(double const & e) : eps(e) {} // binds to `double const &`, `double &` AND ! `double const &&`
A(double &&) = delete; // prohibit to binding only to `double &&`, but not to `double const &&`
};
double const get_eps() { return 0.01; }
A a{0.01}; // hard error
A a{get_eps()}; // no hard error, but it is wrong!
para constructores no de conversión (es decir, no unario) hay un problema: es posible que tenga que proporcionar = delete;
versiones -d para todos los combinatorically posibles versiones de los constructores de la siguiente manera:
struct A
{
A(B const &, C const &) {}
A(B const &&, C const &&) = delete;
// and also!
A(B const &, C const &&) = delete;
A(B const &&, C const &) = delete;
};
para prohibir mixtos casos como:
B b{};
A a{b, C{}};
A temporal no se une a una referencia lvalue. La definición de 'r2' en su primer ejemplo no debe compilarse. – musiphil
Si usa VC++, una solución es subir el nivel de advertencia y le indicará cuándo no funciona. –
Sin embargo, una referencia _const_ se uniría a una temporal, por lo que la pregunta sigue siendo muy buena. He considerado este enfoque, pero sigo opinando que si una clase va a almacenar una referencia (o un puntero) al objeto al que se hace referencia, es mejor tomar un puntero en el constructor, para hacer que las preocupaciones potenciales de por vida sean una Un poco más obvio (cuando un constructor toma un puntero, generalmente me hace pensar dos veces acerca de lo que el objeto va a hacer con él). –