Journal

2011-09-15 CPlusPlus0X

More on Lambdas

As we saw in the example with computing the sum we could in the lambda bind a variable from the defining scope. This is also known as a closure. The functions is closed over its free variables. That is great, it has fancy name, can we look at more ways how to use it?

One new aspect is if we look at capture by value. In the sum example we bound sum by reference so we could update it inside the lambda. If we want the value at the creation time of the lambda we capture by value instead. It looks like this:

[var] (... // capture variable var by value
[=] (...   // capture all variables by value
int divBy = 2;
auto divBy2 = [divBy] (int x) { return x / divBy; };

divBy = 4;
auto divBy4 = [divBy] (int x) { return x / divBy; };

assert(4 == divBy2(8));
assert(2 == divBy4(8));

Yes, the first lambda divides by 2 and the second by 4. All because divBy is captured by value when we defined the lambda.

To go further, we can even bind this. So accessing and calling members from a lambda expression is possible. Let us define a class (using a struct to make the example less verbose)

struct Name 
{
   string name;
   void me() { cout << "I'm: " << name << endl; }
   function<void()> callMe() { return [&]() { me(); }; }
};

The first function member me is easy to understand. It prints the name of the object.

The second member callMe requires some explanation. First it introduces std::function. Let us settle for now that it declares a callable type taking no parameters and returning void. The lambda itself binds all members by reference and calls the member me.

Using it can look like this:

Name al {"Al"};
auto gl = al.callMe();
gl();    // Prints "I'm: Al"

This is like a function object but created with less typing.

2011-09-07 CPlusPlus0X

Lambda expressions

For defining small functions at the very spot they are used C++ introduces lambda expressions. A lambda expression is like a short function that can be used where a normal function would be called. Here is an example of a predicate functions that returns true for odd numbers:

[](int x) { return x % 2 == 1; }

This specifies a lambda expression taking one int parameter. The return type is defined by the type of the return statement. Yet a place where compact notation has been chosen. It can be put to use in a count_if algorithm like this:

list<int> numbers {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int numberOfOdd = count_if(numbers.begin(), numbers.end(), [](int x) { return x % 2 == 1; });

No need to define a local predicate functions. The lambda expression can be used right in place.

But there is more. We just saw that a lambda can take arguments but it can also bind to variables in the scope of its creation like this:

int sum = 0;
for_each(numbers.begin(), numbers.end(), [&sum](int x) { sum += x; });

The variable sum is available in the lambda and it is accessed by reference. The [&sum] notation in the beginning of the lambda expression defines this binding.

In the next posting we'll look more into the closure aspects of lambdas.

2011-07-31 CPlusPlus0X

Range based for loops

Looping over containers is a very common task so it should be easy two write and easy to read. In C++ is was even worse than in many other languages due to the verbose code for treating iterators. We have seen that the new meaning for the auto keyword has resolved that to some extent. But it gets better.

The new construct for range based for loops makes it even easier. For example: To loop over a list of ints we can write it like this:

list<int> numbers {1, 2, 3, 4, 5};

for (int& i : numbers)
{
   i += 2;
}

This will loop over the list and increment each item by two. Note the very compact and clear notation.

auto works too so you could even write the loop like this:

for (auto & i : numbers)
{
   i += 2;
}

2011-06-28 CPlusPlus0X

Taking initialization one step further - Uniform Initialization

Initializing containers is fine but what about structs or classes. Well in good old C++ some initialization was possible using the brace notation. In C++2011 that is taken further by making the initialization uniform and work on any object. So if you have a class with a constructor

class Person
{
public:
  Person(const string & name, int age)
  : name_{name}, age_{age} {};
...
private:
  string name_;
  int age_;
};

you can initialize it like this:

Person me{"No Name", 50};

The same syntax as for a vector or a list but this time for class with a constructor taking two arguments, a string and an int. This works for structs with no constructor as well just initializing each member as you would expect.

You can even do this. Note how the return statement just contains the initialization of the Person type.

Person getPerson()
{
  return {"Foo Bar", 42};
}

2011-06-27 CPlusPlus0X

Initializer lists

How many times have you not wanted to easily initialize a container with a list of values. Instead you would have to solve that with repeated push_backs either inline or in a loop over a good old C array that could be initialized with the brace notation. C++2011 now fixes this by introducing the initializer_list-template.

It works like this. Constructors and a other functions can take a parameter of type std::intitializer_list:

void function(initializer_list<string> list) 
{ 
   cout << "Number of args are " << list.size() << endl; 
   for (auto it = list.begin(); it != list.end(); ++it) 
   { 
      cout << "List contains: " << (*it) << endl; 
   } 
} 

You can call function like this:

   function({"hi", "ho", "foo", "bar"});

The standard library classes implements this so we can now initialize a vector of strings with either of these ways:

   vector<string> v1 = {"hi", "ho", "foo", "bar"}; 
   vector<string> v2 {"hi", "ho", "foo", "bar"}; 

So this adds yet another feature that makes C++ just a little more convenient to use, easier on the typing and makes the code cleaner and easier to understand.

2011-06-17 CPlusPlus0X

More on type inference

Together with auto there is a new keyword decltype. It is used to determine the type of an expression in compile time. You can do like this:

auto var1 = 3.14;
decltype(var1) var2;

var2 will get the same type as var1. Who in it its turn got its type from the initialization with 3.14 and so they are both doubles.

Right now it might not be entirely obvious what this is good for, and it is probably of most use for library developers, but now you have seen it anyway.

2010-11-19 CPlusPlus0X

OOPS! Other stuff came along and I have had to stop with learning more about the new features in C++. I'll try to plan for doing this so that it actually will happen. Stay tuned.

2010-08-06 CPlusPlus0X

As it happens I have had a long vacation and done other stuff than thinking about the new standard. That is probably a good thing. Soon there is time for work and hopefully I will get some time then to come back to these matters.

2010-06-19 CPlusPlus0X

Auto is dead, long live auto

The keyword auto will get a new meaning. The old meaning is something you might not remember because in practice it was used very little. This was because it was the default so it could be left out and it normally was.

The new meaning is of more interest. Auto means that the type of a variable is deduced from its initializer expression. This can be as simple as

auto i = 1;

where the type of i will be int.

Of more practical use is when the initializer expression is more complex. Take for example the initialization of the loop variable in a for loop when traversing a standard library container. The loop variable takes the type of an iterator over the container. That was hard to write before but can now be written like this:

for (auto it = l.begin(); it != l.end(); ++it)
{
...;
}

2010-06-18 CPlusPlus0X

Getting a tool chain to experiment with

To experiment with the new C++ features it is good to have a tool chain so that you can see whether your code is OK. It is fun to write code but it is even better when you can run it!

Fortunately we have gcc. Unfortunately the support for the upcoming standard isn't in the stable releases. It wouldn't be an upcoming standard if it was I guess. So we need to get a development version. That isn't so hard to do (if you are on a linux/unix system that is)

The gcc development version can be downloaded. It is under version control using subversion. So it can be checked out. This way it is easy to update when the developers off gcc adds new features. Check it out like this:

svn checkout svn://gcc.gnu.org/svn/gcc/trunk <your-working-dir>

After that it is actually just a matter of running configure and make. I choose to set the prefix to my $HOME so that it would not mess with stable release of gcc I use for normal work. This installation is just for trying out the new features. So cd to your <your-working-dir> and follow the install instructions there. Configuring the build should be as easy as creating a build directory and doing

../configure --prefix=$HOME --enable-languages=c++

and building it should need no more than...

make
make install

should do it. gcc is then available in $HOME/bin. Voilá, we are read for trying out some code. Just one last thing to look out for. The new features are not activated by default in the beta version of gcc. So in order to use them we need to explicitly tell the compiler we want the new features. You can do like this:

$HOME/bin/gcc -static -std=c++0x

I have added the flag -static there as well to get statically linked executables. This way we avoid having to bother about dynamic linkage when running the programs. Remember we are using a version of gcc where the libraries are not installed in the standard location.