Как стать автором
Обновить

DSL для boost::MPL, превращаем f(x) в f<x>::type

Время на прочтение 2 мин
Количество просмотров 3.4K
Краткое содержание статьи (для тех кто знаком с boost::mpl), typename опущены для ясности:
a = b;				==>		typedef b a;
f(x)				==>		f<x>::type
f(x) { return x*; }		==>		template<typename x> struct x { typedef x* type; };
f()(x)				==>		f::apply<x>::type
a[x]				==>		mpl::at<a, x>::type
(x ? y : z)			==>		mpl::if_<x, y, z>::type
switch (if_<x, y, z>)		==>		*Уфф*, общая (default) и частичные специализации
{
	case if_<bool_<false>, y, z>: return y;
	default: return z;
}

Под хабракатом есть немного пояснений :)

Если кто не в курсе, в С++ есть некоторый, слегка искусственный, механизм, позволяющий выполнять преобразования типов.
Есть у нас обычная переменная x, применяем к ней функцию f(x) и получаем другую переменную.
Так вот, и с типами можно похоже поступать — с помощью механизма шаблонов можно применять к некоторому типу x метафункцию f — «вызов» выполняется так: f<x>::type.
А метафункцию f описывают шаблонной структурой:
template<typename x>
struct f
{
	typedef x* type;
};


Конкретно эта метафункция превращает тип в указатель на этот тип.
В общем, бустовская библиотека MPL — это такая весьма мощная штука, позволяющая оперировать с контейнерами типов, применять к ним метафункторы и т.д. (все на этапе компиляции, естественно).
Мощная она, конечно, мощная, но голову там поломать на очередном
typedef typename detail::static_find_if<next_type, last_type, 
	mpl::bind1<typename mpl::lambda<pred_type>::type, 
		mpl::bind1<mpl::quote1<result_of::value_of>,mpl::_1>
		>
	> filter;

можно запросто.

Почему бы не сделать для этого DSL, т.е. специальный язык препроцессора, превращающий
__dsl::mpl { a = f(x); } в typedef typename f<x>::type a;?

А __dsl::mpl{ f(x) { return x*; } } — в ту самую шаблонную структуру.

Т.е. с помощью __dsl::mpl{...} мы говорим «вот в этом блоке кода мы будем заниматься метапрограммированием». И занимаемся. А вызов функции превращается в вызов метафункции, присваивание превращается в typedef и т.д.

Да, дополнительная стадия компиляции, ну а куда деваться? В чистом виде люди этого mpl'я просто боятся :).

В общем, за 1 день с помощью boost::spirit 2 удалось реализовать почти все описанные в заголовке конструкции.
Основное правило преобразования простое — все что во входном потоке не __dsl::mpl{… } отправляем на выход, что внутри нашего блока — транслируем.
Думаю, еще списки инициализации надо добавить, чтобы писать:
vector my_types = { MainWindow, AboutWindow, ExitWindow };

P.S. Может, кто подскажет, как такое потеснее заинтегрировать в Visual Studio? Чтобы не создавать дополнительные файлы и номера строк для ошибок отображать. Эх, мечты, мечты.
Теги:
Хабы:
+17
Комментарии 14
Комментарии Комментарии 14

Публикации

Истории

Работа

Программист C++
118 вакансий
QT разработчик
6 вакансий

Ближайшие события

PG Bootcamp 2024
Дата 16 апреля
Время 09:30 – 21:00
Место
Минск Онлайн
EvaConf 2024
Дата 16 апреля
Время 11:00 – 16:00
Место
Москва Онлайн
Weekend Offer в AliExpress
Дата 20 – 21 апреля
Время 10:00 – 20:00
Место
Онлайн