Intro base OO More exp Tool conc py
HEP C++ course
B. Gruber, S. Hageboeck, S. Ponce
[email protected] CERN
September 12, 2023
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 1 / 548
Intro base OO More exp Tool conc py
Foreword
What this course is not
It is not for absolute beginners
It is not for experts
It is not complete at all (would need 3 weeks...)
although it is already too long for the time we have
548 slides, 690 pages, 31 exercises...
How I see it
Adaptative pick what you want
Interactive tell me what to skip/insist on
Practical let’s spend time on real code
Where to find latest version ?
full sources at github.com/hsf-training/cpluspluscourse
latest pdf on GitHub
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 2 / 548
Intro base OO More exp Tool conc py
More courses
The HSF Software Training Center
A set of course modules on more software engineering aspects
prepared from within the HEP community
Unix shell
Python
Version control (git, gitlab, github)
...
https://hepsoftwarefoundation.org/training/curriculum.html
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 3 / 548
Intro base OO More exp Tool conc py
Outline
5 Expert C++
1 History and goals
6 Useful tools
2 Language basics
7 Concurrency
3 Object orientation (OO)
8 C++ and python
4 Core modern C++
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 4 / 548
Intro base OO More exp Tool conc py
Detailed outline
Type casting Coroutines
1 History and goals Operator overloading 6 Useful tools
History Function objects C++ editor
Why we use it? Name Lookups Version control
2 Language basics 4 Core modern C++ Code formatting
Core syntax and types Constness The Compiling Chain
Arrays and Pointers Constant Expressions Web tools
Scopes / namespaces Exceptions Debugging
Class and enum types Move semantics Sanitizers
References Copy elision The Valgrind family
Functions Templates Static code analysis
Operators Lambdas Profiling
Control structures The STL Doxygen
Headers and interfaces More STL 7 Concurrency
Auto keyword Ranges Threads and async
Inline keyword RAII and smart pointers Mutexes
Assertions Initialization Atomic types
3 Object orientation (OO) 5 Expert C++ Thread-local storage
Objects and Classes The <=> operator Condition Variables
Inheritance Variadic templates 8 C++ and python
Constructors/destructors Perfect forwarding Writing a module
Static members SFINAE Marrying C++ and C
Allocating objects Concepts The ctypes module
Advanced OO Modules The cppyy project
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 5 / 548
Intro base OO More exp Tool conc py Hist Use
History and goals
4 Core modern C++
1 History and goals
History 5 Expert C++
Why we use it?
6 Useful tools
2 Language basics
7 Concurrency
3 Object orientation (OO)
8 C++ and python
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 6 / 548
Intro base OO More exp Tool conc py Hist Use
History
1 History and goals
History
Why we use it?
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 7 / 548
Intro base OO More exp Tool conc py Hist Use
++
C/C origins
1967 Simula BCPL
1978 K and R C
Classic C
1980 C with Classes
1985 Early C++ C inventor C++ inventor
Dennis M. Ritchie Bjarne Stroustrup
1989 ARM C++ C89
Both C and C++ are born in Bell Labs
1998 C++ 98 C99
C++ almost embeds C
2011 C++ 11 C11
C and C++ are still under development
2014 C++ 14 We will discuss all C++ specs up to
C++ 20 (only partially)
2017 C++ 17
C17
Each slide will be marked with first
2020 C++ 20
spec introducing the feature
2023 C++ 23 C23
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 8 / 548
Intro base OO More exp Tool conc py Hist Use
++ ++ ++
C 11, C 14, C 17, C++ 20, C++ 23, C++ 26...
Status
A new C++ specification every 3 years
C++ 23 complete since 11th of Feb. 2023, awaiting ISO ballot
work on C++ 26 has begun
Bringing each time a lot of goodies
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 9 / 548
Intro base OO More exp Tool conc py Hist Use
++ ++ ++
C 11, C 14, C 17, C++ 20, C++ 23, C++ 26...
Status
A new C++ specification every 3 years
C++ 23 complete since 11th of Feb. 2023, awaiting ISO ballot
work on C++ 26 has begun
Bringing each time a lot of goodies
How to use C++ XX features
Use a compatible compiler C++ gcc clang
add -std=c++xx to 11 ≥4.8 ≥3.3
compilation flags 14 ≥4.9 ≥3.4
17 ≥7.3 ≥5
e.g. -std=c++17
20 >11 >12
Table: Minimum versions of gcc
and clang for a given C++ version
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 9 / 548
Intro base OO More exp Tool conc py Hist Use
Why we use it?
1 History and goals
History
Why we use it?
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 10 / 548
Intro base OO More exp Tool conc py Hist Use
++
Why is C our language of choice?
Adapted to large projects
statically and strongly typed
object oriented
widely used (and taught)
many available libraries
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 11 / 548
Intro base OO More exp Tool conc py Hist Use
++
Why is C our language of choice?
Adapted to large projects
statically and strongly typed
object oriented
widely used (and taught)
many available libraries
Fast
compiled (unlike Java, C#, Python, ...)
allows to go close to hardware when needed
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 11 / 548
Intro base OO More exp Tool conc py Hist Use
++
Why is C our language of choice?
Adapted to large projects
statically and strongly typed
object oriented
widely used (and taught)
many available libraries
Fast
compiled (unlike Java, C#, Python, ...)
allows to go close to hardware when needed
What we get
the most powerful language
the most complicated one
the most error prone?
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 11 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Language basics
Inline keyword
Assertions
1 History and goals
3 Object orientation (OO)
2 Language basics
Core syntax and types
Arrays and Pointers 4 Core modern C++
Scopes / namespaces
Class and enum types 5 Expert C++
References
Functions 6 Useful tools
Operators
Control structures 7 Concurrency
Headers and interfaces
Auto keyword
8 C++ and python
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 12 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Core syntax and types
2 Language basics
Core syntax and types
Arrays and Pointers
Scopes / namespaces
Class and enum types
References
Functions
Operators
Control structures
Headers and interfaces
Auto keyword
Inline keyword
Assertions
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 13 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Hello World C++ 98
1 #include <iostream>
2
3 // This is a function
4 void print(int i) {
5 std::cout << "Hello, world " << i << std::endl;
6 }
7
8 int main(int argc, char** argv) {
9 int n = 3;
10 for (int i = 0; i < n; i++) {
11 print(i);
12 }
13 return 0;
14 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 14 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Comments C++ 98
1 // simple comment until end of line
2 int i;
3
4 /* multiline comment
5 * in case we need to say more
6 */
7 double /* or something in between */ d;
8
9 /**
10 * Best choice : doxygen compatible comments
11 * \brief checks whether i is odd
12 * \param i input
13 * \return true if i is odd, otherwise false
14 * \see https://www.doxygen.nl/manual/docblocks.html
15 */
16 bool isOdd(int i);
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 15 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Basic types(1) C++ 98
1 bool b = true; // boolean, true or false
2
3 char c = 'a'; // min 8 bit integer
4 // may be signed or not
5 // can store an ASCII character
6 signed char c = 4; // min 8 bit signed integer
7 unsigned char c = 4; // min 8 bit unsigned integer
8
9 char* s = "a C string"; // array of chars ended by \0
10 string t = "a C++ string";// class provided by the STL
11
12 short int s = -444; // min 16 bit signed integer
13 unsigned short s = 444; // min 16 bit unsigned integer
14 short s = -444; // int is optional
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 16 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Basic types(2) C++ 98
1 int i = -123456; // min 16, usually 32 bit
2 unsigned int i = 1234567; // min 16, usually 32 bit
3
4 long l = 0L // min 32 bit
5 unsigned long l = 0UL; // min 32 bit
6
7 long long ll = 0LL; // min 64 bit
8 unsigned long long l = 0ULL; // min 64 bit
9
10 float f = 1.23f; // 32 (1+8+23) bit float
11 double d = 1.23E34; // 64 (1+11+52) bit float
12 long double ld = 1.23E34L // min 64 bit float
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 17 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Portable numeric types C++ 98
1 #include <cstdint> // defines the following:
2
3 std::int8_t c = -3; // 8 bit signed integer
4 std::uint8_t c = 4; // 8 bit unsigned integer
5
6 std::int16_t s = -444; // 16 bit signed integer
7 std::uint16_t s = 444; // 16 bit unsigned integer
8
9 std::int32_t s = -674; // 32 bit signed integer
10 std::uint32_t s = 674; // 32 bit unsigned integer
11
12 std::int64_t s = -1635; // 64 bit signed integer
13 std::uint64_t s = 1635; // 64 bit unsigned int
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 18 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Integer literals C++ 98
1 int i = 1234; // decimal (base 10)
2 int i = 02322; // octal (base 8)
3 int i = 0x4d2; // hexadecimal (base 16)
4 int i = 0X4D2; // hexadecimal (base 16)
5 int i = 0b10011010010; // binary (base 2) C++14
6
7 int i = 123'456'789; // digit separators, C++14
8 int i = 0b100'1101'0010; // digit separators, C++14
9
10 42 // int
11 42u, 42U // unsigned int
12 42l, 42L // long
13 42ul, 42UL // unsigned long
14 42ll, 42LL // long long
15 42ull, 42ULL // unsigned long long
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 19 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Floating-point literals C++ 98
1 double d = 12.34;
2 double d = 12.;
3 double d = .34;
4 double d = 12e34; // 12 * 10^34
5 double d = 12E34; // 12 * 10^34
6 double d = 12e-34; // 12 * 10^-34
7 double d = 12.34e34; // 12.34 * 10^34
8
9 double d = 123'456.789'101; // digit separators, C++14
10
11 double d = 0x4d2.4p3; // hexfloat, 0x4d2.4 * 2^3
12 // = 1234.25 * 2^3 = 9874
13
14 3.14f, 3.14F, // float
15 3.14, 3.14, // double
16 3.14l, 3.14L, // long double
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 20 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Useful aliases C++ 98
1 #include <cstddef> // (and others) defines:
2
3 // unsigned integer, can hold any variable's size
4 std::size_t s = sizeof(int);
5
6 #include <cstdint> // defines:
7
8 // signed integer, can hold any diff between two pointers
9 std::ptrdiff_t c = &s - &s;
10
11 // signed/unsigned integer, can hold any pointer value
12 std::intptr_t i = reinterpret_cast<intptr_t>(&s);
13 std::uintptr_t i = reinterpret_cast<uintptr_t>(&s);
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 21 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Extended floating-point types C++ 23
Extended floating-point types
Optional types, which may be provided
Custom conversion and promotion rules
1 #include <stdfloat> // may define these:
2
3 std::float16_t = 3.14f16;
// 16 (1+5+10) bit float
4 std::float32_t = 3.14f32;
// like float
5 // but different type
6 std::float64_t = 3.14f64; // like double
7 // but different type
8 std::float128_t = 3.14f128; // 128 (1+15+112) bit float
9 std::bfloat_t = 3.14bf16; // 16 (1+8+7) bit float
10
11 // also F16, F32, F64, F128 or BF16 suffix possible
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 22 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Arrays and Pointers
2 Language basics
Core syntax and types
Arrays and Pointers
Scopes / namespaces
Class and enum types
References
Functions
Operators
Control structures
Headers and interfaces
Auto keyword
Inline keyword
Assertions
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 23 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Static arrays C++ 98
1 int ai[4] = {1,2,3,4};
2 int ai[] = {1,2,3,4}; // identical
3
4 char ac[3] = {'a','b','c'}; // char array
5 char ac[4] = "abc"; // valid C string
6 char ac[4] = {'a','b','c',0}; // same valid string
7
8 int i = ai[2]; // i = 3
9 char c = ac[8]; // at best garbage, may segfault
10 int i = ai[4]; // also garbage !
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 24 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Pointers C++ 98
1 int i = 4;
2 int *pi = &i;
3 int j = *pi + 1;
4
5 int ai[] = {1,2,3};
6 int *pai = ai; // decay to ptr
7 int *paj = pai + 1;
8 int k = *paj + 1;
9
10 // compile error
11 int *pak = k;
12
13 // seg fault !
14 int *pak = (int*)k;
15 int l = *pak;
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 25 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Pointers C++ 98
1 int i = 4; Memory layout
2 int *pi = &i;
3 int j = *pi + 1; 0x3028
4
0x3024
5 int ai[] = {1,2,3}; 0x3020
6 int *pai = ai; // decay to ptr 0x301C
7 int *paj = pai + 1; 0x3018
8 int k = *paj + 1; 0x3014
9 0x3010
10 // compile error 0x300C
11 int *pak = k; 0x3008
12 0x3004
13 // seg fault ! i=4 0x3000
14 int *pak = (int*)k;
15 int l = *pak;
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 25 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Pointers C++ 98
1 int i = 4; Memory layout
2 int *pi = &i;
3 int j = *pi + 1; 0x3028
4 0x3024
5 int ai[] = {1,2,3}; 0x3020
6 int *pai = ai; // decay to ptr 0x301C
7 int *paj = pai + 1; 0x3018
8 int k = *paj + 1; 0x3014
9 0x3010
10 // compile error 0x300C
11 int *pak = k; 0x3008
12 pi = 0x3000 0x3004
13 // seg fault ! i=4 0x3000
14 int *pak = (int*)k;
15 int l = *pak;
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 25 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Pointers C++ 98
1 int i = 4; Memory layout
2 int *pi = &i;
3 int j = *pi + 1; 0x3028
4 0x3024
5 int ai[] = {1,2,3}; 0x3020
6 int *pai = ai; // decay to ptr 0x301C
7 int *paj = pai + 1; 0x3018
8 int k = *paj + 1; 0x3014
9 0x3010
10 // compile error 0x300C
11 int *pak = k; j=5 0x3008
12 pi = 0x3000 0x3004
13 // seg fault ! i=4 0x3000
14 int *pak = (int*)k;
15 int l = *pak;
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 25 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Pointers C++ 98
1 int i = 4; Memory layout
2 int *pi = &i;
3 int j = *pi + 1; 0x3028
4 0x3024
5 int ai[] = {1,2,3}; 0x3020
6 int *pai = ai; // decay to ptr 0x301C
7 int *paj = pai + 1; 0x3018
8 int k = *paj + 1; ai[2] = 3 0x3014
9 ai[1] = 2 0x3010
10 // compile error ai[0] = 1 0x300C
11 int *pak = k; j=5 0x3008
12 pi = 0x3000 0x3004
13 // seg fault ! i=4 0x3000
14 int *pak = (int*)k;
15 int l = *pak;
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 25 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Pointers C++ 98
1 int i = 4; Memory layout
2 int *pi = &i;
3 int j = *pi + 1; 0x3028
4 0x3024
5 int ai[] = {1,2,3}; 0x3020
6 int *pai = ai; // decay to ptr 0x301C
7 int *paj = pai + 1; pai = 0x300C 0x3018
8 int k = *paj + 1; ai[2] = 3 0x3014
9 ai[1] = 2 0x3010
10 // compile error ai[0] = 1 0x300C
11 int *pak = k; j=5 0x3008
12 pi = 0x3000 0x3004
13 // seg fault ! i=4 0x3000
14 int *pak = (int*)k;
15 int l = *pak;
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 25 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Pointers C++ 98
1 int i = 4; Memory layout
2 int *pi = &i;
3 int j = *pi + 1; 0x3028
4 0x3024
5 int ai[] = {1,2,3}; 0x3020
6 int *pai = ai; // decay to ptr paj = 0x3010 0x301C
7 int *paj = pai + 1; pai = 0x300C 0x3018
8 int k = *paj + 1; ai[2] = 3 0x3014
9 ai[1] = 2 0x3010
10 // compile error ai[0] = 1 0x300C
11 int *pak = k; j=5 0x3008
12 pi = 0x3000 0x3004
13 // seg fault ! i=4 0x3000
14 int *pak = (int*)k;
15 int l = *pak;
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 25 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Pointers C++ 98
1 int i = 4; Memory layout
2 int *pi = &i;
3 int j = *pi + 1; 0x3028
4 0x3024
5 int ai[] = {1,2,3}; k=3 0x3020
6 int *pai = ai; // decay to ptr paj = 0x3010 0x301C
7 int *paj = pai + 1; pai = 0x300C 0x3018
8 int k = *paj + 1; ai[2] = 3 0x3014
9 ai[1] = 2 0x3010
10 // compile error ai[0] = 1 0x300C
11 int *pak = k; j=5 0x3008
12 pi = 0x3000 0x3004
13 // seg fault ! i=4 0x3000
14 int *pak = (int*)k;
15 int l = *pak;
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 25 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Pointers C++ 98
1 int i = 4; Memory layout
2 int *pi = &i;
3 int j = *pi + 1; 0x3028
4 ?? pak = 3 0x3024
5 int ai[] = {1,2,3}; k=3 0x3020
6 int *pai = ai; // decay to ptr paj = 0x3010 0x301C
7 int *paj = pai + 1; pai = 0x300C 0x3018
8 int k = *paj + 1; ai[2] = 3 0x3014
9 ai[1] = 2 0x3010
10 // compile error ai[0] = 1 0x300C
11 int *pak = k; j=5 0x3008
12 pi = 0x3000 0x3004
13 // seg fault ! i=4 0x3000
14 int *pak = (int*)k;
15 int l = *pak;
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 25 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
nullptr C++ 11
A pointer to nothing
if a pointer doesn’t point to anything, set it to nullptr
useful to e.g. mark the end of a linked data structure
or absence of an optional function argument (pointer)
same as setting it to 0 or NULL (before C++ 11)
triggers compilation error when assigned to integer
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 26 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
nullptr C++ 11
A pointer to nothing
if a pointer doesn’t point to anything, set it to nullptr
useful to e.g. mark the end of a linked data structure
or absence of an optional function argument (pointer)
same as setting it to 0 or NULL (before C++ 11)
triggers compilation error when assigned to integer
Example code
1 int* ip = nullptr;
2 int i = NULL; // compiles, bug?
3 int i = nullptr; // ERROR
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 26 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Dynamic arrays using C C++ 98
1 #include <cstdlib>
2 #include <cstring>
3
4 int *bad; // pointer to random address
5 int *ai = nullptr; // better, deterministic, testable
6
7 // allocate array of 10 ints (uninitialized)
8 ai = (int*) malloc(10*sizeof(int));
9 memset(ai, 0, 10*sizeof(int)); // and set them to 0
10
11 ai = (int*) calloc(10, sizeof(int)); // both in one go
12
13 free(ai); // release memory
Good practice: Don’t use C’s memory management
Use std::vector and friends or smart pointers
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 27 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Manual dynamic arrays using C++ C++ 98
1 #include <cstdlib>
2 #include <cstring>
3
4 // allocate array of 10 ints
5 int* ai = new int[10]; // uninitialized
6 int* ai = new int[10]{}; // zero-initialized
7
8 delete[] ai; // release array memory
9
10 // allocate a single int
11 int* pi = new int;
12 int* pi = new int{};
13 delete pi; // release scalar memory
Good practice: Don’t use manual memory management
Use std::vector and friends or smart pointers
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 28 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Scopes / namespaces
2 Language basics
Core syntax and types
Arrays and Pointers
Scopes / namespaces
Class and enum types
References
Functions
Operators
Control structures
Headers and interfaces
Auto keyword
Inline keyword
Assertions
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 29 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Scope C++ 98
Definition
Portion of the source code where a given name is valid
Typically :
simple block of code, within {}
function, class, namespace
the global scope, i.e. translation unit (.cpp file + all includes)
Example
1 { int a;
2 { int b;
3 } // end of b scope
4 } // end of a scope
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 30 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Scope and lifetime of variables C++ 98
Variable life time
Variables are (statically) allocated when defined
Variables are freed at the end of a scope
Good practice: Initialisation
Initialise variables when allocating them!
This prevents bugs reading uninitialised memory
1 int a = 1; Memory layout
2 {
3 int b[4]; 0x3010
4 b[0] = a; 0x300C
5 } 0x3008
6 // Doesn't compile here: 0x3004
7 // b[1] = a + 1; a=1 0x3000
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 31 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Scope and lifetime of variables C++ 98
Variable life time
Variables are (statically) allocated when defined
Variables are freed at the end of a scope
Good practice: Initialisation
Initialise variables when allocating them!
This prevents bugs reading uninitialised memory
1 int a = 1; Memory layout
2 {
3 int b[4]; b[3] = ? 0x3010
4 b[0] = a; b[2] = ? 0x300C
5 } b[1] = ? 0x3008
6 // Doesn't compile here: b[0] = ? 0x3004
7 // b[1] = a + 1; a=1 0x3000
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 31 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Scope and lifetime of variables C++ 98
Variable life time
Variables are (statically) allocated when defined
Variables are freed at the end of a scope
Good practice: Initialisation
Initialise variables when allocating them!
This prevents bugs reading uninitialised memory
1 int a = 1; Memory layout
2 {
3 int b[4]; b[3] = ? 0x3010
4 b[0] = a; b[2] = ? 0x300C
5 } b[1] = ? 0x3008
6 // Doesn't compile here: b[0] = 1 0x3004
7 // b[1] = a + 1; a=1 0x3000
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 31 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Scope and lifetime of variables C++ 98
Variable life time
Variables are (statically) allocated when defined
Variables are freed at the end of a scope
Good practice: Initialisation
Initialise variables when allocating them!
This prevents bugs reading uninitialised memory
1 int a = 1; Memory layout
2 {
3 int b[4]; ? 0x3010
4 b[0] = a; ? 0x300C
5 } ? 0x3008
6 // Doesn't compile here: 1 0x3004
7 // b[1] = a + 1; a=1 0x3000
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 31 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Namespaces C++ 98
Namespaces allow to segment your code to avoid name clashes
They can be embedded to create hierarchies (separator is ’::’)
1 int a; 14 namespace p { // reopen p
2 namespace n { 15 void f() {
3 int a; // no clash 16 p::a = 6;
4 } 17 a = 6; //same as above
5 namespace p { 18 ::a = 1;
6 int a; // no clash 19 p::inner::a = 8;
7 namespace inner { 20 inner::a = 8;
8 int a; // no clash 21 n::a = 3;
9 } 22 }
10 } 23 }
11 void f() { 24 using namespace p::inner;
12 n::a = 3; 25 void g() {
13 } 26 a = -1; // err: ambiguous
27 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 32 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Nested namespaces C++ 17
Easier way to declare nested namespaces
C++ 98
1 namespace A {
2 namespace B {
3 namespace C {
4 //...
5 }
6 }
7 }
C++ 17
1 namespace A::B::C {
2 //...
3 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 33 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Unnamed / anonymous namespaces C++ 98
A namespace without a name!
1 namespace {
2 int localVar;
3 }
Purpose
groups a number of declarations
visible only in the current translation unit
but not reusable outside
allows much better compiler optimizations and checking
e.g. unused function warning
context dependent optimizations
Supersedes static
4 static int localVar; // equivalent C code
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 34 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Using namespace directives C++ 98
Avoid “using namespace” directives
Make all members of a namespace visible in current scope
Risk of name clashes or ambiguities
1 using namespace std;
2 cout << "We can print now\n"; // uses std::cout
Never use in headers at global scope!
1 #include "PoorlyWritten.h" // using namespace std;
2 struct array { ... };
3 array a; // Error: name clash with std::array
What to do instead
Qualify names: std::vector, std::cout, …
Put things that belong together in the same namespace
Use using declarations in local scopes: using std::cout;
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 35 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Class and enum types
2 Language basics
Core syntax and types
Arrays and Pointers
Scopes / namespaces
Class and enum types
References
Functions
Operators
Control structures
Headers and interfaces
Auto keyword
Inline keyword
Assertions
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 36 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
struct C++ 98
“members” grouped together under one name
1 struct Individual { 14 Individual *ptr = &student;
2 unsigned char age; 15 ptr->age = 25;
3 float weight; 16 // same as: (*ptr).age = 25;
4 };
5
6 Individual student;
7 student.age = 25;
8 student.weight = 78.5f;
9
10 Individual teacher = {
11 45, 67.0f
12 };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 37 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
struct C++ 98
“members” grouped together under one name
1 struct Individual { 14 Individual *ptr = &student;
2 unsigned char age; 15 ptr->age = 25;
3 float weight; 16 // same as: (*ptr).age = 25;
4 };
Memory layout
5
6 Individual student; 0x3010
7 student.age = 25; 0x300C
8 student.weight = 78.5f; 0x3008
9
0x3004
10 Individual teacher = { 0x3000
11 45, 67.0f
12 };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 37 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
struct C++ 98
“members” grouped together under one name
1 struct Individual { 14 Individual *ptr = &student;
2 unsigned char age; 15 ptr->age = 25;
3 float weight; 16 // same as: (*ptr).age = 25;
4 };
Memory layout
5
6 Individual student; 0x3010
7 student.age = 25; 0x300C
8 student.weight = 78.5f; student
0x3008
9
78.5 0x3004
10 Individual teacher = { 25 ? ? ? 0x3000
11 45, 67.0f
12 };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 37 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
struct C++ 98
“members” grouped together under one name
1 struct Individual { 14 Individual *ptr = &student;
2 unsigned char age; 15 ptr->age = 25;
3 float weight; 16 // same as: (*ptr).age = 25;
4 };
Memory layout
5
6 Individual student; 0x3010
student.age = 25;
student teacher
7 67.0 0x300C
8 student.weight = 78.5f; 45 ? ? ? 0x3008
9
78.5 0x3004
10 Individual teacher = { 25 ? ? ? 0x3000
11 45, 67.0f
12 };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 37 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
struct C++ 98
“members” grouped together under one name
1 struct Individual { 14 Individual *ptr = &student;
2 unsigned char age; 15 ptr->age = 25;
3 float weight; 16 // same as: (*ptr).age = 25;
4 };
Memory layout
5
6 Individual student; 0x3000 0x3010
student.age = 25;
student teacher
7 67.0 0x300C
8 student.weight = 78.5f; 45 ? ? ? 0x3008
9
78.5 0x3004
10 Individual teacher = { 25 ? ? ? 0x3000
11 45, 67.0f
12 };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 37 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
union C++ 98
“members” packed together at same memory location
1 union Duration {
2 int seconds;
3 short hours;
4 char days;
5 };
6 Duration d1, d2, d3;
7 d1.seconds = 259200;
8 d2.hours = 72;
9 d3.days = 3;
10 d1.days = 3; // d1.seconds overwritten
11 int a = d1.seconds; // d1.seconds is garbage
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 38 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
union C++ 98
“members” packed together at same memory location
1 union Duration {
2 int seconds;
3 short hours;
4 char days; Memory layout
5 }; 0x300C
6 Duration d1, d2, d3; 0x3008
7 d1.seconds = 259200; 0x3004
8 d2.hours = 72;
0x3000
9 d3.days = 3;
10 d1.days = 3; // d1.seconds overwritten
11 int a = d1.seconds; // d1.seconds is garbage
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 38 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
union C++ 98
“members” packed together at same memory location
1 union Duration {
2 int seconds;
3 short hours;
4 char days; Memory layout
5 }; 0x300C
6 Duration d1, d2, d3; 0x3008
7 d1.seconds = 259200; 0x3004
8 d2.hours = 72;
d1 259200 0x3000
9 d3.days = 3;
10 d1.days = 3; // d1.seconds overwritten
11 int a = d1.seconds; // d1.seconds is garbage
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 38 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
union C++ 98
“members” packed together at same memory location
1 union Duration {
2 int seconds;
3 short hours;
4 char days; Memory layout
5 }; 0x300C
6 Duration d1, d2, d3; 0x3008
7 d1.seconds = 259200; d2 72 ? ? 0x3004
8 d2.hours = 72;
d1 259200 0x3000
9 d3.days = 3;
10 d1.days = 3; // d1.seconds overwritten
11 int a = d1.seconds; // d1.seconds is garbage
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 38 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
union C++ 98
“members” packed together at same memory location
1 union Duration {
2 int seconds;
3 short hours;
4 char days; Memory layout
5 }; 0x300C
6 Duration d1, d2, d3; d3 3 ? ? ? 0x3008
7 d1.seconds = 259200; d2 72 ? ? 0x3004
8 d2.hours = 72;
d1 259200 0x3000
9 d3.days = 3;
10 d1.days = 3; // d1.seconds overwritten
11 int a = d1.seconds; // d1.seconds is garbage
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 38 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
union C++ 98
“members” packed together at same memory location
1 union Duration {
2 int seconds;
3 short hours;
4 char days; Memory layout
5 }; 0x300C
6 Duration d1, d2, d3; d3 3 ? ? ? 0x3008
7 d1.seconds = 259200; d2 72 ? ? 0x3004
8 d2.hours = 72;
d1 3 ? ? ? 0x3000
9 d3.days = 3;
10 d1.days = 3; // d1.seconds overwritten
11 int a = d1.seconds; // d1.seconds is garbage
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 38 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
union C++ 98
“members” packed together at same memory location
1 union Duration {
2 int seconds;
3 short hours;
4 char days; Memory layout
5 }; 0x300C
6 Duration d1, d2, d3; d3 3 ? ? ? 0x3008
7 d1.seconds = 259200; d2 72 ? ? 0x3004
8 d2.hours = 72;
d1 3 ? ? ? 0x3000
9 d3.days = 3;
10 d1.days = 3; // d1.seconds overwritten
11 int a = d1.seconds; // d1.seconds is garbage
Good practice: Avoid unions
Starting with C++ 17: prefer std::variant
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 38 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Enums C++ 98
use to declare a list of related constants (enumerators)
has an underlying integral type
enumerator names leak into enclosing scope
1 enum VehicleType { 8 enum VehicleType
2 9 : int { // C++11
3 BIKE, // 0 10 BIKE = 3,
4 CAR, // 1 11 CAR = 5,
5 BUS, // 2 12 BUS = 7,
6 }; 13 };
7 VehicleType t = CAR; 14 VehicleType t2 = BUS;
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 39 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Scoped enumeration, aka enum class C++ 11
Same syntax as enum, with scope
1 enum class VehicleType { Bus, Car };
2 VehicleType t = VehicleType::Car;
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 40 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Scoped enumeration, aka enum class C++ 11
Same syntax as enum, with scope
1 enum class VehicleType { Bus, Car };
2 VehicleType t = VehicleType::Car;
Only advantages
scopes enumerator names, avoids name clashes
strong typing, no automatic conversion to int
3 enum VType { Bus, Car }; enum Color { Red, Blue };
4 VType t = Bus;
5 if (t == Red) { /* We do enter */ }
6 int a = 5 * Car; // Ok, a = 5
7
8 enum class VT { Bus, Car }; enum class Col { Red, Blue };
9 VT t = VT::Bus;
10 if (t == Col::Red) { /* Compiler error */ }
11 int a = t * 5; // Compiler error
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 40 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
More sensible example C++ 98
1 enum class ShapeType {
2 Circle,
3 Rectangle
4 };
5
6 struct Rectangle {
7 float width;
8 float height;
9 };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 41 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
More sensible example C++ 98
1 enum class ShapeType { 10 struct Shape {
2 Circle, 11 ShapeType type;
3 Rectangle 12 union {
4 }; 13 float radius;
5 14 Rectangle rect;
6 struct Rectangle { 15 };
7 float width; 16 };
8 float height;
9 };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 41 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
More sensible example C++ 98
1 enum class ShapeType { 10 struct Shape {
2 Circle, 11 ShapeType type;
3 Rectangle 12 union {
4 }; 13 float radius;
5 14 Rectangle rect;
6 struct Rectangle { 15 };
7 float width; 16 };
8 float height;
9 };
17 Shape s; 20 Shape t;
18 s.type = 21 t.type =
19 ShapeType::Circle; 22 Shapetype::Rectangle;
20 s.radius = 3.4; 23 t.rect.width = 3;
21 24 t.rect.height = 4;
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 41 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
typedef and using C++ 98 / C++ 11
Used to create type aliases
C++ 98
1 typedef std::uint64_t myint;
2 myint count = 17;
3 typedef float position[3];
C++ 11
4 using myint = std::uint64_t;
5 myint count = 17;
6 using position = float[3];
7
8 template <typename T> using myvec = std::vector<T>;
9 myvec<int> myintvec;
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 42 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
References
2 Language basics
Core syntax and types
Arrays and Pointers
Scopes / namespaces
Class and enum types
References
Functions
Operators
Control structures
Headers and interfaces
Auto keyword
Inline keyword
Assertions
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 43 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
References C++ 98
References
References allow for direct access to another object
They can be used as shortcuts / better readability
They can be declared const to allow only read access
Example:
1 int i = 2;
2 int &iref = i; // access to i
3 iref = 3; // i is now 3
4
5 // const reference to a member:
6 struct A { int x; int y; } a;
7 const int &x = a.x; // direct read access to A's x
8 x = 4; // doesn't compile
9 a.x = 4; // fine
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 44 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Pointers vs References C++ 98
Specificities of reference
Natural syntax
Cannot be nullptr
Must be assigned when defined, cannot be reassigned
References to temporary objects must be const
Advantages of pointers
Can be nullptr
Can be initialized after declaration, can be reassigned
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 45 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Pointers vs References C++ 98
Specificities of reference
Natural syntax
Cannot be nullptr
Must be assigned when defined, cannot be reassigned
References to temporary objects must be const
Advantages of pointers
Can be nullptr
Can be initialized after declaration, can be reassigned
Good practice: References
Prefer using references instead of pointers
Mark references const to prevent modification
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 45 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Functions
2 Language basics
Core syntax and types
Arrays and Pointers
Scopes / namespaces
Class and enum types
References
Functions
Operators
Control structures
Headers and interfaces
Auto keyword
Inline keyword
Assertions
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 46 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Functions C++ 98
1 // with return type 11 // no return
2 int square(int a) { 12 void log(char* msg) {
3 return a * a; 13 std::cout << msg;
4 } 14 }
5 15
6 // multiple parameters 16 // no parameter
7 int mult(int a, 17 void hello() {
8 int b) { 18 std::cout << "Hello World";
9 return a * b; 19 }
10 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 47 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Functions C++ 98
1 // with return type 11 // no return
2 int square(int a) { 12 void log(char* msg) {
3 return a * a; 13 std::cout << msg;
4 } 14 }
5 15
6 // multiple parameters 16 // no parameter
7 int mult(int a, 17 void hello() {
8 int b) { 18 std::cout << "Hello World";
9 return a * b; 19 }
10 }
Functions and references to returned values
1 int result = square(2);
2 int & temp = square(2); // Not allowed
3 int const & temp2 = square(2); // OK
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 47 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Function default arguments C++ 98
1 // must be the trailing 11 // multiple default
2 // argument 12 // arguments are possible
3 int add(int a, 13 int add(int a = 2,
4 int b = 2) { 14 int b = 2) {
5 return a + b; 15 return a + b;
6 } 16 }
7 // add(1) == 3 17 // add() == 4
8 // add(3,4) == 7 18 // add(3) == 5
9
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 48 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Functions: parameters are passed by value C++ 98
1 struct BigStruct {...};
2 BigStruct s;
3
Memory layout
4 // parameter by value
5 void printVal(BigStruct p) { 0x31E0
6 ... 0x3190
7 } 0x3140
8 printVal(s); // copy 0x30F0
9 0x30A0
10 // parameter by reference 0x3050
11 void printRef(BigStruct &q) { 0x3000
12 ...
13 }
14 printRef(s); // no copy
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 49 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Functions: parameters are passed by value C++ 98
1 struct BigStruct {...};
2 BigStruct s;
3
Memory layout
4 // parameter by value
5 void printVal(BigStruct p) { 0x31E0
6 ... 0x3190
7 } 0x3140
8 printVal(s); // copy 0x30F0
9 sn 0x30A0
10 // parameter by reference ... 0x3050
s
11 void printRef(BigStruct &q) { s1 0x3000
12 ...
13 }
14 printRef(s); // no copy
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 49 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Functions: parameters are passed by value C++ 98
1 struct BigStruct {...};
2 BigStruct s;
3
Memory layout
4 // parameter by value
5 void printVal(BigStruct p) { 0x31E0
6 ... pn = sn 0x3190
} ... 0x3140
p
7
8 printVal(s); // copy p1 = s1 0x30F0
9 sn 0x30A0
10 // parameter by reference ... 0x3050
s
11 void printRef(BigStruct &q) { s1 0x3000
12 ...
13 }
14 printRef(s); // no copy
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 49 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Functions: parameters are passed by value C++ 98
1 struct BigStruct {...};
2 BigStruct s;
3
Memory layout
4 // parameter by value
5 void printVal(BigStruct p) { 0x31E0
6 ... 0x3190
7 } 0x3140
8 printVal(s); // copy q = 0x3000 0x30F0
9 sn 0x30A0
10 // parameter by reference ... 0x3050
s
11 void printRef(BigStruct &q) { s1 0x3000
12 ...
13 }
14 printRef(s); // no copy
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 49 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Functions: pass by value or reference? C++ 98
1 struct SmallStruct {int a;};
2 SmallStruct s = {1};
3
4 void changeVal(SmallStruct p) {
5 p.a = 2; Memory layout
6 }
7 changeVal(s); 0x3008
8 // s.a == 1 0x3004
9 0x3000
10 void changeRef(SmallStruct &q) {
11 q.a = 2;
12 }
13 changeRef(s);
14 // s.a == 2
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 50 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Functions: pass by value or reference? C++ 98
1 struct SmallStruct {int a;};
2 SmallStruct s = {1};
3
4 void changeVal(SmallStruct p) {
5 p.a = 2; Memory layout
6 }
7 changeVal(s); 0x3008
8 // s.a == 1 0x3004
9 s.a = 1 0x3000
10 void changeRef(SmallStruct &q) {
11 q.a = 2;
12 }
13 changeRef(s);
14 // s.a == 2
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 50 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Functions: pass by value or reference? C++ 98
1 struct SmallStruct {int a;};
2 SmallStruct s = {1};
3
4 void changeVal(SmallStruct p) {
5 p.a = 2; Memory layout
6 }
7 changeVal(s); 0x3008
8 // s.a == 1 p.a = 1 0x3004
9 s.a = 1 0x3000
10 void changeRef(SmallStruct &q) {
11 q.a = 2;
12 }
13 changeRef(s);
14 // s.a == 2
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 50 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Functions: pass by value or reference? C++ 98
1 struct SmallStruct {int a;};
2 SmallStruct s = {1};
3
4 void changeVal(SmallStruct p) {
5 p.a = 2; Memory layout
6 }
7 changeVal(s); 0x3008
8 // s.a == 1 p.a = 2 0x3004
9 s.a = 1 0x3000
10 void changeRef(SmallStruct &q) {
11 q.a = 2;
12 }
13 changeRef(s);
14 // s.a == 2
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 50 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Functions: pass by value or reference? C++ 98
1 struct SmallStruct {int a;};
2 SmallStruct s = {1};
3
4 void changeVal(SmallStruct p) {
5 p.a = 2; Memory layout
6 }
7 changeVal(s); 0x3008
8 // s.a == 1 0x3004
9 s.a = 1 0x3000
10 void changeRef(SmallStruct &q) {
11 q.a = 2;
12 }
13 changeRef(s);
14 // s.a == 2
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 50 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Functions: pass by value or reference? C++ 98
1 struct SmallStruct {int a;};
2 SmallStruct s = {1};
3
4 void changeVal(SmallStruct p) {
5 p.a = 2; Memory layout
6 }
7 changeVal(s); 0x3008
8 // s.a == 1 q = 0x3000 0x3004
9 s.a = 1 0x3000
10 void changeRef(SmallStruct &q) {
11 q.a = 2;
12 }
13 changeRef(s);
14 // s.a == 2
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 50 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Functions: pass by value or reference? C++ 98
1 struct SmallStruct {int a;};
2 SmallStruct s = {1};
3
4 void changeVal(SmallStruct p) {
5 p.a = 2; Memory layout
6 }
7 changeVal(s); 0x3008
8 // s.a == 1 q = 0x3000 0x3004
9 s.a = 2 0x3000
10 void changeRef(SmallStruct &q) {
11 q.a = 2;
12 }
13 changeRef(s);
14 // s.a == 2
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 50 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Functions: pass by value or reference? C++ 98
1 struct SmallStruct {int a;};
2 SmallStruct s = {1};
3
4 void changeVal(SmallStruct p) {
5 p.a = 2; Memory layout
6 }
7 changeVal(s); 0x3008
8 // s.a == 1 0x3004
9 s.a = 2 0x3000
10 void changeRef(SmallStruct &q) {
11 q.a = 2;
12 }
13 changeRef(s);
14 // s.a == 2
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 50 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Pass by value, reference or pointer C++ 98
Different ways to pass arguments to a function
By default, arguments are passed by value (= copy)
good for small types, e.g. numbers
Use references for parameters to avoid copies
good for large types, e.g. objects
Use const for safety and readability whenever possible
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 51 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Pass by value, reference or pointer C++ 98
Different ways to pass arguments to a function
By default, arguments are passed by value (= copy)
good for small types, e.g. numbers
Use references for parameters to avoid copies
good for large types, e.g. objects
Use const for safety and readability whenever possible
Syntax
1 struct T {...}; T a;
2 void fVal(T value); fVal(a); // by value
3 void fRef(const T &value); fRef(a); // by reference
4 void fPtr(const T *value); fPtr(&a); // by pointer
5 void fWrite(T &value); fWrite(a); // non-const ref
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 51 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Overloading C++ 98
Overloading
We can have multiple functions with the same name
Must have different parameter lists
A different return type alone is not allowed
Form a so-called “overload set”
Default arguments can cause ambiguities
1 int sum(int b); // 1
2 int sum(int b, int c); // 2, ok, overload
3 // float sum(int b, int c); // disallowed
4 sum(42); // calls 1
5 sum(42, 43); // calls 2
6 int sum(int b, int c, int d = 4); // 3, overload
7 sum(42, 43, 44); // calls 3
8 sum(42, 43); // error: ambiguous, 2 or 3
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 52 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Functions C++ 98
Exercise: Functions
Familiarise yourself with pass by value / pass by reference.
Go to exercises/functions
Look at functions.cpp
Compile it (make) and run the program (./functions)
Work on the tasks that you find in functions.cpp
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 53 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Functions: good practices C++ 98
Good practice: Write readable functions
Keep functions short
Do one logical thing (single-responsibility principle)
Use expressive names
Document non-trivial functions
Example: Good
1 /// Count number of dilepton events in data.
2 /// \param d Dataset to search.
3 unsigned int countDileptons(Data &d) {
4 selectEventsWithMuons(d);
5 selectEventsWithElectrons(d);
6 return d.size();
7 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 54 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Functions: good practices C++ 98
Example: don’t! Everything in one long function
1 unsigned int runJob() { 15 if (...) {
2 // Step 1: data 16 data.erase(...);
3 Data data; 17 }
4 data.resize(123456); 18 }
5 data.fill(...); 19
6 20 // Step 4: dileptons
7 // Step 2: muons 21 int counter = 0;
8 for (....) { 22 for (....) {
9 if (...) { 23 if (...) {
10 data.erase(...); 24 counter++;
11 } 25 }
12 } 26 }
13 // Step 3: electrons 27
14 for (....) { 28 return counter;
29 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 54 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Operators
2 Language basics
Core syntax and types
Arrays and Pointers
Scopes / namespaces
Class and enum types
References
Functions
Operators
Control structures
Headers and interfaces
Auto keyword
Inline keyword
Assertions
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 55 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Operators(1) C++ 98
Binary and Assignment Operators
1 int i = 1 + 4 - 2; // 3
2 i *= 3; // 9, short for: i = i * 3;
3 i /= 2; // 4
4 i = 23 % i; // modulo => 3
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 56 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Operators(1) C++ 98
Binary and Assignment Operators
1 int i = 1 + 4 - 2; // 3
2 i *= 3; // 9, short for: i = i * 3;
3 i /= 2; // 4
4 i = 23 % i; // modulo => 3
Increment / Decrement Operators
1 int i = 0; i++; // i = 1
2 int j = ++i; // i = 2, j = 2
3 int k = i++; // i = 3, k = 2
4 int l = --i; // i = 2, l = 2
5 int m = i--; // i = 1, m = 2
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 56 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Operators(1) C++ 98
Binary and Assignment Operators
1 int i = 1 + 4 - 2; // 3
2 i *= 3; // 9, short for: i = i * 3;
3 i /= 2; // 4
4 i = 23 % i; // modulo => 3
Increment / Decrement Operators Use wisely
1 int i = 0; i++; // i = 1
2 int j = ++i; // i = 2, j = 2
3 int k = i++; // i = 3, k = 2
4 int l = --i; // i = 2, l = 2
5 int m = i--; // i = 1, m = 2
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 56 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Operators(2) C++ 98
Bitwise and Assignment Operators
1 unsigned i = 0xee & 0x55; // 0x44
2 i |= 0xee; // 0xee
3 i ^= 0x55; // 0xbb
4 unsigned j = ~0xee; // 0xffffff11
5 unsigned k = 0x1f << 3; // 0xf8
6 unsigned l = 0x1f >> 2; // 0x7
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 57 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Operators(2) C++ 98
Bitwise and Assignment Operators
1 unsigned i = 0xee & 0x55; // 0x44
2 i |= 0xee; // 0xee
3 i ^= 0x55; // 0xbb
4 unsigned j = ~0xee; // 0xffffff11
5 unsigned k = 0x1f << 3; // 0xf8
6 unsigned l = 0x1f >> 2; // 0x7
Logical Operators
1 bool a = true;
2 bool b = false;
3 bool c = a && b; // false
4 bool d = a || b; // true
5 bool e = !d; // false
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 57 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Operators(3) C++ 98
Comparison Operators
1 bool a = (3 == 3); // true
2 bool b = (3 != 3); // false
3 bool c = (4 < 4); // false
4 bool d = (4 <= 4); // true
5 bool e = (4 > 4); // false
6 bool f = (4 >= 4); // true
7 auto g = (5 <=> 5); // C++20 (later)
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 58 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Operators(3) C++ 98
Comparison Operators
1 bool a = (3 == 3); // true
2 bool b = (3 != 3); // false
3 bool c = (4 < 4); // false
4 bool d = (4 <= 4); // true
5 bool e = (4 > 4); // false
6 bool f = (4 >= 4); // true
7 auto g = (5 <=> 5); // C++20 (later)
Precedences
c &= 1+(++b)|(a--)*4%5^7; // ???
Details can be found on cppreference
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 58 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Operators(3) C++ 98
Comparison Operators
1 bool a = (3 == 3); // true
2 bool b = (3 != 3); // false
3 bool c = (4 < 4); // false
4 bool d = (4 <= 4); // true
5 bool e = (4 > 4); // false
6 bool f = (4 >= 4); // true
7 auto g = (5 <=> 5); // C++20 (later)
Precedences Avoid
c &= 1+(++b)|(a--)*4%5^7; // ???
Details can be found on cppreference
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 58 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Operators(3) C++ 98
Comparison Operators
1 bool a = (3 == 3); // true
2 bool b = (3 != 3); // false
3 bool c = (4 < 4); // false
4 bool d = (4 <= 4); // true
5 bool e = (4 > 4); // false
6 bool f = (4 >= 4); // true
7 auto g = (5 <=> 5); // C++20 (later)
Precedences Avoid - use parentheses
c &= 1+(++b)|(a--)*4%5^7; // ???
Details can be found on cppreference
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 58 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Control structures
2 Language basics
Core syntax and types
Arrays and Pointers
Scopes / namespaces
Class and enum types
References
Functions
Operators
Control structures
Headers and interfaces
Auto keyword
Inline keyword
Assertions
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 59 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Control structures: if C++ 98
if syntax
1 if (condition1) {
2 Statement1; Statement2;
3 } else if (condition2)
4 OnlyOneStatement;
5 else {
6 Statement3;
7 Statement4;
8 }
The else and else if clauses are optional
The else if clause can be repeated
Braces are optional if there is a single statement
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 60 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Control structures: if C++ 98
Practical example
1 int collatz(int a) {
2 if (a <= 0) {
3 std::cout << "not supported\n";
4 return 0;
5 } else if (a == 1) {
6 return 1;
7 } else if (a%2 == 0) {
8 return collatz(a/2);
9 } else {
10 return collatz(3*a+1);
11 }
12 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 61 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Control structures: conditional operator C++ 98
Syntax
test ? expression1 : expression2;
If test is true expression1 is returned
Else, expression2 is returned
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 62 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Control structures: conditional operator C++ 98
Syntax
test ? expression1 : expression2;
If test is true expression1 is returned
Else, expression2 is returned
Practical example
1 const int charge = isLepton ? -1 : 0;
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 62 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Control structures: conditional operator C++ 98
Syntax
test ? expression1 : expression2;
If test is true expression1 is returned
Else, expression2 is returned
Practical example
1 const int charge = isLepton ? -1 : 0;
Do not abuse it
1 int collatz(int a) {
2 return a==1 ? 1 : collatz(a%2==0 ? a/2 : 3*a+1);
3 }
Explicit ifs are generally easier to read
Use the ternary operator with short conditions and expressions
Avoid nesting
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 62 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Control structures: switch C++ 98
Syntax
1 switch(identifier) {
2 case c1 : statements1; break;
3 case c2 : statements2; break;
4 case c3 : statements3; break;
5 ...
6 default : statementsn; break;
7 }
The break statement is not mandatory but...
Cases are entry points, not independent pieces
Execution “falls through” to the next case without a break!
The default case may be omitted
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 63 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Control structures: switch C++ 98
Syntax
1 switch(identifier) {
2 case c1 : statements1; break;
3 case c2 : statements2; break;
4 case c3 : statements3; break;
5 ...
6 default : statementsn; break;
7 }
The break statement is not mandatory but...
Cases are entry points, not independent pieces
Execution “falls through” to the next case without a break!
The default case may be omitted
Use break
Avoid switch statements with fall-through cases
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 63 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Control structures: switch C++ 98
Practical example
1 enum class Lang { French, German, English, Other };
2 Lang language = ...;
3 switch (language) {
4 case Lang::French:
5 std::cout << "Bonjour";
6 break;
7 case Lang::German:
8 std::cout << "Guten Tag";
9 break;
10 case Lang::English:
11 std::cout << "Good morning";
12 break;
13 default:
14 std::cout << "I do not speak your language";
15 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 64 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
[[fallthrough]] attribute C++ 17
New compiler warning
Since C++ 17, compilers are encouraged to warn on fall-through
C++ 17
1 switch (c) {
2 case 'a':
3 f(); // Warning emitted
4 case 'b': // Warning probably suppressed
5 case 'c':
6 g();
7 [[fallthrough]]; // Warning suppressed
8 case 'd':
9 h();
10 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 65 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Init-statements for if and switch C++ 17
Purpose
Allows to limit variable scope in if and switch statements
C++ 17
1 if (Value val = GetValue(); condition(val)) {
2 f(val); // ok
3 } else
4 g(val); // ok
5 h(val); // error, no `val` in scope here
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 66 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Init-statements for if and switch C++ 17
Purpose
Allows to limit variable scope in if and switch statements
C++ 17
1 if (Value val = GetValue(); condition(val)) {
2 f(val); // ok
3 } else
4 g(val); // ok
5 h(val); // error, no `val` in scope here
C++ 98
Don’t confuse with a variable declaration as condition:
7 if (Value* val = GetValuePtr())
8 f(*val);
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 66 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Control structures: for loop C++ 98
for loop syntax
1 for(initializations; condition; increments) {
2 statements;
3 }
Initializations and increments are comma separated
Initializations can contain declarations
Braces are optional if loop body is a single statement
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 67 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Control structures: for loop C++ 98
for loop syntax
1 for(initializations; condition; increments) {
2 statements;
3 }
Initializations and increments are comma separated
Initializations can contain declarations
Braces are optional if loop body is a single statement
Practical example
4 for(int i = 0, j = 0 ; i < 10 ; i++, j = i*i) {
5 std::cout << i << "^2 is " << j << '\n';
6 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 67 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Control structures: for loop C++ 98
for loop syntax
1 for(initializations; condition; increments) {
2 statements;
3 }
Initializations and increments are comma separated
Initializations can contain declarations
Braces are optional if loop body is a single statement
Practical example
4 for(int i = 0, j = 0 ; i < 10 ; i++, j = i*i) {
5 std::cout << i << "^2 is " << j << '\n';
6 }
Good practice: Don’t abuse the for syntax
The for loop head should fit in 1-3 lines
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 67 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Range-based loops C++ 11
Reason of being
Simplifies loops over “ranges” tremendously
Especially with STL containers and ranges
Syntax
1 for ( type iteration_variable : range ) {
2 // body using iteration_variable
3 }
Example code
4 int v[4] = {1,2,3,4};
5 int sum = 0;
6 for (int a : v) { sum += a; }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 68 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Init-statements for range-based loops C++ 20
Purpose
Allows to limit variable scope in range-based loops
C++ 17
1 std::array data = {"hello", ",", "world"};
2 std::size_t i = 0;
3 for (auto& d : data) {
4 std::cout << i++ << ' ' << d << '\n';
5 }
C++ 20
6 for (std::size_t i = 0; auto& d : data) {
7 std::cout << i++ << ' ' << d << '\n';
8 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 69 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Control structures: while loop C++ 98
while loop syntax
1 while(condition) {
2 statements;
3 }
4
5 do {
6 statements;
7 } while(condition);
Braces are optional if the body is a single statement
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 70 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Control structures: while loop C++ 98
while loop syntax
1 while(condition) {
2 statements;
3 }
4
5 do {
6 statements;
7 } while(condition);
Braces are optional if the body is a single statement
Bad example
1 while (n != 1)
2 if (0 == n%2) n /= 2;
3 else n = 3 * n + 1;
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 70 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Control structures: jump statements C++ 98
break Exits the loop and continues after it
continue Goes immediately to next loop iteration
return Exits the current function
goto Can jump anywhere inside a function, avoid!
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 71 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Control structures: jump statements C++ 98
break Exits the loop and continues after it
continue Goes immediately to next loop iteration
return Exits the current function
goto Can jump anywhere inside a function, avoid!
Bad example
1 while (1) {
2 if (n == 1) break;
3 if (0 == n%2) {
4 std::cout << n << '\n';
5 n /= 2;
6 continue;
7 }
8 n = 3 * n + 1;
9 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 71 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Control structures C++ 11
Exercise: Control structures
Familiarise yourself with different kinds of control structures.
Re-implement them in different ways.
Go to exercises/control
Look at control.cpp
Compile it (make) and run the program (./control)
Work on the tasks that you find in README.md
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 72 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Headers and interfaces
2 Language basics
Core syntax and types
Arrays and Pointers
Scopes / namespaces
Class and enum types
References
Functions
Operators
Control structures
Headers and interfaces
Auto keyword
Inline keyword
Assertions
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 73 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Headers and interfaces C++ 98
Interface
Set of declarations defining some functionality
Put in a so-called “header file”
The implementation exists somewhere else
Header: hello.hpp
void printHello();
Usage: myfile.cpp
1 #include "hello.hpp"
2 int main() {
3 printHello();
4 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 74 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Preprocessor C++ 98
1 // file inclusion
2 #include "hello.hpp"
3 // macro constants and function-style macros
4 #define MY_GOLDEN_NUMBER 1746
5 #define CHECK_GOLDEN(x) if ((x) != MY_GOLDEN_NUMBER) \
6 std::cerr << #x " was not the golden number\n";
7 // compile time or platform specific configuration
8 #if defined(USE64BITS) || defined(__GNUG__)
9 using myint = std::uint64_t;
10 #elif
11 using myint = std::uint32_t;
12 #endif
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 75 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Preprocessor C++ 98
1 // file inclusion
2 #include "hello.hpp"
3 // macro constants and function-style macros
4 #define MY_GOLDEN_NUMBER 1746
5 #define CHECK_GOLDEN(x) if ((x) != MY_GOLDEN_NUMBER) \
6 std::cerr << #x " was not the golden number\n";
7 // compile time or platform specific configuration
8 #if defined(USE64BITS) || defined(__GNUG__)
9 using myint = std::uint64_t;
10 #elif
11 using myint = std::uint32_t;
12 #endif
Good practice: Use preprocessor only in very restricted cases
Conditional inclusion of headers
Customization for specific compilers/platforms
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 75 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Header include guards C++ 98
Problem: redefinition by accident
Headers may define new names (e.g. types)
Multiple (transitive) inclusions of a header would define those
names multiple times, which is a compile error
Solution: guard the content of your headers!
Include guards
1 #ifndef MY_HEADER_INCLUDED
2 #define MY_HEADER_INCLUDED
3 ... // header file content
4 #endif
Pragma once (non-standard)
1 #pragma once
2 ... // header file content
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 76 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Auto keyword
2 Language basics
Core syntax and types
Arrays and Pointers
Scopes / namespaces
Class and enum types
References
Functions
Operators
Control structures
Headers and interfaces
Auto keyword
Inline keyword
Assertions
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 77 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Auto keyword C++ 11
Reason of being
Many type declarations are redundant
They are often a source for compiler warnings and errors
Using auto prevents unwanted/unnecessary type conversions
1 std::vector<int> v;
2 float a = v[3]; // conversion intended?
3 int b = v.size(); // bug? unsigned to signed
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 78 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Auto keyword C++ 11
Reason of being
Many type declarations are redundant
They are often a source for compiler warnings and errors
Using auto prevents unwanted/unnecessary type conversions
1 std::vector<int> v;
2 float a = v[3]; // conversion intended?
3 int b = v.size(); // bug? unsigned to signed
Practical usage
1 std::vector<int> v;
2 auto a = v[3];
3 const auto b = v.size(); // std::size_t
4 int sum{0};
5 for (auto n : v) { sum += n; }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 78 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Loops, references, auto C++ 98
Exercise: Loops, references, auto
Familiarise yourself with range-based for loops and references
Go to exercises/loopsRefsAuto
Look at loopsRefsAuto.cpp
Compile it (make) and run the program (./loopsRefsAuto)
Work on the tasks that you find in loopsRefsAuto.cpp
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 79 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Inline keyword
2 Language basics
Core syntax and types
Arrays and Pointers
Scopes / namespaces
Class and enum types
References
Functions
Operators
Control structures
Headers and interfaces
Auto keyword
Inline keyword
Assertions
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 80 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Inline keyword C++ 98
Inline functions originally
Applies to a function to tell the compiler to inline it
That is, replace function calls by the function’s content
(similar to how a macro works)
Only a hint, compiler can still choose to not inline
Avoids call overhead at the cost of increasing binary size
Major side effect
The linker reduces the duplicated functions into one
An inline function definition can thus live in header files
1 inline int mult(int a, int b) {
2 return a * b;
3 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 81 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Inline keyword C++ 98
Inline functions nowadays
Compilers can judge far better when to inline or not
thus primary purpose is gone
Putting functions into headers became main purpose
Many types of functions are marked inline by default:
function templates
constexpr functions
class member functions
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 82 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Inline keyword C++ 17
Inline variables
Global (or static member) variable specified as inline
Same side effect, linker merges all occurrences into one
Allows to define global variables/constants in headers
1 // global.h
2 inline int count = 0;
3 inline const std::string filename = "output.txt";
4 // a.cpp
5 #include "global.h"
6 int f() { return count; }
7 // b.cpp
8 #include "global.h"
9 void g(int i) { count += i; }
Avoid global variables! Global constants are fine.
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 83 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Assertions
2 Language basics
Core syntax and types
Arrays and Pointers
Scopes / namespaces
Class and enum types
References
Functions
Operators
Control structures
Headers and interfaces
Auto keyword
Inline keyword
Assertions
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 84 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Assertions C++ 98
Checking invariants in a program
An invariant is a property that is guaranteed to be true during
certain phases of a program, and the program might crash or
yield wrong results if it is violated
“Here, ‘a’ should always be positive”
This can be checked using assert
The program will be aborted if the assertion fails
assert in practice - godbolt
1 #include <cassert>
2 double f(double a) {
3 // [...] do stuff with a
4 // [...] that should leave it positive
5 assert(a > 0.);
6 return std::sqrt(a);
7 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 85 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Assertions C++ 98
Checking invariants in a program
An invariant is a property that is guaranteed to be true during
certain phases of a program, and the program might crash or
yield wrong results if it is violated
“Here, ‘a’ should always be positive”
This can be checked using assert
The program will be aborted if the assertion fails
assert in practice - godbolt
% ./testAssert
Assertion failed: (a > 0.), function f,
file testAssert.cpp, line 5.
Abort trap: 6
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 85 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Assertions C++ 98
Good practice: Assert
Assertions are mostly for developers and debugging
Use them to check important invariants of your program
Prefer handling user-facing errors with helpful error
messages/exceptions
Assertions can impact the speed of a program
Assertions are disabled when the macro NDEBUG is defined
Decide if you want to disable them when you release code
Disabling assertions
Compile a program with NDEBUG defined:
g++ -DNDEBUG -O2 -W[...] test.cpp -o test.exe
1 double f(double a) {
2 assert(a > 0.); // no effect
3 return std::sqrt(a);
4 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 86 / 548
Intro base OO More exp Tool conc py Core Ptr NS Class/Enum Refs f() Op Control .h auto inline assert
Static Assert C++ 11
Checking invariants at compile time
To check invariants at compile time, use static_assert
The assertion can be any constant expression (see later)
The message argument is optional in C++ 17 and later
static_assert
1 double f(UserType a) {
2 static_assert(
3 std::is_floating_point<UserType>::value,
4 "This function expects floating-point types.");
5 return std::sqrt(a);
6 }
a.cpp: In function 'double f(UserType)':
a.cpp:3:9: error: static assertion failed: This function
expects floating-point types.
2 | static_assert(
| std::is_floating_point<UserType>::value,
| ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 87 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Object orientation (OO)
Operator overloading
Function objects
1 History and goals
Name Lookups
2 Language basics
4 Core modern C++
3 Object orientation (OO)
5 Expert C++
Objects and Classes
Inheritance
Constructors/destructors 6 Useful tools
Static members
Allocating objects 7 Concurrency
Advanced OO
Type casting 8 C++ and python
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 88 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Objects and Classes
3 Object orientation (OO)
Objects and Classes
Inheritance
Constructors/destructors
Static members
Allocating objects
Advanced OO
Type casting
Operator overloading
Function objects
Name Lookups
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 89 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
What are classes and objects C++ 98
Classes (or “user-defined types”)
C structs on steroids
with inheritance
with access control
including methods (aka. member functions)
Objects
instances of classes
A class encapsulates state and behavior of “something”
shows an interface
provides its implementation
status, properties
possible interactions
construction and destruction
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 90 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
My first class C++ 98
1 struct MyFirstClass {
2 int a;
3 void squareA() {
4 a *= a;
5 }
6 int sum(int b) { MyFirstClass
7 return a + b; int a;
8 } void squareA();
9 }; int sum(int b);
10
11 MyFirstClass myObj;
12 myObj.a = 2;
13
14 // let's square a
15 myObj.squareA();
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 91 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Separating the interface C++ 98
Header: MyClass.hpp User 1: main.cpp
1 #pragma once 1 #include "MyClass.hpp"
2 struct MyClass { 2 int main() {
3 int a; 3 MyClass mc;
4 void squareA(); 4 ...
5 }; 5 }
Implementation: MyClass.cpp User 2: fun.cpp
1 #include "MyClass.hpp" 1 #include "MyClass.hpp"
2 void MyClass::squareA() { 2 void f(MyClass& mc) {
3 a *= a; 3 mc.squareA();
4 } 4 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 92 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Implementing methods C++ 98
Good practice: Implementing methods
usually in .cpp, outside of class declaration
using the class name as “namespace”
short member functions can be in the header
some functions (templates, constexpr) must be in the header
1 void MyFirstClass::squareA() {
2 a *= a;
3 }
4
5 int MyFirstClass::sum(int b) {
6 return a + b;
7 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 93 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
this keyword C++ 98
How to know an object’s address?
Sometimes we need to pass a reference to ourself to a
different entity
For example to implement operators, see later
All class methods can use the keyword this
It returns the address of the current object
Its type is T* in the methods of a class T
1 void freeFunc(S & s);
2 struct S {
3 void memberFunc() { // Implicit S* parameter
4 freeFunc(*this); // Pass a reference to ourself
5 }
6 };
7 S s;
8 s.memberFunc(); // Passes &s implicitly
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 94 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Method overloading C++ 98
The rules in C++
overloading is authorized and welcome
signature is part of the method identity
but not the return type
1 struct MyFirstClass {
2 int a;
3 int sum(int b);
4 int sum(int b, int c);
5 }
6
7 int MyFirstClass::sum(int b) { return a + b; }
8
9 int MyFirstClass::sum(int b, int c) {
10 return a + b + c;
11 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 95 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Inheritance
3 Object orientation (OO)
Objects and Classes
Inheritance
Constructors/destructors
Static members
Allocating objects
Advanced OO
Type casting
Operator overloading
Function objects
Name Lookups
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 96 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
First inheritance C++ 98
1 struct MyFirstClass {
2 int a;
3 void squareA() { a *= a; }
4 }; MyFirstClass
5 struct MySecondClass : int a;
6 MyFirstClass { void squareA();
7 int b;
8 int sum() { return a + b; }
9 }; MySecondClass
10
int b;
11 MySecondClass myObj2; int sum();
12 myObj2.a = 2;
13 myObj2.b = 5;
14 myObj2.squareA();
15 int i = myObj2.sum(); // i = 9
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 97 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
First inheritance C++ 98
1 struct MyFirstClass {
2 int a;
3 void squareA() { a *= a; }
4 }; Memory layout
5 struct MySecondClass :
0x300C
6 MyFirstClass {
7 int b; 0x3008
b=5 0x3004
myobj2
8 int sum() { return a + b; }
9 }; a=2 0x3000
10 this pointer
11 MySecondClass myObj2;
12 myObj2.a = 2;
13 myObj2.b = 5;
14 myObj2.squareA();
15 int i = myObj2.sum(); // i = 9
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 97 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Managing access to class members C++ 98
public / private keywords
private allows access only within the class
public allows access from anywhere
The default for class is private
A struct is just a class that defaults to public access
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 98 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Managing access to class members C++ 98
public / private keywords
private allows access only within the class
public allows access from anywhere
The default for class is private
A struct is just a class that defaults to public access
1 class MyFirstClass { 9 MyFirstClass obj;
2 public: 10 obj.a = 5; // error !
3 void setA(int x); 11 obj.setA(5); // ok
4 int getA(); 12 obj.squareA();
5 void squareA(); 13 int b = obj.getA();
6 private:
7 int a;
8 };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 98 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Managing access to class members C++ 98
public / private keywords
private allows access only within the class
public allows access from anywhere
The default for class is private
A struct is just a class that defaults to public access
1 class MyFirstClass { 9 MyFirstClass obj;
2 public: 10 obj.a = 5; // error !
3 void setA(int x); 11 obj.setA(5); // ok
4 int getA(); 12 obj.squareA();
5 void squareA(); 13 int b = obj.getA();
6 private:
7 int a;
This breaks MySecondClass !
8 };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 98 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Managing access to class members(2) C++ 98
Solution is protected keyword
Gives access to classes inheriting from base class
1 class MyFirstClass { 13 class MySecondClass :
2 public: 14 public MyFirstClass {
3 void setA(int a); 15 public:
4 int getA(); 16 int sum() {
5 void squareA(); 17 return a + b;
6 protected: 18 }
7 int a; 19 private:
8 }; 20 int b;
21 };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 99 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Managing inheritance privacy C++ 98
Inheritance can be public, protected or private
It influences the privacy of inherited members for external code.
The code of the class itself is not affected
public privacy of inherited members remains unchanged
protected inherited public members are seen as protected
private all inherited members are seen as private
this is the default for classes if nothing is specified
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 100 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Managing inheritance privacy C++ 98
Inheritance can be public, protected or private
It influences the privacy of inherited members for external code.
The code of the class itself is not affected
public privacy of inherited members remains unchanged
protected inherited public members are seen as protected
private all inherited members are seen as private
this is the default for classes if nothing is specified
Net result for external code
only public members of public inheritance are accessible
Net result for code in derived classes
only public and protected members of public and protected
parents are accessible
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 100 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Managing inheritance privacy - public C++ 98
MyFirstClass 1 void funcSecond() {
private: 2 int a = priv; // Error
int priv; 3 int b = prot; // OK
protected: 4 int c = pub; // OK
int prot; 5 }
public: 6 void funcThird() {
int pub; 7 int a = priv; // Error
8 int b = prot; // OK
public
9 int c = pub; // OK
MySecondClass 10 }
void funcSecond(); 11 void extFunc(MyThirdClass t) {
public 12 int a = t.priv; // Error
13 int b = t.prot; // Error
MyThirdClass 14 int c = t.pub; // OK
void funcThird(); 15 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 101 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Managing inheritance privacy - protected C++ 98
MyFirstClass 1 void funcSecond() {
private: 2 int a = priv; // Error
int priv; 3 int b = prot; // OK
protected: 4 int c = pub; // OK
int prot; 5 }
public: 6 void funcThird() {
int pub; 7 int a = priv; // Error
8 int b = prot; // OK
protected
9 int c = pub; // OK
MySecondClass 10 }
void funcSecond(); 11 void extFunc(MyThirdClass t) {
public 12 int a = t.priv; // Error
13 int b = t.prot; // Error
MyThirdClass 14 int c = t.pub; // Error
void funcThird(); 15 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 102 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Managing inheritance privacy - private C++ 98
MyFirstClass 1 void funcSecond() {
private: 2 int a = priv; // Error
int priv; 3 int b = prot; // OK
protected: 4 int c = pub; // OK
int prot; 5 }
public: 6 void funcThird() {
int pub; 7 int a = priv; // Error
8 int b = prot; // Error
private
9 int c = pub; // Error
MySecondClass 10 }
void funcSecond(); 11 void extFunc(MyThirdClass t) {
public 12 int a = t.priv; // Error
13 int b = t.prot; // Error
MyThirdClass 14 int c = t.pub; // Error
void funcThird(); 15 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 103 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Final class C++ 11
Idea
make sure you cannot inherit from a given class
by declaring it final
Practically
1 struct Base final {
2 ...
3 };
4 struct Derived : Base { // compiler error
5 ...
6 };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 104 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Constructors/destructors
3 Object orientation (OO)
Objects and Classes
Inheritance
Constructors/destructors
Static members
Allocating objects
Advanced OO
Type casting
Operator overloading
Function objects
Name Lookups
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 105 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Class constructors and destructors C++ 98
Concept
special functions called when building/destroying an object
a class can have several constructors, but only one destructor
the constructors have the same name as the class
same for the destructor with a leading ~
1 class C { 10 // note: special notation for
2 public: 11 // initialization of members
3 C(); 12 C::C() : a(0) {}
4 C(int a); 13
5 ~C(); 14 C::C(int a) : a(a) {}
6 ... 15
7 protected: 16 C::~C() {}
8 int a;
9 };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 106 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Class constructors and destructors C++ 98
1 class Vector {
2 public:
3 Vector(int n);
4 ~Vector();
5 void setN(int n, int value);
6 int getN(int n);
7 private:
8 int len;
9 int* data;
10 };
11 Vector::Vector(int n) : len(n) {
12 data = new int[n];
13 }
14 Vector::~Vector() {
15 delete[] data;
16 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 107 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Constructors and inheritance C++ 98
1 struct First {
2 int a;
3 First() {} // leaves a uninitialized
4 First(int a) : a(a) {}
5 };
6 struct Second : First {
7 int b;
8 Second();
9 Second(int b);
10 Second(int a, int b);
11 };
12 Second::Second() : First(), b(0) {}
13 Second::Second(int b) : b(b) {} // First() implicitly
14 Second::Second(int a, int b) : First(a), b(b) {}
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 108 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Copy constructor C++ 11
Concept
special constructor called for replicating an object
takes a single parameter of type const & to class
provided by the compiler if not declared by the user
in order to forbid copy, use = delete (see next slides)
or private copy constructor with no implementation in C++ 98
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 109 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Copy constructor C++ 11
Concept
special constructor called for replicating an object
takes a single parameter of type const & to class
provided by the compiler if not declared by the user
in order to forbid copy, use = delete (see next slides)
or private copy constructor with no implementation in C++ 98
1 struct C {
2 C();
3 C(const C &other);
4 };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 109 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Copy constructor C++ 11
Concept
special constructor called for replicating an object
takes a single parameter of type const & to class
provided by the compiler if not declared by the user
in order to forbid copy, use = delete (see next slides)
or private copy constructor with no implementation in C++ 98
1 struct C {
2 C();
3 C(const C &other);
4 };
Good practice: The rule of 3/5 (C++ 98/11) - cppreference
if a class needs a custom destructor, a copy/move constructor or a
copy/move assignment operator, it should have all three/five.
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 109 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Class Constructors and Destructors C++ 98
1 class Vector {
2 public:
3 Vector(int n);
4 Vector(const Vector &other);
5 ~Vector();
6 private:
7 int len; int* data;
8 };
9 Vector::Vector(int n) : len(n) {
10 data = new int[n];
11 }
12 Vector::Vector(const Vector &other) : len(other.len) {
13 data = new int[len];
14 std::copy(other.data, other.data + len, data);
15 }
16 Vector::~Vector() { delete[] data; }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 110 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Explicit unary constructor C++ 98
Concept
A constructor with a single non-default parameter can be used
by the compiler for an implicit conversion.
Example - godbolt
1 void print(const Vector & v) {
2 std::cout << "printing v elements...\n";
3 }
4
5 int main {
6 // calls Vector::Vector(int n) to construct a Vector
7 // then calls print with that Vector
8 print(3);
9 };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 111 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Explicit unary constructor C++ 98
Concept
The keyword explicit forbids such implicit conversions.
It is recommended to use it systematically, except in special
cases.
1 class Vector {
2 public:
3 explicit Vector(int n);
4 Vector(const Vector &other);
5 ~Vector();
6 ...
7 };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 112 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Defaulted Constructor C++ 11
Idea
avoid empty default constructors like ClassName() {}
declare them as = default
Details
without a user-defined constructor, a default one is provided
any user-defined constructor disables the default one
but the default one can be requested explicitly
rule can be more subtle depending on data members
Practically
1 Class() = default; // provide default if possible
2 Class() = delete; // disable default constructor
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 113 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Delegating constructor C++ 11
Idea
avoid replication of code in several constructors
by delegating to another constructor, in the initialization list
Practically
1 struct Delegate {
2 int m_i;
3 Delegate(int i) : m_i(i) {
4 ... complex initialization ...
5 }
6 Delegate() : Delegate(42) {}
7 };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 114 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Constructor inheritance C++ 11
Idea
avoid having to re-declare parent’s constructors
by stating that we inherit all parent constructors
derived class can add more constructors
Practically
1 struct Base {
2 Base(int a); // ctor 1
3 };
4 struct Derived : Base {
5 using Base::Base;
6 Derived(int a, int b); // ctor 2
7 };
8 Derived d{5}; // calls ctor 1
9 Derived d{5, 6}; // calls ctor 2
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 115 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Member initialization C++ 11
Idea
avoid redefining same default value for members n times
by defining it once at member declaration time
Practically
1 struct Base {
2 int a{5}; // also possible: int a = 5;
3 Base() = default;
4 Base(int _a) : a(_a) {}
5 };
6 struct Derived : Base {
7 int b{6};
8 using Base::Base;
9 };
10 Derived d1; // a = 5, b = 6
11 Derived d2{7}; // a = 7, b = 6
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 116 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Calling constructors C++ 11
After object declaration, arguments within {}
1 struct A {
2 int a;
3 float b;
4 A();
5 A(int);
6 A(int, int);
7 };
8
9 A a{1,2}; // A::A(int, int)
10 A a{1}; // A::A(int)
11 A a{}; // A::A()
12 A a; // A::A()
13 A a = {1,2}; // A::A(int, int)
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 117 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Calling constructors the old way C++ 98
Arguments are given within (), aka C++ 98 nightmare
1 struct A {
2 int a;
3 float b;
4 A();
5 A(int);
6 A(int, int);
7 };
8
9 A a(1,2); // A::A(int, int)
10 A a(1); // A::A(int)
11 A a(); // declaration of a function!
12 A a; // A::A()
13 A a = (1,2); // A::A(int), comma operator!
14 A a = {1,2}; // not allowed
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 118 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Constructing arrays and vectors C++ 11
List of items given within {}
10 int ip[3]{1,2,3};
11 int* ip = new int[3]{1,2,3}; // not allowed in C++98
12 std::vector<int> v{1,2,3}; // same
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 119 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Static members
3 Object orientation (OO)
Objects and Classes
Inheritance
Constructors/destructors
Static members
Allocating objects
Advanced OO
Type casting
Operator overloading
Function objects
Name Lookups
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 120 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Static members C++ 98
Concept
members attached to a class rather than to an object
usable with or without an instance of the class
identified by the static keyword
Static.hpp
1 class Text {
2 public:
3 static std::string upper(std::string);
4 private:
5 static int callsToUpper; // add `inline` in C++17
6 };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 121 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Static members C++ 98
Concept
members attached to a class rather than to an object
usable with or without an instance of the class
identified by the static keyword
Static.cpp
1 #include "Static.hpp"
2 int Text::callsToUpper = 0; // required before C++17
3
4 std::string Text::upper(std::string lower) {
5 callsToUpper++;
6 // convert lower to upper case
7 // return ...;
8 }
9 std::string uppers = Text::upper("my text");
10 // now Text::callsToUpper is 1
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 121 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Allocating objects
3 Object orientation (OO)
Objects and Classes
Inheritance
Constructors/destructors
Static members
Allocating objects
Advanced OO
Type casting
Operator overloading
Function objects
Name Lookups
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 122 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Process memory organization C++ 98
4 main areas
the code segment for the machine code of the executable
the data segment for global variables
the heap for dynamically allocated variables
the stack for parameters of functions and local variables
Memory layout
heap
...
...
stack
data segment
code segment
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 123 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
The Stack C++ 98
Main characteristics
allocation on the stack stays valid for the duration of the
current scope. It is destroyed when it is popped off the stack.
memory allocated on the stack is known at compile time and
can thus be accessed through a variable.
the stack is relatively small, it is not a good idea to allocate
large arrays, structures or classes
each thread in a process has its own stack
allocations on the stack are thus “thread private”
and do not introduce any thread safety issues
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 124 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Object allocation on the stack C++ 98
On the stack
objects are created on variable definition (constructor called)
objects are destructed when out of scope (destructor is called)
1 int f() {
2 MyFirstClass a{3}; // constructor called
3 ...
4 } // destructor called
5
6 int g() {
7 MyFirstClass a; // default constructor called
8 ...
9 } // destructor called
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 125 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
The Heap C++ 98
Main characteristics
Allocated memory stays allocated until it is specifically
deallocated
beware memory leaks
Dynamically allocated memory must be accessed through
pointers
large arrays, structures, or classes should be allocated here
there is a single, shared heap per process
allows to share data between threads
introduces race conditions and thread safety issues!
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 126 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Object allocation on the heap C++ 98
On the heap
objects are created by calling new (constructor is called)
objects are destructed by calling delete (destructor is called)
1 int f() {
2 // default constructor called
3 MyFirstClass *a = new MyFirstClass;
4 delete a; // destructor is called
5 }
6 int g() {
7 // constructor called
8 MyFirstClass *a = new MyFirstClass{3};
9 } // memory leak !!!
Good practice: Prefer smart pointers over new/delete
Prefer smart pointers to manage objects (discussed later)
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 127 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Array allocation on the heap C++ 98
Arrays on the heap
arrays of objects are created by calling new[]
default constructor is called for each object of the array
arrays of object are destructed by calling delete[]
destructor is called for each object of the array
1 int f() {
2 // default constructor called 10 times
3 MyFirstClass *a = new MyFirstClass[10];
4 ...
5 delete[] a; // destructor called 10 times
6 }
Good practice: Prefer containers over new-ed arrays
Prefer containers to manage collections of objects (discussed later)
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 128 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Advanced OO
3 Object orientation (OO)
Objects and Classes
Inheritance
Constructors/destructors
Static members
Allocating objects
Advanced OO
Type casting
Operator overloading
Function objects
Name Lookups
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 129 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Polymorphism C++ 98
the concept
objects actually have multiple types simultaneously
and can be used as any of them
1 Polygon p; Drawable
2
3 int f(Drawable & d) {...}
4 f(p); //ok Shape
5
6 try {
7 throw p; Polygon
8 } catch (Shape & e) {
9 // will be caught
10 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 130 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Polymorphism C++ 98
the concept
objects actually have multiple types simultaneously
and can be used as any of them
1 Polygon p; Memory layout
2
3 int f(Drawable & d) {...} 0x3020
4 f(p); //ok 0x301C
5
Polygon.nLines 0x3018
... 0x3014
6 try {
7 throw p; Shape.b 0x3010
Polygon
8 } catch (Shape & e) { Shape.a 0x300C
9 // will be caught ... 0x3008
10 } Drawable.b 0x3004
Drawable.a 0x3000
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 130 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Polymorphism C++ 98
the concept
objects actually have multiple types simultaneously
and can be used as any of them
1 Polygon p; Memory layout
2
3 int f(Drawable & d) {...} 0x3020
4 f(p); //ok 0x301C
5
Polygon.nLines 0x3018
... 0x3014
6 try {
7 throw p; Shape.b 0x3010
8 } catch (Shape & e) { Shape.a 0x300C
9 // will be caught ... 0x3008
Drawable
10 } Drawable.b 0x3004
Drawable.a 0x3000
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 130 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Polymorphism C++ 98
the concept
objects actually have multiple types simultaneously
and can be used as any of them
1 Polygon p; Memory layout
2
3 int f(Drawable & d) {...} 0x3020
4 f(p); //ok 0x301C
5
Polygon.nLines 0x3018
... 0x3014
6 try {
7 throw p; Shape.b 0x3010
} catch (Shape & e) { Shape.a 0x300C
Shape
8
9 // will be caught ... 0x3008
10 } Drawable.b 0x3004
Drawable.a 0x3000
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 130 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Inheritance privacy and polymorphism C++ 98
Only public base classes are visible to outside code
private and protected bases are not
this may restrict usage of polymorphism
1 Polygon p; Drawable
2
private
3 int f(Drawable & d) {...}
4 f(p); // Not ok anymore Shape
5
6 try { public
7 throw p; Polygon
8 } catch (Shape & e) {
9 // ok, will be caught
10 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 131 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Method overriding C++ 98
the idea
a method of the parent class can be replaced in a derived class
but which one is called?
1 Polygon p; Drawable
2 p.draw(); // ? void draw();
3
4 Shape & s = p;
5 s.draw(); // ? Shape
Polygon
void draw();
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 132 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Virtual methods C++ 98
the concept
methods can be declared virtual
for these, the most derived object’s implementation is used
(i.e. the dynamic type behind a pointer/reference)
for non-virtual methods, the static type of the variable decides
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 133 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Virtual methods C++ 98
the concept
methods can be declared virtual
for these, the most derived object’s implementation is used
(i.e. the dynamic type behind a pointer/reference)
for non-virtual methods, the static type of the variable decides
1 Polygon p; Drawable
2 p.draw(); // Polygon.draw void draw();
3
4 Shape & s = p;
5 s.draw(); // Drawable.draw Shape
Polygon
void draw();
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 133 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Virtual methods C++ 98
the concept
methods can be declared virtual
for these, the most derived object’s implementation is used
(i.e. the dynamic type behind a pointer/reference)
for non-virtual methods, the static type of the variable decides
1 Polygon p; Drawable
2 p.draw(); // Polygon.draw virtual void draw();
3
4 Shape & s = p;
5 s.draw(); // Polygon.draw Shape
Polygon
void draw();
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 133 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Virtual methods - implications C++ 11
Mechanics
virtual methods are dispatched at run time
while non-virtual methods are bound at compile time
they also imply extra storage and an extra indirection
practically, the object stores a pointer to the correct method
in a so-called “virtual table” (“vtable”)
Consequences
virtual methods are “slower” than standard ones
and they can rarely be inlined
templates are an alternative for performance-critical cases
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 134 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
override keyword C++ 11
Principle
when overriding a virtual method
the override keyword should be used
the virtual keyword is then optional
Practically
1 struct Base {
2 virtual void some_func(float);
3 };
4 struct Derived : Base {
5 void some_func(float) override;
6 };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 135 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Why was override keyword introduced? C++ 11
To detect the mistake in the following code :
Without override (C++ 98)
1 struct Base {
2 virtual void some_func(float);
3 };
4 struct Derived : Base {
5 void some_func(double); // oops !
6 };
with override, you would get a compiler error
if you forget override when you should have it, you get a
compiler warning
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 136 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
final keyword C++ 11
Idea
make sure you cannot further override a given virtual method
by declaring it final
Practically
1 struct Base {
2 virtual void some_func(float);
3 };
4 struct Intermediate : Base {
5 void some_func(float) final;
6 };
7 struct Derived : Intermediate {
8 void some_func(float) override; // error
9 };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 137 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Pure Virtual methods C++ 11
Concept
unimplemented methods that must be overridden
marked by = 0 in the declaration
makes their class abstract
only non-abstract classes can be instantiated
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 138 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Pure Virtual methods C++ 11
Concept
unimplemented methods that must be overridden
marked by = 0 in the declaration
makes their class abstract
only non-abstract classes can be instantiated
1 // Error : abstract class Drawable
2 Shape s; virtual void draw() = 0;
3
4 // ok, draw has been implemented
5 Polygon p; Shape
6
7 // Shape type still usable
Polygon
8 Shape & s = p;
void draw() override;
9 s.draw();
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 138 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Polymorphism and destruction C++ 98
Owning base pointers
We sometimes need to maintain owning pointers to base classes:
1 struct Drawable {
2 virtual void draw() = 0;
3 };
4 Drawable* getImpl();
5
6 Drawable* p = getImpl();
7 p->draw();
8 delete p;
What happens when p is deleted?
What if a class deriving from Drawable has a destructor?
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 139 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Polymorphism and destruction C++ 98
Owning base pointers
We sometimes need to maintain owning pointers to base classes:
1 struct Drawable {
2 virtual void draw() = 0;
3 };
4 std::unique_ptr<Drawable> getImpl(); // better API
5
6 auto p = getImpl();
7 p->draw();
What happens when p is deleted?
What if a class deriving from Drawable has a destructor?
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 139 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Polymorphism and destruction C++ 11
Virtual destructors
We can mark a destructor as virtual
This selects the right destructor based on the runtime type
1 struct Drawable {
2 virtual ~Drawable() = default;
3 virtual void draw() = 0;
4 };
5 Drawable* p = getImpl(); // returns derived obj.
6 p->draw();
7 delete p; // dynamic dispatch to right destructor
Good practice: Virtual destructors
If you expect users to inherit from your class and override methods
(i.e. use your class polymorphically), declare its destructor virtual
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 140 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Pure Abstract Class aka Interface C++ 11
Definition of pure abstract class
a class that has
no data members
all its methods pure virtual
a virtual destructor
the equivalent of an Interface in Java
1 struct Drawable { Drawable
2 virtual ~Drawable() virtual void draw() = 0;
3 = default;
4 virtual void draw() = 0;
5 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 141 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Overriding overloaded methods C++ 98
Concept
overriding an overloaded method will hide the others
unless you inherit them using using
1 struct BaseClass {
2 virtual int foo(std::string);
3 virtual int foo(int);
4 };
5 struct DerivedClass : BaseClass {
6 using BaseClass::foo;
7 int foo(std::string) override;
8 };
9 DerivedClass dc;
10 dc.foo(4); // error if no using
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 142 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Polymorphism C++ 98
Exercise: Polymorphism
go to exercises/polymorphism
look at the code
open trypoly.cpp
create a Pentagon, call its perimeter method
create a Hexagon, call its perimeter method
create a Hexagon, call its parent’s perimeter method
retry with virtual methods
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 143 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Multiple Inheritance C++ 98
Concept
one class can inherit from multiple parents
Polygon 1 class TextBox :
2 public Rectangle, Text {
3 // inherits from both
Rectangle Text 4 // publicly from Rectangle
5 // privately from Text
6 }
TextBox
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 144 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
The diamond shape C++ 98
Definition
situation when one class inherits several times from a given
grand parent
Problem
are the members of the grand parent replicated?
Drawable
Rectangle Text
TextBox
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 145 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Virtual inheritance C++ 98
Solution
inheritance can be virtual or not
virtual inheritance will “share” parents
standard inheritance will replicate them
most derived class will call the virtual base class’s constructor
1 class Text : public virtual Drawable {...};
2 class Rectangle : public virtual Drawable {...};
Drawable Drawable1 Drawable2
l v
ua irt
rt ua
vi l
Rectangle Text Rectangle Text
TextBox TextBox
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 146 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Multiple inheritance advice C++ 98
Good practice: Avoid multiple inheritance
Except for inheriting from interfaces
And for rare special cases
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 147 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Multiple inheritance advice C++ 98
Good practice: Avoid multiple inheritance
Except for inheriting from interfaces
And for rare special cases
Good practice: Absolutely avoid diamond-shaped inheritance
This is a sign that your architecture is not correct
In case you are tempted, think twice and change your mind
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 147 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Virtual inheritance C++ 98
Exercise: Virtual inheritance
go to exercisescode/virtual_inheritance
look at the code
open trymultiherit.cpp
create a TextBox and call draw
Fix the code to call both draws by using types
retry with virtual inheritance
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 148 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Type casting
3 Object orientation (OO)
Objects and Classes
Inheritance
Constructors/destructors
Static members
Allocating objects
Advanced OO
Type casting
Operator overloading
Function objects
Name Lookups
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 149 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Type casting C++ 98
5 types of casts in C++ - These 2 should be used
static_cast<Target>(arg)
converts type if the static types allow it
including using implicit conversion
essentially compile time
dynamic_cast<Target>(arg)
checks if object at address of “arg” is convertible to Target
throws std::bad_cast or returns nullptr if it’s not
essentially run time
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 150 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Type casting example C++ 98
1 struct A{ virtual ~A()=default; } a;
2 struct B : A {} b;
3
4 A& c = static_cast<A&>(b); // OK. b is also an A
5 B& d = static_cast<B&>(a); // UB: a is not a B
6 B& e = static_cast<B&>(c); // OK. c is a B
7
8 B& f = dynamic_cast<B&>(c); // OK, c is a B
9 B& g = dynamic_cast<B&>(a); // throws std::bad_cast
10 B& foo(A& h) {
11 return dynamic_cast<B&>(h);
12 }
13 B& i = foo(c); // OK, c is a B
14
15 B* j = dynamic_cast<B*>(&a); // nullptr. a not a B.
16 if (j != nullptr) {
17 // Will not reach this
18 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 151 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Type casting C++ 98
5 types of casts in C++ - These 3 should be avoided
const_cast<Target>(arg)
removes (or adds) constness from a type
if you think you need this, rather improve your design!
reinterpret_cast<Target>(arg)
changes type irrespective of what ‘arg‘ is
almost never a good idea!
C-style: (Target)arg
Force-changes type in C-style. No checks. Don’t use.
Casts to avoid
1 void func(A const & a) {
2 A& ra = a; // Error: not const
3 A& ra = const_cast<A&>(a); // Compiles. Bad design!
4 // Evil! Don't do this:
5 B* b = reinterpret_cast<B*>(&a);
6 B* b = (B*)&a;
7 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 152 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Operator overloading
3 Object orientation (OO)
Objects and Classes
Inheritance
Constructors/destructors
Static members
Allocating objects
Advanced OO
Type casting
Operator overloading
Function objects
Name Lookups
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 153 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Operator overloading example C++ 98
1 struct Complex {
2 float m_real, m_imaginary;
3 Complex(float real, float imaginary);
4 Complex operator+(const Complex& other) {
5 return Complex(m_real + other.m_real,
6 m_imaginary + other.m_imaginary);
7 }
8 };
9
10 Complex c1{2, 3}, c2{4, 5};
11 Complex c3 = c1 + c2; // (6, 8)
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 154 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Operator overloading C++ 98
Defining operators for a class
implemented as a regular method
either inside the class, as a member function
or outside the class (not all)
with a special name (replace @ by anything)
Expression As member As non-member
@a (a).operator@() operator@(a)
a@b (a).operator@(b) operator@(a,b)
a=b (a).operator=(b) cannot be non-member
a(b...) (a).operator()(b...) cannot be non-member
a[b] (a).operator[](b) cannot be non-member
a-> (a).operator->() cannot be non-member
a@ (a).operator@(0) operator@(a,0)
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 155 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Why have non-member operators? C++ 98
Symmetry
1 struct Complex {
2 float m_real, m_imaginary;
3 Complex operator+(float other) {
4 return Complex(m_real + other, m_imaginary);
5 }
6 };
7 Complex c1{2.f, 3.f};
8 Complex c2 = c1 + 4.f; // ok
9 Complex c3 = 4.f + c1; // not ok !!
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 156 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Why have non-member operators? C++ 98
Symmetry
1 struct Complex {
2 float m_real, m_imaginary;
3 Complex operator+(float other) {
4 return Complex(m_real + other, m_imaginary);
5 }
6 };
7 Complex c1{2.f, 3.f};
8 Complex c2 = c1 + 4.f; // ok
9 Complex c3 = 4.f + c1; // not ok !!
10 Complex operator+(float a, const Complex& obj) {
11 return Complex(a + obj.m_real, obj.m_imaginary);
12 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 156 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Other reason to have non-member operators? C++ 98
Extending existing classes
1 struct Complex {
2 float m_real, m_imaginary;
3 Complex(float real, float imaginary);
4 };
5
6 std::ostream& operator<<(std::ostream& os,
7 const Complex& obj) {
8 os << "(" << obj.m_real << ", "
9 << obj.m_imaginary << ")";
10 return os;
11 }
12 Complex c1{2.f, 3.f};
13 std::cout << c1 << std::endl; // Prints '(2, 3)'
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 157 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Friend declarations C++ 98
Concept
Functions/classes can be declared friend within a class scope
They gain access to all private/protected members
Useful for operators such as a + b
Don’t abuse friends to go around a wrongly designed interface
Avoid unexpected modifications of class state in a friend
operator+ as a friend
1 class Complex {
2 float m_r, m_i;
3 friend Complex operator+(Complex const & a, Complex const & b);
4 public:
5 Complex ( float r, float i ) : m_r(r), m_i(i) {}
6 };
7 Complex operator+(Complex const & a, Complex const & b) {
8 return Complex{ a.m_r+b.m_r, a.m_i+b.m_i };
9 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 158 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Operators C++ 98
Exercise: Operators
Write a simple class representing a fraction and pass all tests
go to exercises/operators
look at operators.cpp
inspect main and complete the implementation of
class Fraction step by step
you can comment out parts of main to test in between
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 159 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Function objects
3 Object orientation (OO)
Objects and Classes
Inheritance
Constructors/destructors
Static members
Allocating objects
Advanced OO
Type casting
Operator overloading
Function objects
Name Lookups
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 160 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Function objects C++ 98
Concept
also known as functors (no relation to functors in math)
a class that implements operator()
allows to use objects in place of functions
with constructors and data members
1 struct Adder {
2 int m_increment;
3 Adder(int increment) : m_increment(increment) {}
4 int operator()(int a) { return a + m_increment; }
5 };
6 Adder inc1{1}, inc10{10};
7 int i = 3;
8 int j = inc1(i); // 4
9 int k = inc10(i); // 13
10 int l = Adder{25}(i); // 28
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 161 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Function objects C++ 20
Function objects as function arguments - godbolt
1 int count_if(const auto& range, auto predicate) {
2 int count = 0; // ↑ template (later)
3 for (const auto& e : range)
4 if (predicate(e)) count++;
5 return count;
6 }
7 struct IsBetween {
8 int lower, upper;
9 bool operator()(int value) const {
10 return lower < value && value < upper;
11 }
12 };
13 int arr[]{1, 2, 3, 4, 5, 6, 7};
14 std::cout << count_if(arr, IsBetween{2, 6}); // 3
15 // prefer: std::ranges::count_if
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 162 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Name Lookups
3 Object orientation (OO)
Objects and Classes
Inheritance
Constructors/destructors
Static members
Allocating objects
Advanced OO
Type casting
Operator overloading
Function objects
Name Lookups
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 163 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Basics of name lookup C++ 98
Example code
1 std::cout << std::endl;
How to find the declaration of a name?
Mainly 2 cases :
qualified lookup, for names preceded by ‘::’
here cout and endl
name is only looked for in given class/namespace/enum class
unqualified lookup
here for std and operator<<
name is looked for in a sequence of scopes until found
remaining scopes are not examined
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 164 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Unqualified name lookup and ADL C++ 98
Ordered list of scopes (simplified)
file (only for global level usage)
current namespace/block, enclosing namespaces/blocks, etc...
current class if any, base classes if any, etc...
for a call expression (e.g. f(a, b) or a + b), Argument
Dependent Lookup (ADL)
Argument Dependent Lookup (simplified)
To find a function name (including operators), the compiler also
examines the arguments. For each argument, it searches:
class, if any
direct and indirect base classes, if any
enclosing namespace
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 165 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
ADL consequences (1) C++ 98
Use standalone/non-member functions
When a method is not accessing the private part of a class, make
it a function in the same namespace
Don’t write : Prefer :
1 namespace MyNS { 6 namespace MyNS {
2 struct A { 7 struct A { ... };
3 T func(...); 8 T func(const A&, ..);
4 }; 9 }
5 }
Advantages :
minimal change in user code, func still feels part of class A
makes sure func does not touch internal state of A
Notes :
non-member func has to be in same namespace as A
please avoid global namespace
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 166 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
ADL consequences (2) C++ 98
Customization points and using
Don’t write : Prefer :
1 N::A a,b; 3 N::A a,b;
2 std::swap(a, b); 4 using std::swap;
5 swap(a, b);
Advantages :
allows to use std::swap by default
but benefits from any dedicated overload
6 namespace N {
7 class A { ... };
8 // optimized swap for A
9 void swap(A&, A&);
10 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 167 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Hidden Friends C++ 11
Hidden friends
Friend functions defined in class scope are “hidden friends”
Without any declaration outside the class
They are not member functions (no access to this)
operator<< as hidden friend
1 class Complex {
2 float m_real, m_imag;
3 public:
4 Complex(float, float) { ... }
5 friend
6 std::ostream & operator<<(std::ostream & os,
7 Complex const & c) {
8 return os << c.m_real << " + " << c.m_imag << "i";
9 }
10 };
11 std::cout << Complex{2.f, 3.f}; // Prints 2 + 3i
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 168 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Hidden Friends and ADL C++ 11
Advantages of hidden friends
Are only found via ADL, e.g. std::cout << complex;
Compiler needs to consider less functions during ordinary
name lookup (faster compilation)
Avoid accidental implicit conversions
Accidental conversions - two examples in one
1 std::ostream & operator<< // out-of-class definition
2 (std::ostream & os, Complex const & c) { ... }
3 struct Fraction {
4 int num, denom;
5 operator Complex() const { ... } // case 1: conversion op
6 };
7 Complex::Complex(Fraction f); // or case 2: converting ctor
8 std::cout << Fraction{2,4}; // Prints 0.5 + 0i, would call:
9 //case 1: operator<<(std::cout, Fraction{2,4}.operator Complex());
10 //case 2: operator<<(std::cout, Complex(Fraction{2, 3}));
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 169 / 548
Intro base OO More exp Tool conc py OO inherit construct static new advOO cast Op () ADL
Good practice for operator overloading C++ 98
Good practice: Operator overloading
Must declare in-class, as member operators:
operator=, operator(), operator[], operator->
Prefer in-class declaration, as member operators:
compound assignment operators, e.g. operator+=
unary operators
e.g. operator++, operator--, operator!, unary operator-
(negate), dereference operator operator*
Prefer definition in-class as hidden friends:
binary arithmetic operators, e.g. operator+, operator|
binary logical operators, e.g. operator<
stream operators, e.g. operator<<
Avoid overloading:
Address-of operator&
Boolean logic operators, e.g. operator||
Comma operator operator,
Member dereference operators operator->*
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 170 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
++
Core modern C
Lambdas
The STL
1 History and goals
More STL
Ranges
2 Language basics RAII and smart pointers
Initialization
3 Object orientation (OO)
5 Expert C++
4 Core modern C++
Constness 6 Useful tools
Constant Expressions
Exceptions
7 Concurrency
Move semantics
Copy elision
Templates 8 C++ and python
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 171 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Constness
4 Core modern C++
Constness
Constant Expressions
Exceptions
Move semantics
Copy elision
Templates
Lambdas
The STL
More STL
Ranges
RAII and smart pointers
Initialization
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 172 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Constness C++ 98
The const keyword
indicates that the element to the left is constant
when nothing on the left, applies to the right
this element won’t be modifiable in the future
this is all checked at compile time
1 int const i = 6;
2 const int i = 6; // equivalent
3
4 // error: i is constant
5 i = 5;
6
7 auto const j = i; // works with auto
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 173 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Constness and pointers C++ 98
1 int a = 1, b = 2;
2
3 int const *i = &a; // pointer to const int
4 *i = 5; // error, int is const
5 i = &b; // ok, pointer is not const
6
7 int * const j = &a; // const pointer to int
8 *j = 5; // ok, value can be changed
9 j = &b; // error, pointer is const
10
11 int const * const k = &a; // const pointer to const int
12 *k = 5; // error, value is const
13 k = &b; // error, pointer is const
14
15 int const & l = a; // reference to const int
16 l = b; // error, reference is const
17
18 int const & const l = a; // compile error
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 174 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Member function constness C++ 98
The const keyword for member functions
indicates that the function does not modify the object
in other words, this is a pointer to a constant object
1 struct Example {
2 void foo() const {
3 // type of 'this' is 'Example const*'
4 data = 0; // Error: member function is const
5 }
6 void foo() { // ok, overload
7 data = 1; // ok, 'this' is 'Example*'
8 }
9 int data;
10 };
11 Example const e1; e1.foo(); // calls const foo
12 Example e2; e2.foo(); // calls non-const foo
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 175 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Member function constness C++ 98
Constness is part of the type
T const and T are different types
but: T is automatically converted to T const when needed
1 void change(int & a);
2 void read(int const & a);
3
4 int a = 0;
5 int const b = 0;
6
7 change(a); // ok
8 change(b); // error
9 read(a); // ok
10 read(b); // ok
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 176 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
constness C++ 98
Exercise: Constness
go to exercises/constness
open constplay.cpp
try to find out which lines won’t compile
check your guesses by compiling for real
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 177 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Constant Expressions
4 Core modern C++
Constness
Constant Expressions
Exceptions
Move semantics
Copy elision
Templates
Lambdas
The STL
More STL
Ranges
RAII and smart pointers
Initialization
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 178 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Generalized Constant Expressions C++ 14
Reason of being
use functions to compute constant expressions at compile time
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 179 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Generalized Constant Expressions C++ 14
Reason of being
use functions to compute constant expressions at compile time
Example
1 constexpr int f(int x) {
2 if (x > 1) return x * f(x - 1);
3 return 1;
4 }
5 constexpr int a = f(5); // computed at compile-time
6 int b = f(5); // maybe computed at compile-time
7 int n = ...; // runtime value
8 int c = f(n); // computed at runtime
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 179 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Generalized Constant Expressions(2) C++ 14
Notes
A constexpr function may be executed at compile time.
Arguments must be constexpr or literals in order to allow
compile time evaluation
Function body must be visible to the compiler
A constexpr function can also be used at runtime
A constexpr variable must be initialized at compile time
Classes can have constexpr member functions
Objects used in constant expressions must be of literal type:
integral, floating-point, enum, reference, pointer type
union (of at least one) or array of literal types
class type with a constexpr constructor and the destructor is
trivial (or constexpr since C++20)
A constexpr function is implicitly inline (header files)
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 180 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Limitations of constexpr functions C++ 11
C++11
Non-virtual function with a single return statement
C++14/C++17
no try-catch, goto or asm statements
no uninitialized/static/thread_local/non-literal-type variables
C++20
no coroutines or static/thread_local/non-literal-type variables
throw and asm statements allowed, but may not be executed
transient memory allocation (memory allocated at compile-time must be
freed again at compile-time)
virtual functions and uninitialized variables allowed
C++23
no coroutines, or execution of throw and asm statements
transient memory allocation
everything else allowed
Further details on cppreference
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 181 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Real life example C++ 11
1 constexpr float toSI(float v, char unit) {
2 switch (unit) {
3 case 'k': return 1000.0f*v;
4 case 'm': return 0.001f*v;
5 case 'y': return 0.9144f*v;
6 case 'i': return 0.0254f*v;
7 ...
8 default: return v;
9 }
10 }
11 constexpr float fromSI(float v, char unit) {
12 switch (unit) {
13 case 'k': return 0.001f*v;
14 case 'y': return 1.093f*v;
15 ...
16 }
17 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 182 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Real life example(2) C++ 11
1 class DimLength {
2 float m_value;
3 public:
4 constexpr DimLength(float v, char unit):
5 m_value(toSI(v, unit)) {
6 }
7 constexpr float get(char unit) const {
8 return fromSI(m_value, unit);
9 }
10 };
11 constexpr DimLength km(1, 'k');
12 constexpr float km_y = km.get('y');
13 constexpr float km_i = km.get('i');
14 static_assert(km_y == 1093, "expected km == 1093 yards!");
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 183 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Immediate functions C++ 20
Motivation
Force a function to be executed at compile-time
Runtime evaluation is forbidden
Same restrictions as constexpr functions
New keyword: consteval
Example
1 consteval int f(int x) {
2 if (x > 1) return x * f(x - 1);
3 return 1;
4 }
5 constexpr int a = f(5); // computed at compile-time
6 int b = f(5); // computed at compile-time
7 int n = ...; // runtime value
8 int c = f(n); // compilation error
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 184 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
constinit C++ 20
Motivation
Like a constexpr variable, a constinit variable guarantees
compile-time initialization, but can be modified afterwards
Only allowed for static/global and thread_local variables
Initializer must be a constant expression, but constexpr
destruction is not required
Example
1 constexpr int f(int x) {
2 if (x > 1) return x * f(x - 1);
3 return 1;
4 }
5 constexpr int a = f(5); // CT init, not modifiable
6 int b = f(5); // maybe CT init, modifiable
7 constinit int c = f(5); // CT init, modifiable
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 185 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Exceptions
4 Core modern C++
Constness
Constant Expressions
Exceptions
Move semantics
Copy elision
Templates
Lambdas
The STL
More STL
Ranges
RAII and smart pointers
Initialization
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 186 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Exceptions C++ 98
Purpose
to handle exceptional events that happen rarely
and cleanly jump to a place where the error can be handled
In practice
add an exception handling block with try ... catch
when exceptions are possible and can be handled
throw an exception using throw
when a function cannot proceed or recover internally
1 try { 7 void process_data(file &f) {
2 process_data(f); 8 ...
3 } catch (const 9 if (i >= buffer.size())
4 std::out_of_range& e) { 10 throw std::out_of_range{
5 std::cerr << e.what(); 11 "buf overflow"};
6 } 12 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 187 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Exceptions C++ 98
Throwing exceptions
objects of any type can be thrown (even e.g. int)
Good practice: Throwing exceptions
prefer throwing standard exception classes
throw objects by value
1 #include <stdexcept>
2 void process_data(file& f) {
3 if (!f.open())
4 throw std::invalid_argument{"stream is not open"};
5 auto header = read_line(f); // may throw an IO error
6 if (!header.starts_with("BEGIN"))
7 throw std::runtime_error{"invalid file content"};
8 std::string body(f.size()); // may throw std::bad_alloc
9 ...
10 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 188 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Exceptions C++ 98
Standard exceptions
std::exception, defined in header <exception>
Base class of all standard exceptions
Get error message: virtual const char* what() const;
Please derive your own exception classes from this one
From <stdexcept>:
std::runtime_error, std::logic_error,
std::out_of_range, std::invalid_argument, ...
Store a string: throw std::runtime_error{"msg"}
You should use these the most
std::bad_alloc, defined in header <new>
Thrown by standard allocation functions (e.g. new)
Signals failure to allocate
Carries no message
...
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 189 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Exceptions C++ 98
Catching exceptions
a catch clause catches exceptions of the same or derived type
multiple catch clauses will be matched in order
if no catch clause matches, the exception propagates
if the exception is never caught, std::terminate is called
1 try {
2 process_data(f);
3 } catch (const std::invalid_argument& e) {
4 bad_files.push_back(f);
5 } catch (const std::exception& e) {
6 std::cerr << "Failed to process file: " << e.what();
7 }
Good practice: Catching exceptions
Catch exceptions by const reference
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 190 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Exceptions C++ 98
Rethrowing exceptions
a caught exception can be rethrown inside the catch handler
useful when we want to act on an error, but cannot handle
and want to propagate it
1 try {
2 process_data(f);
3 } catch (const std::bad_alloc& e) {
4 std::cerr << "Insufficient memory for " << f.name();
5 throw; // rethrow
6 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 191 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Exceptions C++ 98
Catching everything
sometimes we need to catch all possible exceptions
e.g. in main, a thread, a destructor, interfacing with C, …
2 try {
3 callUnknownFramework();
4 } catch(const std::exception& e) {
5 // catches std::exception and all derived types
6 std::cerr << "Exception: " << e.what() << std::endl;
7 } catch(...) {
8 // catches everything else
9 std::cerr << "Unknown exception type" << std::endl;
10 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 192 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Exceptions C++ 98
Stack unwinding
all objects on the stack between a throw and the matching
catch are destructed automatically
this should cleanly release intermediate resources
make sure you are using the RAII idiom for your own classes
1 class C { ... }; 11 int main() {
2 void f() { 12 try {
3 C c1; 13 C c4;
4 throw exception{}; 14 g();
5 // start unwinding 15 cout << "done"; // not run
6 C c2; // not run 16 } catch(const exception&) {
7 } 17 // c1, c3 and c4 have been
8 void g() { 18 // destructed
9 C c3; f(); 19 }
10 } 20 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 193 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Exceptions C++ 17
Good practice: Exceptions
use exceptions for unlikely runtime errors outside the
program’s control
bad inputs, files unexpectedly not found, DB connection, …
don’t use exceptions for logic errors in your code
use assert and tests
don’t use exceptions to provide alternative/skip return values
you can use std::optional or std::variant
avoid using the global C-style errno
never throw in destructors
see also the C++ core guidelines and the ISO C++ FAQ
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 194 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Exceptions C++ 98
A more illustrative example
exceptions are very powerful when there is much code
between the error and where the error is handled
they can also rather cleanly handle different types of errors
try/catch statements can also be nested
1 try { 1 void process_file(File const & file) {
2 for (File const &f : files) { 2 ...
3 try { 3 if (handle = open_file(file))
4 process_file(f); 4 throw bad_file(file.status());
5 } 5 while (!handle) {
6 catch (bad_file const & e) { 6 line = read_line(handle);
7 ... // loop continues 7 database.insert(line); // can throw
8 } 8 // bad_db
9 } 9 }
10 } catch (bad_db const & e) { 10 }
11 ... // loop aborted
12 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 195 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Exceptions C++ 98
Cost
exceptions have little cost if no exception is thrown
they are recommended to report exceptional errors
for performance, when error raising and handling are close, or
errors occur often, prefer error codes or a dedicated class
when in doubt about which error strategy is better, profile!
Avoid Prefer
for (string const &num: nums) { for (string const &num: nums) {
try { optional<int> i = convert(num);
int i = convert(num); // can if (i) {
// throw process(*i);
process(i); } else {
} catch (not_an_int const &e) { ... // log and continue
... // log and continue }
} }
}
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 196 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
noexcept specifier C++ 11
noexcept
a function with the noexcept specifier states that it
guarantees to not throw an exception
int f() noexcept;
either no exceptions is thrown or they are handled internally
checked at compile time
allows the compiler to optimize around that knowledge
a function with noexcept(expression) is only noexcept
when expression evaluates to true at compile-time
int safe_if_8B() noexcept(sizeof(long)==8);
Good practice: noexcept
Use noexcept on leaf functions where you know the behavior
C++11 destructors are noexcept - never throw from them
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 197 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
noexcept operator C++ 11
the noexcept(expression) operator checks at compile-time
whether an expression can throw exceptions
returns a bool, which is true if no exceptions can be thrown
1 constexpr bool callCannotThrow = noexcept(f());
2 if constexpr (callCannotThrow) { ... }
3 template <typename Function>
4 void g(Function f) noexcept(noexcept(f())) {
5 ...
6 f();
7 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 198 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Exceptions C++ 98
Exception Safety Guarantees
A function can offer the following guarantees:
No guarantee
An exception will lead to undefined program state
Basic exception safety guarantee
An exception will leave the program in a defined state
At least destructors must be able to run
This is similar to the moved from state
No resources are leaked
Strong exception safety guarantee
The operation either succeeds or has no effect
When an exception occurs, the original state must be restored
This is hard to do, possibly expensive, maybe impossible
No-throw guarantee
The function never throws (e.g. is marked noexcept)
Errors are handled internally or lead to termination
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 199 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Exceptions
Alternatives to exceptions
The global variable errno (avoid)
Return an error code (e.g. an int or an enum)
Return a std::error_code (C++ 11)
If failing to produce a value is not a hard error, consider
returning std::optional<T> (C++ 17)
Return std::expected<T, E> (C++ 23), where T is the
return type on success and E is the type on failure
Terminate the program
e.g. by calling std::terminate() or std::abort()
Contracts: Specify function pre- and postconditions. Planned
for C++ 20, but removed. Will come back in the future
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 200 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Further resources
Exceptions and Error Handling - ISO C++ FAQ
Back to Basics: Exceptions - Klaus Iglberger - CppCon 2020
The Unexceptional Exceptions - Fedor Pikus - CppCon 2015
The Dawn of a New Error, (C++ error-handling and
exceptions) - Phil Nash - CppCon 2019 (alternatives)
Exceptions the Other Way Round - Sean Parent - CppNow
2022 (theoretical approach to errors)
P0709: Zero-overhead deterministic exceptions: Throwing
values - Herb Sutter (proposal - distant future)
De-fragmenting C++: Making Exceptions and RTTI More
Affordable and Usable - Herb Sutter CppCon 2019
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 201 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Move semantics
4 Core modern C++
Constness
Constant Expressions
Exceptions
Move semantics
Copy elision
Templates
Lambdas
The STL
More STL
Ranges
RAII and smart pointers
Initialization
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 202 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Move semantics: the problem C++ 11
Inefficient code
1 void swap(std::vector<int> &a,
2 std::vector<int> &b) {
3 std::vector<int> c = a;
4 a = b;
5 b = c;
6 }
7 std::vector<int> v(10000), w(10000);
8 ...
9 swap(v, w);
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 203 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Move semantics: the problem C++ 11
Inefficient code
1 void swap(std::vector<int> &a,
2 std::vector<int> &b) {
3 std::vector<int> c = a;
4 a = b;
5 b = c;
6 }
7 std::vector<int> v(10000), w(10000);
8 ...
9 swap(v, w);
What happens during swap
one allocation and one release for 10k ints
a copy of 30k ints
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 203 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Move semantics: the problem C++ 11
Vector’s built-in efficient swap
1 std::vector<int> v(10'000), w(10'000);
2 ...
3 v.swap(w);
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 204 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Move semantics: the problem C++ 11
Vector’s built-in efficient swap
1 std::vector<int> v(10'000), w(10'000);
2 ...
3 v.swap(w);
What happens during swap
3 swaps of int* (9 copies)
only some pointers to the underlying storage are swapped
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 204 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Move semantics: the problem C++ 98
Another potentially inefficient code
1 T consumeVector(std::vector<int> input) {
2 // ... change elements, compute result
3 return result;
4 }
5
6 std::vector<int> values{...};
7 consumeVector(values); // being copied now
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 205 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Move semantics: the problem C++ 98
Another potentially inefficient code
1 T consumeVector(std::vector<int> input) {
2 // ... change elements, compute result
3 return result;
4 }
5
6 std::vector<int> values{...};
7 consumeVector(values); // being copied now
Pass by copy
One unnecessary (large?) allocation and release
Unnecessary copy of the ints
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 205 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Move semantics: the problem C++ 98
Another potentially inefficient code
1 T consumeVector(std::vector<int> const & input) {
2 std::vector tmp{input};
3 // ... change elements, compute result
4 return result;
5 }
6 std::vector<int> values{...};
7 consumeVector(values); // maybe copied internally?
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 205 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Move semantics: the problem C++ 98
Another potentially inefficient code
1 T consumeVector(std::vector<int> const & input) {
2 std::vector tmp{input};
3 // ... change elements, compute result
4 return result;
5 }
6 std::vector<int> values{...};
7 consumeVector(values); // maybe copied internally?
Use references to avoid copies?
Working with pass by reference only moves allocation and
copy to a different place
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 205 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Move semantics: the problem C++ 98
Another potentially inefficient code
1 T consumeVector(std::vector<int> & input) {
2 // ... change elements, compute result
3 return result;
4 }
5
6 std::vector<int> values{...};
7 consumeVector(values); // maybe modified?
8 somethingElse(values); // safe to use values now???
So non-const references?
Non-const references could work, but does the outside know
that we’re changing the vector?
Could lead to bugs
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 205 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Move semantics: the problem C++ 98
Another potentially inefficient code
1 T consumeVector(std::vector<int> & input) {
2 // ... change elements, compute result
3 return result;
4 }
5
6 std::vector<int> values{...};
7 consumeVector(values); // maybe modified?
8 somethingElse(values); // safe to use values now???
The ideal situation
Have a way to express that we move the vector’s content
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 205 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Move semantics C++ 11
The idea
a new type of reference: rvalue reference
used for move semantic
denoted by &&
2 new special member functions in every class:
a move constructor similar to copy constructor
a move assignment operator similar to assignment operator
(now called copy assignment operator)
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 206 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Move semantics C++ 11
The idea
a new type of reference: rvalue reference
used for move semantic
denoted by &&
2 new special member functions in every class:
a move constructor similar to copy constructor
a move assignment operator similar to assignment operator
(now called copy assignment operator)
Practically
1 T(T const & other); // copy construction
2 T( T&& other); // move construction
3 T& operator=(T const & other); // copy assignment
4 T& operator=( T&& other); // move assignment
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 206 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Move semantics C++ 11
A few points
move constructor and assignment operator are allowed to
leave the source object ”empty”
so do not use the source object afterward
leave the source in a valid state (for its destructor)
if no move semantic is implemented, copies will be performed
the language and STL understand move semantic
the compiler moves whenever possible
e.g. when passing temporaries or returning from a function
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 207 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Move semantics C++ 11
A few points
move constructor and assignment operator are allowed to
leave the source object ”empty”
so do not use the source object afterward
leave the source in a valid state (for its destructor)
if no move semantic is implemented, copies will be performed
the language and STL understand move semantic
the compiler moves whenever possible
e.g. when passing temporaries or returning from a function
Practically
1 T f() { T r; return r; } // move r out of f
2 T v = f(); // move returned (temporary) T into v
3 void g(T a, T b, T c);
4 g(f(), T{}, v); // move, move, copy
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 207 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Move semantics C++ 11
In some cases, you want to force a move
1 void swap(T &a, T &b) {
2 T c = a; // copy construct
3 a = b; // copy assign
4 b = c; // copy assign
5 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 208 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Move semantics C++ 11
In some cases, you want to force a move
1 void swap(T &a, T &b) {
2 T c = a; // copy construct
3 a = b; // copy assign
4 b = c; // copy assign
5 }
Explicitly request moving
using the std::move function
which is basically a cast to an rvalue reference
6 void swap(T &a, T &b) {
7 T c = std::move(a); // move construct
8 a = std::move(b); // move assign
9 b = static_cast<T&&>(c); // move assign (don't)
10 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 208 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Move semantics: recommended implementation C++ 11
Use copy and swap idiom
implement an efficient swap function for your class
preferably hidden friend and symmetric
move constructor
consider delegating to default constructor
swap *this with parameter (source)
move assignment as operator=(T source)
parameter passed by value; caller can move or copy into it
swap parameter with *this
end of scope: parameter destroys former content of *this
alternative: move assignment as operator=(T&& source)
swap parameter with *this
1 swap less, separate copy assignment operator needed
former content of *this destroyed with caller argument
swap, move constructor/assignment must be noexcept
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 209 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Move semantics: recommended implementation C++ 11
Practically
1 class Movable {
2 Movable();
3 Movable(const Movable &other);
4 Movable(Movable &&other) noexcept :
5 Movable() { // constructor delegation
6 swap(*this, other);
7 }
8 Movable& operator=(Movable other) noexcept { // by value
9 swap(*this, other);
10 return *this;
11 }
12 friend void swap(Movable &a, Movable &b) noexcept {...}
13 };
14 Movable a, b;
15 a = b; // operator= copies b into "other"
16 a = std::move(b); // operator= moves b into "other"
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 210 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Move semantics: alternative implementation C++ 11
Practically
1 class Movable {
2 Movable();
3 Movable(const Movable &other);
4 Movable(Movable &&other) noexcept :
5 Movable() { // constructor delegation
6 swap(*this, other);
7 }
8 Movable& operator=(const Movable& other);
9 Movable& operator=(Movable&& other) noexcept {
10 swap(*this, other);
11 return *this;
12 }
13 friend void swap(Movable &a, Movable &b) noexcept { ... }
14 };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 211 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Move Semantic C++ 11
Exercise: Move semantics
go to exercises/move
look at the code and run it with callgrind
understand how inefficient it is
implement move semantic the easy way in NVector
run with callgrind and see no improvement
understand why and fix test.cpp
see efficiency improvements
prerequisite: be able to use simple templated code
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 212 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Copy elision
4 Core modern C++
Constness
Constant Expressions
Exceptions
Move semantics
Copy elision
Templates
Lambdas
The STL
More STL
Ranges
RAII and smart pointers
Initialization
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 213 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Copy elision C++ 17
Copy elision
1 struct Foo { ... };
2 Foo f() {
3 return Foo(); // return-value opt. (RVO)
4 }
5 Foo g() {
6 Foo foo;
7 return foo; // named return-value opt. (NRVO)
8 }
9 int main() {
10 // compiler must avoid these copies:
11 Foo a = f();
12 Foo b = Foo();
13 Foo c = Foo(Foo());
14 // copy elision allowed, but not guaranteed:
15 Foo d = g();
16 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 214 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Guaranteed copy elision C++ 17
Allows to write code not allowed in C++ 14 (would not compile)
Guaranteed: Return value optimization (RVO)
1 struct Foo {
2 Foo() { ... }
3 Foo(const Foo &) = delete;
4 Foo(Foo &&) = delete;
5 Foo& operator=(const Foo &) = delete;
6 Foo& operator=(Foo &&) = delete;
7 };
8 Foo f() {
9 return Foo(); // ok, no move
10 }
11 int main() {
12 Foo foo = f(); // ok, no move
13 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 215 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Templates
4 Core modern C++
Constness
Constant Expressions
Exceptions
Move semantics
Copy elision
Templates
Lambdas
The STL
More STL
Ranges
RAII and smart pointers
Initialization
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 216 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Templates C++ 17
Concept
The C++ way to write reusable code
like macros, but fully integrated into the type system
Applicable to functions, classes and variables
1 template<typename T>
2 const T & max(const T &a, const T &b) {
3 return b < a ? a : b;
4 }
5 template<typename T>
6 struct Vector {
7 int m_len;
8 T* m_data;
9 };
10 template <typename T>
11 std::size_t size = sizeof(T);
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 217 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Templates C++ 98
Warning
they are compiled for each instantiation
they need to be defined before used
so all template code must typically be in headers
or declared to be available externally (extern template)
this may lead to longer compilation times and bigger binaries
int func(int a) {
(3) return a;
1 template<typename T> func }
2 T func(T a) {
3 return a;
4 } func(5.2 double func(double a) {
) return a;
}
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 218 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Templates C++ 98
Template parameters
can be types, values or other templates
you can have several
default values allowed starting at the last parameter
1 template<typename KeyType=int, typename ValueType=KeyType>
2 struct Map {
3 void set(const KeyType &key, ValueType value);
4 ValueType get(const KeyType &key);
5 ...
6 };
7
8 Map<std::string, int> m1;
9 Map<float> m2; // Map<float, float>
10 Map<> m3; // Map<int, int>
11 Map m4; // Map<int, int>, C++17
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 219 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Template parameters C++ 98
typename vs. class keyword
for declaring a template type parameter, the typename and
class keyword are semantically equivalent
template template parameters require C++ 17 for typename
1 template<typename T>
2 T func(T a); // equivalent to:
3 template<class T>
4 T func(T a);
5
6 template<template<class> class C>
7 C<int> func(C<int> a); // equivalent to:
8 template<template<typename> class C>
9 C<int> func(C<int> a); // equivalent to:
10 template<template<typename> typename C> // C++17
11 C<int> func(C<int> a);
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 220 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Template implementation C++ 98
1 template<typename KeyType=int, typename ValueType=KeyType>
2 struct Map {
3 // declaration and inline definition
4 void set(const KeyType &key, ValueType value) {
5 ...
6 }
7 // just declaration
8 ValueType get(const KeyType &key);
9 };
10
11 // out-of-line definition
12 template<typename KeyType, typename ValueType>
13 ValueType Map<KeyType, ValueType>::get
14 (const KeyType &key) {
15 ...
16 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 221 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Nested templates C++ 98
Nested templates - godbolt
1 template<typename KeyType=int, typename ValueType=KeyType>
2 struct Map {
3 template<typename OtherValueType>
4 void set(const KeyType &key, OtherValueType value) {
5 ...
6 }
7 template<typename OtherKeyType>
8 ValueType get(const OtherKeyType &key);
9 };
10
11 template<typename KeyType, typename ValueType> //for class
12 template<typename OtherKeyType> //for member function
13 ValueType Map<KeyType, ValueType>::get
14 (const OtherKeyType &key) { ... }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 222 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Non-type template parameter C++ 98 / C++ 17 / C++ 20
template parameters can also be values
integral types, pointer, enums in C++ 98
auto in C++ 17
literal types (includes floating points) in C++ 20
1 template<unsigned int N>
2 struct Polygon {
3 float perimeter() {
4 return 2 * N * std::sin(PI / N) * radius;
5 }
6 float radius;
7 };
8
9 Polygon<19> nonadecagon{3.3f};
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 223 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Template specialization C++ 98
Specialization
Templates can be specialized for given values of their parameter
1 template<typename F, unsigned int N>
2 struct Polygon { ... }; // primary template
3
4 template<typename F> // partial specialization
5 struct Polygon<F, 6> {
6 F perimeter() { return 6 * radius; }
7 F radius;
8 };
9 template<> // full specialization
10 struct Polygon<int, 6> {
11 int perimeter() { return 6 * radius; }
12 int radius;
13 };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 224 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Template argument deduction C++ 98
Template argument deduction
Template arguments deduced from (function) arguments
Template arguments can always be specified explicitly
Only for function templates (Before C++ 14)
1 template <typename T, typename U>
2 void f(T t, U u) { ... }
3
4 f(42, true); // deduces T=int, U=bool
5 // calls f<int, bool>(42, true);
6 f<float>(42, true); // sets T=float, deduces U=bool
7 // calls f<float, bool>(42, true);
8 // 42 converted to float before call
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 225 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Template argument deduction C++ 11
Deduced contexts
Compiler can even deduce template arguments inside certain
expressions (pattern matching)
See cppreference for details
1 template <typename T>
2 void f(T* p) { ... }
3
4 const int * ip = ...;
5 f(ip); // deduces T=const int
6
7 template <typename T, std::size_t N>
8 void g(std::array<T*, N> a) { ... }
9
10 std::array<int*, 3> aip = ...;
11 g(aip); // deduces T=int, N=3
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 226 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Template argument deduction C++ 11
Non-deduced contexts
Deduction from certain expressions is impossible/forbidden
1 template <typename C>
2 void f(typename C::value_type v) { ... }
3 f(std::vector<int>{...}); // cannot deduce C
4 // from a dependent type
5 template <typename T, std::size_t N>
6 void g(std::array<T, N * 2> a) { ... }
7 g(std::array<int, 4>{...}); // deduces T=int,
8 // cannot deduce N from expression
9 template <typename T>
10 void h(std::vector<T> v) { ... }
11 h({1, 2, 3}); // error, braced-initializer list has no type
12 h(std::vector<int>{1, 2, 3}); // ok, T=int
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 227 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Template argument deduction C++ 11
Non-deduced contexts
Deduction from certain expressions is impossible/forbidden
1 template <typename C, typename F>
2 void reduce(const C& cont, const F& f = std::plus{});
3 reduce(std::vector<int>{...}); // error: cannot deduce F
4 // would need: <typename C, typename F = decltype(std::plus{})>
5
6 template<typename T>
7 const T & max(const T &a, const T &b) { ... }
8 int i = 3;
9 max(i, 3.14f); // deduces T=int and T=float, error
10 // either: max<float>(i, 3.14f);
11 // or: max(static_cast<float>(i), 3.14f);
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 227 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Template argument deduction C++ 11
Deduction in partial specializations
Partial specializations also deduce template arguments
with similar rules as for function templates
but some more restrictions (cf. cppreference)
1 template <typename T>
2 struct S { ... }; // primary template
3
4 template <typename T>
5 struct S<T*> { ... }; // specialization 1
6
7 template <typename U, std::size_t N>
8 struct S<std::array<U*, N>> { ... }; // specialization 2
9
10 S<int> s1; // prim. tmpl. (T=int) ok, spec. 1/2 invalid
11 S<int*> s2; // prim. tmpl. (T=int*) and spec. 1 (T=int) ok
12 // spec. 1 is more specialized, will be used
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 228 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Template argument deduction C++ 98
Specialization vs. overloading
For function templates we can choose between specialization
and overloading
Partial specialization of function templates is forbidden
1 template <typename T> 10 template <typename T>
2 void f(T t) { ... } 11 void f(T t) { ... }
3 12
4 13 template <>
5 void f(int* t) { ... } 14 void f<int*>(int* t) { ... }
6 15
7 16 // part. spec. forbidden:
8 template <typename T> 17 template <typename T>
9 void f(T* t) { ... } 18 void f<T*>(T* t) {...}
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 229 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Template argument deduction C++ 11
Disadvantages of specialization vs. overloading
Specialization always needs a primary template
Sometimes this does not make sense
Partial specializations of function templates is forbidden
So we need SFINAE workarounds or concepts
Could you express this with specializations?
1 template <typename T>
2 void f(T* p) { ... }
3
4 template <typename T>
5 void f(std::unique_ptr<T> p) { ... }
Good practice: Specialization vs. overloading
Prefer overloading function templates over template specialization
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 230 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Class Template Argument Deduction (CTAD) C++ 17
CTAD
Deduce the template arguments for a class template
Based on construction arguments
Only when no template arguments provided
Since C++ 20: CTAD for aggregates (no constructor needed)
1 template<typename A, typename B, typename C = double>
2 struct Triple {
3 Triple(A a, B b, C c) : a(a), b(b), c(c) {} // C++17
4 A a; B b; C c;
5 };
6
7 Triple t{42, true, 3.14}; // Triple<int, bool, double>
8 Triple<int> t{42, true, 3.14}; // compilation error
9 Triple<int, bool> t{42, true, 3.14}; // not CTAD
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 231 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Class Template Argument Deduction (CTAD) C++ 17
Deduction guides
Describe how constructor argument types are mapped to class
template arguments
1 template<typename A, typename B>
2 struct Pair {
3 Pair(A a, B b) : a(a), b(b) {}
4 A a; B b;
5 };
6
9 Pair p{42, "hello"}; // Pair<int, const char*>
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 232 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Class Template Argument Deduction (CTAD) C++ 17
Deduction guides
Describe how constructor argument types are mapped to class
template arguments
1 template<typename A, typename B>
2 struct Pair {
3 Pair(A a, B b) : a(a), b(b) {}
4 A a; B b;
5 };
6 template<typename A>
7 Pair(A, const char*) -> Pair<A, std::string>;
8
9 Pair p{42, "hello"}; // Pair<int, std::string>
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 232 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Class Template Argument Deduction (CTAD) C++ 17
Standard library examples
1 std::pair p{1.2, true}; // std::pair<double, bool>
2 std::tuple t{1.2, true, 32};
3 // std::tuple<double, bool, int>
4 std::vector v{1, 2, 3}; // std::vector<int>
5 std::list l{v.begin(), v.end()}; // std::list<int>
6 std::array a{1, 2, 3}; // std::array<int, 3>
7
8 std::mutex m;
9 std::lock_guard l(m); // std::lock_guard<std::mutex>
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 233 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
The full power of templates C++ 98
Exercise: Templates
go to exercises/templates
look at the OrderedVector code
compile and run playwithsort.cpp. See the ordering
modify playwithsort.cpp and reuse OrderedVector with
Complex
improve OrderedVector to template the ordering
test reverse ordering of strings (from the last letter)
test order based on Manhattan distance with complex type
check the implementation of Complex
try ordering complex of complex
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 234 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Lambdas
4 Core modern C++
Constness
Constant Expressions
Exceptions
Move semantics
Copy elision
Templates
Lambdas
The STL
More STL
Ranges
RAII and smart pointers
Initialization
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 235 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Trailing function return type C++ 11
An alternate way to specify a function’s return type
int f(float a); // classic
auto f(float a) -> int; // trailing
auto f(float a) { return 42; } // deduced, C++14
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 236 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Trailing function return type C++ 11
An alternate way to specify a function’s return type
int f(float a); // classic
auto f(float a) -> int; // trailing
auto f(float a) { return 42; } // deduced, C++14
Advantages
Allows to simplify inner type definition
1 class Equation {
2 using ResultType = double;
3 ResultType evaluate();
4 }
5 Equation::ResultType Equation::evaluate() {...}
6 auto Equation::evaluate() -> ResultType {...}
Used by lambda expressions
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 236 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Lambda expressions C++ 11
Definition
A lambda expression is a function with no name
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 237 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Lambda expressions C++ 11
Definition
A lambda expression is a function with no name
Python example
1 data = [1,9,3,8,3,7,4,6,5]
2
3 # without lambdas
4 def isOdd(n):
5 return n%2 == 1
6 print(filter(isOdd, data))
7
8 # with lambdas
9 print(filter(lambda n:n%2==1, data))
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 237 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
++
C Lambdas C++ 11
Simplified syntax
1 auto f = [] (arguments) -> return_type {
2 statements;
3 };
The return type specification is optional
f is an instance of a functor type, generated by the compiler
Usage example
4 int data[]{1,2,3,4,5};
5 auto f = [](int i) {
6 std::cout << i << " squared is " << i*i << '\n';
7 };
8 for (int i : data) f(i);
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 238 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Capturing variables C++ 11
Adaptable lambdas
Adapt lambda’s behaviour by accessing variables outside of it
This is called “capture”
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 239 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Capturing variables C++ 11
Adaptable lambdas
Adapt lambda’s behaviour by accessing variables outside of it
This is called “capture”
First attempt in C++
1 int increment = 3;
2 int data[]{1,9,3,8,3,7,4,6,5};
3 auto f = [](int x) { return x+increment; };
4 for(int& i : data) i = f(i);
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 239 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Capturing variables C++ 11
Adaptable lambdas
Adapt lambda’s behaviour by accessing variables outside of it
This is called “capture”
First attempt in C++
1 int increment = 3;
2 int data[]{1,9,3,8,3,7,4,6,5};
3 auto f = [](int x) { return x+increment; };
4 for(int& i : data) i = f(i);
Error
error: 'increment' is not captured
[](int x) { return x+increment; });
^
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 239 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Capturing variables C++ 11
The capture list
local variables outside the lambda must be explicitly captured
unlike in Python, Java, C#, Rust, ...
captured variables are listed within initial []
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 240 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Capturing variables C++ 11
The capture list
local variables outside the lambda must be explicitly captured
unlike in Python, Java, C#, Rust, ...
captured variables are listed within initial []
Example
1 int increment = 3;
2 int data[]{1,9,3,8,3,7,4,6,5};
3 auto f = [increment](int x) { return x+increment; };
4 for(int& i : data) i = f(i);
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 240 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Default capture is by value C++ 11
Code example
1 int sum = 0;
2 int data[]{1,9,3,8,3,7,4,6,5};
3 auto f = [sum](int x) { sum += x; };
4 for (int i : data) f(i);
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 241 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Default capture is by value C++ 11
Code example
1 int sum = 0;
2 int data[]{1,9,3,8,3,7,4,6,5};
3 auto f = [sum](int x) { sum += x; };
4 for (int i : data) f(i);
Error
error: assignment of read-only variable 'sum'
[sum](int x) { sum += x; });
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 241 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Default capture is by value C++ 11
Code example
1 int sum = 0;
2 int data[]{1,9,3,8,3,7,4,6,5};
3 auto f = [sum](int x) { sum += x; };
4 for (int i : data) f(i);
Error
error: assignment of read-only variable 'sum'
[sum](int x) { sum += x; });
Explanation
By default, variables are captured by value
The lambda’s operator() is const
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 241 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Capture by reference C++ 11
Simple example
In order to capture by reference, add ’&’ before the variable
1 int sum = 0;
2 int data[]{1,9,3,8,3,7,4,6,5};
3 auto f = [&sum](int x) { sum += x; };
4 for (int i : data) f(i);
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 242 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Capture by reference C++ 11
Simple example
In order to capture by reference, add ’&’ before the variable
1 int sum = 0;
2 int data[]{1,9,3,8,3,7,4,6,5};
3 auto f = [&sum](int x) { sum += x; };
4 for (int i : data) f(i);
Mixed case
One can of course mix values and references
5 int sum = 0, off = 1;
6 int data[]{1,9,3,8,3,7,4,6,5};
7 auto f = [&sum, off](int x) { sum += x + off; };
8 for (int i : data) f(i);
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 242 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Anatomy of a lambda C++ 11
Lambdas are pure syntactic sugar - cppinsight
They are replaced by a functor during compilation
1 int sum = 0, off = 1; 13 int sum = 0, off = 1;
2 auto l = 14 struct __lambda4 {
3 [&sum, off] 15 int& sum; int off;
4 16 __lambda4(int& s, int o)
5 17 : sum(s), off(o) {}
6 18
7 (int x) { 19 auto operator()(int x) const {
8 sum += x + off; 20 sum += x + off;
9 }; 21 }
10 22 };
11 23 auto l = __lambda4{sum, off};
12 l(42); 24 l(42);
Some nice consequence
Lambda expressions create ordinary objects
They can be copied, moved, or inherited from
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 243 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Capture list C++ 11
all by value
[=](...) { ... };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 244 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Capture list C++ 11
all by value
[=](...) { ... };
all by reference
[&](...) { ... };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 244 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Capture list C++ 11
all by value
[=](...) { ... };
all by reference
[&](...) { ... };
mix
[&, b](...) { ... };
[=, &b](...) { ... };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 244 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Capture list - this C++ 11
Inside a (non-static) member function, we can capture this.
1 [ this](...) { use(*this); };
2 [ &](...) { use(*this); };
3 [&, this](...) { use(*this); };
4 [ =](...) { use(*this); }; // deprecated in C++20
5 [=, this](...) { use(*this); }; // allowed in C++20
Since the captured this is a pointer, *this refers to the object by
reference.
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 245 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Capture list - this C++ 11
Inside a (non-static) member function, we can capture this.
1 [ this](...) { use(*this); };
2 [ &](...) { use(*this); };
3 [&, this](...) { use(*this); };
4 [ =](...) { use(*this); }; // deprecated in C++20
5 [=, this](...) { use(*this); }; // allowed in C++20
Since the captured this is a pointer, *this refers to the object by
reference.
1 [ *this](...) { use(*this); }; // C++17
2 [&, *this](...) { use(*this); }; // C++17
3 [=, *this](...) { use(*this); }; // C++17
The object at *this is captured by value (the lambda gets a copy).
Details in this blog post.
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 245 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Generic lambdas C++ 14
Generic lambdas (aka. polymorphic lambdas)
The type of lambda parameters may be auto.
auto add = [](auto a, auto b) { return a + b; };
The generated operator() becomes a template function:
template <typename T, typename U>
auto operator()(T a, U b) const { return a + b; }
The types of a and b may be different.
Explicit template parameters (C++ 20)
auto add = []<typename T>(T a, T b)
{ return a + b; };
The types of a and b must be the same.
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 246 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Higher-order lambdas C++ 11
Example - godbolt
1 auto build_incrementer = [](int inc) {
2 return [inc](int value) { return value + inc; };
3 };
4 auto inc1 = build_incrementer(1);
5 auto inc10 = build_incrementer(10);
6 int i = 0;
7 i = inc1(i); // i = 1
8 i = inc10(i); // i = 11
How it works
build_incrementer returns a function object
this function’s behavior depends on a parameter
note how auto is useful here!
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 247 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Lambda improvements C++ 20
Lambda improvements in C++ 20
Allowed in unevaluated contexts,
e.g. within decltype, sizeof, typeid, etc.
Without captures, are default-constructible and assignable
Examples
1 struct S {
2 decltype([](int i) { std::cout << i; }) f;
3 } s;
4 s.f(42); // prints "42"
5
6 template <typename T>
7 using CudaPtr = std::unique_ptr<T,
8 decltype([](T* p){ cudaFree(p); })>;
9
10 std::set<T, decltype([](T a, T b) { ... })> s2;
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 248 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
The STL
4 Core modern C++
Constness
Constant Expressions
Exceptions
Move semantics
Copy elision
Templates
Lambdas
The STL
More STL
Ranges
RAII and smart pointers
Initialization
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 249 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
The Standard Template Library C++ 98
What it is
A library of standard templates
Has almost everything you need
strings, containers, iterators
algorithms, functions, sorters
functors, allocators
...
Portable
Reusable
Efficient
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 250 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
The Standard Template Library C++ 98
What it is
A library of standard templates
Has almost everything you need
strings, containers, iterators
algorithms, functions, sorters
functors, allocators
...
Portable
Reusable
Efficient
Use it
and adapt it to your needs, thanks to templates
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 250 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
STL in practice C++ 14
STL example - godbolt
1 #include <vector>
2 #include <algorithm>
3 #include <functional> // `import std;` in C++23
4 #include <iterator>
5 #include <iostream>
6
7 std::vector<int> in{5, 3, 4}; // initializer list
8 std::vector<int> out(3); // constructor taking size
9 std::transform(in.begin(), in.end(), // input range
10 out.begin(), // start result
11 std::negate{}); // function obj
12 std::copy(out.begin(), out.end(), // -5 -3 -4
13 std::ostream_iterator<int>{std::cout, " "});
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 251 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
STL’s concepts C++ 98
containers
data structures for managing a range of elements, irrespective of:
the data itself (templated)
the memory allocation of the structure (templated)
the algorithms that may use the structure (iterators)
Examples (→ string and container library on cppreference)
string, string_view (C++ 17)
list, forward_list (C++ 11), vector, deque, array (C++ 11)
[multi]map, [multi]set (C++ 23: flat_[multi]map, flat_[multi]set)
unordered_[multi]map (C++ 11), unordered_[multi]set (C++ 11)
stack, queue, priority_queue
span (C++ 20)
non-containers: bitset, pair, tuple (C++ 11), optional (C++ 17),
variant (C++ 17), any (C++ 17), expected (C++ 23)
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 252 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Containers: std::vector C++ 11
1 #include <vector>
2 std::vector<T> v{5, 3, 4}; // 3 Ts, 5, 3, 4
3 std::vector<T> v(100); // 100 default constr. Ts
4 std::vector<T> v(100, 42); // 100 Ts with value 42
5 std::vector<T> v2 = v; // copy
6 std::vector<T> v2 = std::move(v); // move, v is empty
7
8 std::size_t s = v.size();
9 bool empty = v.empty();
10
11 v[2] = 17; // write element 2
12 T& t = v[1000]; // access element 1000, bug!
13 T& t = v.at(1000); // throws std::out_of_range
14 T& f = v.front(); // access first element
15 v.back() = 0; // write to last element
16 T* p = v.data(); // pointer to underlying storage
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 253 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Containers: std::vector C++ 11
1 std::vector<T> v = ...;
2 auto b = v.begin(); // iterator to first element
3 auto e = v.end(); // iterator to one past last element
4 // all following operations, except reserve, invalidate
5 // all iterators (b and e) and references to elements
6
7 v.resize(100); // size changes, grows: new T{}s appended
8 // shrinks: Ts at end destroyed
9 v.reserve(1000); // size remains, memory increased
10 for (T i = 0; i < 900; i++)
11 v.push_back(i); // add to the end
12 v.insert(v.begin()+3, T{}); // insert after 3rd position
13
14 v.pop_back(); // removes last element
15 v.erase(v.end() - 3); // removes 3rd-last element
16 v.clear(); // removes all elements
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 254 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Containers: std::unordered_map C++ 11
Conceptually a container of std::pair<Key const, Value>
1 #include <unordered_map>
2 std::unordered_map<std::string, int> m;
3 m["hello"] = 1; // inserts new key, def. constr. value
4 m["hello"] = 2; // finds existing key
5 auto [it, isNewKey] = m.insert({"hello", 0}); // no effect
6 int val = m["world"]; // inserts new key (val == 0)
7 int val = m.at("monde"); // throws std::out_of_range
8
9 if (auto it = m.find("hello"); it != m.end()) // C++17
10 m.erase(it); // remove by iterator (fast)
11 if (m.contains("hello")) // C++20
12 m.erase("hello"); // remove by key, 2. lookup, bad
13 for (auto const& [k, v] : m) // iterate k/v pairs (C++17)
14 std::cout << k << ": " << v << '\n';
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 255 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
std::hash C++ 11
The standard utility to create hash codes
Used by std::unordered_map and others
Can be customized for your types via template specialization
1 #include <functional>
2 std::hash<std::string> h;
3 std::cout << h("hello"); // 2762169579135187400
4 std::cout << h("world"); // 8751027807033337960
5
6 class MyClass { int a, b; ... };
7 template<> struct std::hash<MyClass> {
8 std::size_t operator()(MyClass const& c) {
9 std::hash<int> h;
10 return h(c.a) ^ h(c.b); // xor to combine hashes
11 }
12 };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 256 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
STL’s concepts C++ 11
iterators
generalization of pointers
allow iteration over some data, irrespective of:
the container used (templated)
the data itself (container is templated)
the consumer of the data (templated algorithm)
examples
std::reverse_iterator, std::back_insert_iterator, ...
Iterator example - godbolt
1 std::vector<int> const v = {1,2,3,4,5,6,7,8,9};
2 auto const end = v.rend() - 3; // arithmetic
3 for (auto it = v.rbegin();
4 it != end; // compare positions
5 it += 2) // jump 2 positions
6 std::cout << *it; // dereference, prints: 975
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 257 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
STL’s concepts C++ 98
algorithms
implementation of an algorithm working on data
with a well defined behavior (defined complexity)
irrespective of
the data handled
the container where the data live
the iterator used to go through data (almost)
examples
for_each, find, find_if, count, count_if, search
copy, swap, transform, replace, fill, generate
remove, remove_if
unique, reverse, rotate, shuffle, partition
sort, partial_sort, merge, make_heap, min, max
lexicographical_compare, iota, reduce, partial_sum
see also 105 STL Algorithms in Less Than an Hour and the
algorithms library on cppreference
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 258 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
STL’s concepts C++ 98
functors / function objects
generic utility functions
as structs with operator()
mostly useful to be passed to STL algorithms
implemented independently of
the data handled (templated)
the context (algorithm) calling it
examples
plus, minus, multiplies, divides, modulus, negate
equal_to, less, greater, less_equal, ...
logical_and, logical_or, logical_not
bit_and, bit_or, bit_xor, bit_not
identity, not_fn
bind, bind_front
see also documentation on cppreference
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 259 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Functors / function objects C++ 11
Example
1 struct Incrementer {
2 int m_inc;
3 Incrementer(int inc) : m_inc(inc) {}
4
5 int operator()(int value) const {
6 return value + m_inc;
7 }
8 };
9 std::vector<int> v{1, 2, 3};
10 const auto inc = 42;
11 std::transform(v.begin(), v.end(), v.begin(),
12 Incrementer{inc});
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 260 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Prefer lambdas over functors C++ 11
With lambdas
1 std::vector<int> v{1, 2, 3};
2 const auto inc = 42;
3 std::transform(begin(v), end(v), begin(v),
4 [inc](int value) {
5 return value + inc;
6 });
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 261 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Prefer lambdas over functors C++ 11
With lambdas
1 std::vector<int> v{1, 2, 3};
2 const auto inc = 42;
3 std::transform(begin(v), end(v), begin(v),
4 [inc](int value) {
5 return value + inc;
6 });
Good practice: Use STL algorithms with lambdas
Prefer lambdas over functors when using the STL
Avoid binders like std::bind2nd, std::ptr_fun, etc.
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 261 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Range-based for loops with STL containers C++ 11
Iterator-based loop (since C++ 98)
1 std::vector<int> v = ...;
2 int sum = 0;
3 for (std::vector<int>::iterator it = v.begin();
4 it != v.end(); it++)
5 sum += *it;
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 262 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Range-based for loops with STL containers C++ 11
Iterator-based loop (since C++ 98)
1 std::vector<int> v = ...;
2 int sum = 0;
3 for (std::vector<int>::iterator it = v.begin();
4 it != v.end(); it++)
5 sum += *it;
Range-based for loop (since C++ 11)
6 std::vector<int> v = ...;
7 int sum = 0;
8 for (auto a : v) { sum += a; }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 262 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Range-based for loops with STL containers C++ 11
Iterator-based loop (since C++ 98)
1 std::vector<int> v = ...;
2 int sum = 0;
3 for (std::vector<int>::iterator it = v.begin();
4 it != v.end(); it++)
5 sum += *it;
Range-based for loop (since C++ 11)
6 std::vector<int> v = ...;
7 int sum = 0;
8 for (auto a : v) { sum += a; }
STL way (since C++ 98)
9 std::vector<int> v = ...;
10 int sum = std::accumulate(v.begin(), v.end(), 0);
11 // std::reduce(v.begin(), v.end()); // C++17
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 262 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
More examples C++ 17
1 std::list<int> l = ...;
2
3 // Finds the first element in a list between 1 and 10.
4 const auto it = std::find_if(l.begin(), l.end(),
5 [](int i) { return i >= 1 && i <= 10; });
6 if (it != l.end()) {
7 int element = *it; ...
8 }
9
10 // Computes sin(x)/(x + DBL_MIN) for elements of a range.
11 std::vector<double> r(l.size());
12 std::transform(l.begin(), l.end(), r.begin(),
13 [](auto x) { return std::sin(x)/(x + DBL_MIN); });
14
15 // reduce/fold (using addition)
16 const auto sum = std::reduce(v.begin(), v.end());
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 263 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
More examples C++ 11
1 std::vector<int> v = ...;
2
3 // remove duplicates
4 std::sort(v.begin(), v.end());
5 auto newEndIt = std::unique(v.begin(), v.end());
6 v.erase(newEndIt, v.end());
7
8 // remove by predicate
9 auto p = [](int i) { return i > 42; };
10 auto newEndIt = std::remove_if(v.begin(), v.end(), p);
11 v.erase(newEndIt, v.end());
12
13 // remove by predicate (C++20)
14 std::erase_if(v, p);
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 264 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Welcome to lego programming! C++ 98
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 265 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Using the STL C++ 98
Exercise: STL
go to exercises/stl
look at the non STL code in randomize.nostl.cpp
it creates a vector of ints at regular intervals
it randomizes them
it computes differences between consecutive ints
and the mean and variance of it
open randomize.cpp and complete the “translation” to STL
see how easy it is to reuse the code with complex numbers
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 266 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Using the STL C++ 98
Be brave and persistent!
you may find the STL quite difficult to use
template syntax is really tough
it is hard to get right, compilers spit out long error novels
but, compilers are getting better with error messages
C++ 20 will help with concepts and ranges
the STL is extremely powerful and flexible
it will be worth your time!
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 267 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
More STL
4 Core modern C++
Constness
Constant Expressions
Exceptions
Move semantics
Copy elision
Templates
Lambdas
The STL
More STL
Ranges
RAII and smart pointers
Initialization
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 268 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
std::string_view cppreference C++ 17
Non owning read-only view of a contiguous char sequence
Doesn’t allocate memory
Similar interface to std::string, but read-only
Easy to copy, faster for some calls eg. substr (O(1) vs O(n))
The data pointed to has to outlive the string_view
Some example uses
1 constexpr std::string_view sv {"Some example"};
2 auto first = sv.substr(0, sv.find_first_of(" "));
3 std::string some_string {"foo bar"};
4 std::string_view sv_str(some_string);
5 char foo[3] = {'f','o','o'};
6 std::string_view carr(foo, std::size(foo));
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 269 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
std::span<T> - Concept cppreference C++ 20
Non owning view of a contiguous sequence of items
Doesn’t allocate memory
Allows to modify items, but not the container itself
no reallocation, push or pop
Provides container like interface
iterators, size, front/back, subspan, ...
Standard contiguous containers convert to it automatically
std::vector, std::array, C arrays, ...
not std::list or std::deque (no contiguous storage)
span should thus be preferred as function argument
Simply a pair (pointer, size), so cheap to copy
and thus to be passed by value
span can also have a static extend
meaning the size is determined at compile time
and thus only a pointer is stored by span
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 270 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
std::span<T> - Usage C++ 20
Some example - godbolt
1 void print(std::span<int> c) {
2 for (auto a : c) { std::cout << a << " "; }
3 std::cout << "\n";
4 }
5 void times2(std::span<int> c) {
6 for(auto &e : c) { e *= 2; }
7 }
8 int a[]{23, 45, 67, 89};
9 print(a); // 23 45 67 89
10
11 std::vector v{1, 2, 3, 4, 5};
12 std::span<int> sv = v;
13 print(sv.subspan(2, 2)); // 3 4
14
15 std::array a2{-14, 55, 24};
16 times2(a2);
17 print(a2); // -28 110 48
18
19 std::span<int, 3> sa2 = a2;
20 std::cout << sizeof(sv) << " " << sizeof(sa2) << "\n"; // 16 8
21 std::span<int, 3> s2a2 = a; // compilation failure, invalid conversion
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 271 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
std::optional cppreference C++ 17
Manages an optionally contained value
Contextually converts to bool, telling if it contains something
Has value semantics (Copy, Move, Compare, stack alloc.)
Useful for the return value of a function that may fail
Useful in place of pointers where value semantics are intuitive
1 std::optional<Phone> parse_phone(std::string_view in) {
2 if (is_valid_phone(in))
3 return in; // equiv. to optional<Phone>{in};
4 return {}; // or: return std::nullopt; (empty opt.)
5 }
6 if (v) { // or: v.is_valid()
7 process_phone(v.value()); // or: *v (unchecked)
8 v->call(); // calls Phone::call() (unchecked)
9 }
10 v.reset(); assert(!v.has_value()); // or: v = {};
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 272 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
std::optional C++ 17
Code example
1 // address may be given for a person or not
2 void processPerson(std::string_view name,
3 std::optional<Address> address);
4 Address addr = wonderland();
5 processPerson("Alice", std::move(addr));
6
7 // Every person has a name, but not always an address
8 struct Person {
9 std::string name;
10 std::optional<Address> address;
11 };
12 std::vector<Person> ps = ...;
13 std::sort(ps.begin(), ps.end(),
14 [](const Person& a, const Person& b) {
15 return a.address < b.address;
16 }); // sorts by address, persons w/o address at front
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 273 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
std::optional C++ 17
Exercise: Handling optional results
go to exercises/optional/optional.cpp
modify mysqrt so to return an std::optional<double>
guess the consequences on square
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 274 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
std::variant cppreference C++ 17
A type-safe union
Allows the variable to hold any of the given types
std::get reads the value of the variant
and throws std::bad_variant_access for bad accesses
Currently held alternative can be probed
Code example
1 std::variant<int, float, string> opt{100}; // holding int
2 int ival = std::get<int>(opt); // or std::get<0>(opt)
3 try {
4 float val = std::get<float>(opt) // will throw
5 } catch (std::bad_variant_access const& ex) {...}
6 if (std::holds_alternative<float>(opt))
7 std::cout << std::get<float>(opt);
8 if (const float* v = std::get_if<float>(&opt)) { ... }
9 const int current_alternative = opt.index(); // == 0
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 275 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
std::variant and the visitor pattern C++ 17
std::visit cppreference
Applies a “visitor” to a given variant
A visitor is a callable able to handle all different types
Must return void or the same type for all overloads
Practically - godbolt
1 struct Visitor {
2 auto operator()(int i) {return "i:"+std::to_string(i);}
3 auto operator()(float f) {return "f:"+std::to_string(f);}
4 auto operator()(const std::string& s) { return "s:"+s;}
5 template <typename T>
6 auto operator()(const T& t) { return std::string{"?"}; }
7 };
8 void print(std::variant<int, float, std::string, char> v) {
9 std::cout << std::visit(Visitor{}, v) << '\n';
10 }
11 print(100); print(42.0f); print("example"); print('A');
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 276 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
std::variant and the lambda visitor pattern C++ 17
Idea
use inheritance to group a set of lambdas
Practically - godbolt
1 template<typename... Ts> // covered in expert part
2 struct Overload : Ts ... { using Ts::operator()...; };
3 template<typename... Ts>
4 Overload(Ts...) -> Overload<Ts...>; // obsolete in C++20
5 int main(){
6 std::variant<int, float, std::string, char> v{ ... };
7 auto overloadSet = Overload {
8 [](int i) { std::cout << "i32:" << i;},
9 [](std::string s) { std::cout << s;},
10 [](auto a) { std::cout << "other"; },
11 };
12 std::visit(overloadSet, v);
13 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 277 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
std::variant exercise C++ 17
Exercise: An alternative to oo polymorphism
go to exercises/variant/variant.cpp
replace inheritance from a common base class with an
std::variant on the three kinds of particle.
two solutions given : with std::get_if and with
std::visit.
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 278 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
std::any cppreference C++ 17
a type-safe container for single values of any type
Allows a variable to hold any type (say bye to void*)
std::any_cast reads the internal value
and throws std::bad_any_cast for bad accesses
std::any_cast only matches types 1:1, ignoring inheritance
Code example
1 std::any val{100}; // holding int
2 val = std::string("hello"); // holding string
3 std::string s = std::any_cast<std::string>(val);
4 try {
5 int val = std::any_cast<int>(val); // will throw
6 } catch (std::bad_any_cast const& ex) {...}
7 if (val.type() == typeid(int)) // requires RTTI
8 std::cout << std::any_cast<int>(val);
9 val.reset(); assert(!val.has_value());
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 279 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
non-member begin and end C++ 11
The problem in C++ 98
STL containers and arrays have different syntax for loop
1 std::vector<int> v;
2 int a[] = {1,2,3};
3 for(auto it = v.begin(); it != v.end(); it++) {...}
4 for(int i = 0; i < 3; i++) {...}
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 280 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
non-member begin and end C++ 11
The problem in C++ 98
STL containers and arrays have different syntax for loop
1 std::vector<int> v;
2 int a[] = {1,2,3};
3 for(auto it = v.begin(); it != v.end(); it++) {...}
4 for(int i = 0; i < 3; i++) {...}
A new syntax
5 for(auto it = begin(v); it != end(v); it++) {...}
6 for(auto i = begin(a); i != end(a); i++) {...}
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 280 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
non-member begin and end C++ 11
The problem in C++ 98
STL containers and arrays have different syntax for loop
1 std::vector<int> v;
2 int a[] = {1,2,3};
3 for(auto it = v.begin(); it != v.end(); it++) {...}
4 for(int i = 0; i < 3; i++) {...}
A new syntax
5 for(auto it = begin(v); it != end(v); it++) {...}
6 for(auto i = begin(a); i != end(a); i++) {...}
Allowing the best syntax
7 for(auto & element : v) {...}
8 for(auto & element : a) {...}
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 280 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
std::tuple cppreference C++ 11
1 #include <tuple>
2
3 std::tuple<int, float, bool> t{42, 3.14f, false};
4 auto t = std::make_tuple(42, 3.14f, false);
5 std::tuple t{42, 3.14f, false}; // C++17 CTAD
6
7 float& f = std::get<1>(t); // get 1. member
8 bool& b = std::get<bool>(t); // get bool member
9
10 using Tup = decltype(t);
11 constexpr auto s = std::tuple_size_v<Tup>; // 3
12 using E2Type = std::tuple_element<2, Tup>; // bool
13
14 auto t2 = std::tuple_cat(t, std::tuple{'A'}, t);
15 // <int, float, bool, char, int, float, bool>
16 bool& b2 = std::get<bool>(t2); // error
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 281 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
std::tuple C++ 11
1 void f(std::tuple<int, float, bool> tuple) {
2 int a; float b; bool c;
3 std::tie(a, b, c) // tuple<int&, float&, bool&>
4 = tuple;
5 // Use structured bindings in C++17
6 }
7
8 int& i = ...;
9 std::tuple{i}; // tuple<int>
10 std::make_tuple(i); // tuple<int>
11 std::make_tuple(std::ref(i)); // tuple<int&>
12 std::tuple{std::ref(i)};
13 // C++17 CTAD, tuple<std::reference_wrapper<int>>
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 282 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Structured Binding Declarations C++ 17
Helps with std::tuple, tuple-like, array or aggregate types
Automatically creates variables and ties them
CV qualifiers and references allowed
1 std::tuple<int, double, long> tuple = ...;
2 auto [ a, b, c ] = tuple;
3
4 struct S { int i; float f; bool b; } s = ...;
5 auto&& [ a, b, c ] = std::move(s);
6
7 int arr[] = {1, 3, 4};
8 const auto& [ a, b, c ] = arr;
9
10 std::unordered_map<K, V> map = ...;
11 for (const auto& [key, value] : map) { ... }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 283 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Structured Binding Declarations C++ 17
“Tuple-like binding prototcol”
For non-aggregates, you can opt-in to structured bindings
The compiler requires these hooks:
Specialize std::tuple_size
Specialize std::tuple_element
Provide either T::get<I>() or get<I>(T)
1 class C { ... }; // complex, cannot change
2 template <>
3 struct std::tuple_size<C> {
4 static constexpr std::size_t value = ...;
5 };
6 template <std::size_t I>
7 struct std::tuple_element<I, C> { using type = ...; };
8 template <std::size_t I>
9 auto& get(C& c) { ... }; // -> std::tuple_element<I, C>&
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 284 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
compile-time branches C++ 17
if constexpr
takes a constexpr expression as condition
evaluates at compile time
key benefit: the discarded branch can contain invalid code
Example code
1 template <typename T>
2 auto remove_ptr(T t) {
3 if constexpr (std::is_pointer_v<T>) {
4 return *t;
5 } else {
6 return t;
7 }
8 }
9 int i = ...; int *j = ...;
10 int r = remove_ptr(i); // equivalent to i
11 int q = remove_ptr(j); // equivalent to *j
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 285 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Pseudo-random number generators (PRNG) C++ 11
Concept
For generating pseudo-random numbers the STL offers:
engines and engine adaptors to generate pseudo random bits
distributions to shape these into numbers
access to (potential) hardware entropy
All found in header <random>
Example
1 #include <random>
2 std::random_device rd;
3 std::default_random_engine engine{rd()};
4 std::normal_distribution dist(5.0, 1.5); // µ, σ
5 double r = dist(engine);
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 286 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Engines C++ 11
Engines
Generate random bits (as integers), depending on algorithm
Can be seeded via constructor or seed()
Algorithms: linear_congruential_engine,
mersenne_twister_engine, subtract_with_carry_engine
Adaptors: discard_block_engine, independent_bits_engine,
shuffle_order_engine
Aliases: minstd_rand0, minstd_rand, mt19937, mt19937_64,
ranlux24, ranlux48, knuth_b (use these)
std::default_random_engine aliases one of the above
Engine creation with seed
1 std::default_random_engine engine{42}; // or empty
2 auto i = engine(); // operator(): random integer
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 287 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Determinism and random device C++ 11
Engines / PRNGs
Are deterministic
Will produce the same number sequence for the same seed
May be useful for reproducibility
std::random_device
Provides non-deterministic random numbers
Uses hardware provided entropy, if available
May become slow when called too often,
e.g. when hardware entropy pool is exhausted
Use only to seed engine, if non-deterministic numbers needed
Non-deterministic engine seeding
1 std::random_device rd;
2 std::default_random_engine engine{rd()};
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 288 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Distributions C++ 11
Distributions
Take random bits from engines and shape them into numbers
Standard library provides a lot of them
Uniform, bernoulli, poisson, normal and sampling distributions
See cppreference for the full list
Distributions sharing a non-deterministic engine
1 std::random_device rd;
2 std::default_random_engine engine{rd()};
3 std::uniform_int_distribution<int> dist(2,7);//min,max
4 const int size = dist(engine); // gen. random number
5 std::vector<int> v(size);
6 std::normal_distribution<double> norm(5.0, 1.5); //µ,σ
7 std::generate(begin(v), end(v),
8 [&]{ return norm(engine); });
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 289 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
C random library C++ 98
C random library
The C library (<cstdlib>) offers a primitive PRNG:
rand() returns random int between 0 and RAND_MAX (incl.)
srand(seed) sets the global seed
Disadvantages
Seeding is not thread-safe; rand() may be.
Returned numbers have small, implementation-defined range
No guarantee on quality
Mapping a random number to a custom range is hard
E.g.: rand() % 10 yields biased numbers and is wrong!
Good practice: Strongly avoid the C random library
Use the C++ 11 facilities from the <random> header
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 290 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Ranges
4 Core modern C++
Constness
Constant Expressions
Exceptions
Move semantics
Copy elision
Templates
Lambdas
The STL
More STL
Ranges
RAII and smart pointers
Initialization
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 291 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Ranges C++ 20
The range concept
A range is a sequence of items that you can iterate over
It must provide iterators to its beginning and end, obtainable
via std::range::begin and std::range::end
Range concepts are located in std::ranges namespace
All STL containers are ranges
Variations on ranges
There are actually different types of ranges
input_range, output_range, forward_range,
bidirectional_range, random_access_range,
contiguous_range
corresponding to the different iterator categories
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 292 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Views C++ 20
The view concept
A view is a non-owning object built from a range or another
view after applying some range adaptor(s)
The time complexity to copy, move, assign is constant
Range adaptors can be applied/chained with | and are lazy
They live in the std::views namespace
They introduce easy functional programming to the STL
Example - godbolt
1 auto const numbers = std::views::iota(0, 6);
2 auto even = [](int i) { return 0 == i % 2; };
3 auto square = [](int i) { return i * i; };
4 auto results = numbers | std::views::filter(even)
5 | std::views::transform(square);
6 for (auto a : results) { ... } // 0, 4, 16
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 293 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Many range adaptors are provided by the STL C++ 20
Useful subset
all a view on all elements
filter applies a filter
transform applies a transformation
take takes only first n elements
drop skips first n elements
join/split joins ranges or splits into subranges
reverse reverses view order
elements for tuple views, extract nth elements of each tuple
keys/values for pair like views, takes 1st/2nd element of each pair
Remember you can combine them via (|)
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 294 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Back to laziness C++ 23
Views are lazy
Computation is only triggered when iterating
And can be stopped by e.g. take
Here, the minimal number of iterations is performed
Example - godbolt
1 // print first 20 prime numbers above 1000000
2 for (int i: std::views::iota(1000000)
3 | std::views::filter(odd)
4 | std::views::filter(isPrime)
5 | std::views::take(20)) {
6 std::cout << i << " ";
7 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 295 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
RAII and smart pointers
4 Core modern C++
Constness
Constant Expressions
Exceptions
Move semantics
Copy elision
Templates
Lambdas
The STL
More STL
Ranges
RAII and smart pointers
Initialization
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 296 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Pointers: why are they error prone? C++ 98
They need initialization
1 char *s;
2 try {
3 foo(); // may throw
4 s = new char[100];
5 read_line(s);
6 } catch (...) { ... }
7 process_line(s);
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 297 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Pointers: why are they error prone? C++ 98
They need initialization Seg Fault
1 char *s;
2 try {
3 foo(); // may throw
4 s = new char[100];
5 read_line(s);
6 } catch (...) { ... }
7 process_line(s);
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 297 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Pointers: why are they error prone? C++ 98
They need initialization Seg Fault
1 char *s;
2 try {
3 foo(); // may throw
4 s = new char[100];
They
5 need to be released
read_line(s);
6
1 } catch
char *s = (...) { ... }
new char[100];
7
2 process_line(s);
read_line(s);
3 if (s[0] == '#') return;
4 process_line(s);
5 delete[] s;
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 297 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Pointers: why are they error prone? C++ 98
They need initialization Seg Fault
1 char *s;
2 try {
3 foo(); // may throw
4 s = new char[100];
They
5 need to be released
read_line(s); Memory leak
6
1 } catch
char *s = (...) { ... }
new char[100];
7
2 process_line(s);
read_line(s);
3 if (s[0] == '#') return;
4 process_line(s);
5 delete[] s;
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 297 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Pointers: why are they error prone? C++ 98
They need initialization Seg Fault
1 char *s;
2 try {
3 foo(); // may throw
4 s = new char[100];
They
5 need to be released
read_line(s); Memory leak
6
1 } catch
char *s = (...) { ... }
new char[100];
7
2 process_line(s);
read_line(s);
They
3 need clear ownership
if (s[0] == '#') return;
4
1 process_line(s);
char *s = new char[100];
5
2 delete[] s;
read_line(s);
3 vec.push_back(s);
4 set.add(s);
5 std::thread t1{func1, vec};
6 std::thread t2{func2, set};
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 297 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Pointers: why are they error prone? C++ 98
They need initialization Seg Fault
1 char *s;
2 try {
3 foo(); // may throw
4 s = new char[100];
They
5 need to be released
read_line(s); Memory leak
6
1 } catch
char *s = (...) { ... }
new char[100];
7
2 process_line(s);
read_line(s);
They
3 need clear ownership
if (s[0] == '#') return; Who should release ?
4
1 process_line(s);
char *s = new char[100];
5
2 delete[] s;
read_line(s);
3 vec.push_back(s);
4 set.add(s);
5 std::thread t1{func1, vec};
6 std::thread t2{func2, set};
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 297 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
This problem exists for any resource C++ 11
For example with a file
1 std::FILE *handle = std::fopen(path, "w+");
2 if (nullptr == handle) { throw ... }
3 std::vector v(100, 42);
4 write(handle, v);
5 if (std::fputs("end", handle) == EOF) {
6 return;
7 }
8 std::fclose(handle);
Which problems do you spot in the above snippet?
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 298 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Resource Acquisition Is Initialization (RAII) C++ 98
Practically
Use variable construction/destruction and scope semantics:
wrap the resource inside a class
acquire resource in constructor
release resource in destructor
create an instance on the stack
automatically destructed when leaving the scope
including in case of exception
use move semantics to pass the resource around
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 299 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
RAII in practice C++ 98
An RAII File class
1 class File {
2 public:
3 // constructor: acquire resource
4 File(const char* filename)
5 : m_handle(std::fopen(filename, "w+")) {
6 // abort constructor on error
7 if (m_handle == nullptr) { throw ... }
8 }
9 // destructor: release resource
10 ~File() { std::fclose(m_handle); }
11 void write (const char* str) {
12 ...
13 }
14 private:
15 std::FILE* m_handle; // wrapped resource
16 };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 300 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
RAII usage C++ 98
Usage of File class
1 void log_function() {
2 // file opening, aka resource acquisition
3 File logfile("logfile.txt");
4
5 // file usage
6 logfile.write("hello logfile!"); // may throw
7
8 // file is automatically closed by the call to
9 // its destructor, even in case of exception!
10 }
Good practice: Use std::fstream for file handling
The standard library provides std::fstream to handle files, use it!
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 301 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
std::unique_ptr C++ 11
A RAII pointer
wraps and behaves like a regular pointer
get underlying pointer using get()
when destroyed, deletes the object pointed to
has move-only semantic
the pointer has unique ownership
copying will result in a compile error
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 302 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
std::unique_ptr C++ 11
A RAII pointer
wraps and behaves like a regular pointer
get underlying pointer using get()
when destroyed, deletes the object pointed to
has move-only semantic
the pointer has unique ownership
copying will result in a compile error
1 #include <memory>
2 void f(std::unique_ptr<Foo> ptr) {
3 ptr->bar();
4 } // deallocation when f exits
5
6 std::unique_ptr<Foo> p{ new Foo{} }; // allocation
7 f(std::move(p)); // transfer ownership
8 assert(p.get() == nullptr);
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 302 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Quiz C++ 11
What do you expect?
1 void f(std::unique_ptr<Foo> ptr);
2 std::unique_ptr<Foo> uptr(new Foo{});
3 f(uptr); // transfer of ownership
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 303 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Quiz C++ 11
What do you expect?
1 void f(std::unique_ptr<Foo> ptr);
2 std::unique_ptr<Foo> uptr(new Foo{});
3 f(uptr); // transfer of ownership
Compilation Error - godbolt
test.cpp:15:5: error: call to deleted constructor
of 'std::unique_ptr<Foo>'
f(uptr);
^~~~
/usr/include/c++/4.9/bits/unique_ptr.h:356:7: note:
'unique_ptr' has been explicitly marked deleted here
unique_ptr(const unique_ptr&) = delete;
^
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 303 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
std::make_unique C++ 14
std::make_unique
allocates and constructs an object with arguments
and wraps it with std::unique_ptr in one step
no new or delete calls anymore!
no memory leaks if used consistently
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 304 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
std::make_unique C++ 14
std::make_unique
allocates and constructs an object with arguments
and wraps it with std::unique_ptr in one step
no new or delete calls anymore!
no memory leaks if used consistently
std::make_unique usage
1 {
2 // calls new File("logfile.txt") internally
3 auto f = std::make_unique<File>("logfile.txt");
4 f->write("hello logfile!");
5 } // deallocation at end of scope
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 304 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Arrays and unique_ptr C++ 11
Dynamic arrays
unique_ptr can wrap arrays
Use T[] as template parameter
This will enable the subscript operator
The default constructor is called for each element
If size known at compile time, prefer std::array
If size might change, prefer std::vector
1 auto b = std::make_unique<Foo[]>(10);
2 b[3] = ...;
3 b[4].someFunction();
4
5 // deallocations at end of scope
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 305 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
RAII or raw pointers C++ 11
When to use what?
Always use RAII for resources, in particular allocations
You thus never have to release / deallocate yourself
Use raw pointers as non-owning, re-bindable observers
Remember that std::unique_ptr is move only
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 306 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
RAII or raw pointers C++ 11
When to use what?
Always use RAII for resources, in particular allocations
You thus never have to release / deallocate yourself
Use raw pointers as non-owning, re-bindable observers
Remember that std::unique_ptr is move only
A question of ownership
1 std::unique_ptr<T> produce();
2 void observe(const T&);
3 void modifyRef(T&);
4 void modifyPtr(T*);
5 void consume(std::unique_ptr<T>);
6 std::unique_ptr<T> pt{produce()}; // Receive ownership
7 observe(*pt); // Keep ownership
8 modifyRef(*pt); // Keep ownership
9 modifyPtr(pt.get()); // Keep ownership
10 consume(std::move(pt)); // Transfer ownership
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 306 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
std::unique_ptr usage summary C++ 11
Good practice: std::unique_ptr
std::unique_ptr is about lifetime management
use it to tie the lifetime of an object to a unique RAII owner
use raw pointers/references to refer to another object
without owning it or managing its lifetime
use std::make_unique for creation
strive for having no new/delete in your code
for dynamic arrays, std::vector may be more useful
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 307 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
std::shared_ptr C++ 11
std::shared_ptr : a reference counting pointer
wraps a regular pointer similar to unique_ptr
has move and copy semantic
uses reference counting internally
”Would the last person out, please turn off the lights?”
reference counting is thread-safe, therefore a bit costly
std::make_shared : creates a std::shared_ptr
1 {
2 auto sp = std::make_shared<Foo>(); // #ref = 1
3 vector.push_back(sp); // #ref = 2
4 set.insert(sp); // #ref = 3
5 } // #ref 2
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 308 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
weak_ptr C++ 11
weak_ptr: a non-owning observer
Sometimes want to observe resources without keeping them alive
shared_ptr? Resource stays alive
Raw pointer? Risk of dangling pointer
The solution is to construct a weak_ptr from a shared pointer
To access the resource, convert the weak into a shared_ptr
1 std::shared_ptr<Cache> getSharedCache();
2 std::weak_ptr<Cache> weakPtr{ getSharedCache() };
3 // ... shared cache may be invalidated here
4 if (std::shared_ptr<Cache> cache = weakPtr.lock()) {
5 // Cache is alive, we actively extend its lifetime
6 return cache->findItem(...);
7 } else {
8 // Cache is nullptr, we need to do something
9 weakPtr = recomputeCache(...);
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 309 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Quiz: std::shared_ptr in use C++ 11
What is the output of this code? - godbolt
1 auto shared = std::make_shared<int>(100);
2 auto print = [shared](){
3 std::cout << "Use: " << shared.use_count() << " "
4 << "value: " << *shared << "\n";
5 };
6 print();
7 {
8 auto ptr{ shared };
9 (*ptr)++;
10 print();
11 }
12 print();
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 310 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Quiz: std::shared_ptr in use C++ 11
What is the output of this code? - godbolt
1 auto shared = std::make_shared<int>(100);
2 auto print = [shared](){
3 std::cout << "Use: " << shared.use_count() << " "
4 << "value: " << *shared << "\n";
5 };
6 print();
7 {
8 auto ptr{ shared };
9 (*ptr)++;
10 print();
11 }
12 print();
Use: 2 value: 100
Use: 3 value: 101
Use: 2 value: 101
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 310 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Quiz: std::shared_ptr in use C++ 11
What is the output of this code?
1 auto shared = std::make_shared<int>(100);
2 auto print = [&shared](){
3 std::cout << "Use: " << shared.use_count() << " "
4 << "value: " << *shared << "\n";
5 };
6 print();
7 {
8 auto ptr{ shared };
9 (*ptr)++;
10 print();
11 }
12 print();
Use: 1 value: 100
Use: 2 value: 101
Use: 1 value: 101
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 311 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Quiz: shared_ptr and weak_ptr in use C++ 11
What is the output of this code? - godbolt
1 auto shared = std::make_shared<int>(100);
2 std::weak_ptr<int> weak{ shared };
3 print(); // with print as before
4
5 auto ptr = weak.lock();
6 (*ptr)++; print();
7
8 ptr = nullptr; print();
9
10 function(weak); print();
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 312 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Quiz: shared_ptr and weak_ptr in use C++ 11
What is the output of this code? - godbolt
1 auto shared = std::make_shared<int>(100);
2 std::weak_ptr<int> weak{ shared };
3 print(); // with print as before
4
5 auto ptr = weak.lock();
6 (*ptr)++; print();
7
8 ptr = nullptr; print();
9
10 function(weak); print();
Use: 1 value: 100
Use: 2 value: 101
Use: 1 value: 101
Use: 1 (or more) value: ???
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 312 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Rule of zero C++ 11
Good practice: Single responsibility principle (SRP)
Every class should have only one responsibility.
Good practice: Rule of zero
If your class has any special member functions (except ctor.)
Your class probably deals with a resource, use RAII
Your class should only deal with this resource (SRP)
Apply rule of 3/5: write/default/delete all special members
Otherwise: do not declare any special members (rule of zero)
A constructor is fine, if you need some setup
If your class holds a resource as data member:
wrap it in a smart pointer, container, or any other RAII class
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 313 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
smart pointers C++ 98
Exercise: Smart pointers
go to exercises/smartPointers
compile and run the program. It doesn’t generate any output.
Run with valgrind if possible to check for leaks
$ valgrind --leak-check=full --track-origins=yes ./smartPointers
In the essentials course, go through problem1() and
problem2() and fix the leaks using smart pointers.
In the advanced course, go through problem1() to
problem4() and fix the leaks using smart pointers.
problem4() is the most difficult. Skip if not enough time.
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 314 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Initialization
4 Core modern C++
Constness
Constant Expressions
Exceptions
Move semantics
Copy elision
Templates
Lambdas
The STL
More STL
Ranges
RAII and smart pointers
Initialization
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 315 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Initialization
Initializing scalars
1 int i(42); // direct initialization
2 int i{42}; // direct list initialization (C++11)
3 int i = 42; // copy initialization
4 int i = {42}; // copy list initialization (C++11)
All of the above have the same effect: i == 42
Narrowing conversions
1 int i(42.3); // i == 42
2 int i{42.3}; // compilation error
3 int i = 42.3; // i == 42
4 int i = {42.3}; // compilation error
Braced initialization prevents narrowing conversions
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 316 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Initialization
Initializing class types with constructors
1 struct C {
2 C(int i);
3 C(int i, int j);
4 };
5
6 C c(42); // calls C(42)
7 C c{42}; // same
8 C c = 42; // calls C(42) in C++17, before C(C(42))
9 C c = {42}; // same
10
11 C c(1, 2); // calls C(1, 2)
12 C c{1, 2}; // calls C(1, 2)
13 C c = (1, 2); // calls C(2), comma operator
14 C c = {1, 2}; // calls C(1, 2) in C++17, before C(C(1, 2))
15
16 C c(1.1, 2.2); // calls C(1, 2)
17 C c{1.1, 2.2}; // compilation error
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 317 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Initialization
std::initializer_list
1 struct C {
2 C(int i, int j);
3 C(std::initializer_list<int> l);
4 };
5
6 C c(1, 2); // calls C(1, 2)
7 C c{1, 2}; // calls C(std::initializer_list<int>{1, 2})
8 C c = (1, 2); // calls C(2), comma operator, error
9 C c = {1, 2}; // calls C(std::initializer_list<int>{1, 2})
A constructor with a std::initializer_list parameter takes
precedence over other overloads.
Beware
1 std::vector<int> v1(4, 5); // {5, 5, 5, 5}
2 std::vector<int> v2{4, 5}; // {4, 5}
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 318 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Initialization
Type deduction
1 auto i(42); // int
2 auto i{42}; // C++11: std::initializer_list<int>
3 // since C++17: int
4 auto i = 42; // int
5 auto i = {42}; // std::initializer_list<int>
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 319 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Initialization C++ 11
Default initialization
T t;
If T has a default constructor (including compiler generated),
calls it
If T is a fundamental type, t is left uninitialized (undefined
value)
If T is an array, the same rules are applied to each item
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 320 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Initialization C++ 11
Value initialization
1 T t{}; // value initialization
2 T t = {}; // same
3 f(T()); // passes value-initialized temporary
4 f(T{}); // same
5 T t(); // function declaration
Basically zero-initializes t (or the temporary), unless T has a
user defined constructor, which is run in this case
Details on cppreference
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 321 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Initialization C++ 11
Aggregate initialization
1 struct S { int i; double d; };
2
3 S s{1, 2.3}; // s.i == 1, s.d == 2.3
4 S s = {1, 2.3}; // same
5 S s{.i = 1, .d = 2.3} // same, designated init. (C++20)
6 S s = {.i = 1, .d = 2.3} // same
7 S s{1}; // s.i == 1, s.d == 0.0
8 S s = {1}; // same
9 S s{.i = 1} // same (C++20)
10 S s = {.i = 1} // same (C++20)
11 S s{}; // value init, s.i == 0, s.d == 0.0
12 S s; // default init, undefined values
An aggregate is a class with no constructors, only public base classes
(C++ 17) and members, no virtual functions, no default member
initializers (until C++ 14)
Details on cppreference
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 322 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Initialization C++ 11
Good practice: Initialization
In generic code, for a generic type T:
T t; performs the minimally necessary initialization
T t{}; performs full and deterministic initialization
Prefer T t{}; over T t; memset(&t, 0, sizeof(t));
Prefer braces over parentheses to avoid accidental narrowing
conversions. E.g. T t{1, 2};
Unless T has a std::initializer_list constructor that you
do not want to call!
Be wary of std::vector!
The STL value initializes when creating new user objects
E.g. vec.resize(vec.size() + 10);
Aggregates are very flexible. If your class does not need
special initialization, make it an aggregate (rule of zero)
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 323 / 548
Intro base OO More exp Tool conc py cst cstexpr except mv copy <T> λ STL More range RAII Init
Initialization
Further resources
The Nightmare of Initialization in C++ - Nicolai Josuttis -
CppCon 2018
Initialization in modern C++ - Timur Doumler - Meeting
C++ 2018
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 324 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
++
Expert C
Variadic templates
Perfect forwarding
1 History and goals
SFINAE
Concepts
2 Language basics Modules
Coroutines
3 Object orientation (OO)
6 Useful tools
4 Core modern C++
7 Concurrency
5 Expert C++
The <=> operator 8 C++ and python
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 325 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
The <=> operator
5 Expert C++
The <=> operator
Variadic templates
Perfect forwarding
SFINAE
Concepts
Modules
Coroutines
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 326 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
The burden of comparison operators
Motivation
One often needs operator< for a user-defined class
e.g. when sorting a std::vector
e.g. when using it as a key for std::set or std::map
Many other operators are also desirable for completeness
operator>, operator>=, operator<=, ...
often implemented reusing e.g. operator< and operator==
Should be defined as hidden friend functions
Much boilerplate code to write. Too much...
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 327 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
The three-way comparison operator C++ 20
Idea
C++20 introduces operator<=>
named the three-way comparison operator.
unofficially called spaceship operator
allowing to implement all comparisons in one go
How it works
it returns something which can be compared to 0
similar to std::strcmp
lower, greater, or equal to 0 means respectively lower than,
greater than and equivalent to
It is provided by default for all built-in types and many types
in the standard library
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 328 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
The three-way comparison operator practically C++ 20
Output of operator<=> - godbolt
1 template <typename T>
2 void three_way_compare( T lhs, T rhs ) {
3 auto res = lhs <=> rhs;
4 std::cout << lhs << "<=>" << rhs << ": "
5 << (res<0) << (res==0) << (res>0)
6 << '\n';
7 }
8 int main() {
9 three_way_compare(1, 2); // 1<=>2: 100
10 three_way_compare(2, 2); // 2<=>2: 010
11 three_way_compare(2, 1); // 2<=>1: 001
12 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 329 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Different kinds of ordering C++ 20
The return type of operator<=>
for integers operator<=> returns std::strong_ordering
weak_ordering and partial_ordering also exist
3 types of ordering
strong exactly one test among <0, ==0, and >0 will return true
weak like strong but two equivalent values may differ
they are however equivalent for ranking
e.g. rational numbers 2/3 and 4/6
partial like weak but some values are incomparable
for some values all tests may return false
e.g. compare a floating point to NaN
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 330 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Exercising different orderings C++ 20
Example - godbolt
1 struct Ratio {
2 unsigned n, d ;
3 friend std::weak_ordering operator<=>( Ratio const & a,
4 Ratio const & b ) {
5 return (a.n * b.d) <=> (a.d * b.n);
6 }
7 friend std::ostream & operator<<( std::ostream & os, Ratio const & r ) {
8 return (os << r.n << '/' << r.d);
9 }
10 };
11 int main() {
12 // Ratio uses weak_ordering
13 three_way_compare(Ratio{1, 2}, Ratio{2, 3}); // 1/2<=>2/3 : 100
14 three_way_compare(Ratio{2, 3}, Ratio{4, 6}); // 2/3<=>4/6 : 010
15 three_way_compare(Ratio{2, 3}, Ratio{1, 2}); // 2/3<=>1/2 : 001
16
17 // floats use partial_ordering
18 three_way_compare(+0., -0.); // 0<=>-0 : 010
19 three_way_compare(0., 1./0.); // 0<=>inf : 100
20 three_way_compare(0., 0./0.); // 0<=>-nan : 000
21 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 331 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Compiler-generated comparison operators C++ 20
For a given user-defined class
defining operator<=> allows the compiler to use it when
encountering the comparison operators <, <=, > and >=
of course, one can still provide a custom implementation
the compiler will NOT add a default implementation for
operator== and operator!=
as those operators mean equal, rather than equivalent
if operator<=> does not provide a strong order, it is advised
not to define operator==
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 332 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Compiler-generated operator<=> C++ 20
Default operator<=> implementation
One can ask the compiler to provide a default implementation
for operator<=> and/or operator==
declaring them with “= default”
it will compare the member variables, one by one
Can be useful e.g. for tuples
Can be wrong, e.g. for the Ratio class
If operator<=> is defaulted and no operator== is defined,
then the compiler also provides operator==
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 333 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
operator<=> summary C++ 20
Summary
Defining operator<=> allows you to use operator<,
operator>, operator<=, and operator>= for free
The standard library defines a few kinds of orderings
strong, weak and partial
If operator<=> does not define a strong ordering, avoid
defining operator==
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 334 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Variadic templates
5 Expert C++
The <=> operator
Variadic templates
Perfect forwarding
SFINAE
Concepts
Modules
Coroutines
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 335 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Basic variadic template C++ 11
The idea
a parameter accepting arbitrarily many arguments (i.e. pack)
template parameter pack for e.g. types, function parameter
packs for values, and expansions, details on cppreference
Recursive example cppinsight
1 template<typename T>
2 T sum(T v) { return v; }
3
4 template<typename T,
5 typename... Args> // temp. param. pack
6 T sum(T first, Args... args) { // func. param. pack
7 return first + sum(args...); // pack expansion
8 }
9 int s = sum(1, 2, 3, 8, 7);
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 336 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
A couple of remarks C++ 11
About performance
do not be afraid of recursion
everything is at compile time!
unlike C-style variadic functions
e.g. printf(const char* fmt, ...);
Why it is better than variadic functions
it’s more performant
type safety is included
it applies to everything, including user-defined types
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 337 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Parameter packs C++ 11
Parameter packs
only a few operations are supported
query the number of elements in a pack with sizeof...
expand it with x...
can be empty
can hold different types
1 template<typename... Args>
2 void f(Args... args) {
3 constexpr std::size_t N = sizeof...(Args);
4 std::tuple<Args...> t{args...};
5 }
6 f(0, 1, 2); // Args = [int, int, int]
7 f(); // Args = empty
8 f(0, true, 3.14); // Args = [int, bool, double]
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 338 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Fold expressions C++ 17
The idea
reduces a parameter pack over a binary operator
details on cppreference
Example
1 template<typename... Args>
2 auto sum1(Args... args) {
3 return (args + ...); // unary fold over +
4 } // parentheses mandatory
5 template<typename... Args>
6 auto sum2(Args... args) {
7 return (args + ... + 0); // binary fold over +
8 } // parentheses mandatory
9 int sum = sum1(); // error
10 int sum = sum2(); // ok
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 339 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Fold expressions C++ 17
Example: call a function on all arguments - cppinsight
1 template<typename T>
2 void print(const T& t) {
3 std::cout << t;
4 }
5 template<typename... Ts>
6 void printAll(const Ts&... ts) {
7 (print(ts),...); // fold over comma operator
8 }
C++ 11 workaround (don’t use anymore)
1 template<typename... Ts>
2 void printAll(const Ts&... ts) {
3 int dummy[]{(print(ts),0)...};
4 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 340 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Variadic class template C++ 11
The tuple example, simplified - godbolt
1 template <typename... Ts>
2 struct tuple {};
3
4 template <typename T, typename... Ts>
5 struct tuple<T, Ts...> : tuple<Ts...> {
6 tuple(T head, Ts... tail) :
7 tuple<Ts...>(tail...), m_head(head) {}
8 T m_head;
9 };
10
11 tuple<double, uint64_t, const char*>
12 t1(12.2, 42, "big");
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 341 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
std::integer_sequence C++ 14
Packs of values
We can also have non-type template parameter packs
Useful to pass lists of compile-time constants around
The standard library includes a few helpers
1 template<typename T, T... Is>
2 struct integer_sequence { ... };
3
4 template<size_t... Is>
5 using index_sequence =
6 integer_sequence<std::size_t, Is...>;
7
8 template<size_t N>
9 using make_index_sequence =
10 index_sequence</*0, 1, ..., N-1*/ >;
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 342 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
std::integer_sequence C++ 14
Example - make_from_tuple with helper
1 template<typename T,
2 typename... Args, std::size_t... Is>
3 T helper(std::tuple<Args...> args,
4 std::index_sequence<Is...>) {
5 return T(std::get<Is>(args)...);
6 }
7 template<typename T, typename... Args>
8 T make_from_tuple(std::tuple<Args...> args) {
9 return helper<T>(args,
10 std::make_index_sequence<sizeof...(Args)>{});
11 }
12
13 struct S { S(int, float, bool) { ... } };
14 std::tuple t{42, 3.14, false};
15 S s = make_from_tuple<S>(t);
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 343 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
std::integer_sequence C++ 20
Example - make_from_tuple with lambda
1 template<typename T, typename... Args>
2 T make_from_tuple(std::tuple<Args...> args) {
3 return [&]<std::size_t... Is>(
4 std::index_sequence<Is...>){
5 return T(std::get<Is>(args)...);
6 }(std::make_index_sequence<sizeof...(Args)>{});
7 }
8
9 struct S { S(int, float, bool) { ... } };
10 std::tuple t{42, 3.14, false};
11 S s = make_from_tuple<S>(t);
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 344 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Variadic templates C++ 11
Exercise: Variadic templates
go to exercises/variadic
you will extend the tuple from the last slides
follow the instructions in the source code
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 345 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Perfect forwarding
5 Expert C++
The <=> operator
Variadic templates
Perfect forwarding
SFINAE
Concepts
Modules
Coroutines
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 346 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
The problem C++ 11
How to write a generic wrapper function?
1 template <typename T>
2 void wrapper(T arg) {
3 // code before
4 func(arg);
5 // code after
6 }
Example usage :
emplace_back
make_unique
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 347 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Why is it not so simple? C++ 11
1 template <typename T>
2 void wrapper(T arg) {
3 func(arg);
4 }
What about references?
what if func takes a reference to avoid copies?
wrapper would force a copy and we fail to use references
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 348 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Second try, second failure ? C++ 11
1 template <typename T>
2 void wrapper(T& arg) {
3 func(arg);
4 }
5 wrapper(42);
6 // invalid initialization of
7 // non-const reference from
8 // an rvalue
and const T& won’t work when passing something non const
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 349 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Solution: cover all cases C++ 11
1 template <typename T>
2 void wrapper(T& arg) { func(arg); }
3
4 template <typename T>
5 void wrapper(const T& arg) { func(arg); }
6
7 template <typename T>
8 void wrapper(T&& arg) { func(std::move(arg)); }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 350 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
The new problem: scaling to more arguments C++ 11
1 template <typename T1, typename T2>
2 void wrapper(T1& arg1, T2& arg2)
3 { func(arg1, arg2); }
4
5 template <typename T1, typename T2>
6 void wrapper(const T1& arg1, T2& arg2)
7 { func(arg1, arg2); }
8
9 template <typename T1, typename T2>
10 void wrapper(T1& arg1, const T2& arg2)
11 { func(arg1, arg2); }
12 ...
Exploding complexity
for n arguments, 3n overloads
you do not want to try n = 5...
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 351 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Reference collapsing C++ 11
Reference to references
Are formally forbidden, but can occur sometimes
1 template <typename T>
2 void foo(T t) { T& k = t; } //int& &, error in C++98
3 int ii = 4;
4 foo<int&>(ii); // want to pass by reference
C++ 11 added rvalue-references
More combinations possible, like: int&& &, or int&& &&
Reference collapsing
Rule: When multiple references are involved, & always wins
T&& &, T& &&, T& & → T&
T&& && → T&&
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 352 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Forwarding references C++ 11
Rvalue reference in type-deducing context
1 template <typename T>
2 void f(T&& t) { ... }
Forwarding reference
Next to a template parameter, that can be deduced, && is not
an rvalue reference, but a “forwarding reference”
aka. “universal reference”
So, this applies only to functions
The template parameter is additionally allowed to be deduced
as an lvalue reference, and reference collapsing proceeds:
if an lvalue of type U is given, T is deduced as U& and the
parameter type U& && collapses to U&
otherwise (rvalue), T is deduced as U
and forms the parameter type U&&
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 353 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Forwarding references C++ 11
Examples
1 template <typename T>
2 void f(T&& t) { ... }
3
4 f(4); // rvalue -> T&& is int&&
5 double d = 3.14;
6 f(d); // lvalue -> T&& is double&
7 float g() {...}
8 f(g()); // rvalue -> T&& is float&&
9 std::string s = "hello";
10 f(s); // lvalue -> T&& is std::string&
11 f(std::move(s)); // rvalue -> T&& is std::string&&
12 f(std::string{"hello"}); // rvalue -> std::string&&
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 354 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Forwarding references C++ 20
Careful!
1 template <typename T> struct S {
2 S(T&& t) { ... } // rvalue references
3 void f(T&& t) { ... } // NOT forwarding references
4 };
Half-way correct version
1 template <typename T> struct S {
2
3 template <typename U>
4 S(U&& t) { ... } // deducing context -> fwd. ref.
5 template <typename U>
6 void f(U&& t) // deducing context -> fwd. ref.
7 // ... but now U can be a different type than T
8 };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 355 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Forwarding references C++ 20
Careful!
1 template <typename T> struct S {
2 S(T&& t) { ... } // rvalue references
3 void f(T&& t) { ... } // NOT forwarding references
4 };
Correct version
1 template <typename T> struct S {
2 template <typename U, std::enable_if_t<
3 std::is_same_v<std::decay_t<U>, T>, int> = 0>
4 S(U&& t) { ... } // deducing context -> fwd. ref.
5 template <typename U>
6 void f(U&& t) // deducing context -> fwd. ref.
7 requires std::same_as<std::decay_t<U>, T> { ... }
8 };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 355 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Perfect forwarding C++ 11
std::remove_reference
Type trait to remove reference from a type
If T is a reference type, remove_reference_t<T> is the type
referred to by T, otherwise it is T.
1 template <typename T>
2 struct remove_reference { using type = T; };
3 template <typename T>
4 struct remove_reference<T&> { using type = T; };
5 template <typename T>
6 struct remove_reference<T&&> { using type = T; };
7
8 template <typename T>
9 using remove_reference_t =
10 typename remove_reference<T>::type; // C++14
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 356 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Perfect forwarding C++ 11
std::forward
Forward lvalue-/rvalueness
Keeps references and maps non-references to rvalue references
1 template<typename T>
2 T&& forward(remove_reference_t<T>& t) noexcept { // 1.
3 return static_cast<T&&>(t);
4 }
5 template<typename T>
6 T&& forward(remove_reference_t<T>&& t) noexcept { // 2.
7 return static_cast<T&&>(t);
8 }
if T is int, selects 2., returns int&&
if T is int&, selects 1., returns int& &&, i.e. int&
if T is int&&, selects 2., returns int&& &&, i.e. int&&
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 357 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Perfect forwarding C++ 11
Example - putting it all together
1 template <typename... T>
2 void wrapper(T&&... args) {
3 func(std::forward<T>(args)...);
4 }
if we pass an rvalue reference U&& to wrapper
T=U, arg is of type U&&
func will be called with a U&&
if we pass an lvalue reference U& to wrapper
T=U&, arg is of type U& (reference collapsing)
func will be called with a U&
if we pass a plain U (rvalue) to wrapper
T=U, arg is of type U&& (no copy in wrapper)
func will be called with a U&&
if func takes a plain U, copy happens there, as expected
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 358 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Real life example C++ 11
1 template<typename T, typename... Args>
2 unique_ptr<T> make_unique(Args&&... args) {
3 return unique_ptr<T>
4 (new T(std::forward<Args>(args)...));
5 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 359 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
SFINAE
5 Expert C++
The <=> operator
Variadic templates
Perfect forwarding
SFINAE
Concepts
Modules
Coroutines
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 360 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Substitution Failure Is Not An Error (SFINAE) C++ 11
The main idea
substitution replaces template parameters with the provided
arguments (types or values)
if it leads to invalid code, do not report an error but try other
overloads/specializations
Example
1 template <typename T>
2 void f(typename T::type arg) { ... }
3 void f(int a) { ... }
4
5 f(1); // Calls void f(int)
Note: SFINAE is largely superseded by concepts in C++ 20
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 361 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
decltype C++ 11
The main idea
gives the type of the result of an expression
the expression is not evaluated (i.e. unevaluated context)
at compile time
Example
1 struct A { double x; };
2 A a;
3 decltype(a.x) y; // double
4 decltype((a.x)) z = y; // double& (lvalue)
5 decltype(1 + 2u) i = 4; // unsigned int
6
7 template<typename T, typename U>
8 auto add(T t, U u) -> decltype(t + u);
9 // return type depends on template parameters
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 362 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
declval C++ 11
The main idea
gives you a reference to a “fake” object at compile time
useful for types that cannot easily be constructed
use only in unevaluated contexts, e.g. inside decltype
1 struct Default {
2 int foo() const;
3 };
4 class NonDefault {
5 private: NonDefault();
6 public: int foo() const;
7 };
8 decltype(Default().foo()) n1 = 1; // int
9 decltype(NonDefault().foo()) n2 = 2; // error
10 decltype(std::declval<NonDefault>().foo()) n3 = 3;
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 363 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
true_type and false_type C++ 11
The main idea
encapsulate a compile-time boolean as type
can be inherited
Example
1 struct truth : std::true_type { };
2
3 constexpr bool test = truth::value; // true
4 constexpr truth t;
5 constexpr bool test = t(); // true
6 constexpr bool test = t; // true
Possible implementation
1 using true_type = integral_constant<bool, true >;
2 using false_type = integral_constant<bool, false>;
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 364 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Using SFINAE for introspection C++ 11
The main idea
use a primary template, inheriting from false_type
use a template specialization, inheriting from true_type
which depends on the feature you want to introspect, as part
of the context where template argument deduction happens
let SFINAE choose between the two templates
Example
1 template <typename T, typename = void>
2 struct hasFoo : std::false_type {}; // primary template
3 template <typename T>
4 struct hasFoo<T, decltype(std::declval<T>().foo())>
5 : std::true_type {}; // template special.
6 struct A{}; struct B{ void foo(); };
7 static_assert(!hasFoo<A>::value, "A has no foo()");
8 static_assert(hasFoo<B>::value, "B has foo()");
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 365 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Not so easy actually... C++ 11
Example - godbolt
1 template <typename T, typename = void>
2 struct hasFoo : std::false_type {};
3 template <typename T>
4 struct hasFoo<T, decltype(std::declval<T>().foo())>
5 : std::true_type {};
6
7 struct A{};
8 struct B{ void foo(); };
9 struct C{ int foo(); };
10
11 static_assert(!hasFoo<A>::value, "A has no foo()");
12 static_assert(hasFoo<B>::value, "B has foo()");
13 static_assert(!hasFoo<C>::value, "C has no foo()");
14 static_assert(hasFoo<C,int>::value, "C has foo()");
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 366 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Using void_t C++ 17
Concept
Maps a sequence of given types to void
Introduced in C++ 17, though trivial to implement in C++ 11
Can be used in specializations to check the validity of an
expression
Implementation in header type_traits
1 template <typename...>
2 using void_t = void;
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 367 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Previous introspection example using void_t C++ 17
Example - godbolt
1 template <typename T, typename = void>
2 struct hasFoo : std::false_type {};
3
4 template <typename T>
5 struct hasFoo<T,
6 std::void_t<decltype(std::declval<T>().foo())>>
7 : std::true_type {};
8
9 struct A{}; struct B{ void foo(); };
10 struct C{ int foo(); };
11
12 static_assert(!hasFoo<A>::value,"unexpected foo()");
13 static_assert(hasFoo<B>::value, "expected foo()");
14 static_assert(hasFoo<C>::value, "expected foo()");
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 368 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Standard type traits C++ 11
Standard type traits
Don’t implement SFINAE introspection for everything,
use the standard library!
Standard type traits in header <type_traits>
They look like std::is_*<T>
Checks at compile time whether T is
float, signed, final, abstract, default_constructible, ...
Result in nested boolean constant value
Since C++ 17, variable template versions: std::is_*_v<T>,
giving the bool directly
1 constexpr bool b = std::is_pointer<int*>::value;
2 constexpr bool b = std::is_pointer_v<int*>; // C++17
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 369 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
SFINAE and the STL C++ 11/C++ 14
enable_if cppreference
template<bool B, typename T=void>
struct enable_if;
If B is true, has a nested alias type to type T
otherwise, has no such alias
Example
1 template<bool B, typename T=void>
2 struct enable_if {};
3 template<typename T>
4 struct enable_if<true, T> { using type = T; };
5
6 template<bool B, typename T = void> // C++14
7 using enable_if_t = typename enable_if<B, T>::type;
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 370 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Usage example - godbolt
1 template <typename T> constexpr bool is_iterable ... ;
2
3 template<typename T,
4 typename std::enable_if_t
5 <!is_iterable<T>, bool> = true>
6 void print(T const& t) {
7 std::cout << t << "\n";
8 }
9 template<typename T,
10 typename std::enable_if_t
11 <is_iterable<T>, bool> = true>
12 void print(T const& t) {
13 for (auto const& item : t) {
14 std::cout << item << "\n";
15 }
16 }
Note : using if constexpr would be simpler
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 371 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Back to variadic class templates C++ 11
The tuple_element trait
1 template <size_t I, typename Tuple>
2 struct tuple_element;
3
4 template <typename T, typename... Ts>
5 struct tuple_element<0, tuple<T, Ts...>> {
6 using type = T;
7 };
8
9 template <size_t I, typename T, typename... Ts>
10 struct tuple_element<I, tuple<T, Ts...>> {
11 using type = typename
12 tuple_element<I - 1, tuple<Ts...>>::type;
13 };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 372 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Back to variadic class templates C++ 14
The tuple get function
1 template <size_t I, typename... Ts>
2 std::enable_if_t<I == 0,
3 typename tuple_element<0, tuple<Ts...>>::type&>
4 get(tuple<Ts...>& t) {
5 return t.m_head;
6 }
7 template <size_t I, typename T, typename... Ts>
8 std::enable_if_t<I != 0,
9 typename tuple_element<I - 1, tuple<Ts...>>::type&>
10 get(tuple<T, Ts...>& t) {
11 return get<I - 1>(static_cast<tuple<Ts...>&>(t));
12 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 373 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
with if constexpr and return type deduction C++ 17
The tuple get function
1 template <size_t I, typename T, typename... Ts>
2 auto& get(tuple<T, Ts...>& t) {
3 if constexpr(I == 0)
4 return t.m_head;
5 else
6 return get<I - 1>(static_cast<tuple<Ts...>&>(t));
7 }
Good practice: SFINAE vs. if constexpr
if constexpr can replace SFINAE in many places.
It is usually more readable as well. Use it if you can.
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 374 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Concepts
5 Expert C++
The <=> operator
Variadic templates
Perfect forwarding
SFINAE
Concepts
Modules
Coroutines
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 375 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Requirements and concepts C++ 20
Motivation
Generic programming is made of variable, function and class
templates which can be instantiated with different types.
It is frequent to instantiate them with unsuited types, and
the resulting compilation errors are cryptic.
As a last resort, authors provide documentation, and
practice tricky template meta-programming.
C++20 brings simpler ways to define constraints on
template parameters.
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 376 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
The world before concepts C++ 17
C++ 17 work around: SFINAE
Unsuited arguments can be avoided by inserting fake template
arguments, leading to a substitution failure
Practical code - godbolt
1 template
2 <typename T,
3 typename = std::enable_if_t<std::is_floating_point_v<T>>>
4 bool equal( T e1, T e2 ) {
5 return std::abs(e1-e2)<std::numeric_limits<T>::epsilon();
6 }
7 ... equal(10,5+5) ...
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 377 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
The world before concepts C++ 17
C++ 17 work around: SFINAE
Unsuited arguments can be avoided by inserting fake template
arguments, leading to a substitution failure
Practical code - godbolt
1 template
2 <typename T,
3 typename = std::enable_if_t<std::is_floating_point_v<T>>>
4 bool equal( T e1, T e2 ) {
5 return std::abs(e1-e2)<std::numeric_limits<T>::epsilon();
6 }
7 ... equal(10,5+5) ...
<source>:11:12: error: no matching function for call to 'equal(int, int)'
11 if (equal(10,5+5)) { std::cout << "FAILURE\n"; }
<source>:7:6: note: candidate: 'template<class T, class> bool equal(T, T)'
7 bool equal( T e1, T e2 )
<source>:7:6: note: template argument deduction/substitution failed:
In file included from <source>:1:
.../type_traits: In substitution of 'template<bool _Cond, class _Tp>
using enable_if_t = typename std::enable_if::type with bool _Cond = false; _Tp = void':
<source>:6:14: required from here
.../type_traits:2514:11: error: no type named 'type' in 'struct std::enable_if<false, void>'
2514 using enable_if_t = typename enable_if<_Cond, _Tp>::type;
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 377 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Basic requirements C++ 20
A new keyword
The keyword requires lets us define various constraints.
With concepts - godbolt
1 template<typename T>
2 requires std::is_floating_point_v<T>
3 bool equal( T e1, T e2 ) {
4 return std::abs(e1-e2)<std::numeric_limits<T>::epsilon();
5 }
6 ... equal(10,5+5) ...
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 378 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Basic requirements C++ 20
A new keyword
The keyword requires lets us define various constraints.
With concepts - godbolt
1 template<typename T>
2 requires std::is_floating_point_v<T>
3 bool equal( T e1, T e2 ) {
4 return std::abs(e1-e2)<std::numeric_limits<T>::epsilon();
5 }
6 ... equal(10,5+5) ...
<source>:11:12: error: no matching function for call to 'equal(int, int)'
11 if (equal(10,5+5)) { std::cout << "FAILURE\n"; }
<source>:7:6: note: candidate: 'template<class T, class> bool equal(T, T)'
7 bool equal( T e1, T e2 )
<source>:7:6: note: template argument deduction/substitution failed:
<source>:7:6: note: constraints not satisfied
<source>: In substitution of 'template<class T> ... bool equal(T, T) with T = int':
<source>:11:12: required from here
<source>:7:6: required by the constraints of 'template<class T> ... bool equal(T, T)'
<source>:6:15: note: the expression 'is_floating_point_v<T> with T = int' evaluated to 'false'
6 requires std::is_floating_point_v<T>
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 378 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Requirements and overloads C++ 20
Example of several competing templates
1 template<typename T>
2 bool equal( T e1, T e2 ) { return (e1==e2); }
3
4 template< typename T>
5 requires std::is_floating_point_v<T>
6 bool equal( T e1, T e2 )
7 {return std::abs(e1-e2)<std::numeric_limits<T>::epsilon();}
Requirements affect overload resolution
Overload resolution considers the second function as a better
match when the requirements are fulfilled.
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 379 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Concepts C++ 20
Definition
a concept gives a name to a given set of requirements
useful when the same requirements are reused frequently
A new keyword: concept
1 template< typename T>
2 concept MyFloatingPoint =
3 std::is_floating_point_v<T> &&
4 std::numeric_limits<T>::epsilon()>0;
5
6 template<typename T>
7 requires MyFloatingPoint<T>
8 bool equal( T e1, T e2 )
9 {return std::abs(e1-e2)<std::numeric_limits<T>::epsilon();}
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 380 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Some usages of concepts C++ 20
Constrained template parameters
a concept can replace typename in a template parameter list
1 template<MyFloatingPoint T>
2 bool equal( T e1, T e2 ) {
3 return std::abs(e1-e2)<std::numeric_limits<T>::epsilon();
4 }
Constrained variables
a concept can be used together with auto to impose
requirements on the type of a variable
Example code
4 MyFloatingPoint auto f = 3.14f;
5 MyFloatingPoint auto d = 3.14;
6 MyFloatingPoint auto i = 3; // compile error
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 381 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Some usages of concepts C++ 20
Abbreviated function templates
function parameters can be constrained as well
similar to variables
the template head becomes obsolete
the function is still a template though!
unconstrained auto parameters are allowed as well
1 // no template <...> here!
2 bool equal( MyFloatingPoint auto e1,
3 MyFloatingPoint auto e2 ) {
4 return std::abs(e1-e2) <
5 std::numeric_limits<decltype(e1)>::epsilon();
6 }
7
8 // unconstrained abbreviated function template:
9 void equal(auto e1, auto e2) { ... }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 382 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Standard concepts C++ 20
Never reinvent the wheel
Writing a bug-proof concept is an expert task
Prefer the ones provided by the standard library
E.g.: the floating point concept
1 #include <concepts>
2 bool equal( std::floating_point auto e1,
3 std::floating_point auto e2 ) {
4 return std::abs(e1-e2) <
5 std::numeric_limits<decltype(e1)>::epsilon();
6 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 383 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Checking concepts C++ 20
Concepts as Boolean operators
Concepts can be used wherever a bool is expected
they can appear in if constexpr conditions
since they are evaluated at compile-time
Using concepts with if constexpr
1 template<typename T>
2 bool equal( T e1, T e2 )
3 {
4 if constexpr (std::floating_point<T>) {
5 return std::abs(e1-e2)
6 < std::numeric_limits<T>::epsilon();
7 } else {
8 return (e1==e2);
9 }
10 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 384 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Advanced requirements overview C++ 20
requires as an expression
requires can express more than basic requirements. It can
include other basic requirements
list expressions that must be valid
check the return type of some expressions
Practically
1 template<typename T>
2 concept StreamableAndComparableNumber =
3 requires( T v1, T v2, std::ostream os ) {
4 requires std::integral<T> || std::floating_point<T>;
5 os<<v1<<v2;
6 { equal(v1,v2) } -> std::convertible_to<bool>;
7 };
Remember: use standard concepts first
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 385 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Requirements and concepts C++ 20
Summary
A template can now require properties of its parameters
Compiler error messages clearly state which argument does
not fulfill which requirement
A set of requirements can be gathered in a concept
Overload resolution takes requirements into account
The standard library provides many ready-to-use concepts
Writing a new good concept is an expert task
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 386 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Exercise time C++ 20
Exercise: Concepts
go to exercises/concepts
you will use concepts to optimize some loop on iterators
follow the instructions in the source code
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 387 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Modules
5 Expert C++
The <=> operator
Variadic templates
Perfect forwarding
SFINAE
Concepts
Modules
Coroutines
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 388 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Modules C++ 20
Motivation
Modules allow for sharing declarations and definitions across
translation units
Header files do the same, but modules have benefits:
Better isolation. No cross-talk between multiple pieces of
included code, and also not between included code and your
code.
Better control over public interface of your library. Avoid
leaking library dependencies into user code.
Faster compilation (import fmt; >1500x faster)
Textual includes
1 #include "math.h"
Module importation
1 import math;
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 389 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Writing modules C++ 20
ratio.cpp
1 export module math;
2 import <string>;
3 namespace utils { // ns. and module names orthogonal
4 export struct Ratio { float num, denom; };
5 export std::string toString(const Ratio& r) { ... }
6 void normalize(Ratio& r) { ... } // not exported
7 }
main.cpp
1 import <iostream>;
2 import math;
3 int main() {
4 auto r = utils::Ratio{1, 3};
5 std::cout << utils::toString(r);
6 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 390 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Writing modules C++ 20
Exporting declarations
By default, everything inside a module is internal
Declarations become visible when declared with export in the
primary module interface
You can only export entities at namespace scope (including
the global scope)
You cannot export entities with internal linkage (declared
static or inside anonymous namespace)
You cannot export aliases to non-exported types
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 391 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Writing modules C++ 20
What to export
1 export module math;
2
3 export void f(); // function
4 export float pi = 3.14f; // variable
5 export namespace utils { // namespace
6 enum Status { Yes, No }; // enum (exported)
7 }
8 namespace utils {
9 export struct Ratio { ... }; // class
10 export using R = Ratio; // alias
11 float e = 2.71f; // (not exported)
12 }
13 export { // content of export block
14 void h();
15 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 392 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Writing modules C++ 20
What not to export
1 export module math;
2
3 namespace {
4 export void f(); // error
5 export float pi = 3.14f; // error
6 export struct Ratio { ... }; // error
7 }
8
9 export static void f(); // error
10 export static float pi = 3.14f; // error
11
12 class C { ... };
13 export using D = C; // error
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 393 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Visibility and reachability C++ 20
ratio.cpp
1 export module math;
2 struct Ratio { float num, denom; };
3 export Ratio golden() { ... } // golden is visible
main.cpp
1 import math;
2 import <iostream>;
3 int main() {
4 Ratio r = golden(); // error: Ratio not visible
5 auto r = golden(); // OK: Ratio is reachable
6 std::cout << r.num; // OK: members of reachable
7 // types are visible
8 using R = decltype(r);
9 R r2{1.f, 3.f}; // OK
10 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 394 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Module structure C++ 20
1 module; // global module fragment (opt.)
2 #include <cassert> // only preprocessor
3 // ... // statements allowed
4
5 export module math; // module preamble starts with
6 // exported module name.
7 import <string>; // only imports allowed
8 // ... //
9
10 export struct S { ... }; // module purview started
11 export S f(); // at first non-import
12 std::string h() { ... }
13
14 module :private // private module fragment (opt.)
15 S f() { ... } // changes here trigger
16 // no recompilation of BMI
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 395 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Module structure C++ 20
Pitfall
1 export module math;
2 #include <header.h>
3 import <string>;
4 // ...
Headers included after export module add to the module’s
preamble and purview
This is usually not what you want
Put includes into global module fragment
1 module;
2 #include <vector>
3 export module math;
4 import <string>;
5 // ...
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 396 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Module structure C++ 20
Like with header files, we can split interface and implementation:
Interface
1 export module math;
2
3 export struct S { ... };
4 export S f();
Implementation
1 module;
2 #include <cassert>
3 module math;
4 import <string>;
5
6 S f() { ... }
7 std::string b() { ... }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 397 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Submodules and re-exporting C++ 20
Modules can (re-)export other modules using export import:
Module one Module two
1 export module one; 1 export module two;
2 2 import <string>;
3 export struct S { ... }; 3
4 export std::string b()
5 { ... }
Module three Module four
1 export module three; 1 export module four;
2 import one; 2 import three;
3 export import two; 3 // b and f visible
4 4 // S and std::string only
5 export S f() { ... } 5 // reachable
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 398 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Module partitions C++ 20
We can split a module’s interface into multiple files:
Primary module interface Module interface partition
1 export module math; 1
2 export import :structs; 2 export module math:structs;
3 3
4 export S f(); 4 export struct S { ... };
Implementation
1 module math;
2 import <string>;
3
4 S f() { ... }
5 std::string b() { ... }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 399 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Module implementation units C++ 20
We can split a module’s implementation into multiple files:
Interface
1 export module math;
2 import :foo; // no export
3 import :bar; // no export
4 import <string>;
5
6 export struct S { ... };
7 export S f();
8 std::string b();
Implementation unit foo Implementation unit bar
1 module math:foo; 1 module math:bar;
2 2
3 S f() { ... } 3 std::string b() { ... }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 400 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Standard library modules C++ 23
Standard library modules
Use import std; for the entire C++ standard library.
Basically everything in namespace std.
E.g. memcpy(a, b, n), sqrt(val), uint32_t i will not
compile. You need to prefix std::.
Use import std.compat; for the entire C and C++
standard library
No macros are exported. For these, you still need to include
the corresponding headers.
1 import std; // everything C++
2 #include <cassert> // for assert()
3 #include <climits> // for e.g. CHAR_BIT
Definition of further, smaller modules of the standard library is
in progress (e.g. fundamentals, containers, networking, etc.)
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 401 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Header units C++ 20
Purpose
For easier transition from header-based projects to modules
Allows to import any header file as if it was a module
Can be mixed with regular header inclusion
1 #include <set>
2 import <vector>;
3
4 #include "header.hpp"
5 import "otherheader.hpp";
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 402 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Header units C++ 20
Effect
All declarations in the imported header will be exported
An imported header is not affected by the preprocessor state.
Thus, you cannot “configure” the header by defining a macro
before importing. This allows the header to be precompiled.
An imported header may still provide preprocessor macros
1 #define MY_MACRO 1
2 #include "header.hpp" // may be affected by MY_MACRO
3 import "otherheader.hpp"; // ignores MY_MACRO
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 403 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Automatic include to import translation C++ 20
Importable headers
A header file which can successfully be either included or
imported is called “importable”
I.e. the header does not require setup of preprocessor state
before inclusion
All C++ standard library headers are importable
C wrapper headers (<c*>) are not
Include translation
Allows the compiler to automatically turn includes into
imports
Controlled via compiler flags and the build system
Basically a standard replacement for precompiled headers
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 404 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Build system
h.hpp Traditional workflow
#include <vector> <vector>
...
#
a.cpp
h.hpp # #
#include "h.hpp"
... # #
a.cpp b.cpp c.cpp t
b.cpp
#include <vector> Compiler Compiler Compiler
#include "h.hpp"
a.o b.o c.o
...
c.cpp Linker
#include <vector>
... binary
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 405 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Build system C++ 20
h.cpp New workflow
export module foo; scan dependencies
import <vector>;
<vector>
...
Compiler
a.cpp vector.bmi #
import foo; imp
... h.cpp c.cpp
Compiler imp Compiler
t
b.cpp h.o foo.bmi c.o
import <vector>; imp imp
import foo; a.cpp b.cpp
... Compiler Compiler
c.cpp a.o b.o
#include <vector> Linker
... binary
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 406 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Build system
New challenges
Resolving a module name to the file name building it
Translation units no longer independent
Extra tool needs to infer dependency graph before building
Called a “dependency scanner”
Needs to be communicated to the build system
Using a new standard dependency file format
Parallel and distributed builds need synchronization
Compilation of module translation units produces a binary
module interface (BMI) and an object file
Need to manage BMIs between multiple compiler invocations
Tools beside the compiler need to build/read BMIs
E.g. static analysis, language servers for auto completion, etc.
The C++ standard specifies very little on how this works
We may experience large implementation divergence
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 407 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Build system C++ 20
Status
Dependency scanner since clang 16: clang-scan-deps
Experimental module support in cmake since 3.26, uses
clang-scan-deps, many fixes in later versions
MSBuild (Windows) fully handles dependency scanning
g++ a.cpp b.cpp ... “just works”, must be one line though
Experimental extensions to GNU make exist to grow
dependency graph on the fly while modules are discovered
Header units unsupported in all build systems (May 2023)
C++23: import std; supported in MSVC, partially in clang
GCC/clang/MSVC also plan support in C++20
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 408 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Building modules (g++) C++ 20
Case study: g++
BMI is called CMI (compiled module interfaces)
By default, g++ caches CMIs in subdirectory ./gcm.cache
Uses a module mapper to resolve imports, which specifies a
protocol and uses a central server for module maintenance
Each module needs to be built before it can be imported
g++ -std=c++20 -fmodules-ts -c ratio.cpp -o ratio.o
Generates ratio.o and ./gcm.cache/ratio.gcm (CMI)
Each header unit needs to be built before it can be imported
g++ -std=c++20 -fmodules-ts -x c++-system-header vector
Generates e.g.
./gcm.cache/usr/include/c++/11/vector.gcm (CMI)
g++ -std=c++20 -fmodules-ts -x c++-header ratio.h
Generates e.g. ./gcm.cache/,/ratio.h.gcm (CMI)
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 409 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Modules C++ 20
Guidance for today
Start writing importable headers (no macro dependencies)
Dual use: #include before C++ 20 and import with C++ 20
Watch progress on module support in your build system
Guidance for tomorrow
Start writing modules when your users have C++ 20
Maybe import standard headers when C++ 20 is available
Start using import std; when available
Future of header units unclear (implementation difficulties)
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 410 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Modules C++ 20
Resources
A (Short) Tour of C++ Modules - Daniela Engert - CppCon 2021
(very technical)
Understanding C++ Modules: Part1, Part2 and Part3.
So, You Want to Use C++ Modules … Cross-Platform? - Daniela
Engert - C++ on Sea 2023
import CMake: 2023 State of C++20 modules in CMake - Bill
Hoffman - CppNow 2023
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 411 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Modules C++ 20
Exercise: Modules
go to exercises/modules
convert the Complex.hpp header into a module named math
Exercise: Header units
go to exercises/header_units
convert all #includes into header unit imports
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 412 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Coroutines
5 Expert C++
The <=> operator
Variadic templates
Perfect forwarding
SFINAE
Concepts
Modules
Coroutines
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 413 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Why do we need coroutines? C++ 20
The generator use case (one of several)
In python one can write
1 for i in range(0, 10):
2 print(i)
What about it in C++ ?
3 someType range(int first, int last) { ... }
4 for (auto i : range(0, 10)) {
5 std::cout << i << "\n";
6 }
How can we implement range?
Requirements
someType needs to be some iterable type
range should execute lazily, only creating values on demand
meaning range should be suspended and resumed
That’s what coroutines are for!
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 414 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
++
What C 20 allows C++ 20
Interesting part of the implementation (see cppreference)
1 template<std::integral T>
2 Generator<T> range(T first, const T last) {
3 while (first < last) {
4 co_yield first++;
5 }
6 }
7 for (const char i : range(65, 91)) {
8 std::cout << i << ' ';
9 }
10 std::cout << '\n';
The bad news
class Generator is not provided by the STL
and is ∼ 80 lines of boiler plate code...
may be sorted out in C++ 23
in the meantime, we’ll have to dive into some details!
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 415 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
A few concepts first C++ 20
Definition of a coroutine
a function which can be suspended and resumed
potentially by another caller (even on a different thread)
practically a function using one of:
co_await suspends execution
co_yield suspends execution and returns a value
co_return completes execution
Implications
on suspension, the state of the function needs to be preserved
the suspended function becomes pure data on the heap
access to this data is given via the returned value
so the returned type must follow some convention
it needs to contain a struct promise_type
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 416 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Minimal code C++ 20
Definition of an empty coroutine
3 #include <coroutine>
4 struct Task {
5 struct promise_type {
6 Task get_return_object() { return {}; }
7 std::suspend_never initial_suspend() { return {}; }
8 std::suspend_never final_suspend() noexcept { return {}; }
9 void return_void() {}
10 void unhandled_exception() { throw; }
11 };
12 };
13 Task myCoroutine() { co_return; }
14 int main() { Task x = myCoroutine(); }
promise_type interface
get_return_object builds a Task from the given promise
initial/final_suspend called before/after coroutine starts/ends
unhandled_exception called in case of exception in coroutine
return_void/value returns final value of the coroutine
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 417 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Minimal sequence of events (nothing suspended) C++ 20
Compiler generated set of calls when calling myCoroutine
call to coroutine user code compiler promise
allocate coroutine state on the heap construct promise inside coroutine state
ro = promise.get_return_object() ro returned to caller
promise.initial_suspend() co_await on result
coroutine body co_return
promise.return_void() promise.final_suspend()
co_await on result destroy promise
caller destroy coroutine
Credits : original idea for this graph comes from this web site
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 418 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Suspending a coroutine C++ 20
Main way to suspend a coroutine: co_wait
it’s an expression taking an “awaitable”/ “awaiter”
we’ll ignore the distinction for now
2 trivial awaiters are provided by the STL:
std::suspend_always and std::suspend_never
obviously only the first one will trigger a suspension
note the other one is used in the minimal code
more details on awaiters later
Code
1 Task myCoroutine() {
2 std::cout << "Step 1 of coroutine\n";
3 co_await std::suspend_always{};
4 std::cout << "Step 2 of coroutine\n";
5 co_await std::suspend_always{};
6 std::cout << "final step\n";
7 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 419 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Resuming a coroutine C++ 20
Principles
one needs to call resume() on the coroutine_handle
BUT user code has no such handle
only the coroutine return object (here a Task instance)
so one has to amend the Task class
and the promise_type as it’s building the Task instance
Code
1 struct Task {
2 struct promise_type {
3 Task get_return_object() {
4 // build Task with the coroutine handle
5 return {std::coroutine_handle<promise_type>::from_promise(*this)};
6 }
7 ... // rest is unchanged
8 };
9 std::coroutine_handle<promise_type> h_;
10 void resume() { h_.resume(); }
11 };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 420 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Resuming a coroutine C++ 20
User code - godbolt
1 Task myCoroutine() {
2 std::cout << "Step 1 of coroutine\n";
3 co_await std::suspend_always{};
4 std::cout << "Step 2 of coroutine\n";
5 co_await std::suspend_always{};
6 std::cout << "final step\n";
7 }
8 int main() {
9 auto c = myCoroutine(); // Step 1 runs
10 std::cout << "In main, between Step 1 and 2\n";
11 c.resume(); // Step 2 runs
12 std::cout << "In main, between Step 2 and final step\n";
13 c.resume(); // final Step runs
14 // c.resume(); // would segfault!
15 }
Step 1 of coroutine
In main, between Step 1 and 2
Step 2 of coroutine
In main, between Step 2 and final step
final step
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 421 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
A few more details C++ 20
About suspension of coroutines
initial/final_suspend methods allow to suspend a
coroutine at the very start/end (after co_return)
a suspended coroutine is not deallocated
i.e. its state will stay on the heap
so you can leak coroutines!
one can directly call coroutine_handle::destroy if the
execution of a suspended coroutine should be aborted
which requires another piece of code in Task, e.g.
~Task() { if (h_) h_.destroy(); }
the Task class should be move only
We need standard Task classes in the STL!
std::generator may come in C++ 23
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 422 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
co_yield - returning a value upon suspension C++ 20
What co_yield really is
an expression like co_await
a shortcut for co_await promise.yield_value(expr)
and we have to provide the yield_value method of
promise_type and the Task accessor
Typical code
1 template<typename T> struct Task {
2 struct promise_type {
3 T value_;
4 std::suspend_always yield_value(T&& from) {
5 value_ = std::forward<T>(from); // caching the result
6 return {};
7 }
8 ... // rest is unchanged
9 };
10 T getValue() { return h_.promise().value_; } // accessor for user code
11 };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 423 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
co_yield - generator behavior C++ 20
Generator behavior - more boiler plate code
1 template<typename T>
2 struct Task {
3 struct iterator {
4 std::coroutine_handle<promise_type> handle;
5 auto &operator++() {
6 handle.resume();
7 if (handle.done()) { handle = nullptr; } // == end iterator
8 return *this;
9 }
10 auto operator++(int) { ++*this; }
11 T const& operator*() const { return handle.promise().value_; }
12 ...
13 };
14 iterator begin() { resume(); return {h_}; }
15 iterator end() { return {nullptr}; }
16 ... // plus error handling is missing
17 };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 424 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
co_yield - final usage C++ 20
Finally, we can use the generator nicely - godbolt
1 Task range(int first, int last) {
2 while (first != last) {
3 co_yield first++;
4 }
5 }
6 for (int i : range(0, 10)) {
7 std::cout << i << "";
8 } // 1 2 3 4 5 6 7 8 9
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 425 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
co_yield - final usage C++ 20
Finally, we can use the generator nicely - godbolt
1 Task range(int first, int last) {
2 while (first != last) {
3 co_yield first++;
4 }
5 }
6 for (int i : range(0, 10)) {
7 std::cout << i << "";
8 } // 1 2 3 4 5 6 7 8 9
Wait a minute: 0 is missing in the output!
resume called in operator++ before 0 is printed
we should pause in initial_suspend
10 struct Task {
11 struct promise_type {
12 ...
13 std::suspend_always initial_suspend() { return {}; }
14 ...
15 }
16 };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 425 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Laziness allows for infinite ranges C++ 20
Generators do not need to be finite - godbolt
1 Task range(int first) {
2 while (true) {
3 co_yield first++;
4 }
5 }
6 for (int i : range(0) | std::views::take(10)) {
7 std::cout << i << "\n";
8 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 426 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Real life example C++ 20
A Fibonacci generator, from cppreference - godbolt
1 Task<long long int> fibonacci(unsigned n) {
2 if (n==0) co_return;
3 co_yield 0;
4 if (n==1) co_return;
5 co_yield 1;
6 if (n==2) co_return;
7 uint64_t a=0;
8 uint64_t b=1;
9 for (unsigned i = 2; i < n; i++) {
10 uint64_t s=a+b;
11 co_yield s;
12 a=b;
13 b=s;
14 }
15 }
16
17 int main() {
18 for (int i : fibonacci(10)) {
19 std::cout << i << "\n";
20 }
21 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 427 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Coming back to awaitables/awaiters C++ 20
awaitables vs awaiters
awaitable is the type required by co_await/co_yield
or the expression given has to be convertible to awaitable
alternatively the promise_type can have an
await_transform method returning an awaitable
an awaiter is retrieved from the awaitable by the compiler
either by calling operator co_wait on it
or via direct conversion if no such operator exists
an awaiter has 3 main methods
await_ready, await_suspend and await_resume
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 428 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
How awaiters work C++ 20
Compiler generated set of calls
co_await awaitable user code compiler awaiter
true false
awaiter.await_ready() coroutine suspended
false
awaiter.await_suspend(handle)
void
coroutine
handle true
handle.resume() coroutine caller
coroutine behind handle suspended or finished caller calls resume
coroutine resumed awaiter.await_resume()
continue coroutine body
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 429 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
awaiter example C++ 20
Switch to new thread, from cppreference - godbolt
1 auto switch_to_new_thread(std::jthread& out) {
2 struct awaiter {
3 std::jthread* th;
4 bool await_ready() { return false; }
5 void await_suspend(std::coroutine_handle<> h) {
6 *th = std::jthread([h] { h.resume(); });
7 std::cout << "New thread ID: " << th->get_id() << '\n';
8 }
9 void await_resume() {}
10 };
11 return awaiter{&out};
12 }
13 Task<int> resuming_on_new_thread(std::jthread& out) {
14 std::cout << "Started on " << std::this_thread::get_id() << '\n';
15 co_await switch_to_new_thread(out);
16 std::cout << "Resumed on " << std::this_thread::get_id() << std::endl;
17 }
18 int main() {
19 std::jthread out;
20 resuming_on_new_thread(out);
21 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 430 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
awaiter example C++ 20
Switch to new thread, from cppreference - godbolt
1 auto switch_to_new_thread(std::jthread& out) {
2 struct awaiter {
3 std::jthread* th;
4 bool await_ready() { return false; }
5 void await_suspend(std::coroutine_handle<> h) {
6 *th = std::jthread([h] { h.resume(); });
7 std::cout << "New thread ID: " << th->get_id() << '\n';
8 }
9 void await_resume() {}
10 };
11 return awaiter{&out};
12 }
13 Task<int> resuming_on_new_thread(std::jthread& out) {
14 std::cout << "Started on " << std::this_thread::get_id() << '\n';
15 co_await switch_to_new_thread(out);
16 std::cout << "Resumed on " << std::this_thread::get_id() << std::endl;
17 }
18 int main() { Output
19 std::jthread out; Started on thread: 140144191063872
20 resuming_on_new_thread(out); New thread ID: 140144191059712
21 } Resumed on thread: 140144191059712
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 430 / 548
Intro base OO More exp Tool conc py spaceship tmpl forward sfinae concepts modules Coroutines
Summary on coroutines C++ 20
Coroutines are usable in C++ 20
allow to have nice generators
also very useful for async/IO code
another big use case which we did not touch
But library support is poor for now
standard Task/Generator classes are not provided
leading to lots of boiler plate code for the end user
std::generator is part of C++ 23’s draft
in the meantime, libraries exist, e.g. CppCoro
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 431 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Useful tools
Version control
Code formatting
1 History and goals
The Compiling Chain
Web tools
2 Language basics Debugging
Sanitizers
3 Object orientation (OO) The Valgrind family
Static code analysis
4 Core modern C++ Profiling
Doxygen
5 Expert C++
7 Concurrency
6 Useful tools
C++ editor 8 C++ and python
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 432 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
++
C editor
6 Useful tools
C++ editor
Version control
Code formatting
The Compiling Chain
Web tools
Debugging
Sanitizers
The Valgrind family
Static code analysis
Profiling
Doxygen
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 433 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
++
C editors and IDEs
Can dramatically improve your efficiency by
Coloring the code for you to “see” the structure
Helping with indenting and formatting properly
Allowing you to easily navigate in the source tree
Helping with compilation/debugging, profiling, static analysis
Showing you errors and suggestions while typing
Visual Studio Heavy, fully fledged IDE for Windows
Visual Studio Code Editor, open source, portable, many plugins
Eclipse IDE, open source, portable
Emacs Vim Editors for experts, extremely powerful.
They are to IDEs what latex is to PowerPoint
CLion, Code::Blocks, Atom, NetBeans, Sublime Text, ...
Choosing one is mostly a matter of taste
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 434 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Version control
6 Useful tools
C++ editor
Version control
Code formatting
The Compiling Chain
Web tools
Debugging
Sanitizers
The Valgrind family
Static code analysis
Profiling
Doxygen
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 435 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Version control
Please use one!
Even locally
Even on a single file
Even if you are the only committer
It will soon save your day
A few tools
git THE mainstream choice. Fast, light, easy to use
mercurial The alternative to git
Bazaar Another alternative
Subversion Historical, not distributed - don’t use
CVS Archeological, not distributed - don’t use
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 436 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Git crash course
$ git init myProject
Initialized empty Git repository in myProject/.git/
$ vim file.cpp; vim file2.cpp
$ git add file.cpp file2.cpp
$ git commit -m "Committing first 2 files"
[master (root-commit) c481716] Committing first 2 files
...
$ git log --oneline
d725f2e Better STL test
f24a6ce Reworked examples + added stl one
bb54d15 implemented template part
...
$ git diff f24a6ce bb54d15
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 437 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Code formatting
6 Useful tools
C++ editor
Version control
Code formatting
The Compiling Chain
Web tools
Debugging
Sanitizers
The Valgrind family
Static code analysis
Profiling
Doxygen
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 438 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
clang-format
.clang-format
File describing your formatting preferences
Should be checked-in at the repository root (project wide)
clang-format -style=LLVM -dump-config >
.clang-format
Adapt style options with help from: https://clang.llvm.
org/docs/ClangFormatStyleOptions.html
Run clang-format
clang-format --style=LLVM -i <file.cpp>
clang-format -i <file.cpp> (looks for .clang-format file)
git clang-format (formats local changes)
git clang-format <ref> (formats changes since git <ref>)
Some editors/IDEs find a .clang-format file and adapt
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 439 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
clang-format
Exercise: clang-format
Go to any example
Format code with:
clang-format --style=GNU -i <file.cpp>
Inspect changes, try git diff .
Revert changes using git checkout -- <file.cpp> or
git checkout .
Go to exercises directory and create a .clang-format file
clang-format -style=LLVM -dump-config >
.clang-format
Run clang-format -i <any_exercise>/*.cpp
Revert changes using git checkout <any_exercise>
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 440 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
The Compiling Chain
6 Useful tools
C++ editor
Version control
Code formatting
The Compiling Chain
Web tools
Debugging
Sanitizers
The Valgrind family
Static code analysis
Profiling
Doxygen
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 441 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
The compiling chain C++ 17
Source code Binary
.cpp, .hpp .so, exe
Preprocessor Compiler Linker
.cpp .o
cpp, gcc -E g++ -c, gcc -c ld, gcc, g++
The steps
cpp the preprocessor
handles the # directives (macros, includes)
creates “complete” source code (ie. translation unit)
g++ the compiler
creates machine code from C++ code
ld the linker
links several binary files into libraries and executables
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 442 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Compilers
Available tools
gcc the most common and most used
free and open source
clang drop-in replacement of gcc
slightly better error reporting
free and open source, based on LLVM
icc icx Intel’s compilers, proprietary but now free
optimized for Intel hardware
icc being replaced by icx, based on LLVM
Visual C++ / MSVC Microsoft’s C++ compiler on Windows
My preferred choice today
gcc as the de facto standard in HEP
clang in parallel to catch more bugs
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 443 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Useful compiler options (gcc/clang)
Get more warnings
-Wall -Wextra get all warnings
-Werror force yourself to look at warnings
Optimization
-g add debug symbols (also: -g3 or -ggdb)
-Ox 0 = no opt., 1-2 = opt., 3 = highly opt. (maybe
larger binary), g = opt. for debugging
Compilation environment
-I <path> where to find header files
-L <path> where to find libraries
-l <name> link with libname.so
-E / -c stop after preprocessing / compilation
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 444 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
How to inspect object files?
Listing symbols : nm
gives list of symbols in a file
these are functions and constants
with their internal (mangled/encoded) naming
also gives type and location in the file for each symbol
’U’ type means undefined
so a function used but not defined
linking will be needed to resolve it
use -C option to demangle on the fly
> nm -C Struct.o
U strlen
U _Unwind_Resume
000000000000008a T SlowToCopy::SlowToCopy(SlowToCopy const&)
0000000000000000 T SlowToCopy::SlowToCopy()
0000000000000064 T SlowToCopy::SlowToCopy(std::__cxx11::basic_st
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 445 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
How to inspect libraries/executables?
Listing dependencies : ldd
gives (recursive) list of libraries required by the given
argument
and if/where they are found in the current context
use -r to list missing symbols (mangled)
> ldd -r trypoly
linux-vdso.so.1 (0x00007f3938085000)
libpoly.so => not found
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00
[...]
undefined symbol: _ZNK7Hexagon16computePerimeterEv (./try
undefined symbol: _ZNK7Polygon16computePerimeterEv (./try
undefined symbol: _ZN7HexagonC1Ef (./trypoly.sol)
undefined symbol: _ZN8PentagonC1Ef (./trypoly.sol)
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 446 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Makefiles
Why to use them
an organized way of describing building steps
avoids a lot of typing
Several implementations
raw Makefiles: suitable for small projects
cmake: portable, the current best choice
automake: GNU project solution
test : test.cpp libpoly.so
$(CXX) -Wall -Wextra -o $@ $^
libpoly.so: Polygons.cpp
$(CXX) -Wall -Wextra -shared -fPIC -o $@ $^
clean:
rm -f *o *so *~ test test.sol
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 447 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
CMake
a cross-platform meta build system
generates platform-specific build systems
see also this basic and detailed talks
Example CMakeLists.txt
1 cmake_minimum_required(VERSION 3.18)
2 project(hello CXX)
3
4 find_package(ZLIB REQUIRED) # for external libs
5
6 add_executable(hello main.cpp util.h util.cpp)
7 target_compile_features(hello PUBLIC cxx_std_17)
8 target_link_libraries(hello PUBLIC ZLIB::ZLIB)
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 448 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
CMake - Building
Building a CMake-based project
Start in the directory with the top-level CMakeLists.txt:
1 mkdir build # will contain all build-related files
2 cd build
3 cmake .. # configures and generates a build system
4 cmake -DCMAKE_BUILD_TYPE=Release .. # pass arguments
5 ccmake . # change configuration using terminal GUI
6 cmake-gui . # change configuration using Qt GUI
7 cmake --build . -j8 # build project with 8 jobs
8 cmake --build . --target hello # build only hello
9 sudo cmake --install . # install project into system
10 cd ..
11 rm -r build # clean everything
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 449 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Compiler chain
Exercise: Compiler chain
go to exercises/polymorphism
preprocess Polygons.cpp (g++ -E -o output)
compile Polygons.o and trypoly.o (g++ -c -o output)
use nm to check symbols in .o files
look at the Makefile
try make clean; make
see linking stage of the final program using g++ -v
just add a -v in the Makefile command for trypoly target
run make clean; make
look at the collect 2 line, from the end up to “-o trypoly”
see library dependencies of ‘trypoly‘ using ‘ldd‘
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 450 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Web tools
6 Useful tools
C++ editor
Version control
Code formatting
The Compiling Chain
Web tools
Debugging
Sanitizers
The Valgrind family
Static code analysis
Profiling
Doxygen
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 451 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Godbolt / Compiler Explorer
Concept
An online generic compiler with immediate feedback. Allows:
compiling online any code against any version of any compiler
inspecting the assembly generated
use of external libraries (over 50 available !)
running the code produced
using tools, e.g. ldd, include-what-you-use, ...
sharing small pieces of code via permanent short links
Typical usage
check small pieces of code on different compilers
check some new C++ functionality and its support
optimize small pieces of code
NOT relevant for large codes
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 452 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Godbolt by example
Check effect of optimization flags
https://godbolt.org/z/Pb8WsWjEx
Check generated code with -O0, -O1, -O2, -O3
See how it gets shorter and simpler
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 453 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
cppinsights
Concept
Reveals the actual code behind C++ syntactic sugar
lambdas
range-based loops
templates
initializations
auto
...
Typical usage
understand how things work behind the C++ syntax
debug some non working pieces of code
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 454 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
cppinsights by example
Check how range-based loop work
https://cppinsights.io/s/b886aa76
See how they map to regular iterators
And how operators are converted to function calls
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 455 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Debugging
6 Useful tools
C++ editor
Version control
Code formatting
The Compiling Chain
Web tools
Debugging
Sanitizers
The Valgrind family
Static code analysis
Profiling
Doxygen
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 456 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Debugging
The problem
everything compiles fine (no warning)
but crashes at run time
no error message, no clue
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 457 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Debugging
The problem
everything compiles fine (no warning)
but crashes at run time
no error message, no clue
The solution: debuggers
dedicated program able to stop execution at any time
and show you where you are and what you have
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 457 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Debugging
The problem
everything compiles fine (no warning)
but crashes at run time
no error message, no clue
The solution: debuggers
dedicated program able to stop execution at any time
and show you where you are and what you have
Existing tools
gdb THE main player
lldb the debugger coming with clang/LLVM
gdb-oneapi the Intel OneAPI debugger
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 457 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
gdb crash course
start gdb
gdb <program>
gdb <program><core file>
gdb --args <program><program arguments>
inspect state
bt prints a backtrace
print <var> prints current content of the variable
list show code around current point
up/down go up or down in call stack
breakpoints
break <function> puts a breakpoint on function entry
break <file>:<line> puts a breakpoint on that line
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 458 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
gdb
Exercise: gdb
go to exercises/debug
compile, run, see the crash
run it in gdb (or lldb on newer MacOS)
inspect backtrace, variables
find problem and fix bug
try stepping, breakpoints
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 459 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Debugging UIs
User interfaces for debuggers
offer convenience on top of command line
windows for variables, breakpoints, call stack, active threads,
watch variables in-code, disassembly, run to cursor ...
VSCode Built-in support for gdb
CodeLLDB VS Code plugin for LLDB
GDB dashboard Poplar terminal UI for gdb
GEF Modern terminal UI for gdb
some editors and most IDEs have good debugger integration
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 460 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Sanitizers
6 Useful tools
C++ editor
Version control
Code formatting
The Compiling Chain
Web tools
Debugging
Sanitizers
The Valgrind family
Static code analysis
Profiling
Doxygen
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 461 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Address Sanitizer (ASan)
ASan introduction
Compiler instrumentation
Program stops on invalid memory access, e.g.
Invalid read/write on heap and stack
Double free/delete, use after free
Buffer overflow on stack (few tools can do this)
Only linux: memory leaks
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 462 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Address Sanitizer (ASan)
ASan introduction
Compiler instrumentation
Program stops on invalid memory access, e.g.
Invalid read/write on heap and stack
Double free/delete, use after free
Buffer overflow on stack (few tools can do this)
Only linux: memory leaks
Usage (gcc/clang syntax)
Compile with
-fsanitize=address -fno-omit-frame-pointer -g
With clang, add optionally:
-fsanitize-address-use-after-return=always
-fsanitize-address-use-after-scope
Link with -fsanitize=address
Run the program
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 462 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Address Sanitizer (ASan)
How it works
Compiler adds run-time checks (∼2x slow down)
IsPoisoned(address) looks up state of address in asan’s
“shadow memory”
Shadow memory: memory where 1 shadow byte tracks state
of 8 application bytes (state = accessible, poisoned, …)
Functions that deal with memory (new() / delete() /
strings / ...) update entries in shadow memory when called
asan instrumentation (mock code)
1 int i = *address;
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 463 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Address Sanitizer (ASan)
How it works
Compiler adds run-time checks (∼2x slow down)
IsPoisoned(address) looks up state of address in asan’s
“shadow memory”
Shadow memory: memory where 1 shadow byte tracks state
of 8 application bytes (state = accessible, poisoned, …)
Functions that deal with memory (new() / delete() /
strings / ...) update entries in shadow memory when called
asan instrumentation (mock code)
1 if (IsPoisoned(address)) {
2 ReportError(address, kAccessSize, kIsWrite);
3 }
4 int i = *address;
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 463 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
ASan red zones
If adjacent data blocks are owned by the process, the
operating system will allow an access
Illegal access (not detected without ASan)
1 void foo() {
Memory layout
2 char a[8];
3 char b[8]; 0x300C
4 a[8] = '1'; 0x3008
5 } 0x3004
a[0-7] b[0-7] 0x3000
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 464 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
ASan red zones
If adjacent data blocks are owned by the process, the
operating system will allow an access
ASan surrounds blocks of memory by poisoned red zones
Program stops when accessing a red zone
Illegal access (not detected without ASan)
void foo() {
Memory layout
+ char redzone1[32];
char a[8]; 0x300C
+ char redzone2[24]; b[0-7] redzone3 0x3008
char b[8]; a[0-7] redzone2 0x3004
+ char redzone3[24]; redzone1 0x3000
+ // <poison redzones>
a[8] = '1';
+ // <unpoison redzones>
}
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 464 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
==34015==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffee93ed968 a
WRITE of size 1 at 0x7ffee93ed968 thread T0
#0 0x106812df3 in foo() asan.cpp:4
#1 0x106812ed8 in main asan.cpp:9
#2 0x7fff6d3923d4 in start (libdyld.dylib:x86_64+0x163d4)
Address 0x7ffee93ed968 is located in stack of thread T0 at offset 40 in frame
#0 0x106812cdf in foo() asan.cpp:1
This frame has 2 object(s):
[32, 40) 'a' (line 2) <== Memory access at offset 40 overflows this variable
[64, 72) 'b' (line 3)
Shadow bytes around the buggy address:
=>0x1fffdd27db20: 00 00 00 00 00 00 00 00 f1 f1 f1 f1 00[f2]f2 f2
0x1fffdd27db30: 00 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
0x1fffdd27db40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1fffdd27db50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 465 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Finding memory leaks with ASan
On linux, ASan can display memory leaks
Start executable with
ASAN_OPTIONS=detect_leaks=1 ./myProgram
==113262==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 32 byte(s) in 1 object(s) allocated from:
#0 0x7f2671201647 in operator new(unsigned long) /build/dkonst/WORK/build/contrib
#1 0x4033c7 in memoryLeak[abi:cxx11]() /afs/cern.ch/user/s/shageboe/asan.cpp:33
#2 0x403633 in main /afs/cern.ch/user/s/shageboe/asan.cpp:40
#3 0x7f2670a15492 in __libc_start_main (/lib64/libc.so.6+0x23492)
Indirect leak of 22 byte(s) in 1 object(s) allocated from:
#0 0x7f2671201647 in operator new(unsigned long) /build/dkonst/WORK/build/contrib
#1 0x403846 in void std::__cxx11::basic_string<char, std::char_traits<char>, std:
#2 0x4033f4 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allo
#3 0x4033f4 in memoryLeak[abi:cxx11]() /afs/cern.ch/user/s/shageboe/asan.cpp:33
#4 0x403633 in main /afs/cern.ch/user/s/shageboe/asan.cpp:40
#5 0x7f2670a15492 in __libc_start_main (/lib64/libc.so.6+0x23492)
SUMMARY: AddressSanitizer: 54 byte(s) leaked in 2 allocation(s).
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 466 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Address sanitizer (ASan)
Wrap up
If a program crashes, run it with asan
Should be part of every C++ continuous integration system
It will also find bugs that by luck didn’t crash the program
It doesn’t generate false positives
More info
https://github.com/google/sanitizers/wiki/
AddressSanitizer
Compile with asan, and start executable using
ASAN_OPTIONS=help=1 <executable>
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 467 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Address sanitizer (ASan)
Exercise: address sanitizer
Go to exercises/asan
Compile and run the program ./asan
There are two bugs and one memory leak. Use asan to trace
them down.
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 468 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Thread sanitizer (TSan)
TSan
Thread sanitizer detects many data races in MT programs
Recompile your program with e.g.
clang++ -fsanitize=thread -g -O1 datarace.cpp
% ./a.out
WARNING: ThreadSanitizer: data race (pid=19219)
Write of size 4 at 0x7fcf47b21bc0 by thread T1:
#0 Thread1 datarace.c:4 (exe+0x00000000a360)
Previous write of size 4 at 0x7fcf47b21bc0 by main thread:
#0 main datarace.c:10 (exe+0x00000000a3b4)
Thread T1 (running) created at:
#0 pthread_create tsan_interceptors.cc:705 (exe+0x00000000c790)
#1 main datarace.c:9 (exe+0x00000000a3a4)
https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 469 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Undefined Behaviour Sanitizer (UBSan)
UBSan
Tracks uninitialised memory, broken arithmetic, wrong array
indexing and other undefined behaviour
Recompile your program with e.g.
clang++ -fsanitize=undefined -g -O1 ub.cpp
% ./a.out
up.cpp:3:5: runtime error: signed integer overflow:
2147483647 + 1 cannot be represented in type 'int'
https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 470 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
The Valgrind family
6 Useful tools
C++ editor
Version control
Code formatting
The Compiling Chain
Web tools
Debugging
Sanitizers
The Valgrind family
Static code analysis
Profiling
Doxygen
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 471 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
The valgrind family
Valgrind fundamentals
valgrind is a framework for different tools
a processor simulator allowing checks in between instructions
slow (10-50 times slower than normal execution)
easy to use : “valgrind <your executable>”
no recompilation
better with -g -O0, but not strictly needed
it is free and open source
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 472 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
The valgrind family
Valgrind fundamentals
valgrind is a framework for different tools
a processor simulator allowing checks in between instructions
slow (10-50 times slower than normal execution)
easy to use : “valgrind <your executable>”
no recompilation
better with -g -O0, but not strictly needed
it is free and open source
Main tools
memcheck a memory checker (default tool) and leak detector
callgrind a call graph builder
helgrind a race condition detector
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 472 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
memcheck
keeps track of all memory allocations and deallocations
is able to detect accesses to unallocated memory
and even tell you when it was deallocated if it was
or what is the closest array in case of overflow
is able to list still allocated memory when program exits
(memory leaks detection)
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 473 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
valgrind
Exercise: valgrind
go to exercises/valgrind
compile, run, it should work
run with valgrind, see the problem
fix the problem
go back to the exercises/debug exercise
check it with valgrind
analyze the issue, see that the variance was biaised
fix the issue
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 474 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
memcheck
Exercise: memcheck
go to exercises/memcheck
compile, run, it should work
run with valgrind, see LEAK summary
run with --leak-check=full to get details
analyze and correct it
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 475 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
callgrind and kcachegrind
callgrind
keeps track of all function calls
and time spent in each function
build statistics on calls, CPU usages and more
outputs flat statistics file, quite unreadable
kcachegrind
a gui exploiting statistics built by callgrind
able to browse graphically the program calls
able to “graph” CPU usage on the program structure
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 476 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
callgrind
Exercise: callgrind
go to exercises/callgrind
compile, run, it will be slow
change nb iterations to 20
run with valgrind --tool=callgrind
look at output with kcachegrind
change fibo call to fibo2
observe the change in kcachegrind
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 477 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
helgrind
keeps track of all pthreads activity
in particular keeps track of all mutexes
builds a graph of dependencies of the different actions
works on the resulting graph to detect:
possible dead locks
possible data races
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 478 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
helgrind
keeps track of all pthreads activity
in particular keeps track of all mutexes
builds a graph of dependencies of the different actions
works on the resulting graph to detect:
possible dead locks
possible data races
Note the “possible”. It finds future problems!
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 478 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
helgrind
Exercise: helgrind
go to exercises/helgrind
compile, run
check it with valgrind. You may see strange behavior
or it will be perfectly fine
check it with valgrind --tool=helgrind
understand issue and fix
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 479 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Static code analysis
6 Useful tools
C++ editor
Version control
Code formatting
The Compiling Chain
Web tools
Debugging
Sanitizers
The Valgrind family
Static code analysis
Profiling
Doxygen
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 480 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Static analysis
The problem
all the tools discussed so far work on binaries
they analyze the code being run
so there is a coverage problem (e.g. for error cases)
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 481 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Static analysis
The problem
all the tools discussed so far work on binaries
they analyze the code being run
so there is a coverage problem (e.g. for error cases)
A (partial) solution : analyzing the source code
build a graph of dependencies of the calls
use graph tools to detect potential memory corruptions,
memory leaks or missing initializations
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 481 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Static analysis
The problem
all the tools discussed so far work on binaries
they analyze the code being run
so there is a coverage problem (e.g. for error cases)
A (partial) solution : analyzing the source code
build a graph of dependencies of the calls
use graph tools to detect potential memory corruptions,
memory leaks or missing initializations
Existing tools
Coverity proprietary tool, the most complete
cppcheck free and opensource, but less complete
clang-tidy clang-based “linter”, includes clang static analyzer
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 481 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
cppcheck
Exercise: cppcheck
go to exercises/cppcheck
compile, run, see that it works
use valgrind: no issue
use cppcheck, see the problem
analyze the issue, and fix it
bonus: understand why valgrind did not complain
and how the standard deviation could be biased
hint : use gdb and check addresses of v and diffs
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 482 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
clang-tidy
Documentation and supported checks
https://clang.llvm.org/extra/clang-tidy/
Run clang-tidy
clang-tidy <file.cpp> -checks=...
clang-tidy <file.cpp> (checks from .clang-tidy file)
clang-tidy <file.cpp> --fix (applies fixes)
Compilation flags
clang-tidy needs to know exactly how your program is built
clang-tidy ... -- <all compiler flags>
.clang-tidy file
describes which checks to run
usually checked in at repository root
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 483 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Automatically collecting compilation flags
clang-tidy looks for a file called compile_commands.json
contains the exact build flags for each .cpp file
generate with CMake:
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ...
for Makefiles try Bear
allows to run clang-tidy in bulk on all files:
run-clang-tidy -checks ...
run-clang-tidy (checks from .clang-tidy)
run-clang-tidy -fix (applies fixes)
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 484 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
clang-tidy
Exercise: clang-tidy
go to any example which compiles (e.g.
exercises/cppcheck)
mkdir build && cd build
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..
clang-tidy <../file.cpp> -checks=*
inspect output
run with --fix flag
revert changes using git checkout <../file.cpp>
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 485 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Profiling
6 Useful tools
C++ editor
Version control
Code formatting
The Compiling Chain
Web tools
Debugging
Sanitizers
The Valgrind family
Static code analysis
Profiling
Doxygen
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 486 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Profiling
Conceptually
take a measurement of a performance aspect of a program
where in my code is most of the time spent?
is my program compute or memory bound?
does my program make good use of the cache?
is my program using all cores most of the time?
how often are threads blocked and why?
which API calls are made and in which order?
...
the goal is to find performance bottlenecks
is usually done on a compiled program, not on source code
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 487 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
perf, VTune and uProf
perf
perf is a powerful command line profiling tool for linux
compile with -g -fno-omit-frame-pointer
perf stat -d <prg> gathers performance statistics while
running <prg>
perf record -g <prg> starts profiling <prg>
perf report displays a report from the last profile
More information in this wiki, this website or this talk.
Intel VTune and AMD uProf
Graphical profilers from CPU vendors with rich features
Needs vendor’s CPU for full experience
More information on Intel’s website and AMD’s website
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 488 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Doxygen
6 Useful tools
C++ editor
Version control
Code formatting
The Compiling Chain
Web tools
Debugging
Sanitizers
The Valgrind family
Static code analysis
Profiling
Doxygen
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 489 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Doxygen
Doxygen
Generates documentation from source code comments
Output formats: HTML, LaTeX, XML, ...
May be input for further generators, e.g. Sphinx
Doxygen uses a config file, usually called Doxyfile
Run doxygen -g to generate an initial Doxyfile
Edit Doxyfile (e.g. output format, source code location, etc.)
Run doxygen to (re-)generate documentation
View e.g. HTML documentation using a standard web browser
More on the doxygen website
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 490 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Doxygen
Comment blocks
1 /** 10 ///
2 * text/directives ... 11 /// text/directives ...
3 */ 12 ///
4 some_cpp_entity 13 some_cpp_entity
5 14
6 /*! 15 //!
7 * text/directives ... 16 //! text/directives ...
8 */ 17 //!
9 some_cpp_entity 18 some_cpp_entity
More details available here
Comment blocks for members
int a_class_member; ///< trailing documentation
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 491 / 548
Intro base OO More exp Tool conc py edit VCS format gcc web gdb sani valgrind static prof doxygen
Doxygen
Comment directives
1 /**
2 * Long description here. May include HTML etc.
3 *
4 * \brief Checks whether i is odd
5 * \tparam Integral The integral type of the input
6 * \param i Input value
7 * \return True if i is odd, otherwise false
8 * \throw std::out_of_range if i is larger than 100
9 * \see isEven
10 */
11 template <typename Integral>
12 bool isOdd(Integral i);
All directives can also start with @ instead of \
A list of all commands can be found here
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 492 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Concurrency
6 Useful tools
1 History and goals
7 Concurrency
Threads and async
2 Language basics
Mutexes
Atomic types
3 Object orientation (OO) Thread-local storage
Condition Variables
4 Core modern C++
8 C++ and python
5 Expert C++
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 493 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Threads and async
7 Concurrency
Threads and async
Mutexes
Atomic types
Thread-local storage
Condition Variables
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 494 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Basic concurrency C++ 11/C++ 20
Threading
C++ 11 added std::thread in <thread> header
takes a function as argument of its constructor
must be detached or joined before the main thread terminates
C++ 20: std::jthread automatically joins at destruction
Example code
1 void foo() {...}
2 void bar() {...}
3 int main() {
4 std::thread t1{foo};
5 std::thread t2{bar};
6 for (auto t: {&t1,&t2}) t->join();
7 return 0;
8 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 495 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Basic concurrency C++ 11/C++ 20
Threading
C++ 11 added std::thread in <thread> header
takes a function as argument of its constructor
must be detached or joined before the main thread terminates
C++ 20: std::jthread automatically joins at destruction
Example with jthread (C++ 20)
1 void foo() {...}
2 void bar() {...}
3 int main() {
4 std::jthread t1{foo};
5 std::jthread t2{bar};
6 return 0;
7 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 495 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
The thread constructor C++ 11
Can take a function and its arguments
1 void function(int j, double j) {...};
2 std::thread t1{function, 1, 2.0};
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 496 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
The thread constructor C++ 11
Can take a function and its arguments
1 void function(int j, double j) {...};
2 std::thread t1{function, 1, 2.0};
Can take any function-like object
1 struct AdderFunctor {
2 AdderFunctor(int i): m_i(i) {}
3 int operator() (int j) const { return m_i+j; }
4 int m_i;
5 };
6 std::thread t2{AdderFunctor{2}, 5};
7 int a;
8 std::thread t3{[](int i) { return i+2; }, a};
9 std::thread t4{[a] { return a+2; }};
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 496 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Basic asynchronicity C++ 11
Concept
separation of the specification of what should be done and the
retrieval of the results
“start working on this, and let me check if it’s done”
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 497 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Basic asynchronicity C++ 11
Concept
separation of the specification of what should be done and the
retrieval of the results
“start working on this, and let me check if it’s done”
Practically
std::async function launches an asynchronous task
std::future<T> allows to retrieve the result
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 497 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Basic asynchronicity C++ 11
Concept
separation of the specification of what should be done and the
retrieval of the results
“start working on this, and let me check if it’s done”
Practically
std::async function launches an asynchronous task
std::future<T> allows to retrieve the result
Example code
1 int f() {...}
2 std::future<int> res = std::async(f);
3 std::cout << res.get() << "\n";
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 497 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Mixing the two C++ 11
Is async running concurrently ?
it depends!
you can control this with a launch policy argument
std::launch::async start executing immediately on a separate
thread (may be a new thread, a thread pool, ...)
std::launch::deferred causes lazy execution in current thread
execution starts when get() is called on the returned future
default is not specified, but tries to use existing concurrency!
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 498 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Mixing the two C++ 11
Is async running concurrently ?
it depends!
you can control this with a launch policy argument
std::launch::async start executing immediately on a separate
thread (may be a new thread, a thread pool, ...)
std::launch::deferred causes lazy execution in current thread
execution starts when get() is called on the returned future
default is not specified, but tries to use existing concurrency!
Usage
1 int f() {...}
2 auto res1 = std::async(std::launch::async, f);
3 auto res2 = std::async(std::launch::deferred, f);
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 498 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Fine-grained control on asynchronous execution C++ 11
std::packaged_task template
creates an asynchronous version of any function-like object
identical arguments
returns a std::future
provides access to the returned future
associated with threads, gives full control on execution
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 499 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Fine-grained control on asynchronous execution C++ 11
std::packaged_task template
creates an asynchronous version of any function-like object
identical arguments
returns a std::future
provides access to the returned future
associated with threads, gives full control on execution
Usage
1 int f() { return 42; }
2 std::packaged_task<int()> task{f};
3 auto future = task.get_future();
4 task();
5 std::cout << future.get() << std::endl;
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 499 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Mutexes
7 Concurrency
Threads and async
Mutexes
Atomic types
Thread-local storage
Condition Variables
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 500 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Races C++ 11
Example code - godbolt
1 int a = 0;
2 void inc() { a++; };
3 void inc100() {
4 for (int i=0; i < 100; i++) inc();
5 };
6 int main() {
7 std::thread t1{inc100};
8 std::thread t2{inc100};
9 for (auto t: {&t1,&t2}) t->join();
10 std::cout << a << "\n";
11 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 501 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Races C++ 11
Example code - godbolt
1 int a = 0;
2 void inc() { a++; };
3 void inc100() {
4 for (int i=0; i < 100; i++) inc();
5 };
6 int main() {
7 std::thread t1{inc100};
8 std::thread t2{inc100};
9 for (auto t: {&t1,&t2}) t->join();
10 std::cout << a << "\n";
11 }
What do you expect? (Exercise exercises/race)
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 501 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Races C++ 11
Example code - godbolt
1 int a = 0;
2 void inc() { a++; };
3 void inc100() {
4 for (int i=0; i < 100; i++) inc();
5 };
6 int main() {
7 std::thread t1{inc100};
8 std::thread t2{inc100};
9 for (auto t: {&t1,&t2}) t->join();
10 std::cout << a << "\n";
11 }
What do you expect? (Exercise exercises/race)
Anything between 100 and 200 !!!
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 501 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Atomicity C++ 11
Definition (wikipedia)
an operation (or set of operations) is atomic if it appears to
the rest of the system to occur instantaneously
Practically
an operation that won’t be interrupted by other concurrent
operations
an operation that will have a stable environment during
execution
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 502 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Atomicity C++ 11
Definition (wikipedia)
an operation (or set of operations) is atomic if it appears to
the rest of the system to occur instantaneously
Practically
an operation that won’t be interrupted by other concurrent
operations
an operation that will have a stable environment during
execution
Is ++ operator atomic ?
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 502 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Atomicity C++ 11
Definition (wikipedia)
an operation (or set of operations) is atomic if it appears to
the rest of the system to occur instantaneously
Practically
an operation that won’t be interrupted by other concurrent
operations
an operation that will have a stable environment during
execution
Is ++ operator atomic ?
Usually not. It behaves like :
1 eax = a // memory to register copy
2 increase eax // increase (atomic CPU instruction)
3 a = eax // copy back to memory
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 502 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Timing C++ 11
Code
1 eax = a // memory to register copy
2 increase eax // increase (atomic CPU instruction)
3 a = eax // copy back to memory
For 2 threads
Thread 1:eax Memory:a Thread 2:eax
read read
0 0
incr incr
time
write 1 write 1
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 503 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Mutexes and Locks C++ 17
Concept
Use locks to serialize access to a non-atomic piece of code
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 504 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Mutexes and Locks C++ 17
Concept
Use locks to serialize access to a non-atomic piece of code
The objects
std::mutex in the mutex header. Mutual exclusion
std::scoped_lock RAII to lock and unlock automatically
std::unique_lock same, but can be released/relocked explicitly
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 504 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Mutexes and Locks C++ 17
Concept
Use locks to serialize access to a non-atomic piece of code
The objects
std::mutex in the mutex header. Mutual exclusion
std::scoped_lock RAII to lock and unlock automatically
std::unique_lock same, but can be released/relocked explicitly
Practically - godbolt
1 int a = 0;
2 std::mutex m;
3 void inc() {
4 std::scoped_lock lock{m};
5 a++;
6 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 504 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Mutexes and Locks C++ 17
Good practice: Locking
Generally, use std::scoped_lock. Before C++ 17 use
std::lock_guard.
Hold as short as possible, consider wrapping critical section in
block statement { }
Only if manual control needed, use std::unique_lock
1 void function(...) {
2 // uncritical work ...
3 {
4 std::scoped_lock myLocks{mutex1, mutex2, ...};
5 // critical section
6 }
7 // uncritical work ...
8 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 505 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Mutexes and Locks
Exercise: Mutexes and Locks
Go to exercises/race
Look at the code and try it
See that it has a race condition
Use a mutex to fix the issue
See the difference in execution time
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 506 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Dead locks C++ 11
Scenario
2 mutexes, 2 threads
locking order different in the 2 threads
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 507 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Dead locks C++ 11
Scenario
2 mutexes, 2 threads
locking order different in the 2 threads
Sequence diagram
Thread 1: Mutex A: Mutex B: Thread 2:
lock
lock
lock (block) time
lock (block)
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 507 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
How to avoid dead locks C++ 11
Possible solutions
C++ 17: std::scoped_lock lock{m1, m2}; comes with
deadlock-avoidance algorithm
Never take several locks
Or add master lock protecting the locking phase
Respect a strict locking order across all threads
Do not use locks
Use other techniques, e.g. lock-free queues
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 508 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Shared mutex / locks C++ 17
Sharing a mutex
Normal std::mutex objects cannot be shared
std::shared_mutex to the rescue, but can be slower
It locks either in exclusive or in shared mode; never both
1 Data data; std::shared_mutex mutex;
2 auto reader = [&](){
3 std::shared_lock lock{mutex};
4 read(data); // Many can read
5 };
6 std::thread r1{reader}, r2{reader}, ...;
7
8 std::thread writer([&](){
9 std::scoped_lock lock{mutex}; // exclusive
10 modify(data); // Only one can write
11 });
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 509 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Atomic types
7 Concurrency
Threads and async
Mutexes
Atomic types
Thread-local storage
Condition Variables
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 510 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
++
Atomic types in C C++ 11
std::atomic template
Any trivially copyable type can be made atomic in C++
Most useful for integral types
May internally use locks for custom types
1 std::atomic<int> a{0};
2 std::thread t1([&](){ a++; });
3 std::thread t2([&](){ a++; });
4 a += 2;
5 t1.join(); t2.join();
6 assert( a == 4 ); // Guaranteed to succeed
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 511 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Warning: Expressions using an atomic type are not atomic!
1 std::atomic<int> a{0};
2 std::thread t1([&]{ a = a + 2; });
3 std::thread t2([&]{ a = a + 2; });
Atomic load; value+2; atomic store
Sequence diagram
Thread 1: atomic: Thread 2:
load load
+2 +2
time
store 2 store 2
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 512 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Solution: Use atomic member functions
The member functions of std::atomic are thread safe
fetch_add and operator+=: atomic { load; add; store }
But don’t confuse “a += 2” and “a = a + 2”
1 std::atomic<int> a{0};
2 std::thread t1([&]{ a.fetch_add(2); });
3 std::thread t2([&]{ a += 2; });
Sequence diagram
Thread 1: atomic: Thread 2:
fetch_add
time
+=
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 513 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Atomic references C++ 20
std::atomic_ref template
Wraps a T& and makes access to it atomic
Like std::atomic<T>, but does not contain the T
1 int a{0};
2 std::thread t1([&]{ std::atomic_ref<int> r{a}; r++;});
3 std::thread t2([&]{ std::atomic_ref{a}++; });
4 t1.join(); t2.join();
5 a += 2; // non-atomic (fine, threads joined before)
6 assert( a == 4 ); // Guaranteed to succeed
Don’t mix concurrent atomic and non-atomic access
1 std::thread t3([&]{ std::atomic_ref{a}++; });
2 a += 2; // data race
3 t3.join();
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 514 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
++
Atomic types in C
Exercise: Atomics
Go to exercises/atomic
You’ll find a program with the same race condition as in race
Fix it using std::atomic
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 515 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Thread-local storage
7 Concurrency
Threads and async
Mutexes
Atomic types
Thread-local storage
Condition Variables
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 516 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Thread-local storage C++ 20
thread_local keyword
A variable can be declared thread-local
Then every thread will have its own copy
Most useful for “working memory” in each thread
Note: Can also be declared directly on the stack of a thread
and will be faster, thus should be preferred when possible
1 thread_local int a{0};
2 std::jthread t1([&] { a++; });
3 std::jthread t2([&] { a++; });
4 a += 2;
5 t1.join(); t2.join();
6 assert( a == 2 ); // Guaranteed to succeed
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 517 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Condition Variables
7 Concurrency
Threads and async
Mutexes
Atomic types
Thread-local storage
Condition Variables
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 518 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Condition variables C++ 11
Communicating between threads
Take the case where threads are waiting for other thread(s)
std::condition_variable
from <condition_variable> header
Allows for a thread to sleep (= conserve CPU time) until a
given condition is satisfied
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 519 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Condition variables C++ 11
Communicating between threads
Take the case where threads are waiting for other thread(s)
std::condition_variable
from <condition_variable> header
Allows for a thread to sleep (= conserve CPU time) until a
given condition is satisfied
Usage
Use RAII-style locks to protect shared data
wait() will block until the condition is met
you can have several waiters sharing the same mutex
notify_one() will wake up one waiter
notify_all() will wake up all waiters
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 519 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Using condition variables: notify C++ 17
Producer side: providing data to waiting threads
Protect data with a mutex, and use condition variable to
notify consumers
Optimal use: don’t hold lock while notifying
waiting threads would be blocked
1 std::mutex mutex;
2 std::condition_variable cond;
3 Data data;
4 std::thread producer([&](){
5 {
6 std::scoped_lock lock{mutex};
7 data = produceData(); // may take long ...
8 }
9 cond.notify_all();
10 });
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 520 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Using condition variables: wait C++ 11
Mechanics of wait
Many threads are waiting for shared data
Pass a unique_lock and a predicate for wakeup to wait()
wait() sends threads to sleep while predicate is false
wait() will only lock when necessary; unlocked while sleeping
Threads might wake up spuriously, but wait() returns only
when lock available and predicate true
Naïve waiting
1 auto processData = [&](){
2 std::unique_lock<std::mutex> lock{mutex};
3 cond.wait(lock, [&](){ return data.isReady(); });
4 process(data);
5 };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 521 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Using condition variables: wait C++ 11
Waiting / waking up
notify_all() is called, threads wake up
Threads try to lock mutex, and evaluate predicate
One thread succeeds to acquire mutex, starts data processing
Problem: Thread holds mutex now, other threads are blocked!
Naïve waiting
1 auto processData = [&](){
2 std::unique_lock<std::mutex> lock{mutex};
3 cond.wait(lock, [&](){ return data.isReady(); });
4 process(data);
5 };
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 521 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Using condition variables: correct wait C++ 11
Waiting / waking up
Solution: Put locking and waiting in a scope
Threads will one-by-one wake up, acquire lock, evaluate
predicate, release lock
Correct waiting
1 auto processData = [&](){
2 {
3 std::unique_lock<std::mutex> lock{mutex};
4 cond.wait(lock, [&](){ return data.isReady(); });
5 }
6 process(data);
7 };
8 std::thread t1{processData}, t2{processData}, ...;
9 for (auto t : {&producer, &t1, &t2, ...}) t->join();
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 522 / 548
Intro base OO More exp Tool conc py thr mutex atomic TLS condition
Condition variables
Exercise: Condition variables
Go to exercises/condition_variable
Look at the code and run it
See that it has a race condition
Fix the race condition in the usage of the condition variable
Try to make threads process data in parallel
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 523 / 548
Intro base OO More exp Tool conc py module C ctypes cppyy
++
C and python
6 Useful tools
1 History and goals
7 Concurrency
2 Language basics
8 C++ and python
Writing a module
3 Object orientation (OO)
Marrying C++ and C
The ctypes module
4 Core modern C++ The cppyy project
5 Expert C++
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 524 / 548
Intro base OO More exp Tool conc py module C ctypes cppyy
Writing a module
8 C++ and python
Writing a module
Marrying C++ and C
The ctypes module
The cppyy project
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 525 / 548
Intro base OO More exp Tool conc py module C ctypes cppyy
How to build a python 3 module around C++ code
C++ code : mandel.hpp
1 int mandel(Complex const & a);
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 526 / 548
Intro base OO More exp Tool conc py module C ctypes cppyy
Basic Module(1): wrap your method
mandelModule.cpp - see exercises/python exercise
1 #include <Python.h>
2 #include "mandel.hpp"
3 PyObject * mandel_wrapper(PyObject * self,
4 PyObject * args) {
5 // Parse Input
6 float r, i;
7 if (!PyArg_ParseTuple(args, "ff", &r, &i))
8 return nullptr;
9 // Call C++ function
10 int result = mandel(Complex(r, i));
11 // Build returned objects
12 return PyLong_FromLong(result);
13 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 527 / 548
Intro base OO More exp Tool conc py module C ctypes cppyy
Basic Module(2): create the python module
mandelModule.cpp - see exercises/python exercise
1 // declare the modules' methods
2 PyMethodDef mandelMethods[] = {
3 {"mandel", mandel_wrapper, METH_VARARGS,
4 "computes nb of iterations for mandelbrot set"},
5 {nullptr, nullptr, 0, nullptr}
6 };
7 // declare the module
8 struct PyModuleDef mandelModule = {
9 PyModuleDef_HEAD_INIT,
10 "mandel", nullptr, -1, mandelMethods
11 };
12 PyMODINIT_FUNC PyInit_mandel() {
13 return PyModule_Create(&mandelModule);
14 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 528 / 548
Intro base OO More exp Tool conc py module C ctypes cppyy
Basic Module(3): use it
First compile the module
as a regular shared library
with ’-I \$(PYTHON\_INCLUDE)’
mandel.py - see exercises/python exercise
from mandel import mandel
v = mandel(0.7, 1.2)
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 529 / 548
Intro base OO More exp Tool conc py module C ctypes cppyy
++
Marrying C and C
8 C++ and python
Writing a module
Marrying C++ and C
The ctypes module
The cppyy project
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 530 / 548
Intro base OO More exp Tool conc py module C ctypes cppyy
A question of mangling
Mangling
the act of converting the name of variable or function to a symbol
name in the binary code
C versus C++ symbol names
C uses bare function name
C++ allows overloading of functions by taking the signature
into account
so C++ mangling has to contain signature
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 531 / 548
Intro base OO More exp Tool conc py module C ctypes cppyy
C mangling
Source : file.c
1 float sum(float a, float b);
2 int square(int a);
3 // won't compile : conflicting types for ‘square’
4 // float square(float a);
Binary symbols : file.o
# nm file.o
000000000000001a T square
0000000000000000 T sum
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 532 / 548
Intro base OO More exp Tool conc py module C ctypes cppyy
++
C mangling
Source : file.cpp
1 float sum(float a, float b);
2 int square(int a);
3 // ok, signature is different
4 float square(float a);
Binary symbols : file.o
# nm file.o
0000000000000000 T _Z3sumff
000000000000002a T _Z6squaref
000000000000001a T _Z6squarei
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 533 / 548
Intro base OO More exp Tool conc py module C ctypes cppyy
Forcing C mangling in C++
extern “C”
These functions will use C mangling :
1 extern "C" {
2 float sum(float a, float b);
3 int square(int a);
4 }
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 534 / 548
Intro base OO More exp Tool conc py module C ctypes cppyy
Forcing C mangling in C++
extern “C”
These functions will use C mangling :
1 extern "C" {
2 float sum(float a, float b);
3 int square(int a);
4 }
You can now call these C++ functions from C code
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 534 / 548
Intro base OO More exp Tool conc py module C ctypes cppyy
Forcing C mangling in C++
extern “C”
These functions will use C mangling :
1 extern "C" {
2 float sum(float a, float b);
3 int square(int a);
4 }
You can now call these C++ functions from C code
Limitations
no C++ types should go out
no exceptions either (use noexcept here)
member functions cannot be used
they need to be wrapped one by one
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 534 / 548
Intro base OO More exp Tool conc py module C ctypes cppyy
The ctypes module
8 C++ and python
Writing a module
Marrying C++ and C
The ctypes module
The cppyy project
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 535 / 548
Intro base OO More exp Tool conc py module C ctypes cppyy
The ctypes python module
From the documentation
provides C compatible data types
allows calling functions in DLLs or shared libraries
can be used to wrap these libraries in pure Python
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 536 / 548
Intro base OO More exp Tool conc py module C ctypes cppyy
ctypes: usage example
C++ code : mandel.hpp
1 int mandel(Complex const & a);
“C” code : mandel_cwrapper.hpp
1 extern "C" {
2 int mandel(float r, float i) {
3 return mandel(Complex(r, i));
4 };
5 }
calling the mandel library
from ctypes import *
libmandel = CDLL('libmandelc.so')
v = libmandel.mandel(c_float(0.3), c_float(1.2))
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 537 / 548
Intro base OO More exp Tool conc py module C ctypes cppyy
++
Marrying C and python
Exercise: C++ and python
go to exercises/python
look at the original python code mandel.py
time it (‘time python3 mandel.py‘)
look at the code in mandel.hpp/cpp
look at the python module mandel_module.cpp
compile and modify mandel.py to use it
see the gain in time
look at the C wrapper in mandel_cwrapper.cpp
modify mandel.py to use libmandelc directly with ctypes
Note : you may have to add ’.’ to LD_LIBRARY_PATH and PYTHONPATH
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 538 / 548
Intro base OO More exp Tool conc py module C ctypes cppyy
The cppyy project
8 C++ and python
Writing a module
Marrying C++ and C
The ctypes module
The cppyy project
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 539 / 548
Intro base OO More exp Tool conc py module C ctypes cppyy
Automatic Python-C++ bindings
The cppyy project
originated from the ROOT project
still young, version 1.0 from Mid 2018
but very active, current version 2.1.0
extremely powerful for interfacing C++ and python
How it works
uses Just in Time compilation through cling
an interactive C++ interpreter
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 540 / 548
Intro base OO More exp Tool conc py module C ctypes cppyy
cppyy crash course(1)
Shamelessly copied from the cppyy documentation
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 541 / 548
Intro base OO More exp Tool conc py module C ctypes cppyy
cppyy crash course(1)
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 542 / 548
Intro base OO More exp Tool conc py module C ctypes cppyy
This is the end
Questions ?
https://github.com/hsf-training/cpluspluscourse/raw/download/talk/C++Course_full.pdf
https://github.com/hsf-training/cpluspluscourse
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 543 / 548
Index External Resources and Further Reading
Index of Good Practices
1 C’s memory management 27 18 Absolutely avoid diamond-shaped
2 Manual memory management 28 inheritance 147
3 Initialisation 31 19 Operator overloading 170
4 Avoid unions 38 20 Throwing exceptions 188
5 References 45 21 Catching exceptions 190
6 Write readable functions 54 22 Exceptions 194
7 for syntax 67 23 noexcept 197
8 preprocessor 75 24 Specialization vs. overloading 230
9 Assert 86 25 STL and lambdas 261
10 Implementing methods 93 26 C random library 290
11 Rule of 3/5 109 27 Use std::fstream 301
12 Prefer smart pointer 127
28 std::unique_ptr 307
13 Prefer containers 128
29 Single responsibility principle 313
14 Virtual destructors 140
30 Rule of zero 313
15 Avoid multiple inheritance 147
31 Initialization 323
16 Absolutely avoid diamond-shaped
inheritance 147 32 SFINAE vs. if constexpr 374
17 Avoid multiple inheritance 147 33 Locking 505
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 544 / 548
Index External Resources and Further Reading
Index of Exercises
1 Functions 53 12 std::variant 278 23 memcheck 475
2 Control structs 72 13 Smart pointers 314 24 callgrind 477
3 Loops, refs, auto 79 14 Variadic tpl 345
25 helgrind 479
4 Polymorphism 143 15 Concepts 387
5 Virtual OO 148 16 Modules 412 26 cppcheck 482
6 Operators 159 17 Header units 412 27 clang-tidy 485
7 Constness 177 18 clang-format 440 28 Mutexes/Locks 506
8 Move semantics 212 19 Compiler chain 450
29 Atomics 515
9 Templates 234 20 gdb 459
10 STL 266 21 address sanitizer 468 30 Condition vars 523
11 std::optional 274 22 valgrind 474 31 C++ and python 538
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 545 / 548
Index External Resources and Further Reading
Index of Godbolt code examples
1 assert - godbolt 85 16 <=> output - godbolt 329
2 Unary constructor in action - 17 various orderings - godbolt 331
godbolt 111
18 tuple code - godbolt 341
3 function objects - godbolt 162
4 Nested templates - godbolt 222
19 hasFoo failing - godbolt 366
5 lambda - godbolt 247 20 hasFoo working - godbolt 368
6 STL - godbolt 251 21 enable_if - godbolt 371
7 Iterator example - godbolt 257 22 SFINAE failure - godbolt 377
8 span - godbolt 271 23 concept failure - godbolt 378
9 variant visitor - godbolt 276
24 Resuming a coroutine - godbolt 421
10 variant λ visitor - godbolt 277
11 Views - godbolt 293 25 co_yield - godbolt 425
12 Lazy view - godbolt 295 26 Infinite generator - godbolt 426
13 unique_ptr copy - godbolt 303 27 Fibonacci generator - godbolt 427
14 std::shared_ptr quiz - godbolt 28 Thread switching - godbolt 430
310
29 Race - godbolt 501
15 shared_ptr vs. weak_ptr quiz -
godbolt 312 30 mutex - godbolt 504
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 546 / 548
Index External Resources and Further Reading
Books
A Tour of C++, Third Edition
Bjarne Stroustrup, Addison-Wesley, Sep 2022
ISBN-13: 978-0136816485
Effective Modern C++
Scott Meyers, O’Reilly Media, Nov 2014
ISBN-13: 978-1-491-90399-5
C++ Templates - The Complete Guide, 2nd Edition
David Vandevoorde, Nicolai M. Josuttis, and Douglas Gregor
ISBN-13: 978-0-321-71412-1
C++ Best Practices, 2nd Edition
Jason Turner
https://leanpub.com/cppbestpractices
Clean Architecture
Robert C. Martin, Pearson, Sep 2017
ISBN-13: 978-0-13-449416-6
The Art of UNIX Programming
Eric S. Raymond, Addison-Wesley, Sep 2002
ISBN-13: 978-0131429017
Introduction to Algorithms, 4th Edition
T. H. Cormen, C. E. Leiserson, R. L. Rivest, C. Stein, Apr 2022
ISBN-13: 978-0262046305
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 547 / 548
Index External Resources and Further Reading
Conferences
CppCon — cppcon.org — CppCon
C++ Now — cppnow.org — BoostCon
Code::Dive — codedive.pl — codediveconference
ACCU Conference — accu.org — ACCUConf
Meeting C++ — meetingcpp.com — MeetingCPP
See link below for more information
https://isocpp.org/wiki/faq/conferences-worldwide
B. Gruber, S. Hageboeck, S. Ponce HEP C++ course 548 / 548