Advanced Programming Techniques (Amazing C++) 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/32rn4èy3j 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 <iostream> // 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<int n> 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<factorial(4)> 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 <class T> int *pi = new int[5]{1, 2, 3, 4, 5}; struct S { std::vector<T> v; std::string s {"hello"}; S(std::initializer_list<T> l) : v(l) { std::vector foo{1, 2}; std::cout << "constructed with a " std::map<int,std::string> bar << l.size() { {0,"zero"}, {1,"one"}, {2,"two"} }; << "-element list\n"; } f({foo, bar}); void append(std::initializer_list<T> 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 <utility> #include <iostream> 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<decltype(a), int>); static_assert(std::is_same_v<decltype(b), double>); 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<int> auto n = {5}; // OK: type of n is std::initializer_list<int> // auto e{1, 2}; // Error as of C++17, std::initializer_list<int> before auto m{5}; // OK: type of m is int as of C++17, initializer_list<int> 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 <iostream> #include <iostream> #include <array> #include <array> template <typename T, typename V> template <typename T, typename V> 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 <typename T> template <typename T> 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<int, 5> t = {0, 1, 2, 3}; std::array<int, 5> 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 <iostream> 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 <iostream> 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<class T> struct Alloc { }; static_assert(sizeof(T1) >= 2, "Type size is too small."); // error template<class T> // type-id is vector<T, Alloc<T>> static_assert(sizeof(T2) >= 2, using Vec = vector<T, Alloc<T>>; "Type size is too small."); // ok } Vec<int> v; // Vec<int> == <int, Alloc<int>> [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 <iostream> that accepts zero or more template arguments template<class T, class ...Ts> 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 T, class ...Ts> class template void print(T arg, Ts... args) { print(arg); variable template print(args...); function template parameter lists } int main() { template<class ... Types> print(1, 2.0, "Tekst", "Next text"); struct Tuple {}; } Tuple<> t0; // no arguments Tuple<int> t1; // one argument: int Tuple<int, float> 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<typename T> class A { int x; }; // primary template template<class T> class A<T*> template<typename T> { long x; }; // partial specialization using stack_v = stack<T, std::vector>; // class template with a template template parameter int main() { template<template<typename> class V> class C using stack = stack<int, std::vector>; { stack s1; V<int> y; // uses the primary template V<int*> z; // uses the partial specialization stack_v<double> s2; }; } C<A> 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 <iostream> template<bool B, class T, class F> #include <type_traits> struct conditional { typedef T type; }; #include <typeinfo> template<class T, class F> int main() { struct conditional<false, T, F> { typedef F type; }; using std::conditional<true,
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages37 Page
-
File Size-