Why no container-based algorithms?

A few minutes ago, a colleague on another team asked:

I really enjoyed your talk on Modern C++ from the Build conference, and have a quick question: Could there be a simpler syntax – something like:

foreach(collection, lambda_function) // or some other syntactic name for “foreach”

which would expand to

for_each(begin(collection), end(collection), lambda_function)

Same for find_if, etc.

This was considered and is desirable. In today’s C++ it’s easy to do for some algorithms, but not others. The main problem is overloading, which needs better template support (i.e., C++0x concepts which were proposed but didn’t make it) and/or adding enable_if.

Briefly, the basic problem is that you already have predicate overloads for some algorithms:

template<typename Iter>
void sort( Iter, Iter ); // 1

template<typename Iter, typename Pred>
void sort( Iter, Iter, Pred ); // 2

So far, so good. But what we want to add is:

template<typename Container>
void sort( Container& ); // 3

template<typename Container, typename Pred>
void sort( Container&, Pred ); // 4

And 4 is difficult to distinguish cleanly from 1 today. Both are match-anything function templates taking two parameters, and 1 would be preferred by the language when the argument types are identical, but in common cases you encounter unfortunate effects. For example, Howard Hinnant points out that if you try to call sort with (say) an iterator and a const_iterator, if we had only 1 you’d get a reasonably clear error message, but now because 4 is able to match different parameter types the compiler will instead try to invoke 4, which isn’t at all close to the original intent, and you’ll get a deeply strange template error message somewhere in the bowels of 4’s implementation because it wasn’t expecting anything like an iterator for either parameter.

Of course, not all algorithms have this issue where there are already overloads with different numbers of parameters. I’m hopeful that the standard library will get range-based overloads of all standard algorithms that are enable_if’d to avoid the problem or can use concepts if those make it into a future standard.

Here’s what the enable_if workaround might look like (I haven’t actually tried this though):

template<typename Iter>
typename enable_if< !CallableWithBeginAndEnd< Iter >::value, void >::type
sort( Iter, Iter ); // 1

template<typename Iter, typename Pred>
void sort( Iter, Iter, Pred ); // 2

template<typename Container>
void sort( Container& ); // 3

template<typename Container, typename Pred>
typename enable_if< CallableWithBeginAndEnd<Container>::value, void >::type
sort( Container&, Pred ); // 4

WordPress.com expertise

I’m generally satisfied with the look and feel of this blog, but would like to tweak it in a few small ways to get a cleaner look, nicer formatting for code examples, and such.

If you or someone you know is familiar with WordPress.com blog customization, and is interested in a small project along these lines, please send me mail. Thanks.

Steve Jobs

Today our industry is much less than it was yesterday. We have lost one of the great innovators. Even more importantly, Steve Jobs’ family has lost a husband and brother and father, and our thoughts are with them.

What can be said that hasn’t been said? Steve has been arguably the single most influential driver and shaper of personal computing in every one of its five decades, from the 1970s to the 2010s. It’s obviously true for the 1970s (Apple, Apple ][) and 1980s (Mac). As for the 1990s, it should be enough that the Mac shaped essentially all of that decade’s desktop and notebook platforms, and icing on the cake that technologies pioneered at NeXT and Pixar so heavily influenced personal gaming and other personal computing. In the 2000s, suffice it to say that Steve put the personal  i  into modern computing and again transformed this industry, and other industries. Looking forward, absent some other world-changing event, it’s clear that the rest of the 2010s will see personal computing develop along the trail he and his teams have blazed already in this decade.

Here is a measure of a man’s impact: Imagine how different — how diminished — the world would be today if Steve had passed away ten years ago.

Makes our hearts fade a little, doesn’t it?

Now imagine how different — how much more — the world would be if Steve had lived another ten years.

Or another twenty. Or another fifty, as though what we have seen were but the first half of his life — and if the second half were not as a slowly aging, diminishing man, but with his health and strength and faculties as strong as ever for that much more time, a true fifty more years.

We are all cut down too soon.

Thanks, Steve.