генерирование огромных последовательностей типа Boost.MPL - PullRequest
4 голосов
/ 01 марта 2012

Рассмотрим следующий код, который автоматизирует генерацию последовательностей типа 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 Ответ

5 голосов
/ 01 марта 2012

В соответствии с документами , BOOST_MPL_LIMIT_xxx_SIZE указывается ограничение для последовательности variadic (например, list<>);форма пронумерована (например, list42<>), не имеет предварительно определенного верхнего предела, кроме ограничений компилятора на количество параметров шаблона.Хорошо, последнее утверждение не совсем точно: на практике в конфигурации библиотеки по умолчанию есть ограничение на пронумерованные формы, налагаемое с использованием предварительно сгенерированных предварительно обработанных заголовков;см. этот пост о том, как его поднять.

СЛЕДУЙТЕ ЗА: @rhalbersma Вы, кажется, связываете два отдельных понятия: максимальное количество элементов списка и максимальная арность list "конструктор".BOOST_MPL_LIMIT_LIST_SIZE контролирует последнее , а не первое, и между ними действительно нет никакой зависимости.Ваш код выше тестирует первый;максимальная шаблонная арность это совершенно другой зверь.

Причина, по которой существует ограничение арности для последовательностей MPL, в первую очередь заключается в том, что библиотека должна была эмулировать шаблоны с переменным числом аргументов (это было написано задолго до C ++ 11), что обычно выполняется по умолчаниюнеиспользуемые аргументы некоторого вспомогательного типа и предоставление набора специализаций, чтобы отсеять эти неиспользуемые аргументы перед построением фактической последовательности .Стоимость этого заключается в том, что аргументы по умолчанию обычно отображаются в сообщениях об ошибках и скрывают все остальное, а большое количество специализаций заметно влияет на время компиляции.Итак, вам пришлось где-то остановиться, и в то время казалось маловероятным, что вам часто приходилось передавать более 20 элементов последовательности в «конструктор» последовательности (и если вы это делали, всегда есть пронумерованные формы), отсюда и текущаяпределы.

...