15

What are the coolest examples of metaprogramming that you've seen in C++?
What are some practical uses of metaprogramming that you've seen in C++?

Marc.2377
  • 7,807
  • 7
  • 51
  • 95
Brian R. Bondy
  • 339,232
  • 124
  • 596
  • 636
  • I think Boost Metaparse is a really amazing thing https://github.com/boostorg/metaparse https://github.com/sabel83/metaparse_tutorial – Jerry Jeremiah Oct 11 '16 at 22:31

10 Answers10

25

Personally, I think Boost.Spirit is a pretty amazing example of meta-programming. It's a complete parser generator that lets you express grammars using C++ syntax.

L. F.
  • 19,445
  • 8
  • 48
  • 82
Ferruccio
  • 98,941
  • 38
  • 226
  • 299
  • 1
    +1: spirit is pretty sick. You might want to link to a newer version of spirit maybe? This version seems a little old. – n1ckp Oct 27 '10 at 01:19
22

The most practical use of meta programming is turning a runtime error into a compile time error.

Example: Lets call the interface IFoo. One of my programs dealt with a COM object that had multiple paths to IFoo (very complicated inheritance hierarchy). Unfortunately the underlying COM object implementation didn't realize they had multiple paths to IFoo. They assumed it was always the left most one. So inside their code, the following pattern was very common

   void SomeMethod(IFoo* pFoo) {
        CFooImpl *p = (CFooImpl)pFoo;
   }

The second IFoo though caused the resulting "p" pointer to be completely invalid (multiple inheritance is dangerous).

The long term solution was to have the COM object owner fix this issue. Short term though I needed to make sure that I always returned the correct IFoo. I could guarantee that I had the appropriate IFoo by using a QI and avoiding any implicit casts to IFoo. So I created a new CComPtr<> implementation and added the following override to the equal method.

template <typename T>
CComPtr<T>& operator=(const T* pT)  { 
// CComPTr Assign logic
}
template <>
CComPtr<IFoo> operator=<IFoo>(const IFoo* pT) {
  COMPILE_ERROR();
}

This quickly revealed every single place I implicitly casted to IFoo.

Head Geek
  • 38,128
  • 22
  • 77
  • 87
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • 1
    QI = QueryInterface http://msdn.microsoft.com/en-us/library/ms682521(VS.85).aspx – JaredPar Oct 26 '08 at 09:42
  • 2
    Is this metaprogramming? Looks like a simple specialization. – fizzer Oct 26 '08 at 09:44
  • 1
    In many ways Metaprogramming is specialization. This is a fairly simple example of meta programming (but very effective). I think it represents one of the more practical aspects of meta programming, keeping you from hurting yourself. – JaredPar Oct 26 '08 at 09:46
  • 8
    I think it's grandiose to call this metaprogramming. I don't see selection, recursion or any other compile time programming constructs. – fizzer Oct 26 '08 at 10:13
  • 2
    This is really smart thinking - awesome! – JBRWilkinson Feb 18 '10 at 14:04
16

Not of practical usage (except maybe for compiler testing), but metatrace is a Whitted-Style (i.e. recursive and deterministic) ray tracer which generates images like those at compilation time:

metatrace example

Some more complex parts of the code can be seen in fixp.hh, which has an implementation of fixed-point sqrt using the Heron method, or sphere.hh which shows ray/sphere-intersection calculation.

Sebastian Mach
  • 38,570
  • 8
  • 95
  • 130
12

Blitz++ does some impressive things with templates (for instance, a single readable line of code can be turned into a set of loops over a multidimensional array, automatically optimized for the best traversal order).

L. F.
  • 19,445
  • 8
  • 48
  • 82
CesarB
  • 43,947
  • 7
  • 63
  • 86
8

Coolest metaprogramming example: tricking the compiler into computing a list of prime numbers. Not very practical, but impressive.

One practical use is compile-time assert statements, i.e. causing a compile error if a Boolean condition does not hold.

John D. Cook
  • 29,517
  • 10
  • 67
  • 94
8

Loki written by Andrei Alexandrescu

4

I would have to say Boost.Lambda, Boost.Function, and Boost.Bind and the way that they all work seamlessly together. They provide a really slick interface and make functional programming about as easy as possible in a language that wasn't really built for it.

user21714
  • 5,781
  • 1
  • 20
  • 26
2

luabind is a pretty cool practical example, quite a nice binding dsl for binding C++ classes to lua

Keith Nicholas
  • 43,549
  • 15
  • 93
  • 156
1

BOOST_FOREACH

Static assertion (boosts version here)

(Note: builtin support for range-based for loops and static assertions is introduced in C++11)

L. F.
  • 19,445
  • 8
  • 48
  • 82
Viktor Sehr
  • 12,825
  • 5
  • 58
  • 90
0

I posed a question not to long ago: C++ Runtime Knowledge of Classes and the answer I got back from a StackOverflow user "Denice" was a URL to a website Meatspace: C++ runtime class registration.

I think that is a really cool way to use templates and instantiate objects that are all derived from a base class, so that when I have 10 C++ files, they can all just add the AUTO_REGISTER_BASE() at the bottom, and when everything is all done and linked, only those classes/files that made it would be registered, so at runtime you can switch between the different classes that are available, and those that are not available are not registered and thus can't accidently be called.

There are many different OS dependant ways to do event notification (select(), kqueue(), /dev/epoll, Solaris has it's own thing, poll()), and I needed a way to have all of the class files exist in the directory, but depending on what OS the Makefile was run, it would only compile certain ones. I needed a way to know at runtime which ones were available, and have a way for the programmer using the library to select their preference, however if it was unavailable to just use the one that made the most logical sense for the platform (they each have weights assigned to them).

The code above helped me accomplish this goal, with some hefty modifications, but it helped me none-the-less!

Community
  • 1
  • 1
X-Istence
  • 16,324
  • 6
  • 57
  • 74