5

我编写了一些代码来生成一个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?
    */
    
4

2 回答 2

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) };
于 2011-02-25T02:22:29.690 回答
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 到该文件。任何反馈将不胜感激!

于 2011-02-25T04:46:39.363 回答