2011-02-25 12 views
5

Escribí un código para generar un boost::mpl::vector para usar como una tabla de búsqueda para una función factorial, como una prueba para una función de biblioteca más general con la que un desarrollador puede generar una búsqueda tabla en forma de una matriz estática de primitivas. La función (que muy probablemente se implementaría como una definición de macro de preprocesador) aceptaría el nombre y el tamaño de la matriz que se inicializará, así como el nombre de una plantilla de clase que se utilizará como la metafunción para inicializar cada elemento i de la matrizConvirtiendo un vector MPL en una matriz estática

pensé que la mejor manera de ir haciendo esto sin el uso de scripts externos sería

  1. Crear un boost::mpl::vector, como se hace en el listado de código de abajo, y empuje el valor de retorno de la metafunción proporcionada por el usuario para cada elemento de la matriz en la parte posterior del vector;
  2. Utilice los elementos del vector para inicializar la matriz estática (quizás usando una serie de macros, la última de las cuales usaría la macro __VARARGS__ para lograr esto).

No sé cómo lograría (2) ni si el procedimiento que describo es una buena manera de hacer lo que busco. Aquí están las siguientes preguntas para las cuales me gustaría recibir respuestas:

  1. ¿Mi procedimiento es una buena manera de lograr lo que busco? De lo contrario, describa un procedimiento mejor que logre lo mismo, sin el uso de scripts externos.
  2. Si mi procedimiento es de hecho una buena manera de lograr lo que busco, ¿cómo implementaría (2)?

    Me aseguraré de publicar un enlace al archivo de origen que contiene la función de biblioteca que describo una vez que lo implemente. El listado del código sigue a continuación.

    namespace mpl = boost :: mpl;

    template <typename x> 
    struct factorial: 
        mpl::if_<mpl::greater<x, mpl::int_<1>>, 
         mpl::multiplies<x, factorial<x::prior>>, 
         mpl::int_<1> 
        >::type 
    {}; 
    
    template <typename sequence, typename size> 
    struct compileTable: 
        mpl::if_<mpl::greater<size, mpl::int_<0>>, 
         compileTable< 
          mpl::push_front<sequence, factorial<size>>::type, 
          size::prior 
         >, 
         sequence 
        >::type 
    {}; 
    
    static const int TABLE_SIZE = 13; 
    
    typedef compileTable< 
        mpl::vector<>, 
        mpl::int_<TABLE_SIZE> 
    >::type factorialTable; 
    
    /* 
    ** This is where I am stuck; how would I use the elements 
    ** of factorialTable to initialize a static array? 
    */ 
    
+0

use http://www.boost.org/doc/libs/1_45_0/libs/mpl/doc/refmanual/for-each.html – Anycorn

+0

Estoy un poco confundido aquí, ya que para cada uno es un algoritmo de tiempo de ejecución, ¿cómo lo usaría para inicializar una matriz estática? –

+0

¿qué quiere decir exactamente con matriz estática? 'static int foo []'? – Anycorn

Respuesta

1

Aquí está el código fuente para el archivo que contiene la función de la biblioteca, como se había prometido; por favor, asegúrese de leer los comentarios que he hecho debajo de las listas de códigos. Gracias de nuevo a aaa por su ayuda para mostrarme cómo inicializar una matriz estática usando BOOST_PP_ENUM!

El código fuente para XI/MPL/lut.h:

#ifndef __XI_LUT_INCLUDED__ 
#define __XI_LUT_INCLUDED__ 

#ifndef __cplusplus 
    #error The file __FILE__ requires a C++ compiler in order to be successfully compiled. 
#endif 

#include <boost/mpl/apply.hpp> 
#include <boost/mpl/at.hpp> 
#include <boost/mpl/greater.hpp> 
#include <boost/mpl/if.hpp> 
#include <boost/mpl/int.hpp> 
#include <boost/mpl/multiplies.hpp> 
#include <boost/mpl/placeholders.hpp> 
#include <boost/mpl/push_front.hpp> 
#include <boost/mpl/vector.hpp> 
#include <boost/preprocessor/repetition/enum.hpp> 

#define __XI_LUT_SET_INDEX(z, n, sequence) \ 
    mpl::at_c<sequence, n>::type::value 

#define __XI_GENERATE_LUT_IMPL(function, tableType, tableName, tableSize) \ 
    \ 
    template <typename sequence, typename size> \ 
    struct __compileTable_##function##_##tableSize##: \ 
     mpl::if_<mpl::greater<size, mpl::int_<0>>, \ 
      __compileTable_##function##_##tableSize##< \ 
       mpl::push_front<sequence, \ 
        mpl::apply< \ 
         function##<mpl::_>, \ 
         size \ 
        >::type>::type, \ 
       size::prior \ 
      >, \ 
      sequence \ 
     >::type \ 
    {}; \ 
    \ 
    typedef __compileTable_##function##_##tableSize##< \ 
     mpl::vector<>, \ 
     mpl::int_<##tableSize##> \ 
    >::type __compiledTable_##function##_##tableSize##; \ 
    \ 
    static const tableType tableName##[] = { \ 
     BOOST_PP_ENUM(\ 
      tableSize##, \ 
      __XI_LUT_SET_INDEX, \ 
      __compiledTable_##function##_##tableSize## \ 
     ) \ 
    } 

#define XI_GENERATE_LUT(function, tableType, tableName, tableSize) \ 
    __XI_GENERATE_LUT_IMPL(function, tableType, tableName, tableSize) 

#endif 

El código fuente de un archivo de prueba útil:

#include <boost/mpl/greater.hpp> 
#include <boost/mpl/if.hpp> 
#include <boost/mpl/int.hpp> 
#include <boost/mpl/multiplies.hpp> 
#include <boost/mpl/placeholders.hpp> 
#include <cstdio> 
#include <xi/mpl/lut.hpp> 

namespace mpl = boost::mpl; 

template <typename x> 
struct factorial: 
    mpl::if_<mpl::greater<x, mpl::int_<1>>, 
     mpl::multiplies<x, factorial<x::prior>>, 
     mpl::int_<1> 
    >::type 
{}; 

XI_GENERATE_LUT(factorial, int, FACTORIAL_TABLE, 4); 

int main(int argc, char ** argv) { 

    // This should print '24:' 
    printf("Result: %d.\n", FACTORIAL_TABLE[3]); 
    return 0; 

} 

voy a abstenerse de proporcionar una dirección URL para el archivo de ahora para poder seguir editando la lista del código. Estoy seguro de que el código se puede mejorar para fines de compatibilidad, por lo que definitivamente no está en un estado final. Aquí hay algunos problemas conocidos:

  1. El código no se compilará en MSVC 9.0.
  2. Intentar crear una tabla de búsqueda de un tamaño particular para un nombre de metafunción después de que ya se haya creado del mismo tamaño y para el mismo nombre de metafunción resultará en un error, ya que los tipos y plantillas correspondientes se definirían para estos parámetros . No quiero usar __COUNTER__ para aliviar este problema ya que es una definición de macro no estándar.

no han tratado de compilar este código en cualquier otro compiladores excepto CPI y MSCV, y me gustaría saber cómo GCC maneja - por favor hágamelo saber de cualquier problema que surja por lo que el recurso adecuado se puede tomar . Publicaré una URL en el archivo una vez que el código funcione sin problemas en la mayoría de los principales compiladores. ¡Cualquier comentario sería muy apreciado!

Cuestiones relacionadas