This article explains how to define and use metafunctions, the compile-time equivalent of functions, and introduces the Boost Metaprogramming Library.
The ability to add new comments in this discussion is temporarily disabled.
Most recent reply: October 13, 2004 7:27 AM by
This article investigates the use of metafunctions in template metaprogramming, and introduces the Boost Metaprogramming Library. It is an excerpt from the upcoming book, "C++ Template Metaprogramming", by David Abrahams and Aleksey Gurtovoy.http://artima.com/cppsource/metafunctions.html
This is a very good article but took a couple of reads before I really understood what was going on. It seems the C++ template mechanism is more poerful than anyone ever thought which is probably an indication of good design. However, it does seem to require a lot of 'tricks' to get it up and running these tend to stem from syntax problems in my experience at least. I suspect that many people will be put off from using these techniques in a general way which is a shame.
Does anyone know of a language that has a familiar feeling of C++ but integrated something like templates earlier on so that the syntax is clearer and ideas can be expressed more cleanly. I'm trying to construct one myself and would like to see what experience other people have had.
> Does anyone know of a language that has a familiar feeling
> of C++ but integrated something like templates earlier on
> so that the syntax is clearer and ideas can be expressed
> more cleanly.
You may be interested in Heron:http://www.heron-language.com/
Unlike C++, it has built-in support for metaprogramming. Be aware that this language is in a pretty early stage of development, though.
I've taken a look but as there is no doucmentation it's a bit hard to decipher. It looks like it has some nice ideas but one thing I've noticed while using templates heavily in C++ is that I regulary have to specify types when I know the compiler can deduce them. It seems constructing a language that used the compilers ability to infer types as in a say a functional language might add great flexibility without losing an of the safety.
add( a, b )
return a + b;
template< class S, class T >
AddResult<S,T>::type add( S a, T b )
return a + b;
} //for some suitable class AddResult
I really would like a C++ style language that allowed this and I know others would too having read many articles on such things. I just wondered if anyone had decided to go down this route.
I have actually just posted the metaprogramming documentation online at http://www.heron-language.com/metaprogramming.html
. The language is very young, but the Heron2C compiler successfully compiles the source to a compile time program which outputs prime numbers. The source can be found to the prime number program at http://www.heron-forums.com/viewtopic.php?t=21
Concerning Pete's post, interfaces in Heron which aren't yet neither implemented nor documented for Heron (well they were with an old version, but I have been rewriting things from the ground up lately) will provide a way to have a certain amount of type inference, but perhaps not as much as he wants.
I don't really want to encourage an in-depth discussion of Heron here, and I'd like to steer things back towards the article or at least towards metaprogramming in general. That said, some remarks on Heron's metaprogramming:
1. I for one am flattered that Christopher's work was inspired by MPL.
2. One of the drawbacks of many proposed in-language metaprogramming systems is that they impose limitations that don't apply to the runtime part of the language. Template metaprogramming may work that way, but using a different syntax and limited semantics doesn't seem to provide any real advantage. I don't see any reason that all
of the language's capabilities shouldn't be available at compile-time. There's precedent for what I'm describing in Forth and I think also in Scheme.
The OP might want to read about metacode: http://www.vandevoorde.com/Daveed/News/Archives/000014.html
for more examples of language-based metaprogramming support.
You should be flattered David, I hold your work in very high regard.
Making an entire language available at compile time is difficult for a compiled multi-paradigm language like Heron or C++. What do you do about functions that depend on command line arguments or user input? What about user defined casts and operator overloads? What about floats, which because that are system dependant will compile differently on different compilers? Either you don't make them available at run-time or you have some kind of default behaviour in these conditions, which is essentially the same as separating semantics. Even the article on meta-code you link to, the semantics are not the same as C++, just similar. I like to keep things explicit, if there are two sets of rules, one for compile time and one for run-time, you might as well make it very clear.
> You should be flattered David, I hold your work in very
> high regard.
> Making an entire language available at compile time is
> difficult for a compiled multi-paradigm language like
> Heron or C++. What do you do about functions that depend
> on command line arguments or user input?
The usual. If there's no way to get at argc and argv outside of main, metafunctions can't touch them. If the metafunction depends on user input, it waits for user input, as usual. I don't see a problem there.
> What about user
> defined casts and operator overloads?
What about them?
> What about floats,
> which because that are system dependant will compile
> differently on different compilers?
> Either you don't make
> them available at run-time or you have some kind of
> default behaviour in these conditions
No, you just have non-portable results.
This is no great mystery and it presents no serious problems; it's been done before in other languages.
> , which is
> essentially the same as separating semantics. Even the
> article on meta-code you link to, the semantics are not
> the same as C++, just similar.
I know that. It's one of the limitations of metacode that I dislike.
> I like to keep things
> explicit, if there are two sets of rules, one for compile
> time and one for run-time, you might as well make it very
Yes, but you don't need two sets of rules. Simple is better than explicit and complex.
I can't come up with a good counter argument! I thought that there were some circular catch-22's that would arise if we tried to have meta-programming using the language itself, but I haven't found any scenarios that are particularly difficult to resolve.
The only challenge I see is in implementing the compiler. It seems to me that it would be neccessary in the case of either C++ or Heron, having complete metaprogramming support would imply an interpreter embedded in the compiler. Does this sound correct to you? Can you think of any possible drawbacks to providing all language facilities at compile-time in a language that I should be wary of?
I have identified a potential problem with full metaprogramming support:
Some code's behaviour depends on global variables which are set by the main function ( directly or indirectly ). So we have to execute every program from the beginning (with argc
and argv and all). Either we disallow metacode which depends on the main thread of execution, or we don't.
Assuming we disallow the metacode to depend on the main we run into problems when type-casts or constructors have dependencies on global variables which are set by main thread of execution. Some very basic code (in the case of Heron Int+Int) could become unavailable.
Just to show that this is not entirely theoretical, a real world example, would be a scientific calulator that allows the user to set the arithmetic underflow and overflow behaviour at run-time.
The other option then is to allow dependencies on global variables and main. This means that the program needs to be run each time during compilation. This would confuse programmers because they need to run a program at compile-time in order to compile a run-time version, with the run-time version behaving differently depending on the input given to the compile-time version.
I don't see a nice way out of this problem other than making a language always interpreted.