Fighting FUD – Introducing C++11 to Legacy Programmers


I’m at the ACCU 2013 conference, and this morning Bjarne Stroustrup held a keynote about C++11. One of his points was that full adoption of C++11 will take some time, due to compilers, libraries etc. lagging behind, but also due to many programmers not wanting to use new things in general. What can you do about it? Bjarne briefly suggested we fight the FUD by starting to introduce the very simplest features that just make everyone’s lives easier. Here is my take on that.

Simple feature #1: Uniform Initilaization

Initializing containers used to be painful. For example, initializing a vector of ints required a long list of push_backs, or something like this:

    int tmp_v[] = {1, 1, 2, 3, 5, 8};
    vector<int> old_v(tmp_v, tmp_v + sizeof(tmp_v) / sizeof(tmp_v[0]));

Now however, we can do this:

    vector<int> new_v = {1, 1, 2, 3, 5, 8};

Even the most hard-core “I don’t need all that new stuff” legacy programmer will appreciate that. Btw, I think this is especially useful in unit tests, where you typically initialize a lot of data manually. (Those legacy programmers probably “don’t need all that new unit testing stuff” either, though.)

This becomes even more important when you have more complex containers:

    vector<pair<int, string>> ints = {{1, "one"}, {2, "two"}};

Simple feature #2: Type deduction

Let’s say we want to print out that vector of pairs from the previous example. This is how you’d do it in C++03:

    for (vector<pair<int, string>>::const_iterator it = ints.begin(); it != ints.end(); ++it)
    {
        cout << it->first << ":" << it->second << " ";
    }

That vector<pair<int,string>>::const_iterator is a bit cumbersome, right? Well, in C++11 we can let the compiler figure out the type for us:

    for (auto it = ints.begin(); it != ints.end(); ++it)
    {
        cout << it->first << ":" << it->second << " ";
    }
    cout << endl;

Note that auto is resolved compile-time, this is not dynamic typing. But we can do even better:

Simple feature #3: Range based for

    for (auto& elm : ints)
    {
        cout << elm.first << ":" << elm.second << " ";
    }
    cout << endl;

This really is as simple as it gets. Notice that the type of elm is no longer an iterator, it is a reference to the element. This means you no longer have to dereference the iterator, and things become even simpler. (Not having to dereference is a bigger issue when the containers store pointers, and you end up doing (*it)->member.)

(Not so?) simple feature #4: Lambdas

The first three features should be fairly simple to convince anyone to use. I would however argue that it should be fairly simple to make an argument for the simplest uses of lambda functions too.

Lets say we want to find an element in that vector<pair>. To do that, we need a predicate function/functor. In C++03, we would need to either do something with std::bind_1st / std::bind_2nd, or write our own predicate like this:

    class CompareString
    {
        public:
            CompareString(string s) : s(s) {}
            bool operator()(const pair<int,string>& p) { return p.second == s; };
        private:
            string s;
    };

    auto it = find_if(ints.begin(), ints.end(), CompareString("two"));

We are not really interested in making that class. All we want is the content of operator(). Wouldn’t it be nice if we could just paste that code directly in the call to find_if? Something like this?

    auto it2 = find_if(ints.begin(), ints.end(),
        bool operator()(const pair<int,string>& p) { return p.second == "two";});    

With lambdas, we can:

    auto it2 = find_if(ints.begin(), ints.end(),
        [](const pair<int,string>& p) { return p.second == "two";});    

For the purpose of this article, [] can be read as “lambda function follows:”. Notice that we don’t even have to specify the return type, as it can be deduced by the compiler.

Conclusion

That’s it! Just a few simple things to start introducing in you code base, to fight the FUD and convince the legacy programmers that C++11 is nice. (And sorry if this blog post feels a bit rushed, I wrote it during lunch at ACCU 2013. Now I’m off to see my friend Mike Long talk about legacy code base restoration projects.)

As usual, the code for this blog post is available on GitHub.

If you enjoyed this post, you can subscribe to my blog, or follow me on Twitter.

Why we should see an uptake in <algorithm> usage


With C++11 out, I think we should see an uptake in use of the good old std <algorithm>. Why?

A common thing to do in a program is to iterate over a container of objects, producing another container of other objects. Imagine for instance you have a vector of domain objects:

struct DomainObject
{
    string label;
};
vector<DomainObject> objects;

Now you want to produce a vector containing the labels of all your domain objects. This is the “classical” solution:

    vector<string> labels(objects.size());
    for (size_t i = 0; i < objects.size(); ++i)
        labels[i] = objects[i].label;


You can however instead use std::transform, which is more declarative, immune to Off-by-one errors, possibly more optimization friendly etc. This is how it looks:

    vector<string> labels(objects.size());
    transform(objects.begin(), objects.end(), labels.begin(), label_for);


The problem is however that you need a function / function object to provide as the last argument to transform. Here is the one I used:

string label_for(const DomainObject& obj)
{
    return obj.label;
}


This reduces locality, and makes the code harder to read. Unless the helper is sufficiently advanced that you would want to either reuse it a lot or test it, it would be better to be able to write it directly in the transform call. This is exactly what C++11 lambdas are good for, and where I’ll think we’ll see them used a lot:

    vector<string> labels(objects.size());
    transform(objects.begin(), objects.end(), labels.begin(), [](const DomainObject& o){return o.label;});


This isn’t a complete introduction to lambdas, but if you haven’t seen them before, here is a quick intro. Lambdas are just a fancy name for functions without a name. That means you can simply type them in directly where you’d normally call a function. [] means “anonymous function follows” (at least for the purposes of this article), and then you just type out any normal function body. Mine takes a reference to a DomainObject and returns its label, just like label_for() did.

Here is another example, using std::find_if to look for a specific element in a container:

    auto matched = find_if(objects.begin(), objects.end(), [](const DomainObject& o) { return o.label == "two"; });
    cout << matched->label << endl;


Notice the use of auto, another C++11 feature. It uses type inference to deduce the type of the variable by looking at the rest of the expression. Here it understands that you will be getting a vector<DomainObject>::iterator from find_if(), so there is no need for you to type that out.

As usual, the code for this blog post is available on GitHub.

If you enjoyed this post, you can subscribe to my blog, or follow me on Twitter.

The Minesweeper Kata in 15 lines of C++


In which I solve the Minesweeper Kata using c++0x lambdas and a little thinking outside the box (literally).

A few days ago I went to see Prepared Katas at Communities in Action, in which four guys solved minesweeper in Ruby, Perl, Java and Javascript. They had just 20 minutes to code and test, which is short even for a prepared kata. They all looked pretty stressed out, except for the Perl guy who looked smug. But that’s how they always look, isn’t it?

Anyway, I thought I’d try the kata in C++, and see if I could golf it a bit without sacrificing readability too much. I ended up solving it in 15 12 lines, expanded a bit here for readability.

I use two tricks that I should mention before I show you the code:

The first is to expand the board by one in each direction. That is, if the board is 3×3, I allocate a 5×5 scratch board. In this way, each cell can check all it’s neighbours without special handling of the edge cases.

The second trick is not really a trick, but I should mention it anyway, since most C++ developers won’t be familiar with it. I am using C++0x lambda functions, which work nicely with the normal stl algorithms.

But let’s get to the point, here’s the code:

vector<string> solve(vector<string> board) {
	int rows = board.size();
	int cols = board[0].size();
	char* big_board = static_cast<char*>(calloc((rows+2)*(cols+2), sizeof(char))); //Supersized board

	for (int r = 0; r < rows; ++r)  //Put 1 in each mine-cell
		transform(board[r].begin(), board[r].end(), &big_board[(r+1)*(cols+2)+1],
			[](char c) {return (c == '*');});

	vector<string> solution(rows);
	for (int r = 0; r < rows; ++r)  //Calculate solution
		transform(&big_board[(r+1)*(cols+2)+1], &big_board[(r+1)*(cols+2)+cols+1], back_inserter(solution[r]),
			[=](char&c){ return (c ? '*' : '0'
				+ *(&c-cols-3) + *(&c-cols-2) + *(&c-cols-1) //Previous row
				+ *(&c-1) + *(&c+1) //This row
				+ *(&c+cols+1) + *(&c+cols+2) + *(&c+cols+3));}); //Next row
	free(big_board);
	return solution;
}

Update 10 April: Thanks Mike Long for golfing off another line using calloc instead of new and fill, and having me fix the memory leak.

You need G++ 4.5 to compile this (sudo apt-get install g++-4.5). Compile with g++-4.5 -std=c++0x

I also uploaded a tarball with the full code, including unittests and a make-script, here.

If you enjoyed this post, you can subscribe to my blog, or follow me on Twitter.