【问题标题】:generating huge Boost.MPL type sequences生成巨大的 Boost.MPL 类型序列
【发布时间】:2012-02-29 23:09:56
【问题描述】:

考虑以下自动生成 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 个元素的列表!

有人知道为什么会这样吗?

【问题讨论】:

  • 只是一个猜测,但我认为实现 mpl 向量比仅包含一个简单的两个参数模板的链表更困难,并且涉及更多的元编程。考虑到更简单的模板和可能更少的实例化、更少的静态递归和分支,mpl 列表能够处理更多元素,这对我来说并不奇怪。
  • 那么在这种情况下,为什么限制向量和列表序列的宏不一样呢?在我的系统上,两者都是 20,但我可以生成多达 247 个元素的列表!
  • 这些宏设置了实际限制,这可能是基于 boost 作者通常可以在各种编译器中安全支持的内容。您可以使用 list 进行检查的事实可能仍然超出了 boost 作者希望您编写可移植代码的范围。
  • 换句话说,您可以在您现在使用的任何编译器(MSVC 2010)上使用您的 mpl 列表执行 247 个列表条目,但您可能无法移植它许多不同编译器的代码。每个都有不同的限制,这些宏可能是基于作者在各种编译器中发现的实际限制。

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


【解决方案1】:

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

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

首先,MPL 序列存在数量限制的原因是该库必须模拟可变参数模板(它是在 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 个序列元素传递给序列的“构造函数”(如果你这样做了,总是有编号的形式),因此当前限制。

【讨论】:

  • 是的,我知道如何更改限制宏。但是,在我的系统上,列表的宏等于 20,但我可以生成最多包含 247 个元素的列表! iota_n 的错误消息提到了 Sequence = list<...>,而不是 list248<...>。所以我仍然很困惑为什么宏不将列表限制为 20,就像它对 vector 所做的那样。
  • @rhalbersma 曾经尝试过将您的代码移植到不同的编译器吗?您现在看到的这些限制不是基于某些标准语言限制,而是基于编译器的限制。推动编译器的模板递归限制肯定不会产生非常可移植的代码。
  • @stinky472 我曾经使用 Eclipse/CDT 进行并行构建(同时使用 gcc 和 Intel 编译器),但 Ubuntu 在 C++ 库中有点落后(我大量使用 c++11我的项目中的功能)。我应该重试,谢谢。
  • 我刚刚看到了 FOLLOW UP(我没有收到自动通知,因为它不是单独的评论)。谢谢,这是一个非常有用的答案。
猜你喜欢
  • 2011-01-04
  • 1970-01-01
  • 1970-01-01
  • 2012-01-08
  • 2020-08-17
  • 2017-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多