【问题标题】:Copy an mpl::vector_c to a static array at compile time在编译时将 mpl::vector_c 复制到静态数组
【发布时间】:2012-05-31 09:00:23
【问题描述】:

使用 C++11 我有类似的东西

#include <boost/mpl/vector_c.hpp>
#include <boost/mpl/size.hpp>

#include <boost/array.hpp>

#include <iostream>

namespace mpl = boost::mpl;

template<std::size_t ... Args>
struct Test
{
            typedef mpl::vector_c<std::size_t, Args ...> values_type;

            static const boost::array<std::size_t, sizeof...(Args)> values;
};


int main (int argc, char** argv)
{
            Test<3,2,5,6,7> test;
            return 0;
}

我想用 mpl::vector_c 中“包含”的值初始化 boost::array 内容。此初始化应在编译时执行。我在 SO 上看到了一些使用预处理器的解决方案,但我不知道如何将它们应用于可变参数模板案例。

请注意,在上面的示例代码中,mpl::vector_c 的元素与Test 的模板参数相同。在实际代码中并非如此,而是 values_type 具有长度 == 模板参数的数量,但实际值来自一系列 mpl 算法的应用。因此,不要假设论点是相同的。

希望问题清楚,谢谢!

【问题讨论】:

    标签: c++ templates boost c++11 boost-mpl


    【解决方案1】:

    一种方法是使用at_c将vector_c提取到一个参数包中,然后展开并使用它来初始化数组。

    #include <cstdio>
    #include <array>
    #include <boost/mpl/vector_c.hpp>
    #include <boost/mpl/at.hpp>
    #include <boost/mpl/size.hpp>
    #include <utils/vtmp.hpp>
    // ^ https://github.com/kennytm/utils/blob/master/vtmp.hpp
    
    template <typename MPLVectorType>
    class to_std_array
    {
        typedef typename MPLVectorType::value_type element_type;
        static constexpr size_t length = boost::mpl::size<MPLVectorType>::value;
        typedef std::array<element_type, length> array_type;
    
        template <size_t... indices>
        static constexpr array_type
                make(const utils::vtmp::integers<indices...>&) noexcept
        {
            return array_type{{
                boost::mpl::at_c<MPLVectorType, indices>::type::value...
            }};
        }
    
    public:
        static constexpr array_type make() noexcept
        {
            return make(utils::vtmp::iota<length>{});
        }
    };
    

    int main()
    {
        typedef boost::mpl::vector_c<size_t, 3, 2, 5, 6, 7> values;
    
        for (size_t s : to_std_array<values>::make())
            printf("%zu\n", s);
        return 0;
    }
    

    我在这里使用std::array,但您可以简单地将其更改为boost::array,它仍然有效。表达式

    to_std_array<MPLVector>::make()
    

    在编译时运行,因为make() 函数是constexpr


    相同的技术通常用于将std::tuple 扩展为std::array (Convert std::tuple to std::array C++11),扩展为函数调用("unpacking" a tuple to call a matching function pointer),等等。

    【讨论】:

    • 我只是好奇与for (size_t s : {3, 2, 5, 6, 7})相比有没有优势?
    • @betabandido:不,它们都编译成同一个程序集(当然是在优化之后)。
    • 我猜想在模板元编程的更复杂使用中,问题中显示的方法和您的解决方案实际上是必要的,对吧?例如,我正在考虑需要将数组从一个函数传递到另一个函数的情况。在这种情况下是否也可以使用普通数组 ({3, 2, ...})?
    • @betabandido:我不明白你的问题。数组和初始化列表都可以使用基于范围的for进行迭代。
    • @CntrAltCanc:统一初始化。理想情况下,一对{ 就足够了(即array_type{...}),但是clang 会产生错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-04
    • 1970-01-01
    • 2021-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多