DevelopKit

New features in C++14 for LHCb Physicists

Overview

Teaching: 20 min
Exercises: 0 min
Questions
  • What can I use from the improvements C++ in 2014?

Objectives
  • Learn a few of the most useful tools in C++14.

Unlike C++11, this is a minor release, focused mostly on improvements on top of C++11 changes, with very little that one could call “new”. C++14 feels a little more natural than C++11 by expanding the usage of features and implementing common sense additions.

The biggest issue with C++14 is the GNU compiler; full C++14 support was released in version 5.0, but due to some binary changes, many projects, including SL6 and Ubuntu, chose to delay moving from version 4.9. This is finally a smaller issue with some fixes in 6.0, but it will take a while for that version to become commonly used. By run 3, hopefully C++14 and even C++17 will be completely available.

Also, while C++11 is available in ROOT 6, C++14 requires a flag and compatible compiler, so C++14 features are often unavailable.

Auto and lambdas

Type syntax is more consistent in C++14, with auto working in more places. You can now write a function returning auto and it will deduce the return type from the return statements instead of having to use the peculiar trailing return type syntax and decltype. This should be used with caution when designing a function for a third party use; you should always present a clear interface, and auto obscures that. This used to work only with lambdas and only if there was a single return statement. A related improvement with lambdas is that they now support auto for parameters; this allows a template lambda functions to be created and reused (called a generic lambda). They have also gained slightly more powerful capture abilities.

Constexpr

This expression has gained quite a bit in C++14; you can now use if, switch, and loops inside a constexpr, as well as variable definitions and mutating local objects. A bit more of the standard library now includes constexpr, as well, such as std::array. Most of the algorithms still do not have constexpr and thus require using a third party library, sadly.

A related change is the addition of variable templates. You can now define a variable with template specializations; for example, you could define pi to provide a double and a string representation all in one variable, depending on how it is used. This could also be used to define a constant variable without being tied to a library.

Smaller changes

The standard library received a few improvements, as well. The C++ literals syntax is finally supported by the standard library. You can now write:

using namespace std::string_literals;
some_string_function("This is a std::string"s + " simply by adding an s at the end"s);

Other standard library types have literals support for units now too, too, such as the chrono library. As an example where a duration is created:

using namespace std::literals::chrono_literals;
auto duration = 1h + 2min + 3s + 4ms + 5us + 6ns;

Complex numbers also gained a set of literals, as well. The literal syntax is entirely a C++11 construct, the new feature is just the addition of the predefined literals to the standard library (albeit in an opt-in namespace). These literals, however, are free from the requirement that a user-defined literal must follow; they do not start with an underscore.

Digit separators, using single quotes, can make large numbers more readable. They are ignored by the compiler and are only visual aids. Binary literals are now available, using a 0b prefix.

An omission of the C++11 standard was fixed with the addition of std::make_unique to mimic std::make_shared for unique smart pointers.

The type system has received minor improvements, with _t type aliases to reduce typing (pun intended), and a std::enable_if_t helper type makes std::enable_if slightly less verbose (if you are stuck in C++11, this is easy to define using the possible implementation).

Bugfixes

Several bugs in C++11 were addressed, as well. Most compilers backport these fixes into C++11 mode, such as GCC4.8/4.9. One example is type overloading with std::function; in C++11, you could not distinguish between different std::function signatures for function or method overloads, but in C++14 and newer C++11 compilers you can.

Futher reading

A few other resources:

Key Points