c++ - "Constexpr if" frente a "if" con optimizaciones: ¿por qué se necesita "constexpr"?
c++17 if-constexpr (1)
Esto es fácil de explicar a través de un ejemplo. Considerar
struct Cat { void meow() { } };
struct Dog { void bark() { } };
y
template <typename T>
void pet(T x)
{
if(std::is_same<T, Cat>{}){ x.meow(); }
else if(std::is_same<T, Dog>{}){ x.bark(); }
}
Invocando
pet(Cat{});
pet(Dog{});
activará un error de compilación
(
ejemplo de wandbox
)
, porque ambas ramas de la instrucción
if
deben estar bien formadas.
prog.cc:10:40: error: no member named ''bark'' in ''Cat''
else if(std::is_same<T, Dog>{}){ x.bark(); }
~ ^
prog.cc:15:5: note: in instantiation of function template specialization ''pet<Cat>'' requested here
pet(Cat{});
^
prog.cc:9:35: error: no member named ''meow'' in ''Dog''
if(std::is_same<T, Cat>{}){ x.meow(); }
~ ^
prog.cc:16:5: note: in instantiation of function template specialization ''pet<Dog>'' requested here
pet(Dog{});
^
Cambio de
pet
para usar
if constexpr
template <typename T>
void pet(T x)
{
if constexpr(std::is_same<T, Cat>{}){ x.meow(); }
else if constexpr(std::is_same<T, Dog>{}){ x.bark(); }
}
solo requiere que las ramas se puedan analizar; solo la rama que coincida con la condición debe estar bien formada ( ejemplo de caja de barras ) .
El fragmento
pet(Cat{});
pet(Dog{});
compilará y funcionará como se espera.
C ++ 1z introducirá "constexpr if", un if que tendrá una de las ramas eliminadas, según la condición. Parece razonable y útil.
Sin embargo, ¿no es posible prescindir de la palabra clave constexpr? Creo que durante la compilación, el compilador debe saber si se conoce la condición durante el tiempo de compilación o no. Si es así, incluso el nivel de optimización más básico debería eliminar la rama innecesaria.
Por ejemplo (ver en godbolt: https://godbolt.org/g/IpY5y5 ):
int test() {
const bool condition = true;
if (condition) {
return 0;
} else {
// optimized out even without "constexpr if"
return 1;
}
}
Godbolt explorer muestra que incluso gcc-4.4.7 con -O0 no compiló "return 1", por lo que logró lo prometido con constexpr if. Obviamente, ese compilador antiguo no podrá hacerlo cuando la condición sea el resultado de la función constexpr, pero el hecho sigue siendo: el compilador moderno sabe si la condición es constexpr o no y no necesita que lo explique explícitamente.
Entonces la pregunta es:
¿Por qué se necesita "constexpr" en "constexpr if"?