I find C++ template metaprogramming so funny. Maybe it’s the feel of being hacking the compiler, maybe is just a way to improve my functional programming skills. I’m not sure. But the fact is that I do meta on C++ a lot, and I’m actually used to the way it works and its idiosyncrasies.
In this crazy story, to run the metaprogram becomes to compile the c++ program and then see the results. This means the process usually includes feeding some input variables for our metaprogram, compile it, and run the resulting C++ program to see the results. You can always inspect the assembly and deal with name mangling if you don’t want to run the executable…
Let’s write a simple metaprogram: To generate 100 consecutive numbers at compile-time.
Let’s build it:
And then run the executable to see what happened:
What if i want to run the same metaprogram, but with different arguments? There’s no equivalent of
int main(int argc, char* argv) for metaprograms. What we probably are going to do is to touch the code and repeat all the build steps above.
Trust me, this is so boring. Even more if you want to test your metaprograms multiple times with a widespread set of inputs.
I’m sick of this. There should be a better way to play with C++ template metaprograms. Okay, there’s not, so let’s try develop it. Meet foldie
A run system for C++ template metaprograms
Since running the metaprogram becomes to build the C++ program, a build system becomes a run system. I’m going crazy, I know.
So what’s our goal?
- Pass parameters to the metaprogram in an easy way
- Run the metaprogram
- See its results (output)
Everything in a human readable way. I love YAML-based configuration, you have been warned.
Passing parameters to the metaprogram
What’s the equivalent of
int main(int argn, char* argv)? I’m not sure. Here’s my solution: Keep your input variables in a header file, then include that file:
Foldie takes its input in the form of a
foldie.yaml file with the project settings.
For metaprogram input, just add values to the
Then foldie will generate a
foldie.hpp file from your input. Also you can specify a custom header with the
Note all files/directories are relative to the
Passing parameters to the metaprogram, director’s cut
“Put each input in the yaml
input entry”. Simple and working approach, but still a bit boring, isn’t? Since I have done the effort to write this scripts, let’s push the thing to the top level. Forget templates. Enter python values.
You can even write simple python expressions:
The single quotes are needed, a matter of how yaml parses the file…
Then foldie will generate
tml::list<std::integral_constant<int,1>, std::integral_constant<int,1>,...,std::integral_constant<int,99>> typelist named
But this does not work with Turbo only. What foldie really does is to figure out what datatypes your metaprogramming library has, then translates the python values to your lib equivalents. This is the
The key of each entry is the name of the equivalent python type, with some exceptions such as
pair since python does not handle those types. I added them for convenience.
This is part of the
foldie.yml file I have written to try foldie with Eric Niebler’s Meta:
The syntax for datatypes is simple: Just write your templates, putting variables on them representing the python input:
$(n)represents the n-element of the input python value. Note for simple values only
$(1)variable is valid.
$(...)represents the whole python value as a sequence (So it only works with sequence values). That is, think of it as variadic pack expansion. It also supports slices in the form
Foldie parses datatypes recursively. So in most situations only one simple variable substitution is needed. See the lists examples above:
$(...) variable there really means “expand whatever elements the sequence has”. Before variable substitution foldie always translates variable/s value/s first.
Building and running
Of course you can run your favorite compiler and then launch the executable. But since the point of foldie is to ease running metaprograms, it provides two extra entries:
Again, paths are relative to
Foldie is shipped as a bash executable script which calls the
foldie.py script. Let’s see foldie’s help message:
We have three commands:
foldie build: Build metaprogram. Does all the processing, parsing input, generating foldie input header, then calling the build command.
foldie run: Just calls the output executable, supposed to see the output.
foldie buzz: Calls two commands above, for easy running.
Also we have a
--project argument which can be used to pass an alternative
foldie.yml file (Foldie supposes it’s the
foldie.yml file located on the current directory by default) and an incremental verbose flag.
Let’s write a simple foldie example step by step:
TODO: C++ snippet example
Written with StackEdit.