📜 ⬆️ ⬇️

DSL for boost :: MPL, convert f (x) to f :: type

Summary of the article (for those familiar with boost :: mpl), typename omitted for clarity:
 a = b;  ==> typedef ba;
 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>) ==> * Uff *, general (default) and partial specializations
 {
	 case if_ <bool_ <false>, y, z>: return y;
	 default: return z;
 }

There are a few explanations under habrakat :)

If someone does not know, in C ++ there is some, slightly artificial, mechanism that allows you to perform type conversions.
We have an ordinary variable x, apply the function f (x) to it and get another variable.
So, it is possible to act similarly with types - using the template mechanism, you can apply a metafunction f to some type x - the “call” is performed like this: f<x>::type .
And the metafunction f is described by a template structure:
 template <typename x>
 struct f
 {
	 typedef x * type;
 };


Specifically, this meta-function turns a type into a pointer to this type.
In general, the MPL Boost library is such a very powerful thing that allows you to operate with type containers, apply metafunctors to them, etc. (all at compile time, of course).
Powerful it is, of course, powerful, but it breaks the head there at the next
 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;

You can easily.

Why not make a DSL for this, i.e. special preprocessor language that turns
__dsl::mpl { a = f(x); } __dsl::mpl { a = f(x); } in typedef typename f<x>::type a; ?
')
And __dsl::mpl{ f(x) { return x*; } } __dsl::mpl{ f(x) { return x*; } } - to the same template structure.

Those. with the help of __dsl :: mpl {...} we say “in this block of code we will be involved in metaprogramming”. And doing. And the function call turns into a meta-function call, the assignment turns into typedef, etc.

Yes, an additional stage of compilation, but where to go? In its pure form, people of this mpl are simply afraid :).

In general, in 1 day, using boost :: spirit 2, almost all the constructs described in the header were implemented.
The basic conversion rule is simple - everything that is in the input stream is not __dsl :: mpl {...} sent to the output, which is broadcast inside our block.
I think more initialization lists should be added to write:
vector my_types = {MainWindow, AboutWindow, ExitWindow};

PS Maybe someone will tell you how to integrate more closely into Visual Studio? Not to create additional files and line numbers for errors to display. Oh, dreams, dreams.

Source: https://habr.com/ru/post/86651/


All Articles