Notes of talk: C++ in the 21st century

I recently came across a 2014 talk by Arvid Norberg about the new features in C++11. The video is here and slides are here.

C++ is huge and getting bigger every day. So, I keep discovering interesting new features that I like to note down for use in my own code. Below are my notes from this talk. I do not note aspects that I already know well. This talk has examples that are small but illustrative, so if you hit any of these features, you should see the video to look at the examples.

For loops

  • std::begin and std::end work on C arrays too. Note that this is only when the array size is known. So, the array must have been created in the same local scope.

decltype

  • decltype deduces the type of an expression. So its use is in type expressions. For example, as template arguments.
// vector of the return type of function f
std::vector<decltype(f())> vals;
  • Internally, it is used by auto to deduce type of expression

lambda functions

  • Lambda expression yields an unnamed function object. The tiny examples in the talk are good.

override

  • This is to help programmers find errors. For example, when virtual method in base class is not const and in derived it is. Programmer might miss this error. If virtual method in derived class is declared override and it is actually not, compiler will complain.

unique_ptr

  • This smart pointer is not copyable, but movable. It is deleted when pointer goes out of scope.
  • Many functions create a heap-allocated object and return it. Traditionally, programmers had to worry about the ownership and lifetime of such a returned object. Return it as unique_ptr and forget about these worries.
  • Also great for storing such heap-allocated objects in containers.

error_code

This C++11 feature was something new to me! I did not understand how to apply it either. I might need to study this in future.

  • error_code represents an error. It has error_value integral value indicating what is the error. It has category indicating domain of error value.
  • category is an abstract base class implementing conversion of error_value to human readable message.

chrono

  • There are a whole bunch of old C, C++, Unix and POSIX time functions. They are not platform agnostic, have low time resolutions, have no type safety (milliseconds value can be passed to a function that takes in microseconds and so on) and are not monotonic. Monotonic in this context means that if you measure a time before DST is turned on and after it, the latter value should always be larger, though the wall clock may have been turned back by DST.
  • Chrono introduces a clock with its own epoch (start of life) and its own resolution.
  • time_point: A point in time relative to epoch. It has its resolution encoded inside it.
  • time_duration: Difference of two time points. It has its resolution encoded inside it.
  • Because these types have their resolutions embedded inside, two durations of different resolutions can be added together to produce a duration that has resolution that is highest or higher than both. They can be passed to function that accepts in a different resolution. The template machinery ensures that it all converts correctly.

How to change compiler options used by indexer in Eclipse CDT

Eclipse CDT understands the C++ code in a window by running it through an indexer. This indexer is nothing but an invocation of the GCC C++ compiler with certain compilation options. Sometimes, you might want to change the compiler options used by this indexer.

For example, I recently found that C++11 containers and classes (like future) were not resolved by the indexer and were underlined with red squiggles. This is because the compiler options used by the indexer does not have -std=c++11.

To change the compiler options of the indexer:

  1. Open Preferences and go to C/C++ -> Build -> Settings.
  2. Click the Discovery tab and choose CDT GCC Built-in Compiler Settings.
  3. Modify the command string shown below it as you wish. For example, here I added -std=c++11.
  4. Eclipse CDT will automatically re-index your C++ files after this is saved. However, I found that this did not remove the unresolved items.
  5. I manually re-indexed by right-clicking the project and choosing Index -> Rebuild. This worked!

Tried with: Eclipse 4.5 (Mars) and Ubuntu 14.04

How to lock using mutex in C++

Launching asynchronous threads is super easy in C++11 as described here. Once you have multi-threading, you might also need locking to handle concurrent access to shared data. Thankfully, locking using mutex is also super easy in C++11!

  • A std::mutex object is required to act as the mutex.

  • The simplest way to lock a section of code is to create a std::lock_guard object. It takes a mutex as input. This not only creates the lock object but starts the locked section of the code.

  • At the end of the scope of the std::lock_guard object, it is unlocked and destroyed. This is thanks due to the RAII design of the lock.

Using these constructs, we can now handle concurrent access to a queue from multiple threads for both adding and removing items from it:

class SharedQueue
{
public:
    SharedQueue() {}

    void Put(const Foo* item)
    {
        std::lock_guard<std::mutex> lock(mutex_); // Locking begins

        // Code for adding to queue goes here

        // Code is unlocked at end of the scope of lock_guard object
    }

    const Foo* Get()
    {
        std::lock_guard<std::mutex> lock(mutex_); // Locking begins

        // Code for removing from queue goes here

        // Code is unlocked at end of the scope of lock_guard object
    }

private:
    std::mutex mutex_; // Mutex object used for [un]locking this queue
};

Constructor delegation in C++11

C++11 added a feature that I personally find extremely useful. It is called constructor delegation. It is a natural addition to the language to reduce duplicated code in constructors of different signatures in a class. It can be understood easily with an example.

Consider a class with two constructors:

class Point
{
public:
    Point()
    {
        x_ = 0;
        y_ = 0;
        z_ = 0;
    }

    Point(int z)
    {
        x_ = 0;
        y_ = 0;
        z_ = z; // Only update z
    }

private:
    int x_;
    int y_;
    int z_;
};

How to avoid the duplicated initialization statements in both constructors? You should not call one constructor in the other constructor of the same class! That is a very common bug in C++, since that only creates a temporary object and does not actually call the constructor of the same object.

The common solution to this is to create an init function that is called from both constructors:

class Point
{
public:
    Point()
    {
        Init();
    }

    Point(int z)
    {
        Init();
        z_ = z; // Only update z
    }

private:
    void Init()
    {
        x_ = 0;
        y_ = 0;
        z_ = 0;
    }

    int x_;
    int y_;
    int z_;
};

C++11 constructor delegation provides an elegant solution that should have been there in C++ since the beginning: you can call a constructor by placing it in the initializer list of constructors. The above code with constructor delegation:

class Point
{
public:
    Point()
    {
        x_ = 0;
        y_ = 0;
        z_ = 0;
    }

    Point(int z) : Point()
    {
        z_ = z; // Only update z
    }

private:
    int x_;
    int y_;
    int z_;
};

If you are going to use constructor delegation, please remember to use a compiler version that supports it (I used GCC 5.1.0) and you may need to specify a C++11 flag (I used -std=c++11).

Reference: Sec 17.4.3 Delegating Constructors from The C++ Programming Language (4th Ed) by Stroustrup

How to set C++ compiler options for Syntastic

To learn how to install and use Syntastic, please see this post.

Syntastic should be able to detect the C++ compiler on your system and use it for syntax checking automatically. If you need to change it or set it explicitly, then add its command or full path to your .vimrc:

let g:syntastic_cpp_compiler = "g++"

You might want to enable some compiler options for Syntastic to apply on your code. For example, I like to add support for C++11 and also rigorously check for warnings, so I add this to my .vimrc:

let g:syntastic_cpp_compiler_options = "-std=c++11 -Wall -Wextra -Wpedantic"

Tried with: GCC 4.9.2, Vim 7.4 and Ubuntu 14.04

How to use emplace operations of C++11

C++11 introduced emplace operations on many of the STL containers. For example, vector now has emplace_back operation along with the old push_back operation.

Emplace operation is provided for convenience, to make writing code in C++ a bit more easier. It should be used when you want to add an object by constructing at the point of calling the emplace operation. For example, you may want to construct the object using its default constructor and then push it into the container. Or you may want to construct it using some parameters on the spot. The older alternative for this involved the construction of a temporary object and then copying it into the container.

The code below shows a simple example of these scenarios: