生成巨大的Boost.MPL类型序列

时间:2012-02-29 23:09:57

标签: c++ boost-mpl template-meta-programming

考虑以下代码,自动生成Boost.MPL类型序列(列表或向量)。

    #include <iostream>                     // cout
    #include <boost/mpl/for_each.hpp>       // for_each
    #include <boost/mpl/identity.hpp>       // identity, make_identity
    #include <boost/mpl/int.hpp>            // int_
    #include <boost/mpl/list.hpp>           // list
    #include <boost/mpl/next.hpp>           // next
    #include <boost/mpl/push_front.hpp>     // push_front
    #include <boost/mpl/vector.hpp>         // vector

    template<size_t, typename> struct iota_n;

    template<typename Value>
    struct iota_n<0, Value>
    :
            boost::mpl::list<>      // can change this to boost::mpl::vector<>
    {};

    template<size_t N, typename Value>
    struct iota_n
    :
            boost::mpl::push_front< typename
                    iota_n< 
                            N - 1, typename
                            boost::mpl::next<Value>::type
                    >::type,
                    Value
            >
    {};

    // works for N <=  20 and boost::mpl::vector
    // works for N <= 247 and boost::mpl::list
    typedef iota_n< 247, boost::mpl::int_<0> >::type sequence;

    struct print
    {
            template<typename T>
            void operator()(boost::mpl::identity<T>)
            {
                    std::cout << T::value << "\n";
            }
    };

    int main()
    {
            boost::mpl::for_each<sequence, boost::mpl::make_identity<> >(
                    print()
            );
            std::cout << BOOST_MPL_LIMIT_LIST_SIZE << '\n';         // 20 on my system
            std::cout << BOOST_MPL_LIMIT_VECTOR_SIZE << '\n';       // 20 on my system
            return 0;
    }

根据Boost.MPL文档,boost::mpl::list序列最多可包含BOOST_MPL_LIMIT_LIST_SIZE个元素,类似于boost::mpl::vector,编译器可以达到BOOST_MPL_LIMIT_VECTOR_SIZE。两个宏在我的系统上评估为20。

MSVC ++ 2010和Boost 1.47.0确实无法生成超过记录的20个元素的向量。令人惊讶的是,它可以生成多达247个元素的列表!

有谁知道为什么会这样?

1 个答案:

答案 0 :(得分:5)

根据the docsBOOST_MPL_LIMIT_xxx_SIZE指定序列的可变参数形式的限制(例如list<>);除了编译器对模板参数数量的限制外,编号表单(例如list42<>)没有预定义的上限。好的,后一种说法并不完全准确:实际上,在默认库配置中,对使用预先生成的预处理标头强加的编号表单有限制;请参阅this post了解如何解除它。

关注:@rhalbersma您似乎将两个单独的概念捆绑在一起:列表元素的最大数量与list的“构造函数”的最大值。 BOOST_MPL_LIMIT_LIST_SIZE controls the latter,而不是前者,两者之间确实没有依赖关系。您上面的代码正在测试前者;最大模板arity是一个完全不同的野兽。

首先对MPL序列存在arity限制的原因是库必须模拟可变参数模板(它是在C ++ 11之前编写的),通常是by defaulting unused arguments to some auxiliary type and providing a bunch of specializations to weed out those unused arguments before constructing the actual sequence。这样做的代价是默认参数通常显示在错误消息中并掩盖其他所有内容,并且大量特化对编译时间有明显影响。 IOW,你必须停在某个地方,当时你似乎不太可能经常需要将超过20个序列元素传递给序列的“构造函数”(如果你这样做,总是有编号形式),因此当前限制。