T4 Templates - suitable for generating C++ code?
A bit lengthy answer yet I think some might find it interesting
I would say T4 is excellent to generate C++ with
Some might retort that C++ already has tools to do MetaProgramming with like:
The Preprocessor
Using the preprocessor and higher-order macros you can achieve somewhat what you can do with T4, but I say there are some pretty convincing benefits of T4:
- The generated code from T4 is easy to debug and understand
- MetaProgramming with T4 is simpler than with the preprocessor. The preprocessor can do macros like max/min easy enough but when we talk about model driven templates it gets difficult
- T4 is more powerful than the preprocessor making it easier to develop the templates
- T4 can be executed as part of the build process or on-demand
Partial template specialization
I do love partial template specialization tricks but I speak from experience that not everyone loves maintaining them.
I always strived to reduce code redundancies in an effort to increase maintainability. In addition I prefer compile-time errors over run-time errors when possible. So after reading Modern C++ by Andrei Alexandrescu I thought I found the answer.
I wrote a component inspired by this book which worked great, then I went on vacation. When I came back the team had thrown out the component and rewrote their own using traditional techniques. It contained more code, was buggier and didn't perform as well however they couldn't figure how to add the functionality to the Component I had written and determined they had to do this. Nothing could be salvaged. These were smart guys too.
Were they wrong to do so? In terms of maintainability I would say they did the correct choice even though it saddens me.
My point with this anecdote is that T4 has some benefits over partial template specialization tricks:
- The generated code from T4 is easy to debug and understand
- T4 is simpler
- T4 is more powerful
- T4 can be executed part of the build-process or on-demand
- If the maintainers can't get their head around the T4 template they can still salvage the code (start maintaining the generated code and throw away the template). That wasn't possible in the anecdote above.
Of course in C++ MetaProgramming is a combination of the PreProcessor and partial template specialization.
Drawbacks
There are drawbacks with T4 of course;
- It is Visual Studio specific (or Mono specific). However the generated code can of course be made to be compilable by GCC and others.
- It is non-standard
- Visual Studio C++ Projects doesn't seem to support T4 which forces me to use a dummy .NET Project to generate the code from.
Wrapping up
All in all I have lost interest doing advanced MetaProgramming C++ using fancy tricks with the PreProcessor or the type system (I do use them for simpler tasks though) and rely on T4 for that these days.
If anyone is interested in a sample on how to do it in C++ you could check out InteractiveGraphics. It's a library for C#, VB, PowerShell and SmallBasic to do simple Graphics in. There I use T4 to generate all APIs and boilerplate code for message passing between .NET and C++ (I don't use C++/CLI if I can avoid it all) from a Model describing the API. Adding a new method is then as simple as extending the model and regenerating all template files, then I implement an abstract method in C++ and do the fun stuff.
It can generate any text you want, including C++ code.