¿Cuáles son las reglas por las cuales se std::is_constructible
manejan los constructores privados? Dado el siguiente código:
#include <iostream>
class Class {
private:
Class() { }
};
template <typename T>
class Test {
public:
static void test() {
std::cout
//<< std::is_constructible<Class>::value
<< std::is_constructible<T>::value
<< std::endl;
}
};
int main() {
Test<Class>::test();
}
Esto imprime 0
( ideone ), es decir, T
no es construible por defecto.
Descomentando la línea comentada, imprime 11
( ideone ), por lo que de T
repente se convirtió en construible por defecto.
Podría encontrar un razonamiento para respaldar ambos resultados, pero no entiendo cómo incluir la línea comentada cambia el resultado del segundo. ¿Esto de alguna manera invoca a UB? ¿Es esto un error del compilador? ¿O es std::is_constructible
realmente tan inconsistente?
c++
typetraits
zennehoy
fuente
fuente
00
::value
versión también es capaz de cambiar la salida de los que vienen antes: godbolt.org/z/zCy5xU Descomente la línea comentada y todo se convierte en 1: s en gcc.false
pero si la plantilla de función no está comentada, de repente regresatrue
: godbolt.org/z/zqxdk2Respuestas:
std::is_constructible
debería regresarfalse
en este escenario porque el constructor no es accesible.Como se señaló debajo de la pregunta, el comportamiento descrito en la pregunta es causado por un error en GCC / libstdc ++. El error se informa aquí y, de acuerdo con Bugzilla, está relacionado con, si no es causado por un error de control de acceso para clases en funciones de plantilla que no se ha resuelto durante bastante tiempo. La relación entre los dos errores se toma del comentario de Jonathan Wakely sobre Bugzilla, que parece haber detectado primero la conexión entre los dos errores.
Esto también está implícito en el hecho de que el comportamiento de este escenario en GCC se vuelve correcto al eliminar el constructor en lugar de hacerlo privado:
que imprime
0
y00
respectivamente. Este es el resultado correcto (que tambiénclang
informa correctamente en el escenario con un constructor privado).Esto podría explicar el cambio de comportamiento observado al comentar en la línea, porque dentro de la función en la estructura con plantilla , la comprobación de acceso no funciona e informa que el constructor es accesible cuando no lo es. Cuando el rasgo se verifica nuevamente en la siguiente línea o posiblemente en una ubicación completamente diferente (como es el caso aquí ), ya se ha instanciado y, por lo tanto, produce la respuesta incorrecta.
fuente