将MPL向量转换为静态数组

时间:2011-02-25 01:25:42

标签: c++ templates c-preprocessor metaprogramming boost-mpl

我编写了一些代码来生成boost::mpl::vector以用作阶乘函数的查找表,作为更通用库函数的测试,开发人员可以使用该函数在表单中生成查找表一个静态的基元数组。该函数(最有可能实现为预处理器宏定义)将接受要初始化的数组的名称和大小,以及要用作初始化每个元素的元函数的类模板的名称​​ i 阵列。

我认为在不使用外部脚本的情况下执行此操作的最佳方法是

  1. 创建boost::mpl::vector,如下面的代码清单所示,并将数组中每个元素的用户提供的元函数的返回值推送到向量的后面;
  2. 使用向量的元素初始化静态数组(可能使用一系列宏,其中最后一个将使用__VARARGS__宏来完成此操作。)
  3. 我既不知道我将如何完成(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?
      */
      

2 个答案:

答案 0 :(得分:9)

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 :(得分: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__来缓解这个问题,因为它是一个非标准的宏定义。
  3. 我没有尝试在除ICC和MSCV之外的任何其他编译器上编译此代码,并且想知道GCC如何处理它 - 请让我知道任何出现的问题,以便适当的追索权可能被采取。一旦代码工作,我将在文件中发布一个URL,在大多数主要编译器上都没有问题。任何反馈将不胜感激!