mirror of
https://github.com/AnthonyCalandra/modern-cpp-features.git
synced 2025-12-17 01:54:36 +03:00
Fix formatting.
This commit is contained in:
33
CPP11.md
33
CPP11.md
@@ -324,7 +324,7 @@ constexpr const int& y = x; // error -- constexpr variable `y` must be initializ
|
|||||||
Constant expressions with classes:
|
Constant expressions with classes:
|
||||||
```c++
|
```c++
|
||||||
struct Complex {
|
struct Complex {
|
||||||
constexpr Complex(double r, double i) : re(r), im(i) { }
|
constexpr Complex(double r, double i) : re{r}, im{i} { }
|
||||||
constexpr double real() { return re; }
|
constexpr double real() { return re; }
|
||||||
constexpr double imag() { return im; }
|
constexpr double imag() { return im; }
|
||||||
|
|
||||||
@@ -341,7 +341,7 @@ Constructors can now call other constructors in the same class using an initiali
|
|||||||
```c++
|
```c++
|
||||||
struct Foo {
|
struct Foo {
|
||||||
int foo;
|
int foo;
|
||||||
Foo(int foo) : foo(foo) {}
|
Foo(int foo) : foo{foo} {}
|
||||||
Foo() : Foo(0) {}
|
Foo() : Foo(0) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -404,13 +404,8 @@ struct C : B {
|
|||||||
|
|
||||||
Class cannot be inherited from.
|
Class cannot be inherited from.
|
||||||
```c++
|
```c++
|
||||||
struct A final {
|
struct A final {};
|
||||||
|
struct B : A {}; // error -- base 'A' is marked 'final'
|
||||||
};
|
|
||||||
|
|
||||||
struct B : A { // error -- base 'A' is marked 'final'
|
|
||||||
|
|
||||||
};
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Default functions
|
### Default functions
|
||||||
@@ -418,7 +413,7 @@ A more elegant, efficient way to provide a default implementation of a function,
|
|||||||
```c++
|
```c++
|
||||||
struct A {
|
struct A {
|
||||||
A() = default;
|
A() = default;
|
||||||
A(int x) : x(x) {}
|
A(int x) : x{x} {}
|
||||||
int x {1};
|
int x {1};
|
||||||
};
|
};
|
||||||
A a; // a.x == 1
|
A a; // a.x == 1
|
||||||
@@ -428,7 +423,7 @@ A a2 {123}; // a.x == 123
|
|||||||
With inheritance:
|
With inheritance:
|
||||||
```c++
|
```c++
|
||||||
struct B {
|
struct B {
|
||||||
B() : x(1) {}
|
B() : x{1} {}
|
||||||
int x;
|
int x;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -447,7 +442,7 @@ class A {
|
|||||||
int x;
|
int x;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
A(int x) : x(x) {};
|
A(int x) : x{x} {};
|
||||||
A(const A&) = delete;
|
A(const A&) = delete;
|
||||||
A& operator=(const A&) = delete;
|
A& operator=(const A&) = delete;
|
||||||
};
|
};
|
||||||
@@ -477,9 +472,9 @@ The copy constructor and copy assignment operator are called when copies are mad
|
|||||||
```c++
|
```c++
|
||||||
struct A {
|
struct A {
|
||||||
std::string s;
|
std::string s;
|
||||||
A() : s("test") {}
|
A() : s{"test"} {}
|
||||||
A(const A& o) : s(o.s) {}
|
A(const A& o) : s{o.s} {}
|
||||||
A(A&& o) : s(std::move(o.s)) {}
|
A(A&& o) : s{std::move(o.s)} {}
|
||||||
A& operator=(A&& o) {
|
A& operator=(A&& o) {
|
||||||
s = std::move(o.s);
|
s = std::move(o.s);
|
||||||
return *this;
|
return *this;
|
||||||
@@ -581,7 +576,7 @@ Allows non-static data members to be initialized where they are declared, potent
|
|||||||
```c++
|
```c++
|
||||||
// Default initialization prior to C++11
|
// Default initialization prior to C++11
|
||||||
class Human {
|
class Human {
|
||||||
Human() : age(0) {}
|
Human() : age{0} {}
|
||||||
private:
|
private:
|
||||||
unsigned age;
|
unsigned age;
|
||||||
};
|
};
|
||||||
@@ -613,7 +608,7 @@ struct Foo {
|
|||||||
Bar getBar() const& { return bar; }
|
Bar getBar() const& { return bar; }
|
||||||
Bar getBar() && { return std::move(bar); }
|
Bar getBar() && { return std::move(bar); }
|
||||||
private:
|
private:
|
||||||
Bar bar{};
|
Bar bar;
|
||||||
};
|
};
|
||||||
|
|
||||||
Foo foo{};
|
Foo foo{};
|
||||||
@@ -908,8 +903,8 @@ int CountTwos(const T& container) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int> vec = {2,2,43,435,4543,534};
|
std::vector<int> vec = {2, 2, 43, 435, 4543, 534};
|
||||||
int arr[8] = {2,43,45,435,32,32,32,32};
|
int arr[8] = {2, 43, 45, 435, 32, 32, 32, 32};
|
||||||
auto a = CountTwos(vec); // 2
|
auto a = CountTwos(vec); // 2
|
||||||
auto b = CountTwos(arr); // 1
|
auto b = CountTwos(arr); // 1
|
||||||
```
|
```
|
||||||
|
|||||||
38
CPP17.md
38
CPP17.md
@@ -39,8 +39,8 @@ Automatic template argument deduction much like how it's done for functions, but
|
|||||||
template <typename T = float>
|
template <typename T = float>
|
||||||
struct MyContainer {
|
struct MyContainer {
|
||||||
T val;
|
T val;
|
||||||
MyContainer() : val() {}
|
MyContainer() : val{} {}
|
||||||
MyContainer(T val) : val(val) {}
|
MyContainer(T val) : val{val} {}
|
||||||
// ...
|
// ...
|
||||||
};
|
};
|
||||||
MyContainer c1 {1}; // OK MyContainer<int>
|
MyContainer c1 {1}; // OK MyContainer<int>
|
||||||
@@ -67,7 +67,7 @@ A fold expression performs a fold of a template parameter pack over a binary ope
|
|||||||
* An expression of the form `(... op e)` or `(e op ...)`, where `op` is a fold-operator and `e` is an unexpanded parameter pack, are called _unary folds_.
|
* An expression of the form `(... op e)` or `(e op ...)`, where `op` is a fold-operator and `e` is an unexpanded parameter pack, are called _unary folds_.
|
||||||
* An expression of the form `(e1 op ... op e2)`, where `op` are fold-operators, is called a _binary fold_. Either `e1` or `e2` is an unexpanded parameter pack, but not both.
|
* An expression of the form `(e1 op ... op e2)`, where `op` are fold-operators, is called a _binary fold_. Either `e1` or `e2` is an unexpanded parameter pack, but not both.
|
||||||
```c++
|
```c++
|
||||||
template<typename... Args>
|
template <typename... Args>
|
||||||
bool logicalAnd(Args... args) {
|
bool logicalAnd(Args... args) {
|
||||||
// Binary folding.
|
// Binary folding.
|
||||||
return (true && ... && args);
|
return (true && ... && args);
|
||||||
@@ -77,7 +77,7 @@ bool& b2 = b;
|
|||||||
logicalAnd(b, b2, true); // == true
|
logicalAnd(b, b2, true); // == true
|
||||||
```
|
```
|
||||||
```c++
|
```c++
|
||||||
template<typename... Args>
|
template <typename... Args>
|
||||||
auto sum(Args... args) {
|
auto sum(Args... args) {
|
||||||
// Unary folding.
|
// Unary folding.
|
||||||
return (... + args);
|
return (... + args);
|
||||||
@@ -89,9 +89,9 @@ sum(1.0, 2.0f, 3); // == 6.0
|
|||||||
Changes to `auto` deduction when used with the uniform initialization syntax. Previously, `auto x {3};` deduces a `std::initializer_list<int>`, which now deduces to `int`.
|
Changes to `auto` deduction when used with the uniform initialization syntax. Previously, `auto x {3};` deduces a `std::initializer_list<int>`, which now deduces to `int`.
|
||||||
```c++
|
```c++
|
||||||
auto x1 {1, 2, 3}; // error: not a single element
|
auto x1 {1, 2, 3}; // error: not a single element
|
||||||
auto x2 = {1, 2, 3}; // decltype(x2) is std::initializer_list<int>
|
auto x2 = {1, 2, 3}; // x2 is std::initializer_list<int>
|
||||||
auto x3 {3}; // decltype(x3) is int
|
auto x3 {3}; // x3 is int
|
||||||
auto x4 {3.0}; // decltype(x4) is double
|
auto x4 {3.0}; // x4 is double
|
||||||
```
|
```
|
||||||
|
|
||||||
### constexpr lambda
|
### constexpr lambda
|
||||||
@@ -153,10 +153,10 @@ S x2 = S{123}; // mov eax, dword ptr [.L_ZZ4mainE2x2]
|
|||||||
It can also be used to declare and define a static member variable, such that it does not need to be initialized in the source file.
|
It can also be used to declare and define a static member variable, such that it does not need to be initialized in the source file.
|
||||||
```c++
|
```c++
|
||||||
struct S {
|
struct S {
|
||||||
S() : id(count++) {}
|
S() : id{count++} {}
|
||||||
~S() {count--;}
|
~S() { count--; }
|
||||||
int id;
|
int id;
|
||||||
static inline int count{0}; // declare and initialize count to 0 within the class
|
static inline int count{0}; // declare and initialize count to 0 within the class
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -192,7 +192,7 @@ y; // == 0
|
|||||||
std::unordered_map<std::string, int> mapping {
|
std::unordered_map<std::string, int> mapping {
|
||||||
{"a", 1},
|
{"a", 1},
|
||||||
{"b", 2},
|
{"b", 2},
|
||||||
{"c", 3},
|
{"c", 3}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Destructure by reference.
|
// Destructure by reference.
|
||||||
@@ -372,14 +372,14 @@ Invoke a `Callable` object with parameters. Examples of `Callable` objects are `
|
|||||||
```c++
|
```c++
|
||||||
template <typename Callable>
|
template <typename Callable>
|
||||||
class Proxy {
|
class Proxy {
|
||||||
Callable c;
|
Callable c;
|
||||||
public:
|
public:
|
||||||
Proxy(Callable c): c(c) {}
|
Proxy(Callable c): c(c) {}
|
||||||
template <class... Args>
|
template <class... Args>
|
||||||
decltype(auto) operator()(Args&&... args) {
|
decltype(auto) operator()(Args&&... args) {
|
||||||
// ...
|
// ...
|
||||||
return std::invoke(c, std::forward<Args>(args)...);
|
return std::invoke(c, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
auto add = [](int x, int y) {
|
auto add = [](int x, int y) {
|
||||||
return x + y;
|
return x + y;
|
||||||
|
|||||||
73
README.md
73
README.md
@@ -281,7 +281,7 @@ auto f = []<typename T>(std::vector<T> v) {
|
|||||||
### Range-based for loop with initializer
|
### Range-based for loop with initializer
|
||||||
This feature simplifies common code patterns, helps keep scopes tight, and offers an elegant solution to a common lifetime problem.
|
This feature simplifies common code patterns, helps keep scopes tight, and offers an elegant solution to a common lifetime problem.
|
||||||
```c++
|
```c++
|
||||||
for (auto v = std::vector{1, 2, 3}; auto& e : v) {
|
for (std::vector v{1, 2, 3}; auto& e : v) {
|
||||||
std::cout << e;
|
std::cout << e;
|
||||||
}
|
}
|
||||||
// prints "123"
|
// prints "123"
|
||||||
@@ -324,8 +324,8 @@ Automatic template argument deduction much like how it's done for functions, but
|
|||||||
template <typename T = float>
|
template <typename T = float>
|
||||||
struct MyContainer {
|
struct MyContainer {
|
||||||
T val;
|
T val;
|
||||||
MyContainer() : val() {}
|
MyContainer() : val{} {}
|
||||||
MyContainer(T val) : val(val) {}
|
MyContainer(T val) : val{val} {}
|
||||||
// ...
|
// ...
|
||||||
};
|
};
|
||||||
MyContainer c1 {1}; // OK MyContainer<int>
|
MyContainer c1 {1}; // OK MyContainer<int>
|
||||||
@@ -352,7 +352,7 @@ A fold expression performs a fold of a template parameter pack over a binary ope
|
|||||||
* An expression of the form `(... op e)` or `(e op ...)`, where `op` is a fold-operator and `e` is an unexpanded parameter pack, are called _unary folds_.
|
* An expression of the form `(... op e)` or `(e op ...)`, where `op` is a fold-operator and `e` is an unexpanded parameter pack, are called _unary folds_.
|
||||||
* An expression of the form `(e1 op ... op e2)`, where `op` are fold-operators, is called a _binary fold_. Either `e1` or `e2` is an unexpanded parameter pack, but not both.
|
* An expression of the form `(e1 op ... op e2)`, where `op` are fold-operators, is called a _binary fold_. Either `e1` or `e2` is an unexpanded parameter pack, but not both.
|
||||||
```c++
|
```c++
|
||||||
template<typename... Args>
|
template <typename... Args>
|
||||||
bool logicalAnd(Args... args) {
|
bool logicalAnd(Args... args) {
|
||||||
// Binary folding.
|
// Binary folding.
|
||||||
return (true && ... && args);
|
return (true && ... && args);
|
||||||
@@ -362,7 +362,7 @@ bool& b2 = b;
|
|||||||
logicalAnd(b, b2, true); // == true
|
logicalAnd(b, b2, true); // == true
|
||||||
```
|
```
|
||||||
```c++
|
```c++
|
||||||
template<typename... Args>
|
template <typename... Args>
|
||||||
auto sum(Args... args) {
|
auto sum(Args... args) {
|
||||||
// Unary folding.
|
// Unary folding.
|
||||||
return (... + args);
|
return (... + args);
|
||||||
@@ -374,9 +374,9 @@ sum(1.0, 2.0f, 3); // == 6.0
|
|||||||
Changes to `auto` deduction when used with the uniform initialization syntax. Previously, `auto x {3};` deduces a `std::initializer_list<int>`, which now deduces to `int`.
|
Changes to `auto` deduction when used with the uniform initialization syntax. Previously, `auto x {3};` deduces a `std::initializer_list<int>`, which now deduces to `int`.
|
||||||
```c++
|
```c++
|
||||||
auto x1 {1, 2, 3}; // error: not a single element
|
auto x1 {1, 2, 3}; // error: not a single element
|
||||||
auto x2 = {1, 2, 3}; // decltype(x2) is std::initializer_list<int>
|
auto x2 = {1, 2, 3}; // x2 is std::initializer_list<int>
|
||||||
auto x3 {3}; // decltype(x3) is int
|
auto x3 {3}; // x3 is int
|
||||||
auto x4 {3.0}; // decltype(x4) is double
|
auto x4 {3.0}; // x4 is double
|
||||||
```
|
```
|
||||||
|
|
||||||
### constexpr lambda
|
### constexpr lambda
|
||||||
@@ -438,10 +438,10 @@ S x2 = S{123}; // mov eax, dword ptr [.L_ZZ4mainE2x2]
|
|||||||
It can also be used to declare and define a static member variable, such that it does not need to be initialized in the source file.
|
It can also be used to declare and define a static member variable, such that it does not need to be initialized in the source file.
|
||||||
```c++
|
```c++
|
||||||
struct S {
|
struct S {
|
||||||
S() : id(count++) {}
|
S() : id{count++} {}
|
||||||
~S() {count--;}
|
~S() { count--; }
|
||||||
int id;
|
int id;
|
||||||
static inline int count{0}; // declare and initialize count to 0 within the class
|
static inline int count{0}; // declare and initialize count to 0 within the class
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -477,7 +477,7 @@ y; // == 0
|
|||||||
std::unordered_map<std::string, int> mapping {
|
std::unordered_map<std::string, int> mapping {
|
||||||
{"a", 1},
|
{"a", 1},
|
||||||
{"b", 2},
|
{"b", 2},
|
||||||
{"c", 3},
|
{"c", 3}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Destructure by reference.
|
// Destructure by reference.
|
||||||
@@ -657,14 +657,14 @@ Invoke a `Callable` object with parameters. Examples of `Callable` objects are `
|
|||||||
```c++
|
```c++
|
||||||
template <typename Callable>
|
template <typename Callable>
|
||||||
class Proxy {
|
class Proxy {
|
||||||
Callable c;
|
Callable c;
|
||||||
public:
|
public:
|
||||||
Proxy(Callable c): c(c) {}
|
Proxy(Callable c): c(c) {}
|
||||||
template <class... Args>
|
template <class... Args>
|
||||||
decltype(auto) operator()(Args&&... args) {
|
decltype(auto) operator()(Args&&... args) {
|
||||||
// ...
|
// ...
|
||||||
return std::invoke(c, std::forward<Args>(args)...);
|
return std::invoke(c, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
auto add = [](int x, int y) {
|
auto add = [](int x, int y) {
|
||||||
return x + y;
|
return x + y;
|
||||||
@@ -1215,7 +1215,7 @@ constexpr const int& y = x; // error -- constexpr variable `y` must be initializ
|
|||||||
Constant expressions with classes:
|
Constant expressions with classes:
|
||||||
```c++
|
```c++
|
||||||
struct Complex {
|
struct Complex {
|
||||||
constexpr Complex(double r, double i) : re(r), im(i) { }
|
constexpr Complex(double r, double i) : re{r}, im{i} { }
|
||||||
constexpr double real() { return re; }
|
constexpr double real() { return re; }
|
||||||
constexpr double imag() { return im; }
|
constexpr double imag() { return im; }
|
||||||
|
|
||||||
@@ -1232,7 +1232,7 @@ Constructors can now call other constructors in the same class using an initiali
|
|||||||
```c++
|
```c++
|
||||||
struct Foo {
|
struct Foo {
|
||||||
int foo;
|
int foo;
|
||||||
Foo(int foo) : foo(foo) {}
|
Foo(int foo) : foo{foo} {}
|
||||||
Foo() : Foo(0) {}
|
Foo() : Foo(0) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1295,13 +1295,8 @@ struct C : B {
|
|||||||
|
|
||||||
Class cannot be inherited from.
|
Class cannot be inherited from.
|
||||||
```c++
|
```c++
|
||||||
struct A final {
|
struct A final {};
|
||||||
|
struct B : A {}; // error -- base 'A' is marked 'final'
|
||||||
};
|
|
||||||
|
|
||||||
struct B : A { // error -- base 'A' is marked 'final'
|
|
||||||
|
|
||||||
};
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Default functions
|
### Default functions
|
||||||
@@ -1309,7 +1304,7 @@ A more elegant, efficient way to provide a default implementation of a function,
|
|||||||
```c++
|
```c++
|
||||||
struct A {
|
struct A {
|
||||||
A() = default;
|
A() = default;
|
||||||
A(int x) : x(x) {}
|
A(int x) : x{x} {}
|
||||||
int x {1};
|
int x {1};
|
||||||
};
|
};
|
||||||
A a; // a.x == 1
|
A a; // a.x == 1
|
||||||
@@ -1319,7 +1314,7 @@ A a2 {123}; // a.x == 123
|
|||||||
With inheritance:
|
With inheritance:
|
||||||
```c++
|
```c++
|
||||||
struct B {
|
struct B {
|
||||||
B() : x(1) {}
|
B() : x{1} {}
|
||||||
int x;
|
int x;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1338,7 +1333,7 @@ class A {
|
|||||||
int x;
|
int x;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
A(int x) : x(x) {};
|
A(int x) : x{x} {};
|
||||||
A(const A&) = delete;
|
A(const A&) = delete;
|
||||||
A& operator=(const A&) = delete;
|
A& operator=(const A&) = delete;
|
||||||
};
|
};
|
||||||
@@ -1368,9 +1363,9 @@ The copy constructor and copy assignment operator are called when copies are mad
|
|||||||
```c++
|
```c++
|
||||||
struct A {
|
struct A {
|
||||||
std::string s;
|
std::string s;
|
||||||
A() : s("test") {}
|
A() : s{"test"} {}
|
||||||
A(const A& o) : s(o.s) {}
|
A(const A& o) : s{o.s} {}
|
||||||
A(A&& o) : s(std::move(o.s)) {}
|
A(A&& o) : s{std::move(o.s)} {}
|
||||||
A& operator=(A&& o) {
|
A& operator=(A&& o) {
|
||||||
s = std::move(o.s);
|
s = std::move(o.s);
|
||||||
return *this;
|
return *this;
|
||||||
@@ -1472,7 +1467,7 @@ Allows non-static data members to be initialized where they are declared, potent
|
|||||||
```c++
|
```c++
|
||||||
// Default initialization prior to C++11
|
// Default initialization prior to C++11
|
||||||
class Human {
|
class Human {
|
||||||
Human() : age(0) {}
|
Human() : age{0} {}
|
||||||
private:
|
private:
|
||||||
unsigned age;
|
unsigned age;
|
||||||
};
|
};
|
||||||
@@ -1505,7 +1500,7 @@ struct Foo {
|
|||||||
Bar getBar() && { return std::move(bar); }
|
Bar getBar() && { return std::move(bar); }
|
||||||
Bar getBar() const&& { return std::move(bar); }
|
Bar getBar() const&& { return std::move(bar); }
|
||||||
private:
|
private:
|
||||||
Bar bar{};
|
Bar bar;
|
||||||
};
|
};
|
||||||
|
|
||||||
Foo foo{};
|
Foo foo{};
|
||||||
@@ -1800,8 +1795,8 @@ int CountTwos(const T& container) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int> vec = {2,2,43,435,4543,534};
|
std::vector<int> vec = {2, 2, 43, 435, 4543, 534};
|
||||||
int arr[8] = {2,43,45,435,32,32,32,32};
|
int arr[8] = {2, 43, 45, 435, 32, 32, 32, 32};
|
||||||
auto a = CountTwos(vec); // 2
|
auto a = CountTwos(vec); // 2
|
||||||
auto b = CountTwos(arr); // 1
|
auto b = CountTwos(arr); // 1
|
||||||
```
|
```
|
||||||
|
|||||||
Reference in New Issue
Block a user