En el siguiente ejemplo de código, la if
instrucción depende del bool
parámetro de plantilla, que es una constante en tiempo de compilación. Los compiladores manejan este código de manera diferente:
MSVC falla con el error de enlace (que es lo que esperaba), porque la función de plantilla en la
else
rama carece de especialización para eltrue
valor del parámetro de plantilla (aunque nunca se llama).GCC y Clang compilan sin problemas y el comportamiento en tiempo de ejecución es correcto. Obviamente, esto se debe a que evalúan la
if
declaración en tiempo de compilación y eliminan las ramas no utilizadas antes de vincular.
La pregunta es qué comportamiento cumple con los estándares (o es un comportamiento indefinido y ambos son correctos a su manera).
#include <iostream>
template<const bool condition>
struct Struct
{
void print()
{
if (condition)
{
std::cout << "True\n";
}
else
{
printIfFalse();
}
}
private:
void printIfFalse();
};
template <>
void Struct<false>::printIfFalse()
{
std::cout << "False\n";
}
int main()
{
Struct<true> withTrue{};
withTrue.print();
Struct<false> withFalse{};
withFalse.print();
return 0;
}
fuente
if constexpr
Respuestas:
Todos los compiladores se comportan correctamente.
Su programa es mal formado, no se requiere diagnóstico , porque usted está usando odr a
Struct<true>::printIfFalse
través de la instanciación deStruct<true>::print()
requerido desde la llamadawithTrue.print();
. Una función que se usa fuera de una declaración descartada debe tener una definición en el programa, consulte [basic.def.odr] / 4 ; de lo contrario, el programa está mal formado, no se requiere diagnóstico .UNA declaración descartada es lo que obtienes si la usas
if constexpr
en una plantilla y la declaración no está en la rama elegida. Entonces, lo que puede hacer para que el programa esté bien formado es usarlo enif constexpr
lugar de hacerloif
. Esta es una característica de C ++ 17.fuente