Instancias redundantes en expresiones constantes booleanas
Frecuentes
Visto 116 veces
2
tengo un n-cualquier booleano OR
función de tiempo de ejecución any_run
#include <assert.h>
bool any_run() { return false; }
template <typename... B>
bool any_run(bool a, B... b)
{
assert(a);
return a || any_run(b...);
}
así como un análogo en tiempo de compilación any_comp
#include <type_traits>
template <bool E>
using expr = std::integral_constant <bool, E>;
using _true = expr <true>;
using _false = expr <false>;
template <typename... A>
struct any_comp : public _false { };
template <typename A, typename... B>
struct any_comp <A, B...> : public expr <A() || any_comp <B...>()>
{
static_assert(A(), "");
};
ambos contienen aserciones (en tiempo de ejecución o en tiempo de compilación, respectivamente) para garantizar que el primer argumento sea verdadero.
Ahora dando la siguiente entrada
int main()
{
any_run (true, false, false);
any_comp <_true, _false, _false>();
}
la aserción en tiempo de ejecución nunca falla, pero la de tiempo de compilación sí. Esto significa que any_run(false, false)
nunca se llama, sin embargo any_comp <_false, _false>
se instancia, a pesar del hecho de que la expresión constante booleana
A() || any_comp <B...>()
podría ser evaluado para true
if A() == true
sin instanciar nunca any_comp <B...>
.
Mi pregunta es si este experimento y su conclusión son válidos, y qué diría la norma al respecto.
Es importante porque si la conclusión es válida, tendría que volver a implementar varias funciones en tiempo de compilación con más cuidado (con más especializaciones) para que la compilación sea más rápida, aunque generalmente prefiero mantener las cosas lo más simples posible.
1 Respuestas
3
El cortocircuito solo funciona en el nivel de tiempo de ejecución para ||
. En tiempo de compilación, necesita algo más como:
#include <type_traits>
template <typename T, typename U>
struct integral_or : U { };
template <typename U>
struct integral_or <std::true_type, U> : std::true_type { };
template <typename... A>
struct any_comp : std::false_type { };
template <typename A, typename... B>
struct any_comp <A, B...> : integral_or <A, any_comp <B...>>
{
static_assert(A(), "");
};
int main()
{
any_comp <std::true_type, std::false_type, std::false_type>();
}
Respondido el 21 de Septiembre de 13 a las 12:09
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas c++ c++11 instantiation template-meta-programming constant-expression or haz tu propia pregunta.
Correcto... y estamos (casi) de regreso a C++03... Y estaba tan feliz de deshacerme de todas esas funciones como
integral_and
que hacen todo tan ilegible cuando ocurren expresiones más complejas. ¡Gracias! - iavrTambién podría sobrecargar los operadores booleanos para implementar plantillas de expresión y proporcionar una sintaxis más clara (
decltype( a() || b() && c() )
por ejemplo. Me gusta este - Manu343726