08 May 2014

Constification in C++11

Here’s a neat little pattern. Suppose you want to initialise some object using mutating operations, and thereafter make the object const, without any overhead. In C++11 you can do just that with a lambda:

const auto v = []{
  vector<int> v;
  for (auto i = 0; i < 10; ++i)
    v.push_back(i * 10);
  return v;
}();

This “inline builder pattern” turns out to be a nice way to encapsulate mutation to smaller scope, thereby making your code a bit easier to reason about. Of course, the drawback of this is that objects you would initialise this way are the sorts of objects you might prefer to move rather than copy, and const interferes with that; but that is a problem in C++11 generally.

It goes to show that lambdas make working with const things a bit nicer all around. This pattern also lets you initialise const members in an object:

struct X {
  X()
    : x([]{
      auto s = 0;
      auto i = 10;
      while (i) s += --i;
      return s;
    }())
    {}
  const int x;
};

Ugly, but it gets the job done. That’s C++ for you.

1 comment:

  1. Of course, you can also use `const_cast` which will let you move something in, and which exists exactly for these kinds of situations.

    As for your second example: Writing the 'ugly' inline code in a separate function and calling that one from your constructor makes it less 'ugly'.

    ReplyDelete