Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alternatives to C++ templates?

I think meta programming is very very cool. In particular, I love lisp macros.

However, I think C++ template suck because:
1. they slow down compile time (even with precompiled headers that end up being 50MB big if you include any of he STL stuff).
2. they give terrible compiler/syntax errors that are counintuitive
3. they weren't desinged for complicated meta programming in the first place (generating comipler errors for prime numbers / showing templates are turing complete was a big deal back in the day).

Having said all that, is there a decent alternative for C++ meta programming? something like

*.m -> meta compiler -> *.cpp -> g++ -> executable ?

EDIT:

I'm thikning along the lines of "custom code generations scripts." I'm just wondering if there's a really good set of them out there.

like image 915
anon Avatar asked Jan 28 '10 01:01

anon


3 Answers

I am not sure this is what should want, I have used code generators to produce C++ code. In particular, python cheetah. You basically embed straight python code inside your C++ code and run through cheetah preprocessor.it allows to do pretty complex computations much easier than using templates or C++ preprocessor, plus you get all python libraries and extensions. on the other hand it makes debugging harder if something goes wrong.if you are interested I could provide some examples and Emacs mode for editing cheetah C++ programs.

If you need something less powerful and want to stay within C++ C only, take a look at boost preprocessor, here. It takes a bit of time to get used to it, but could make life really easy when the repetitive code is involved

okay, I am pasting cheetah example, give me a few minutes:

#if defined (__INTEL_COMPILER)
#pragma vector aligned
#endif
        for(int a = 0; a < $N; ++a) {
            /// for functions in block
%for ii, (fi,fj) in enumerate(fb)
%set i = ii + ifb
/// can also use (ix,iy,iz)=fi[0:2], need to clean up when not lazy
%set ix = fi[0]
%set iy = fi[1]
%set iz = fi[2]
%set jx = fj[0]
%set jy = fj[1]
%set jz = fj[2]
            q$(i) += Ix(a,$(ix),$(jx))*Iy(a,$(iy),$(jy))*Iz(a,$(iz),$(jz));
%end for
            /// end for functions in block
        }

produces (after running cheetah ...)

#if defined (__INTEL_COMPILER)
#pragma vector aligned
#endif
        for(int a = 0; a < 6; ++a) {
            q0 += Ix(a,0,1)*Iy(a,0,0)*Iz(a,0,0);
            q1 += Ix(a,1,1)*Iy(a,0,0)*Iz(a,0,0);
            q2 += Ix(a,0,1)*Iy(a,1,0)*Iz(a,0,0);
            q3 += Ix(a,0,1)*Iy(a,0,0)*Iz(a,1,0);
            q4 += Ix(a,0,0)*Iy(a,0,1)*Iz(a,0,0);
            q5 += Ix(a,1,0)*Iy(a,0,1)*Iz(a,0,0);
            q6 += Ix(a,0,0)*Iy(a,1,1)*Iz(a,0,0);
            q7 += Ix(a,0,0)*Iy(a,0,1)*Iz(a,1,0);
            q8 += Ix(a,0,0)*Iy(a,0,0)*Iz(a,0,1);
            q9 += Ix(a,1,0)*Iy(a,0,0)*Iz(a,0,1);
        }

which is a regular C++ code

lines starting with % are interpreted as python statements by cheetah preprocessor. /// are cheetah comments. Defaults use # as python statements, but I changed them to avoid collision with C preprocessor directives. %end must be used to terminate python blocks. Variables in C++ code which start with $ are replaced by python variables.

Do you want examples using boost preprocessor?

like image 102
Anycorn Avatar answered Sep 21 '22 01:09

Anycorn


Most people insist on trying to metaprogram from inside their favorite language. C++ is held up as the quintessential example because of template metaprogramming. While it works, it is painful and clumsy. I find it telling the people figured out it was Turing-capable, after Stroustrop added it to the language; I don't think even he expected it to turn out quite the way he did, although I doubt he'd complain about it now.

But most programming languages don't have metaprogramming facilities. (Or they may have weak or clumsy capabilities :)

A way around this is to do metaprogramming from outside the language, using program transformation tools. Such tools can parse source code, and carry out arbitrary transformations on it (that's what metaprogramming does anyway) and then spit the revised program.

If you have a general purpose program transformation system, that can parse arbitrary languages, you can then do metaprogramming on/with whatever language you like. See our DMS Software Reengineering Toolkit for such a tool, that have robust front ends for C, C++ (even C++17), Java, C#, COBOL, PHP and a number of other programming languages, and has been used for metaprogramming on all of these.

This approach is useful because it provides a regular, methodological approach to providing metaprogramming methods for whatever language you'd like to manipulate. And you don't have to wait for the language designers and implementers to implement, nor do you have to live with the limitations of what they can imagine or actually implemented, or pay the runtime space/time price of all that reflective data it takes to support it.

And program transformation is more powerful than C++ template metaprogramming, despite TM being Turing capable! The reason is that TM can generate arbitrary code from the templates, but cannot modify the non-template code. Program transformations can simulate TM if you insist, and so is at least as strong, but it can also carry out arbitrary changes to the non template code. Thus, strictly more powerful.

Like TM, using program transformations takes some effort to learn and apply. But being able to manipulate programs in arbitrary ways seems pretty useful.

(We've done architectural reengineering of very large C++ applications using DMS. TM simply can't do this).

like image 27
Ira Baxter Avatar answered Sep 19 '22 01:09

Ira Baxter


Code generation is the best answer...

You should also look at how the Linux kernel does linked lists.

Linux Kernel Linked List Explained

The basic idea is that instead of having your type embedded in some struct (say with next and prev pointers, for a typical list implementation), you have the kernel list struct embedded in YOUR struct... Kind of mind bending, but check out the article... I never thought type safe generics were possible in C until I saw this....

like image 27
dicroce Avatar answered Sep 18 '22 01:09

dicroce