Descubrí plantilla de metaprogramación hace más de 5 años y tiene un enorme retroceso de la lectura C++ Moderno Diseño pero nunca he encontrado un opertunity para usarlo en la vida real.

Han que nunca utilizó esta técnica en el código real?

Contribuyentes a Boost no es necesario aplicar ;o)

InformationsquelleAutor Motti | 2008-09-15

15 Comentarios

  1. 26

    Alguna vez he utilizado la plantilla de metaprogramación en C++ para implementar una técnica llamada «simbólica de la perturbación» para tratar con el degenerado de entrada en algoritmos geométricos. Mediante la representación de expresiones aritméticas como las plantillas anidadas (es decir, básicamente por escrito a cabo el análisis de los árboles con la mano) yo era capaz de entregar todo el análisis de la expresión a la plantilla del procesador.

    Haciendo este tipo de cosas con las plantillas es más eficiente que, por ejemplo, la escritura de árboles de expresión, el uso de objetos y haciendo el análisis en tiempo de ejecución. Es más rápido porque el modificado (perturbado) árbol de expresión está disponible para el optimizador en el mismo nivel que el resto de su código, para obtener el máximo de beneficios de la optimización, tanto en sus expresiones, sino también (cuando sea posible) entre sus expresiones y los alrededores de código.

    Por supuesto, usted puede lograr lo mismo mediante la implementación de una pequeña DSL (lenguaje específico de dominio) por sus expresiones y el pegado de la traducción del código de C++ en el programa regular. Que obtendrían los mismos beneficios de optimización y también ser más legible -, pero la desventaja es que usted tiene que mantener un analizador.

    • Prefiero mantener un analizador, personalmente, de mantener anidada las plantillas de C++.
    • Usted no necesita un analizador. El Uso De JetBrains Meta De La Programación Del Sistema. Usted puede definir un lenguaje, un editor y un generador de código. Usted no necesita un analizador en absoluto porque son de la edición de el árbol de sintaxis directamente. Y no es un anuncio, este programa es software libre.
  2. 21

    He encontrado las políticas, que se describe en C++ Moderno Diseño, muy útil en dos situaciones:

    1. Cuando estoy desarrollando un componente que me espera va a ser reutilizados, pero de una manera ligeramente diferente. Alexandrescu la sugerencia de utilizar una política para reflejar un diseño se adapta muy bien aquí – me ayuda a conseguir más allá de preguntas como, «yo podría hacer esto con un subproceso en segundo plano, pero lo que si alguien más tarde quiere hacerlo en intervalos de tiempo?» Ok bien, acabo de escribir mi clase para que acepte un ConcurrencyPolicy y aplicar la que más me necesitan en el momento. Al menos sé que la persona que viene detrás de mí puede escribir y enchufe en una nueva política cuando la necesitan, sin tener que totalmente de renovación de mi diseño. Advertencia: he a reinar a mí mismo, a veces, o este puede salirse de control — recuerda el YAGNI principio!

    2. Cuando estoy tratando de rehacer varias similar bloques de código en una sola. Generalmente el código se copia-pega y modificado ligeramente, porque habría tenido demasiado if/else lógica de lo contrario, o porque el tipo en cuestión eran demasiado diferentes. He encontrado que a menudo las políticas de permitir una limpia única versión donde la lógica tradicional o la herencia múltiple no.

  3. 13

    Lo he utilizado en el interior de los bucles de un juego de gráficos del código, donde se desea un cierto nivel de abstracción y la modularidad, pero no puede pagar el costo de las ramas o virtual de llamadas. En general fue una solución mejor que una proliferación de manuscritas de casos especiales de funciones.

  4. 12

    Plantilla de metaprogramación y la expresión de las plantillas son cada vez más popular en la comunidad científica como de la optimización de métodos de descarga de algunos de que el esfuerzo computacional en el compilador, mientras que el mantenimiento de algunas de abstracción. El código resultante es más grande y menos legible, pero he utilizado estas técnicas para acelerar álgebra lineal las bibliotecas y los métodos de cuadratura en FEM bibliotecas.

    Para la aplicación específica de la lectura, Todd Veldhuizen es un gran nombre en esta área. Un libro popular es C++ y Orientado a Objetos Numéricos de la Computación para Ingenieros y Científicos por Daoqi Yang.

    • Bien, de acuerdo a la tabla de contenido, D. Yang libro contiene 7 páginas de material en expr. las plantillas y metaprogramación. El resto parece ser un general de programación 101 libro de texto, con un par de ejemplo con métodos numéricos. Nada de malo con eso, por supuesto.
    • Justo lo suficiente. Para una información más completa de la referencia, me gustaría ir con la Alexandrescu libro. Las referencias que he citado son específicas de informática científica de aplicaciones, y puede ser limitado por mi conocimiento de la literatura. El Barton/Nackman libro también tiene una pequeña cantidad de material.
  5. 10

    Plantilla meta de programación es un maravilloso y el poder de la técnica cuando la escritura de c++ bibliotecas. Lo he utilizado un par de vez en soluciones personalizadas, pero generalmente la menos elegante de estilo antiguo, c++ solución es más fácil de conseguir a través de la revisión de código y más fáciles de mantener para el resto de usuarios.

    Sin embargo, tengo una gran cantidad de kilometraje de plantilla meta de programación cuando la escritura de componentes reutilizables/bibliotecas. No estoy hablando de algo tan grande que algunos de Boost cosas pequeñas componentes que se volverán a utilizar con frecuencia.

    He utilizado TMP para un singleton sistema donde el usuario puede especificar qué tipo de singleton que se desee. La interfaz es muy básica. Debajo de ella fue impulsado por las fuertes TMP.

    template< typename T >
    T& singleton();
    
    template< typename T >
    T& zombie_singleton();
    
    template< typename T >
    T& phoenix_singleton();

    Otro uso exitoso fue la simplificación de nuestro IPC de la capa. Está construido mediante clásico estilo OO. Cada mensaje debe derivar de una clase base abstracta y reemplazar algunos métodos de serialización. Nada demasiado extremo, pero que genera una gran cantidad de la caldera de la placa de código.

    Tiramos algunas TMP y automatizado de la generación de todo el código para el caso simple de los mensajes que contienen sólo POD de datos. El TMP mensajes todavía se utiliza la OO backend pero reducir drásticamente la cantidad de la caldera de la placa de código. El TMP también fue utilizado para generar el mensaje de visitante. Con el tiempo todos nuestro mensaje emigraron a la TMP método. Era más fácil y menos código para crear un sencillo POD struct sólo para el paso de mensajes y agregar los pocos (tal vez 3) líneas necesarias para obtener la TMP para generar las clases que derivan de un nuevo mensaje para enviar una clase regular a través de la CIP marco.

  6. 7

    Yo uso la plantilla de metaprogramación todo el tiempo, pero en D, no en C++. C++plantilla metalenguaje fue originalmente diseñado para el tipo simple parametrización y se convirtió en una Turing completo metalenguaje casi por accidente. Por lo tanto, es una de Turing tarpit que sólo Andrei Alexandrescu, no los simples mortales, puede utilizar.

    D plantilla del sublenguaje, por otro lado, fue en realidad diseñado para metaprogramación más allá de la simple tipo de parametrización. Andrei Alexandrescu parece que el amor de ella, pero otras personas pueden realmente entender su D plantillas. También es lo suficientemente poderoso que alguien escribió un en tiempo de compilación raytracer en ella como una prueba de concepto.

    Supongo que el más útil/no-trivial metaprogram que he escrito en la D era una plantilla de función que, dada una estructura de tipo como el parámetro de plantilla y una lista de nombres de encabezado de columna en un orden correspondiente a las declaraciones de variables en la estructura como en tiempo de ejecución parámetro, se lee en un archivo CSV, y devolver un array de structs, uno para cada fila, cada struct campo correspondiente a una columna. Todas las conversiones de tipo (string float, int, etc.) se realizan de forma automática, basándose en los tipos de los campos de la plantilla.

    Otro bueno, que en su mayoría funciona, pero todavía no sabe manejar un par de casos correctamente, es una copia profunda plantilla de función que se encarga de estructuras, clases, y las matrices correctamente. Se utiliza sólo en tiempo de compilación reflexión y la introspección, de modo que puede trabajar con estructuras, que, a diferencia de en toda regla clases, no tienen tiempo de ejecución de reflexión y la introspección de las capacidades de D porque se supone que deben ser de peso ligero.

    • Es útil saber acerca de la D, pero creo que la pregunta es acerca de C++, no D.
    • En cualquier caso, es útil para saber qué tipos de cosas que usted puede lograr con la metaprogramación cuando usted no tiene que ser un gurú para entenderlo 🙂
    • Parece que el enlace a la ray-tracer estaba roto 🙁
  7. 6

    La mayoría de los programadores que utilizan la plantilla de metaprogramación uso de él de forma indirecta, a través de las bibliotecas como boost. Ni siquiera probablemente sabe lo que está sucediendo detrás de las escenas, sólo que hace que la sintaxis de ciertas operaciones mucho más fácil.

  8. 4

    He usado un poco con el código de DSP, especialmente Fft, fija el tamaño de buffers circulares, hadamard transforma y similares.

  9. 4

    Para aquellos que están familiarizados con Oracle Plantilla de la Biblioteca (OTL), boost::cualquier Loki de la biblioteca (la descrita en C++ Moderno Diseño) aquí está la prueba de concepto TMP código que permite almacenar una fila de otl_stream en vector<boost::any> contenedor y el acceso a los datos de número de columna. Y ‘Sí’, me voy a incorporar en el código de producción.

    #include <iostream>
    #include <vector>
    #include <string>
    #include <Loki/Typelist.h>
    #include <Loki/TypeTraits.h>
    #include <Loki/TypeManip.h>
    #include <boost/any.hpp>
    #define OTL_ORA10G_R2
    #define OTL_ORA_UTF8
    #include <otlv4.h>
    using namespace Loki;
    /* Auxiliary structs */
    template <int T1, int T2>
    struct IsIntTemplateEqualsTo{
    static const int value = ( T1 == T2 );
    };
    template <int T1>
    struct ZeroIntTemplateWorkaround{
    static const int value = ( 0 == T1? 1 : T1 );
    };
    /* Wrapper class for data row */
    template <class TList>
    class T_DataRow;
    template <>
    class T_DataRow<NullType>{
    protected:
    std::vector<boost::any> _data;
    public:
    void Populate( otl_stream& ){};
    };
    /* Note the inheritance trick that enables to traverse Typelist */
    template <class T, class U>
    class T_DataRow< Typelist<T, U> >:public T_DataRow<U>{
    public:
    void Populate( otl_stream& aInputStream ){
    T value;
    aInputStream >> value;
    boost::any anyValue = value;
    _data.push_back( anyValue );
    T_DataRow<U>::Populate( aInputStream );
    }
    template <int TIdx>
    /* return type */
    Select<
    IsIntTemplateEqualsTo<TIdx, 0>::value,
    typename T,
    typename TL::TypeAt<
    U,
    ZeroIntTemplateWorkaround<TIdx>::value - 1
    >::Result
    >::Result
    /* sig */
    GetValue(){
    /* body */
    return boost::any_cast<
    Select<
    IsIntTemplateEqualsTo<TIdx, 0>::value,
    typename T,
    typename TL::TypeAt<
    U,
    ZeroIntTemplateWorkaround<TIdx>::value - 1
    >::Result
    >::Result
    >( _data[ TIdx ] );
    }
    };
    int main(int argc, char* argv[])
    {
    db.rlogon( "AMONRAWMS/[email protected]" ); //connect to Oracle
    std::cout<<"Connected to oracle DB"<<std::endl;
    otl_stream o( 1, "select * from blockstatuslist", db );
    T_DataRow< TYPELIST_3( int, int, std::string )> c;
    c.Populate( o );
    typedef enum{ rcnum, id, name } e_fields; 
    /* After declaring enum you can actually acess columns by name */
    std::cout << c.GetValue<rcnum>() << std::endl;
    std::cout << c.GetValue<id>() << std::endl;
    std::cout << c.GetValue<name>() << std::endl;
    return 0;
    };

    Para aquellos no familiarizados con las mencionadas bibliotecas.

    El problema con OTL del otl_stream contenedor, es que uno puede acceder a los datos de las columnas sólo en el orden secuencial de la declaración de variables de tipo apropiado y la aplicación de la operator >> a otl_stream objeto de la siguiente manera:

    otl_stream o( 1, "select * from blockstatuslist", db );
    int rcnum; 
    int id;
    std::string name;
    o >> rcnum >> id >> name; 

    No siempre es conveniente. La solución es escribir alguna clase de contenedor y rellenarla con los datos de otl_stream. El deseo es ser capaz de declarar la lista de tipos de columna y, a continuación:

    • tomar el tipo T de la columna
    • declarar variables de ese tipo
    • aplicar olt_stream::operator >>(T&)
    • almacenar el resultado (en el vector de boost::cualquier)
    • tomar el tipo de la columna siguiente y repita hasta que todas las columnas son procesados

    Usted puede hacer todo esto con la ayuda de Loki la Typelist una estructura, plantilla de la especialización y de la herencia.

    Con la ayuda de Loki la biblioteca de construcciones también puede generar montón de GetValue funciones que devuelven valores de tipo apropiado deducir de la columna número (en realidad el número de tipo de Typelist).

  10. 2

    No he usado en el código de producción.

    ¿Por qué?

    1. Tenemos que apoyar a 6+ plataformas con nativo plataforma compiladores. Es
      duro lo suficiente como para utilizar STL en este entorno digamos moderna plantilla
      técnicas.
    2. De que los desarrolladores no parecen estar manteniendo a C++ avances más. Hacemos uso de C++
      cuando tenemos que. Hemos código de la herencia con el legado de los diseños. El nuevo código es
      hecho en algo más, por ejemplo, Java, Javascript, Flash.
    • Lamentablemente este es el caso también para nosotros.
  11. 2

    Casi 8 meses después de preguntar a este fin he utilizado algunos TMP, yo uso un TypeList de interfaces para implementar QueryInterface en una clase base.

    • He querido hacer lo mismo, pero no todavía. Tenemos un montón de código heredado envuelto como objetos COM de modo que se puede acceder desde C#, pero nadie quiere trabajar en él o ampliarlo porque la COM repetitivo es tan tedioso. Estoy seguro de plantilla de metaprogramación en realidad podría ayudar, pero simple plantilla de programación no es porque de la manera COM reglas difieren de C++ queridos.
  12. 2

    Yo lo uso con boost::statechart para grandes statemachines.

    • Usted debe tratar de la próxima boost:msm – la meta de la máquina de estado (esperemos que en boost 2.0). Es un entrire de la máquina de estado marco basado en la metaprogramación. Y su UML2 compatible. Nos hizo uso de ella para un par de proyectos y simplemente impresionante. Así, en el lado negativo, hay un largo tiempo de compilación…
    • Entonces, ¿cómo se diferencian en características de sc? La única uml los conceptos sc falta se distribuyen y se unan, que son fáciles de imitar.
    • Sólo una actualización. Me miró a los hsh ahora que está en el impulso adecuado. No es de ninguna manera un sustituto para un statechart como parece que carecen de cualquier tipo de jerarquía. Los HSH que parece ser un diagrama de transición de estados, donde statechart es más como un statechart de stateflow/simulink.
  13. 1

    Sí que tengo, sobre todo para hacer algunas de las cosas que se asemejan a los de pato de escribir cuando me estaba terminando un legado de la API en un sistema más moderno de C++ de la interfaz.

  14. -1

    Que no lo hacen. La razón detrás de esto es la siguiente: por la naturaleza de la plantilla de metaprogramación, si alguna parte de su lógica se realiza en tiempo de compilación, toda lógica que es dependiente debe hacerse en tiempo de compilación como bien. Una vez que de inicio, haga una parte de su lógica en tiempo de compilación, no hay retorno. La bola de nieve va a seguir rodando y no hay manera de detenerlo.

    Por ejemplo, no se puede iterar sobre los elementos de un impulso::tupla<>, porque sólo se puede acceder a ellos en tiempo de compilación. Usted debe utilizar la plantilla de metaprogramación para lograr lo que habría sido fácil y sencilla de C++, y este siempre sucede cuando los usuarios de C++ no se tiene suficiente cuidado de no mover demasiadas cosas a tiempo de compilación. A veces es difícil de ver cuando un cierto uso de tiempo de compilación lógica sería problemático, y a veces los programadores con ganas de probar y probar lo que he leído en Alexandrescu del. En cualquier caso, esta es una muy mala idea en mi opinión.

    • mpl::for_each, boost.la fusión, inteligente contras<car,cdr> especialización, todas bastante fácil de puente de compilación en tiempo de ejecución v
    • Bueno, no es que difícil decidir a un límite donde desea pasar de tiempo de compilación al tiempo de ejecución de la programación. Obviamente, no todo el código que uso una plantilla que necesita ser hecho con la plantilla de programación. Y por lo general, usted no tiene esa cantidad de niveles entre el reutilizables de código genérico y el específico de la aplicación del código.
  15. -4

    Muchos programadores no uso plantillas mucho debido a la mala compilador de apoyo hasta hace poco. Sin embargo, mientras que las plantillas han tenido un montón de problemas en el pas, los nuevos compiladores tiene mucho mejor soporte. Puedo escribir el código que se tiene que trabajar con GCC en Mac y Linux, así como en Microsoft Visual C++, y es sólo con GCC 4 y VC++ 2005 que estos compilador han apoyado la norma realmente bien.

    De programación genérica a través de plantillas no es algo que usted necesita todo el tiempo, pero es sin duda útil el código para tener en su caja de herramientas.

    El ejemplo obvio contenedor de clases, pero las plantillas también son útiles para muchas otras cosas. Dos ejemplos de mi propio trabajo son:

    • Punteros inteligentes ( por ejemplo, Referencia contada, copy-on-write, etc.)
    • De matemáticas clases de apoyo, tales como Matrices, vectores, estrías, etc. que se necesita para apoyar una variedad de tipos de datos y todavía ser eficiente.
    • La pregunta fue sobre la plantilla de metade programación, no el viejo y simple de las plantillas, que son mucho más comúnmente utilizado.

Dejar respuesta

Please enter your comment!
Please enter your name here