将MPL向量转换为静态数组

5
我写了一些代码来生成一个 boost::mpl::vector 作为阶乘函数的查找表,这是一个更通用库函数的测试,开发人员可以使用该函数生成原语静态数组形式的查找表。该函数(最有可能被实现为预处理器宏定义)将接受要初始化的数组的名称和大小,以及要用作元函数初始化每个元素 i 的类模板的名称。
我认为在不使用外部脚本的情况下做到这一点的最佳方法是:
  1. 创建一个 boost::mpl::vector,如下面的代码清单中所示,并将用户提供的元函数的返回值推送到向量的后面,以初始化数组的每个元素;
  2. 使用向量的元素初始化静态数组(也许通过使用一系列宏,其中最后一个宏将使用 __VARARGS__ 宏来实现这一点)。
我不知道我应该如何完成(2),也不知道我描述的过程是否是我所寻求的好方法。以下是我想要回答的问题:
  1. Is my procedure a good way of accomplishing what I seek? If not, please describe a better procedure which would accomplish the same thing, without the use of external scripts.

  2. If my procedure is indeed a good way of accomplishing what I seek, how would I implement (2)?

    I will be sure to post a link to the source file containing library function which I describe once I implement it. The code listing follows below.

    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?
    */
    

请使用http://www.boost.org/doc/libs/1_45_0/libs/mpl/doc/refmanual/for-each.html。 - Anycorn
我在这里有点困惑 - 因为for-each是一个运行时算法,那么我该如何使用它来初始化静态数组? - void-pointer
你所说的静态数组是什么意思?static int foo[]是指什么? - Anycorn
抱歉 - 我的意思是在编译时初始化的静态常量数组,例如 static int * const FOO = { ... }。 - void-pointer
2个回答

9

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。任何反馈都将不胜感激!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接