使用Boost MPL线性化指数

时间:2016-03-21 23:31:03

标签: c++ templates boost

我正在开发一个更大的项目来概括模板瞬时,并且正在努力使用Boost MPL和C ++ 03来干净地线性化一些索引。用一个例子来展示我的问题是最容易的(原谅我的可怜的伪代码)。

我有N个任意长度的向量。说N是3,并说它们看起来像:

v0 = {1,2,3};
v1 = {4,5,6,7,8};
v2 = {9,10};

对于每一个,我有一个索引存储在一个单独的向量中,如:

vectorOfIndices = {0,4,1};

我想通过执行以下操作将这些转换为整体索引:

0*sizeof(v1)*sizeof(v2) + 4*sizeof(v2) + 1;

我正在寻找帮助定义的元函数/类是对它的概括,它应该包含两个模板参数,类型mpl :: vector(包含mpl :: int_ entries)。第一个向量将包含索引序列(vectorOfIndices,但长度为N),第二个向量将包含长度列表(上面的v0,v1,v2 ... vN的长度)。结果类型应该是包含整体索引的mpl :: int_。

1 个答案:

答案 0 :(得分:0)

花了一段时间(很多阅读...很多......元编程有一个陡峭的学习曲线),但我终于有了一个有效的解决方案。它不是最漂亮的,但它是我的:p。如果有人有改进建议或看到任何问题,我很乐意听取您的意见。

/* 
 * Computes and absolute index from a sequence of indices and vectors lengths.
 * Example:
 * 
 * Vectors:
 * v0 = {1, 2, 3}
 * v1 = {2}
 * v2 = {4, 5, 6, 7}
 * 
 * Inputs:
 * lengthsOfVectors = {3, 1, 4}
 * indexSequence = {2, 0, 3}
 * 
 * Result:
 * type = 2*(1*4) + 0*(4) + 3
 * 
 */
struct ComputeAbsoluteIndex
{
    template <typename lengthsOfVectors, typename indexSequence> struct apply
    {
        // Number of indices in sequence.
        typedef typename mpl::size<indexSequence>::type numberOfIndicesInSequence;

        // Forward sequence to iterate over number of indices in sequence.
        typedef typename mpl::range_c<int, 0, numberOfIndicesInSequence::value>::type indexSequenceRange;

        // Forward iterator that points to start of lengths of vectors. 
        // Add one since offset contributions are computed by multiplying the current index, from the index sequence, by the lengths subsequent vectors.
        typedef typename mpl::next<typename mpl::begin<lengthsOfVectors>::type >::type lengthsOfVectorsStart;

        // Forward iterator that points to the end of lengths of vectors.
        typedef typename mpl::end<lengthsOfVectors>::type lengthsOfVectorsEnd;

        typedef typename mpl::lambda // Helper metafunction class to multiply lengths.
        <
            mpl::fold // Loop over lengths to multiply.
            <
                mpl::_1, // Sequence of lengths to multiply.
                mpl::int_<1>, // Initial multiplier of one.
                typename mpl::lambda // Wrap multiply in lambda such that place holders (_1 and _2) are replaced properly.
                <
                    mpl::multiplies<mpl::_1, mpl::_2 >
                >::type
            >
        >::type multiplySequence;

        typedef typename mpl::fold // Loop over each index in index sequence.
        <
            indexSequenceRange, // Forward Sequence to iterate over number of indices in index sequence.
            mpl::int_<0>, // Initial total index of zero.
            mpl::plus // Add offsets.
            <
                mpl::_1, // Initial state to start (zero), then result of previous addition for each following iteration.
                mpl::multiplies // Multiply current index from index sequence by remaining lengths.
                <
                    mpl::at<indexSequence, mpl::_2 >, // Get current index from index sequence.
                    multiplySequence::apply // Invoke helper metafunction class to multiply lengths.
                    <
                        mpl::iterator_range // Create Forward Sequence that iterates over lengths to multiply.
                        <
                            mpl::advance<lengthsOfVectorsStart, mpl::_2>, // Advance iterator start to multiply proper lengths.
                            lengthsOfVectorsEnd
                        > 
                    >
                >
            >
        >::type type;
    };
};