<<

Advanced Programming Techniques (Amazing ++) Bartosz Mindur Applied Physics and Computer Science Summer School '20

Kraków, 2020-07-16

[1 / 37] www.menti.com/28f8u5o5xr Which programming language do you use the most?

cpp h s a

b python a

c v a y j

csharp l b m e s s a

18

[2 / 37] Agenda References C++ history C++11/14 - must be used C++17 - should be used C++20 - may (eventually) be used ...

[3 / 37] www.menti.com/uaw75janh7 What is your current knowledge of C++?

Core C++ 3.1

C++ STL ! e k e 2.2 i l n

o d o N C++ 11/14 G 2.4

C++17 1.4

17

[4 / 37] References and tools

[5 / 37] C++ links and cool stu

C++ links Online tools

ISO C++ Compiler Explorer cpp references cpp insights c & cpp programming cpp.sh #include <C++> repl.it LernCpp.com Quick Bench cplusplus.com Online GDB CppCon piaza.io CppCast codiva.io Bartek Filipek ... Oine tools

CMake Valgrind GDB Docker Clang Static Analyzer [6 / 37] Things you (probably) already know well

[7 / 37] C++ basics variables conversion and casts references implicit pointers explicit functions static statements dynamic loops exceptions declaration function templates initialization class templates operator overloading smart pointers classes basics of the STL constructors & destructor containers fields iterators methods algorithms inheritance building programs types compilation virtual functions linking polymorphism libraries multiple inheritance tools

[8 / 37] www.menti.com/32rn4y3j What is the most important C++ feature?

polymorphism templates encapsulation s r e t n i e inheritance o c p n a s

w hardware accessibility i e r e s g s

n multithreading i a l generic programming c

8

[9 / 37] C++ history

[10 / 37] The Design of C++

The Design of C++, a lecture by Bjarne Stroustrup This video has been recorded in March, 1994 [link]

The Design of C++ , lecture by Bjarne Stroustr… Do obejrze… Udostępnij

[11 / 37] C++ Timeline

[link]

[12 / 37] C++11/C++14

[13 / 37] Move semantics Value categories (simplied) Special members lvalue T::T(const T&& other) or T::T(T&& other) T& operator=(T&& other) e.g. named variable something which stands on the left of the operator= prvalue - pure rvalue

e.g. temporary variable (without name) something which stands on the right of the operator= xvalue - 'eXpiring' value

std::move(x) rvalue = prvalue + xvalue [Ref], [Ref], [Ref] and Code sample [14 / 37] Constant expressions - constexpr

The constexpr #include // C++11 constexpr functions use recursion rather than iteration specier declares that it is // C++14 constexpr functions may use local variables and loops possible to evaluate the constexpr int factorial(int n) { const int res = n <= 1 ? 1 : (n * factorial(n - 1)); value of the function or return res; variable at compile time } // output function that requires a compile-time constant, for testing template Such variables and struct constN { constN() { std::cout << n << '\n'; } functions can then be used }; where only compile time int main() { constant expressions are std::cout << "4! = " ; allowed constN out1; // computed at compile time int n = std::rand()/((RAND_MAX + 1u)/6); int out2 = factorial(n); //computed at run time They are somehow similar std::cout << n << "! = " << out2 << "\n"; } to const but ordinary const refers to run-time [Ref] and Code sample #1, Code sample #2 [15 / 37] Uniform initialization and initializer_list

Braced initialization list - {} Initialization with std::initializer_list int foo(){ int i{1}; int arr[] = {1, 2, 3, 4, 5}; template int *pi = new int[5]{1, 2, 3, 4, 5}; struct S { std::vector v; std::string s {"hello"}; S(std::initializer_list l) : v(l) { std::vector foo{1, 2}; std::cout << "constructed with a " std::map bar << l.size() { {0,"zero"}, {1,"one"}, {2,"two"} }; << "-element list\n"; } f({foo, bar}); void append(std::initializer_list l) { return {foo, bar}; v.insert(v.end(), l.begin(), l.end()); } } };

[Ref], [Ref] and Code sample

[16 / 37] Type interface auto

For variables, species that the type of the variable that is being declared will be automatically deduced from its initializer

For functions, species that the return type will be deduced from its return statements [Ref]

#include #include int main() { auto a = 1 + 2; // type of a is int auto b = 1 + 1.2; // type of b is double static_assert(std::is_same_v); static_assert(std::is_same_v);

const auto c0 = a; // type of c0 is int, holding a copy of a

auto d = {1, 2}; // OK: type of d is std::initializer_list auto n = {5}; // OK: type of n is std::initializer_list // auto e{1, 2}; // Error as of C++17, std::initializer_list before auto m{5}; // OK: type of m is int as of C++17, initializer_list before

// auto int x; // valid C++98, error as of C++11 // auto x; // valid C, error in C++ } [17 / 37] Range-based for loop

Executes a for loop over a range

#include #include #include #include

template template void set_for_each(T cnt, V val){ void set_for_each(T& cnt, V val){ for(auto v: cnt) for(auto& v: cnt) v = val; v = val; } }

template template void printer(T cnt, std::ostream& o = std::cout) { void printer(T cnt, std::ostream& o = std::cout) { for(auto v: cnt) for(auto v: cnt) o << v << ";"; o << v << ";"; } }

int main() { int main() { std::array t = {0, 1, 2, 3}; std::array t = {0, 1, 2, 3}; set_for_each(t, 13); set_for_each(t, 13); printer(t); printer(t);

} }

Code sample #1 Code sample #2 and [Ref] [18 / 37] Explicit override and final virtual function specier override

#include Specifies that a virtual function overrides another struct Base { virtual function. virtual void f() { std::cout << "base\n"; } }; final struct Derived : Base { void f() { Specifies that a virtual function cannot be std::cout << "derived\n"; } overridden in a derived class }; Or that a class cannot be inherited from

Do not forget of virtual destructors [Ref], [Ref] and Code sample [Ref] and Code sample

[19 / 37] Lambdas

#include Constructs a closure int main() { auto f1 = [] () { an unnamed function object capable of capturing std::cout << "simple lambda\n"; }; variables in scope f1();

[ captures ] ( params ) spec -> ret { body } int a = {5}; auto f2 = [=] () { std::cout << "simple lambda: " << a << "\n"; captures - a comma-separated list of zero or more }; f2(); captures with =, &, this params - a list of parameters, as in named auto f3 = [&] () { a = 17; functions std::cout << "simple lambda: " << a << "\n"; spec - optional sequence of specifiers (e.g. }; mutable) f3(); } ret - return type, if not present it's implied by the function return statements body - function body Code sample #1 and Code explanation, Code sample #2 [Ref] Code sample #3 and Code explanation [20 / 37] Template aliases and static assertions using static_assert

type alias is a name that refers to a previously performs compile-time assertion checking defined type (similar to typedef) no runtime costs alias template is a name that refers to a family of types int main() { using T1 = char; using T2 = int; template struct Alloc { }; static_assert(sizeof(T1) >= 2, "Type size is too small."); // error template // type-id is vector> static_assert(sizeof(T2) >= 2, using Vec = vector>; "Type size is too small."); // ok } Vec v; // Vec == >

[Ref] [Ref] and Code sample

[21 / 37] Variadic templates & parameter pack

Parameter pack Expand parameter pack

a template parameter pack is a template parameter #include that accepts zero or more template arguments template a template with at least one parameter pack is void print(T arg) { called a variadic template std::cout << "[" << arg << "] "; } template parameter pack ... appears in alias template template class template void print(T arg, Ts... args) { print(arg); variable template print(args...); function template parameter lists } int main() { template print(1, 2.0, "Tekst", "Next text"); struct Tuple {}; } Tuple<> t0; // no arguments Tuple t1; // one argument: int Tuple t2; // two arguments: int and float Tuple<0> error; // error: 0 is not a type Code sample #1, Code sample #2 and [Ref]

[22 / 37] Template template parameters (pre C++11 standard)

Sometimes we would like to pass into the template the names of template template parameters do not a template type without fixing its values have to be specified This is what template template parameters are created for template class A { int x; }; // primary template template class A template { long x; }; // partial specialization using stack_v = stack; // class template with a template template parameter int main() { template class V> class C using stack = stack; { stack s1; V y; // uses the primary template V z; // uses the partial specialization stack_v s2; }; } C c; // c.y.x has type int, c.z.x has type long Code sample #1 and [Ref] Code sample #2

[23 / 37] Compile-time decisions and type_traits

Compile-time 'if'' statement Possible implantation

#include template #include struct conditional { typedef T type; }; #include template int main() { struct conditional { typedef F type; }; using std::conditional::type T1; using std::conditional::type T2; using T3=std::conditional= sizeof(double), int, double>::type; Type traits std::cout << typeid(T1).name() << '\n'; type traits defines a compile-time template-based std::cout << typeid(T2).name() << '\n'; std::cout << typeid(T3).name() << '\n'; interface to query or modify the properties of types } type categories type properties Code sample type operations [Ref] and Code sample

[24 / 37] Asynchronous execution the function template std::async runs given #include function asynchronously [Ref] #include int main() { potentially in a separate thread which may be part of a thread pool auto f1 = // std::feature std::future std::async( returns a that will eventually hold []() { // lambda the result of that function call int sum = 0; for(int i = 1; i < 100; ++i) std::future [Ref] sum += i; return sum; }); provides a mechanism to access the result of asynchronous operations e.g. std::async or std::cout << "Sum: " << f1.get() << '\n'; } std::promise std::promise [Ref] Code sample provides a facility to store a value or an exception that is later acquired asynchronously via a std::future object created by the std::promise object [25 / 37] C++17

[26 / 37] Structured binding declaration

Useful way to work with pair, tupe or set and map auto [a, b, c, ...] = expression;

std::pair a(0, 1.0f); struct Point { auto [x, y] = a; double x; double y; }; std::pair a(0, 1.0f); const auto [x, y] = a; Point GetStartPoint() { return { 0.0, 0.0 }; } std::tuple a {0, 1.0f, "string", 3.14, }; auto& [ refA, refB, refC, refD ] = a; const auto [x, y] = GetStartPoint();

Code sample #1, Code sample #2 and [Ref]

[27 / 37] Class template argument deduction

In order to instantiate a class template, every In C++17 deduction of template types is possible template argument must be known for classes in

any declaration that specifies initialization of a Before C++17 all templates arguments have to be variable specied directly, or using function templates - new expressions function-style casts expressions like unsigned(f) // direct usage std::tuple p1{1, 1.0}; std::pair p(2, 4.5); // helper function template // deduces to std::pair p(2, 4.5); auto p2 = std::make_tuple(1, 1.0); std::tuple t(4, 3, 2.5); // same as auto t = std::make_tuple(4, 3, 2.5); auto ptr = new std::pair{42, "World"s}; // for new

Code sample and [Ref]

[28 / 37] Initialization statements for if and switch

In the init section you can specify a new variable, similarly to the init section in for loop if (init; condition) and switch (init; condition)

{ //C++ code before C++17 // Structured bindings + if initializer auto val = GetValue(); if (auto [iter, succeeded] = m.insert(value); if (condition(val)) succeeded) // on success { else use(iter); // ok // on false... // ... } } // iter and succeeded are destroyed here

if (auto val = GetValue(); condition(val)) // on success [Ref] and Code sample else // on false...

[29 / 37] Nested namespaces

Namespaces provide a method for preventing name conicts in large projects Nasted namespaces to be used in more convenient way of grouping namespace inside other namespace

// pre C++ 17 code // C++ 17 code namespace MyCompany { namespace MyCompany::SecretProject::SafetySystem { namespace SecretProject { class SuperArmor { namespace SafetySystem { // ... class SuperArmor { }; // ... class SuperShield { }; // ... class SuperShield { }; // ... } }; } // SafetySystem } // SecretProject } // MyCompany [Ref]

[30 / 37] __has_include preprocessor directive

__has_include

result of 1 only means that a file with the specified name exists it does not mean that the file, when included, would not cause an error etc. e.g. one could use experimental features or standard without changing the code

#if __has_include() # include # define have_optional 1 #elif __has_include() # include # define have_optional 1 # define experimental_optional 1 #else # define have_optional 0 #endif

// rest of code

Code sample and [Ref] [31 / 37] Fold expressions

C++11 introduced variadic templates Variadic templates required some additional code when you wanted to implement 'recursive' functions - rule to stop it

// C++11 code // C++17 code auto Sum() { template return 0; void FoldPrint(Args... args) { } (std::cout << ... << args) << '\n'; template } auto sum(T1 s, T... ts) { return s + sum(ts...); } Code sample and [Ref]

// C++17 code template auto sum(Args ...args) { return (args + ...); }

[32 / 37] Attributes

[[noreturn]] void terminate() noexcept {} Introduces in C++11 [[deprecated("use BetterFunc")]] void f() { } struct [[deprecated]] OldStruct { }; [[noreturn]] void switch_fun(char c) { switch (c) { case 'a': In C++14 added f(); // Warning! fallthrough case 'b': [[deprecated]] and [[deprecated("reason")]] terminate(); [[fallthrough]]; // Warning suppressed case 'c': terminate(); In C++17 added } } [[fallthrough]] - for switch void foo() { [[maybe_unused]] - OK if not used int x = 13; // warning [[maybe_unused]] int y = 13; // no warning [[nodiscard]] - return value shall no be omitted }

[[nodiscard]] inline int Compute() {return 1;} [Ref] and Code sample int main () { Compute(); // Warning! return value of a // nodiscard function is discarded } [33 / 37] C++20

[34 / 37] Not yet (fully) implemented Much to be learned (soon)

Concepts Coroutines Ranges Modules ...

[35 / 37] www.menti.com/317wc755y5 What is the most important C++ feature?

0

[36 / 37] Thank you for your time (any questions?)

[37 / 37]