介绍C++14的标准,也对C++17标准做一些大概介绍。通过代码示例对照解释的方式,介绍新的标准。

献良发布于2019/01/19

注脚

展开查看详情

1.Mitglied der Helmholtz-Gemeinschaft Programming in C++ Introduction to the language standard C++14 ( and a preview of C++17 ) 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre Chapter 1 Introduction 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 2 330

2. C++ ∗ Express ideas in code Specify actions to be Direct mappings of built executed by the machine in operations and types to Concepts to use when hardware thinking about what can Affordable and flexible be done abstraction mechanisms C++ is a language for developing and using elegant and efficient abstractions * Chapter 1, The C++ Programming Language, 4th Edition, Bjarne Stroustrup 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 3 330 C++ Goals General purpose: no specialization to specific usage areas No over simplification that precludes a direct expert level use of hardware resources Leave no room for a lower level language What you don’t use, you don’t pay for 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 4 330

3. Goals Express ideas directly in code Express independent ideas independently in code Represent relationships among ideas directly in code Combine ideas expressed in code freely Express simple ideas with simple code 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 5 330 Programming Styles A programming Programming styles in C++ solution should be... Procedural programming Small Data abstraction Fast Object oriented programming Correct Generic programming Readable Functional programming Maintainable C++ is not restricted to any specific programming style. Choose any combination of the above that fits best with the problem you are trying to solve. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 6 330

4. C++ in 2017 Current standard, C++14. list<pair<string,size_t>> F; Follows C++11, precedes for (auto entry : freq) F.push_back(entry); C++17, to be finalised later F.sort([](auto i, auto j) { this year. return i.second < j.second; }); Easier, cleaner and more // with C++17 ... for (auto planet : solar_system) { efficient language auto [Decln, RA] = planet.calc_coordinates(ut); // ... } 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 7 330 Compiler support for C++11/C++14 (May 2017) LLVM/clang++ : Complete (Version 3.4 and above). Useful error messages. Fast compilation. Generated binaries competitive with others. Own STL : libc++. GCC/g++ : Complete (Version 5.0 and above). Mature code base. Own STL : libstdc++. In GCC 6.1.0, C++14 became the default language standard, and using any older standard requires --std=c++98 or --std=c++11 options. Intel Compiler : Practically complete (Version 2017.1). Great optimizer. Uses system STL. Not free. IBM XLC Compiler : Usable with version 14.1. System/external STL. Not free. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 8 330

5. Course plan In this course you will ... study illustrative code and do programming exercises learn C++ according to the current language standard Essential C++ concepts Classes and class hierarchies Templates and generic programming learn to use the C++ standard library STL containers and algorithms Smart pointers, time library, random numbers, multi-threading ... learn to make graphical user interfaces for your C++ programs using Qt Quick 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 9 330 Resources Effective Modern C++: 42 Specific Ways to Improve Your Use of C++11 and C++14, Scott Meyers, ISBN 978-1491903995 The C++ Programming Language(Fourth Edition), Bjarne Stroustrup, ISBN 978-0321563842 The C++ Standard Library: A Tutorial and Reference, Nicolai M. Josuttis, ISBN 978-0-321-62321-8 C++11: Der Leitfaden für Programmierer zum neuen Standard, Rainer Grimm, ISBN 978-3-8273-3088-8 Structured Parallel Programming, Michael McCool, Arch D. Robinson, James Reinders, ISBN 978-0-12-415993-8 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 10 330

6. Online Resources http://www.cplusplus.com/reference/ http://en.cppreference.com/ http://www.qt.io http://www.threadingbuildingblocks.org https://github.com/isocpp/CppCoreGuidelines git clone https://github.com/isocpp/CppCoreGuidelines.git 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 11 330 Elementary Constructs 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 12 330

7. Getting started The first step: Hello World! Set up environment for using the a // Hello World! #include <iostream> recent version of g++. For example, int main() using environment modules: { std::cout<<"Hello, world!\n"; module load gcc/7.1.0 } Find your favourite text editor and type in the simple “hello world“ program in this slide Compile and run the program using the following commands : g++ helloworld.cc -o hello ./hello 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 13 330 Getting started Useful aliases We will use thin wrappers G and A (in $course_home/bin) for g++ and clang++, which fill in frequently used options. They are inserted into your PATH when you type module load course G is (roughly) a shorthand for g++ --std=c++14 -pedantic $* A is (roughly) a shorthand for clang++ -std=c++14 -pedantic -stdlib=libc++ $* Whichever compiler you choose to use, load the corresponding module : module load gcc/7.1.0 or module load gcc/6.3.0 or module load llvm/4.0.0 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 14 330

8. Getting started Comments on the hello world program #include <header> tells the // Hello World #include <iostream> preprocessor to include the contents int main() { of header in the current std::cout<<"Hello, world!\n"; } "translation unit" #include "somefile" searches Comments in C++ for a file called somefile and start with // and run imports its contents to the end of the line The search for headers is performed Think of std::cout in an implementation defined way. as a sink which prints what you throw at it on the screen 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 15 330 Getting started Comments on the hello world program All C++ programs must contain a unique main() function All executable code is contained either in main(), or in functions invoked directly or indirectly from main() The return value for main() is canonically an integer. A value 0 means successful completion, any other value means errors. UNIX based operating systems make use of this. In a C++ main function, the return 0; at the end of main() can be omitted. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 16 330

9. Getting started Command line arguments Main can be declared as int main // Hello xyz #include <iostream> (int argc, char *argv[]) to int main(int argc, char *argv[]) { accept parameters from the std::cout<<"Hello, "; if (argc > 1) command line std::cout <<argv[1]<< "!\n"; else The entire command line is broken } std::cout<<"world!\n"; into a sequence of character strings G hello_xyz.cc (by unquoted and unescaped white a.out bird space) and passed as the array argv The name of the program is the first string in this list, argv[0]. Therefore argc is never 0. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 17 330 The compilation process 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 18 330

10. The compilation process Exercise 1.1: By passing the additional compiler option -v to g++, recompile the hello world program and observe the logs from different stages of the compilation process. Where does the g++ search for headers ? Where does clang++ look for headers ? Try clang++ -v hello.cc and clang++ -stdlib=libc++ -v hello.cc, and observe the differences. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 19 330 Code legibility double foo(double x, int i) { Code indentation double y=1; if (i>0) { for (int j=0;j<i;++j) { Human brains are not y *= x; } made for searching { and } else if (i<0) { for (int j=0;j>i;--j) { } in dense text y /= x; } return y; } 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 20 330

11. Style double foo(double x, int i) { Code indentation double y=1; if (i>0) { for (int j=0;j<i;++j) { Indenting code clarifies y *= x; } the logic } else if (i<0) { for (int j=0;j>i;--j) { y /= x; Misplaced brackets, } } braces etc. are easier to } return y; detect 4-5 levels of nesting is sometimes unavoidable Recommendation: indent with 2-4 spaces and be consistent! 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 21 330 Style double foo(double x, int i) { Code indentation double y=1; if (i>0) { for (int j=0;j<i;++j) { Set up your editor to y *= x; } indent automatically! } else if (i<0) { for (int j=0;j>i;--j) { y /= x; Use a consistent } } convention for braces ({ } return y; and }). These are for the human reader (most often, yourself!). Be nice to yourself, and write code that is easy on the eye! 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 22 330

12. Types, variables and declarations long n_particles{1000}; // 64 bits interpreted with rules for integers const double G{6.67408e-11}; // 64 bits interpreted as a floating point number char user_choice=’y’; bool received_ngb_updates=false; A "type" defines the possible values and operations for an object An "object" is some memory holding a value of a certain type A "value" is bits interpreted according to a certain type A "variable" is a named object Every expression has a "type" A "declaration" is a statement introducing a name into the program C++ is a statically typed language 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 23 330 Types, variables and declarations Types like char, int, float, double are known as fundamental types Fundamental types can be inter-converted when possible Arithmetic operations +, −, ∗, /, as well as comparisons <, >, <=, >=, ==, ! = are defined for the fundamental types, and mapped in an obvious way to low level instructions As in many languages, = is assignment where as == is equality comparison Note how variables are "initialized" to sensible values when they are declared 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 24 330

13. Initialization Both int i=23 and int i{23} are valid initializations The newer curly bracket form should be preferred, as it does not allow "narrowing" initializations: int i{2.3}; //Compiler error The curly bracket form can also be used to initialise C++ collections: std::list<double> masses{0.511, 938.28, 939.57}; std::vector<int> scores{667,1}; // Vector of two elements, 667 and 1 std::vector<int> lows(250,0); // vector of 250 zeros The old initialisation notation with () is needed in some cases Variables can be declared anywhere in the program. So, avoid declaring a variable until you have something meaningful to store in it 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 25 330 The C++11 uniform initialisation syntax int I{20}; Variables can be initialised at // define integer I and set it to 20 string nat{"Germany"}; declaration with a suitable // define and initialise a string double a[4]{1.,22.1,19.3,14.1}; value enclosed in {} // arrays have the same syntax tuple<int,int,double> x{0,0,3.14}; // So do tuples Pre-C++11, only the = and list<string> L{"abc","def","ghi"}; // and lists, vectors etc. () notations (also double m=0.5; // Initialising with ’=’ // is ok for simple variables, but ... demonstrated in the left int k=5.3; // Allowed, although the panel) were available. // integer k stores 5, and not 5.3 int j{5.3}; // Helpful compiler error. Initialising non trivial int i{}; // i=0 vector<int> u{4,0};// u={4, 0} collections was not allowed. vector<int> v(4,0);// v={0, 0, 0, 0} Recommendation: Use {} initialisation syntax as your default. A few exceptional situations requiring the () or = syntax can be seen in the left panel. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 26 330

14. The keywords auto and decltype int sqr(int x) If a variable is initialised { return x*x; when it is declared, in such a } int main() way that its type is { char oldchoice{’u’},choice{’y’}; unambiguous, the keyword size_t i=20’000’000;//grouping in C++14 double electron_mass{0.511}; auto can be used to declare int mes[6]{33,22,34,0,89,3}; bool flag{true}; its type decltype(i) j{9}; auto positron_mass = electron_mass; The keyword decltype can auto f = sqr; // Without "auto", f can // be declared like this: be used to say "same type as //int (*f)(int)=&sqr; std::cout << f(j) << ’\n’; that one" auto muon_mass{105.6583745}; // In C++17, if somefunc() returns // tuple<string, int, double> In C++17, several variables auto [name, nspinstates, lifetime] = somefunc(serno); can be declared and } initialised together from a suitable tuple, as shown 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 27 330 Scope of variable names double find_root() Variable declarations are { if (not initialized()) init_arrays(); allowed throughout the code for (int i=0;i<N;++i) { // loop counter i defined only A scope is : // for this "for" loop. } A block of code, bounded by double newval=0; // This is ok. for (int i=0;i<N;++i) { { and } // The counter i here is a // different entity A loop or a function body if (newval < 5) { string fl{"small.dat"}; (C++17) Both if and // do something else parts of an if } newval=...; statement cout << fl << ’\n’; // Error! } Variables defined in a scope int fl=42; // ok // C++17 exist from the point of if (auto fl=filename; val < 5) { // fl is available here declaration till the end of the } else { // fl is also available here scope. After that, the name } } may be reused. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 28 330

15. Example 1.1: The programs examples/vardecl.cc, examples/vardecl2.cc and vardecl_in_if.cc demonstrate variable declarations in C++. Use g++ program.cc -o program to compile. For the last one, you will need the option -std=c++1z. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 29 330 C++ namespaces // Somewhere in the header iostream A namespace is a named namespace std { ostream cout; context in which variables, } functions etc. are defined. // In your program ... #include <iostream> The symbol :: is called the int main() { scope resolution operator. for (int cout=0;cout<5;++cout) std::cout<<"Counter="<<cout<<’\n’; using namespace blah // Above, plain cout is an integer, imports all names declared // but std::cout is an output stream // The syntax to refer to a name inside the // // defined inside a namespace is: namespace_name::identifier_name namespace blah to the } current scope. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 30 330

16. C++ namespaces // examples/namespaces.cc No name clash due to the #include <iostream> using namespace std; same name in different namespace UnitedKingdom { namespaces string London{"Big city"}; } void load_slang() {...} Functions defined inside namespace UnitedStates { namespaces need to be string London{"Small town in Kentucky"}; void load_slang() {...} accessed using the same } scope rules as variables int main() { using namespace UnitedKingdom; cout<<London<<’\n’; cout<<UnitedStates::London<<’\n’; } 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 31 330 C++ namespaces // examples/multdef/somehdr.hh Variables declared outside extern int D; bool f(int); any function are global bool g(int); // examples/multdef/file1.cc variables and live for the #include "somehdr.hh" bool f(int x) entire duration of the { return x>D; program } // examples/multdef/file2.cc #include "somehdr.hh" For non-constant variables bool g(int x) declared in a namespace { return x*x<=D; (global or not), the extern } // examples/multdef/main.cc keyword can be used to #include "somehdr.hh" int D=56; avoid multiple definitions int main() { if (f(23) or g(33)) return 1; return 0; } 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 32 330

17. Example 1.2: The files in the directory examples/multdef illustrate the need and use of the extern keyword. The global variable D is used in functions f(int) and g(int), defined in file1.cc and file2.cc. It is only given a value in main.cc, where it is defined without the extern keyword. To compile, you need to do the following steps: G -c file1.cc G -c file2.cc G -c main.cc G file1.o file2.o main.o -o multdef Check what happens if you remove the extern in the header. In C++17, you can also declare D to be ”inline“, and assign a value in the header itself. There is also need to define it explicitly in any source file. Check this! 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 33 330 unnamed namespaces // examples/unnamednsp/somehdr.hh Global variables such as D bool f(int); bool g(int); in file1.cc and // examples/unnamednsp/file1.cc // namespace { file2.cc will clash during int D=42; // } linking bool f(int x) { return x>D; They can be enclosed in } // examples/unnamednsp/file2.cc anonymous namespaces as // namespace {} shown int D=23; // } bool g(int x) The unnamed namespace is { return x*x<=D; a uniquely named } // examples/unnamednsp/main.cc namespace with internal int main() { linkage 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 34 330

18. Unnamed namespaces Example 1.3: The directory examples/unnamednsp contains the same files as examples/multdef, with unnamed namespaces enclosing the variables D in files file(1|2).cc. Comment/uncomment the namespace boundaries and try to build. With the unnamed namespaces in place, the variables in the two files are independent of each other. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 35 330 Inline namespaces and versioning namespace myl { Identifiers declared inside an inline namespace V200 { double solve(); inline namespace are } namespace V150 { automatically exported to the double solve(); } surrounding namespace, as if namespace V100 { double solve(); there was an implicit } } using namespace ... void elsewhere(){ myl::solve(); //myl::V200::solve() Useful tool for vending a myl::V150::solve(); //as it says. } library where you must support multiple versions of something 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 36 330

19. C++ namespaces: Final comments //examples/namespaces2.cc namespaces can be nested. #include <iostream> namespace UnitedKingdom In C++17, direct nested { std::string London{"Big city"}; declarations are allowed. } namespace UnitedStates { Long namespace names can namespace KY { std::string London{" in Kentucky"}; be given aliases } namespace OH { Tip1: Don’t indiscriminately std::string London{" in Ohio"}; } put using namespace ... } // With C++17 ... tags, especially in headers. namespace mylibrary::onefeature { double solve(int i); Tip2: The purpose of } int main() namespaces is to avoid { namespace USOH=UnitedStates::OH; name clashes. Not std::cout<<"London is" <<USOH::London<<’\n’; taxonomy! } 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 37 330 Preprocessor directives Example 1.4: The program examples/bits_in_int.cc counts the number of 1 bits in the binary representation of the numbers you enter. Compile and run to check. Then use the C preprocessor cpp to process the file. The output is what the compiler receives. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 38 330

20. Preprocessor directives #include <iostream> Processed before the unsigned char n_on_bits(int b) { compiler checks language #define B2(n) n, n+1, n+1, n+2 #define B4(n) B2(n), B2(n+1), \ syntax B2(n+1), B2(n+2) #define B6(n) B4(n), B4(n+1), \ #define pat sub B4(n+1), B4(n+2) const unsigned char tbl[256] { B6(0), B6(1), B6(1), B6(2) }; substitutes any occurrence of #undef B6 pat in the source with sub return tbl[b & 0xff] + tbl[(b>> 8) & 0xff] + Definitions valid until tbl[(b>>16) & 0xff] + tbl[(b>>24) & 0xff]; #undef. Scoping rules of the } int main() language do not apply. { #ifdef B6 Uses: reduce code text, #error B6 should not be defined! #endif tailored compiler errors, hints ... to the compilers (e.g. #pragma) 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 39 330 Compile time assertions double advance(unsigned long L) { static_assert(sizeof(L)>=8,"long type must be at least 8 bytes)"); //Bit manipulation assuming "long" is at least 8 bytes } Prints the second argument as an error message if the first argument evaluates to false. Express assumptions clearly, so that the compiler notifies you when they are violated In C++17, you can leave out the message parameter 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 40 330

21. The type bool bool debugging=false; Possible values true or ... if (debugging) { false std::cout<<"additional messages.\n"; } Can be converted back and forth from integer types 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 41 330 C-style enumerations enum color { red, green, blue }; A type whose instances can using rgbtype = array<float, 3>; rgbtype adjust(rgbtype rgb) take a few different values { float factors[3]{0.8,1.0,0.93}; (e.g., directions on the rgb[red] *= factors[red]; rgb[green] *= factors[green]; screen, colours, supported rgb[blue] *= factors[blue]; return rgb; output modes ...) } Less error prone than using integers with ad hoc rules like, ”1 means red, 2 means green ...“ Internally represented as (and convertible to) an integer All type information is lost upon conversion into an integer 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 42 330

22. Scoped enumerations Defined with enum class enum class color { red, green, blue }; enum class traffic_light { Must always be fully qualified }; red,yellow,green when used: bool should_brake(traffic_light c); traffic_light::red etc. if (should_brake(blue)) apply_brakes(); //Syntax error! if (state==traffic_light::yellow) ...; No automatic conversion to int. Possible to use the same name, e.g., green, in two different scoped enums. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 43 330 Pointers and references int i{5}; A pointer is an integral type int * iptr{&i}; // iptr points at i i+=1; to store the memory address std::cout << *iptr ; // 6 (*iptr)=0; of objects std::cout << i ; // 0 int & iref{i}; // iref "refers" to i iref=4; If iptr is a pointer, *iptr is std::cout << i ; // 4 the object it is pointing at For a variable X, its memory address can be obtained using &X A reference is a restricted pointer which must always point at the same object When in use, a reference appears as if it were a regular variable 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 44 330

23. C++ standard library strings #include <string> Character strings ... std::string fullname; std::string name{"Albert"}; String of characters std::string surname{"Einstein"}; //Concatenation and assignment Knows its size (see example) fullname=name+" "+surname; Allocates and frees memory //Comparison if (name=="Godzilla") run(); as needed std::cout<<fullname<<’\n’; No need to worry about \0 for (size_t i=0;i<fullname.size();++i) { if (fullname[i]>’j’) blah+=fullname[i]; Can contain \0 in the middle } Simple syntax for assignment (=), concatenation(+), Don’t use C style strings! comparison (<,==,>) 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 45 330 C++ strings #include <ctype.h> #include <iostream> #include <stdio.h> #include <string> #include <string.h> int main() #include <stdlib.h> { int main() std::string name, bkpname; { std::cout << "What is your name ? "; char name[100], *bkpname; std::getline(std::cin,name); int nmsize,i; if (not name.empty()) { printf("What is your name ? "); bkpname = name; if ( fgets(name,100,stdin) ) { for (int i=0;i<name.size();++i) { nmsize = strlen(name); name[i]=toupper(name[i]); bkpname = (char *) malloc((nmsize+1)* } sizeof(char)); std::cout<<bkpname<<" <--> " bkpname = strdup(name); <<name<<"\n"; for (i=0;i<nmsize;++i) { } name[i]=toupper(name[i]); } } printf("%s <--> %s\n",bkpname,name); } if (bkpname) free(bkpname); Cleaner, easier to maintain return 0; } code using C++ strings. Did you notice the memory leak in the C code ? 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 46 330

24. Raw string literals // Instead of ... string message{"The tag \"\\maketitle\" is unexpected here."}; // You can write ... string message{R"(The tag "\maketitle" is unexpected here.)"}; Can contain line breaks, ’\’ characters without escaping them Very useful with regular expressions Starts with R"( and ends with )" More general form R"delim( text )delim" Example 1.5: The file examples/rawstring.cc illustrates raw strings in use. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 47 330 Exercise 1.2: The file exercises/raw1.cc has a small program printing a message about using the continuation character ’\’ at the end of the line to continue the input. Modify using raw string literals. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 48 330

25. Converting to and from strings std::cout << "integer : "<<std::to_string(i) << ’\n’; tot+=std::stod(line); // String-to-double The standard library string class provides functions to inter-convert with variables of type int, double Akin to atoi,strtod and using sprintf Example 1.6: Test example usage of string↔number conversions in examples/to_string.cc and examples/stoX.cc 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 49 330 Arrays double A[10]; // C-style array Fixed length C-style arrays int sz; std::cin >> sz; exist, but do not know their int M[sz]; // Not allowed! // Since C++11 ... own size #include <array> ... std::array<double,10> A; // On stack Variable length arrays of C99 // Like the C-style array, but obeys // C++ standard library conventions. are illegal in C++, although for (size_t i=0;i<A.size();++i) { P*=A[i]; tolerated with warnings in } many compilers std::vector<double> B(sz,3.0); std::array<type,size> is a compile-time fixed length array obeying STL conventions std::vector<type> is a dynamically allocated resizeable array type 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 50 330

26. Branches/Selections if (condition) { The if and switch // code } else if (another condition) { constructs can be used to // code } else { select between different //code } alternatives at execution switch (enumarable) { case 1: time. // code break; case 2: Conditional assignments are // code frequently written with the break; default: ternary operator as shown // code }; x = N>10 ? 1.0 : 0.0; 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 51 330 Loops for (initialisation;condition;increment){ Execute a block of code // Loop body } repeatedly for (int i=0;i<N;++i) s+=a[i]; while (condition) {} while (T>t0) {} Loop counter for the for do {} while (condition); do { loop can and should usually } while (ch==’y’); for (variable : collection) {} be declared in the loop head for (int i : {1,2,3}) f(i); for (int i=0;i<N;++i) { The break keyword in a loop if (a[i]<cutoff) s+=a[i]; else break; immediately stops the loop } for (std::string s : names) { and jumps to the code if (s.size()>10) { longnames.push_back(s); following it continue; } The continue keyword skips // process other names } all remaining statements in the current iteration, and continues in the loop 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 52 330

27. Exercise 1.3: What is the largest number in the Fibonacci sequence which can be represented as a 64 bit integer ? How many numbers of the sequence can be represented in 64 bits or less ? Write a C++ program to find out. Use only concepts presented so far. Exercise 1.4: Finish the program exercises/gcd.cc so that it computes and prints the greatest common divisor of two integers. The following algorithm (attributed to Euclid!) achieves it : 1 Input numbers : smaller , larger 2 remainder = larger mod smaller 3 larger = smaller 4 smaller = remainder 5 if smaller is not 0, go back to 2. 6 larger is the answer you are looking for 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 53 330 Range based for loops // Instead of ... //for (size_t i=0;i<fullname.size();++i) { // if (fullname[i]>’j’) blah+=fullname[i]; //} // you could write ... for (auto c : fullname) if (c>’j’) blah+=c; // Loop over a linked list ... std::list<double> L{0.5,0.633,0.389,0.34,0.01}; for (auto d : L ) { std::cout << d << ’\n’; } Anything that has a begin and an end Iteration over elements of a collection Use on strings, arrays, STL lists, maps ... 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 54 330

28. Range based for loops // Loop over a small list of names ... for (auto day : { "Monday", "Tuesday", "Wednesday","Thursday","Friday"}) { std::cout << day << ’\n’; } // or a list of non contiguous integers ... for (auto i : { 1,1,2,3,5,8,13,21 }) { std::cout << Recs[i] << ’\n’; } Anything that has a begin and an end collections which provide a begin() and end() functions ... or which work well with global begin() and end() functions 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 55 330 Example 1.7: You will find two tiny example programs examples/loop.cc and examples/loop2.cc to demonstrate the range based for loops. Modify the code to write out an array of strings. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 56 330

29. Functions return_type function_name(parameters) All executable code is in { // function body functions } double sin(double x) { Logically connected reusable // Somehow calculate sin of x return answer; blocks of code } int main() A function must be called { constexpr double pi{3.141592653589793}; with values called arguments. for (int i=0;i<100;++i) { std::cout << i*pi/100 The type of the arguments << sin(i*pi/100) <<"\n"; } must match or be implicitly std::cout << sin("pi") <<"\n"; //Error! } convertible to the corresponding type in the function parameter list 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 57 330 Functions: Syntax // A function prototype A function prototype bool pythag(int i, int j, int k); // and a function definition introduces a name as a int hola(int i, int j) { function, its return type as int ans{0}; if (pythag(i,j,23)) { well as its parameters // A prototype or definition must be // visible in the translation unit // at the point of usage Functions can live freely ans=42; } C++11 introduced an return ans; } alternative syntax with the // Definition of pythag bool pythag(int i, int j, int k) return type coming after the { // code parameters (last example in } // Trailing return type (since C++11) the left panel) auto f(double x, double y)->double { // function body } 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 58 330

30. Functions at run time When a function is called, it is given a "workbook" in memory called a stack frame Argument values are copied double sin(double x) to the stack frame, and a { // Somehow calculate sin of x return address is stored. return answer; } (Non-static) local variables int main() { are allocated in the stack constexpr double pi{3.141592653589793}; for (int i=0;i<100;++i) { frame std::cout << i*pi/100 << sin(i*pi/100) <<"\n"; When the function concludes, } std::cout << sin("pi") <<"\n"; //Error! execution continues at the } stored return address, and the stack frame is destroyed 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 59 330 Recursion SP=<in factorial()> n=1 u=1 RP=<4> SP=<in factorial()> n=2 u=2 RP=<4> A function calling itself SP=<in factorial()> n=3 u=3 RP=<4> SP=<in factorial()> n=4 u=4 RP=<9> Each level of "recursion" has SP=<in someother()> RP=<...> its own stack frame 1 unsigned int factorial(unsigned int n) Function parameters are 2 { 3 int u=n; // u: Unnecessary copied to the stack frame 4 if (n>1) return n*factorial(n-1); 5 6 } else return 1; Local variables at different 7 8 int someother() { levels of recursion live in 9 10 } factorial(4); their own stack frames, and do not interfere 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 60 330

31. Example 1.8: The tower of Hanoi is a mathematical puzzle with three towers and a set of disks of increasing sizes. At the beginning, all the disks are at one tower. In each step, a disk can be moved from one tower to another, with the rule that a larger disk must never be placed over a smaller one. The example examples/honoi.cc solves the puzzle for a given input number of disks, using a recursive algorithm. Test the code and verify the solution. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 61 330 static variables in functions void somefunc() Private to the function, but { static int ncalls=0; survive from call to call. ++ncalls; // code --> something unexpected std::cerr << "Encountered unexpected" Initialisation only done on << "situation in the " << ncalls << "th call to " << __func__ << "\n"; first call. } Aside: The built in macro __func__ always stores the name of the function 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 62 330

32. Function overloading int power(int x, unsigned int n) double someother(double mu, { double alpha, ans=1; int rank) for (;n>0;--n) ans*=x; { return ans; double st=power(mu,alpha)*exp(-mu); } if (n_on_bits(power(rank,5))<8) double power(double x, double y) st=0; { return exp(y*log(x)); return st; } } The same function name can be used for different functions if the parameter list is different Function name and the types of its parameters are combined to create an "internal" name for a function. That name must be unique It is not allowed for two functions to have the same name and parameters and differ only in the return value 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 63 330 inline functions double sqr(double x) inline double sqr(double x) { { return x*x; return x*x; } } When function call overhead matters To eliminate overhead when a function is called, request the compiler to insert the entire function body where it is called Very small functions which are called very frequently Only a request to the compiler! Different popular use: define the entire function (even if it is large) in the header file, as identical inline objects in multiple translation units are allowed. (E.g. header only libraries) 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 64 330

33. Exercise 1.5: Why not simply use macros rather than bothering with inline functions ? Check the program exercises/inlining.cc and compare the inlined version of sqr and the corresponding macro. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 65 330 Function return values as auto Automatic type deduction auto greet(std::string nm) { methods of C++14 can be for (auto & c: nm) c=std::toupper(c); std::cout << nm << std::endl; used for the return values in return nm.size()>10; } function definitions Return type ambiguity will be a compiler error in such Exercise 1.6: situations The program exercises/autoret.cc decltype(auto) can also be used like auto for the illustrates the use of auto as return type, along with the the function return type. What different type deduction rules happens if you have multiple which apply for return statements ? decltype(auto) 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 66 330

34. The type qualifier const const double pi{3.141592653589793}; Can not be changed after const unsigned int n_3d_ngb{26}; initialisation int cell[n_3d_ngb]; const double BL=optimal_length(); // OK Compilers and debuggers BL=0.8*BL; //Compiler error know their type, unlike in the case of macros They can be used as the size of C-style arrays on the stack, if obviously known at compile time 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 67 330 The constexpr keyword constexpr double b=13.2; constexpr double r=1.08; constexpr double a=6*r*r*r*r-5*r*2*b; constexpr unsigned fact(unsigned N) { return N<2?1:N*fact(N-1); } int f() { int indexes[fact(4)]; constexpr is used to declare that something is possible to evaluate at compile time Compiler can optimize more, because of compile time evaluations Non-trivial calculations can be done at compile time using constexpr Integers of type constexpr can be array sizes 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 68 330

35. Exercise 1.7: constexpr The program exercises/constexpr0.cc demonstrates the use of constexpr functions. How would you verify that it is really evaluated at compile time ? Try to compile in the following cases: The code as is. After uncommenting the line with a static_assert Keeping the static assert, but giving it the correct value to check against Keeping the static assert with the correct value, removing the constexpr from the function replacing the constexpr with a const in the function 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 69 330 Restrictions on functions declared constexpr Must be "pure" functions. Can not alter global state. For C++11: Must consist of a single return statement Can not contain loops or temporary local variables, loops or if statements C++14 introduced multi-line constexpr functions with loops, local variables and branches. Exercise 1.8: constexpr The file exercises/constexpr1.cc has essentially the same code as in the previous exercise, but replaces the constexpr function with one that uses a loop and a local variable. Check that it behaves as expected in C++14, but not with C++11. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 70 330

36. Input and output std::cout and std::cin To read user input into variable x, simply write std::cin>>x; To read into variables x,y,z,name and count std::cin >> x >> y >> z >> name >> count; std::cin will infer the type of input from the type of variable being read. For printing things on screen the direction for the arrows is towards std::cout: std::cout << x << y << z << name << count << ’\n’; 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 71 330 Reading and writing files Include fstream Declare your own source/sink objects, which will have properties like std::cout or std::cin #include <fstream> ... std::ifstream fin; std::ofstream fout; Connect them to file names fin.open("inputfile"); fout.open("outputfile"); Use them like std::cout or std::cin double x,y,z; int i; std::string s; fin >> x >> y >> z >> i >> s; fout << x << y << z << i << s << ’\n’; 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 72 330

37. Exercise 1.9: Strings and I/O Write a simple program to find the largest word in a plain text document. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 73 330 Heap vs stack double f(double x) Variables in a function are { int i=(int) x; // stack variable allocated on the stack, but double M[1000][1000][1000]; // Oops! M[123][344][24]=x; sometimes we need more return x-M[i][555][1]; } space than what the stack int main() { permits std::cout << f(5) << "\n"; } // Immediate SEGFAULT We do not know how much space we should reserve for a variable (e.g. a string) We need a way to allocate from the "free store" 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 74 330

38. Heap vs stack The pointer A is still on the stack. But it holds the address of memory allocated by the new operator on the "heap" void f() { int *A = new int[1000000]; Memory allocated from the // use A delete [] A; heap stays with your program } until you free it, using delete Note: Heap allocation and deallocation are slower than If you forget the address of those on the stack! Don’t put the allocated memory, you everything on the heap. have a memory leak 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 75 330 Object lifetime management with smart pointers Smart pointers in C++ 3 kinds of smart pointers were introduced in C++11: unique_ptr, shared_ptr, and weak_ptr unique_ptr claims exclusive ownership of the allocated array. When it runs out of its scope, it calls delete on the allocated resource. It is impossible to ”forget“ to delete the memory owned by unique_ptr Several instances of shared_ptr may refer to the same block of memory. When the last of them expires, it cleans up. Helper functions make_unique and make_shared can be used to allocate on heap and retrieve a smart pointer to the allocated memory 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 76 330

39. Dynamic memory with smart pointers using big = std::array<int, 1000000>; int f() { auto u1=std::make_unique<big>(); // use u1 } // u1 expires, and frees the allocated memory Current recommendation: avoid free new/delete calls in normal user code Use them to implement memory management components Use unique_ptr and shared_ptr to manage resources You can then assume that an ordinary pointer in your code is a ”non-owning“ pointer, and let it expire without leaking memory 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 77 330 Memory allocation/deallocation You don’t need it often: std::string takes care of itself Using standard library containers like vector, list, map, deque even rather complicated structures can be created without explicit memory allocation and de-allocation. When you nevertheless must (first choice): auto c = make_unique<complex_number>(1.2,4.2); // on the heap int asize=100; // on the stack auto darray = make_unique<double[]>(asize); // The stack frame contains the unique_ptr variables c and darray. // The memory locations they point to on the other hand, are not // on the stack, but on the heap. But, you don’t need to worry about // releasing that memory explicitly. If you don’t have any way of // accessing the resource (the pointers expire), the memory will be // freed for you. // 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 78 330

40. Memory allocation/deallocation You don’t need it often: std::string takes care of itself Using standard library containers like vector, list, map, deque even rather complicated structures can be created without explicit memory allocation and de-allocation. When you nevertheless must (second choice): complex_number *c = new complex_number{1.2,4.2}; // on the heap int asize=100; // on the stack double *darray = new double[asize]; // The stack frame contains the pointer variables c and darray // The memory locations they point to on the other hand, are not // on the stack, but on the heap. Unless you release that memory // explicitly, before the stack variables expire, there will be // a memory leak. delete c; delete [] darray; 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 79 330 Evaluation order 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 80 330

41. Sub-expression evaluation Guess the output! int i=0; std::cout << ++i <<’\t’<< i <<’\t’ << i++ <<"\n"; clang++ prints 1 1 1 g++ prints 2 2 0 although both parse it as cout.operator<<(exp1).operator<<(’\t’).operator<<(i).operator<<(’\t’).operator (exp2).operator("\n"); 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 81 330 Sub-expression evaluation a = i+j*k; A statement or expression in C++ ends with a semi-colon ";" An expression may be parsed as a tree of subexpressions Subexpression evaluation order is governed by well-defined, but non-trivial rules 1 1 http://en.cppreference.com/w/cpp/language/eval_order 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 82 330

42. Sub-expression evaluation I std::cout << ++i <<’\t’<< i <<’\t’ << i++ <<"\n"; // clang++ prints 1 1 1, g++ prints 2 2 0 although both parse it as // cout.op<<(exp1).op<<(’\t’).op<<(i).op<<(’\t’).op(exp2).op("\n"); 1 Each value and side-effect of a full expression is sequenced before those of the next full expression 2 Value computations (but not side effects!) of operands to an operator are sequenced before the value computation of the result of the operator 3 Every value and side-effect evaluation of all arguments of a function are sequenced before the function body 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 83 330 Sub-expression evaluation II 4 Value calculations of built-in post increment (i++) and post decrement (i--) operators are sequenced before their side effects 5 Side effect calculations of built-in pre-increment (++i) and pre-decrement (--i) operators are sequenced before their values 6 For built-in logical AND and OR operators (&& and ||) the value as well as side effects of the LHS are sequenced before those of the RHS 7 For cond?then:otherwise ternary operator, value computation of cond is sequenced before both value and side effects of the then and otherwise 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 84 330

43. Sub-expression evaluation III 8 Modification of the LHS in an assignment operation is sequenced after the value calculation of both LHS and RHS, but ahead of the value calculation of the whole assignment expression 9 Every value and side effect calculation of the LHS of a built-in comma operator, such as in for (i=L.begin(),j=i;i!=L.end();++i,++j) is sequenced before those of the RHS 10 In comma separated initializer lists, value and side effects of each initializer is sequenced before those of the initializers to its right 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 85 330 Evaluation order: examples i = ++i + i++; // undefined behaviour i = i++ + 1; // undefined behaviour, although i= ++i +1 is well defined f(++i,++i); // undefined behaviour std::cout << i <<’ ’<<i++<<’\n’; // undefined behaviour! a[i]=i++; // undefined behaviour! Example 1.9: Beware of unsequenced operations! The file examples/unsequenced.cc illustrates all the above examples and comma separated initializer lists. Compilers go give warnings in this kind of simple situations. Use both the GNU and clang compilers to compile the program, and compare the behaviour. Keep this example in mind and avoid ill structured code like this. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 86 330

44. Error handling 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 87 330 Run-time error handling When there is nothing reasonable to return double f(double x) { Exceptions double answer=1; if (x>=0 and x<10) { while (x>0) { answer*=x; A function may be called } x-=1; with arguments which } else { // the function is undefined don’t make sense } return answer; An illegal mathematical // should we really return anything // if the function went into operation // the "else"? } Too much memory might have been requested. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 88 330

45. When there is nothing reasonable to return #include <stdexcept> try { std::cout<<"Enter start point : "; double f(double x) std::cin >> x; { std::cout<<"The result is " double answer=1; <<f(x)<<’\n’; if (x>=0 and x<10) { } catch (std::domain_error ex) { while (x>0) { std::cerr<<ex.what()<<’\n’; answer*=x; } x-=1; } } else { throw std::domain_error("Value "+ Enclose the area where an std::string(x)+" is out of range"); } exception might be return answer; } thrown in a try block In case the error happens, control shifts to the catch block 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 89 330 Assertions #include <cassert> assert(condition) aborts bool check_things() { if condition is false // false if something is wrong } // true otherwise Used for non-trivial checks in double somewhere() { code during development. // if I did everything right, // val should be non-negative The errors we are trying to assert(val>=0); assert(check_things()); catch are logic errors in } implementation. If the macro NDEBUG is After we are satisfied that defined before including the program is correctly <cassert> implemented, we can pass assert(condition) -DNDEBUG to the compiler, reduces to nothing and skip all assertions. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 90 330

46. Exercise 1.10: The program exercises/exception.cc demonstrates the use of exceptions. Rewrite the loop so that the user is asked for a new value until a reasonable value for the function input parameter is given. Exercise 1.11: Handle invalid inputs in your gcd.cc program so that if we call it as gcd apple orange it quits with an understandable error message. Valid inputs should produce the result as before. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 91 330 Chapter 2 C++ abstraction mechanisms 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 92 330

47. C++ classes struct Vector3 { Use defined data types double x,y,z; inline double dot(Vector3 other) { Identifies a concept return x*other.x + y*other.y + Encapsulates the data needed z*other.z; } to describe it }; Specifies how that data may void somefunc() { be manipulated int a, b, c; // On the stack Vector3 d,e,f; // On the stack // ... Objects of user defined types } if (d.dot(e)<d.dot(f)) doX(); can live on the stack 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 93 330 C++ classes Functions, relevant for the concept, can be declared inside the struct : struct complex_number Data and function members { double real, imaginary; double modulus() A (non-static) member { return sqrt(real*real+ function is invoked on an } imaginary*imaginary); instance of our structure. }; ... a.real is the real part of a. complex_number a{1,2},b{3,4}; double c,d; a.modulus() is the ... c=a.modulus();//1*1+2*2 modulus of a. d=b.modulus();//3*3+4*4 Inside a member function, member variables correspond to the invoking instance. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 94 330

48. C++ classes A member function can take arguments like any other function. struct complex_number Data members of the { complex_number add(complex_number b) function arguments need to { return complex_number(real+b.real, be addressed with the "." imaginary+b.imaginary); } operator // with C++11 ... complex_number subt(complex_number b) { Probably a better way to return {real-b.real, imaginary-b.imaginary}; "pronounce" the a.add(b) } is "sum of a with b" }; ... complex_number a(0,0),b(0,0),c(1,1); ... c=a.add(b); 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 95 330 Defining member functions outside the struct struct complex_number { complex_number add(complex_number b); }; complex_number complex_number::add(complex_number b) { return {real+b.real,imaginary+b.imaginary}; } If the function body is more than a line, for readability, it is better to only declare the function in the struct In such a case, when the function is defined, the scope resolution operator :: has to be used to specify that the function belongs with the structure. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 96 330

49. Member functions’ promise to not change object struct complex { Member functions have an double m_real, m_imag; double modulus(); implicit argument: the calling complex sub(const complex b); }; instance, through the this void somewhere_else() pointer. Where do we put a { complex z1,z2; const qualifier, if we want z1.sub(z2); // We know z2 didn’t change. to express that the calling // But did z1 ? } instance must not change ? 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 97 330 Member functions’ promise to not change object struct complex { Member functions have an double m_real, m_imag; double modulus(); implicit argument: the calling complex sub(const complex b) const; }; instance, through the this void somewhere_else() pointer Where do we put a { complex z1,z2; const qualifier, if we want z1.sub(z2); // We know z2 didn’t change. to express that the calling // We know z1 didn’t change, // as we called a const member instance must not change ? } Answer: After the closing parentheses of the function signature. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 98 330

50. Overloading member functions struct complex_number Member functions can { complex_number multiply(complex_number b) and often are { return {real*b.real-imaginary*b.imaginary, overloaded real*b.imaginary+imaginary*b.real}; } complex_number multiply(double d) Member functions can { return {d*real, d*imaginary}; be accessed from a }; } pointer to an object ... using -> instead of . : complex_number a{0.33,0.434}; complex *b=new complex{3,4} b->multiply(c) double c; ... means a=b->multiply(c); (*b).multiply(c) 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 99 330 Operator overloading Defining new actions for the operators struct complex_number { complex_number operator+(complex_number b); // instead of complex_number add(complex_number b); }; complex_number complex_number::operator+(complex_number b) { return {real+b.real, imaginary+b.imaginary}; } ... complex_number a,b,c; ... c=a+b; // means a.operator+(b); Operators like +, −, ∗, /, <<, >>, |, ... are functions with a special calling syntax 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 100 330

51. Exercise 2.1: The file complex_numbers.cc contains a short implementation of a complex number type, with the syntax discussed up to this point. Change the member functions doing the mathematical operations into operators, and modify their usage in the main function. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 101 330 Some example classes class Angle { class IsingLattice { double rd = 0; public: public: using update_type = std::pair<size_t, enum unit { size_t>; radian, IsingLattice(); degree IsingLattice(size_t Nx, double JJ); }; void setLatticeSize(size_t ns); Angle operator-(Angle a) const ; Angle operator+(Angle a) const ; Angle operator-=(Angle a) ; class KMer { public: Nucleotide at(size_t i); class Vector3 bool operator==(const KMer &); { public: enum crdtype {cartesian=0,polar=1}; inline double x() const {return dx;} class SimulationManager { inline void x(double gx) {dx=gx;} public: double dot(const Vector3 &p) const; void loadSettings(std::string file); Vector3 cross(const Vector3 &p) const; bool checkConfig(); void start(); 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 102 330

52. Datatypes Type Bits Value Float 0100 0000 0100 1001 0000 1111 1101 1011 3.1415927 Int 0100 0000 0100 1001 0000 1111 1101 1011 1078530011 Same bits, different rules =⇒ different type From arbitrary collection of members to a new “data type” class Date { Make sure every way to int m_day, m_month, m_year; public: create an object results in a static Date today(); Date operator+(int n) const; valid state Date operator-(int n) const; }; int operator-(const Date &) const; Provide only those operations on the data which keep the essential properties intact 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 103 330 C++ classes: user defined data types struct Vector3 { "Nouns" important in double x,y,z; inline double dot(Vector3 other) expressing ideas about the { return x*other.x + problem being solved are y*other.y + z*other.z; candidates to become classes } }; struct complex_number { Need not be profound and double realpart, imagpart; double modulus(); universally usable. If it helps // etc. solving a problem clearly and }; // But also, efficiently, write it. struct Cat { }; // If it helps solve your problems struct HonoiTower { Use namespaces and local }; // To represent disks on one tower classes to avoid name conflicts 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 104 330

53. Object creation: constructors In C++, initialisation functions for a struct have the same name as the struct. They are called constructors. struct complex_number { complex_number(double re, double im) { real=re; imaginary=im; } }; Alternative syntax to initialise variables in constructors struct complex_number { complex_number(double re, double im) : real{re}, imaginary{im} {} }; A structure can have as many constructors as it needs. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 105 330 Constructors struct complex_number Constructors may be (and { complex_number(double re, double im) normally are) overloaded. { real=re; imaginary=im; When a variable is declared, } complex_number() a constructor with the { real=imaginary=0; appropriate number of } double real,imaginary; arguments is implicitly called }; ... The default constructor is the complex_number a(3.2,9.3); // C++11 and older one without any arguments. complex_number b{4.3,1.9}; // C++11 That is the one invoked when no arguments are given while creating the object. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 106 330

54. Constructors struct complex_number In C++11, member variables { complex_number(double re, double im) can be initialised to "default { real=re; values" at the point of imaginary=im; } declaration complex_number() {} double real = 0; // C++11 or later! double imaginary = 0; Member variables not }; ... touched by the constructor complex_number a(4.3,23.09),b; stay at their default values 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 107 330 Freeing memory for user defined types struct darray { What happens to the memory ? double *data=nullptr; size_t sz=0; darray(size_t N) : sz{N} { The struct darray has a pointer } data = new double[sz]; member, which points to }; dynamically allocated memory double tempfunc(double phasediff) { When the life of the variable A // find number of elements darray A{large_number}; ends the member variables (e.g. // do some great calculations return answer; the pointer data) go out of } scope. How does one free the dynamically allocated memory attached to the member data ? 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 108 330

55. Freeing memory for user defined types struct darray For any struct which explicitly { allocates dynamic memory double *data=nullptr; size_t sz=0; darray(size_t N) : sz{N} { We need a function that cleans } data = new double[sz]; up all explicitly allocated ~darray() { if (data) delete [] data; memory in use. Such functions }; } are called destructors, and have double tempfunc(double phasediff) the name ~ followed by the { // find number of elements struct name. darray A{large_number}; // do some great calculations Destructors take no arguments, return answer; } and there is exactly one for each struct The destructor is automatically called when the variable expires. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 109 330 Copying and assignments struct complex_number { What values should the double x, y; }; members get ? //... complex_number z0{2.0,3.0},z1; z1=z0; // assignment operator complex_number z2{z0}; //copy constructor In most cases, we want to assign the data members to the corresponding members This happens automatically, but using special functions for these copy operations You can redefine them for your class Why would you want to ? 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 110 330

56. Copying and assignments class darray { double *x; }; darray::darray(unsigned n) { x=new double[n]; } void foo() { darray ar1(5); darray ar2{ar1}; //copy constructor ar2[3]=2.1; //oops! ar1[3] is also 2.1 now! } //trouble Copying pointers with dynamically allocated memory May not be what we want Leads to "double free" errors when the objects are destroyed 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 111 330 Copying and assignments class darray { len=other.len; double *x=nullptr; if (x) delete [] x; unsigned int len=0; x= new double[len]; public: } // Copy constructor for (unsigned i=0;i<len;++i) { darray(const darray &); x[i]=other.x[i]; //assignment operator } darray & operator=(const darray &); } }; return *this; darray::darray(const darray & other) } { if (other.len!=0) { len=other.len; x = new double[len]; for (unsigned i=0;i<len;++i) { x[i]=other.x[i]; } } } darray & darray::operator=(const darray & other) { if (this!=&other) { if (len!=other.len) { 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 112 330

57. Move constructor/assignment operator class darray { darray(darray &&); //Move constructor darray & operator=(darray &&); //Move assignment operator }; darray::darray(darray && other) { len=other.len; x=other.x; other.x=nullptr; } darray & darray::operator=(darray && other) { len=other.len; x=other.x; Construct or assign from an other.x=nullptr; R-value reference return *this; } (darray &&) darray d1(3); init_array(d1);//d1={1.0,2.0,3.0} darray d2{d1};//Copy construction Steal resources from RHS // d1 and d2 are {1.,2.,3.} darray d3{std::move(d1)}; //Move Put disposable content in // d3 is {1.,2.,3.}, but d1 is empty! RHS 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 113 330 Move constructor/assignment operator You can enable move semantics for your class by writing a constructor or assignment operator using an R-value reference Usually you will not be using it explicitly You can invoke the move constructor by casting the function argument to an R-value reference, e.g. darray d3{std::move(d1)} 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 114 330

58. Big five (or zero) Default constructor How many of these do you Copy constructor have to write for each and every class you make ? Move constructor Answer: None! If you don’t Assignment operator have bare pointers in your Move assignment operator class, and don’t want anything fancy happening, the compiler will auto-generate reasonable defaults. “Rule of zero” 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 115 330 Big five class cnumber { public: cnumber(double x, double y) : re{x}, im{y} {} cnumber() = default; cnumber(const cnumber &) = default; cnumber(cnumber &&) = default; cnumber & operator=(const cnumber &) = default; cnumber & operator=(cnumber &) = default; }; If you have to write any constructor yourself, auto-generation is disabled But you can request default versions of the rest of these functions as shown 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 116 330

59. Big five class darray { darray() = delete; darray(const cnumber &) = delete; darray(cnumber &&) = default; darray & operator=(const cnumber &) = delete; darray & operator=(cnumber &) = default; }; You can also explicitly request that one or more of these are not auto-generated In the example shown here, it will not be possible to copy objects of the class, but they can be moved 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 117 330 Copy and swap We want to reuse the code in darray & operator=(darray d) { swap(d); the copy constructor and return *this; } destructor to do memory // No further move assignment operator! management Pass argument to the Neat trick that works in most assignment operator by value cases instead of reference Reduces the big five to big Use the class member four function swap to swap the data with the newly created copy 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 118 330

60. Public and private members Separating interface and implementation int foo(complex_number a, int p, truck c) { complex_number z1,z2,z3=a; ... z1=z1.argument()*z2.modulus()*z3.conjugate(); c.start(z1.imaginary*p); } Imagine that ... We have used our complex number structure in a lot of places Then one day, it becomes evident that it is more efficient to define the complex numbers in terms of the modulus and argument, instead of the real and imaginary parts. We have to change a lot of code. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 119 330 Public and private members Separating interface and implementation int foo(complex_number a, int p, truck c) { complex_number z1,z2,z3=a; ... z1=z1.argument()*z2.modulus()*z3.conjugate(); c.start(z1.imaginary*p); } Imagine that ... External code calling only member functions can survive Direct use of member variables while using a class is often messy, the implementer of the class then loses the freedom to change internal organisation of the class for efficiency or other reasons 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 120 330

61. C++ classes class complex_number Members declared under the { public: keyword private can not be complex_number(double re, double im) : m_real(re), m_imag(im) {} accessed from outside complex_number() = default; double real() const {return m_real;} double imag() const {return m_imag;} Public members (data or ... private: function) can be accessed double m_real=0,m_imag=0; }; Provide a consistent and useful interface through public functions Keep data members hidden Make accessor functions const when possible 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 121 330 Exercise 2.2: The program exercises/complex_number_class.cc contains a version of the complex number class, with all syntax elements we discussed in the class. It is heavily commented with explanations for every subsection. Please read it to revise all the syntax relating to classes. Write a main program to use and test the class. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 122 330

62. Constructor/destructor calls Exercise 2.3: The file exercises/verbose_ctordtor.cc demonstrates the automatic calls to constructors and destructors. The simple class Vbose has one string member. All its constructors and destructors print messages to the screen when they are called. The main() function creates and uses some objects of this class. Follow the messages printed on the screen and link them to the statements in the program. Does it make sense (i) When the copy constructor is called ? (ii) When is the move constructor invoked ? (iii) When the objects are destroyed ? Suggested reading: http://www.informit.com/ articles/printerfriendly/2216986 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 123 330 Exercise 2.4: Write a class to represent dynamic arrays of complex numbers. You should be able to write : complex_array q; std::cout<<"Number of points: "; unsigned int npt; std::cin>>npt; q.resize(npt); for (unsigned j=0;j<npt;++j) { q[j].set(j*pi/npt,0); } Define an inner product of two complex arrays 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 124 330

63. Making std::cout recognize class Teaching cout how to print your construction std::ostream & operator<<(std::ostream &os, complex_number &a) { os<<a.real; if (a.imaginary<0) os<<a.imaginary<<" i "; else os<<" +"<<a.imaginary<<" i "; return os; } complex_number a; ... std::cout<<"The roots are "<<a<<" and "<<a.conjugate()<<’\n’; 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 125 330 Class invariants A class is supposed to represent a concept: a complex number, a date, a dynamic array. It will often contain data members of other types, with assumed constraints on those values: A dynamic array is supposed to have a pointer that is either nullptr or a valid block of allocated memory, with the correct size also stored in the structure. A Date structure could have 3 integers for day, month and year, but they can not be, for example, 0,-1,1 Using private data members and well designed public interfaces, we can ensure that assumptions behind a concept are always true. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 126 330

64. Class invariants class darray { Construct ensuring class private: double * dataptr=nullptr; Invariants size_t sz=0; public: // initialize with N elements Maintain Invariants in every darray(size_t N); ~darray(); member // resize to N elements void resize(size_t N); → a structure which always // other members who don’t change // dataptr or sz has sensible values }; 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 127 330 C++ classes Exercise 2.5: The file exercises/angles.cc contains a lot of elements from what we learned about classes. There are also a few new tips, and suggested experiments. Read the code. Run it. Try to understand the output. Do the suggested code changes, and make sure you understand the compiler errors or the change in results. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 128 330

65. Static members class Triangle { Static variables exist only public: static unsigned counter; once for all objects of the Triangle() : ... { class. ++counter; } ~Triangle() { --counter; } Can be used to keep track of static unsigned instanceCount() { return counter; the number of objects of one }; } type created in the whole ... Triangle.cc ... application unsigned Triangle::counter=0; Must be initialised in a Static member functions do source file somewhere, or else not have an implicit this you get an "unresolved pointer argument. They can symbol" error be invoked as ClassName::function(). 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 129 330 Example 2.1: A singleton class is a type designed in such a way that there is at most one object of that type. Every attempt to get an object of that type results in a pointer or reference to the same object. One way to implement this, is by making all constructors of the class private, and providing a static Singleton * getInstance() member function. This function, being a member of the class, can access the private constructors. It can create a static object and return its address. From outside, the only way to get an object of this type is then to call getInstance(), which will return a pointer to the same static object. The singleton programming pattern is demonstrated in examples/singleton.cc. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 130 330

66. Some fun: overloading the () operator class swave const double pi=acos(-1); { private: int N=100; double a=1.0, omega=1.0; swave f{2.0,0.4}; public: swave g{2.3,1.2}; swave()=default; swave(double x, double w) : for (int i=0;i<N;++i) { a{x}, omega{w} {} double ar=2*i*pi/N; double operator()(double t) const std::cout<<i<<" "<<f(ar) { <<" "<<g(ar) return a*sin(omega*t); <<’\n’; } } }; Functionals Function like objects, i.e., classes which define a () operator If they return a bool value, they are called predicates 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 131 330 Functionals Using function like objects They are like other variables. But they can be used as if they were functions! You can make vectors or lists of functionals, pass them as arguments ... 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 132 330

67. Templates 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 133 330 Introduction to C++ templates void copy_int(int *start, int *end, int *start2) Same operations on { for (;start!=end; ++start,++start2) { different types *start2=*start; } } Exactly the same high void copy_string(string *start, string *end, string *start2) level code { for (;start!=end; ++start,++start2) { *start2=*start; Differences only due to } } properties of the void copy_double(double *start, double *end, double *start2) arguments { for (;start!=end; ++start,++start2) { *start2=*start; } } ... double a[10],b[10]; ... copy_double(a,a+10,b); 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 134 330

68. Introduction to C++ templates template <class itr> Same operations on void mycopy(itr start, itr end, itr start2) { different types for (;start!=end; ++start,++start2) { *start2=*start; } Exactly the same high } ... level code double a[10],b[10]; string anames[5],bnames[5]; ... Differences only due to mycopy(a,a+10,b); mycopy(anames,anames+5,bnames); properties of the arguments Internally the compiler translates the Let the compiler do two calls to the horse work! mycopy<double *>(a,a+10,b); mycopy<string *>(anames,anames+5,bnames); ... so that there is no name conflict. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 135 330 Introduction to C++ templates Example 2.2: The example code examples/template_intro.cc contains the above templated copy function. Compile and check that it works. Read through the code and understand it. Although we seemingly call a function we wrote only once, first with an array of doubles and then with an array of strings, the compiler sees these as calls to two different functions. No runtime decision needs to be made according to the incomming types in this example. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 136 330

69. memcpy void* memcpy(void* region1, const void* region2, size_t n) { const char* first = (const char*)region2; const char* last = ((const char*)region2) + n; char* result = (char*)region1; while (first != last) *result++ = *first++; return result; } 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 137 330 memcpy Generic code The use of void * is a trick: pointer to any class can be cast to a void * So, the memcpy code can copy arrays of int, float, double etc. But what if the collection we want to copy is in a linked list, instead of an array ? ... or bare copy is not enough for your type (Remember why you needed copy constructors ?) 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 138 330

70. memcpy Generic code The logic of the copy operation is quite simple. Given an iterator range first to last in an input sequence, and a target location result in an output sequence, we want to: Loop over the input sequence For each position of the input iterator, copy the corresponding element to the output iterator position Increment the input and output iterators Stop if the input iterator has reached last 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 139 330 A template for a generic copy operation template <typename InputIterator, typename OutputIterator> OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result) { while (first != last) *result++ = *first++; return result; } C++ template notation A template with which to generate code! If you had iterators to two kinds of sequences, you could substitute them in the above template and have a nice copy function! Better still, you don’t even need to do it yourself! The compiler will do it for you. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 140 330

71. Test generic copy function Exercise 2.6: The file exercises/copy0.cc contains the above generic copy function, and a test code in which we copy a std::list into a std::vector. Compile and run the program At the end of the main program, declare two strings s1="AAAA AAAA"; s2="BBBB BBBB"; Check that the same copy function can copy s1 to s2! 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 141 330 C++ templates Exercise 2.7: Write a generic inner product function, that takes two sequences of "stuff", multiplies them term by term and adds them. Show that you can use it to multiply lists of doubles, integers, complex numbers. Also, check that you can use the same function after changing one or both lists to vectors. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 142 330

72. Writing generic code Identify similar operations performed on different kinds of data Think about the essential logic of those operations, not involving peculiar properties of one data type. Write code using templates, so that when the templates are instantiated, correct code results for the different data types Template substitution happens at compile time. Type information is retained and used to generate efficient code. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 143 330 Ordered pairs struct double_pair { Template classes double first,second; }; ... double_pair coords[100]; Classes can be templates too ... struct int_pair Generated when the template { int first,second; is “instantiated” }; ... int_pair line_ranges[100]; ... template <class T, class U> struct int_double_pair struct pair { { // wait! T first; // can I make a template out of it? U second; }; }; 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 144 330

73. Ordered pairs Template classes Classes can be templated too Generated when the template pair<double,double> coords[100]; pair<int,int> line_ranges[100]; is “instantiated” pair<int,double> whatever; template <class T, class U> struct pair { T first; U second; }; 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 145 330 Exercise: Write a template class of your own template <typename Datatype> class darray Exercise 2.8: Template classes { private: The dynamic array from your Datatype *data=nullptr; unsigned len=0; earlier exercise is a prime public: Datatype operator[] const; candidate for a template Datatype & operator[]; etc. implementation. Rewrite your }; ... code using templates so that darray<string> A(24); darray<complex_number> C(32); you can use it for an array of strings as well as an array of dynamic array of doubles. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 146 330

74. Inheritance and class hierarchies 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 147 330 Class inheritance Analogy from biology Relationships among organisms Shared traits along a branch and its sub-branches Branches "inherit" traits from parent branch and introduce new distinguishing traits A horse is a mammal. A dog is a mammal. A monkey is a mammal. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 148 330

75. Class inheritance struct Point {double X, Y;}; class Triangle { Geometrical figures public: // Constructors etc., and then, void translate(); void rotate(double byangle); Many actions (e.g. translate and double area() const; double perimeter() const; rotate) will involve identical code private: Point vertex[3]; Properties like area and }; class Quadilateral { perimeter make sense for all, but public: void translate(); are better calculated differently for void rotate(double byangle); double area() const; each type double perimeter() const; bool is_convex() const; There may also be new properties private: Point vertex[4]; (is_convex) introduced by a type }; 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 149 330 Class inheritance We want to write a program to list the area of all the geometric objects select the largest and smallest objects draw in our system. A loop over a darray of them will be nice. But darray< ??? > Object oriented languages like C++, Java, Python ... have a concept of "inheritance" for the classes, to describe such conceptual relations between different types. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 150 330

76. Inheritance: basic syntax class SomeBase { Class members can be public: double f(); private, protected or protected: int i; public private: }; int j; public members are class Derived : public SomeBase { void haha() { accessible from everywhere // can access f() and i // can not access j private members are for } }; internal use in one class void elsewhere() { protected members can be SomeBase a; Derived b; seen by derived classes // Can call a.f(), // but e.g., a.i=0; is not allowed } 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 151 330 Inheritance Inheriting class may add more data, but it retains all the data of the base The base class functions, if invoked, will see a base class object The derived class object is a base class object, but with additional properties 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 152 330

77. Inheritance A pointer to a derived class always points to an address which also contains a valid base class object. baseptr=derivedptr is called "upcasting". Always allowed. Implicit downcasting is not allowed. Explicit downcasting is possible with static_cast and dynamic_cast 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 153 330 Inheritance class Base { public: void f(){std::cout<<"Base::f()\n";} protected: int i{4}; }; class Derived : public Base { int k{0}; public: void g(){std::cout<<"Derived::g()\n";} }; int main() { Derived b; Base *ptr=&b; ptr->g(); // Error! static_cast<Derived *>(ptr)->g(); //OK } 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 154 330

78. Inheritance with virtual functions Abstract concept class “Shape” Inherited classes add/change some properties and inherit other properties from “base” class A triangle is a polygon. A polygon is a shape. A circle is a shape. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 155 330 Class inheritance with virtual functions class Shape { Circle is a derived class from public: virtual ~Shape()=0; base class Shape virtual void rotate(double)=0; virtual void translate(Point)=0; virtual double area() const =0; A derived class inherits from }; virtual double perimeter() const =0; its base(s), which are class Circle : public Shape { public: indicated in the class Circle(); // and other constructors ~Circle(); declaration. void rotate(double phi) {} double area() const override Functions marked as { return pi*r*r; virtual in the base class } private: can be re-implemented in a }; double r; derived class. Note: In C++, member functions are not virtual by default. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 156 330

79. Class inheritance with virtual functions class Shape { A derived class inherits all public: virtual ~Shape()=0; member variables and virtual void rotate(double)=0; virtual void translate(Point)=0; functions from its base. virtual double area() const =0; }; virtual double perimeter() const =0; virtual re-implemented in class Circle : public Shape { public: a derived class are said to be Circle(); // and other constructors ~Circle(); "overriden", and ought to be void rotate(double phi) {} marked with override double area() const override { return pi*r*r; A class with a pure virtual } private: function (with "=0" in the }; double r; declaration) is an abstract ... Shape a; // Error! class. Objects of that type Circle b; // ok. can not be declared. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 157 330 Class inheritance with virtual functions class Polygon : public Shape { public: Syntax for inheritance double perimeter() const final { } // return sum over sides Triangle implements its own protected: darray<Point> vertex; area() function, but can }; int npt; not implement a class Triangle : public Polygon { perimeter(), as that is public: Triangle() : npt(3) declared as final in { vertex.resize(3); // ok Polygon. This is done if the } double area() const override implementation from the { // return sqrt(s*(s-a)*(s-b)*(s-c)) base class is good enough for } }; intended inheriting classes. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 158 330

80. Class inheritance with virtual functions class Polygon : public Shape { The keyword override public: double perimeter() const final ensures that the compiler { // return sum over sides checks there is a } protected: corresponding base class darray<Point> vertex; int npt; function to override. }; class Triangle : public Polygon { public: Virtual functions can be Triangle() : npt(3) re-implemented without this { vertex.resize(3); // ok keyword, but an accidental } double area() override // Error!! omission of a const or an & { // return sqrt(s*(s-a)*(s-b)*(s-c)) can lead to really obscure } }; runtime errors. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 159 330 Class inheritance with virtual functions int main() { darray<Shape *> shape; shape.push_back(new Circle(0.5, Point(3,7))); shape.push_back(new Triangle(Point(1,2),Point(3,3),Point(2.5,0))); ... for (size_t i=0;i<shape.size();++i) { std::cout<<shape[i]->area()<<’\n’; } } A pointer to a base class is allowed to point to an object of a derived class Here, shape[0]->area() will call Circle::area(), shape[1]->area() will call Triangle::area() 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 160 330

81. Calling virtual functions: how it works For classes with virtual functions, the compiler inserts an invisible pointer member to the data and additional book keeping code There is a table of virtual functions for each derived class, with entries pointing to function code somewhere The vptr pointer points to the vtable of that particular class 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 161 330 vptr Example 2.3: The program examples/vptr.cc gives you a tiny class with two double data members. The main function simply creates an object of this kind and prints its size. It prints 16 (bytes) as expected. Uncomment a line containing a virtual destructor function for this class, and recompile and re-run. It will now print 24 as the size on a typical 64 bit machine. Compiling with g++ -O0 -g3 --no-inline and running it in the debugger, you can see the layout of the data structure in memory, and verify that the extra data member is indeed a pointer to a vtable for the class. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 162 330

82. Calling virtual functions: how it works Virtual function call proceeds by first finding the right vtable, then the correct entry for the called function, dereferencing that function pointer and then executing the correct function body Don’t make everything But if virtual functions offer virtual! The overhead, with the cleanest solution with modern machines and acceptable performance, compilers, is not huge. But don’t invent weird things to abusing this feature will hurt avoid them! performance 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 163 330 Class inheritance Inherit or include as data member ? class DNA { A derived class extends the ... std::valarray<char> seq; concept represented by its }; class Cell : public DNA ??? base class in some way. or class Cell { ... Although this extension }; DNA mydna; might mean addition of new data members, Concept B = Concept A + new data does not necessarily mean the class for B should inherit from the class for A 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 164 330

83. Class inheritance Inherit or include as data member ? class DNA { ... is vs has std::valarray<char> seq; }; A good guide to decide class Cell : public DNA ??? whether to inherit or include or is to ask whether the concept class Cell { ... B contains an object A, or DNA mydna; }; whether any object of type B is also an object of type A, like a monkey is a mammal, and a triangle is a polygon. is =⇒ inherit . has =⇒ include 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 165 330 Class inheritance Inheritance summary Base classes to represent common properties of related types : e.g. all proteins are molecules, but all molecules are not proteins. All triangles are polygons, but not all polygons are triangles. Less code: often, only one or two properties need to be changed in an inherited class Helps create reusable code A base class may or may not be constructable ( Polygon as opposed to Shape ) 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 166 330

84. Class decorations More control over classes class A { Class design improvements int v[]{1,-1,-1,1}; public: A() = default; Possible to initialise data in A(std::initializer_list<int> &); A(int i,int j,int k,int l) class declaration { v[0]=i; v[1]=j; Initialiser list constructors v[2]=k; v[3]=l; Delegating constructors } //Delegate work to another constructor allowed A(int i,int j) : A(i,j,0,0) {} }; Inheriting constructors class B : public A { public: possible // Inherit all constructors from A using A::A; B(string s); }; 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 167 330 More control over classes Class design improvements class A { Explicit default, delete, // Automatically generated is ok A() = default; override and final // Don’t want to allow copy A(const A &) = delete; "Explicit is better than A & operator=(const A &) = delete; // Instead, allow a move constructor implicit" A(const A &&); // Don’t try to override this! More control over what the void getDrawPrimitives() final; virtual void show(int i); compiler does with the class }; class B : public A { Compiler errors better than B() = default; void show()override;//will be an error! hard to trace run-time errors }; due to implicitly generated functions 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 168 330

85. Exercise 2.9: The directory exercises/geometry contains a set of files for the classes Point, Shape, Polygon, Circle, Triangle, and Quadrilateral. In addition, there is a main.cc and a Makefile. The implementation is old style. Using what you have learned about classes in C++, improve the different classes using keywords like default,override, final etc. Compile by typing make. Familiarise yourself with Implementation of inherited classes Compiling multi-file projects The use of base class pointers arrays to work with heterogeneous types of objects 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 169 330 Curiously Recurring Template Pattern You need types A and B which have some properties in common, which can be calculated using similar data There are a few polymorphic functions, but conceptually A and B are so different that you don’t expect to store them in a single pointer container The penalty of using virtual functions seems to matter Option 1: implement as totally different classes, just copy and paste the common functions Option 2: try the CRTP 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 170 330

86. Curiously Recurring Template Pattern template <class D> struct Named { int main() inline string get_name() const { { Acetyl a; return static_cast<D const *>(this) Car b; ->get_name_impl(); cout << "get_name on a returns : " } << a.get_name() << ’\n’; inline int version() const cout << "get_name on b returns : " { << b.get_name() << ’\n’; return 42; cout << "Their versions are " } << a.version()<< " and " }; << b.version()<<’\n’; struct Acetyl : public Named<Acetyl> { } inline string get_name_impl() const { return "Acetyl"; }; } CRTP struct Car : public Named<Car> { inline string get_name_impl() const { Polymorphism without return get_brand()+get_model()+ get_year(); virtual functions } }; Faster in many cases 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 171 330 Example 2.4: CRTP The file examples/crtp1.cc demonstrates the use of CRTP to implement a form of polymorphic behaviour. The function version() is inherited without changes in Acetyl and Car. get_name() is inherited, but behaves differently for the two types. All this is without using virtual functions. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 172 330

87. Initialiser list constructors We want to initialise our darray<T> like this: darray<string> S{"A","B","C"}; darray<int> I{1,2,3,4,5}; We need a new type of constructor: the initializer_list constructor darray(initializer_list<T> l) { arr=new T[l.size()]; size_t i=0; for (auto el : l) arr[i++]=el; } 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 173 330 A dynamic array template class template <typename T> Two versions of the [] class darray { operator for read-only public: and read/write access darray() = default; Use const qualifier in darray(const darray<T> &oth); any member function darray(darray<T> &&oth); which does not change darray(size_t N); the object darray<T> &operator=(const darray<T> &); Note how the friend darray<T> &operator=(darray<T> &&); function is declared ~darray(); inline T operator[](size_t i) const { return arr[i]; } inline T &operator[](size_t i) { return arr[i]; } T sum() const; template <typename U> friend ostream &operator<<(ostream &os,const darray<U> &); private: void swap(darray &oth) { std::swap(arr,oth.arr); std::swap(sz,oth.sz); } T *arr=nullptr; size_t sz=0; }; 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 174 330

88. A dynamic array template class template <typename T> T darray<T>::sum() const { The template keyword T a{}; must be used before for (size_t i=0;i<sz;++i) a+=arr[i]; all member functions return a; defined outside class } declaration template <typename U> The class name before ostream &operator<<(ostream &os,const darray<U> &da) { the :: must be the ... fully qualified name } e.g. darray<T> template <typename T> darray<T>::darray(size_t N) { if (N!=0) { arr=new T [N]; sz=N; } } template <typename T> darray<T>::~darray() { if (arr) delete [] arr; } template <typename T> darray<T>::darray(darray<T> &&oth) { swap(oth); } 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 175 330 A dynamic array template class template <typename T> All function darray<T>::darray(const darray<T> &oth) { definitions, not just if (oth.sz!=0) { the declarations must sz=oth.sz; be visible at the point arr=new T[sz]; where templates are } instantiated. for (size_t i=0;i<sz;++i) arr[i]=oth.arr[i]; Often, template } functions are defined template <typename T> inside the class darray<T> &operator=(const darray<T> &oth) { declarations. if (this!=&oth) { if (arr && sz!=oth.sz) { sz=oth.sz; delete [] arr; arr=new T[sz]; } for (size_t i=0;i<sz;++i) arr[i]=oth.arr[i]; } return *this; } template <typename T> darray<T> &operator=(darray<T> &&oth) { swap(oth); return *this; } 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 176 330

89. A dynamic array template class template <typename T> We escape having to write class darray { the template <typename T public: >before every inline T operator[](size_t i) const { return arr[i]; } function inline T &operator[](size_t i) { return arr[i]; } Class declaration longer, so T sum() const { that it is harder to quickly T a{}; glance at all available for (size_t i=0;i<sz;++i) a+=arr[i]; functions return a; } darray() = default; darray(size_t N) { if (N!=0) { arr=new T [N]; sz=N; } } ~darray() { if (arr) delete [] arr; } darray(darray<T> &&oth) { swap(oth); } darray &operator=(darray &&oth) { swap(oth); return *this; } 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 177 330 A dynamic array template class darray(const darray<T> &oth) { Note: assignment if (oth.sz!=0) { operators must return sz=oth.sz; a reference to the arr=new T[sz]; calling object (i.e., } *this) for (size_t i=0;i<sz;++i) arr[i]=oth.arr[i]; Notice how the copy } constructor and the darray &operator=(const darray &oth) { assignment operators if (this!=&oth) { have redundant code if (arr && sz!=oth.sz) { sz=oth.sz; delete [] arr; arr=new T[sz]; } for (size_t i=0;i<sz;++i) arr[i]=oth.arr[i]; } return *this; } private: void swap(darray &oth) { std::swap(arr,oth.arr); std::swap(sz,oth.sz); } T *arr=nullptr; size_t sz=0; }; 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 178 330

90. Example 2.5: The file examples/darray_complete.cc has a completed and extensively commented dynamic array class. Notice the use of the new function syntax in C++11. See how to enable range based for loop for your classes. See how the output operator was written entirely outside the class. Check the subtle difference in this case between using {10} and (10) as arguments while constructing a darray. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 179 330 Chapter 3 Lambda functions 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 180 330

91. Lambda Functions Purpose Basic syntax Uses Effective use of STL Initialisation of const Concurrency New loop styles Herb Sutter: Get used to }); : you will be seeing it a lot! 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 181 330 Motivation struct Person {string firstname,lastname; void display_list(Community &c) size_t age;}; { class Community { size_t ma; std::vector<Person> thepeople; std::cout<<"Minimum age: "; template <class F> std::cin >> ma; vector<Person> select(F f) // We want to select all Persons with { // age >= ma vector<Person> ans; auto v = c.select(???); for (auto p : thepeople) { } if (f(p)) ans.push_back(p); ... } ... return ans; ... } ... }; ... What should we pass as an argument to c.select() ? 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 182 330

92. Motivation struct Person {string firstname,lastname; void display_list(Community &c) size_t age;}; { class Community { size_t ma; std::vector<Person> thepeople; std::cout<<"Minimum age: "; template <class F> std::cin >> ma; vector<Person> select(F f) // We want to select all Persons with { // age >= ma. Perhaps ... vector<Person> ans; bool filter(Person p) { for (auto p : thepeople) { // Error! Nested function! if (f(p)) ans.push_back(p); return p.age>=ma; } } return ans; auto v = c.select(filter); } } }; A locally defined function aware of the variable ma would be perfect. But a nested function definition is not allowed in C++. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 183 330 Motivation void display_list(Community &c) { size_t ma; std::cout<<"Minimum age: "; Besides, should the locally std::cin >> ma; // perhaps ... defined function use the value of bool filter(Person p) { // Error! return p.age>=ma; ma when the function was } // Besides,... defined, or when it was passed ma=std::max(legal_minimum_age(),ma); auto v = c.select(filter); to c.select()? //What value of ma should filter see ? } We want something like the local function here, but with more control over how it sees its environment. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 184 330

93. Motivation A function object class, or a class Filter { public: functor can certainly solve the Filter(size_t &co) : cutoff(co){} bool operator()(Person p) { problem. But, return p.age>=cutoff; } it is cumbersome to write a private: cutoff=0; new functor for every new }; void display_list(Community &c) kind of filter. { size_t ma; it takes the logic of what is std::cout<<"Minimum age: "; std::cin >> ma; done in the filter out of the ma=std::max(legal_minimum_age(),ma); Filter filter{ma}; local context auto v = c.select(filter); } it wastes possibly useful names 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 185 330 Enter lambda functions “Captures” ma by value and void display_list(Community &c) { uses it in a locally defined size_t ma; std::cout<<"Minimum age: "; function-like-thing std::cin >> ma; ma=std::max(legal_minimum_age(),ma); auto v = c.select([ma](Person p){ We control how it sees }); return p.age>=ma; variables in its context } Keeps the logic of the filter in the local context Example 3.1: The program community.cc has exactly the code used in this explanation. Check that it works! Modify so that the selection is based on the age and a maximum number of characters in the name. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 186 330

94. Lambda Functions: Syntax [capture] (arguments)mutable−>return_type{body} Examples [ ](int a, int b)->bool{return a>b;} [=](int a)->bool{return a>somevar;} [&](int a){somevar += a;} [=,&somevar](int a){somevar+=max(a,othervar);} [a,&b]{f(a,b);} The optional keyword mutable allows variables captured by value to be changed inside the lambda function The return type is optional if there is one return statement Function arguments field is optional if empty 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 187 330 Lambda Functions: captures Imagine there is a variable int p=5 defined previously We can “capture” p by value and use it inside our lambda auto L=[p](int i){std::cout << i*3+p;}; L(3); // result : prints out 14 auto M=[p](int i){p=i*3;}; // syntax error! p is read-only! We can capture p by value (make a copy), but use the mutable keyword, to let the lambda function change its local copy of p auto M=[p](int i)mutable{return p+=i*3;}; std::cout<<M(1)<<" ";std::cout<<M(2)<<" ";std::cout<<p<<"\n"; // result : prints out "8 14 5" We can capture p by reference and modify it auto M=[&p](int i){return p+=i*3;}; std::cout<<M(1)<<" ";std::cout<<M(2)<<" ";std::cout<<p<<"\n"; // result : prints out "8 14 14" 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 188 330

95. No default capture! [] Capture nothing [=] Capture all by value (copy) [=,&x] Capture all by value, except x by reference [&] Capture all by reference [a=move(b)] Move capture [&,x] Capture all by reference, except x by value A lambda with empty capture brackets is like a local function, and can be assigned to a regular function pointer. It is not aware of identifiers defined previously in its context When you use a variable defined outside the lambda in the lambda, you have to capture it 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 189 330 Example 3.2: The program captures.cc demonstrates capturing variables in the surrounding scope of a lambda function. Compile and run. Observe the differences between capturing by value with and without mutable, and capturing by reference. Exercise 3.1: The program lambda_1.cc shows one way to initialise a list of integers to {1,2,3,4,5... }. Modify to initialise the list to the Fibonacci sequence. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 190 330

96. Chapter 4 Standard Template Library 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 191 330 s s hm er ics rs in ies rit er to rs nta e ilit m go ra m Nu Co Ite Ut Ti Al be g rs in m te ad nu in re po om th ti- t nd ar ul Sm Ra M 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 192 330

97. The time library namespace std::chrono defines many time related functions and classes (include file: chrono) system_clock: System clock steady_clock: Steady monotonic clock high_resolution_clock: To the precision of your computer’s clock steady_clock::now() : nanoseconds since 1.1.1970 duration<double>: Abstraction for a time duration. Uses std::ratio<>internally Example 4.1: examples/chrono_demo.cc 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 193 330 The time library // examples/chrono_demo.cc #include <iostream> #include <chrono> #include <vector> #include <thread> using namespace std::chrono; bool is_prime(unsigned n); int main() { std::vector<unsigned> primes; auto t = steady_clock::now(); for (unsigned i=0;i<10000;++i) { if (is_prime(i)) primes.push_back(i); } std::cout << "Primes till 10000 are ... " << ’\n’; for (unsigned i : primes) std::cout << i << ’\n’; auto d = steady_clock::now() -t; std::cout<<"Prime search took "<<duration<double>(d).count()<<" seconds"<<’\n’; std::cout << "Sleeping for 3 seconds ...\n"; std::this_thread::sleep_for(3s); // h, min, s, ms, us and ns are known time units. std::cout << "finished.\n"; } 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 194 330

98. Unique pointer // examples/uniqueptr.cc int main() { auto u1=std::make_unique<MyStruct>(1); //auto u2 = u1; //won’t compile auto u3 = std::move(u1); std::cout << "Data value for u3 is u3->vl = " << u3->vl <<’\n’; auto u4 = std::make_unique<MyStruct[]>(4); } Exclusive access to resource The data pointed to is freed when the pointer expires Can not be copied (deleted copy constructor and assignment operator) Data ownership can be transferred with std::move Can create single instances as well as arrays through make_unique 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 195 330 Shared pointer // examples/sharedptr.cc int main() { auto u1=std::make_shared<MyStruct>(1); std::shared_ptr<MyStruct> u2 = u1; // Copy is ok std::shared_ptr<MyStruct> u3 = std::move(u1); std::cout << "Reference count of u3 is " << u3.use_count() << ’\n’; } Can share resource with other shared/weak pointers The data pointed to is freed when the pointer expires Can be copy assigned/constructed Maintains a reference count ptr.use_count() 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 196 330

99. Weak pointer // examples/weakptr.cc int main() { auto s1=std::make_shared<MyStruct>(1); std::weak_ptr<MyStruct> w1(s1); std::cout << "Ref count of s1 = " << s1.use_count()<<’\n’; std::shared_ptr<MyStruct> s3(s1); std::cout << "Ref count of s1 = " << s1.use_count()<<’\n’; } Does not own resource Can "kind of" share data with shared pointers, but does not change reference count 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 197 330 Smart pointers: examples Example 4.2: uniqueptr.cc, sharedptr.cc, weakptr.cc Read the 3 smart pointer example files, and try to understand the output. Observe when the constructors and destructors for the data objects are being called. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 198 330

100. std::bind //examples/binddemo.cc #include <iostream> #include <functional> using namespace std::placeholders; int add(int i, int j) { std::cout << "add: received arguments "<<i<<" and "<<j<<’\n’; return i+j; } int main() { auto a10 = std::bind(add,10,_1); // new functional a10, which calls add(10,_1) // where _1 is the argument passed to a10 std::cout << a10(1) << ’\n’; // call add(10,1) std::cout << a10(2) << ’\n’; // call add(10,2) std::cout << a10(3) << ’\n’; auto dda = std::bind(add, _2, _1); // new functional, passing arguments to add in the reverse order dda(1000000, 99999999); } Example 4.3: binddemo.cc 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 199 330 Random number generation Old rand() , erand(), drand() etc have poor properties with regard to correlations Random number classes in Figure: Source XKCD: the standard library replace http://xkcd.com and vastly supercede these functions 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 200 330

101. Random number generation Share a common structure Uniform random generator engine with (hopefully) well tested properties Distribution generator which adapts its input to a required std::mt19937_64 engine; distribution std::poisson_distribution<> dist{8.5}; auto gen = std::bind(dist, engine); // Better still ... // auto gen = [&dist, &engine]{ // return dist(engine); // }; r = gen(); 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 201 330 Random number generators #include <random> #include <functional> #include <iostream> #include <map> int main() { std::poisson_distribution<> distribution{8.5}; std::mt19937_64 engine; auto generator = std::bind(distribution,engine); std::map<int,unsigned> H; for (unsigned i=0;i<5000000;++i) H[generator()]++; for (auto & i : H) std::cout<<i.first<<" "<<i.second<<’\n’; } std::mt19937_64 is a 64 bit implementation of Mersenne Twister 19937 The template std::poisson_distribution is a functional implementing the Poission distribution std::bind “binds” the first argument of distribution to engine and returns a new function object 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 202 330

102. Random number generators std::normal_distribution<> G{3.5,1.2}; // Gaussian mu=3.5, sig=1.2 std::uniform_real_distribution<> U{3.141,6.282}; std::binomial_distribution<> B{13}; std::discrete_distribution<> dist{0.3,0.2,0.2,0.1,0.1,0.1}; // The following is an engine like std::mt19937, but is non-deterministic std::random_device seed; // int i= seed() will be a random integer Lots of useful distributions available in the standard With one or two lines of code, it is possible to create a high quality generator with good properties and the desired distribution std::random_device is a non-deterministic random number generator. It is good for setting seeds for the used random number engine It is slower than the pseudo-random number generators 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 203 330 Random number generator: Exercises Exercise 4.1: Make a program to generate normally distributed random numbers with user specified mean and variance, and make a histogram to demonstrate that the correct distribution is produced. Exercise 4.2: Make a program to implement a "biased die", i.e., with user specified non-uniform probability for different faces. You will need std::discrete_distribution<> 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 204 330

103. Exercises Exercise 4.3: For a real valued random variable X with normal distribution of a given mean µ and standard deviation σ, calculate the following quantity: (X − µ)4 K [X ] = ( (X − µ)2 )2 Fill in the random number generation parts of the program exercises/K.cc. Run the program a few times varying the mean and standard deviation. What do you observe about the quantity in the equation above ? 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 205 330 vector: templated dynamic array type A vector Element type is a template parameter Consecutive elements in memory Can be accessed using an "iterator" 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 206 330

104. A linked list A linked list is a collection of connected nodes. Each node has some data, and one or two pointers to other nodes. They are the "next" and "previous" nodes in the linked list. When "next" or "previous" does not exist, the pointer is set to nullptr 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 207 330 A linked list When a new element is added to the end of a list, its "previous" pointer is set to the previous end of chain, and it becomes the target of the "next" pointer of the previous end. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 207 330

105. A linked list New elements can be added to the front or back of the list with only a few pointers needing rearrangement. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 207 330 A linked list Any element in the list can be reached, if one kept track of the beginning or end of the list, and followed the "next" and "previous" pointers. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 207 330

106. A linked list A concept of an "iterator" can be devised, where the ++ and -- operators move to the next and previous nodes. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 207 330 A linked list Inserting a new element in the middle of the list does not require moving the existing nodes in memory. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 207 330

107. A linked list Just rearranging the next and previous pointers of the elements between which the new element must go, is enough. This gives efficient O(1) insertions and deletions. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 207 330 Generic "containers" Generic data holding constructions Can be accessed through a suitably designed "iterator" The data type does not affect the design => template Similarity of interface is by choice 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 208 330

108. STL containers Structures to organise data std::vector<> : dynamic arrays Include file names correspond to class names std::list<> : linked lists All of them provide std::queue<> : queue corresponding iterator classes std::deque<> : If iter is an iterator, *iter double ended queue is data. std::map<A,B> : All of them provide begin() associative container and end() functions 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 209 330 std::list struct userinfo {int age; string name;}; Example 4.4: std::list demo int main() { We need a program to manage a std::list<userinfo> ulist; char c=’y’; list of names and ages. The user do { std::cout << "Add more entries ?"; can keep adding information on std::cin>>c; if (c!=’y’) break; names and ages, as long as userinfo tmp; std::cout << "Name :"; required. When the user quits, std::cin >> std::ws; getline(std::cin,tmp.name); the program should print the std::cout << "Age :"; std::cin >> tmp.age; entered names sorted according ulist.push_back(tmp); } while (c==’y’); to age. A small program to do ulist.sort([](auto a, auto b){ return a.age < b.age or this is examples/list0.cc a.age == b.age and a.name < b.name; }); for (auto & user : ulist) std::cout<<user.name<<" : " <<user.age<<’\n’; } 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 210 330

109. Linked lists struct userinfo {int age; string name;}; int main() Solution using STL lists { std::list<userinfo> ulist; char c=’y’; do { We don’t worry about how std::cout << "Add more entries ?"; std::cin>>c; long a name would be if (c!=’y’) break; userinfo tmp; We don’t need to keep track std::cout << "Name :"; std::cin >> std::ws; of next, previous pointers getline(std::cin,tmp.name); std::cout << "Age :"; std::list<userinfo> is a std::cin >> tmp.age; ulist.push_back(tmp); linked list of our hand made } while (c==’y’); ulist.sort([](auto a, auto b){ structure userinfo ! return a.age < b.age or }); a.age == b.age and a.name < b.name; Notice how we used a for (auto & user : ulist) lambda function to specify std::cout<<user.name<<" : " <<user.age<<’\n’; sorting order } 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 211 330 std::list #include <list> ulist.push_back(tmp) ... std::list<userinfo> ulist; appends (a copy of) the object userinfo tmp; ... tmp at the end of the list ulist.push_back(tmp); ... ulist.sort() sorts the ulist.sort([](auto a, auto b){ return a.age < b.age or elements in the list using the < a.age == b.age and a.name < b. name; operator for its elements }); ... for (auto & user : ulist) { ulist.sort(comp) can use a std::cout<<user.name<<" : " <<user.age<<std::endl; user supplied binary predicate } (comp) while comparing elements 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 212 330

110. std::list for (auto it=ulist.begin(); it!=ulist.end();++it) { std::cout << it->name << " : " << it->age << std::endl; } Iterator iterator is something that iterates over a sequence and gives access to an element of the sequence like a pointer In this example, it is the current pointer for our linked list, with additional code to represent the concept of an iterator 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 213 330 std::list for (auto it=ulist.begin(); it!=ulist.end();++it) { std::cout << it->name << " : " << it->age << std::endl; } Iterator An iterator has the ++ operations defined on it, which mean “move to the next element in the sequence”. Similarly there are -- operators defined ulist.begin() and ulist.end()return iterators at the start and (one past the) end of the sequence 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 214 330

111. std::list Iterator ulist.end() actually points to a fictitious “one-past-the-last” element. This enables the familiar C-style loop iterations. ulist.rbegin() and ulist.rend()return reverse_iterators which browse the sequence in the opposite direction 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 215 330 List operations ulist.insert(pos,newdata) inserts the value newdata before pos ulist.erase(pos) erases the element at pos ulist.erase(pos1, pos2) erases the elements starting at pos1 until but excluding the element at pos2 ulist.pop_back() and ulist.pop_front() erase the terminal elements 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 216 330

112. Familiarise yourself with std::list Exercise 4.4: The program exercises/list1.cc demonstrates the syntax of STL lists. Study the program. Change it so that the list contents are printed in reverse order. Also, create two lists and learn how to merge them. Consult the online documentation for the syntax and usage of the STL containers. Look up std::list at http://www.cplusplus.com/reference/stl/list/ or http://en.cppreference.com/w/cpp/container/list 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 217 330 Other STL containers std::vector<stuff> : a dynamic array of stuff std::queue<stuff> : a queue std::map<key, stuff> : an associative array std::valarray<stuff> : a fast dynamic array of numeric types std::bitset<N> : a special container with single “bits” as elements std::set<stuff> : for the concept of a set 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 218 330

113. Using std::vector std::vector<int> v(10); : array of 10 integers Efficient indexing operator [], for unchecked element access v.at(i) provides range checked access. An exception is thrown if at(i) is called with an out-of-range i std::vector<std::list<userinfo>> vu(10); array of 10 linked lists! Supports push_back and insert operations, but sometimes has to relocate the all the elements because of one push_back operation (next slide) 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 219 330 std::vector std::vector may reserve a few extra memory blocks to allow a few quick push_back operations. New items are simply placed in the previously reserved but unused memory and the size member adjusted. With repeated push_back calls, std::vector will run out of its pre-allocated capacity 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 220 330

114. std::vector When push_back is no longer possible, a new larger memory block is reserved, and all previous content is moved or copied to it. A few more quick push_back operations are again possible. Exercise 4.5: Construct a list and a vector of 3 elements of the Verbose class from your earlier exercise. Add new elements one by one and pause to examine the output. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 221 330 std::vector<T> Fast element access, since the elements are stored in contiguous memory locations Insertion and deletion can involve copy/move operations of a subset of elements For each element, the minimal amount of memory consistent with the element’s alignment requirement is stored std::list<T> To reach the i’th element from the first element, one must access the second element, and then the next one, and the next one, and so on until the i’th element is found Insertion and deletion are very fast, as none of the existing elements need to be copied or moved item For each element, two additional pointers are stored, increasing the memory foot print if we need billions of elements of tiny size 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 222 330

115. std::array : arrays with fixed compile time size std::array<T,N> is a fixed length array of size N holding elements of type T It implements functions like begin() and end() and is therefore usable with STL algorithms like transform, generate etc. The array size is a template parameter, and hence a compile time constant. std::array<std::string,7> week{"Mon","Tue","Wed ","Thu","Fri","Sat","Sun"}; std::array<DataType, integer value> is therefore equivalent to the raw C-style fixed length arrays, and should be used when fixed length arrays are needed. Depending on the application, they may be a bit faster than a vector 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 223 330 Associative containers: std::map std::map<std::string, int> flsize; flsize["S.dat"]=123164; flsize["D.dat"]=423222; flsize["A.dat"]=1024; Think of it as a special kind of "vector" where you can have things other than integers as indices. Template arguments specify the key and data types Could be thought of as a container storing (key,value) pairs : {(”S.dat”, 123164), (”D.dat”, 423222), (”A.dat”, 1024)} The less than comparison operation must be defined on the key type Implemented as a tree, which keeps its elements sorted 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 224 330

116. A word counter program Example 4.5: Fake exercise: Write a program that counts all different words in a text file and prints the statistics. #include <iostream> #include <fstream> A quick histogram! #include <iomanip> #include <string> #include <map> std::map<string,int> is int main(int argc, char *argv[]) { a container which stores an std::ifstream fin(argv[1]); std::map<std::string,unsigned> freq; integer, for each unique std::string s; while (fin >> s) freq[s]++; std::string key. for (auto i : freq) std::cout<<std::setw(12)<< i.first The iterator for std::map <<std::setw(4) << ’:’ <<std::setw(12)<< i.second “points to” a <<std::endl; } pair<key,value> 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 225 330 std::unordered_map and std::unordered_set Like std::map<k,v> and std::set<v>, but do not sort the elements Internally, these are hash tables, providing faster element access than std::map and std::set Additional template arguments to specify hash functions Unordered map 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 226 330

117. STL algorithms The similarity of the interface, ... e.g. begin(), end() etc., std::vector<YourClass> vc(inp.size()); std::copy(inp.begin(),inp.end(), among STL containers allows vc.begin()); //Copy contents of list to a vector generic algorithms to be written auto pos = std::find(vc.begin(),vc.end(), elm); as template functions, //Find an element in vc which equals elm std::sort(vc.begin(),vc.end()); performing common tasks on //Sort the vector vc. The operator "<" //must be defined collections ... std::transform(inp.begin(), inp.end(), out.begin(), rotate); //apply rotate() to each input element, //and store results in output sequence 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 227 330 STL algorithms Exercise 4.6: The standard library provides a large number of template functions to work with containers Look them up in www.cplusplus.com or en.cppreference.com In a program, define a vector of integers 1..9 Use the suitable STL algorithms to generate successive permutations of the vector 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 228 330

118. STL algorithms: sorting std::sort(iter_1, #include <iostream> #include <algorithm> iter_2) sorts the elements #include <vector> using namespace std; between iterators iter_1 struct myless { and iter_2 bool operator()(int i, int j) { std::sort(iter_1, return (i*i < j*j); } iter_2, less_than) sorts }; int main() the elements between { vector<int> v{2,-3,7,4,-1,9,0}; iterators iter_1 and sort(v.begin(),v.end()); //Sort using "<" operator iter_2 using a custom for (auto el : v) cout << el << endl; sort(v.begin(),v.end(),myless()); comparison method //Sort using custom comparison for (auto el: v) cout << el << endl; less_than, which could be } any callable object 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 229 330 STL algorithms: sorting std::sort(iter_1, #include <iostream> #include <algorithm> iter_2) sorts the elements #include <vector> using namespace std; between iterators iter_1 int main() { and iter_2 vector<int> v{2,-3,7,4,-1,9,0}; sort(v.begin(),v.end()); std::sort(iter_1, //Sort using "<" operator for (auto el : v) cout << el << endl; iter_2, less_than) sorts sort(v.begin(),v.end(), [](int i, int j){ the elements between return i*i < j*j; }); iterators iter_1 and //Sort using custom comparison for (auto el: v) cout << el << endl; iter_2 using a custom } comparison method less_than, which could be Lambda functions obviate any callable object the need for many adhoc out-of-context classes. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 229 330

119. std::transform std::transform(begin_1 , end_1, begin_res, unary_function); std::transform(begin_1 , end_1, begin_2, begin_res, binary_function); Apply callable object to the sequence and write result starting at a given iterator location The container holding result must be previously resized so that it has the right number of elements The “result” container can be (one of the) input container(s) std::vector<double> v{0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9}; std::list<double> l1(v.size(),0),l2(v.size(),0); std::transform(v.begin(),v.end(),l1.begin(),sin); std::transform(v.begin(),v.end(),l1.begin(),l2.begin(),std::max); Result: l1 contains sin(x) for each x in v, and l2 contains the greater(x,sin(x)) 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 230 330 all_of and any_of bool valid(std::string name) { return all_of(name.begin(),name.end(), [](char c) {return (isalpha(c))||isspace(c);}); } std::all_of(begin_ , end_ , condition) checks if all elements in a given range satisfy condition condition is a callable object std::any_of(begin_ , end_ , condition) checks if any single element in a given range satisfies condition 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 231 330

120. Exercise 4.7: The program sort_various.cc defines an array of strings and prints them sorted (using std::sort) in various ways: alphabetical order using the default string comparison according to the lengths of the strings, by passing a lambda function to std::sort alphabetical order of back-to-front strings. The third part is left for you to fill in. Use the algorithm std::reverse to reverse the strings locally in your lambda function. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 232 330 Exercise 4.8: The program sort_complex.cc defines an array of complex numbers, and demonstrates how to sort it by their real parts using a lambda function as the comparison function. Add code to subsequently print the list sorted according their absolute difference from a given complex number. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 233 330

121. Example 4.6: Probabilities with playing cards The program examples/cards_problem.cc demonstrates many topics discussed during this course. It has a constexpr funtion to create a fixed length array to store results, several standard library containers and algorithms as well as the use of the random number machinery for a Monte Carlo simulation. It has extensive comments explaining the use of various features. Read the code and identify the different techniques used, and run it to solve a probability question regarding playing cards. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 234 330 Iterator adaptors template <typename InItr,typename OutItr> void copy(InItr src, InItr src_end, OutItr dest) { while (src!=src_end) { *dest = *src; ++src,++dest; } } The copy algorithm Move iterators along source and destination sequences Get objects at the iterators Call operator=() on LHS with RHS as argument 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 235 330

122. Iterator adaptors struct FakeItr { FakeItr &operator++(int){return *this;} FakeItr &operator++(){return *this;} Proxy operator*() {return prx;} }; What if, the destination "iterator" does not really browse any sequence, but simply returns one special object with unary operator*() ? ... and that special object has operator=() defined with RHS as argument ? 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 236 330 Iterator adaptors struct Proxy { template <typename T> OutputProxy& operator=(const T &t) { std::cout<<"Output by proxy: " << t <<"\n"; return *this; } }; The copy algorithm then becomes a way to call prx.operator=(obj) for each object in the source sequence ... and that function need not actually assign anything! 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 237 330

123. ... but, WHY ? Our copy function assumes template <typename InItr, typename OutItr> that the destination void copy(InItr src, InItr src_end, OutItr dest) container has enough space { while (src!=src_end) { You must resize them ahead } *dest++ = *src++; of using them } ... std::list<int> l{1,2,3,4,5}; ... or, perhaps you could std::list<int> m; copy(l.begin(),l.end(),m.begin()); create an imposter, which //segfault calls push_back on the destination container in its operator= ? 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 238 330 Iterator adaptors #include <iterator> ... list<int> l{1,2,3,4,5}; list<int> m; copy(l.begin(),l.end(), back_inserter(m)); copy(m.begin(),m.end(), ostream_iterator<int>(cout," ")); std::back_insert_iterator is an "iterator adaptor", which uses a container’s own push_back function to insert elements The convenience function std::back_inserter simplifies handling Similarly std::ostream_iterator is an iterator adaptor, which simulates an output sequence on an output stream 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 239 330

124. Exercise 4.9: Modify the program exercises/transform.cc to use an iterator adaptor to feed the results of std::transform into the results array, instead of setting the size in the beginning. Example 4.7: Reading in a file as a list of strings The example examples/line_read.cc demonstrates how iterator adaptors can be used to read a file as a list of strings (one for each line), using std::copy and an appropriately designed iterator imposter and a line proxy class. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 240 330 Chapter 5 Metaprogramming in C++ 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 241 330

125. Metaprogramming in C++14 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 242 330 Template specialisation template <class T> Templates are defined to class vector { // implementation of a general work with generic template // vector for any type T }; parameters template <> class vector<bool> { // Store the true false values But special values of those // in a compressed way, i.e., // 32 of them in a single int parameters, which should be }; void somewhere_else() treated differently, can be { specified using "template vector<bool> A; // Uses the special implementation specialisations" as shown } If a matching specialisation is found, it is preferred over the general template 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 243 330

126. An interesting property of C++ templates C++ templates ... can take typenames template <typename T, int N> struct my_array { and integral types as T data[N]; }; parameters can be used to specify template <typename T, compile time constant int nrows, int ncols> struct my_matrix { sizes T data[nrows*ncols]; }; but also give you a peculiar kind of template <int i, int j> struct mult { “function” in effect static const int value=i*j; }; ... my_array<mult<19,21>::value> vals; 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 244 330 Template meta-programming in C++ Recursion and specialisation no “if”, “for” or state template <int N> struct factorial { static const int value=N* variables like for factorial<N-1>::value; }; run-time functions template <> struct factorial<0> { static const int value=1; But, we have recursion }; std::array<int,factorial<7>::value> P; and specialisation! Iteration can be template <int i, bool flag> struct cube_mag_impl { emulated using tail static const int value=i*i*i; }; recursion and template<int i, false> struct cube_mag_impl { static const int value=-i*i*i; specialisation }; template <int i> Conditional branches using cube_mag=cube_mag_impl<i,(i>0)>::value; std::array<double,cube_mag<7>> A; can also be done with std::array<double,cube_mag<-3>> B; specialisation 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 245 330

127. Evaluate dependent types Suppose we want to implement a template function template <typename T> U f(T a); such that when T is a non-pointer type, U should take the value T. But if T is itself a pointer, U is the type obtained by dereferencing the pointer We could use a template function to "compute" the type U like this: template <typename T> struct remove_pointer { using type=T; }; template <typename T> struct remove_pointer<T*> { using type=T; }; We can then declare the function as: template <typename T> remove_pointer<T>::type f(T a); 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 246 330 Type functions Gives rise to a variety of template <typename T1, typename T2> std::is_same<T1,T2>::value "type functions" template <typename T> Compute properties of types std::is_integral<T>::value template <typename T> Compute dependent types std::make_signed<T>::type 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 247 330

128. static_assert with type traits #include <iostream> #include <type_traits> template < class T > class SomeCalc { static_assert(std::is_arithmetic<T>::value, "argument T must be an arithmetic type"); }; int main() { SomeCalc<string> mycalc; //Compiler error! ... } Use static_assert and type_traits in combination with constexpr Example 5.1: static_assert2.cc 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 248 330 Typetraits Unary predicates is_integral<T> : T is an integer type is_const<T> : has a const qualifier is_class<T> : struct or class is_pointer<T> : Pointer type is_abstract<T> : Abstract class with at least one pure virtual function is_copy_constructible<T> : Class allows copy construction 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 249 330

129. Typetraits Type relations is_same<T1,T2> : T1 and T2 are the same types is_base_of<T,D> : T is base class of D is_convertible<T,T2> : T is convertible to T2 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 250 330 Another example with typetraits template <typename T> Situation: You have two void f_impl(T val, true_type); different ways to implement a // for integer T template <typename T> function, for integers and for void f_impl(T val, false_type); // for others everything else. template <typename T> void f(T val) { Implement two } f_impl(val,std::is_integral<T>()); specializations using a true_type and a false_type argument Use is_integral trait to choose one or the other at compile time 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 251 330

130. Variadic templates template <typename ... Args> int countArgs(Args ... args) { return (sizeof ...args); } std::cout<<"Num args="<<countArgs(1,"one","ein","uno",3.232)<<’\n’; Templates with arbitrary number of arguments Typical use: template meta-programming Recursion, partial specialisation The ... is actual code! Not blanks for you to fill in! 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 252 330 Parameter pack The ellipsis (...) template argument is called a parameter pack 2 It represents 0 or more arguments which could be type names, integers or other templates : template <typename ... Args> class mytuple; // The above can be instantiated with : mytuple<int,int,double,string> t1; mytuple<int> t2; mytuple<> t3; Definition: A template with at least one parameter pack is called a variadic template 2 http://en.cppreference.com/w/cpp/language/parameter_pack 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 253 330

131. Parameter pack //examples/variadic_1.cc template <typename ... Types> void f(Types ... args); template <typename Type1, typename ... Types> void f(Type1 arg1, Types ... rest) { std::cout <<typeid(arg1).name()<<": "<< arg1 << "\n"; f(rest ...); } template <> void f() {} int main() { int i{3},j{}; const char * cst{"abc"}; std::string cppst{"def"}; f(i,j,true,k,l,cst,cppst); } Divide argument list into first and rest Do something with first and recursively call template with rest Specialise for the case with 1 or 0 arguments 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 254 330 Parameter pack expansion pattern ... is called a parameter pack expansion It applies a pattern to a comma separated list of instantiations of the pattern If we are in a function : template <typename ... Types> void g(Types ... args) args... means the list of arguments used for the function. Calling f(args ...) in g will call f with same arguments Calling f(h(args)...) in g will call f with an argument list generated by applying function h to each argument of g In g(true,"abc",1), f(h(args)...) means f(h(true),h("abc"),h(1)) 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 255 330

132. Parameter pack expansion template <typename ... Types> void f(Types ... args); template <typename Type1, typename ... Types> void f(Type1 arg1, Types ... rest) { std::cout <<" The first argument is "<<arg1 <<". Remainder argument list has "<<sizeof...(Types)<<" elements.\n"; f(rest ...); } template <> void f() {} template <typename ... Types> void g(Types ... args) { std::cout << "Inside g: going to call function f with the sizes of " << "my arguments\n"; f(sizeof(args)...); } sizeof...(Types) retrieves the number of arguments in the parameter pack In g above, we call f with the sizes of each of the parameters passed to g Similarly, one can generate all addresses as &args..., increment all with ++args... (examples variadic_2.cc and variadic_3.cc) 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 256 330 Parameter pack expansion: where template <typename ... Types> void f(Types & ... args) {} template <typename ... Types> void h(Types ... args) { f(std::cout<<args<<"\t"...); [=,&args ...]{ return g(args...); }(); int t[sizeof...(args)]={args ...}; int s=0; for (auto i : t) s+=i; std::cout << "\nsum = "<<s <<"\n"; } Parameter pack expansion can be done in function parameter list, function argument list, template parameter list or template argument list Braced initializer lists Base specifiers and member initializer lists in classes Lambda captures 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 257 330

133. Example 5.2: Parameter packs Study the examples variadic_1.cc,variadic_2.cc and variadic_3.cc. See where parameter packs are begin expanded, and make yourself familiar with this syntax. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 258 330 Fold expressions in C++17 #include <iostream> ... op ppack translates to template <typename ... Args> auto addup(Args ... args) reduce from the left with { return (1 + ... + args); operator op } int main() { ppack op ... means, std::cout << addup(1,2,3,4,5) << "\n"; reduce from the right with op } init op ... op ppack reduces from the left, with Example 5.3: initial value init examples/foldex.cc pack op ... op init reduces from the right ... 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 259 330

134. Tuples #include <tuple> #include <iostream> int main() { std::tuple<int,int,std::string> name_i_j{0,1,"Uralic"}; auto t3=std::make_tuple<int,bool>(2,false); auto t4=std::tuple_cat(name_i_j,t3); std::cout << std::get<2>(t4) <<’\n’; } Like std::pair, but with arbitrary number of members "Structure templates without names" Accessor "template functions" std::get<index> with index starting at 0 Supports relational operators for lexicographical comparisons tuple_cat(args ...) concatenates tuples. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 260 330 Tuples std::tuple<int,int,string> f(); // elsewhere int main() { int i1; std::string name; std::tie(i1,std::ignore,name) = f(); } tie(args ...) "extracts a tuple" into named variables. Some fields may be ignored during extraction using std::ignore as shown 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 261 330

135. Printing a tuple template <int idx, int MAX, typename... Args> struct PRINT_TUPLE { static void print(std::ostream & strm,const std::tuple<Args...> & t) { strm << std::get<idx>(t)<<(idx+1==MAX ? "" : ", "); PRINT_TUPLE<idx+1,MAX,Args...>::print(strm,t); } }; template <int MAX, typename... Args> struct PRINT_TUPLE<MAX,MAX,Args...> { static void print(std::ostream &strm, const std::tuple<Args...> &t){} }; template <typename ... Args> std::ostream & operator<<(std::ostream & strm,const std::tuple<Args...> &t) { strm << "["; PRINT_TUPLE<0,sizeof...(Args),Args...>::print(strm,t); return strm <<"]"; Tail recursion in place of a loop Template specialization is used to stop the recursion Wrapper for a clean overall look 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 262 330 Simplification using constexpr if // examples/print_tuple_cxx17.cc C++17 introduces a template <int idx, int MAX, typename... Args> if constexpr statement struct PRINT_TUPLE { static void print(std::ostream & strm, that can be used for compile const std::tuple<Args...> & t) { time conditionals. if constexpr (idx < MAX) { strm << std::get<idx>(t); if constexpr ((idx+1)<MAX) Using if constexpr as strm << ", "; PRINT_TUPLE<idx+1,MAX,Args...> shown, we can shorten the ::print(strm,t); code a bit, by avoiding the } } final template specialisation }; case 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 263 330

136. Example 5.4: The file examples/tuple0.cc demonstrates the use of tuples with some commonly used functions in their context. Example 5.5: Printing a tuple is demonstrated in print_tuple.cc, print_tuple_cxx17.cc and print_tuple_foldex.cc. The last two will need compiler flags to enable C++17. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 264 330 VoT to ToV Exercise 5.1: Write a function to convert a vector of tuples into a tuple of vectors. The following main program should print out a vector of doubles extracted from the vector of tuples. int main() { std::vector<std::tuple<int,double,int>> Vt; Vt.emplace_back<>(std::make_tuple(1,4.3,0)); Vt.emplace_back<>(std::make_tuple(3,8.3,3)); Vt.emplace_back<>(std::make_tuple(2,0.3,2)); auto Tv=vot_tov(Vt); //supply the function vot_tov() for (auto vl : std::get<1>(Tv)) std::cout << vl << "\n"; } 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 265 330

137. Zipping tuples together Suppose we have two tuples in our program: std::tuple<int,int,std::string> t1; std::tuple<unsigned,unsigned,unsigned> t2; We want to zip them together with a function that produces: std::tuple<std::pair<int,unsigned>, std::pair<int,unsigned>, std::pair<std::string,unsigned>> t3=zip(t1,t2); What should be the return type of the general version of the function, for n-tuples ? template <class ... Args1> struct zip_st { template <class ... Args2> struct with { using type = std::tuple<std::pair<Args1,Args2>...>; }; }; template <class ... Args1> template <class ... Args2> zip_st<Args1 ...>::with<Args2 ...>::type zip(const std::tuple<Args1 ...> &t1,const std::tuple<Args2 ...> &t2); 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 266 330 Range based for loops for multiple containers We have three containers A, B and C of the same size, and we want to print their corresponding elements like for (size_t i=0;i<A.size();++i) std::cout << A[i]<<’\t’<<B[i]<<’\t’<<C[i]<<’\n’; Not good, if the containers do not have the operator[] defined. Separate iterators for each is possible, but ungainly. We want to be (C++17: will be) able to write : for (auto [el1,el2,el3] : zip(A,B,C)) std::cout<<el1<<’\t’<<el2<<’\t’<<el3<<’\n’; We can do the following with a little work: for (auto el : zip(A,B,C)) std::cout<<std::get<0>(el)<<’\t’<<std::get<1>(el) <<’\t’<<std::get<2>(el)<<’\n’; 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 267 330

138. Range based for loops for multiple containers template <typename ... Args> class ContainerBundle { public: using iterator = IteratorBundle<typename Args::iterator ...>; using iter_coll = std::tuple<typename Args::iterator ...>; ContainerBundle(typename std::add_pointer<Args>::type ... args) : dat{args ...}, bg{args->begin() ...}, nd{args->end() ...} {} ~ContainerBundle() = default; ContainerBundle(const ContainerBundle &) = delete; ContainerBundle(ContainerBundle &&) = default; inline iterator begin() { return bg; } inline iterator end() const { return nd; } private: std::tuple<typename std::add_pointer<Args>::type ...> dat; iterator bg,nd; }; We need a container bundle class taking pointers to each container 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 268 330 Range based for loops for multiple containers template <typename ... Itr> class IteratorBundle { public: using value_type = std::tuple<typename Itr::value_type ...>; using internal_type = std::tuple<Itr ...>; IteratorBundle() = default; // etc. bool operator==(const IteratorBundle &it) const { return loc==it.loc; } // special implementation insisting that all // elements in the bundle compare unequal. This ensures proper // function for containers of different sizes. bool operator!=(const IteratorBundle &it) const; inline value_type operator*() { return deref(); } inline IteratorBundle & operator++() { advance_them<0,sizeof ...(Itr)>::eval(loc); return *this; } We need an iterator bundle class to represent combined iterators Handling containers of different sizes is tricky. We do it here with a special implementation of operator!= 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 269 330

139. Range based for loops for multiple containers template <bool... b> struct static_all_of; template <bool... tail> struct static_all_of<true, tail...> : static_all_of<tail...> {}; //no need to look further if first argument is false template <bool... tail> struct static_all_of<false, tail...> : std::false_type {}; template <> struct static_all_of<> : std::true_type {}; template <typename ... Args> ContainerBundle<typename std::remove_pointer<Args>::type ...> zip(Args ... args) { static_assert(static_all_of<std::is_pointer<Args>::value ...>::value, "Each argument to zip must be a pointer to a container! "); return {args ...}; } And some code to ensure we pass pointers when creating the zipped containers 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 270 330 Example 5.6: Range-for for multiple containers The file examples/multi_range_for.cc demonstrates the use of multiple containers with range based for loops and the syntax just discussed. Check what happens when you forget to pass a pointer to the zip function! Notice that when the containers are of different sizes, the range for only iterates until the shortest container is exhausted. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 271 330

140. Metaprogramming with constexpr constexpr bool is_prime_rec(size_t number, size_t c) { return (c*c>number)?true:(number % c == 0)?false:is_prime_rec(number, c+1); } constexpr bool is_prime(size_t number) { return (number<=1)?false:is_prime_rec(number,2); } int main() { constexpr unsigned N=1000003; static_assert(is_prime(N),"Not a prime"); New mechanism for compile time calculations Code can be clearer than template functions Floating point calculations possible Recommendation: use constexpr functions for numeric calculations at compile time The same functions are available at run time if the arguments are not compile time constants 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 272 330 Exercise 5.2: The program exercises/cexprprime.cc demonstrates compile time verification of a number being a prime number, using the old C++11 style constexpr functions. Rewrite for C++14 so that larger values, like the one in the commented out line, can be handled without increasing recursion limits. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 273 330

141. Chapter 6 Graphical User Interfaces with Qt5 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 274 330 Introduction to GUI design with Qt Cross platform framework for application and UI development Easily readable C++ code for GUI programming "Principle of least surprises" Trolltech → Nokia → Digia → The Qt Company https://www.qt.io Downloads, tutorials, documentation Link to other courses Books: https://wiki.qt.io/Books 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 275 330

142. Introduction to GUI design with Qt Extends the C++ language with new excellent container classes Java style iterators Copy-on-write Signals and slots mechanisms I/O classes with Unicode I/O, many character encodings, and platform independent abstraction for binary data. Neat framework for GUI programming For you: GUI programming is a good training ground to get used to “object oriented programming” 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 276 330 Qt5: Two ways of creating GUI Qt Widgets: For more traditional classic desktop GUI (not discussed here) Qt Quick: Declarative language for fluid and animated user interfaces. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 277 330

143. Environment set-up for Qt5 module load qt will set the environment variables you need We will be using CMake to build all our Qt5 based programs. A generic CMakeLists.txt file suitable for starting new projects can be found under $COURSE_HOME/share/Qt5 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 278 330 Hello, World! Qt Quick style // examples/hello.qml import QtQuick 2.5 Rectangle { width: 800 height: 300 color: "gold" Text { anchors.centerIn: parent text: "Hello, World!" font.pointSize : 48 font.family: "Lucida" } } If you just need to show some simple visual element on the screen, the size of the C++ program you need to write is 0 characters. Nothing to compile. View the content with qmlscene hello.qml 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 279 330

144. Hello, World! Qt Quick style // examples/hello.qml import QtQuick 2.5 Rectangle { width: 800 height: 300 color: "gold" Text { anchors.centerIn: parent text: "Hello, World!" font.pointSize : 48 font.family: "Lucida" } } The QML file is “data” used by the QML engine to generate the visual components It is possible to write interface side logic in a convenient Javascript syntax In a typical Qt Quick C++ application, you pass on the main qml file to a Qt C++ class, which renders it on the screen 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 280 330 QML // examples/hello.qml import QtQuick 2.5 JSON style format to say: “I Rectangle { width: 800 want a rectangle with width height: 300 color: "gold" W and height H ... ” Text { anchors.centerIn: parent text: "Hello, World!" font.pointSize : 48 font.family: "Lucida" The fundamental elements in QML, using which you construct your interface, are called Items. Rectangle and Text in this example are Items. An Item can contain other Items Items can be composed to create new Itemtypes in QML. But the fundamental ones are implemented in C++ inheriting from QQuickItem. (later!) 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 281 330

145. QML // examples/hello.qml import QtQuick 2.5 JSON style format to say: “I Rectangle { width: 800 want a rectangle with width height: 300 color: "gold" W and height H ... ” Text { anchors.centerIn: parent text: "Hello, World!" font.pointSize : 48 font.family: "Lucida" An Item can have “properties”. A property can be assigned a value, or “bound” to another property of possibly another Item, so that if the RHS property changes, the change will be reflected in the LHS property as well. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 282 330 QML // examples/hello.qml import QtQuick 2.5 Positioning using anchors Rectangle { width: 800 Try to resize the “Hello, height: 300 color: "gold" World!” window you created, Text { anchors.centerIn: parent by dragging the edge or text: "Hello, World!" font.pointSize : 48 cornor of the window. What font.family: "Lucida" } happens to the text ? Does it } deform ? Does it move closer to or farther from the top ? An Item has anchors, which can be bound to anchors in another Item Some other possibilities : anchors.left : parent.left, anchors.verticalCenter : other.verticalCenter, anchors.fill: parent ... 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 283 330

146. Basic GUI development with Qt Quick Use a simple and intuitive markup language to create visual components and check that they look right Put them together in a suitable GUI shell for the application Write the business end of the application with as little coupling with Graphical Interfaces as possible Write a top level controller class which will receive user input from the GUI and take appropriate action Implement any new visual element necessary in C++, by inheriting from QQuickItem In the main.cc register any C++ types you wrote which shall be instantiated in the QML files create the UI represented by your QML, and enter event loop 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 284 330 QML Hello, World! through a C++ main function Example 6.1: The folder examples/qmlhello contains the hello.qml file along with a main.cc file, and a generic CMakeLists.txt file for Qt5 projects. Build and run : cd /path/to/qmlhello mkdir build; cd build cmake .. make cd .. build/qmlhello What happens if your current working directory does not have the hello.qml file ? What happens if you are in a directory containing a different file which happens to be named hello.qml ? 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 285 330

147. The C++ main() for a program with a QML GUI // examples/qmlhello/main.cc #include <QGuiApplication> #include <QtQuick/QQuickView> int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQuickView gui; gui.setSource(QUrl("hello.qml")); gui.show(); return app.exec(); } QGuiApplication manages global resources Create one in main and pass the argc and argv to it At the end of main, pass control to it with app.exec() Forget about it and concentrate on functionality and graphical elements 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 286 330 Qt resource system // examples/qmlhello/main.cc #include <QGuiApplication> Example 6.2: #include <QtQuick/QQuickView> int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); In your main.cc file in QQuickView gui; examples/qmlhello, gui.setSource(QUrl("hello.qml")); gui.setSource(QUrl("qrc:/hello.qml")); replace the red line with the gui.show(); blue line in the top panel return app.exec(); } Create a file with the content as shown in the bottom // examples/qmlhello/ui.qrc // You create this!! panel, with a suffix .qrc <RCC> <qresource prefix="/"> Build as before, and run in <file>hello.qml</file> </qresource> different working directories. </RCC> What change do you notice ? 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 287 330

148. Qt resource system Resource files have the extension .qrc, and specify what auxiliary files will be required at run time, e.g., icons, images, GUI description QML files ... Resources identified in the .qrc files are incorporated into the binary Paths in the resource file are relative to that file The prefix qrc:/ in a QUrl object tells Qt to look for the path as given in the resource file. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 288 330 Rectangle // examples/demos/rectangle.qml Rectangle { Rectangle items id: box width: 600 height: 400 rotation: 45 Can be used to create circular radius: 30 // Rounded corners! border.color: "red" items as well, by choosing an border.width: 3 antialiasing: true appropriate radius // color: "green" // or, If gradient is specified, gradient : Gradient { GradientStop { color will be ignored position: 0.0 color : "red" gradient and } GradientStop { antialiasing are relatively position: 1.0 color : "green" expensive, and should be } } used for static items only } 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 289 330

149. MouseArea // examples/demos/mousearea.qml import QtQuick 2.7 Mouse area Rectangle { width: 600 height: 400 Fill a named visual object Rectangle { id: box with a mouse area to capture width: 300 height: 200 mouse events anchors.centerIn: parent rotation: 45 radius: 100 // Rounded corners! You can then take action border.color: "red" border.width: 3 based on “signals” emitted antialiasing: true when a mouse event happens color: "green" } MouseArea { Q: Does the mouse click anchors.fill: box onClicked: { correspond to the rotated or } console.log("Click detected!") unrotated rectangle ? Does it } } follow the curved boundary ? 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 290 330 Text // examples/demos/text.qml import QtQuick 2.3 Rectangle { width: 600 height: 400 Text { anchors.fill: parent text: "<a href=\"http://www.fz-juelich.de\">Forschungszentrum</a> <a href=\"http://www.juelich.de\">Juelich</a>" color: "green" wrapMode: Text.Wrap font { family: "Times"; pointSize: 32; bold:true } onLinkActivated: console.log("Activated link " + link) } } You can choose the color, font, wrapping mode for the text Rich-text/HTML style formatting is supported Can tell you when an embedded link is activated 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 291 330

150. Image // examples/demos/image.qml Bitmap formats like PNG, import QtQuick 2.0 JPEG as well as vector Image { source: "start.svg" graphics formats like SVG fillMode: Image.PreserveAspectFit } fillMode can be used to specify how it should behave when resized For large images, set asynchronous to true. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 292 330 Rows, columns and grids // examples/demos/row.qml Arrange items in rows, import QtQuick 2.7 Row { // or Column, or Grid columns or grids Rectangle { width: 100 height:100 For grids, the property } color: "red" columns can be used to Rectangle { width: 100 specify grid shape height:100 color: "green" If the contained items are of } Rectangle { different sizes, properties like width: 100 height:100 horizontalItemAlignment } color: "blue" can be used to set the } desired alignment. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 293 330

151. Repeater Repeats an item according to a “model” If model is an integer, creates as many copies // examples/demos/repeater.qml import QtQuick 2.7 If model is a list, repeats Grid { columns: 10 according to list size Repeater { model: 40 Each copy has access to an // or, // model: ["red","green","blue"] index inside the repeater Rectangle { width: 100 height:100 For list models, there is also radius:50 color: index%3?"red":"blue" modelData referring to the } // color: modelData corresponding list element } } 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 294 330 Item Base type for all visual items in Qt Quick Not visible itself, but implements common visual element attributes like width, height, anchoring and key handling support Convenient to bundle a few elements into a new QML type 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 295 330

152. Item // examples/demos/MyToolButton.qml import QtQuick 2.7 Item { id: root property alias icon : theimg.source property alias label : thetext.text width: theimg.implicitWidth + thetext.implicitWidth Row { Image { id: theimg height: root.height fillMode: Image.PreserveAspectFit } Text { id: thetext padding:20 anchors.verticalCenter: theimg.verticalCenter } } } // examples/demos/toolbuttons.qml import QtQuick 2.7 Row { MyToolButton { height: 50; icon: "start.svg"; label: "Start" } MyToolButton { height: 50; icon: "start.svg"; label: "Also, start!" } } 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 296 330 When we load toolbuttons.qml in qmlscene, it looks for a definition of the apparent typename MyToolButton. It finds the file MyToolButton.qml in its search path, and finds an item definition, which it accepts as the definition of the type MyToolButton 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 297 330

153. MyToolButton.qml does not specify the source of the image or the actual text. We create top level aliases for properties we want to be modifiable from the outside. We arrange the items relative to each other Now we can reuse this new QML element as an image-text combo whenever we need one 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 298 330 Positioning with anchors Each Item has 7 invisible anchor lines, called left, horizontalCenter, right, top, verticalCenter, bottom and baseline You can use the anchor lines Rectangle { to position the elements //haha Text { relative to each other anchors.top : parent.top anchors.right: parent.right // ... } } 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 299 330

154. Layouts Invisible entities which take care of arranging their children in a well defined manner Layouts are Items. So, a Layout can have other Layouts or Items as children ColumnLayout arranges its children vertically RowLayout arranges its children horizontally GridLayout arranges its children in a grid Layouts can resize the Items they arrange 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 300 330 Layouts Since the layouts can resize their contents, they need to know the minimum, maximum, preferred, heights and widths of their contents. Each Item placed in a Layout gets additional properties, Layout.minimumWidth, Layout.preferredWidth, Layout.maximumWidth etc. To specify hints to the layout If Layout.fillWidth is set to true for an Item, it will stretch to fill horizontal space. If not, it will stay at the preferred width, even if the containing window is enlarged. If Layout.fillHeight is ... 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 301 330

155. Layouts // examples/demos/layouts_grid.qml Rectangle { property int margin: 10 width: g.implicitWidth+ 2*margin height: g.implicitHeight+ 2*margin GridLayout { id: g anchors.fill: parent columns : 2 Rectangle { color: "blue"; border.color: "red" ; Layout.preferredWidth: 100; Layout.preferredHeight: 50 Layout.fillWidth: true Layout.fillHeight: true } Rectangle { color: "blue"; border.color: "red" ; Layout.preferredWidth: 100; Layout.preferredHeight: 50 Layout.fillWidth: true Layout.fillHeight: true } } 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 302 330 Qt Quick Controls Frequently needed compounds With Items, Text etc, we can create more complex building blocks for a GUI But for frequently used components, it is desirable to have some prepackaged entities available through the library. =⇒ Qt Quick Controls library 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 303 330

156. Qt Quick Controls Frequently needed compounds Provides Buttons, Sliders, Labels, ComboBoxes, CheckBoxes, RadioButtons, SplitView, TabView, ScrollView ... 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 304 330 Qt Quick Controls Exercise 6.1: Develop using Qt Quick Controls In the folder exercises/gamma you will find the QML tree for an interface similar to the one of the KDE Plasma program called kgamma, to make gamma adjustments of the monitors. It’s missing a few buttons. Try to finish it, so that it looks close to the interface you see in the previous slide. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 305 330

157. Creating the main window Has menu bars, tool bars, status bars etc Has a central item for the main functionality Can be created in QML using ApplicationWindow 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 306 330 Creating the main window ApplicationWindow { Menu bar, tool bar and title: "My great program" visible: true status bar sub-elements menuBar: MenuBar { Menu { are already present in the title: "&File" MenuItem { main window, but need to text: "E&xit" shortcut: StandardKey.Quit be bound to items of the onTriggered: Qt.quit() } right type. They know } Menu { where they should live. title: "&Help" MenuItem { The top menus can be text: "About..." onTriggered: aboutDialog.open() filled with items as shown. } } Each menu item when } toolBar: ToolBar { ... } selected, emits a statusBar: StatusBar { RowLayout { ... } } } “triggered” signal. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 307 330

158. Creating the main window Action { Actions are named invisible id: startAction text: "&Run" entities which can be shortcut: StandardKey.Forward iconName: "file-run" “triggered” onTriggered: prog.start() } Action { An action can be added to a id: stopAction text: "&Stop" menu as an item shortcut: StandardKey.Close iconName: "file-stop" Actions have a signal onTriggered: prog.stop() } ”triggered“, which could be connected to something 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 308 330 Creating the main window toolBar: ToolBar { toolBar can to be filled RowLayout { ToolButton { with ToolButtons, with a iconSource: "icons/start.svg" onClicked:startAction.trigger(this) text and an icon tooltip:"Start" } ToolButton { statusBar can similarly be iconSource: "icons/stop.svg" onClicked:stopAction.trigger(this) given some content as shown tooltip: "Stop" } Between the tool bar and the statusBar: StatusBar { RowLayout { status bar, some visual item Label { text: "Ready" takes the stage as the main } ProgressBar { item in the program id: progbar value: prog.cycleCount } } 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 309 330

159. Properties Shades { gamma : gammachannel.value } A property of a qml item can ... be bound to another property text: theslider.value.toFixed(2) ... of that or another item The lhs property then ”follows“ the rhs property Provided through the Qt meta object system 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 310 330 Example 6.3: The qml file examples/demos/binding.qml shows how the one QML item can be set up to follow changes in another QML item using properties. Observe the behaviour using qmlscene and then look at the QML file to see the code that does the work. Exercise 6.2: Insert the right property bindings (two total lines) in exercises/gamma so that the gray scale bar as well as the right side numeric values for the sliders start to respond to the sliders. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 311 330

160. Communication between objects Qt signals and slots mechanism When a signal is emitted, all slots it is connected to are called. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 312 330 Qt signals and slots Signals are declared, but not implemented by the user We can connect signals to slots as we like using the connect() function If a class has its own signals or slots, the Q_OBJECT macro needs to be used as shown A signal called somethingHappened is exposed to the QML system as onSomethingHappened 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 313 330

161. Qt signals and slots MouseArea { The response to the signal in anchors.fill: box onClicked: { QML can be written as console.log("Click detected!") } shown here. } Action { id: quitAction C++ functions can be called text: "&Quit" shortcut: StandardKey.Quit here if they have been made iconName: "file-exit" onTriggered: Qt.quit() available to QML through } the Q_INVOKABLE macro 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 314 330 Calling C++ functions class DoSomething : public QObject{ Q_OBJECT public: Q_INVOKABLE double sum() const; Q_INVOKABLE QString greet() const; private: std::array<double,10> dat{{3,2,4,3,5,4,6,5,7,6}}; }; If you want to call a member function from within the qml interface, you have to put the macro Q_INVOKABLE in front of it, in addition to setting the Q_OBJECT macro for the class. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 315 330

162. Calling C++ functions QGuiApplication a(argc, argv); DoSomething interf; QQuickView gui; gui.rootContext()->setContextProperty("interf", &interf); gui.setSource(QUrl("qrc:///ui.qml")); gui.show(); return a.exec(); In the main program, you can declare an object of that type Create a QQuickView as usual and pass the object of your own class as an argument to the setContextProperty() function, along with a name which should be used for this object inside QML. You can now access member functions of your class which have been marked with Q_INVOKABLE directly from QML 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 316 330 Calling C++ functions Rectangle { id: rect function updateUI() { text.text = interf.sum(); } Rectangle { id: buttonl MouseArea { anchors.fill: parent onClicked: { buttonl.pressed = !buttonl.pressed; text.text = interf.greet(); } } } } ... and call the C++ functions directly from the qml 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 317 330

163. Example 6.4: Calling C++ functions from Qml The folder examples/bigredbutton contains a QML file to create a big round red button. There is a class with some simple functions in it, and we call one of them when the red button is pressed. This program is a minimal demo, where you make something happen by interacting with the GUI. Break it a little. Remove the Q_INVOKABLE macros, infront of the functions. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 318 330 Exercise 6.3: A GUI for one of your own simpler programs Choose one of the simpler programs you have written in a previous exercise, e.g., the Poisson distribution demonstration, and make it start using a button. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 319 330

164. Information exchange : GUI and your C++ classes Example 6.5: infoexchange The example program examples/infoexchange demonstrates a few major components in any C++ program with a Qt Quick GUI. It modifies the Kurtosis problem in yesterday’s exercise to give it a GUI. The sliders in the GUI can now change the mean and standard deviation of the distribution. The start button triggers the calculation. The result of the calculation is then displayed in a big label in the GUI. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 319 330 Information exchange : GUI and your C++ classes We need to create a controller class to mediate between our GUI and the calculations This class, KurtosisProblem, inherits from QQuickItem, and contains the Q_OBJECT macro The start() member function performs the calculation Mean and standard deviation of the normal distribution are member variables 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 320 330

165. class KurtosisProblem : public QQuickItem { Q_OBJECT public: Q_INVOKABLE void start(); Q_PROPERTY(qreal mean MEMBER m_mean NOTIFY meanChanged) Q_PROPERTY(qreal sigma READ sigma WRITE setSigma NOTIFY sigmaChanged) Q_PROPERTY(qreal result MEMBER m_result NOTIFY resultChanged) KurtosisProblem(QQuickItem *parent = 0); inline auto sigma() const { return m_sigma; } inline void setSigma(qreal sg) { std::cout << "Called setSigma with argument " << sg << "\n"; auto old_sig = m_sigma; if (fabs(sg - old_sig)>eps) { emit sigmaChanged(); m_sigma = sg; } } signals: void meanChanged(); void sigmaChanged(); void resultChanged(); private: qreal m_mean = 10.0, m_sigma = 35.8, m_result=0; }; 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 321 330 Information exchange : GUI and your C++ classes To make mean and standard deviation visible in QML as ”properties“, we make them Q_PROPERTY in our C++ class. For each property, we decide how it should be accessed from QML We make the start() function Q_INVOKABLE so that we can call it from QML. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 322 330

166. Information exchange : GUI and your C++ classes The implementation of the class simply performs the same calculation as the K.cc program But, since KurtosisProblem inherits from QQuickItem, and takes a QQuickItem parent, we write that constructor. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 323 330 Information exchange : GUI and your C++ classes int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); qmlRegisterType<KurtosisProblem>("KurtosisProblem", 1, 0, "KurtosisProblem"); QQuickView gui; gui.setSource(QUrl("qrc:///main.qml")); gui.show(); return app.exec(); } In the main program, we register the KurtosisProblem class with QML Rest of the code remains like in our QML hello world programs. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 324 330

167. Information exchange : GUI and your C++ classes In the main.qml, we import KurtosisProblem 1.0 Rectangle { instantiate our KurtosisProblem { id : prog KurtosisProblem Qt Quick mean : meanctrl.value sigma: sigctrl.value Item, and give it a name } ... We bind the mean and sigma Button { id: startbutton ”properties“, to the values of anchors.centerIn: parent text: "Start" the respective control sliders onClicked: prog.start() } ... The start button’s onClicked signal handler is set to call the start() Now let’s see if that works! function for the instantiated object 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 325 330 Custom visual Items I Introduction to Qt Scene Graph QQuickItems in a QML scene populate a tree structure of QSGNode objects To make a new visible type to use in QML, you need to inherit the QQuickItem class, and in the constructor, set the flag QQuickItem::ItemHasContents. Override the updatePaintNode member function where you insert and manipulate any visual items you want to create This function is called by the rendering engine when your node needs to be redrawn The argument passed is a pointer to a QSGNode, meant to represent the geometry and texture of your visual item. 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 326 330

168. Custom visual Items II Introduction to Qt Scene Graph If the node is empty, you should allocate memory for it, but once you pass it over to the rendering engine, it handles the clean up. Each time the function is called for an object, it is called with the same QSGNode pointer, so that allocation and initialization does not have to be repeated, just the changes recorded When the the rendered content has changed, you have to call update(). This schedules a call to updatePaintNode if the item is visible Example: LatticeDisplay in the Ising model example 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 327 330 Square Lattice Ising Model Simulator I Toy physics problem well suited as a simple but non-trivial example Square lattice with spins, with only nearest neighbour interactions Properties easily approximated using a simple Metropolis Monte Carlo simulation One can vary the temperature and the strength of the external magnetic field The lattice reacts : at temperatures below about 2.27, the very long spin correlation lengths are favoured. At higher temperatures, spins are more random, and the magnetisation is small 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 328 330

169. Square Lattice Ising Model Simulator I The lattice and the Monte Carlo engine can be implemented without any thought about the GUI The lattice display has to be a visual Qt Quick Item, and must override updatePaintNode A top level handler class MCRunner handles GUI inputs and passes them on to the MC engine Results are passed back to the GUI using the properties system and displayed. Implementation : examples/slimsim 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 329 330 Square Lattice Ising Model Simulator 29 May – 01 June 2017 Sandipan Mohanty | Jülich Supercomputing Centre 330 330