SlideShare a Scribd company logo
Timur Doumler
CoreHard Autumn Conference
30 November 2019
C++20:
The small things
@timur_audio
Version 1.4
C++20 the small things - Timur Doumler
C++20 the small things - Timur Doumler
C++20 the small things - Timur Doumler
we are here
C++20 the small things - Timur Doumler
C++20 the small things - Timur Doumler
C++20 the small things - Timur Doumler
C++20 the small things - Timur Doumler
C++20 the small things - Timur Doumler
11
1 Initialisation
2 Structured bindings
3 Lambdas
4 Templates
5 constexpr
6 Miscellaneous
12
1 Initialisation
2 Structured bindings
3 Lambdas
4 Templates
5 constexpr
6 Miscellaneous
Aggregates
13
struct Widget {
int a;
bool b;
int c;
};
Aggregates
14
struct Widget {
int a;
bool b;
int c;
};
int main() {
Widget widget = {3, true};
}
Designated initialisers
15
struct Widget {
int a;
bool b;
int c;
};
int main() {
Widget widget{.a = 3, .c = 7};
}
16
struct Widget {
int a;
bool b;
int c;
};
int main() {
Widget widget{.a = 3, .c = 7};
}
Only for aggregate types.
C compatibility feature.
Works like in C99, except:
• not out-of-order
Widget widget{.c = 7, .a = 3} // Error
• not nested
Widget widget{.c.e = 7} // Error
• not mixed with regular initialisers
Widget widget{.a = 3, 7} // Error
• not with arrays
int arr[3]{.[1] = 7} // Error
Designated initialisers
17
18
Aggregates can no longer declare constructors
19
struct Widget {
Widget() = delete;
};
Widget w1; // Error
Aggregates can no longer declare constructors
20
struct Widget {
Widget() = delete;
};
Widget w1; // Error
Widget w2{}; // OK in C++17!
Aggregates can no longer declare constructors
21
struct Widget {
Widget() = delete;
};
Widget w1; // Error
Widget w2{}; // OK in C++17! Will be error in C++20
Aggregates can no longer declare constructors
• Does not work with macros:
22
assert(Widget(2, 3)); // OK
C++17 problems with aggregate initialisation:
• Does not work with macros:
23
assert(Widget(2, 3)); // OK
assert(Widget{2, 3}); // Error: this breaks the preprocessor :(
C++17 problems with aggregate initialisation:
• Does not work with macros:
• Can’t do perfect forwarding in templates
• can’t write emplace or make_unique that works for aggregates :(
24
assert(Widget(2, 3)); // OK
assert(Widget{2, 3}); // Error: this breaks the preprocessor :(
C++17 problems with aggregate initialisation:
25
struct Widget {
int i;
int j;
};
Widget widget(1, 2); // will work in C++20!
C++20: Direct-initialisation of aggregates
26
struct Widget {
int i;
int j;
};
Widget widget(1, 2); // will work in C++20!
int arr[3](0, 1, 2); // will work in C++20!
C++20: Direct-initialisation of aggregates
27
struct Widget {
int i;
int j;
};
Widget widget(1, 2); // will work in C++20!
int arr[3](0, 1, 2); // will work in C++20!
So in C++20, (args) and {args} will do the same thing!
Except:
• () does not call std::initializer_list constructors
• {} does not allow narrowing conversions
C++20: Direct-initialisation of aggregates
28
struct Colour
{
Colour(int r, int g, int b) noexcept;
};
constinit
29
struct Colour
{
Colour(int r, int g, int b) noexcept;
};
namespace Colours
{
const Colour red = {255, 0, 0};
}
constinit
30
struct Colour
{
Colour(int r, int g, int b) noexcept;
};
namespace Colours
{
const Colour red = {255, 0, 0}; // dynamic initialisation
}
constinit
31
struct Colour
{
Colour(int r, int g, int b) noexcept;
};
namespace Colours
{
const Colour red = {255, 0, 0}; // dynamic initialisation
} // -> initialisation order fiasco -> UB :(
constinit
32
struct Colour
{
constexpr Colour(int r, int g, int b) noexcept;
};
namespace Colours
{
constexpr Colour red = {255, 0, 0};
}
constinit
33
struct Colour
{
constexpr Colour(int r, int g, int b) noexcept;
};
namespace Colours
{
constexpr Colour red = {255, 0, 0}; // constant initialisation :)
}
constinit
struct Colour
{
constexpr Colour(int r, int g, int b) noexcept;
};
namespace Colours
{
Colour backgroundColour = getBackgroundColour();
}
34
constinit
struct Colour
{
constexpr Colour(int r, int g, int b) noexcept;
};
namespace Colours
{
Colour backgroundColour = getBackgroundColour(); // const or dynamic init?
}
35
constinit
struct Colour
{
constexpr Colour(int r, int g, int b) noexcept;
};
namespace Colours
{
constinit Colour backgroundColour = getBackgroundColour();
}
36
constinit
37
constinit
struct Colour
{
constexpr Colour(int r, int g, int b) noexcept;
};
namespace Colours
{
constinit Colour backgroundColour = getBackgroundColour();
} // ^^^^^^ only compiles if init happens at compile time :)
Database getDatabase();
for (auto&& user : getDatabase().getUsers())
{
registerUser(user);
}
38
Range-based for with initialiser
C++17
Database getDatabase();
for (auto&& user : getDatabase().getUsers()) // maybe undefined behaviour!
{
registerUser(user);
}
39
Range-based for with initialiser
C++17
Database getDatabase();
auto db = getDatabase();
for (auto&& user : db.getUsers())
{
registerUser(user);
}
40
Range-based for with initialiser
C++17
Database getDatabase();
{
auto db = getDatabase();
for (auto&& user : db.getUsers())
{
registerUser(user);
}
}
41
Range-based for with initialiser
C++17
42
Range-based for with initialiser
Database getDatabase();
for (auto db = getDatabase(); auto&& user : db.getUsers())
{
registerUser(user);
}
C++20
43
1 Initialisation
2 Structured bindings
3 Lambdas
4 Templates
5 constexpr
6 Miscellaneous
44
struct Widget
{
int i;
bool b;
};
auto [a, b] = getWidget();
45
struct Widget
{
int i;
bool b;
};
auto [a, b] = getWidget();
static [a, b] = getWidget(); // Error in C++17
thread_local [a, b] = getWidget(); // Error in C++17
46
struct Widget
{
int i;
bool b;
};
auto [a, b] = getWidget();
static [a, b] = getWidget(); // OK in C++20
thread_local [a, b] = getWidget(); // OK in C++20
47
struct Widget
{
int i;
bool b;
};
auto [a, b] = getWidget();
auto f = [a]{ return a > 0; }; // Error in C++17:
// capture ‘a’ does not name a variable
48
struct Widget
{
int i;
bool b;
};
auto [a, b] = getWidget();
auto f = [a]{ return a > 0; }; // OK in C++20
49
struct Widget
{
int i;
bool b;
};
auto [a, b] = getWidget();
auto f = [a]{ return a > 0; }; // OK in C++20
// copies ‘a’, not the whole object
50
1 Initialisation
2 Structured bindings
3 Lambdas
4 Templates
5 constexpr
6 Miscellaneous
template<class F, class... Args>
auto delay_invoke(F f, Args... args) {
return [f = std::move(f), ...args = std::move(args)]() -> decltype(auto) {
return std::invoke(f, args...);
};
}
51
C++20: pack expansion allowed in lambda init capture
52
– Lambdas are allowed in unevaluated contexts
– Lambdas (without captures) are default-constructible
and assignable
More C++20 lambda features:
53
– Lambdas are allowed in unevaluated contexts
– Lambdas (without captures) are default-constructible
and assignable
More C++20 lambda features:
decltype([]{})
54
– Lambdas are allowed in unevaluated contexts
– Lambdas (without captures) are default-constructible
and assignable
More C++20 lambda features:
decltype([]{}) f;
55
– Lambdas are allowed in unevaluated contexts
– Lambdas (without captures) are default-constructible
and assignable
More C++20 lambda features:
class Widget
{
decltype([]{}) f;
};
56
template <typename T>
using MyPtr = std::unique_ptr<
T, decltype([](T* t) { myDeleter(t); })>;
MyPtr<Widget> ptr;
57
template <typename T>
using MyPtr = std::unique_ptr<
T, decltype([](T* t) { myDeleter(t); })>;
MyPtr<Widget> ptr;
using WidgetSet = std::set<
Widget,
decltype([](Widget& lhs, Widget& rhs) { return lhs.x < rhs.x; })>;
WidgetSet widgets;
58
Generic lambdas / functions
auto f = [](auto a){
return a * a;
};
59
auto f = [](auto a){
return a * a;
};
auto f(auto a) { // Generic *functions* – OK since C++20 :)
return a * a;
}
Generic lambdas / functions
60
template <typename T>
void f(std::vector<T> vector) {
// ...
}
Generic lambdas / functions
61
template <typename T>
void f(std::vector<T> vector) {
// ...
}
// C++20:
auto f = []<typename T>(std::vector<T> vector) {
// ...
};
Generic lambdas / functions
62
1 Initialisation
2 Structured bindings
3 Lambdas
4 Templates
5 constexpr
6 Miscellaneous
63
Non-type template parameters (NTTPs)
64
Non-type template parameters (NTTPs)
template <int size>
struct Widget
{
std::array<int, size> a;
};
65
Non-type template parameters (NTTPs)
template <int size>
struct Widget
{
std::array<int, size> a;
};
66
C++20: floating-point NTTPs
template <double x>
struct Filter
{
std::array<double, 2> coefficients = {x, 0.5 * x * x};
// stuff...
};
67
C++20: class-type NTTPs
struct Coefficients
{
double x;
double y;
};
68
C++20: class-type NTTPs
struct Coefficients
{
double x;
double y;
};
template <Coefficients coeffs>
struct Filter
{
// stuff :)
};
69
C++20: class-type NTTPs
struct Coefficients
{
double x;
double y;
};
template <Coefficients coeffs>
struct Filter
{
// stuff :)
};
constexpr Filter<Coefficients{1, 0.125}> f;
70
CTAD
71
CTAD
std::vector v = {1, 2, 3}; // std::vector<int>
72
CTAD
std::vector v = {1, 2, 3}; // std::vector<int>
std::tuple t = {42, 0.5, true}; // std::tuple<int, double, bool>
73
CTAD
std::vector v = {1, 2, 3}; // std::vector<int>
std::tuple t = {42, 0.5, true}; // std::tuple<int, double, bool>
std::scoped_lock lock(rtmutex); // std::scoped_lock<std::recursive_timed_mutex>
74
C++20 adds:
– CTAD for aggregates
– CTAD for alias templates
75
template <typename T, typename U>
struct aggr_pair
{
T t;
U u;
};
aggr_pair p = {1, true}; // Error: no deduction candidate found
C++17
76
template <typename T, typename U>
struct aggr_pair
{
T t;
U u;
};
template <typename T, typename U>
aggr_pair(T, U) -> aggr_pair<T, U>;
aggr_pair p = {1, true}; // OK
C++17
77
template <typename T, typename U>
struct aggr_pair
{
T t;
U u;
};
template <typename T, typename U>
aggr_pair(T, U) -> aggr_pair<T, U>;
aggr_pair p = {1, true}; // OK
C++17 C++20
template <typename T, typename U>
struct aggr_pair
{
T t;
U u;
};
aggr_pair p = {1, true}; // OK
78
template<typename... Bases>
struct overloaded : Bases...
{
using Bases::operator()...;
};
C++17
79
template<typename... Bases>
struct overloaded : Bases...
{
using Bases::operator()...;
};
template<typename... Bases>
overloaded(Bases...) -> overloaded<Bases...>;
C++17
80
template<typename... Bases>
struct overloaded : Bases...
{
using Bases::operator()...;
};
template<typename... Bases>
overloaded(Bases...) -> overloaded<Bases...>;
overloaded printer = {
[](auto arg) { std::cout << arg << ' '; },
[](double arg) { std::cout << std::fixed << arg << ' '; },
[](const char* arg) { std::cout << std::quoted(arg) << ' '; }
};
C++17
template<typename... Bases>
struct overloaded : Bases...
{
using Bases::operator()...;
};
template<typename... Bases>
overloaded(Bases...) -> overloaded<Bases...>;
overloaded printer = {
[](auto arg) { std::cout << arg << ' '; },
[](double arg) { std::cout << std::fixed << arg << ' '; },
[](const char* arg) { std::cout << std::quoted(arg) << ' '; }
};
int main()
{
printer("Hello, World!");
}
81
C++17
82
template<typename... Bases>
struct overloaded : Bases...
{
using Bases::operator()...;
};
template<typename... Bases>
overloaded(Bases...) -> overloaded<Bases...>;
overloaded printer = {
[](auto arg) { std::cout << arg << ' '; },
[](double arg) { std::cout << std::fixed << arg << ' '; },
[](const char* arg) { std::cout << std::quoted(arg) << ' '; }
};
int main()
{
printer("Hello, World!");
}
C++17
template<typename... Bases>
struct overloaded : Bases...
{
using Bases::operator()...;
};
overloaded printer = {
[](auto arg) { std::cout << arg << ' '; },
[](double arg) { std::cout << std::fixed << arg << ' '; },
[](const char* arg) { std::cout << std::quoted(arg) << ' '; }
};
int main()
{
printer("Hello, World!");
}
83
C++20
84
namespace pmr {
template <class T>
using vector = std::vector<T, std::pmr::polymorphic_allocator<T>>;
}
C++17
std::pmr::vector<int> v{1, 2, 3};
85
namespace pmr {
template <class T>
using vector = std::vector<T, std::pmr::polymorphic_allocator<T>>;
}
C++17 C++20
std::pmr::vector<int> v{1, 2, 3}; std::pmr::vector v{1, 2, 3};
86
1 Initialisation
2 Structured bindings
3 Lambdas
4 Templates
5 constexpr
6 Miscellaneous
87
In C++20, in a constexpr function you can:
– have a try-block
– have an unevaluated asm block
– use a union
– call virtual functions
– dynamic_cast and typeid
– new and delete
88
Daveed Vandevoorde
“C++ Constants”
C++Now 2019 keynote
Louis Dionne
"Compile-time programming and
reflection in C++20 and beyond”
CppCon 2018 talk
89
“running” code at compile time
int square(int i) {
return i * i;
}
90
“running” code at compile time
constexpr int square(int i) {
return i * i;
}
square(3); // compile time
square(x); // runtime
consteval int square(int i) {
return i * i;
}
square(3); // compile time
square(x); // Error - x is not a compile-time constant!
91
“running” code at compile time
92
compile time or runtime?
int square(int i) {
return __magic_fast_square(i); // contains runtime magic
}
square(3); // runtime, fast magic
square(x); // runtime, fast magic
93
compile time or runtime?
constexpr int square(int i) {
return i * i;
}
square(3); // compile time
square(x); // runtime, no fast magic :(
94
compile time or runtime?
constexpr int square(int i) {
if (std::is_constant_evaluated()) {
return i * i;
}
else {
return __magic_fast_square(i);
}
}
square(3); // compile time
square(x); // runtime, fast magic :)
constexpr int square(int i) {
if (std::is_constant_evaluated()) {
return i * i;
}
else {
return __magic_fast_square(i);
}
}
square(3); // compile time
square(x); // runtime, fast magic :)
95
compile time or runtime?
96
1 Initialisation
2 Structured bindings
3 Lambdas
4 Templates
5 constexpr
6 Miscellaneous
97
template <typename Container>
auto findFirstValid(const Container& c) -> Container::iterator
{
return std::find_if(c.begin(), c.end(), [](auto elem){ return elem.is_valid(); });
}
98
template <typename Container>
auto findFirstValid(const Container& c) -> Container::const_iterator
{
return std::find_if(c.begin(), c.end(), [](auto elem){ return elem.is_valid(); });
}
// Error: missing 'typename' prior to dependent type name ‘Container::const_iterator'
99
template <typename Container>
auto findFirstValid(const Container& c) -> Container::const_iterator
{
return std::find_if(c.begin(), c.end(), [](auto elem){ return elem.is_valid(); });
}
// OK in C++20 :)
100
New attributes in C++20
101
– [[likely]], [[unlikely]]
New attributes in C++20
102
– [[likely]], [[unlikely]]
– [[no_unique_address]]
New attributes in C++20
103
– [[likely]], [[unlikely]]
– [[no_unique_address]]
– [[nodiscard]] on constructors
New attributes in C++20
104
– [[likely]], [[unlikely]]
– [[no_unique_address]]
– [[nodiscard]] on constructors
– [[nodiscard(“can have a message”)]]
New attributes in C++20
enum class rgba_color_channel {
red,
green,
blue,
alpha
};
105
Using enum
enum class rgba_color_channel {
red,
green,
blue,
alpha
};
std::string_view to_string(rgba_color_channel channel) {
switch (channel) {
case rgba_color_channel::red: return "red";
case rgba_color_channel::green: return "green";
case rgba_color_channel::blue: return "blue";
case rgba_color_channel::alpha: return "alpha";
}
}
106
Using enum
107
Using enum
enum class rgba_color_channel {
red,
green,
blue,
alpha
};
std::string_view to_string(rgba_color_channel channel) {
switch (channel) {
case rgba_color_channel::red: return "red";
case rgba_color_channel::green: return "green";
case rgba_color_channel::blue: return "blue";
case rgba_color_channel::alpha: return "alpha";
}
}
enum class rgba_color_channel {
red,
green,
blue,
alpha
};
std::string_view to_string(rgba_color_channel channel) {
switch (channel) {
using enum rgba_color_channel;
case red: return "red";
case green: return "green";
case blue: return "blue";
case alpha: return "alpha";
}
}
108
Using enum
enum class Suit {
diamonds,
hearts,
spades,
clubs
};
class Card {
using enum Suit;
Suit suit = spades;
};
109
Using enum
110
Built-in UTF-8 char type
int main() {
const char* str = u8" 🦄 🌈"; // C++17...
}
111
Built-in UTF-8 char type
int main() {
const char* str = u8" 🦄 🌈"; // compile error in C++20!
}
int main() {
const char8_t* str = u8" 🦄 🌈";
}
112
Built-in UTF-8 char type
we are here
Timur Doumler
CoreHard Autumn Conference
30 November 2019
C++20:
The small things
@timur_audio
Version 1.4

More Related Content

PPTX
C++17 std::filesystem - Overview
PDF
Memory Leak In java
PPTX
Angular Data Binding
PPTX
Android Training (Storing data using SQLite)
PPTX
qemu + gdb + sample_code: Run sample code in QEMU OS and observe Linux Kernel...
PDF
Java 8 Lambda Built-in Functional Interfaces
PDF
Design and Concepts of Android Graphics
PPS
Java rmi example program with code
C++17 std::filesystem - Overview
Memory Leak In java
Angular Data Binding
Android Training (Storing data using SQLite)
qemu + gdb + sample_code: Run sample code in QEMU OS and observe Linux Kernel...
Java 8 Lambda Built-in Functional Interfaces
Design and Concepts of Android Graphics
Java rmi example program with code

What's hot (20)

PPTX
.NET Oxford Windows Subsystem for Linux v2
PDF
Spring Security
PDF
Vulkan 1.1 Reference Guide
PDF
Valgrind tutorial
PDF
Functional programming with Java 8
PDF
Git - An Introduction
PPT
PDF
eBPF/XDP
PDF
Apache Sling : JCR, OSGi, Scripting and REST
PDF
Linux Profiling at Netflix
PPS
Wrapper class
PPTX
Google V8 engine
PDF
Introduction to Go programming language
PDF
XilinxのxsimでSoftware Driven Verification.pdf
PDF
Angular - Chapter 4 - Data and Event Handling
PDF
Golang Channels
PPTX
Implicit object.pptx
PDF
Spring Framework - AOP
PPTX
Android Binder: Deep Dive
PPTX
Golang - Overview of Go (golang) Language
.NET Oxford Windows Subsystem for Linux v2
Spring Security
Vulkan 1.1 Reference Guide
Valgrind tutorial
Functional programming with Java 8
Git - An Introduction
eBPF/XDP
Apache Sling : JCR, OSGi, Scripting and REST
Linux Profiling at Netflix
Wrapper class
Google V8 engine
Introduction to Go programming language
XilinxのxsimでSoftware Driven Verification.pdf
Angular - Chapter 4 - Data and Event Handling
Golang Channels
Implicit object.pptx
Spring Framework - AOP
Android Binder: Deep Dive
Golang - Overview of Go (golang) Language
Ad

Similar to C++20 the small things - Timur Doumler (20)

PPT
Whats new in_csharp4
PDF
COSCUP2023 RSA256 Verilator.pdf
ODP
Java Generics
PPTX
Applying Compiler Techniques to Iterate At Blazing Speed
PDF
C++ amp on linux
PPTX
C++ 11 Features
PPTX
week14Pointers_II. pointers pemrograman dasar C++.pptx
PPTX
How to Adopt Modern C++17 into Your C++ Code
PPTX
How to Adopt Modern C++17 into Your C++ Code
PDF
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2
PDF
Boosting Developer Productivity with Clang
PPT
Lecture5
PPTX
C# 6.0 Preview
ODP
Java 5 6 Generics, Concurrency, Garbage Collection, Tuning
DOCX
20145-5SumII_CSC407_assign1.htmlCSC 407 Computer Systems II.docx
PPT
Cpp tutorial
PDF
Analysis of Microsoft Code Contracts
PPT
data Structure Lecture 1
PDF
.gradle 파일 정독해보기
PDF
Introduction to cython: example of GCoptimization
Whats new in_csharp4
COSCUP2023 RSA256 Verilator.pdf
Java Generics
Applying Compiler Techniques to Iterate At Blazing Speed
C++ amp on linux
C++ 11 Features
week14Pointers_II. pointers pemrograman dasar C++.pptx
How to Adopt Modern C++17 into Your C++ Code
How to Adopt Modern C++17 into Your C++ Code
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2
Boosting Developer Productivity with Clang
Lecture5
C# 6.0 Preview
Java 5 6 Generics, Concurrency, Garbage Collection, Tuning
20145-5SumII_CSC407_assign1.htmlCSC 407 Computer Systems II.docx
Cpp tutorial
Analysis of Microsoft Code Contracts
data Structure Lecture 1
.gradle 파일 정독해보기
Introduction to cython: example of GCoptimization
Ad

More from corehard_by (20)

PPTX
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
PPTX
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
PDF
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
PPTX
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
PPTX
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
PPTX
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
PPTX
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
PPTX
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
PPTX
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
PPTX
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
PDF
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
PPTX
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
PPTX
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
PDF
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
PDF
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
PDF
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
PDF
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
PPTX
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
PDF
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019
PDF
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019

Recently uploaded (20)

PPTX
Machine Learning_overview_presentation.pptx
PDF
Accuracy of neural networks in brain wave diagnosis of schizophrenia
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PDF
NewMind AI Weekly Chronicles - August'25-Week II
PDF
gpt5_lecture_notes_comprehensive_20250812015547.pdf
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PDF
Getting Started with Data Integration: FME Form 101
PDF
Encapsulation theory and applications.pdf
PPT
Teaching material agriculture food technology
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PPTX
A Presentation on Artificial Intelligence
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PDF
MIND Revenue Release Quarter 2 2025 Press Release
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PPTX
Spectroscopy.pptx food analysis technology
PPTX
MYSQL Presentation for SQL database connectivity
Machine Learning_overview_presentation.pptx
Accuracy of neural networks in brain wave diagnosis of schizophrenia
“AI and Expert System Decision Support & Business Intelligence Systems”
NewMind AI Weekly Chronicles - August'25-Week II
gpt5_lecture_notes_comprehensive_20250812015547.pdf
20250228 LYD VKU AI Blended-Learning.pptx
Per capita expenditure prediction using model stacking based on satellite ima...
Network Security Unit 5.pdf for BCA BBA.
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...
Diabetes mellitus diagnosis method based random forest with bat algorithm
Getting Started with Data Integration: FME Form 101
Encapsulation theory and applications.pdf
Teaching material agriculture food technology
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
A Presentation on Artificial Intelligence
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
MIND Revenue Release Quarter 2 2025 Press Release
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
Spectroscopy.pptx food analysis technology
MYSQL Presentation for SQL database connectivity

C++20 the small things - Timur Doumler

  • 1. Timur Doumler CoreHard Autumn Conference 30 November 2019 C++20: The small things @timur_audio Version 1.4
  • 11. 11 1 Initialisation 2 Structured bindings 3 Lambdas 4 Templates 5 constexpr 6 Miscellaneous
  • 12. 12 1 Initialisation 2 Structured bindings 3 Lambdas 4 Templates 5 constexpr 6 Miscellaneous
  • 13. Aggregates 13 struct Widget { int a; bool b; int c; };
  • 14. Aggregates 14 struct Widget { int a; bool b; int c; }; int main() { Widget widget = {3, true}; }
  • 15. Designated initialisers 15 struct Widget { int a; bool b; int c; }; int main() { Widget widget{.a = 3, .c = 7}; }
  • 16. 16 struct Widget { int a; bool b; int c; }; int main() { Widget widget{.a = 3, .c = 7}; } Only for aggregate types. C compatibility feature. Works like in C99, except: • not out-of-order Widget widget{.c = 7, .a = 3} // Error • not nested Widget widget{.c.e = 7} // Error • not mixed with regular initialisers Widget widget{.a = 3, 7} // Error • not with arrays int arr[3]{.[1] = 7} // Error Designated initialisers
  • 17. 17
  • 18. 18 Aggregates can no longer declare constructors
  • 19. 19 struct Widget { Widget() = delete; }; Widget w1; // Error Aggregates can no longer declare constructors
  • 20. 20 struct Widget { Widget() = delete; }; Widget w1; // Error Widget w2{}; // OK in C++17! Aggregates can no longer declare constructors
  • 21. 21 struct Widget { Widget() = delete; }; Widget w1; // Error Widget w2{}; // OK in C++17! Will be error in C++20 Aggregates can no longer declare constructors
  • 22. • Does not work with macros: 22 assert(Widget(2, 3)); // OK C++17 problems with aggregate initialisation:
  • 23. • Does not work with macros: 23 assert(Widget(2, 3)); // OK assert(Widget{2, 3}); // Error: this breaks the preprocessor :( C++17 problems with aggregate initialisation:
  • 24. • Does not work with macros: • Can’t do perfect forwarding in templates • can’t write emplace or make_unique that works for aggregates :( 24 assert(Widget(2, 3)); // OK assert(Widget{2, 3}); // Error: this breaks the preprocessor :( C++17 problems with aggregate initialisation:
  • 25. 25 struct Widget { int i; int j; }; Widget widget(1, 2); // will work in C++20! C++20: Direct-initialisation of aggregates
  • 26. 26 struct Widget { int i; int j; }; Widget widget(1, 2); // will work in C++20! int arr[3](0, 1, 2); // will work in C++20! C++20: Direct-initialisation of aggregates
  • 27. 27 struct Widget { int i; int j; }; Widget widget(1, 2); // will work in C++20! int arr[3](0, 1, 2); // will work in C++20! So in C++20, (args) and {args} will do the same thing! Except: • () does not call std::initializer_list constructors • {} does not allow narrowing conversions C++20: Direct-initialisation of aggregates
  • 28. 28 struct Colour { Colour(int r, int g, int b) noexcept; }; constinit
  • 29. 29 struct Colour { Colour(int r, int g, int b) noexcept; }; namespace Colours { const Colour red = {255, 0, 0}; } constinit
  • 30. 30 struct Colour { Colour(int r, int g, int b) noexcept; }; namespace Colours { const Colour red = {255, 0, 0}; // dynamic initialisation } constinit
  • 31. 31 struct Colour { Colour(int r, int g, int b) noexcept; }; namespace Colours { const Colour red = {255, 0, 0}; // dynamic initialisation } // -> initialisation order fiasco -> UB :( constinit
  • 32. 32 struct Colour { constexpr Colour(int r, int g, int b) noexcept; }; namespace Colours { constexpr Colour red = {255, 0, 0}; } constinit
  • 33. 33 struct Colour { constexpr Colour(int r, int g, int b) noexcept; }; namespace Colours { constexpr Colour red = {255, 0, 0}; // constant initialisation :) } constinit
  • 34. struct Colour { constexpr Colour(int r, int g, int b) noexcept; }; namespace Colours { Colour backgroundColour = getBackgroundColour(); } 34 constinit
  • 35. struct Colour { constexpr Colour(int r, int g, int b) noexcept; }; namespace Colours { Colour backgroundColour = getBackgroundColour(); // const or dynamic init? } 35 constinit
  • 36. struct Colour { constexpr Colour(int r, int g, int b) noexcept; }; namespace Colours { constinit Colour backgroundColour = getBackgroundColour(); } 36 constinit
  • 37. 37 constinit struct Colour { constexpr Colour(int r, int g, int b) noexcept; }; namespace Colours { constinit Colour backgroundColour = getBackgroundColour(); } // ^^^^^^ only compiles if init happens at compile time :)
  • 38. Database getDatabase(); for (auto&& user : getDatabase().getUsers()) { registerUser(user); } 38 Range-based for with initialiser C++17
  • 39. Database getDatabase(); for (auto&& user : getDatabase().getUsers()) // maybe undefined behaviour! { registerUser(user); } 39 Range-based for with initialiser C++17
  • 40. Database getDatabase(); auto db = getDatabase(); for (auto&& user : db.getUsers()) { registerUser(user); } 40 Range-based for with initialiser C++17
  • 41. Database getDatabase(); { auto db = getDatabase(); for (auto&& user : db.getUsers()) { registerUser(user); } } 41 Range-based for with initialiser C++17
  • 42. 42 Range-based for with initialiser Database getDatabase(); for (auto db = getDatabase(); auto&& user : db.getUsers()) { registerUser(user); } C++20
  • 43. 43 1 Initialisation 2 Structured bindings 3 Lambdas 4 Templates 5 constexpr 6 Miscellaneous
  • 44. 44 struct Widget { int i; bool b; }; auto [a, b] = getWidget();
  • 45. 45 struct Widget { int i; bool b; }; auto [a, b] = getWidget(); static [a, b] = getWidget(); // Error in C++17 thread_local [a, b] = getWidget(); // Error in C++17
  • 46. 46 struct Widget { int i; bool b; }; auto [a, b] = getWidget(); static [a, b] = getWidget(); // OK in C++20 thread_local [a, b] = getWidget(); // OK in C++20
  • 47. 47 struct Widget { int i; bool b; }; auto [a, b] = getWidget(); auto f = [a]{ return a > 0; }; // Error in C++17: // capture ‘a’ does not name a variable
  • 48. 48 struct Widget { int i; bool b; }; auto [a, b] = getWidget(); auto f = [a]{ return a > 0; }; // OK in C++20
  • 49. 49 struct Widget { int i; bool b; }; auto [a, b] = getWidget(); auto f = [a]{ return a > 0; }; // OK in C++20 // copies ‘a’, not the whole object
  • 50. 50 1 Initialisation 2 Structured bindings 3 Lambdas 4 Templates 5 constexpr 6 Miscellaneous
  • 51. template<class F, class... Args> auto delay_invoke(F f, Args... args) { return [f = std::move(f), ...args = std::move(args)]() -> decltype(auto) { return std::invoke(f, args...); }; } 51 C++20: pack expansion allowed in lambda init capture
  • 52. 52 – Lambdas are allowed in unevaluated contexts – Lambdas (without captures) are default-constructible and assignable More C++20 lambda features:
  • 53. 53 – Lambdas are allowed in unevaluated contexts – Lambdas (without captures) are default-constructible and assignable More C++20 lambda features: decltype([]{})
  • 54. 54 – Lambdas are allowed in unevaluated contexts – Lambdas (without captures) are default-constructible and assignable More C++20 lambda features: decltype([]{}) f;
  • 55. 55 – Lambdas are allowed in unevaluated contexts – Lambdas (without captures) are default-constructible and assignable More C++20 lambda features: class Widget { decltype([]{}) f; };
  • 56. 56 template <typename T> using MyPtr = std::unique_ptr< T, decltype([](T* t) { myDeleter(t); })>; MyPtr<Widget> ptr;
  • 57. 57 template <typename T> using MyPtr = std::unique_ptr< T, decltype([](T* t) { myDeleter(t); })>; MyPtr<Widget> ptr; using WidgetSet = std::set< Widget, decltype([](Widget& lhs, Widget& rhs) { return lhs.x < rhs.x; })>; WidgetSet widgets;
  • 58. 58 Generic lambdas / functions auto f = [](auto a){ return a * a; };
  • 59. 59 auto f = [](auto a){ return a * a; }; auto f(auto a) { // Generic *functions* – OK since C++20 :) return a * a; } Generic lambdas / functions
  • 60. 60 template <typename T> void f(std::vector<T> vector) { // ... } Generic lambdas / functions
  • 61. 61 template <typename T> void f(std::vector<T> vector) { // ... } // C++20: auto f = []<typename T>(std::vector<T> vector) { // ... }; Generic lambdas / functions
  • 62. 62 1 Initialisation 2 Structured bindings 3 Lambdas 4 Templates 5 constexpr 6 Miscellaneous
  • 64. 64 Non-type template parameters (NTTPs) template <int size> struct Widget { std::array<int, size> a; };
  • 65. 65 Non-type template parameters (NTTPs) template <int size> struct Widget { std::array<int, size> a; };
  • 66. 66 C++20: floating-point NTTPs template <double x> struct Filter { std::array<double, 2> coefficients = {x, 0.5 * x * x}; // stuff... };
  • 67. 67 C++20: class-type NTTPs struct Coefficients { double x; double y; };
  • 68. 68 C++20: class-type NTTPs struct Coefficients { double x; double y; }; template <Coefficients coeffs> struct Filter { // stuff :) };
  • 69. 69 C++20: class-type NTTPs struct Coefficients { double x; double y; }; template <Coefficients coeffs> struct Filter { // stuff :) }; constexpr Filter<Coefficients{1, 0.125}> f;
  • 71. 71 CTAD std::vector v = {1, 2, 3}; // std::vector<int>
  • 72. 72 CTAD std::vector v = {1, 2, 3}; // std::vector<int> std::tuple t = {42, 0.5, true}; // std::tuple<int, double, bool>
  • 73. 73 CTAD std::vector v = {1, 2, 3}; // std::vector<int> std::tuple t = {42, 0.5, true}; // std::tuple<int, double, bool> std::scoped_lock lock(rtmutex); // std::scoped_lock<std::recursive_timed_mutex>
  • 74. 74 C++20 adds: – CTAD for aggregates – CTAD for alias templates
  • 75. 75 template <typename T, typename U> struct aggr_pair { T t; U u; }; aggr_pair p = {1, true}; // Error: no deduction candidate found C++17
  • 76. 76 template <typename T, typename U> struct aggr_pair { T t; U u; }; template <typename T, typename U> aggr_pair(T, U) -> aggr_pair<T, U>; aggr_pair p = {1, true}; // OK C++17
  • 77. 77 template <typename T, typename U> struct aggr_pair { T t; U u; }; template <typename T, typename U> aggr_pair(T, U) -> aggr_pair<T, U>; aggr_pair p = {1, true}; // OK C++17 C++20 template <typename T, typename U> struct aggr_pair { T t; U u; }; aggr_pair p = {1, true}; // OK
  • 78. 78 template<typename... Bases> struct overloaded : Bases... { using Bases::operator()...; }; C++17
  • 79. 79 template<typename... Bases> struct overloaded : Bases... { using Bases::operator()...; }; template<typename... Bases> overloaded(Bases...) -> overloaded<Bases...>; C++17
  • 80. 80 template<typename... Bases> struct overloaded : Bases... { using Bases::operator()...; }; template<typename... Bases> overloaded(Bases...) -> overloaded<Bases...>; overloaded printer = { [](auto arg) { std::cout << arg << ' '; }, [](double arg) { std::cout << std::fixed << arg << ' '; }, [](const char* arg) { std::cout << std::quoted(arg) << ' '; } }; C++17
  • 81. template<typename... Bases> struct overloaded : Bases... { using Bases::operator()...; }; template<typename... Bases> overloaded(Bases...) -> overloaded<Bases...>; overloaded printer = { [](auto arg) { std::cout << arg << ' '; }, [](double arg) { std::cout << std::fixed << arg << ' '; }, [](const char* arg) { std::cout << std::quoted(arg) << ' '; } }; int main() { printer("Hello, World!"); } 81 C++17
  • 82. 82 template<typename... Bases> struct overloaded : Bases... { using Bases::operator()...; }; template<typename... Bases> overloaded(Bases...) -> overloaded<Bases...>; overloaded printer = { [](auto arg) { std::cout << arg << ' '; }, [](double arg) { std::cout << std::fixed << arg << ' '; }, [](const char* arg) { std::cout << std::quoted(arg) << ' '; } }; int main() { printer("Hello, World!"); } C++17
  • 83. template<typename... Bases> struct overloaded : Bases... { using Bases::operator()...; }; overloaded printer = { [](auto arg) { std::cout << arg << ' '; }, [](double arg) { std::cout << std::fixed << arg << ' '; }, [](const char* arg) { std::cout << std::quoted(arg) << ' '; } }; int main() { printer("Hello, World!"); } 83 C++20
  • 84. 84 namespace pmr { template <class T> using vector = std::vector<T, std::pmr::polymorphic_allocator<T>>; } C++17 std::pmr::vector<int> v{1, 2, 3};
  • 85. 85 namespace pmr { template <class T> using vector = std::vector<T, std::pmr::polymorphic_allocator<T>>; } C++17 C++20 std::pmr::vector<int> v{1, 2, 3}; std::pmr::vector v{1, 2, 3};
  • 86. 86 1 Initialisation 2 Structured bindings 3 Lambdas 4 Templates 5 constexpr 6 Miscellaneous
  • 87. 87 In C++20, in a constexpr function you can: – have a try-block – have an unevaluated asm block – use a union – call virtual functions – dynamic_cast and typeid – new and delete
  • 88. 88 Daveed Vandevoorde “C++ Constants” C++Now 2019 keynote Louis Dionne "Compile-time programming and reflection in C++20 and beyond” CppCon 2018 talk
  • 89. 89 “running” code at compile time int square(int i) { return i * i; }
  • 90. 90 “running” code at compile time constexpr int square(int i) { return i * i; } square(3); // compile time square(x); // runtime
  • 91. consteval int square(int i) { return i * i; } square(3); // compile time square(x); // Error - x is not a compile-time constant! 91 “running” code at compile time
  • 92. 92 compile time or runtime? int square(int i) { return __magic_fast_square(i); // contains runtime magic } square(3); // runtime, fast magic square(x); // runtime, fast magic
  • 93. 93 compile time or runtime? constexpr int square(int i) { return i * i; } square(3); // compile time square(x); // runtime, no fast magic :(
  • 94. 94 compile time or runtime? constexpr int square(int i) { if (std::is_constant_evaluated()) { return i * i; } else { return __magic_fast_square(i); } } square(3); // compile time square(x); // runtime, fast magic :)
  • 95. constexpr int square(int i) { if (std::is_constant_evaluated()) { return i * i; } else { return __magic_fast_square(i); } } square(3); // compile time square(x); // runtime, fast magic :) 95 compile time or runtime?
  • 96. 96 1 Initialisation 2 Structured bindings 3 Lambdas 4 Templates 5 constexpr 6 Miscellaneous
  • 97. 97 template <typename Container> auto findFirstValid(const Container& c) -> Container::iterator { return std::find_if(c.begin(), c.end(), [](auto elem){ return elem.is_valid(); }); }
  • 98. 98 template <typename Container> auto findFirstValid(const Container& c) -> Container::const_iterator { return std::find_if(c.begin(), c.end(), [](auto elem){ return elem.is_valid(); }); } // Error: missing 'typename' prior to dependent type name ‘Container::const_iterator'
  • 99. 99 template <typename Container> auto findFirstValid(const Container& c) -> Container::const_iterator { return std::find_if(c.begin(), c.end(), [](auto elem){ return elem.is_valid(); }); } // OK in C++20 :)
  • 101. 101 – [[likely]], [[unlikely]] New attributes in C++20
  • 102. 102 – [[likely]], [[unlikely]] – [[no_unique_address]] New attributes in C++20
  • 103. 103 – [[likely]], [[unlikely]] – [[no_unique_address]] – [[nodiscard]] on constructors New attributes in C++20
  • 104. 104 – [[likely]], [[unlikely]] – [[no_unique_address]] – [[nodiscard]] on constructors – [[nodiscard(“can have a message”)]] New attributes in C++20
  • 105. enum class rgba_color_channel { red, green, blue, alpha }; 105 Using enum
  • 106. enum class rgba_color_channel { red, green, blue, alpha }; std::string_view to_string(rgba_color_channel channel) { switch (channel) { case rgba_color_channel::red: return "red"; case rgba_color_channel::green: return "green"; case rgba_color_channel::blue: return "blue"; case rgba_color_channel::alpha: return "alpha"; } } 106 Using enum
  • 107. 107 Using enum enum class rgba_color_channel { red, green, blue, alpha }; std::string_view to_string(rgba_color_channel channel) { switch (channel) { case rgba_color_channel::red: return "red"; case rgba_color_channel::green: return "green"; case rgba_color_channel::blue: return "blue"; case rgba_color_channel::alpha: return "alpha"; } }
  • 108. enum class rgba_color_channel { red, green, blue, alpha }; std::string_view to_string(rgba_color_channel channel) { switch (channel) { using enum rgba_color_channel; case red: return "red"; case green: return "green"; case blue: return "blue"; case alpha: return "alpha"; } } 108 Using enum
  • 109. enum class Suit { diamonds, hearts, spades, clubs }; class Card { using enum Suit; Suit suit = spades; }; 109 Using enum
  • 110. 110 Built-in UTF-8 char type int main() { const char* str = u8" 🦄 🌈"; // C++17... }
  • 111. 111 Built-in UTF-8 char type int main() { const char* str = u8" 🦄 🌈"; // compile error in C++20! }
  • 112. int main() { const char8_t* str = u8" 🦄 🌈"; } 112 Built-in UTF-8 char type
  • 114. Timur Doumler CoreHard Autumn Conference 30 November 2019 C++20: The small things @timur_audio Version 1.4