2010-10-21 9 views
9

Estoy confundido acerca de las ventajas del uso de las lasVentajas del uso de MPL impulso :: :: bool_ en lugar de un int const

bool_<true> 

y

bool_<false> 

tipos contra el simple uso de Bools const en el contexto de la metaprogramación de plantillas.

La biblioteca boost :: mpl claramente prefiere el primer enfoque, y define funciones auxiliares como and_, or_ para ayudar a administrar tal bool_. Las metafunciones condicionales como if_ "toman" un bool_ como primer argumento (plantilla), pero detrás de las escenas "llaman" a una metafunción if_c que espera un (const) bool como primer argumento (plantilla).

¿Cuáles son los argumentos detrás de esta decisión?

Gracias de antemano por su ayuda!

Respuesta

11

Aquí hay un pequeño ejemplo de cómo uso estos tipos de vez en cuando. Este ejemplo no sería posible, utilizando const int:

void do_something(boost::mpl::bool_<true>) 
{ 
    ... 
} 

void do_something(boost::mpl::bool_<false>) 
{ 
    ... 
} 

Llame a uno de estos dos funciones dependiendo del tipo de argumento:

template<class T> 
void doIt(void) 
{ 
    do_something(boost::mpl::bool_<boost::is_pointer<T>::val>()) 
} 

En este caso, la primera o la segunda función será llamado, dependiendo del hecho si el tipo T es un puntero o no. Estos tipos le permiten usar la función de sobrecarga, donde no sería posible usar un const bool. Con un bool const tendrías que decidir en tiempo de ejecución, qué rama tomar. Esto es especialmente importante si las funciones llamadas son en sí mismas plantillas, que no se compilarían correctamente, si se instanciaran para tipos distintos a los esperados, p. la primera definición de función anterior podría contener código, que solo compila para punteros.

+0

¡Gracias, ese es un buen ejemplo! – stepelu

+0

¡Oh, sí, me olvidé de sobrecargar! – sbi

+2

Esta es una buena respuesta, pero es mucho más detallada de lo necesario. Puede escribir 'do_something (boost :: is_pointer ())', que hará lo mismo de la misma manera. –

2

supongo que una de las razones es que bool_<...> son tipos, y al utilizarlos como resultado de un funciones del meta, usted nunca tendrá que parar y pensar si su resultado es un tipo y hay que hacerlo

typedef some_type result; 

o un valor, el cual tiene que ser devuelto como

const static ??? result = some_value; 

donde también se tiene que realizar un seguimiento de este tipo.

Además, sospecho (no he trabajado con Boost.MPL aún) que ambos tienen un tipo anidado result referirse a sí mismos, por lo que se puede escribir funciones meta con sólo derivada de ellos:

template< bool b > 
struct my_meta_func : bool_<b> {}; 

y puede invocar my_meta_func::result.

+0

Tienes razón en adelante, sólo resultados son siempre llamados ':: type' en MPL. –

8

Se trata de crear la uniformidad suficiente para que la biblioteca pueda proporcionar una funcionalidad útil. El protocolo MPL es: "todos los argumentos de metafunción (y devoluciones) son tipos". Esto nos permite escribir plantillas que pueden operar genéricamente en metafunciones. Por ejemplo, esta plantilla acepta cualquier metafunción (o cualquier metafunción con hasta N argumentos en C++ 03):

template <template <class...> class some_metafunction> 
struct wrapper; 

Una vez que permitir que algunos de los argumentos de plantilla a ser no-tipos, la escritura se convierte en un envoltorio de tales imposible.Para un ejemplo práctico de por qué nos preocupamos, esta uniformidad permite a la biblioteca separar y evaluar las expresiones MPL lambda. Si los argumentos de metafunción permitieran ser no-tipos, esa característica no se podría implementar, porque no habría forma de escribir todas las especializaciones parciales necesarias para desenredar la plantilla externa xxx de sus argumentos ai en xxx<a1,a2,a3,...>.

Una razón menos interesante, si no menos válida, es que muchas cosas se vuelven menos detalladas de la manera en que lo hicimos en MPL. Comparar:

and_<mf0<x,y>, mf1<z>, mf2<x,z> >::value 

vs

mf0<x,y>::value && mf1<z>::value && mf2<x,z>::value 
Cuestiones relacionadas