C++11 talk notes

On 2014-11-27 I gave a talk about C++ and new features introduced with C++11: these are the talk notes. See C++11 talk examples for the examples.

(note: I had to add U+2063 INVISIBLE SEPARATOR to prevent noreturn statements to be misinterpreted by the blog formatter. If you copypaste the code and encounter issues, you may want to delete the noreturn statements and retype them)

Overview of programming languages

It has to be as fast as possible, so interpreted languages are out.

You don't want to micro manage memory, so C is out.

You don't want to require programmers to have a degree, so C++ is out.

You want fast startup and not depend on a big runtime, so Java is out.

[...]

(Bram Moolenaar)

C++ secret cultist protip

Do not call up what you cannot put down.

C++ is a compiled language

It is now possible to use the keyword constexpr to mark functions and objects that can be used at compile time:

/*
 * constexpr tells the compiler that a variable or function can be evaluated at
 * compile time.
 *
 * constexpr functions can also be run at run time, if they are called with
 * values not known at compile time.
 *
 * See http://en.cppreference.com/w/cpp/language/constexpr for more nice examples
 *
 * It can be used to avoid using constants in code, and using instead functions
 * for computing hardware bitfields or physical values, without losing in
 * efficiency.
 */

#include <iostream>

using namespace std;

constexpr int factorial(int n)
{
    return n <= 1 ? 1 : (n * factorial(n-1));
}

int main()
{
    cout << "Compile time factorial of 6: " << factorial(6) << endl;

    cout << "Enter a number: ";
    int a;
    cin >> a;

    cout << "Run time factorial of " << a << ": " << factorial(a) << endl;
}

See also this for more nice examples. See this and this for further discussion.

Multiline strings

        const char* code = R"--(
          printf("foo\tbar\n");
          return 0;
        )--";

See this.

C++ memory management protip

RAII: Resource Acquisition Is Instantiation

This is not new in C++11, but in my experience I have rarely seen it mentioned in C++ learning material, and it does make a huge difference in my code.

See this and this for details.

Constructors and member initializer lists

Initializers in curly braces now have their own type: std::initializer_list:

#include <string>
#include <iostream>
#include <unordered_set>

using namespace std;

// std::initializer_list<…>
//   will have as its value all the elements inside the curly braces

string join(initializer_list<string> strings)
{
    string res;
    for (auto str: strings)
    {
        if (!res.empty())
            res += ", ";
        res += str;
    }
    return res;
}

int main()
{
    unordered_set<string> blacklist{ ".", "..", ".git", ".gitignore" };

    cout << join({ "antani", "blinda" }) << endl;
}

See this for details, including the new uniform initialization trick of omitting parentesis in constructors so that you can call normal constructors and initializer_list constructors with the same syntax, which looks like an interesting thing when writing generic code in templates.

Type inference

I can now use auto instead of a type to let the compiler automatically compute the value of something I assign to:

        auto i = 3 + 2;

        // See also https://github.com/esseks/monicelli
        vector<string> names{ "antani", "blinda", "supercazzola" };
        for (auto i = names.cbegin(); i != names.cend(); ++i)
            cout << i;

        template<typename T>
        T frobble(const T& stuff)
        {
             // This will work whatever type is returned by stuff.read()
             auto i = stuff.read();
             // …
        }

See this for more details.

Range-based for loop

C++ now has an equivalent of the various foreach constructs found in several interpreted languages!

        for (auto i: list_of_stuff)
                cout << i << endl;

        for (auto n: {0,1,2,3,4,5})
                cout << n << endl;

        // This construct:
        for (auto i: stuff)

        // If stuff is an array, it becomes:
        for (i = stuff, i < stuff + sizeof(stuff) / sizeof(stuff[0]); ++i)

        // If stuff has .begin() and .end() methods it becomes:
        for (i = stuff.begin(); i != stuff.end(); ++i)

        // Otherwise it becomes:
        for (i = begin(stuff); i != end(stuff); ++i)

        // And you can define begin() and end() functions for any type you
        // want, at any time

See this and this for details.

Lambda functions and expressions

Lambdas! Closures!

Something like this:

// JavaScript
var add = function(a, b) { return a + b; }
# Python
add = lambda a, b: a + b

Becomes this:

auto add = [](int a, int b) { return a + b; }

And something like this:

// JavaScript
var a = 0;
$.each([1, 2, 3, 4], function(idx, el) { a += el });

Becomes this:

unsigned a = 0;
std::for_each({ 1, 2, 3, 4 }, [&a](int el) { return a += el; });

See this, this and this.

Tuple types

C++ now has a std::tuple type, that like in Python can be used to implement functions that return multiple values:

        tuple<int, string, vector<string>> parse_stuff()
        {
                return make_tuple(id, name, values);
        }

        string name; vector<string> values;

        // std::ignore can be used to throw away a result
        tie(ignore, name, values) = parse_stuff();

        // std::tie can also be used to do other kind of
        // multi-operations besides assignment:
        return tie(a, b, c) < tie(a1, b1, c1);
        // Is the same as:
        if (a != a1) return a < a1;
        if (b != b1) return b < b1;
        return c < c1;

See here, here and here.

Regular expressions

We now have regular expressions!

        std::regex re(R"((\w+)\s+(\w+))");
        string s("antani blinda");
        smatch res;

        if (regex_match(s, res, re))
            cout << "OK " << res[1] << " -- " << res[2] << endl;

The syntax is ECMAScript by default and can be optionally changed to basic, extended, awk, grep, or egrep.

See here and here.

General-purpose smart pointers

There is std::unique_ptr to code memory ownership explicitly, and std::shared_ptr as a reference counted pointer, and smart pointers can have custom destructors:

    unique_ptr<dirent, std::function<void(void*)>> dirbuf((dirent*)malloc(len), free);

See here and here.

Miscellaneous other cool things

Standard attribute specifiers

string errno_str(int error)
{
    char buf[256];
#if (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && ! _GNU_SOURCE
    strerror_r(errno, buf, 256);
    string res(buf);
#else
    string res(strerror_r(errno, buf, 256));
#endif
    return res;
}

[[noreturn]] void throw_libc_error(int error)
{
    throw runtime_error(errno_str(error));
}

See here.

Hash tables

See here and look at the new containers unordered_set, unordered_map, unordered_multiset, and unordered_multimap.

Multithreading

There is a standard threading model, with quite a bit of library support: see here, here, here, and here for atomic data structures.

Variadic templates

Templates can now take variable number of arguments, and that opens possibilities for interesting code generation, like implementing a generic, type-safe printf statement, or something like this:

db.query(R"(
   INSERT INTO table NAMES (id, name, description)
     VALUES (?, ?, ?)
)", 4, "genio", "fantasia, intuizione, decisione, e velocità di esecuzione");

See here and here.

Essential tools

You need at least g++ 4.8 or clang 3.3 to have full C++11 support. They will be both available in jessie, and for wheezy you can use the nightly clang packages repository. I cannot think of a good excuse not to use -Wall on new code.

scan-build from clang is another nice resource for catching even more potential problems at compile time.

valgrind is a great tool for runtime code analysis: valgrind --tool=memcheck (the default) will check your program for wrong memory accesses and memory leaks. valgrind --tool=callgrind will trace function calls for profiling, to be analyzed with kcachegrind. valgrind --tool=helgrind can check multi-threaded programs for suspicious concurrent memory accesse patterns.

And of course gdb: a nice trick with C++ is to issue catch throw to get a breakpoint at the point where an exception is being thrown. help catch provides a list of other interesting catch examples.

Coredump tips: ulimit -c to enable core dumps, triggering a core dump with ^\, opening a core with gdb program core, and more details on man 5 core.

An extra gdb tip, which is not related to C++ but helped me considerably recently, is that it can be attached to running python programs to get a live Python traceback.