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

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.


Modern C++ and C++11 are used interchangeably. Both refer to the standards published in C++11, C++14, C++17 and C++20.


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 see related extern template. In C++20 see related to modules.
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.
Base class for function objects.
In C++11, see the more general std::function.
Binds the argument(s) to the parameter of a function object.
In C++11, see std::bind.
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.
Implicit lambda capture of this using [=] In C++20 prefer capturing explicitly using [=, this] or [=, *this].
In C++20, the corresponding headers remain for compatibility with C.


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.
auto Automatic compiler deduction of variable and return types according to the type. Particularly useful for long template declarations.
Range based for loop Executes the for loop over a range, a more readable equivalent of the traditional syntax.
if with initializer
switch with initializer
range based for with initializer
New versions of the if, switch and range based for statements which simplify common code patterns and keep scopes tight.
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.
using Type alias which is semantically similar to a typedef, which is easier to read and compatible with templates.
Introduces the named enumerator members into the scope, similar to namespace.
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
3-way comparison operator <=> Takes two values A and B belonging to a type and determines whether A < B, A = B, or A > B in a single operation.
Feature test macros Set of preprocessor macros corresponding to C++ language and library features introduced in C++11 or later. They are intended as a simple and portable way to detect the presence of said features.
Aggregate initialization
Designated initializers
Initializes an aggregate from braced-init-list.
Supports C-style designated initializer syntax.

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.
explicit(bool) Implicit conversion (converting constructor or user defined conversion function) can be restricted by using the explicit specifier. Also can conditionally select at compile-time whether it is made explicit or not.
Non-static data member
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.
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.
consteval Similar to constexpr functions, but functions with a consteval specifier must produce a constant. These are called immediate functions.
constinit Indicates that a variable has static initialization.
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 as non-type template parameter Type can be deduced from the passed in argument.
class type in non-type template parameter Class types are allowed as non-type template parameter.
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
Move semantics is mostly about performance optimization, the ability to move an object without the expensive overhead of copying.
Perfect forwarding
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.
Concepts are named compile-time predicates which constrain types. The requires keyword is used either to start a requires clause or a requires expression.
A coroutine is a function that can suspend execution to be resumed later.
Modules help divide large amounts of code into logical parts.

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.


Simple much required string utilities.

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).
Checks if the string begins or ends with the given substring.
<format> Text formatting offers a safe and extensible alternative to the printf family of functions.

Containers and related features which make the library more complete.

std::initializer_list A lightweight array-like container of elements created using a braced list syntax.
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.
Associative container sorted in no particular order.
<span> A view (i.e. non-owning) of a container providing bounds-checked access to a contiguous group of elements.
<ranges> Uniform composable operations on containers.
Uniform container erasure.
contains() Member function on associative container to check if it has an element.

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

Smart pointers
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.
<filesystem> Standard way to manipulate files, directories, and paths in a file system.
<chrono> Utility functions and types that deal with durations, clocks, and time points.
Pseudo-random number generation.
Compile-time rational arithmetic.
Mathematical constants including PI, Euler's number, etc.
<regex> Regex library for pattern matching.
<type_traits> Defines a compile-time template-based interface to query or modify the properties of types.
Atomic smart pointers
Provides components for fine-grained atomic operations allowing for lockless concurrent programming.
Standard replacement for platform dependent threading library (e.g. pthreads, windows threads).
<concepts> Support for concepts.
<coroutine> Support for coroutines.
<bit> Support for bit operations.
<source_location> A class representing information about the source code, such as file names, line numbers, and function names.
<version> Supplies implementation dependent information about the standard library.

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::bind_front Binds arguments to the first n parameters.
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.
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.
Predicate check for containers
std::find_if_not Extensions to existing std::find
Extensions to existing std::copy
Move ranges
Randomly re-orders elements in a range
std::sample Selects n random elements from a sequence
Extension to partitioning operations
Checks for heaps, permutations and sorted ranges
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::midpoint Computes the midpoint of the integers, floating-points, or pointers.
std::lerp Linear interpolation and extrapolation at paramter t.
Out of order reduction
Operations on uninitialized memory



  1. C++ FAQ
  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. Algorithms Library
  26. Clang: Modules
  27. Modules

Leave a Reply

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

You are commenting using your 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