Modern C++ Features (C++11, C++14, C++17)

As posted in C++ Then and Now, Modern C++11 feels like a new language. There are plenty of resources online which explain Modern C++ features. This is different in how it is organized. It’s a list that you can approach and adopt/learn incrementally without getting overwhelmed by the large set of new features.

The descriptions are intentionally short to keep the features as an easily accessible list. Much of the details can be easily found online. References are listed besides some features and the full list is in the references section at the bottom.

Deprecated
Language
Library
References

Modern C++ and C++11 are used interchangeably. Both refer to the standards published in C++11, C++14 and C++17. It does not (yet) include the C++20 draft.

Deprecated

C++11 is backward compatible, except for a minor set of deprecated features which may/will be removed in the future. It is best to ensure that these constructs are purged from your code base sooner than later. Most are deprecated in C++11 and removed in C++17 or C++20.

export Used to mark a template definition exported.
In C++11, the keyword is reserved and unused. See related extern template.
register Automatic storage duration specifier.
In C++11, the keyword is reserved and unused.
throw()[8] Dynamic exception specification.
In C++11, see related noexcept.
std::auto_ptr Legacy smart pointer.
In C++11, see related to smart pointers, particularly std::unique_ptr.
std::unary_function
std::binary_function
Base class for function objects.
In C++11, see the more general std::function.
std::bind1st
std::bind2nd
Binds the argument(s) to the parameter of a function object.
In C++11, see std::bind.
std::ptr_fun
std::pointer_to_unary_function
std::pointer_to_binary_function
Creates a function wrapper object.
In C++11, see the more general std::function and std::ref.
std::mem_fun Creates a member function wrapper object.
In C++11, see std::mem_fn.

Language

General features that improve code readability and type safety. The underlying compiler implementation may be significant (e.g. auto) but the implication for the programmer is straight forward.

Angle brackets Compiler recognizes between operator and typedef without having to add whitespace.
nullptr Designed to replace NULL macro. Can be implicitly converted into pointer types, and unlike NULL, not convertible to integral types except bool.
using Type alias which is semantically similar to a typedef. However, with using it is easier to read and is compatible with templates.
auto Automatic compiler deduction of variable and return types according to the type. Particularly useful for long template declarations.
if and switch with initializer New versions of the if and switch statements which simplify common code patterns and keep scopes tight. Similar to for statement initializer.
Range based for loop Executes the for loop over a range, a more readable equivalent of the traditional syntax.
class enum Strongly typed enum to fix C-style enum problems like implicit conversions, inability to specify the underlying type and scope pollution.
Supports forward declaration.
Supports direct list initialization.
Nested namespace Using the namespace resolution operator to create compact nested namespace definitions.
namespace A::B::C {...}
Digit separator Optional single quotes may be inserted between the digits as a separator, which are ignored by the compiler.
int i = 1'000'000;
Binary literal A prefix to represent binary digits similar to octal and hex.
int d = 42; // integer
int o = 052; // octal
int x = 0x2a; // hex
int b = 0b101010; // binary
Raw string literal Prefix R"()" used to avoid escaping of any character.
UTF string literals Prefix for UTF encoded string literal.
u8 = char8_t
u = char16_t
U = char32_t
Attributes Attributes provide a standard syntax over compiler specific __attribute__(...), __declspec, etc.
The attributes specified by the standard are [[noreturn]] [[fallthrough]] [[nodiscard]] [[maybe_unused]] [[deprecated]].

Classes which are the basis of encapsulation in C++ get much needed improvements that make the code cleaner and safer. It fits really well with
the existing constructs.

Delegating constructor Constructors can call other constructors in the same class using an initializer list.
Prior to C++11, this was achieved by having a common initializer member function.
Inherited constructor [10] The using directive “inherits” the base class constructors.
Prior to C++11, this was achieved by writing a matching constructor in the derived class and invoking the appropriate base class constructor.
Converting constructor All constructors without the explicit specifier are considered for implicit conversion.
Prior to C++11, it was restricted to only constructors without the explicit specifier and with a single parameter.
Non-static data member initializers Non-static data members can be initialized where they are declared, potentially cleaning up constructors of default initializations.
=delete Explicitly specify that a function should not be implemented or invoked. Particularly useful to restrict compiler generated member functions.
Prior to C++11, the approach was to make the functions private.
=default Explicitly specify/request the compiler to generate the default function implementation.
override Explicitly specify that a virtual function overrides another virtual function.
final Specify that a virtual function cannot be overridden in a derived class.
Specify that a class cannot be derived further.
Explicit conversion function Implicit conversion can be restricted by using the explicit specifier.
Special member functions Additional member functions, move constructor and move assignment aperator, to support move semantics.

These are some not so obvious features but reasonably easy to grasp and leverage.

inline variable A variable declared inline has the same semantics as a function declared inline.
inline namespace All members of an inline namespace are treated as if they were part of its parent namespace.
constexpr [11][12] Specifies a variable or function as constant expression, which is evaluated by the compiler at compile-time. It provides a type safe alternative to macros.
User defined literals

std literals

Allows integer, floating-point, character, and string literals to produce objects of user-defined type by defining a user defined suffix.
It allows creation of literals like 12_km, 0.5_Pa, 10_celsius.
A suffix that does not begin with the underscore is reserved for the literal operators provided by the standard library, which include built-in literals for std::chrono and std::basic_string.
static_assert Assertions that are evaluated at compile-time. Particularly useful in generic/template programming. It’s quite powerful in conjunction with the STL type_traits.
noexcept Functions that guarantee they won’t emit exceptions.
decltype [13] Operator which returns the declared type of an expression passed to it. Use std::declval for member functions in decltype expressions without the need to go through constructors.
alignof Returns the alignment, in bytes, required for any instance of the type indicated by type-id.
alignas The byte alignment specifier may be applied to the declaration of a type.
Trailing return type [14] An alternative syntax for writing function declarations. Instead of putting the return type before the name of the function, in the new syntax, it is written after the parameters with the -> symbol.

Generic programming with templates have improvements, which have long been pain points but the topics listed here are not necessarily exhaustive.

extern template Indicates to the compiler not to instantiate a template as it will be explicitly done elsewhere.
Template argument deduction To instantiate a function or class template, every template argument must be known, but not every template argument need to be specified.
auto non-type template parameter Type can be deduced from the passed in argument.
Variable template Defines a family of variables or static data members.
Variadic template Accepts zero or more template arguments.
Folding expressions Reduces (folds) a parameter pack over a binary operator.

These are the big-name features of Modern C++, which require time and patience to learn. They are not necessarily difficult to use, but it is important to recognize the underlying concepts to fully comprehend and appreciate them. So do take the time to understand the fundamentals.

Uniform initialization Using braces {} as a single initialization syntax.
RValue reference [15] The pre C++11 reference is now called lvalue reference. The rvalue reference is required for move semantics and perfect forwarding.
Ref qualified member functions [16][17] Calling a function on a rvalue object.
Move semantics
std::move
Move semantics is mostly about performance optimization, the ability to move an object without the expensive overhead of copying.
Perfect forwarding
std::forward
Passing arguments from one function to another without any overhead.
Lambda expression Convenient way to create function objects and unnamed/anonymous callback functions.
Structured binding [18] Binds the specified names to subobjects or elements of the initializer. Ability to declare multiple variables initialised from a tuple or struct.
Memory model Defines the semantics of computer memory storage for the purpose of the C++ abstract machine.
Garbage Collection ABI [20] Provides a definition of what a Garbage Collection can do if one is used and an ABI (Application Binary Interface) to help control its actions.

Modern C++ continues to provide compatibility with C.

Updated POD definition The POD (Plain Old Data) type, which is compatible with C, can be of trivial or standard layout type.
C99 compatibility Adopted many (though not all) of C99 features.

Library

Simple much required string utilities.

std::to_string
std::to_wstring
Converts a numeric argument to a string.
std::string_view A non-owning reference to a string. Useful for providing an abstraction on top of strings (e.g. for parsing).

New containers which make the library more complete.

std::initializer_list A lightweight array-like container of elements created using a braced list syntax.
std::array Container built on top of a C-style array
std::tuple Tuples are a fixed-size collection of heterogeneous values.
Works in conjunction with std::tie, std::get and std::ignore.
std::unordered_set
std::unordered_multiset
std::unordered_map
std::unordered_multimap
Associative container sorted in no particular order.

These are much needed library features that should eliminate propietary implemenations.

Smart pointers
std::unique_ptr
std::shared_ptr
std::weak_ptr
std::make_unique
std::make_shared
Smart pointers are wrappers around raw pointers that act much like the raw pointers they wrap, but that avoid many of their pitfalls. std::auto_ptr is deprecated.
std::filesystem Standard way to manipulate files, directories, and paths in a file system.
std::chrono Utility functions and types that deal with durations, clocks, and time points.
std::regex
std::wregex
Regex library for pattern matching.
type_traits Defines a compile-time template-based interface to query or modify the properties of types.
Concurrency
std::thread
std::async
std::atomic
Standard replacement for platform dependent threading library (e.g. pthreads, windows threads).

Generic types that provide type safety.

std::any Type-safe container for single values of any type.
std::optional [23] Manages an optional contained value, that is, a value that may or may not be present. A common use case for optional is the return value of a function that may fail.
std::variant Represents a type-safe union. An instance of std::variant at any given time holds a value of one of its alternative types (it’s also possible for it to be valueless).
std::byte Distinct type that implements the concept of byte.

General purpose wrappers and utilities for Callable and Function objects.

std::function Store, copy and invoke any Callable target — functions, lambda expressions, bind expressions, or other function objects, as well as pointers to member functions and pointers to data members.
std::bind Binds one or more arguments to a function object.
std::placeholders Namespace contains the placeholder objects [_1, . . . _N]. When used as an argument in std::bind, it acts as a stand-in for unbound arguments.
std::invoke Invoke the Callable object with the given parameter arguments.
std::apply Invoke the Callable object with the given tuple of arguments.
std::mem_fn Generates wrapper objects for pointers to members, which can store, copy, and invoke a pointer to member.
std::ref
std::cref
Helper functions that generate an object of type std::reference_wrapper. Used to pass objects by reference to std::bind.
std::reference_wrapper Wraps a reference in a copyable and assignable object.

New algorithms for a variety of purposes (e.g. searching, sorting, counting, manipulating) that operate on ranges of elements.

Execution policies Most algorithms have overloads that accept execution policies to support different types of parallel execution.
std::all_of
std::any_of
std::none_of
Predicate check for containers
std::find_if_not Extensions to existing std::find
std::copy_i
std::copy_n
Extensions to existing std::copy
std::move
std::move_backward
Move ranges
std::random_shuffle
std::shuffle
Randomly re-orders elements in a range
std::sample Selects n random elements from a sequence
std::is_partitioned
std::partition_copy
std::partition_point
Extension to partitioning operations
std::is_sorted
std::is_sorted_until
std::is_heap
std::is_heap_until
std::is_permutation
Checks for heaps, permutations and sorted ranges
std::minmax
std::minmax_element
Retrieve min and max element as a pair in one call.
std::clamp Clamps a value between a pair of boundary values
std::iota Range of successive increments
std::reduce
std::transform_reduce
Out of order reduction
std::uninitialized_*
std::destroy*
Operations on uninitialized memory

References

    General

  1. isocpp.org: C++ FAQ
  2. cppreference.com
  3. Wikipedia: C++11
  4. Bjarne Stroustrup: C++11 - the new ISO C++ standard
  5. Cheatsheet of modern C++ language and library features
  6. C++17 Features
  7. Scott Meyers: Effective Modern C++
  8. Specific features

  9. Don't use exception specifications
  10. Don't use auto unless you mean it
  11. Inherited constructors
  12. Using constexpr
  13. Convert macros to constexpr
  14. decltype and std::declval
  15. Pros and Cons of Alternative Function Syntax in C++
  16. A Brief Introduction to Rvalue References
  17. Ref qualifiers
  18. Introducing ref-qualifiers for member functions
  19. Structured Bindings
  20. Structured Bindings, Template Argument Deduction and Selection Initialization
  21. Garbage collection ABI
  22. What’s the difference between C++ and C?
  23. Make your functions functional
  24. Clearer interfaces with std::optional
  25. cppreference.com: Algorithms Library

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s