2011-02-25 1 views
5

Я написал код для генерации boost::mpl::vector для использования в качестве справочной таблицы для факториальной функции в качестве теста для более общей библиотечной функции, с помощью которой разработчик может создавать поиск таблицу в виде статического массива примитивов. Функция (которая, скорее всего, будет реализована как определение макропроцессора), будет принимать имя и размер инициализируемого массива, а также имя шаблона класса, который будет использоваться в качестве метафайла для инициализации каждого элемента. i of массив.Преобразование вектора MPL в статический массив

Я думал, что лучший способ идти об этом без использования внешних скриптов будет

  1. Создать boost::mpl::vector, как это делается в коде листинга ниже, и нажать возвращаемое значение из предоставленная пользователем метафункция для каждого элемента массива на обратной стороне вектора;
  2. Используйте элементы вектора, инициализирующего статический массив (возможно, используя ряд макросов, последний из которых будет использовать макрос __VARARGS__ для выполнения этого).

Я не знаю ни того, как я выполнил бы (2), ни то, что я описываю, - это хороший способ делать то, что я ищу. Вот следующие вопросы, на которые я хотел бы ответить:

  1. Является ли моя процедура хорошим способом достижения того, что я ищу? Если нет, просьба описать лучшую процедуру, которая будет выполнять одно и то же, без использования внешних скриптов.
  2. Если моя процедура действительно является хорошим способом достижения того, что я ищу, как бы реализовать (2)?

    Обязательно отправьте ссылку на исходный файл, содержащий библиотечную функцию, которую я описываю, как только я ее реализую. Ниже приведен список кодов.

    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

Я немного запутался здесь - поскольку for-each - это алгоритм времени выполнения, как бы я использовал его для инициализации статического массива? –

+0

Что именно вы подразумеваете под статическим массивом? 'static int foo []'? – Anycorn

ответ

1

Вот исходный код файла, содержащего функции библиотеки, как и обещал; пожалуйста, прочитайте замечания, которые я сделал ниже списков кодов. Еще раз спасибо aaa за помощь в показе мне, как инициализировать статический массив с помощью BOOST_PP_ENUM!

Исходный код 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 

Исходный код для полезного тестового файла:

#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; 

} 

Я воздержусь от предоставления URL к файлу для теперь, чтобы я мог продолжать редактировать список кодов. Я уверен, что код может быть улучшен с точки зрения совместимости, поэтому он определенно не находится в конечном состоянии. Вот некоторые известные проблемы:

  1. Код не компилируется на MSVC 9.0.
  2. Попытка создать таблицу поиска определенного размера для имени метафайла после того, как он уже был создан того же размера и для одного и того же имени метафайла, приведет к ошибке, так как для этих параметров будут определены соответствующие типы и шаблоны , Я не хочу использовать __COUNTER__, чтобы облегчить эту проблему, поскольку это определение нестандартного макроса.

Я не пробовал компиляции этого кода на других компиляторах, кроме ICC и MSCV, и хотел бы знать, как GCC обрабатывает его - пожалуйста, дайте мне знать о каких-либо проблем, которые возникают так, что надлежащее обращение может быть принято , Я отправлю URL-адрес в файл, как только код будет работать с большинством основных компиляторов. Любая обратная связь будет принята с благодарностью!