c++ - resueltos - ¿Necesito poner constexpr después de else-if?
sentencia if else en c++ (1)
¿Necesitamos poner constexpr después de cada sentencia if en el bloque if-else en este tipo de situaciones?
Sí. El else-if bloque 1 es una mentira :), solo hay bloques si 1 y else bloques 1 . Así es como el compilador ve tu código:
if constexpr (std::is_same_v<int, T>)
return {a, 0.0};
else // {
if (std::is_same_v<double, T>)
return {0, a};
else
return {0, 0.0};
// }
else if (/*...*/)
es solo una convención de formato que todos usan. Como tal, puede ver claramente que se necesita el segundo constexpr
.
1 : "bloque" no es la terminología correcta. si es una declaración (con otra parte opcional). Un bloque es { /*...*/ }
.
Inspirado por esta respuesta , intenté copiar y pegar (y agregar pruebas en main()
) este código:
template<typename T>
std::tuple<int, double> foo(T a) {
if constexpr (std::is_same_v<int, T>)
return {a, 0.0};
else if (std::is_same_v<double, T>)
return {0, a};
else
return {0, 0.0};
}
int main()
{
auto [x, y] = foo("");
std::cout << x << " " << y;
}
Esto es muy sencillo: si T
se deduce como int
, queremos devolver una tupla de [a, 0.0]
. Si T
se deduce como double
, queremos devolver una tupla de [0, a]
. De lo contrario, queremos devolver [0, 0.0]
.
Como puede ver, en la función main()
, estoy llamando a foo
con el argumento const char*
, lo que debería resultar en que x
e y
sean 0
. Ese no es el caso .
Al intentar compilarlo, me encontré con un error extraño:
error: no se pudo convertir ''
{0, a}
'' de ''<brace-enclosed initializer list>
'' ''a''std::tuple<int, double>
''
¿Y yo estaba como qué? . Por qué demonios querría que ... std::is_same
específicamente std::is_same
para habilitar la return {0, a}
solo cuando el tipo de a
se deduce como double
.
Así que rápidamente corrí a cppreference en if-constexpr. En la parte inferior de la página, arriba de Notas , podemos ver este fragmento de código:
extern int x; // no definition of x required
int f() {
if constexpr (true)
return 0;
else if (x)
return x;
else
return -x;
}
Pensé para mí oookay ..? Realmente no puedo ver lo que está mal con el código original. Utilizan la misma sintaxis y semántica ....
Pero yo tenía curiosidad. Tenía curiosidad si tal vez algo extraño (en ese momento) pudiera solucionar ese problema, así que cambié el código original a:
template<typename T>
std::tuple<int, double> foo(T a) {
if constexpr (std::is_same_v<int, T>)
return {a, 0.0};
else if constexpr (std::is_same_v<double, T>) // notice the additional constexpr here
return {0, a};
else
return {0, 0.0};
}
int main()
{
auto [x, y] = foo("");
std::cout << x << " " << y;
}
¡Y voilá! El código compilado y ejecutado como se espera. Entonces, mi pregunta es: ¿debemos poner constexpr
después de cada sentencia if-else
en la sentencia if-else
en este tipo de situaciones? ¿O es sólo mi compilador? Estoy usando GCC 7.3.