BOOST MPL Добавление двух объектов list_c приводит к неожиданному поведению

У меня есть следующий код:

#include <boost/mpl/list_c.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/equal.hpp>
#include <boost/mpl/equal_to.hpp>
#include <boost/mpl/assert.hpp>
#include <iostream>
#include <typeinfo>
#include <assert.h>

using namespace boost::mpl;

typedef list_c<long,0,2,4,6,8,10> evens;
typedef list_c<long,2,3,5,7,11,13> primes;
typedef list_c<long,2,5,9,13,19,23> sums;

typedef transform< evens, primes, plus<> >::type result;
BOOST_MPL_ASSERT(( equal< result,sums,equal_to<_1,_2> > ));

int main()
{
std::cout << typeid(sums).name() << std::endl << typeid(result).name() << std::endl;
assert(typeid(sums) == typeid(result));
}

Он компилируется, поэтому BOOST_MPL_ASSERT имеет место. Однако при его запуске утверждение в главной функции не выполняется. Что это значит? Разве две вещи list_c (кажется, мне не хватает подходящего слова), содержащие одинаковые элементы, определяют один и тот же тип?

Спасибо за помощь.

4

Решение

MPL не дает никаких гарантий относительно точных типов, которые являются результатом алгоритмов MPL.

1

Другие решения

transform выводит неопределенный тип последовательности (из integral_c<long, n> элементы), а не list_c,

Один из способов преобразования результата transform в известный тип должен использовать insert_range на list:

insert_range<list0<>, begin<list0<> >::type, result>::type

К сожалению, это не дает listвместо внутреннего mpl::l_item введите, так что вам придется сделать одну и ту же операцию с обеих сторон:

BOOST_MPL_ASSERT((is_same<
insert_range<list0<>, begin<list0<> >::type, result>::type,
insert_range<list0<>, begin<list0<> >::type, sums>::type>));

Эквивалентно, вы могли бы использовать reverse_copy в переднюю вставку:

BOOST_MPL_ASSERT((is_same<
reverse_copy<result, front_inserter<list0<> > >::type,
reverse_copy<sums, front_inserter<list0<> > >::type
>));

Действительно, потому что front_inserter реализуется с точки зрения внутренней метафункции push_frontэто дает тот же тип, что и insert_range,

Тем не менее, проще просто положиться на copy всегда получая один и тот же неопределенный тип последовательности:

BOOST_MPL_ASSERT((is_same<copy<result>::type, copy<sums>::type>));

И с тех пор copy алгоритм преобразования, он возвращает тот же тип, что и transformтак что вы можете просто написать:

BOOST_MPL_ASSERT((is_same<result, copy<sums>::type>));

assert(typeid(copy<sums>::type) == typeid(result));
1