Преобразование вектора MPL в статический массив - PullRequest
5 голосов
/ 25 февраля 2011

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

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

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

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

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

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

    пространство имен 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?
    */
    

Ответы [ 2 ]

9 голосов
/ 25 февраля 2011

http://www.boost.org/doc/libs/1_46_0/libs/preprocessor/doc/index.html

#define MACRO(z, i, data) \
    mpl::at_c<data,i>::value

static const data[] = { BOOST_PP_ENUM(N, MACRO, factorialTable) };
1 голос
/ 25 февраля 2011

Вот исходный код файла, содержащего библиотечную функцию, как и было обещано;пожалуйста, обязательно прочитайте замечания, которые я сделал ниже, в списках кодов.Еще раз спасибо 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-адрес файла, как только код заработает без проблем на большинстве основных компиляторов.Любая обратная связь будет принята с благодарностью!

...