c++ - Ejemplos de uso práctico de Boost:: MPL?
boost-mpl (6)
¿Puede compartir ejemplos del mundo real del uso de Boost::MPL (excepto lambdas), solo para permitirme comprender mejor sus propósitos y el campo del uso práctico? El tutorial de documentación de MPL tiene un ejemplo de análisis dimensional , pero tal vez porque es un ejemplo académico, no me ha dado una sensación de Boost :: MPL y cuándo se puede usar con eficacia.
Algo gracioso que hice: https://github.com/edubois/static-factorial/blob/master/main.cpp
Utiliza una pequeña parte de boost :: mpl para calcular estáticamente el valor de factorial <8> () ...
Esto puede ayudar a entender la idea principal.
El hecho es que Boost.MPL, como Boost.Preprocessor, realmente son bloques de construcción.
La mayoría de las veces, probablemente lo use a través de otras bibliotecas, ya que una cantidad de bibliotecas Boost se basan en esas dos.
Por ejemplo:
- Boost.Fusion (que cruza las brechas entre el tiempo de compilación y el tiempo de ejecución)
- Boost.MultiIndex (para una interfaz más fácil)
- Boost.Unit (para análisis dimensional)
- Boost.Variant puede, creo, también depende de ello
Puedes usarlo ya de manera desconocida :)
He usado Boost.Mpl para generar clases similares a variantes.
Por ejemplo, dada una lista tipo MPL como esta:
typedef boost::mpl::set<Foo, Bar, Baz> type_set;
Luego uso boost::mpl::fold
para construir una cadena de clases derivadas de cada una, cada una de ellas agrega un std::unordered_set
de uno de los tipos en el tipo de conjunto. El resultado final es una clase que contiene un unordered_set<Foo>
, un unordered_set<Bar>
y un unordered_set<Baz>
.
Y debido a que la clase se especifica en términos de un boost::mpl::set
, puedo iterar sobre estos tipos para generar automáticamente otras funciones también, como un operator==
que compara todos los unordered_set
.
Para agregar a la respuesta de Matthieu, también se usa ampliamente en Boost.Python y Luabind .
Uso boost :: mpl (y boost :: fusion) extensivamente en mi biblioteca stat_log . Esta biblioteca permite al usuario especificar una jerarquía de estadísticas y etiquetas de registro y sus comportamientos asociados, es decir, tipos de estadísticas por etiqueta (histograma, contador, etc.).
Confío mucho en la metaprogramación para hacer lo correcto con el usuario:
stat_log::writeStat<IP_PKTS_RCVD>(450);
Por ejemplo, si el usuario define el rasgo de tipo:
template <>
struct stat_tag_to_type<IP_PKTS_RCVD>
{
using type = Accumulator<
stat_log::HistogramCount<
int,
1, //start bin
1500, //stop bin
10 //num_bits
>
>;
};
la llamada "writeStat" anterior hará un proxy (en tiempo de compilación) a una estadística de histograma. El poderoso aspecto de esta técnica de diseño es que el sitio de llamada "writeStat" no está en absoluto acoplado con la estadística particular elegida.
También uso una gran cantidad de MPL y boost :: fusion para ver las estadísticas. Según su pregunta, consulte los siguientes archivos para obtener la mayor concentración de boost :: mpl:
https://github.com/rjmccabe3701/stat_log/blob/master/include/stat_log/util/stat_log_impl.h https://github.com/rjmccabe3701/stat_log/blob/master/include/stat_log/util/tag_commander.h https://github.com/rjmccabe3701/stat_log/blob/master/include/stat_log/stat_log.h
especialmente la ingeniosa plantilla meta "función" en stat_log_impl.h:
//This template is used in conjunction with an MPL algorithm
// with the same semantics as mpl::find_if.
//BoolFunc is the "condition" metafunction.
//StatTagFunc is a metafunction that transforms the given
// stat_tag into something the algorithm requires.
// For example the "Identity" metafunction would work here.
//StatTagArgs is extra arguments to the BoolFunc
template <template<typename...> class BoolFunc,
template<typename...> class StatTagFunc,
class... StatTagArgs>
struct tag_node_query
{
template<typename TheTagNode>
struct apply
{
using stat_tag = typename TheTagNode::tag;
using type = std::integral_constant
<
bool,
BoolFunc<
typename StatTagFunc<stat_tag>::type,
StatTagArgs...
>::value
>;
};
};
Utilizo una biblioteca de análisis dimensional más mejorada llamada Boost.Units.
Desarrollé una biblioteca de reflexión en tiempo de compilación y luego utilicé esa biblioteca para crear una clase genérica que proporcione runtime-reflection a cualquier tipo de reflejo reflejado en tiempo de compilación. Utilicé ese soporte para generar automáticamente componentes UI para editar las propiedades de tales tipos reflejados.
También es primordial para la distribución de eventos dentro de nuestra aplicación. Por ejemplo, cuando alguien cambia las unidades en las que desea que esté el sistema, no es necesario que le enseñe a ese sistema que se han agregado elementos nuevos a dispositivos determinados porque el código usa MPL para analizar esos tipos y simplemente sabe que se ha agregado algo y lo cambia
Acabo de utilizar técnicas de metaprogramación para envolver las señales de Qt en algo que recupera la seguridad tipo eliminada por su sistema y puede conectarse con cualquier entidad funcional.
Pero a decir verdad, casi seguramente usaste técnicas de metaprogramación prácticamente aplicadas cuando usaste algoritmos estándar como sort. Una implementación decente del algoritmo de ordenamiento utiliza una forma menos desarrollada de metaprogramación para analizar los iteradores pasados y luego utiliza el despacho de etiquetas para iniciar un algoritmo de ordenamiento capaz de utilizar completamente las características de esos iteradores.
Francamente, si no estás haciendo metaprogramación, entonces no estás utilizando el poder de C ++ y también puedes estar usando otra cosa.