views:

1275

answers:

9

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++?

+6  A: 

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
+14  A: 

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.

Ferruccio
+1: spirit is pretty sick. You might want to link to a newer version of spirit maybe? This version seems a little old.
n1ck
@n1ck: thanks, I updated the link
Ferruccio
+2  A: 

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

Keith Nicholas
+12  A: 

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.

JaredPar
QI = QueryInterface http://msdn.microsoft.com/en-us/library/ms682521(VS.85).aspx
JaredPar
Is this metaprogramming? Looks like a simple specialization.
fizzer
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
I think it's grandiose to call this metaprogramming. I don't see selection, recursion or any other compile time programming constructs.
fizzer
This is really smart thinking - awesome!
JBRWilkinson
+9  A: 

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).

CesarB
+3  A: 

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.

A: 

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!

X-Istence
+5  A: 

Loki written by Andrei Alexandrescu

A: 

BOOST_FOREACH

Static assertion (boosts version here)

Viktor Sehr