Форум программистов, компьютерный форум, киберфорум
Boost C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.55/11: Рейтинг темы: голосов - 11, средняя оценка - 4.55
 Аватар для DiffEreD
1458 / 795 / 257
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2

MPL упражнения из документации

20.07.2014, 23:45. Показов 2275. Ответов 4
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Если кто читал документацию по MPL, то там в туториале есть раздел с упражнениями по пройденному материалу Exercises. Мне интересно было и вот моя попытка решить некоторые из них. Хотелось бы услышать замечания по моему коду и увидеть где я накосячил. Ну и так, может кому интересно будет.
Проблемы у меня возникли с заданиями 1.0 (не уверен правильно ли подошел к нему) и 1.6 (так и не решил до конца). Вот код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#include <iostream>
#include <boost/type_traits.hpp>
#include <boost/static_assert.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/mpl/equal.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/apply.hpp>
#include <boost/mpl/arithmetic.hpp>
 
namespace mpl = boost::mpl;
using namespace mpl::placeholders;
 
//1-0 Use BOOST_STATIC_ASSERT to add error checking to the binary template presented
//in section 1.4.1 so that binary<N>::value causes a compilation error if N contains
//digits other than 0 or 1.
 
//Вроде бы так.
template <int N>
struct binary : mpl::int_<N>
{
   BOOST_STATIC_ASSERT(( N != 0 && N != 1 ));
};
 
typedef binary<2>::type two; //Ok
BOOST_STATIC_ASSERT(( binary<3>::value == 3 )); //Ok
//typedef binary<1>::type two; //assert
//typedef binary<0>::type two; //assert
 
//1-1 Turn vector_c<int,1,2,3> into a type sequence with elements (2,3,4) using transform.
typedef mpl::vector_c<int, 1,2,3>::type ints;
typedef mpl::transform<ints, mpl::plus<_1, mpl::int_<1>> >::type res_t;
BOOST_MPL_ASSERT(( mpl::equal<res_t, mpl::vector_c<int, 2,3,4>::type> ));
 
 
//1-2 Turn vector_c<int,1,2,3> into a type sequence with elements (1,4,9) using transform.
typedef mpl::transform<ints, mpl::times<_1, _1> >::type res_t2;
BOOST_MPL_ASSERT(( mpl::equal<res_t2, mpl::vector_c<int, 1,4,9>> ));
 
 
//1-3 Turn T into T**** by using twice twice.
template <typename F, typename Arg>
struct twice : mpl::apply<F, typename mpl::apply<F, Arg>::type>
{};
 
template <typename T>
struct two_pointers : twice<boost::add_pointer<_1>, T>
{};
 
template <typename T>
struct four_pointers : twice<boost::add_pointer<_1>, typename two_pointers<T>::type>
{};
 
BOOST_STATIC_ASSERT(( boost::is_same<four_pointers<int>::type, int****>::value ));
 
 
//1-4 Turn T into T**** using twice on itself.
template <typename T>
struct four_pointers2 : twice<boost::add_pointer<_1>, typename twice<boost::add_pointer<_1>, T>::type>
{};
 
BOOST_STATIC_ASSERT(( boost::is_same<four_pointers2<int>::type, int****>::value ));
 
//1-5 There's still a problem with the dimensional analysis code in section 1.1.
/*Hint: What happens when you do:
f = f + m * a;
Repair this example using techniques shown in this chapter.*/
 
typedef mpl::vector_c<int,1,0,0,0,0,0,0> mass;
typedef mpl::vector_c<int,0,1,-2,0,0,0,0> acceleration;
typedef mpl::vector_c<int,1,1,-2,0,0,0,0> force;
 
template <typename T, typename Dimensions>
struct quantity
{
   template <typename OtherDimensions>
   quantity(quantity<T, OtherDimensions> const& rhs) : m_value(rhs.value())
   {
      BOOST_STATIC_ASSERT(( mpl::equal<Dimensions, OtherDimensions>::type::value ));
   }
 
   explicit quantity(T x) : m_value(x)
   {}
 
   T value() const { return m_value; }
private:
   T m_value;
};
 
template <typename T, typename D1, typename D2>
quantity<T, typename mpl::transform<D1, D2, mpl::plus<_1, _2>>::type>
operator * (const quantity<T, D1>& x, const quantity<T, D2>& y)
{
   typedef typename mpl::transform<D1, D2, mpl::plus<_1, _2>>::type dim;
   return quantity<T, dim>(x.value() * y.value());
}
 
template <typename T, typename D>
quantity<T, D> operator + (const quantity<T, D>& x, const quantity<T, D>& y)
{
   return quantity<T, D>(x.value() + y.value());
}
 
//Решение:
template <typename T, typename D1, typename D2>
quantity<T, D1> operator + (const quantity<T, D1>& x, const quantity<T, D2>& y)
{
   BOOST_MPL_ASSERT(( mpl::equal<D1, D2> ));
   return quantity<T, D1>(x.value() + y.value());
}
 
//1-6 Build a lambda expression that has functionality equivalent to twice.
//Hint: mpl::apply is a metafunction!
 
//Не работает
template <typename F, typename Arg>
struct twice2
{
   typedef typename mpl::lambda<F>::type once;
   typedef typename mpl::lambda<once>::type twice;
 
   //typedef typename twice::apply<Arg>::type type;
};
 
template <typename T>
struct two_pointers2 : twice2<boost::add_pointer<_1>, T>
{};
 
//BOOST_STATIC_ASSERT(( boost::is_same<two_pointers2<int>::type, int**>::value ));
 
int main()
{
   quantity<float, mass> m(2.0f);
   quantity<float, acceleration> a(9.8f);
   quantity<float, force> f = m * a;
   f = f + m * a;
   std::cout << "(f = f + m * a) :" << f.value() << "\n";
 
   return 0;
}
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
20.07.2014, 23:45
Ответы с готовыми решениями:

tmp with mpl
я в ран тайме заполняю массив числами фибоначи до 10000 элемента...можно ли вычислить в компиле тайм и в рантайме только заполнить?..)

boost::mpl
Всем привет. Просьба поделиться какими-либо реальными примерами использования Boost :: MPL, чтобы я лучше мог понять его цели и область...

MPL push_back
А как тут push_back пользоваться?#include &lt;iostream&gt; #include &lt;type_traits&gt; #include &lt;boost/mpl/vector.hpp&gt; #include...

4
 Аватар для DiffEreD
1458 / 795 / 257
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
22.07.2014, 12:59  [ТС]
Упражнение 1-7. Расставил только некоторые ассерты. С лямбдой более менее все понятно, а с apply, где на первом месте стоит заменитель, не совсем все понятно - как их вызывать то потом?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
typedef mpl::lambda<mpl::lambda<_1> >::type t1;
typedef t1::apply<mpl::int_<42>>::type r1;
BOOST_MPL_ASSERT_RELATION( r1::value, ==, 42 );
 
typedef mpl::apply<_1, mpl::plus<_1,_2> >::type t2;
BOOST_STATIC_ASSERT(( boost::is_same<t2, mpl::plus<_1,_2>>::value ));
 
typedef mpl::apply<_1, std::vector<int> >::type t3;
BOOST_STATIC_ASSERT(( boost::is_same<t3, std::vector<int>>::value ));
 
typedef mpl::apply<_1, std::vector<_1> >::type t4;
BOOST_STATIC_ASSERT(( boost::is_same<t4, std::vector<_1>>::value ));
 
typedef mpl::apply<mpl::lambda<_1>, std::vector<int> >::type t5;
BOOST_STATIC_ASSERT(( boost::is_same<t5, std::vector<int>>::value ));
 
// не совсем понял как это трактовать:
typedef mpl::apply<mpl::lambda<_1>, std::vector<_1> >::type t6;
//BOOST_STATIC_ASSERT(( boost::is_same<t6, std::vector<_1>>::value ));
BOOST_MPL_ASSERT(( mpl::equal<t6, std::vector<_1>> ));
 
// тут тоже:
typedef mpl::apply<mpl::lambda<_1>, mpl::plus<_1,_2> >::type t7;
//BOOST_MPL_ASSERT(( mpl::equal<t7, mpl::plus<_1,_2>> )); // assert
 
// аналогично:
typedef mpl::apply<_1, mpl::lambda< mpl::plus<_1,_2> > >::type t8;
//typedef t8::type<mpl::int_<1>, mpl::int_<2>>::type r8;
Как пользоватьтся вот таким выражениям:
C++
1
2
3
4
typedef mpl::apply<_1, mpl::plus<_1,_2> >::type t2;
//так не работает
typedef mpl::bind<t2, mpl::int_<42>, mpl::int_<42>> test1;
BOOST_MPL_ASSERT_RELATION( test1::value, ==, 84 );
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
22.07.2014, 15:03
Лучший ответ Сообщение было отмечено DiffEreD как решение

Решение

DiffEreD, А что именно непонятно в 6?

C++
1
2
   typedef mpl::apply<mpl::lambda<_1>, std::vector<_1> >::type t6;
   BOOST_STATIC_ASSERT((boost::is_same<t6::apply<int>::type, std::vector<int> >::value));
7 например так:
C++
1
2
   typedef mpl::apply<mpl::lambda<_1>, mpl::plus<_1,_2> >::type t7;
   BOOST_STATIC_ASSERT((mpl::equal<t7::apply<mpl::int_<1>, mpl::int_<2> >::type, mpl::int_<3> >::value));
А 8 как-то так:

C++
1
2
   typedef mpl::apply<_1, mpl::lambda<mpl::plus<_1,_2> > >::type t7;
   BOOST_STATIC_ASSERT((mpl::equal<t7::type::apply<mpl::int_<1>, mpl::int_<2> >::type, mpl::int_<3> >::value));
Добавлено через 8 минут
А по последнему: можно как-то так.
C++
1
2
3
   typedef mpl::apply<_1, mpl::plus<_1,_2> >::type t2;
   typedef mpl::apply<t2, mpl::int_<42>, mpl::int_<42> > test;
   BOOST_STATIC_ASSERT((test::type::value == 84));
2
 Аватар для DiffEreD
1458 / 795 / 257
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
22.07.2014, 17:41  [ТС]
ForEveR, спасибо за примеры, очень познавательно.
Я вот тут еще пытаюсь решить первое задание с моего первого поста про binary. Там, короче, надо было код с книги (C++ Template Metaprogramming) брать, я сразу не понял. Вот такой код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
template <unsigned long N>
struct binary
{
   static constexpr unsigned value =
         binary<N/10>::value << 1 | N%10;
};
 
template<> struct binary<0>
{
   static constexpr unsigned value = 0;
};
 
unsigned constexpr seven = binary<111>::value;
unsigned constexpr invalid = binary<101234>::value;
 
BOOST_STATIC_ASSERT(seven == 7);
Надо что бы при параметризации binary цифрами отличными от 0 и 1 срабатывал assert. Я застрял на этом:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
template <unsigned long N>
struct is_valid
{
   static constexpr unsigned check = is_valid<N % 10>::check;
   typedef typename mpl::if_< mpl::equal<mpl::size_t<0>, mpl::size_t<check>>,
   mpl::true_,
   mpl::if_<mpl::equal<mpl::size_t<1>, mpl::size_t<check>>,
   mpl::true_,
   mpl::false_>
   >::type type;
};
 
template<> struct is_valid<0>
{
   static constexpr unsigned check = 0;
};
 
template <unsigned long N>
struct binary
{
   BOOST_STATIC_ASSERT(is_valid<N>::type::value);
   static constexpr unsigned value =
         binary<N/10>::value << 1 | N%10;
};
 
template<> struct binary<0>
{
   static constexpr unsigned value = 0;
};
 
unsigned constexpr seven = binary<111>::value;
unsigned constexpr invalid = binary<101234>::value;
 
BOOST_STATIC_ASSERT(seven == 7);
Компилятор уходит в глубокий штопор.
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
23.07.2014, 14:22
Лучший ответ Сообщение было отмечено DiffEreD как решение

Решение

DiffEreD, Пишем простенькую рекурсивную функцию вида:
C++
1
2
3
4
5
bool is_valid_f(int value)
{
   int current = value % 10;
   return value == 0 ? true : current == 0 || current == 1 ? is_valid_f(value / 10) : false;
}
Тестируем, она работает. Пишем такой же вариант через структуры, работающий на этапе компиляции:
C++
1
2
3
4
5
6
7
8
template <unsigned long N>
struct is_valid : mpl::bool_<N % 10 == 0 || N % 10 == 1 ? is_valid<N / 10>::value : false>
{
};
 
template<> struct is_valid<0> : mpl::true_
{
};
Тестируем - на invalid дается assert. Можно все конечно написать через mpl::if_ etc, но мне лень и слишком громоздко.

Добавлено через 3 минуты
Хотя, вполне достаточно сделать и так.

C++
1
2
3
4
5
6
7
template <unsigned long N>
struct binary
{
   BOOST_STATIC_ASSERT(N % 10 == 0 || N % 10 == 1);
   static constexpr unsigned value =
         binary<N/10>::value << 1 | N%10;
};
3
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
23.07.2014, 14:22
Помогаю со студенческими работами здесь

mpl проход по элементам
Пытался написать вывод элементов vector_c не через for_each. Не вышло. Кто подскажет как сие сделать наиболее удобно? Пример вектора. ...

split mpl::boost
Реализация compile-time алгоритма split для строки. Так как оставлять сообщения в теме...

Определить mpl последовательность
здравствуйте, помогите допилить mpl-sequence до юзабельного состояния, за основу взято это: http://rsdn.ru/forum/cpp/4523366.all в...

boost::mpl и метапрограммирование вцелом
Сейчас сижу любуюсь на mpl::vector. template&lt; typename T0, typename T1, typename T2, typename T3, typename T4 , typename...

Достать mpl sequency из условия
здравствуйте, есть такой код: template&lt;typename seq&gt; struct get_symbols { typedef typename mpl::back&lt;seq&gt;::type symbol; ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Логарифм записывается как: (x-2)log(x^2+2) - означает логарифм (x^2+2) по основанию (x-2). Унарный минус обозначается как ! */ #include <iostream> #include <stack> #include <cctype>. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru