From 15861fe88fb7e4ddcb894a696b7e259ddab1d466 Mon Sep 17 00:00:00 2001 From: Anthony Calandra Date: Sat, 5 Nov 2016 21:11:14 -0700 Subject: [PATCH] More C++11 language features. --- README.md | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/README.md b/README.md index 06c1899..341fcbf 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,11 @@ C++11 includes the following new language features: - [move semantics](#move-semantics) - [variadic templates](#variadic-templates) - [rvalue references](#rvalue-references) +- [initializer lists](#initializer-lists) +- [static assertions](#static-assertions) +- [auto](#auto) +- [lambda expressions](#lambda-expressions) +- [decltype](#decltype) C++11 includes the following new library features: - [std::move](#stdmove) @@ -489,6 +494,109 @@ static_assert(arity<>::value == 0); static_assert(arity::value == 3); ``` +### Initializer lists +A lightweight array-like container of elements created using a "braced list" syntax. For example, `{ 1, 2, 3 }` creates a sequences of integers, that has type `std::initializer_list`. Useful as a replacement to passing a vector of objects to a function. +```c++ +int sum(const std::initializer_list& list) { + int total = 0; + for (auto& e : list) { + total += e; + } + + return total; +} + +auto list = { 1, 2, 3 }; +f(list); // == 6 +f({ 1, 2, 3 }); // == 6 +f({}); // == 0 +``` + +### Static assertions +Assertions that are evaluated at compile-time. +```c++ +constexpr int x = 0; +constexpr int y = 1; +static_assert(x == y, "x != y"); +``` + +### auto +`auto`-typed variables are deduced by the compiler according to the type of their initializer. +```c++ +auto a = 3.14; // double +auto b = 1; // int +auto& c = b; // int& +auto d = { 0 }; // std::initializer_list +auto&& e = 1; // int&& +auto&& f = b; // int& +auto g = new auto(123); // int* +const auto h = 1; // const int +auto i = 1, j = 2, k = 3; // int, int, int +auto l = 1, m = true, n = 1.61; // error -- `l` deduced to be int, `m` is bool +auto o; // error -- `o` requires initializer +``` + +Extremely useful for readability, especially for complicated types: +```c++ +std::vector v = ...; +std::vector::const_iterator cit = v.cbegin(); +// vs. +auto cit = v.cbegin(); +``` + +Functions can also deduce the return type using `auto`. In C++11, a return type must be specified either explicitly, or using `decltype` like so: +```c++ +template +auto add(X x, Y y) -> decltype(x + y) { + return x + y; +} +add(1, 2); // == 3 +add(1, 2.0); // == 3.0 +add(1.5, 1.5); // == 3.0 +``` +The trailing return type in the above example is the _declared type_ (see section on `decltype`) of the expression `x + y`. For example, if `x` is an integer and `y` is a double, `decltype(x + y)` is a double. Therefore, the above function will deduce the type depending on what type the expression `x + y` yields. Notice that the trailing return type has access to its parameters, and `this` when appropriate. + +### Lambda expressions +A `lambda` is an unnamed function object capable of capturing variables in scope. It features: a _capture list_; an optional set of parameters with an optional trailing return type; and a body. Examples of capture lists: +* `[]` - captures nothing. +* `[=]` - capture local objects (local variables, parameters) in scope by value. +* `[&]` - capture local objects (local variables, parameters) in scope by reference. +* `[this]` - capture `this` pointer by value. +* `[a, &b]` - capture objects `a` by value, `b` by reference. + +```c++ +int x = 1; + +auto getX = [=]{ return x; }; +getX(); // == 1 + +auto addX = [=](int y) { return x + y; }; +addX(1); // == 2 + +auto getXRef = [&]() -> int& { return x; }; +getXRef(); // int& to `x` +``` + +### decltype +`decltype` is an operator which returns the _declared type_ of an expression passed to it. Examples of `decltype`: +```c++ +int a = 1; // `a` is declared as type `int` +decltype(x) b = a; // `decltype(x)` is `int` +const int& c = a; // `c` is declared as type `const int&` +decltype(c) d = a; // `decltype(c)` is `const int&` +decltype(123) e = 123; // `decltype(123)` is `int` +int&& f = 1; // `f` is declared as type `int&&` +decltype(f) g = 1; // `decltype(f) is `int&&` +decltype((a)) h = x; // `decltype((a))` is int& +``` +```c++ +template +auto add(X x, Y y) -> decltype(x + y) { + return x + y; +} +add(1, 2.0); // `decltype(x + y)` => `decltype(3.0)` => `double` +``` + ## C++11 Library Features ### std::move