Static If I Had a Hammer

Download this episode

Description

All right, the C++11 Standard is done. Can we go home? Definitely not - progress waits for no one.

For all its might, C++11 is not addressing a few basic needs in template programming. For example, you'd hate to have to define a new function or indeed a whole new class wherever you need an "if" statement; yet, this is exactly what we do for template code. Also, conditional overloading using the likes of std::enable_if is syntactically bulky and semantically ham-fisted (as is visible with constructors and other special functions).

This talk describes a new proposal (joint work with Herb Sutter and Walter Bright): a "static if" construct that works much like "if", just during compilation. It's reminiscent of #if, just done copiously right.

With "static if" a lot of generic code becomes radically simpler, which in turn enables idioms that today are too complex to be usable. This proposal for C++ benefits from a large body of experience within the D programming language.

The Discussion

thesaint

Your talks were both great ;). I really hope you get this into the standard as soon as possible! Seems like it is even possible to get C++ back on the rail without a complete redesign, like D. Even though I like the idea of D it will always impose a great barrier from programmers to switch. So it would be great if we could get C++ to be usable again. Your talks are were the fun stuff begins, but unfortunately, with current C++ it was rather annoying, and surely no fun...

I am very interested to see how static if stacks up against the refactored concepts. Maybe there will be a place for both, or even some kind of merger. The static if proposal certainly looks a lot easier, but I can see why if could be seen as a bit of a hack. On the other hand, the concept proposal still strikes me as looking rather too 'academic'.

This all leaves me quite conflicted. My instinct is to trust Bjarne, as ever since originally reading "The Design and Evolution of C++" I have been aware of his very powerful problem solving skills, that really get to the heart of the matter. On the other hand, I deeply sympathise with Andrei's desire to keep things 'simple'.

@Ben Hanson: static if and concepts really do two different things. While Andrei presented many things that overlap with concepts, they're different tools for different jobs. Concepts do two very important jobs.

First, they provide a way to easily tell *exactly* what a type has to do in order to be used in a template. This prevents user code from having to parse through a million errors to figure out what went wrong. Yes, Clang is great in this regard, but it's still verbose over what concepts provide, and look at how much time clang's developers spent on getting those errors tamed. With a proper language feature, it's simple and trivial for compiler writers.

The second job, which `static if` cannot emulate, is verifying that the template *itself* uses the template parameter in the prescribed manor. This is *very important* during the development of a template. If you take a ForwardIterator, but you do -- on it, you've changed what your iterator means all by accident. This is an easy mistake to make and requires a lot of testing to find. Or you use concepts and get it for free.

At the same time, `static if` is much more free-form. It's #define, only it's actually part of the language. There are a lot of things you can do with `static if` that you can't with concepts.

`static if` is like a pencil, while concepts are like paintbrushes. They both can be used to "draw", but they make very different kinds of drawings. If you use pencils to "paint" a painting, you can only get black-and-white. That's better than nothing, but not nearly as good as if you had a paintbrush and a set of paints, is it?

> static if and concepts really do two different things. While Andrei presented> many things that overlap with concepts, they're different tools for different> jobs.

I'm hoping this is the case. Bjarne didn't seem convinced, although to be fair he did say that it all needed thinking through in more detail. As it's early days no doubt the details will be thrashed out over time. The fact that Herb supports static if is also a major plus.

> First, they provide a way to easily tell *exactly* what a type has to do in> order to be used in a template. This prevents user code from having to parse> through a million errors to figure out what went wrong. Yes, Clang is great> in this regard, but it's still verbose over what concepts provide, and look> at how much time clang's developers spent on getting those errors tamed. With> a proper language feature, it's simple and trivial for compiler writers.

Clangs error messages look like another complimentary feature too, as they address code other than templates. Bjarne made the point that concepts aren't just about better error msgs. I of course agree that concepts will help a lot (as did Chandler).

> The second job, which `static if` cannot emulate, is verifying that the> template *itself* uses the template parameter in the prescribed manor. This> is *very important* during the development of a template. If you take a> ForwardIterator, but you do -- on it, you've changed what your iterator means> all by accident. This is an easy mistake to make and requires a lot of> testing to find. Or you use concepts and get it for free.

OK. I have actually experienced the very example you give in my own library!

> At the same time, `static if` is much more free-form. It's #define, only it's> actually part of the language. There are a lot of things you can do with> `static if` that you can't with concepts.

It certainly looks very powerful and of course easy to understand. Bjarne felt it was a bit of a hack! Maybe he'll come round once all the details have been worked through.

Parenthesis are required around the return though. If you forget them, the compile will say something like 'ERROR_PARENTHESIS_MUST_BE_PLACED_AROUND_THE_RETURN_TYPE' is undefined. As a friendly reminder of the parenthesis. The EXCLUDE is useful, because the traits don't have an hierarchy. So if you wanted uninitialized_fill for forward_iterator and random_access_iterator you need to define them like this:

The idea of "static if" is great! We're using the semantics anyway in the ugly form of std::enable_if, therefore what is required is a better syntax (so that people other than the library author may understand what's going on)"static if" is fine as a concept, but syntactically it is an absolute no-go that it abuses the curly brace syntax in a way that does not respect scope.What about something like a non-macro #if, #endif?

I agree that syntax is an abomination, and probably the best suggestion so far is to extend preprocessor #if/else/endif if they refer to the compile-time constants inside templates to be deferred to the time of instantiation. That would cover the existing use and the 'static if'.

Comments closed

Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums, or Contact Us and let us know.