Mead's Guide to Modern C++

List of topics (in no real order):
  1. Overview
  2. Right Angle Brackets (N1757)
  3. Binary Literals (N3472)
  4. Single-Quotation-Mark As a Digit Separator (N3781)
  5. Explicit Conversion Operators
  6. Uniform Initialization
  7. Initializer Lists (N2672)
  8. Range-Based For Loops (N2930)
  9. nullptr (N2431)
  10. Strongly Typed Enums (N2347)
  11. auto Deductions (N1984)
  12. Forward Declarations Of Enums (N2764)
  13. Raw and Unicode String Literals (N2442)
  14. Non-static Data Member Initializers (N2756)
  15. Trailing Return Types (N3276)
  16. __func__ Predefined Identifier (N2340)
  17. Delegating Constructors (N1986)
  18. noexcept
  19. Generalized constexpr (N2235)
  20. Template Aliases (N2258)
  21. Lambdas (N2927)
  22. References

Overview

Because there were so many additions and changes to the C++ language and the libraries, it is virtually impossible to cover everything in one document. (Short of the 1000+ pages of the standard.) This document is just going to give you an introduction to many of these enhancements. Some explanations will be fairly short, and others will be longer. If you really want to know everything about everything, there are links to additional information on each topic. Be warned, though, that some of the documents are quite lengthy and complex and require quite a bit of C++ programming experience.

The topics presented should be understandable by anyone that has programmed in C++ for a few months. I am not going to cover topics that I consider "advanced" such as move semantics, rvalue references, universal references, perfect forwarding, variadic templates, or template deduction. I'm also not covering the additions to the STL (e.g. concurrency, regular expressions).

I present the topics in no particular order. However, some may need to be looked at before others, as they may have some dependencies.

To build these examples, you may need to tell the compiler which "standard" to use. Most of the examples only require a C++11-compliant compiler, but some of them use features from C++14. At the time of this writing, to specify C++11:

g++ -std=c++11 foo.cpp
clang++ -std=c++11 foo.cpp
for C++14:
g++ -std=c++14 foo.cpp
clang++ -std=c++14 foo.cpp
To enable C++17, a.k.a C++1z, you would do this:
g++ -std=c++17 foo.cpp
g++ -std=c++1z foo.cpp
clang++ -std=c++1z foo.cpp
Notice that g++ will accept either c++17 or c++1z. At the time of this writing, Clang only accepts c++1z. Also, these -std= options replace the -ansi option. You can't use both of them.

This is the list of included files to compile all of the examples:

#include <iostream>
#include <vector>
#include <list>
#include <deque>
#include <set>
#include <string>
#include <typeinfo>
#include <initializer_list>
#include <algorithm>
Finally, if you're really interested in learning this stuff, you must actually use it. Reading about the new features is all fine and good, but you're not going to get proficient by simply reading about them. All of the code examples should compile and run (unless they are purposely showing improper use), so you can copy and paste them into your sandbox and play with them to answer all of your questions like "Can I do this?" and "What happens if I do that?"

Right Angle Brackets (N1757)

This is probably the lowest of the low-hanging fruit to be picked! Consider the problem:
vector<list<int>> vl;  // Error in C++03 because >> is extraction operator!
vector<list<int> > vl; // This was the "fix" in C++03
For years, C++ programmers have been typing that "work-around". Now, they don't have to. That's about it for this one, but if you want to read more about the history, go here.

Binary Literals (N3472)

This feature may seem very insignificant, and may well be. But, if you find yourself doing a lot of bit-twiddling, this is a great addition to the language. We always had the ability to write integral literals as decimal, octal, and hexadecimal. Now, we have binary:
  // All values are equivalent, decimal 17
int i1 = 17;      // decimal
int i2 = 021;     // octal (leading zero)
int i3 = 0x11;    // hexadecimal (leading 0x or OX)
int i4 = 0b10001; // C++14 binary (leading Ob or OB)

  // All lines output 17 (decimal)
cout << "i1 is " << i1 << endl;
cout << "i2 is " << i2 << endl;
cout << "i3 is " << i3 << endl;
cout << "i4 is " << i4 << endl;

  // Overriding the default decimal base
cout << oct << showbase << i1 << endl; // 021
cout << hex << showbase << i1 << endl; // 0x11

  // Unfortunately, there currently is no built-in way to print in binary
cout << bin << showbase << i1 << endl; // The bin manipulator doesn't exist!!
For now, you'll have to resort to some other way to get std::ostream to display values in binary.

Single-Quotation-Mark As a Digit Separator (N3781)

Quick, what's the value of a below?
long a = 10000000000; // Hold on, let me count the zeros...
Ok, what's the value of b below?
long b = 10,000,000,000; // Easy! 10 billion
Those little marks (commas) make it trivially easy to know the exact value of the data. Unfortunately, the comma is already used as an operator so we can't use it here. But, we can use the single-quote character:
long b = 10'000'000'000; // Still easy to read
The single-quotes are just for humans (programmers). The compiler strips them out. This means that the groupings and positions are arbitary. These all mean the exact same thing:
long b;
b = 10'000'000'000; 
b = 100'0000'0000;
b = 1'0000'000000;
b = 100'00'00'00'00;
b = 1'0'0'0'0'0'0'0'0'0'0;
One reason for the arbitrary nature of the groupings is that each culture has its own way of grouping numbers. Also, cultures may use different symbols for delimiting the groups. Some cultures use a comma, or a dot, or a space. The C++ culture chose to use the single quotation character.

This delimiter will work with any number base:

int i1 = 1'234'789;   // decimal
int i2 = 01'234'567;  // octal
int i3 = 0x1'abc'def; // hexadecimal
int i4 = 0b1'000'101; // binary
as well as with floating-point types:
float f = 3.14'999'999F;          // float
double d1 = 1'234.7'200'009;      // double
double d2 = 1.234'567e+123;       // double (e-notation)
double d3 = 1.2'3'4'5'6'7e+1'2'3; // crazy!!
Notes:

Explict Conversion Operators (N2437)

First, a quick review of conversion constructors.

C++ has had conversion constructors forever. A conversion constructor is essentially a one-argument constructor. This constructor, then, converts the argument into an object of the class' type. Hence, the term, conversion constructor. Quick example:

class Foo3
{
  public:
    // Conversion constructor
    Foo3(int x) : x_(x)
    {
    }
  private:
    int x_;
};
With the conversion constructor available, the compiler with automatically and silently convert an integer to a Foo3 object whenever it is necessary:
void fn1(const Foo3& f)
{
  // Do something with f
}

Foo3 f(42); // Construct a Foo3 object from an integer (conversion constructor)
f = 43;     // The conversion constructor is called implicitly
fn1(45);    // The conversion constructor is called implicitly
In the code above, the assignment operator expects a Foo3 object, but the programmer has given it an integer. The compiler makes a call to the conversion constructor to perform the conversion before it is passed to the assignment operator. A similar thing occurs when calling function fn1 with an integer when it expects a Foo3 object.

To prevent these automatic and silent conversions, you simply mark the conversion constructor as explicit:

// Explicit conversion constructor
explicit Foo3(int x) : x_(x)
{
}
Now the code above will emit these errors:
error: no viable overloaded '='
  f = 43;     // The conversion constructor is called implicitly
  ~ ^ ~~
note: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const Foo3' for 1st argument
class Foo3
      ^
error: no matching function for call to 'fn1'
  fn1(43);    // The conversion constructor is called implicitly
  ^~~
note: candidate function not viable: no known conversion from 'int' to 'const Foo3' for 1st argument
void fn1(const Foo3& f)
     ^
2 errors generated.
Marking the conversion constructor explicit means that the programmer must explicitly cast the integers:
f = Foo3(43);  // OK, explicit cast
fn1(Foo3(43)); // OK, explicit cast
Conversion constructors are used to convert some other type (e.g. int) into the object's type (e.g. Foo3). What if we want to go in the other direction: converting the object's type into some other type?
Foo3 f(42); // Construct a Foo3 object from an integer

int i = f;                   // Error: Can't assign a Foo3 to an integer
int j = (int)f;              // Error: Still can't do it (compiler doesn't know how)
int k = int(f);              // Nope
int n = static_cast<int>(f); // Nope
That's where conversion operators come in. They tell the compiler how to convert (cast) the object into some other type.

Adding a conversion operator to the Foo3 class:

class Foo3
{
  public:
    // Conversion constructor
    explicit Foo3(int x) : x_(x)
    {
    }

    // Conversion operator
    operator int() const
    {
      return x_;
    }

  private:
    int x_;
};
Now the above conversions to integer work as expected. C++11 has added the ability to mark these conversion operators as explicit, much like conversion constructors:
// Conversion operator
explicit operator int() const
{
  return x_;
}
This will once again fail:
int i = f; // Error: Can't implicitly convert a Foo3 to integer
However, these will all work fine:
int j = (int)f;              // OK, explicit cast
int k = int(f);              // OK, explicit cast
int n = static_cast<int>(f); // OK, explicit cast
You can convert to any type, as long as you provide the appropriate conversion operator. This function expects a string:
void prints(const string& str)
{
  cout << str << endl;
}

Foo3 f(42); // Construct a Foo3 object from an integer
prints(f);  // Error: No conversion from Foo3 to string
Add another conversion operator to Foo3:
// You can mark this explicit, if necessary
operator string() const
{
  return std::to_string(x_); // to_string is new in C++11
}
Foo3 f(42); // Construct a Foo3 object from an integer
prints(f);  // OK, now prints 43
Notes: At Stroustup's FAQ.

Uniform Initialization (uniform-init)

This is actually part of Initializer Lists (N2672) described below, but I wanted to demonstrate the simplest uses before the more complicated ones.

Initializing data in C++ is pretty straight-forward, and there are only a few rules that you have to remember.
  1. Simple built-in scalar types:
    int a = 1; // Copy initialization ("assignment" operator)
    int b(3);  // Direct initialization (parentheses)
    
  2. Arrays:
      // Use "assignment" operator and braces to initialize the arrays
    int array1[] = {1, 2, 3};                       
    const char *array2[] = {"one", "two", "three"};
    
  3. Structs (POD types):
    struct Point
    {
      double x;
      double y;
    };
    
      // Use "assignment" operator and braces to initialize the struct
    Point p = {1.0, 2.0};
    
  4. Classes (with private members)
    class Foo
    {
      public: 
        Foo(int v1, int v2) : a_(v1) // This is initialization (member initializer list)
        {
          b_ = v2; // This is assignment
        }
      private:
        int a_;
        int b_;
    };
    
    Foo f(1, 2); // a_ will be initialized by the constructor
    
These ways of initialization have worked fairly well for years, but they are inconsistent. Also, there are things that still cannot be initialized (e.g. arrays that are members of a class). Well, now things have changed. C++11 adds a couple of other ways to initialize things.
  // Simple initialization
double d1 = 3.14;   // C++98 (copy initialization)
double d2(3.14);    // C++98 (direct initialization)
double d3{3.14};    // C++11 (brace initialization)
double d4 = {3.14}; // C++11 (brace initialization)
This means that you can be consistent and use braces for all of your initializations. Using braces causes the compiler to ensure no loss of data (which is expected):
int i1 = 3.14;   // Clang warns, g++ is silent (even with -Wall, need -Wconversion)
int i2(3.14);    // Clang warns, g++ is silent (even with -Wall, need -Wconversion)
int i3{3.14};    // Clang error, g++ error
int i4 = {3.14}; // Clang error, g++ error
However, you might be surprised by this:
int i5 = 1;    // OK
double d5 = 2; // OK
double d6{1};  // OK, literal is known at compile-time
double d7{i5}; // Clang error, g++ warning,
int i6{d5};    // Clang error, g++ warning,
Setting data to the "default" value:
int ii1;         // Undefined (assume inside of a function)
int ii2();       // Function prototype! a.k.a "the most vexing parse" (Clang warns)
int ii3{};       // 0
int ii4 = {};    // 0
int ii5 = int(); // 0
int ii6 = int{}; // 0
Ok, so which one should you use? All things being equal, I will defer to the man himself (Bjarne Stroustrup):

"Prefer the {}-initializer syntax for declarations with a named type."

There are times when you will use one of the other forms, but those are more advanced situations.

Links:

Initializer Lists (N2672)

Initializer lists are one of the most important new features (IMHO) in C++. They are somewhat related to the uniform intialization, but they have some caveats. Let's start simple with something that has been missing from C++ since the beginning: Member array initialization.

Member Array Initialization

This is how we would "initialize" an array previously:
class Foo2
{
  public:
    Foo2()
    {
        // C++98/03 can't initialize a member array. Must use a loop and "assign" values.
      for (int i = 0; i < 3; i++)
        array_[i] = i + 1;
    }
  private:
    int array_[3]; // How to initialize?
};
Now, C++11 adds the ability to initialize a member array using the member initializer list and braces:
class Foo2
{
  public:
    Foo2() : array_{1, 2, 3} // member array initialization
    {
      // empty body
    }
  private:
    int array_[3];
};
Be sure not to include parentheses in the member initializer list:
Foo2() : array_( {1, 2, 3} ) // Incorrect (GNU extension)
C++11 also allows you to initialize the array directly in the class:
class Foo2
{
  public:
    Foo2()
    {
      // empty body
    }
  private:
    int array_[3] = {1, 2, 3}; // member array initialization (equal sign is optional)
};
You must still specify the size, even though there is an initializer list. This is the error from Clang without it:
error: array bound cannot be deduced from an in-class initializer
    int array_[] = {1, 2, 3}; // member array initialization (equal sign is optional)
                 ^
This is what GNU g++ says:
error: too many initializers for 'int [0]'
     int array_[] = {1, 2, 3}; // member array initialization (equal sign is optional)
                            ^
Another welcome addition is the ability to initialize a standard container with this syntax. Previously, like arrays, there was no easy way of initializing a vector. You had to do something like this:
  // size and capacity is 0
vector<int> v0;

  // Add elements
v0.push_back(1);
v0.push_back(2);
v0.push_back(3);
v0.push_back(4);
v0.push_back(5);

  // Size is 5, capacity is implementation-dependent (it's 8 with clang)
cout << "size: " << v0.size() << ", capacity: " << v0.capacity() << endl;

  // Initialize vector with initializer list syntax
vector<int> v1{1, 2, 3, 4, 5};

  // Size and capacity are both 5
cout << "size: " << v1.size() << ", capacity: " << v1.capacity() << endl;
Lists and other containers also work:
list<int> list1 {5, 4, 3, 2, 1};
deque<int> deque1 {3, 4, 5, 1, 2};
set<int> set1 {5, 4, 3, 2, 1};
Iterating over the containers to display the contents of the list, set, and deque, respectively:
5  4  3  2  1  
3  4  5  1  2  
1  2  3  4  5  


Functions taking initializer lists

A couple of functions to use:

// Function taking a vector
void fn1(const std::vector<int>& v)
{
  cout << "vector: ";
  print5(v);
}

// Function taking an initializer_list
void fn2(const std::initializer_list<int>& lst)
{
  cout << "init list: ";
  print5(lst);
}
Calling the functions:
fn1({1, 2, 3});               // conversion constructor for vector
fn1(vector<int>{1, 2, 3, 4}); // pass vector
fn2({1, 2, 3, 4, 5});         // pass initializer_list
fn1(1, 2, 3, 4, 5);           // Error
fn2(1, 2, 3, 4, 5);           // Error
Output:
vector: 1  2  3  
vector: 1  2  3  4  
init list: 1  2  3  4  5  
Errors from Clang:
cpp14.cpp:357:3: error: no matching function for call to 'fn1'
  fn1(1, 2, 3);
  ^~~
cpp14.cpp:244:6: note: candidate function not viable: requires single argument 'v', 
                 but 3 arguments were provided
void fn1(const std::vector& v)
     ^
cpp14.cpp:358:3: error: no matching function for call to 'fn2'
  fn2(1, 2, 3);
  ^~~
cpp14.cpp:250:6: note: candidate function not viable: requires single argument 'lst', 
                       but 3 arguments were provided
void fn2(const std::initializer_list& lst)
     ^
Notes:


How would we add support for initializer lists to, say, our own Vector class?

  1. First, we would have to include the header file that supports initializer lists (in Vector.h):
    #include <initializer_list>
    
  2. And then add a new constructor to the header file:
    Vector(const std::initializer_list<int>& list);
    
  3. Then in the .cpp file we would implement it:
    Vector::Vector(const std::initializer_list<int>& list) 
       : array_(0), size_(0), capacity_(0)
    {
        // Get the number of elements in the intializer list
      size_t size = list.size();
    
        // The initializer list could be empty
      if (size)
      {
          // Just grow the internal array once (optimization)
        grow(size);
    
          // Iterate over the initializer list, pushing each element to the back
        std::initializer_list<int>::const_iterator it = list.begin();
        while (it != list.end())
          push_back(*it++);
      }
    }
    
  4. And then test it out with some driver code:
    Vector v {1, 2, 3, 4, 5};
    Print(v);
    
    Output:
    1  2  3  4  5  (size=5, capacity=5, allocs=1)
    

Links:

Range-Based For Loops (N2930)

Range-based for loops are another welcomed addition. They work a lot like similar constructs in other languages. However, they are not to be confused with the for_each generic algorithm:
template<typename InputIt, typename Op> Op for_each(InputIt first, InputIt last, Op op);
Examples will clarify. This is how we've used for loops with arrays since the beginning:
  // Initialize int array (20 bytes)
int a[] = {1, 2, 3, 4, 5};

  // Print out each element: 1 2 3 4 5
int size = sizeof(a) / sizeof(*a);
for (int i = 0; i < size; i++)
  cout << a[i] << " ";
cout << endl;
Now, with range-based for loops:
  // Using a range-based for: 1 2 3 4 5
for (int i : a)
  cout << i << " ";
cout << endl;
If we want to modify each element of the array, we need to use references:
  // Multiply each element by 10 (reference)
for (int& i : a)
  i *= 10;

  // Display: 10 20 30 40 50
for (int i : a)
  cout << i << " ";
cout << endl;
You can also use const with the references:
  // Assume some array of large objects
const BigObject BigObjectArray[] = {. . .};

  // Don't want to copy large objects, but don't want to modify either
for (const BigObject& b : BigObjectArray)
  ProcessBigObject(b);
Of course, as you'd expect, the standard containers work equally well. Using a std::list here, just to mix it up a bit. The first loop example is how it was done before C++11:
list<int> lst {1, 2, 3, 4, 5}; // Using C++11 initializer lists

  // Using C++98 iterators with for loop: 1 2 3 4 5
for (list<int>::iterator it = lst.begin(); it != lst.end(); ++it)
  cout << *it << " ";
cout << endl;
You can use the newly re-purposed auto keyword for the iterator. The compiler knows the type that lst.begin() returns, so it can deduce the type for it:
  // Using auto with iterators and for loop: 1 2 3 4 5
for (auto it = lst.begin(); it != lst.end(); ++it)
  cout << *it << " ";
cout << endl;
Using the new range-based for loops, the loop is made even more compact:
  // Using range-based for loop: 1 2 3 4 5
for (int i : lst)
  cout << i << " ";
cout << endl;
Notes:

nullptr (N2431)

A new keyword, nullptr has been created to deal with, well, NULL pointers. The type of nullptr is std::nullptr_t. Historically, there have been some problems when mixing NULL, due to the fact that the actual value is implementation-dependent. It is usually defined in C++ to be 0, but is defined in C to be a void pointer:
#define NULL ((void *)0) // C
#define NULL 0           // C++98
For the most part, this wasn't a huge problem, but it did lead to some ambiguities at times. Given these overloaded functions:
void foo(int)
{
  cout << "foo(int)" << endl;
}

void foo(int *)
{
  cout << "foo(int *)" << endl;
}
this code is fine:
foo(0);       // foo(int)
foo(nullptr); // foo(int*), C++11
foo((int*)0); // foo(int*)
but this is ambiguous:
foo(NULL); // possibly ambiguous, depending on how NULL is defined
Clang says:
error: call to 'foo' is ambiguous
  foo(NULL); // possibly ambiguous, depending on how NULL is defined
  ^~~
note: candidate function
void foo(int)
     ^
candidate function
void foo(int *)
     ^
1 error generated.
Notes:

Strongly Typed Enums (N2347)

OK, so what kinds of problems exist with enumerations that require changes to the language? There are several, and I'm going to discuss a few of them.

There are actually 3 things that have changed with respect to enumerations in C++11. In no particular order:

  1. Create a new kind of enum that is strongly typed: enum class
  2. Allow the programmer to choose the underlying type (i.e. sizeof) used to represent the enum.
  3. Allow access to the enum via the scope resolution operator.
Let's start with how enumerations were handled before C++11. Take this simple enumeration:
enum ColorSpace {Red, Green, Blue};     // Represent graphics colors
and use it:
ColorSpace cs = Green; // Set light to green (integer 1)
In C++, enumerations are their own distinct type, so this is illegal:
cs = 1; // ERROR: no conversion from integer
However, this is fine:
int i = Green; // OK, implicit conversion to integer, C++03 only
OK, so far, so good. This is the pre-C++11 behavior. But, we also have this problem:
enum ColorSpace {Red, Green, Blue};     // Represent graphics colors
enum TrafficLight {Red, Yellow, Green}; // Represent traffic signals
Clang says this:
error: redefinition of enumerator 'Red'
  enum ColorSpace {Red, Green, Blue};     // Represent graphics colors
                   ^
note: previous definition is here
  enum TrafficLight {Red, Yellow, Green}; // Represent traffic signals
                     ^
error: redefinition of enumerator 'Green'
  enum ColorSpace {Red, Green, Blue};     // Represent graphics colors
                        ^
note: previous definition is here
  enum TrafficLight {Red, Yellow, Green}; // Represent traffic signals
                                  ^
This has led programmers to do things like this:
enum ColorSpace {csRed, csGreen, csBlue};     // Represent graphics colors
enum TrafficLight {tlRed, tlYellow, tlGreen}; // Represent traffic signals
There is no longer any ambiguity:
ColorSpace color = csGreen;   // OK 
TrafficLight light = tlGreen; // OK
Of course, there are other solutions (e.g. namespaces, static members of a class).

Then there is the issue with this:

sizeof(ColorSpace)
This is compiler-dependent. The only thing the compiler guarantees is that the underlying type used to represent the enumerations is large enough to hold the value of the largest element.

Fortunately, C++11 solves these shortcomings with a feature call enumeration classes:

  // No longer ambiguous
enum class ColorSpace {Red, Green, Blue};     // Represent graphics colors
enum class TrafficLight {Red, Yellow, Green}; // Represent traffic signals

  // Clear, unambiguous, self-documenting
ColorSpace cs = ColorSpace::Green;
TrafficLight tl = TrafficLight::Green;
However, this is no longer supported:
int i = Color::Green; // No conversion to int in C++11
These are also referred to as scoped enumerations because you access them with the scope resolution operator. Also, the size of the underlying type is guaranteed to be integer (unless you specifically request a different type).

If you leave off the class, you can still use the scope resolution operator. This was an enhancement made to the original enum specification:

enum TrafficLight {Red, Yellow, Green}; // Represent traffic signals

TrafficLight tl = TrafficLight::Green; // Optional qualifier (recommended)
TrafficLight tl2 = Green;              // Same as TrafficLight::Green
However, I would avoid the old-style enumerations, as that can lead to ambiguities. Get into the habit of using the qualified names and you'll never have a problem.

C++11 also lets you choose the representation of the enumeration:

enum class TrafficLight : char {Red, Yellow, Green};  // Represent traffic signals
enum class ColorSpace : short {Red, Green, Blue};     // Represent graphics colors
enum class Twister : long {Red, Green, Blue, Yellow}; // Represent the game colors
enum class Checkers {Red, Black};                     // Represent the game colors

  // Sizes shown are using the LP64 data model  
cout << sizeof(TrafficLight) << endl; // 1
cout << sizeof(ColorSpace) << endl;   // 2
cout << sizeof(Twister) << endl;      // 8
cout << sizeof(Checkers) << endl;     // 4 (default type is int)
Notes: Another thing relating to enumerations that was introduced in C++11 is forward declaration of enumerations (N2764).
enum class ColorSpace : short; // Represent graphics colors (forward declaration)

// Other code ...

enum class ColorSpace : short {Red, Green, Blue}; // Actual definition is here
Notes:

auto Deductions (N1984)

Just as the compiler can (usually) deduce the types of parameters to templated functions, the compiler can now deduce the type of a variable based on it's initializer. It uses the deprecated auto keyword:
auto i = 10;    // int
auto d = 10.0;  // double
auto f = 10.0F; // float
cout << typeid(i).name() << endl; // i
cout << typeid(d).name() << endl; // d
cout << typeid(f).name() << endl; // f
You can also include qualifiers:
const auto ii = 10;    // const int
auto& ri = ii;         // int&
const auto& cri = ii; // const int&
Be careful when using auto:
auto i1 = 1;   // int, as expected
auto i2 = {1}; // initializer_list<int>, probably not what you want
auto i3 {1};   // int
auto i4(1);    // int

cout << typeid(i1).name() << endl; // i
cout << typeid(i2).name() << endl; // St16initializer_listIiE
cout << typeid(i3).name() << endl; // i
cout << typeid(i4).name() << endl; // i
More examples:
vector<int> v1;

auto x1 = v1.crbegin();
cout << typeid(x1).name() << endl;

vector<int>::const_reverse_iterator x2 = v1.crbegin();
cout << typeid(x2).name() << endl;
Output:
St16reverse_iteratorIN9__gnu_cxx17__normal_iteratorIPKiSt6vectorIiSaIiEEEEE
St16reverse_iteratorIN9__gnu_cxx17__normal_iteratorIPKiSt6vectorIiSaIiEEEEE
Using auto:
  // vector<int>
auto v2(v1);
cout << "   auto v2(v1) is " << typeid(v2).name() << endl;

  // vector<int>
auto v3 = v1;
cout << "  auto v3 = v1 is " << typeid(v3).name() << endl;

  // vector<int>  
auto v4{v1};
cout << "   auto v4{v1} is " << typeid(v4).name() << endl;

  // initializer_list<vector<int>>
auto v5 = {v1};
cout << "auto v5 = {v1} is " << typeid(v5).name() << endl;
Output:
   auto v2(v1) is St6vectorIiSaIiEE
  auto v3 = v1 is St6vectorIiSaIiEE
   auto v4{v1} is St6vectorIiSaIiEE
auto v5 = {v1} is St16initializer_listISt6vectorIiSaIiEEE
The "classic" example for using auto is with iterators in loops. Here's the print5 function:
template <typename T>
void print5a(const T& container)
{
  for (typename T::const_iterator iter = container.begin(); iter != container.end(); ++iter)
    std::cout << *iter << "  ";
  std::cout << std::endl;
}
Using auto:
template <typename T>
void print5b(const T& container)
{
  for (auto iter = container.begin(); iter != container.end(); ++iter)
    std::cout << *iter << "  ";
  std::cout << std::endl;
}
Using auto and range-based for loops:
template <typename T>
void print5(const T& container)
{
  for (auto e : container)
    std::cout << e << "  ";
  std::cout << std::endl;
}
When declaring multiple variables with the auto keyword, they all must be the same type:
auto i = 5, j = 7, *pi = &i; // OK
auto k = 100, d = 3.1415;    // error: inconsistent deduction for auto

vector<int> v1 {1, 2, 3};
for (auto iter = v1.begin(), end = v1.end(); iter != end; ++iter)
  cout << *iter << endl;
Notes:

Raw and Unicode String Literals (N2442)

Here is some sample code from the link above that shows the motivation for raw strings:

    "('(?:[^\\\\']|\\\\.)*'|\"(?:[^\\\\\"]|\\\\.)*\")|"

Are the high-lighted five backslashes correct or not? Even experts become easily confused. Here is the same line as a raw string literal:

    R"(('(?:[^\\']|\\.)*'|"(?:[^\\"]|\\.)*")|)"

Anytime that you need to deal with strings that include characters like backslashes and double-quotes, you end up having to escape them (with the backslash character). This makes the string difficult to parse (for a human). Certain types of text processing requires these "special" characters (e.g. HTML, XML, regular expressions, etc.) Having a more convenient way to code those strings without all of the escaping, is desirable.

This is something that every Windows programmer has had to deal with:

std::string text_editor("c:\windows\system32\notepad.exe");
Errors from Clang:
error: unknown escape sequence '\w' [-Werror,-Wunknown-escape-sequence]
  std::string text_editor("c:\windows\system32\notepad.exe");
                             ^~
error: unknown escape sequence '\s' [-Werror,-Wunknown-escape-sequence]
  std::string text_editor("c:\windows\system32\notepad.exe");
                                     ^~
2 errors generated.
The programmer forgot to escape the backslashes (directory delimiters): Because the backslashes are used to delimit subdirectories, the compiler thinks that there are 3 escape sequences: \w, \s, and \n. Of course, \n is a valid escape sequence, but it's unlikely that the text_editor intended to have a newline as part of it. I have seen this exact problem confuse new C/C++ programmers several times.

This is the proper way:

std::string text_editor("c:\\windows\\system32\\notepad.exe");
Using raw strings makes it much simpler:
std::string text_editor(R"(c:\windows\system32\notepad.exe)");
Raw strings are pretty simple. Thye just tell the compiler to use the strings without any interpretation of the escape sequences.

To construct a raw string:

  1. A raw string must start with R" (capital 'R' only, not lowercase 'r') and a double-quote character.
  2. The R" is then followed by a PREFIX which consists of 0 to 16 characters. Most characters are allowed.
  3. The (optional) PREFIX must be followed by a left parenthesis.
  4. After the left parenthesis, the actual characters of the string will follow and no interpretation is done, i.e. backslashes do not escape anything and double-quotes do not terminate the raw string but are part of it.
  5. The raw string is terminated by a right parenthesis followed by the same PREFIX that was specified in #2.
  6. Finally, a double-quote character terminates the entire sequence.
Examples will clarify. The text in blue is the actual raw string. The normal text on either side are the delimiters that mark the begin and end of the raw text.
const char *s1 = R"(hello)";     // hello
const char *s2 = R"(he"ll"o)";   // he"ll"o
const char *s3 = R"(hel)lo)";    // hel)lo
const char *s4 = R"(h\tello\n)"; // h\tello\n
const char *s5 = R"(R"()";       // R"(
const char *s6 = R"(R"()")";     // ERROR
Output:
hello
he"ll"o
hel)lo
h\tello\n
R"(
This is the error from Clang for the last one:
cpp14.cpp:562:29: error: missing terminating '"' character [-Werror,-Winvalid-pp-token]
  const char *s6 = R"(R"()")";     // ERROR
                            ^
cpp14.cpp:562:28: error: expected ';' at end of declaration
  const char *s6 = R"(R"()")";     // ERROR
                           ^
                           ;
2 errors generated.
What we are trying to do is to print this string:
R"()"
But the sequence )" is what is terminating the raw string. If you need to include characters in the raw string that have the same sequence as the delimiter, you need to change the delimiter into something unique. That's why the PREFIX is 0 to 16 characters. If there are no conflicts, you don't need the PREFIX (hence, the optional wording). In this case, we have a conflict so we need to resolve it by creating a PREFIX.

Any character (or set of characters) will do:

const char *s7 = R"x(R"()")x";   // R"()"
The PREFIX is just the character x and is enough to prevent any conflicts. It doesn't matter what character(s) you use, as long as they are not part of the PREFIX.

Non-static Data Member Initializers (N2756)

Before C++11, you could only initialize non-static, constant integral members in the class definition. All other members were required to be initialized in a constructor. For base classes, members that are user-defined types, constants, and reference, the initialization must take place in the member initializer list. For all other types, you could assign to them in the body of the constructor, although they could still be initialized in the initializer list.

With C++11 and later, you can now initialize members directly in the class definition. This is a welcomed addition that other languages (such as Java and D) have had already. The concept is easy to understand, so let's look at an example.

// Global function
int getnumber()
{
  return 42;
}

class A
{
  public:
    A() : b{7, 8, 9} // initialized by member initializer list
    {
        // Assignment, not initialization (OK, c is non-const)
      for (int i = 0; i < 3; i++)
        c[i] = i;
    }

    A(int x) : i(x), b{x, x, x}
    {
      // c is left unitialized
    }

    void print()
    {
      cout << i << endl;
      cout << j << endl;
      cout << k << endl;
      cout << d << endl;
      for (auto it : v)
        cout << it << " ";
      cout << endl;
      for (auto it : a)
        cout << it << " ";
      cout << endl;
      for (auto it : b)
        cout << it << " ";
      cout << endl;
      for (auto it : c)
        cout << it << " ";
      cout << endl;
    }

  private:
    int i = 5;             // Member initialization
    int j = getnumber();   // Member initialization (calls member function)
    int k = ::getnumber(); // Member initialization (calls global function)
    double d = 3.14;       // Member initialization

    vector<int> v{1, 2, 3};   // Member initialization (vector constructor)

    const int a[3] {0, 0, 0}; // const can be initialized here
    const int b[3];           //   or using the member initializer list in the constructor
    int c[3];                 // Non-const can be assigned in the constructor

    // private member function
    int getnumber()
    {
      return 32;
    }
};
There aren't too many rules about what can be initialized in the class definition, but you can read more about it

Trailing Return Types (N3276)

I'm going to introduce some new syntax using trivial examples. However, these techniques should never be used for trivial functions, as they cause more problems than they solve. Actually, they don't solve anything, they just create problems. But, before I show you the advanced reasons for using these techniques, I want you to understand what's going on.

In C++03, the programmer had to specify the return type for a function as the first part of the function header:
int Add(int a, int b)
{
  return a + b;
}
This is all fine and good. C++11 allows you to specify the return type at the end of the function header instead of the beginning:
auto Add(int a, int b) -> int
{
  return a + b;
}
At first glance, you may be thinking that this isn't doing anything helpful. In this trivial example, you're correct. It was meant for much more complicated things (as you'll soon see). Also, some languages actually specify their return types at the end, and, IMHO, I find those functions easier to read. Some examples:
foo(int, int, int) -> long;
foo(const char *) -> std::string;
The first one is a function that takes 3 integers as input and returns a long integer. The second function takes a constant character pointer and returns a std::string. It's really just a matter of preference as there is really no benefit to either.

The primary reason for this was to help deduce returns from templated functions:

template <typename T, typename U>
auto Add(T a, U b) -> decltype(a + b)
{
  return a + b;
}
Call the function:
int i1 = 5, i2 = 6;
double d1 = 2.72, d2 = 3.14;

cout << Add(i1, i2) << endl; // return type is int
cout << Add(d1, d2) << endl; // return type is double
cout << Add(i1, d2) << endl; // return type is double
Notice the new keyword decltype at the end. This tells the compiler to "figure out" what the return type will be based on the two template parameters. Also, it must come at the end of the function header and not the beginning:
template <typename T, typename U>
decltype(a + b) Add(T a, U b)
{
  return a + b;
}
Error from Clang:
error: use of undeclared identifier 'a'
decltype(a + b) Add(T a, U b) ->
         ^
error: use of undeclared identifier 'b'
decltype(a + b) Add(T a, U b) ->
             ^
This is simply because the compiler hasn't seen a or b yet. This is why it's at the end.
C++14 has taken this one step further and automatically deduces the return type, so you don't even need to specify it at the end:
auto Add(int a, int b)
{
  return a + b;
}
And with the templated function above:
template <typename T, typename U>
auto Add(T a, U b)
{
  return a + b; // The compiler figures out the return type
}
Realize that if there are multiple return calls, they all must be the same type:
template <typename T, typename U>
auto max(T a, U b)
{
  if (a > b)
    return a;
  else
    return b; // a and b can be different types
}

cout << max(1, 2.0) << endl; // Call max with different types
Error from Clang:
error: 'auto' in return type deduced as 'double' here but deduced as 'int' in earlier return statement
    return b;
    ^
Notes:

__func__ Predefined Identifier (N2340)

Before C++11, many compilers used a non-standard way of identifying the name of the function during compilation:
void SomeFunction()
{
  cout << "Function name is: " << __FUNCTION__ << endl; // Old non-standard extension
}
Output:
Function name is: SomeFunction
C++11 has standardized it with __func__:
cout << "In function: " << __func__ << endl; // The name of the function
cout << "    in file: " << __FILE__ << endl; // The name of the C++ file
cout << "    at line: " << __LINE__ << endl; // The current line number
cout << "         on: " << __DATE__ << endl; // The current date
cout << "         at: " << __TIME__ << endl; // The current time
Output:
In function: f13
    in file: cpp14.cpp
    at line: 873
         on: Apr 15 2017
         at: 14:58:20
The test function is named f13.

It is unfortunate that all of the other similar techniques use all uppercase names. I believe that this is due to the fact that __func__ is implemented by the compiler and the others are expanded by the pre-processor. To "prove" this, I just compiled the code with the -E option (show the pre-processed code):

cout << "In function: " << __func__ << endl;
cout << "    in file: " << "cpp14.cpp" << endl;
cout << "    at line: " << 873 << endl;
cout << "         on: " << "Apr 15 2017" << endl;
cout << "         at: " << "14:59:39" << endl;

The purpose of __func__ is to help with diagnostic messages at runtime. You can easily build up an informative error message with the aid of these features:

cout << "An out-of-range error has occurred in file " << __FILE__
     << " at line " << __LINE__
     << " (in function " << __func__ << ").\n"
     << "The software was last compiled on " << __DATE__
     << " at " << __TIME__ << ".\n";
Output:
An out-of-range error has occurred in file cpp14.cpp at line 879 (in function f13).
The software was last compiled on Apr 15 2017 at 14:58:20.
Notes: Standard Predefined Macros This page lists some of the other macros that are available.

Delegating Constructors (N1986)

Delegating constructors is a fancy way of saying that one constructor can call another constructor. In this scenario, I'm not talking about a derived class constructor calling a base class constructor. That has been around since the beginning. I'm talking about one constructor of a class calling another constructor of the same class. Until this feature came around in C++11, this was not allowed by the language. C++ programmers have done all sorts of things to get around this situation (as other languages, such as Java and D, already have this capability.)

Constructors are generally the place to initialize members of the class. It's not uncommon to have more than one constructor, so this "initialization code" needed to be duplicated in several places. Or, better yet, this "duplicated" code was factored out into a separate init(...) method that was then called from each constructor:

class C1
{
  public:
      // Default constructor
    C1() 
    {
      init(); // Do other setup code...
    }

      // Single-argument conversion constructor
    C1(double x) : d_(x)
    {
      init(); // Do other setup code...
    }

      // Non-default constructor
    C1(int a, int b, int c, double d) : a_(a), b_(b), c_(c), d_(d)
    {
      init(); // Do other setup code...
    }

  private:
    int a_, b_, c_;
    double d_;

    void init()
    {
       // Do a lot of setup stuff
    }
};
Although we have factored out the common "initialization" code, it's not really initialization because that must take place in the constructor, not another method (even if you name it init!)

With delegating constructors, we can just call the "main" constructor that will do all of the initialization:

class C2
{
  public:
      // Default constructor
    C2() : C2(0, 0, 0, 0.0) // delegate to other constructor
    {
    }

      // Single-argument conversion constructor
    C2(double x) : C2(0, 0, 0, x) // delegate to other constructor
    {
    }

      // Non-default constructor
    C2(int a, int b, int c, double d) : a_(a), b_(b), c_(c), d_(d)
    {
      // Do a lot of setup stuff
    }

  private:
    int a_, b_, c_;
    double d_;
};
Notes:

noexcept ()

Previous versions of C++ have had exception specifications. This was a mechanism that allowed the programmer to "tag" functions with the types of exceptions that might be thrown. For example, this lookup function can potentially throw an exception if the index is out of range:
int lookup(const vector<int>& v, int index) throw(std::out_of_range)
{
  return v.at(index); // This method does range checking
}
The code at the end:
throw (std::out_of_range)
is the exception specification and informs the programmer what may be thrown from the function. It also tells the compiler to prevent any other exceptions from being thrown. If any exception, other than std::out_of_range is thrown, the entire program is terminated.

This is sample code that calls the function above:

vector<int> v {10, 20, 30};
try
{
  cout << lookup(v, 2) << endl; // Prints 30
  cout << lookup(v, 5) << endl; // Throws a std::out_of_range exception
}
catch (const std::out_of_range& ex)
{
  cout << ex.what() << endl; // Display details about the exception
}
Output:
30
vector::_M_range_check: __n (which is 5) >= this->size() (which is 3)

There are 3 varieties of exception specifications:
// foo1 will throw no exceptions
int foo1() throw();

// foo2 will only throw std::out_of_range or std:bad_alloc
int foo2() throw (std::out_of_range, std::bad_alloc);

// foo3 may thrown any exception
int foo3();
  1. foo1 - An empty exception specification may not throw any exception.
  2. foo2 - A non-empty exception specification may only throw the exceptions listed.
  3. foo3 - A missing exception specification may throw any exception.
For various reasons, exception specifications never worked out as intended and have been deprecated for several years. Now, with C++11, there is a replacement. As it turns out, the important information that the compiler wants to know is if the function throws an exception or not. The compiler doesn't care about which exception is thrown. The new technique reflects this change:
// Function will not throw an exception
void foobar1() noexcept(true)
{
  // do something safe
}

// Function may throw an exception
void foobar2() noexcept(false)
{
  // do something possibly unsafe
}

// foobar3 may throw an exception only if foobar2 may throw an exception
void foobar3() noexcept(noexcept(foobar2()))  
{
  foobar2(); // call possibly unsafe function
}

// foobar4 will not throw an exception (protects unsafe call to foobar2)
void foobar4() noexcept(true)  
{
  try
  {
    foobar2(); // call possibly unsafe function
  }
  catch (.../* whatever foobar2 throws */)
  {
    // do something with the exception
  }

  // safely continue excecuting...
}
Examples showing a noexcept expression:
cout << boolalpha;
cout << "  noexcept(true)? " << noexcept(true) << endl;
cout << " noexcept(false)? " << noexcept(false) << endl;
cout << "foobar1 noexcept? " << noexcept(foobar1()) << endl;
cout << "foobar2 noexcept? " << noexcept(foobar2()) << endl;
cout << "foobar3 noexcept? " << noexcept(foobar3()) << endl;
cout << "foobar4 noexcept? " << noexcept(foobar4()) << endl;
Output:
  noexcept(true)? true
 noexcept(false)? true
foobar1 noexcept? true
foobar2 noexcept? false
foobar3 noexcept? false
foobar4 noexcept? true
When declaring a function to be noexcept, these both mean the same thing:
void foobar() noexcept(true) // explicit
void foobar() noexcept       // implicit
On a side note, it's a little unfortunate that the terminology kind of reverses the definition of on/true/enabled with off/false/disabled. By setting noexcept to true, you are disabling the ability to throw exceptions. It has always seemed strange to me when you "turn something off" by answering in the affirmative:
Q: "Do you want me to not turn the lights off?"
A: Yes, please do not turn them off.
Most English speakers will ask in the affirmative:
Q: "Do you want me to turn the lights off?"
A: No, please do not turn them off.
This would mean we would have except(true) to allow exceptions and except(false) to not allow them. Anyhoo...

Notes:

Generalized constexpr (N2235)

C++11 introduces a new way of dealing with constant expressions. You can now explicitly mark a symbol with the constexpr keyword. This is more powerful than simply using const alone. Using just const means that the expression is constant and won't change, but it doesn't mean that the value is known at compile-time:
const int i = getvalue1(); // Sets i at runtime. Must be initialized because it's const
int array[i];              // Illegal, i isn't known at compile time. 
In the code above, getvalue1() is just some arbitrary function that will return an integer when called. However, the value returned isn't known to the compiler and can't be used to set the size of the array. With the constexpr keyword, things change.

Here are 4 functions for the examples below:

constexpr int ipower(int base, int exponent)
{
  int p = 1;
  
  for (int i = 0; i < exponent; i++)
    p *= base;

  return p;
}
constexpr int squared(int x)
{
  return x * x;
}
int getvalue1()
{
  return 10;
}
constexpr int getvalue2()
{
  return 20;
}
Code that calls the above functions:
int a1[getvalue1()];            // Illegal, getvalue1() isn't known at compile-time
int a2[getvalue2()];            // OK, constant expression

const int v1 = getvalue1();     // OK, but v1 isn't known at compile-time (not constexpr)
int a3[v1];                     // Illegal

const int v2 = getvalue2();     // OK, but v2 is not constexpr
int a4[v2];                     // Illegal

constexpr int v3 = getvalue1(); // Illegal, can't initialize v3 with non-constexpr

constexpr int v4 = getvalue2(); // OK
int a5[v4];                     // OK

int a6[squared(5)];             // OK
cout << sizeof(a6) << endl;     // prints 100 (25 * 4)

int a7[squared(getvalue1())];   // Illegal, getvalue1 is not constexpr
int a8[squared(getvalue2())];   // OK
cout << sizeof(a8) << endl;     // prints 1600 (40 * 4)

int a9[ipower(2, 3)];            // OK
cout << sizeof(a9) << endl;     // prints 32 (8 * 4)
Notes:

Template Aliases (N2258)

In C++03, if you want to define an alias for a type, you used typedef:
typedef unsigned char BYTE;
typedef short int FAST_INT;
typedef float CURRENCY;
typedef unsigned char * PCHAR;
Using them:
BYTE next, previous;    // For scanning bytes in memory
CURRENCY tax, discount; // To calculate total price
PCHAR inbuf, outbuf;    // To manipulate strings
The equivalent with the using keyword:
using BYTE = unsigned char;
using FAST_INT = short int;
using CURRENCY = float;
using PCHAR = unsigned char *;
We can use typedef with the STL containers:
typedef vector<int> MyVectorI;    // MyVectorI is an alias for vector of int
typedef vector<string> MyVectorS; // MyVectorS is an alias for vector of string
typedef vector<double> MyVectorD; // MyVectorD is an alias for vector of double
Usage:
MyVectorI mvi; // vector of int
MyVectorS mvs; // vector of string
MyVectorD mvd; // vector of double
At this point there is absolutely no difference in behavior between typedef and using. However, when it comes to templates, there is a problem with typedef:
template <typename T>
typedef vector<T> MyVectorOfT;
Error from Clang:
error: a typedef cannot be a template
typedef vector MyVectorOfT;
                  ^
1 error generated.
This is where the new behavior of using comes in:
template <typename T>
using MyVector = vector<T>; // MyVector is an alias for a vector anything
Usage:
MyVector<int> vi2;    // vector of int
MyVector<string> vs2; // vector of string
MyVector<double> vd2; // vector of double
At this point, there is not much to be gained. But as the types get more complicated:
template <typename T>
using MyVectorT = vector<list<T>>; // MyVectorT is an alias for a vector of list of anything

MyVectorT<int> vli;    // vector of list of int
MyVectorT<string> vls; // vector of list string
MyVectorT<double> vli; // vector of list of double
Or this:
template <typename T, typename Alloc = std::allocator<T>>
using MyIter = typename vector<list<T, Alloc>>::iterator;

MyIter<string> it1;       // An iterator on a vector of lists of string and the default allocator
MyIter<Foo, MyAlloc> it2; // An iterator on a vector of lists of Foo and custom allocator
Yes, that's a little contrived. However, in real code, you are likely to have instances where the types are complicated and tedious to write out, especially when you start using templates. Notes:

Lambdas (N2927)

I've already written a substantial guide on lambdas here.

References

This was just an introduction to some of the new features of the C++ language. If you want to learn more, here are a few places to start:

Compiler support for Modern C++:

Books:

Other resources