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 that were missed in the original C++11 release. There were also quite a few bug fixes; several of these were backported into C++11 mode in compilers.
Also, while C++11 is always available in ROOT 6, C++14 requires a flag and compatible compiler, so C++14 features are often unavailable. The Conda-Forge ROOT package has C++17 enabled.
Auto and lambdas
Type syntax is more consistent in C++14, with
auto working in more places. You
can now write a function returning
decltype(auto) and it will deduce
the return type from the return statements instead of having to use the peculiar
trailing return type syntax and lots of
decltype work.1 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. However, massive unreadable
return types computed from the arguments could obscure it far more. 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). This will end up being very powerful in C++17 with variants, since the
objects created truly are generic until instantiated. They have also gained
slightly more powerful capture abilities.
This expression has gained quite a bit in C++14; you can now use
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,
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.
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
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
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
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.
A few other resources:
- Official C++14 Overview, C++14 language additions, and C++14 library additions pages
- Dr. Dobbs
- A set of general rules for good C++14
If you use
auto&&, you will explicitly define the result’s value category, just like if you had used this in a variable declaration. If you use
decltype(auto), the value category will be deduced – this is often what you want. ↩︎