diff --git a/.gitignore b/.gitignore index 2c4a067..3aa70de 100644 --- a/.gitignore +++ b/.gitignore @@ -37,5 +37,8 @@ # Build Outputs **/build/* +# Book Build +book + # Misc. *:Zone.Identifier diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..1c4cd27 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,87 @@ +# Contributing + +Thank you for taking the time to contribute. +Any and all contributions are always very much appreciated. However, to make sure the process of accepting patches goes for everyone (especially for the maintainer), you should try to follow these few simple guidelines when you contribute: + +## Prerequisites + +1. [rustup](https://www.rust-lang.org/tools/install) - for the Rust compiler and Cargo +2. [mdBook](https://rust-lang.github.io/mdBook/) - Book generation tool + +## Steps to Contribute + +1. Fork the repository. +2. Create a new branch based on the `dev` branch (`git checkout -b dev`). + If your contribution is a bug fix, you should name your branch `bugfix/xxx`; + for a feature, it should be `feature/xxx` etc. Otherwise, just use your good + judgment. Consistent naming of branches is appreciated since it makes the + output of `git branch` easier to understand with a single glance. +3. Do your modifications on that branch. +4. Make sure your modifications did not break anything by building and verifying the output using: + + ```sh + mdbook serve --open + ``` + +5. Commit your changes. Your commit message should start with a one line + short description of the modifications, with the details and explanations + of your modifications following in subsequent paragraphs or bullet points. If you address an issue, create a subtitle with the issues number and title followed by the changes involved in resolving the issue. + Please limit your lines to about 78 characters in commit messages, since + it makes the output easier to read in `git log`. Also, starting your commit + message with a tag describing the nature of the commit is nice, since it + makes the commit history easier to skim through. For commits that do not + change any functionality (e.g. refactoring or fixing typos), the `[NFC]` + tag (No Functionality Change) can be used. Here's an example of an + acceptable commit message: + + ```txt + [TAG] Refactor the interface + + - Rename elem to contains + - Rename subset to is_subset, and make is_subset applicable in infix notation + + Issue (#12) - Add an at `at_key` method: + - Added the `at_key` method + - operator[] is now bound to at_key instead of find + ``` + + When applicable, please squash adjacent _wip_ commits into a single _logical_ commit. + If your contribution has several logical commits, it's fine. +6. Push the changes to your fork (`git push origin `). +7. Open a pull request against the package's `dev` branch (not against `main`). + +I will do my best to respond in a timely manner. I might discuss your patch and suggest some modifications, or I might amend your patch myself and ask you for feedback. +You will always be given proper credit. + +## Style guide + +Markdown uses the CommonMark style guide for the most part however, certain exceptions are allowed for customizing the style. It is a guide for a reason. + +- Any code example should have a corresponding example link that is either a full file/project or a link to an external compiler (eg. Godbolt). +- Any free standing or example links that are related should be put in a bullet-list and separate unrelated links by a empty line. +- Reserve the use of quote blocks (lines beginning with `>` in Markdown) for side notes relating to content or examples + +For C++ content such as examples: + +- Indent using 4 spaces. +- Do not leave trailing white spaces at the end of lines, and no more than a + single newline at the end of a source file. +- A definition blocks' initial brace should start on a newline, not trail off the declaration. +- Prefer direct initialisation (`{}` over `=`) over assignment initialisation, especially for primitive types. +- Prefer brace-based initialisation for invoking a types constructor. +- Use spaces on either side of constructor arguments when using braces (eg. `int{ _ }`). +- Use `auto` as variable introducer and declare type explicitly in the brace initialiser or on right-hand-side of the assignment. +- Prefer trailing return types on functions over prefixed notation. +- Prefer to separate functions declarations (eg. `constexpr auto`), signature, constant and reference qualifiers (classes), `noexcept` specification and return type on separate lines if function declaration gets too long. Indent the constant and references qualifiers, `noexcept` specification and return type if they are on a newline. + +```cxx +constexpr auto +really_long_function_signature(that_takes lots_of_arguments, with_really long_names, for_types and_arguments) + noexcept( noexcept(long_noexcept_specification) && noexcept(with_multiple_conditions) ) + -> a_really_long_return_type, template_type> +{} +``` + +- Indent `requires` clauses and `requires` expressions. +- `#include` should be sorted in alphabetical order. +- Mostly use your own judgment and stick to the style of the existing and surrounding code. diff --git a/README.md b/README.md index 8bc122b..20c9289 100644 --- a/README.md +++ b/README.md @@ -1,45 +1,33 @@ # High Performance Programming -Resources and challenges for the Monash DeepNeuron High Performance Programming Team. +This repository contains the source code for "High Performance Programming" Book. All examples, slides and content are also found in this repository. This book is available online or can be built locally and served in your browser. -## Welcome +## Building -Welcome and congratulations on joining the MDN HPP Team! We are excited to have you as a part of this team and look forward to teaching some cool technologies and ideas to you. My name is Tyler Swann and I'll be the lead educator for this workshop series. During this series you will be learning the C++ programming language along with techniques for, computer memory, algorithm intuition and parallel computing techniques. +To build this book you need [mdBook](https://rust-lang.github.io/mdBook/index.html) a tool for creating books with Markdown. mdBook can be installed using Cargo - Rust's package manager. -## About this Repository +```sh +$ cargo install mdbook +``` -This repository contains the information, resources and links to help guide you through this series. Each directory will have a corresponding `README.md` file which is displayed when viewing that directory on GitHub. These files will give a synopsis of everything to do with that directory. The weekly content can be found in the `content/` directory, which has been broken down by week. +You can build this book you must clone this repository using Git. You can then build it and even serve it to localhost to view in your browser. The serve command will produce a localhost you can view. -Each week has directories for the tasks, examples and meetup slides for that week. Any other helpful information brought during meetups will be added to the `README.md` of each week. Read the information carefully and follow each step as listed. If you need help, don't hesitate to read out. +```sh +$ git clone https://github.com/MonashDeepNeuron/HPP.git +$ cd HPP -The links below can help direct you to the relevant pages. +# Build ... +$ mdbook build -## Weekly Meetups - -Each week, the team will meet at Monash Clayton Campus (location, day, time etc. are TBD) were we will go through the content, tackle any issues and misunderstandings, experiment, discuss ideas and showcase things people have built. - -It is expected that all team members show up for the meetups in person unless previously discussed with the management team. There will be online access and we have plans to record it for future reference but again, ideally everyone is present for the meetups. - -Each week I will make an announcement containing any information regarding the weekly meetup. Meetup times and locations are expected to remain relatively consistent throughout the series. Any clashes will be dealt with in the meetup the week before and announced to all members. - -## Links and External Resources - -- [Content](/content/README.md) -- [Series Timeline](https://oraqlle.notion.site/4421929e24944bcfa4f3a771fb322a2b?v=d844b80fad784a7a9dcc273442b222a1) -- [cppreference](https://en.cppreference.com/w/Main_Page) -- [Compiler Explorer](https://www.godbolt.org/) -- [bpt docs](https://bpt.pizza/docs/latest/index.html) -- [Godbolt Links](/GODBOLT.md) - -## Current Educators, Demonstrators and Managers - -- Tyler Swann -- Nikhil Kannachel +# ... or serve build and serve locally +$ mdbook serve --open +``` ## Contributors - Tyler Swann +- Nikhil Kannachel -## Concerns +## Code of Conduct, License & Contributing -Refer to the [Code of Conduct](/CODE_OF_CONDUCT.md) and the [License](/LICENSE) for this repository for the expected behavior of contributors and users of the repository. If you have any concerns reach out to me (Tyler Swann) on Teams or follow standard MDN procedures for issues you are having within the team, branch or MDN. +Refer to the [Code of Conduct](/CODE_OF_CONDUCT.md) and the [License](/LICENSE) for this repository for the expected behavior of contributors and users of the repository. If you have any concerns reach out to me (Tyler Swann) on Teams or follow standard M procedures for issues you are having within the team, branch or MDN. If you wish to contribute, follow the [contributing guide](/CONTRIBUTING.md). diff --git a/book.toml b/book.toml new file mode 100644 index 0000000..c79a80e --- /dev/null +++ b/book.toml @@ -0,0 +1,12 @@ +[book] +authors = ["Tyler Swann"] +title = "High Performance Programming" +description = "Monash DeepNeuron's High Performance Programming Curriculum" + +language = "en" +multilingual = false + +src = "src" + +[output.html] +mathjax-support = true diff --git a/content/README.md b/content/README.md deleted file mode 100644 index 446d260..0000000 --- a/content/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# Content - -This directory contains all the relevant content information for the workshop series as well as a brief overview of the week-by-week content that will be covered. Below are links to the `README.md` for each week. These will guide you through the content, examples and tasks for each week. - -The idea is that you will use this repository as your guide for the series, reading the relevant information in the markdown files. This should make it easier to follow along, copy commands and code and access the needed resources. The slides for each week are more of a brief overview designed to be a visual aid to the meetups and thus might not have all the necessary information in order to do the tasks. - -## Weekly Synopsis - -- [Part 1](/content/part1/README.md) - Introduction -- [Part 2](/content/part2/README.md) - Types, Variables, Operators, IO, Conditionals, Loops and Functions -- [Part 3](/content/part3/README.md) - Pointers, Slices, References, Dynamic Memory and The Standard Library -- [Part 4](/content/part4/README.md) - Functional Programming, Namespaces, Enumerations, Unions, Structures -- [Part 5](/content/part5/README.md) - Classes, Templates, Generics and Concepts -- [Part 6](/content/part6/README.md) - Iterators, Data Structures, Algorithms, Ranges and Views -- [Part 7](/content/part7/README.md) - Parallel Algorithms, Atomics, Threads, Mutexes & Locks and Async - -## Home - -- [Home](/README.md) diff --git a/content/part1/README.md b/content/part1/README.md deleted file mode 100644 index d20484a..0000000 --- a/content/part1/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# Part 1 - -Introduction to Shells, Terminals, Compilers and C++ - -## Overview - -Welcome to Week 0 of MDN's High Performance Programming Workshop Series (HPP). This week you will hit the ground running and setup your device for developing with C++ by downloading the essential tools and software. - -You will create your first C++ program, looking at various components and getting a basic understanding of how to compile and execute you code. You will also get access to unique tools to speed and ease development including learning the basics of version control with Git and GitHub. - -## Tasks - -You tasks this week are outlined in the following documents. Follow each in order to setup you device and run your first program. There is quite a bit to setup before you can start coding with C++ but all of this is to ensure that the experience down the track is as seamless as possible. - -1. [Git & GitHub](/content/part1/tasks/github.md) -2. [WSL](/content/part1/tasks/wsl.md) -3. [Homebrew](/content/part1/tasks/homebrew.md) -4. [bpt](/content/part1/tasks/bpt.md) -5. [VSCode](/content/part1/tasks/vscode.md) -6. [Hello World](/content/part1/tasks/helloworld.md) -7. [Compiler Explorer](/content/part1/tasks/godbolt.md) - -## Weekly Meetup - -This weeks meetup will be on 09/12/22 in Room: 135B, Building: LTB (Learning and Teaching Building), Location: 19 Ancora Imparo Way, Clayton. - -## Go To - -- [Task 1 : Git & GitHub](/content/part1/tasks/github.md) -- [Examples](/content/part1/examples/README.md) -- [Slides](/content/part1/slides/README.md) -- [Content](/content/README.md) -- [Home](/README.md) diff --git a/content/part1/examples/README.md b/content/part1/examples/README.md deleted file mode 100644 index ca83eb5..0000000 --- a/content/part1/examples/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Table of Contents - -- [hello](/content/part1/examples/hello/README.md) - Basic 'hello world' example in C++. -- [hello-bpt](/content/part1/examples/hello-bpt/README.md) - Hello World using bpt. diff --git a/content/part1/slides/README.md b/content/part1/slides/README.md deleted file mode 100644 index 0537892..0000000 --- a/content/part1/slides/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# Slides - -![Slides 01](/content/part1/slides/imgs/hpp_part1-01.png) -![Slides 02](/content/part1/slides/imgs/hpp_part1-02.png) -![Slides 03](/content/part1/slides/imgs/hpp_part1-03.png) -![Slides 04](/content/part1/slides/imgs/hpp_part1-04.png) -![Slides 05](/content/part1/slides/imgs/hpp_part1-05.png) -![Slides 06](/content/part1/slides/imgs/hpp_part1-06.png) -![Slides 07](/content/part1/slides/imgs/hpp_part1-07.png) -![Slides 08](/content/part1/slides/imgs/hpp_part1-08.png) -![Slides 09](/content/part1/slides/imgs/hpp_part1-09.png) -![Slides 10](/content/part1/slides/imgs/hpp_part1-10.png) -![Slides 11](/content/part1/slides/imgs/hpp_part1-11.png) -![Slides 12](/content/part1/slides/imgs/hpp_part1-12.png) -![Slides 13](/content/part1/slides/imgs/hpp_part1-13.png) -![Slides 14](/content/part1/slides/imgs/hpp_part1-14.png) -![Slides 15](/content/part1/slides/imgs/hpp_part1-15.png) -![Slides 16](/content/part1/slides/imgs/hpp_part1-16.png) -![Slides 17](/content/part1/slides/imgs/hpp_part1-17.png) -![Slides 18](/content/part1/slides/imgs/hpp_part1-18.png) -![Slides 19](/content/part1/slides/imgs/hpp_part1-19.png) -![Slides 20](/content/part1/slides/imgs/hpp_part1-20.png) -![Slides 21](/content/part1/slides/imgs/hpp_part1-21.png) -![Slides 22](/content/part1/slides/imgs/hpp_part1-22.png) diff --git a/content/part1/tasks/bpt.md b/content/part1/tasks/bpt.md deleted file mode 100644 index a3c85d9..0000000 --- a/content/part1/tasks/bpt.md +++ /dev/null @@ -1,36 +0,0 @@ -# bpt - -bpt is a C++ build and packaging tool. It makes consuming C?++ libraries, running tests and packaging your code much easier and conventional techniques. - -## Contents - -- [bpt](#bpt) - - [Contents](#contents) - - [Task 4](#task-4) - - [4.1 : Installing bpt](#41--installing-bpt) - - [Links](#links) - -## Task 4 - -### 4.1 : Installing bpt - -Installing bpt is relatively simple. Simply run. - -```sh -# Linux -curl bpt.pizza/get/linux -Lo bpt - -# MacOS -curl bpt.pizza/get/macos -Lo bpt - -# Both -chmod a+x bpt -./bpt install-yourself -``` - -## Links - -- [Previous Page : Homebrew](/content/part1/tasks/homebrew.md) -- [Next Page : VSCode](/content/part1/tasks/vscode.md) -- [Content](/content/README.md) -- [HOME](/README.md) diff --git a/content/part1/tasks/github.md b/content/part1/tasks/github.md deleted file mode 100644 index 693c4bc..0000000 --- a/content/part1/tasks/github.md +++ /dev/null @@ -1,37 +0,0 @@ -# Git and GitHub - -## Contents - -- [Git and GitHub](#git-and-github) - - [Contents](#contents) - - [What is Git](#what-is-git) - - [What is GitHub](#what-is-github) - - [Task 1](#task-1) - - [1.1 : Create a Github Account](#11--create-a-github-account) - - [1.2 : Get Access to MDN Organization](#12--get-access-to-mdn-organization) - - [Links](#links) - -## What is Git - -Git is a Software Control Management (SCM) tool. It keeps track of files current changes, keeps a history of files and has facilities to merge and distribute changes amongst contributors. Projects are managed in what is called a repository (repo). A repo is just a directory/folder that a software project lives. You are currently looking at a file in a repo. - -## What is GitHub - -GitHub is a website that hosts and helps manage remote/online repos. This makes it easier to collaborate and share repos as well as having many tools to automate project pipelines. - -## Task 1 - -### 1.1 : Create a Github Account - -To start off, create a GitHub account. Use a personal email as you are likely to use this throughout your career. Take note of your username and email as you will need it later. - -### 1.2 : Get Access to MDN Organization - -During this weeks meetup we will gather your usernames to give you direct access the the MDN GitHub organization. This will allow you to access the discussion channels and direct access to the repos within. - -## Links - -- [Previous Page : Part 1](/content/part1/README.md) -- [Next Page : WSL](/content/part1/tasks/wsl.md) -- [Content](/content/README.md) -- [HOME](/README.md) diff --git a/content/part1/tasks/godbolt.md b/content/part1/tasks/godbolt.md deleted file mode 100644 index 2171c95..0000000 --- a/content/part1/tasks/godbolt.md +++ /dev/null @@ -1,37 +0,0 @@ -# Compiler Explorer - -Compiler Explorer; sometimes referred to as Godbolt (after its creator Matthew Godbolt) is an online compiler for C++. It is good for testing and prototyping small code snippets from C++ across many different compiler versions, from different vendors and on different architectures. - -It also displays the assembly output allowing you to have a closer look at what goes on under the hood in C++. It also allows sharing permalinks to instances of Godbolt with specific code and configuration running so you xan distribute working code to anyone as long as they got a browser. - -## Contents - -- [Compiler Explorer](#compiler-explorer) - - [Contents](#contents) - - [Task 7](#task-7) - - [7.1 Godbolt ⚡](#71-godbolt-) - - [Final Words](#final-words) - - [Links](#links) - -## Task 7 - -### 7.1 Godbolt ⚡ - -Head on over to [Compiler Explorer](https://www.godbolt.org/) and copy the "Hello World" program, replacing the code in the editor with your "Hello World". It should automatically compile and build and display the results in one of the screens. - -If this doesn't work, not to worry, we'll cover it in more detail in the meetup. if you want to see a running, shared godbolt program, click [here](https://www.godbolt.org/z/GKxzfees6). - -## Final Words - -Well done! You just finished your first week of High Performance Programming. I know it was pretty dull and tedious installing the all the software but now you are setup good and well to start learning the most powerful programming language. - -All the best and see you at the meetup. - -\- Tyler - -## Links - -- [Previous Page : Hello World](/content/part1/tasks/helloworld.md) -- [Back to Part 1](/content/part1/README.md) -- [Content](/content/README.md) -- [HOME](/README.md) diff --git a/content/part1/tasks/homebrew.md b/content/part1/tasks/homebrew.md deleted file mode 100644 index 67a5342..0000000 --- a/content/part1/tasks/homebrew.md +++ /dev/null @@ -1,118 +0,0 @@ -# Homebrew - -Homebrew is a system package manager similar to `apt` however, it is cross platform allowing us to install packages on Linux and MacOS. - -## Contents - -- [Homebrew](#homebrew) - - [Contents](#contents) - - [Task 3](#task-3) - - [3.1 : Installing Homebrew](#31--installing-homebrew) - - [Note](#note) - - [3.2 : Packages from Homebrew](#32--packages-from-homebrew) - - [3.3 : Installing Git (MacOS only)](#33--installing-git-macos-only) - - [3.4 : Authenticating Git](#34--authenticating-git) - - [Links](#links) - -## Task 3 - -### 3.1 : Installing Homebrew - -Install Homebrew is super simple. Copy the following command and run. - -```sh -/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" -``` - -#### Note - -> For linux users you will need `curl` installed. Look below for the relevant commands. - -Like `apt` we should update its package index and packages (although non-should be installed if this is a fresh install). - -```sh -# Update Index -brew update - -# Upgrade Packages -brew upgrade -``` - -### 3.2 : Packages from Homebrew - -The reason we are using Homebrew: - -1. Package consistency between members regardless of OS and machine. -2. It is the goto for MacOS users but is available to everyone. -3. GCC 12 is most consistently available from Homebrew. - -Here are the packages you need to install depending on your setup. For linux : - -```sh -# WSL (Windows) -brew install gcc gdb llvm cmake - -# MacOS -brew install curl wget gcc gdb llvm cmake - -# Linux -# Replace `apt` with your distros package manager. -sudo apt update -sudo apt upgrade -y -sudo apt install git curl wget ca-certificates build-essential -/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" -brew update -brew upgrade -brew install gcc gdb llvm cmake -``` - -You can verify that GCC installed the correct version by running the following command. The output should be similar to this. - -```sh -$ gcc-12 -v -Reading specs from /home/linuxbrew/.linuxbrew/Cellar/gcc/12.2.0/bin/../lib/gcc/current/gcc/x86_64-pc-linux-gnu/12/specs -COLLECT_GCC=gcc-12 -. -. -. -gcc version 12.2.0 (Homebrew GCC 12.2.0) -``` - -### 3.3 : Installing Git (MacOS only) - -In the last couple tasks Linux and WSL users have installed Git however, Git is a bit awkward on MacOS. To check if Git is already installed run. - -```sh -git --version -``` - -If it says something like command cannot be found, this is ok. If it prompts you to install Git, follow the on-screen instructions. Once finished, run the above command and you should get. - -```sh -git --version -git version 2.25.1 -``` - -If it didn't prompt you, you can install it with Homebrew. - -```sh -$ brew install git -$ git --version -git version 2.25.1 -``` - -### 3.4 : Authenticating Git - -Now that any machine you could be working on has Git, we can authenticate its use with GitHub with a few simple commands. Replace the `<>` with your GitHub credentials from earlier - -```sh -git config --global user.name "" -git config --global user.email "" -``` - -## Links - -- [Previous Page : WSL](/content/part1/tasks/wsl.md) -- [Next Page : bpt](/content/part1/tasks/bpt.md) -- [Content](/content/README.md) -- [HOME](/README.md) diff --git a/content/part1/tasks/vscode.md b/content/part1/tasks/vscode.md deleted file mode 100644 index 683e5db..0000000 --- a/content/part1/tasks/vscode.md +++ /dev/null @@ -1,76 +0,0 @@ -# VSCode - -VSCode is a text editor with rich extension ecosystem allowing developers to customize a developer environment to their needs. - -## Contents - -- [VSCode](#vscode) - - [Contents](#contents) - - [Note](#note) - - [Task 5](#task-5) - - [5.1 : Installing VSCode](#51--installing-vscode) - - [Note (WSL)](#note-wsl) - - [5.2 : WSL Extensions](#52--wsl-extensions) - - [5.3 : General Extensions](#53--general-extensions) - - [Links](#links) - -## Note - -> We will be using VSCode throughout this series and as such, all debugging examples will be in reference to VSCode but you are free to use any text editor you want and we will do our best to adjust. - -## Task 5 - -### 5.1 : Installing VSCode - -Go to [VSCode's Download page](https://code.visualstudio.com/download) and install it for your host OS. - -#### Note (WSL) - -> For Windows/WSL users, this means install on the Windows side. - -### 5.2 : WSL Extensions - -On its own VSCode is just a text editor like Notepad but with colour text however, using extensions we can set it up nicely for developing with C++. - -For WSL users, you need to install some extensions on the Windows installation of VSCode in order for VSCode to access the correct permissions. MacOS and Linux users, you can skip to [4.3](#53--general-extensions). - -Open VSCode how you would any other app in Windows. In VSCode, open the extension marketplace tab. In the search bar, search for the following extensions click on the extension and click and click the install button for them. - -- Remote development -- WSL -- Remote SSH - -You can now close VSCode and continue. - -### 5.3 : General Extensions - -To open VSCode from the terminal, open a new terminal window and type. - -```sh -# `.` represents 'this' directory -code . -``` - -This will open VSCode in the current user directory which should be `~` which represents your users home directory. WSL users, make sure to launch VSCode from your WSL terminal this time so the extensions install on you WSL platform. - -In VSCode, open the extension marketplace tab. In the search bar, search for the following extensions click on the extension and click and click the install button for them. - -- C/C++ -- GitLens -- Git Graph -- GitHub Pull Requests and Issues -- Sonarlint -- markdownlint -- Markdown All In One -- Markdown Preview GitHub Styling - -You may have to restart VSCode for the extensions to load. Finally, press `ctrl + ,` to open settings. in the search bar search for "cpp default standard". In the drop down select `c++20`. - -And that is it, everything should be set up and ready to go. You next task is to run your first C++ code. - -## Links - -- [Previous Page : bpt](/content/part1/tasks/bpt.md) -- [Next Page : Hello World](/content/part1/tasks/helloworld.md) -- [Content](/content/README.md) -- [HOME](/README.md) diff --git a/content/part2/README.md b/content/part2/README.md deleted file mode 100644 index 16c4b33..0000000 --- a/content/part2/README.md +++ /dev/null @@ -1,30 +0,0 @@ -# Part 2 - -Types, Variables, Qualifiers, Operators and Streams - -## Overview - -This week you will be introduced to C++ type system, how it differs from other languages and how types reflect machine architecture. You will also learn about variable declarations, type qualifiers and a few of the key operators and IO facilities in C++. You will also be exposed to the concept of ordering, equality and the logical operators in C++. You will also learn about conditional logic and how it can be used to create structure and control the flow of a program. You will also learn about C++ looping facilities and how it can be used to perform iterative programming. Finally, you will learn the basics of functions in C++. This part of the course is designed to span two weeks with only a single meetup towards the end of the two week period. - -## Tasks - -1. [The C++ Type System](/content/part2/tasks/typesystem.md) -2. [Primitive Types](/content/part2/tasks/types.md) -3. [Variables](/content/part2/tasks/variables.md) -4. [Operators](/content/part2/tasks/operators.md) -5. [IO](/content/part2/tasks/io.md) -6. [Equality, Ordering & Logical Operators](/content/part2/tasks/eqordlogic.md) -7. [Conditional Expressions](/content/part2/tasks/condexpr.md) -8. [Loops](/content/part2/tasks/loops.md) -9. [Functions](/content/part2/tasks/functions.md) - -## Weekly Meetup - -This weeks meetup will be on 09/12/22 in Room: 135B, Building: LTB (Learning and Teaching Building), Location: 19 Ancora Imparo Way, Clayton. - -## Links - -- [Task 1 : The C++ Type System](/content/part2/tasks/typesystem.md) -- [Slides](/content/part2/slides/README.md) -- [Content](/content/README.md) -- [Home](/README.md) diff --git a/content/part2/slides/README.md b/content/part2/slides/README.md deleted file mode 100644 index bc3ece6..0000000 --- a/content/part2/slides/README.md +++ /dev/null @@ -1,66 +0,0 @@ -# Slides - -![Slides 01](/content/part2/slides/imgs/hpp_part2-01.png) -![Slides 02](/content/part2/slides/imgs/hpp_part2-02.png) -![Slides 03](/content/part2/slides/imgs/hpp_part2-03.png) -![Slides 04](/content/part2/slides/imgs/hpp_part2-04.png) -![Slides 05](/content/part2/slides/imgs/hpp_part2-05.png) -![Slides 06](/content/part2/slides/imgs/hpp_part2-06.png) -![Slides 07](/content/part2/slides/imgs/hpp_part2-07.png) -![Slides 08](/content/part2/slides/imgs/hpp_part2-08.png) -![Slides 09](/content/part2/slides/imgs/hpp_part2-09.png) -![Slides 10](/content/part2/slides/imgs/hpp_part2-10.png) -![Slides 11](/content/part2/slides/imgs/hpp_part2-11.png) -![Slides 12](/content/part2/slides/imgs/hpp_part2-12.png) -![Slides 13](/content/part2/slides/imgs/hpp_part2-13.png) -![Slides 14](/content/part2/slides/imgs/hpp_part2-14.png) -![Slides 15](/content/part2/slides/imgs/hpp_part2-15.png) -![Slides 16](/content/part2/slides/imgs/hpp_part2-16.png) -![Slides 17](/content/part2/slides/imgs/hpp_part2-17.png) -![Slides 18](/content/part2/slides/imgs/hpp_part2-18.png) -![Slides 19](/content/part2/slides/imgs/hpp_part2-19.png) -![Slides 20](/content/part2/slides/imgs/hpp_part2-20.png) -![Slides 21](/content/part2/slides/imgs/hpp_part2-21.png) -![Slides 22](/content/part2/slides/imgs/hpp_part2-22.png) -![Slides 23](/content/part2/slides/imgs/hpp_part2-23.png) -![Slides 24](/content/part2/slides/imgs/hpp_part2-24.png) -![Slides 25](/content/part2/slides/imgs/hpp_part2-25.png) -![Slides 26](/content/part2/slides/imgs/hpp_part2-26.png) -![Slides 27](/content/part2/slides/imgs/hpp_part2-27.png) -![Slides 28](/content/part2/slides/imgs/hpp_part2-28.png) -![Slides 29](/content/part2/slides/imgs/hpp_part2-29.png) -![Slides 30](/content/part2/slides/imgs/hpp_part2-30.png) -![Slides 31](/content/part2/slides/imgs/hpp_part2-31.png) -![Slides 32](/content/part2/slides/imgs/hpp_part2-32.png) -![Slides 33](/content/part2/slides/imgs/hpp_part2-33.png) -![Slides 34](/content/part2/slides/imgs/hpp_part2-34.png) -![Slides 35](/content/part2/slides/imgs/hpp_part2-35.png) -![Slides 36](/content/part2/slides/imgs/hpp_part2-36.png) -![Slides 37](/content/part2/slides/imgs/hpp_part2-37.png) -![Slides 38](/content/part2/slides/imgs/hpp_part2-38.png) -![Slides 39](/content/part2/slides/imgs/hpp_part2-39.png) -![Slides 40](/content/part2/slides/imgs/hpp_part2-40.png) -![Slides 41](/content/part2/slides/imgs/hpp_part2-41.png) -![Slides 42](/content/part2/slides/imgs/hpp_part2-42.png) -![Slides 43](/content/part2/slides/imgs/hpp_part2-43.png) -![Slides 44](/content/part2/slides/imgs/hpp_part2-44.png) -![Slides 45](/content/part2/slides/imgs/hpp_part2-45.png) -![Slides 46](/content/part2/slides/imgs/hpp_part2-46.png) -![Slides 47](/content/part2/slides/imgs/hpp_part2-47.png) -![Slides 48](/content/part2/slides/imgs/hpp_part2-48.png) -![Slides 49](/content/part2/slides/imgs/hpp_part2-49.png) -![Slides 50](/content/part2/slides/imgs/hpp_part2-50.png) -![Slides 51](/content/part2/slides/imgs/hpp_part2-51.png) -![Slides 52](/content/part2/slides/imgs/hpp_part2-52.png) -![Slides 53](/content/part2/slides/imgs/hpp_part2-53.png) -![Slides 54](/content/part2/slides/imgs/hpp_part2-54.png) -![Slides 55](/content/part2/slides/imgs/hpp_part2-55.png) -![Slides 56](/content/part2/slides/imgs/hpp_part2-56.png) -![Slides 57](/content/part2/slides/imgs/hpp_part2-57.png) -![Slides 58](/content/part2/slides/imgs/hpp_part2-58.png) -![Slides 59](/content/part2/slides/imgs/hpp_part2-59.png) -![Slides 60](/content/part2/slides/imgs/hpp_part2-60.png) -![Slides 61](/content/part2/slides/imgs/hpp_part2-61.png) -![Slides 62](/content/part2/slides/imgs/hpp_part2-62.png) -![Slides 63](/content/part2/slides/imgs/hpp_part2-63.png) -![Slides 64](/content/part2/slides/imgs/hpp_part2-64.png) diff --git a/content/part3/README.md b/content/part3/README.md deleted file mode 100644 index ea99383..0000000 --- a/content/part3/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# Part 3 - -Pointers, Slices, Dynamic Memory, References and The Standard Library - -## Overview - -This week you will be introduced to C++'s memory model and how it allows us to have precise control over memory resources in C++. You will also cover the difference in stack and heap based memory and the facilities for obtaining memory. You will learn about pointers, references and how they allow you to reference data located elsewhere. You will also be introduced to C++'s slice type allowing to store multiple values in a single object. Finally, you get and introduction into a few fundamental types found in C++'s standard library that make working with memory and collections far easier. - -## Tasks - -1. [Pointers](/content/part3/tasks/pointers.md) -2. [Slices](/content/part3/tasks/slices.md) -3. [Dynamic Memory](/content/part3/tasks/memory.md) -4. [References](/content/part3/tasks/references.md) -5. [Introduction to the Standard Library](/content/part3/tasks/stdlib.md) - -## Weekly Meetup - -This weeks meetup will be on 14/12/2022 & 04/01/2023 - -## Go To - -- [Task 1 : Pointers](/content/part3/tasks/pointers.md) -- [Slides](/content/part3/slides/README.md) -- [Content](/content/README.md) -- [Home](/README.md) diff --git a/content/part3/slides/README.md b/content/part3/slides/README.md deleted file mode 100644 index 4b0de06..0000000 --- a/content/part3/slides/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# Slides - -![Slides 01](/content/part3/slides/imgs/hpp_part3-01.png) -![Slides 02](/content/part3/slides/imgs/hpp_part3-02.png) -![Slides 03](/content/part3/slides/imgs/hpp_part3-03.png) -![Slides 04](/content/part3/slides/imgs/hpp_part3-04.png) -![Slides 05](/content/part3/slides/imgs/hpp_part3-05.png) -![Slides 06](/content/part3/slides/imgs/hpp_part3-06.png) -![Slides 07](/content/part3/slides/imgs/hpp_part3-07.png) -![Slides 08](/content/part3/slides/imgs/hpp_part3-08.png) -![Slides 09](/content/part3/slides/imgs/hpp_part3-09.png) -![Slides 10](/content/part3/slides/imgs/hpp_part3-10.png) -![Slides 11](/content/part3/slides/imgs/hpp_part3-11.png) -![Slides 12](/content/part3/slides/imgs/hpp_part3-12.png) -![Slides 13](/content/part3/slides/imgs/hpp_part3-13.png) -![Slides 14](/content/part3/slides/imgs/hpp_part3-14.png) -![Slides 15](/content/part3/slides/imgs/hpp_part3-15.png) -![Slides 16](/content/part3/slides/imgs/hpp_part3-16.png) -![Slides 17](/content/part3/slides/imgs/hpp_part3-17.png) -![Slides 18](/content/part3/slides/imgs/hpp_part3-18.png) -![Slides 19](/content/part3/slides/imgs/hpp_part3-19.png) -![Slides 20](/content/part3/slides/imgs/hpp_part3-20.png) -![Slides 21](/content/part3/slides/imgs/hpp_part3-21.png) -![Slides 22](/content/part3/slides/imgs/hpp_part3-22.png) -![Slides 23](/content/part3/slides/imgs/hpp_part3-23.png) -![Slides 24](/content/part3/slides/imgs/hpp_part3-24.png) -![Slides 25](/content/part3/slides/imgs/hpp_part3-25.png) -![Slides 26](/content/part3/slides/imgs/hpp_part3-26.png) -![Slides 27](/content/part3/slides/imgs/hpp_part3-27.png) -![Slides 28](/content/part3/slides/imgs/hpp_part3-28.png) -![Slides 29](/content/part3/slides/imgs/hpp_part3-29.png) -![Slides 30](/content/part3/slides/imgs/hpp_part3-30.png) -![Slides 31](/content/part3/slides/imgs/hpp_part3-31.png) -![Slides 32](/content/part3/slides/imgs/hpp_part3-32.png) -![Slides 33](/content/part3/slides/imgs/hpp_part3-33.png) -![Slides 34](/content/part3/slides/imgs/hpp_part3-34.png) -![Slides 35](/content/part3/slides/imgs/hpp_part3-35.png) -![Slides 36](/content/part3/slides/imgs/hpp_part3-36.png) -![Slides 37](/content/part3/slides/imgs/hpp_part3-37.png) -![Slides 38](/content/part3/slides/imgs/hpp_part3-38.png) -![Slides 39](/content/part3/slides/imgs/hpp_part3-39.png) diff --git a/content/part4/README.md b/content/part4/README.md deleted file mode 100644 index 91c9045..0000000 --- a/content/part4/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# Part 4 - -Advanced Functions, Namespaces, Enumerations, Unions and Structures - -## Overview - -Throughout this part you will delve deeper into the practical abilities of C++ from advanced function usage and functional programming idioms to logical code separation and modularization. You will also be introduced to a features that allow for the creation of custom types. - -## Tasks - -1. [Advanced Functions](/content/part4/tasks/advfunc.md) -2. [Namespaces](/content/part4/tasks/namespaces.md) -3. [Enumerations](/content/part4/tasks/enums.md) -4. [Unions](/content/part4/tasks/unions.md) -5. [Structures](/content/part4/tasks/structs.md) - -## Weekly Meetup - -This weeks meetup will be on 04/01/2023 from 1:30pm. - -## Go To - -- [Task 1 : Advanced Functions](/content/part4/tasks/advfunc.md) -- [Slides](/content/part4/slides/README.md) -- [Content](/content/README.md) -- [Home](/README.md) diff --git a/content/part4/slides/README.md b/content/part4/slides/README.md deleted file mode 100644 index 7890ef3..0000000 --- a/content/part4/slides/README.md +++ /dev/null @@ -1,44 +0,0 @@ -# Slides - -![Slides 01](/content/part4/slides/imgs/hpp_part4-01.png) -![Slides 02](/content/part4/slides/imgs/hpp_part4-02.png) -![Slides 03](/content/part4/slides/imgs/hpp_part4-03.png) -![Slides 04](/content/part4/slides/imgs/hpp_part4-04.png) -![Slides 05](/content/part4/slides/imgs/hpp_part4-05.png) -![Slides 06](/content/part4/slides/imgs/hpp_part4-06.png) -![Slides 07](/content/part4/slides/imgs/hpp_part4-07.png) -![Slides 08](/content/part4/slides/imgs/hpp_part4-08.png) -![Slides 09](/content/part4/slides/imgs/hpp_part4-09.png) -![Slides 10](/content/part4/slides/imgs/hpp_part4-10.png) -![Slides 11](/content/part4/slides/imgs/hpp_part4-11.png) -![Slides 12](/content/part4/slides/imgs/hpp_part4-12.png) -![Slides 13](/content/part4/slides/imgs/hpp_part4-13.png) -![Slides 14](/content/part4/slides/imgs/hpp_part4-14.png) -![Slides 15](/content/part4/slides/imgs/hpp_part4-15.png) -![Slides 16](/content/part4/slides/imgs/hpp_part4-16.png) -![Slides 17](/content/part4/slides/imgs/hpp_part4-17.png) -![Slides 18](/content/part4/slides/imgs/hpp_part4-18.png) -![Slides 19](/content/part4/slides/imgs/hpp_part4-19.png) -![Slides 20](/content/part4/slides/imgs/hpp_part4-20.png) -![Slides 21](/content/part4/slides/imgs/hpp_part4-21.png) -![Slides 22](/content/part4/slides/imgs/hpp_part4-22.png) -![Slides 23](/content/part4/slides/imgs/hpp_part4-23.png) -![Slides 24](/content/part4/slides/imgs/hpp_part4-24.png) -![Slides 25](/content/part4/slides/imgs/hpp_part4-25.png) -![Slides 26](/content/part4/slides/imgs/hpp_part4-26.png) -![Slides 27](/content/part4/slides/imgs/hpp_part4-27.png) -![Slides 28](/content/part4/slides/imgs/hpp_part4-28.png) -![Slides 29](/content/part4/slides/imgs/hpp_part4-29.png) -![Slides 30](/content/part4/slides/imgs/hpp_part4-30.png) -![Slides 31](/content/part4/slides/imgs/hpp_part4-31.png) -![Slides 32](/content/part4/slides/imgs/hpp_part4-32.png) -![Slides 33](/content/part4/slides/imgs/hpp_part4-33.png) -![Slides 34](/content/part4/slides/imgs/hpp_part4-34.png) -![Slides 35](/content/part4/slides/imgs/hpp_part4-35.png) -![Slides 36](/content/part4/slides/imgs/hpp_part4-36.png) -![Slides 37](/content/part4/slides/imgs/hpp_part4-37.png) -![Slides 38](/content/part4/slides/imgs/hpp_part4-38.png) -![Slides 39](/content/part4/slides/imgs/hpp_part4-39.png) -![Slides 40](/content/part4/slides/imgs/hpp_part4-40.png) -![Slides 41](/content/part4/slides/imgs/hpp_part4-41.png) -![Slides 42](/content/part4/slides/imgs/hpp_part4-42.png) diff --git a/content/part4/tasks/structs.md b/content/part4/tasks/structs.md deleted file mode 100644 index 81caf60..0000000 --- a/content/part4/tasks/structs.md +++ /dev/null @@ -1,120 +0,0 @@ -# Structures - -## Contents - -- [Structures](#structures) - - [Contents](#contents) - - [Task 5](#task-5) - - [Task 4.1 : Structures](#task-41--structures) - - [Assignment 1 : Your Turn](#assignment-1--your-turn) - - [Requirements](#requirements) - - [Bonus](#bonus) - - [Submitting](#submitting) - - [Links](#links) - -## Task 5 - -### Task 4.1 : Structures - -Structures (structs) are fundamental to developing with C++. They allow for creating custom types that can have member variables, and member functions (methods). They allow for packing any amalgamation of data into a single type. Structures are created using the `struct` keyword. To access the members and methods of a struct the member access operator `.` is used. For pointers to struct types, the pointer member access operator `->` is used. - -> Note: The definition of a structure must have an `;` after the last brace. - -```cxx -#include -#include - -struct PairInt -{ - int first; - int second; - - /// Adds members of two `PairInt` - constexpr auto - add(const PairInt& o) - const noexcept - -> PairInt - { return PairInt{first + o.first, second + o.second}; } - - /// Overload `+~ cleaner `PairInt::add` call - friend constexpr auto - operator+ (const PairInt& x, const PairInt& y) - noexcept - -> PairInt - { return x.add(y); } - - /// Overload `<<` for printing - friend auto - operator<< (std::ostream& os, const PairInt& v) - -> std::ostream& - { - os << "(.first: " << v.first << ", .second: " << v.second << ")"; - return os; - } -}; - -auto main() -> int -{ - auto a = PairInt{5, 7}; - auto b = PairInt{.first = 2, .second = 9}; ///< Named aggregate initialisation - auto p = std::addressof(b); ///< Pointer to struct type - - std::cout << "a = " << a << std::endl; ///< `PairInt` works with `std::cout` - std::cout << "b = " << b << std::endl; - - std::cout << "a + b = " << a + b << std::endl; ///< Call to overloaded `+` - std::cout << "a + c = " << a + *p << std::endl; ///< Pointer to structs works like regular pointers - - std::cout << "a.add(b) = " << a.add(b) << std::endl; ///< Method access - std::cout << "p->add(a) = " << p->add(a) << std::endl; ///< Pointer member access - - return 0; -} -``` - -[Example](https://www.godbolt.org/z/6MbYMGGMz) - -> Note: Ignore the `friend` keyword for now. - -## Assignment 1 : Your Turn - -Having learnt a massive chunk of C++ now I want you to try and right some code for yourself. Your task is to create a triple struct, ie. like a 3D point but semantically more general. You must demonstrate and run all of the properties of the struct. The program should be called `triple.cxx` (or `triple.main.cxx` if using bpt) - -### Requirements - -- Must have three members of the same type (either `int`, `float` or `double`) -- A way to add two points -- A way to subtract two points -- A way to multiply a point by a scalar (of the same underlying type) -- A way to divide a point by a scalar (of the same underlying type) -- A way to be print a formatted output using `std::cout` - -### Bonus - -- A way to be created using input from `std::cin` -- Create a 'triple' structure for the other underlying types. - -### Submitting - -You can use Godbolt or bpt to build and test your struct. Once you have created your implementation: - -- clone this repo using `git clone https://github.com/MonashDeepNeuron/HPP.git`. -- create a new branch using `git checkout -b triple/`. -- create a folder in the `/content/part4` directory called `submissions/`. -- Copy your mini project into this directory (bpt setup, cmake scripts etc.) with a `README.md` or comment in the code on how to run the program (verify it still works). There is a sample header file in `/templates` that you can use. -- Go to and click 'New pull request'. -- Change the branches in the drop down so that your branch is going into `main` and `Create new pull request. -- Give the pull request a title and briefly describe what you were able to implement and any struggles you had. -- On the right side-panel, under the 'Assignees' section, click the cog and assign me. -- Click 'Create pull request' and I'll take it from there. - -> Note: If you created a GodBolt instance, put the link in a comment at the top of the file (under your copy comments). This is generated by clicking the `share` button in the top-right-most corner of the webpage and clicking the 'short link' option. - -This, ideally should be submitted before our meetup on 11/01/2023. Please note that I will be asking each of you a few questions about how you went and your thought processes in throughout the implementation. - -## Links - -- [Previous Page : Unions](/content/part4/tasks/enums.md) -- [Back to Part 4](/content/part4/README.md) -- [Content](/content/README.md) -- [HOME](/README.md) diff --git a/content/part5/README.md b/content/part5/README.md deleted file mode 100644 index ab9e9ad..0000000 --- a/content/part5/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# Part 5 - -Classes, Templates, Generics and Concepts - -## Overview - -Throughout this part you will discover C++ immensely customizable type system. How you can utilise structures and classes to create your own types from abstract base classes, data structures. You will also learn briefly about C++ Object Orientated facilities and how to utilise dynamic and static inheritance. You will also be introduced to generic programming through templates and metaprogramming. Finally you will learn about constraining your programs and enforcing requirements using C++ new concept faculties. - -## Tasks - -1. [Classes](/content/part5/tasks/classes.md) -2. [Templates](/content/part5/tasks/templates.md) -3. [Generics](/content/part5/tasks/generics.md) -4. [Concepts](/content/part5/tasks/concepts.md) - -## Weekly Meetup - -This weeks meetup will be on 18/01/2023 from 1:30pm. - -## Go To - -- [Task 1 : Classes](/content/part5/tasks/classes.md) -- [Slides](/content/part5/slides/README.md) -- [Content](/content/README.md) -- [Home](/README.md) diff --git a/content/part5/slides/README.md b/content/part5/slides/README.md deleted file mode 100644 index fe2489b..0000000 --- a/content/part5/slides/README.md +++ /dev/null @@ -1,47 +0,0 @@ -# Slides - -![Slides 01](/content/part5/slides/imgs/hpp_part5-01.png) -![Slides 02](/content/part5/slides/imgs/hpp_part5-02.png) -![Slides 03](/content/part5/slides/imgs/hpp_part5-03.png) -![Slides 04](/content/part5/slides/imgs/hpp_part5-04.png) -![Slides 05](/content/part5/slides/imgs/hpp_part5-05.png) -![Slides 06](/content/part5/slides/imgs/hpp_part5-06.png) -![Slides 07](/content/part5/slides/imgs/hpp_part5-07.png) -![Slides 08](/content/part5/slides/imgs/hpp_part5-08.png) -![Slides 09](/content/part5/slides/imgs/hpp_part5-09.png) -![Slides 10](/content/part5/slides/imgs/hpp_part5-10.png) -![Slides 11](/content/part5/slides/imgs/hpp_part5-11.png) -![Slides 12](/content/part5/slides/imgs/hpp_part5-12.png) -![Slides 13](/content/part5/slides/imgs/hpp_part5-13.png) -![Slides 14](/content/part5/slides/imgs/hpp_part5-14.png) -![Slides 15](/content/part5/slides/imgs/hpp_part5-15.png) -![Slides 16](/content/part5/slides/imgs/hpp_part5-16.png) -![Slides 17](/content/part5/slides/imgs/hpp_part5-17.png) -![Slides 18](/content/part5/slides/imgs/hpp_part5-18.png) -![Slides 19](/content/part5/slides/imgs/hpp_part5-19.png) -![Slides 20](/content/part5/slides/imgs/hpp_part5-20.png) -![Slides 21](/content/part5/slides/imgs/hpp_part5-21.png) -![Slides 22](/content/part5/slides/imgs/hpp_part5-22.png) -![Slides 23](/content/part5/slides/imgs/hpp_part5-23.png) -![Slides 24](/content/part5/slides/imgs/hpp_part5-24.png) -![Slides 25](/content/part5/slides/imgs/hpp_part5-25.png) -![Slides 26](/content/part5/slides/imgs/hpp_part5-26.png) -![Slides 27](/content/part5/slides/imgs/hpp_part5-27.png) -![Slides 28](/content/part5/slides/imgs/hpp_part5-28.png) -![Slides 29](/content/part5/slides/imgs/hpp_part5-29.png) -![Slides 30](/content/part5/slides/imgs/hpp_part5-30.png) -![Slides 31](/content/part5/slides/imgs/hpp_part5-31.png) -![Slides 32](/content/part5/slides/imgs/hpp_part5-32.png) -![Slides 33](/content/part5/slides/imgs/hpp_part5-33.png) -![Slides 34](/content/part5/slides/imgs/hpp_part5-34.png) -![Slides 35](/content/part5/slides/imgs/hpp_part5-35.png) -![Slides 36](/content/part5/slides/imgs/hpp_part5-36.png) -![Slides 37](/content/part5/slides/imgs/hpp_part5-37.png) -![Slides 38](/content/part5/slides/imgs/hpp_part5-38.png) -![Slides 39](/content/part5/slides/imgs/hpp_part5-39.png) -![Slides 40](/content/part5/slides/imgs/hpp_part5-40.png) -![Slides 41](/content/part5/slides/imgs/hpp_part5-41.png) -![Slides 42](/content/part5/slides/imgs/hpp_part5-42.png) -![Slides 43](/content/part5/slides/imgs/hpp_part5-43.png) -![Slides 44](/content/part5/slides/imgs/hpp_part5-44.png) -![Slides 45](/content/part5/slides/imgs/hpp_part5-45.png) diff --git a/content/part5/slides/imgs/hpp_part5-25.png b/content/part5/slides/imgs/hpp_part5-25.png deleted file mode 100644 index eb25c38..0000000 Binary files a/content/part5/slides/imgs/hpp_part5-25.png and /dev/null differ diff --git a/content/part5/slides/imgs/hpp_part5-39.png b/content/part5/slides/imgs/hpp_part5-39.png deleted file mode 100644 index 2106c24..0000000 Binary files a/content/part5/slides/imgs/hpp_part5-39.png and /dev/null differ diff --git a/content/part6/README.md b/content/part6/README.md deleted file mode 100644 index 793ec75..0000000 --- a/content/part6/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# Part 6 - -Iterators, Data Structures, Algorithms, Ranges and Views - -## Overview - -So far you have learnt a lot about the C++ language from user-defined types with classes, to generic programming with templates and concepts as well as (almost) all of the languages primitive types, control flow and looping mechanisms. With all of this you can pretty much get a computer to do anything. However, this is only the foundation; mind you all taught at once, what comes next is the fun part. We cover some the of facilities, techniques and practices focused on actually manipulating data and performing actual computation. Many of these facilities are available in the C++ standard library; after all this isn't C, we don't have to build everything from scratch. This will include everything from building up your algorithm intuition to exploring different data structures and how they work under the hood. We will also cover topics such as evaluation techniques, function composition and lifting. - -## Tasks - -1. [Iterators](/content/part6/tasks/iterators.md) -2. [Data Structures](/content/part6/tasks/data-structures.md) -3. [Algorithms](/content/part6/tasks/algorithms.md) -4. [Ranges](/content/part6/tasks/ranges.md) -5. [Views](/content/part6/tasks/views.md) - -## Weekly Meetup - -Meetups will be held on: - -This weeks meetup will be on 25/01/2023 from 1:30pm. - -## Go To - -- [Task 1 : Iterators](/content/part6/tasks/iterators.md) -- [Examples](/content/part/examples/README.md) -- [Slides](/content/part6/slides/README.md) -- [Content](/content/README.md) -- [Home](/README.md) diff --git a/content/part6/slides/imgs/hpp_part6-01.png b/content/part6/slides/imgs/hpp_part6-01.png deleted file mode 100644 index 245612c..0000000 Binary files a/content/part6/slides/imgs/hpp_part6-01.png and /dev/null differ diff --git a/content/part6/slides/imgs/hpp_part6-13.png b/content/part6/slides/imgs/hpp_part6-13.png deleted file mode 100644 index c5acf48..0000000 Binary files a/content/part6/slides/imgs/hpp_part6-13.png and /dev/null differ diff --git a/content/part6/tasks/views.md b/content/part6/tasks/views.md deleted file mode 100644 index c6c1733..0000000 --- a/content/part6/tasks/views.md +++ /dev/null @@ -1,207 +0,0 @@ -# Views - -## Contents - -- [Views](#views) - - [Contents](#contents) - - [Task 5](#task-5) - - [Task 5.1 : What is a View?](#task-51--what-is-a-view) - - [Task 5.2 : Lazy Evaluation](#task-52--lazy-evaluation) - - [Task 5.3 : Factories](#task-53--factories) - - [Task 5.4 : Range Adaptors, Composition \& The Pipe Operators](#task-54--range-adaptors-composition--the-pipe-operators) - - [Task 5.5 : Standard View Range Adaptors](#task-55--standard-view-range-adaptors) - - [Task 5.6 : Assignment 3](#task-56--assignment-3) - - [Requirements](#requirements) - - [Optional](#optional) - - [Submitting](#submitting) - - [Links](#links) - -## Task 5 - -### Task 5.1 : What is a View? - -A view is a simple abstraction on a range. Views can be thought of as a reference or pointer to a range that is cheap to copy, move, assign and destroy. Views allow for a ranges to be used in a lazy evaluation contexts. Views are found in the `std::ranges` namespace from the `` header, often with a '_view' suffix or can be found in the `std::views` namespace of the same header without the suffix. Views can be passed to range based algorithms or even used as the range evaluated in a range-for. - -Ranges can be created from an iterator and sentinel pair or a range using `std::subrange`. - -```cxx -#include -#include -#include -#include - -auto main() -> int -{ - auto v = std::vector{ 1, 2, 3, 4, 5 }; - - /// Note: This is unnecessary and is only a showcase - for (const auto& e : std::ranges::subrange(v.begin(), v.end())) - std::cout << e << " "; - - std::cout << std::endl; - - return 0; -} -``` - -[Example](https://www.godbolt.org/z/sE5Eq5a3z) - -### Task 5.2 : Lazy Evaluation - -What is lazy evaluation? Lazy evaluation is the process of delaying evaluation of functions and expressions until the result of the evaluation is actually needed. This reduces the amount of memory, compute cycles and evaluations the function undergoes and allows for easier composition of functions. - -### Task 5.3 : Factories - -Some views are used convert ranges and scalars into views. These views are called factories as they generate a view from its arguments. - -- `std::views::empty` - A view containing no element. It still takes an unused template type parameter. -- `std::views::single` - A owning view containing a single element. -- `std::views::iota` - A range factory, generating a elements from a repeatedly incremented initial value. This view can be bound to a final value or unbounded, generating an infinite view. Bounded iota views are exclusive ie. the bound is excluded from the resulting range. -- `std::views::istream` - A range factory, generating elements by repeated calls to `>>` on a input stream eg. `std::cin`. - -```cxx -#include -#include -#include - -auto main() -> int -{ - /// Prints "0 1 2 3 4 5 6 7 8 9 10" - std::ranges::copy(std::views::iota(0, 11), std::ostream_iterator(std::cout, " ")); - - return 0; -} -``` - -[Example](https://www.godbolt.org/z/brff8rY5T) - -- [`std::views::empty` : cppreference](https://en.cppreference.com/w/cpp/ranges/empty_view) -- [`std::views::single` : cppreference](https://en.cppreference.com/w/cpp/ranges/single_view) -- [`std::views::iota` : cppreference](https://en.cppreference.com/w/cpp/ranges/iota_view) -- [`std::views::istream` : cppreference](https://en.cppreference.com/w/cpp/ranges/basic_istream_view) - -### Task 5.4 : Range Adaptors, Composition & The Pipe Operators - -So far views aren't all that interesting. The true power of views comes from their ability to be composed. Composition allows for views to be combined to build more complex views over data while still adhering to lazy evaluation. Instead of evaluating each function one at a time a single function, which is the composition of all the view functions gets evaluated once for every access to the element. Views are composed using the pipe operator (`|`) and are read from left-to-right as opposed to inside-out. This makes function composition far more expressible and extensible. Range (including containers) or view object are 'piped' to the range adaptor with the resulting view; when evaluated, applying the range adaptor on the every element. - -### Task 5.5 : Standard View Range Adaptors - -- `std::views::transform` - a range adapter whose resulting view maps an unary function to the input range. -- `std::views::filter` - a range adaptor that whose resulting view excludes any element that do not satisfy an unary predicate. -- `std::views::reverse` - a range adaptor returning a view of the input range as if its order was reversed. -- `std::views::take` - a range adaptor whose resulting view take only $n$ elements from the input range. Performs bound checks to ensure that it doesn't take more elements then the view can see. -- `std::views::take_while` - a range adaptor whose resulting view contains every element until an unary predicate returns `false`. -- `std::views::drop` - a range adapter whose resulting view skips the first $n$ elements from a input range. -- `std::views::drop_while` - a range adaptor whose resulting view starts at the first element for which the unary predicate evaluates `false`. -- `std::views::join` - a range adaptor whose resulting view will flatten nested range or view object a single view. -- `std::views::split` - a range adaptor whose resulting view contains subranges split by a given deliminator. Is not entirely lazy and will eagerly move forward through the view at each iteration during evaluation. -- `std::views::lazy_split` - a range adaptor whose resulting view contains subranges split by a given deliminator Is entirely lazy evaluated but is unable to model the subranges as a [common range](https://en.cppreference.com/w/cpp/ranges/common_range)(a range with the same type for the iterator and sentinel) and cannot be used in algorithms expecting a bidirectional range (or higher). -- `std::views::common` - a range adaptor whose resulting view adapts the input range to have the same type for its iterator and sentinels. -- `std::views::element` - a range adaptor that accepts an input range with _Tuple-Like_ elements and whose resulting view contains the $Nth$ entry from every _Tuple-Like_ element of the input range. -- `std::views::keys` - a range adaptor who is a specialisations of `std::views::elements` taking the $0th$ entry of a view of _Tuple-Like_ elements. This can be used to obtain a view of just the keys of an associative container. -- `std::views::values` - a range adaptor who is a specialisations of `std::views::elements` taking the $1st$ entry of a view of _Tuple-Like_ elements. This can be used to obtain a view of just the values of an associative container. - -```cxx -#include -#include -#include - -auto square = [](const auto& x){ return x * x; }; -auto even = [](const auto& x){ return x % 2 == 0; }; - -auto main() -> int -{ - auto nums = std::views::iota(0) - | std::views::transform(square) - | std::views::filter(even) - | std::views::take(10); - - std::ranges::copy(nums, std::ostream_iterator(std::cout, " ")); - - std::cout << std::endl; - - return 0; -} -``` - -[Example](https://www.godbolt.org/z/3fdW1P7hj) - -- [`std::views::transform` : cppreference](https://en.cppreference.com/w/cpp/ranges/transform_view) -- [`std::views::filter` : cppreference](https://en.cppreference.com/w/cpp/ranges/filter_view) -- [`std::views::reverse` : cppreference](https://en.cppreference.com/w/cpp/ranges/reverse_view) -- [`std::views::take` : cppreference](https://en.cppreference.com/w/cpp/ranges/take_view) -- [`std::views::take_while` : cppreference](https://en.cppreference.com/w/cpp/ranges/take_while_view) -- [`std::views::drop` : cppreference](https://en.cppreference.com/w/cpp/ranges/drop_view) -- [`std::views::drop_while` : cppreference](https://en.cppreference.com/w/cpp/ranges/drop_while_view) -- [`std::views::join` : cppreference](https://en.cppreference.com/w/cpp/ranges/join_view) -- [`std::views::split` : cppreference](https://en.cppreference.com/w/cpp/ranges/split_view) -- [`std::views::lazy_split` : cppreference](https://en.cppreference.com/w/cpp/ranges/lazy_split_view) -- [`std::views::common` : cppreference](https://en.cppreference.com/w/cpp/ranges/common_view) -- [`std::views::elements` : cppreference](https://en.cppreference.com/w/cpp/ranges/elements_view) -- [`std::views::keys` : cppreference](https://en.cppreference.com/w/cpp/ranges/keys_view) -- [`std::views::values` : cppreference](https://en.cppreference.com/w/cpp/ranges/values_view) - -### Task 5.6 : Assignment 3 - -This assignment is a tricker one. Your job is to implement a [circular buffer](https://en.wikipedia.org/wiki/Circular_buffer) or a ring buffer. Circular buffers are First-In-First-Out buffers - -#### Requirements - -- Must be a `class` (or `struct`). -- Must have these constructors - - Default - - Copy - - Move - - Assignment Copy - - Assignment Move - - A destructor -- Must be templated for any element type `T`. -- Can either be dynamic in size (adds memory as it needs) or semi-static (fixed maximum but variable current size) -- Methods for pushing in a new element to the front and popping the oldest from the back. -- Introspection methods - - Current size - - Current capacity - - One that returns a pointer to the first element - - A method to check if the buffer is full - - A method to check if the buffer is empty -- Element access - - _at-like_ method with index checking - - subscript operator overload (`[]`) - -You can manually create and destroy the memory, use smart pointers or use a container to store the underlying memory. - -#### Optional - -- Have a custom iterator type with the relevant methods in the circular buffer for obtaining them. -- front and and back element access. -- Equality (`==`) and inequality (`!=`) operator overloads. -- Output stream operator overload (`>>`). -- Constructor and assignment operator overload (`=`) that take an `std::initializer_list`. -- Uses an allocator (eg. `std::allocator`) to allocate memory. -- Takes an additional template argument that correlates to a generic allocator type. -- Takes an additional template parameter that correlates to the type of the underlying container used to for storage of elements (eg. `std::vector`) making the circular buffer an adaptor. - -#### Submitting - -You can use Godbolt or bpt to build and test your struct. Once you have created your implementation: - -- clone this repo using `git clone https://github.com/MonashDeepNeuron/HPP.git`. -- create a new branch using `git checkout -b circular_buffer/`. -- create a folder in the `/content/part5` directory called `submissions/`. -- Copy your mini project into this directory (bpt setup, cmake scripts etc.) with a `README.md` or comment in the code on how to run the program (verify it still works). There is a sample header file in `/templates` that you can use. -- Go to and click 'New pull request'. -- Change the branches in the drop down so that your branch is going into `main` and `Create new pull request. -- Give the pull request a title and briefly describe what you were able to implement and any struggles you had. -- On the right side-panel, under the 'Assignees' section, click the cog and assign me. -- Click 'Create pull request' and I'll take it from there. - -> Note: If you created a GodBolt instance, put the link in a comment at the top of the file (under your copy comments). This is generated by clicking the `share` button in the top-right-most corner of the webpage and clicking the 'short link' option. - -This, ideally should be submitted before our meetup on 18/01/2023. Please note that I will be asking each of you a few questions about how you went and your thought processes in throughout the implementation. - -## Links - -- [Previous Page : Ranges](/content/part6/tasks/ranges.md) -- [Back to Part 6](/content/part6/README.md) -- [Content](/content/README.md) -- [HOME](/README.md) diff --git a/content/part7/README.md b/content/part7/README.md deleted file mode 100644 index 34fc00b..0000000 --- a/content/part7/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# Part 7 - -Parallel Algorithms, Atomics, Threads, Mutexes, Semaphores and Async/Await - -## Overview - -The focus of this part is parallelism and concurrency. Parallelism allows for large amount data to be broken into smaller chunks and processed at the same time. Even undergoing different transformations. Concurrency is the ability to run multiple jobs, tasks or functions simultaneously and communicate data and transfer between the states of the jobs. Together, these allow programs to expand the amount of work they are able to do and separate a program into multiple moving pieces. C++ has many primitives that make parallel and concurrent programming simple and effective. - -## Tasks - -1. [Parallel Algorithms](/content/part7/tasks/parallel-alg.md) -2. [Atomics](/content/part7/tasks/atomics.md) -3. [Thread](/content/part7/tasks/threads.md) -4. [Mutexes & Locks](/content/part7/tasks/mutexes.md) -5. [Async](/content/part7/tasks/async.md) - -## Weekly Meetup - -Meetups will be held on: - -- 8/02/2023 -- 15/02/2023 - -## Go To - -- [Task 1 : Parallel Algorithms](/content/part7/tasks/parallel-alg.md) -- [Slides](/content/part7/slides/README.md) -- [Content](/content/README.md) -- [Home](/README.md) diff --git a/content/part7/examples/par-algs/content/part6/slides/README.md b/content/part7/examples/par-algs/content/part6/slides/README.md deleted file mode 100644 index c195c49..0000000 --- a/content/part7/examples/par-algs/content/part6/slides/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# Slides - -![Slides 01](/content/part6/slides/imgs/hpp_part6-01.png) -![Slides 02](/content/part6/slides/imgs/hpp_part6-02.png) -![Slides 03](/content/part6/slides/imgs/hpp_part6-03.png) -![Slides 04](/content/part6/slides/imgs/hpp_part6-04.png) -![Slides 05](/content/part6/slides/imgs/hpp_part6-05.png) -![Slides 06](/content/part6/slides/imgs/hpp_part6-06.png) -![Slides 07](/content/part6/slides/imgs/hpp_part6-07.png) -![Slides 08](/content/part6/slides/imgs/hpp_part6-08.png) -![Slides 09](/content/part6/slides/imgs/hpp_part6-09.png) -![Slides 10](/content/part6/slides/imgs/hpp_part6-10.png) -![Slides 11](/content/part6/slides/imgs/hpp_part6-11.png) -![Slides 12](/content/part6/slides/imgs/hpp_part6-12.png) -![Slides 13](/content/part6/slides/imgs/hpp_part6-13.png) -![Slides 14](/content/part6/slides/imgs/hpp_part6-14.png) -![Slides 15](/content/part6/slides/imgs/hpp_part6-15.png) -![Slides 16](/content/part6/slides/imgs/hpp_part6-16.png) -![Slides 17](/content/part6/slides/imgs/hpp_part6-17.png) -![Slides 18](/content/part6/slides/imgs/hpp_part6-18.png) -![Slides 19](/content/part6/slides/imgs/hpp_part6-19.png) -![Slides 20](/content/part6/slides/imgs/hpp_part6-20.png) -![Slides 21](/content/part6/slides/imgs/hpp_part6-21.png) -![Slides 22](/content/part6/slides/imgs/hpp_part6-22.png) -![Slides 23](/content/part6/slides/imgs/hpp_part6-23.png) -![Slides 24](/content/part6/slides/imgs/hpp_part6-24.png) -![Slides 25](/content/part6/slides/imgs/hpp_part6-25.png) -![Slides 26](/content/part6/slides/imgs/hpp_part6-26.png) -![Slides 27](/content/part6/slides/imgs/hpp_part6-27.png) -![Slides 28](/content/part6/slides/imgs/hpp_part6-28.png) -![Slides 29](/content/part6/slides/imgs/hpp_part6-29.png) -![Slides 30](/content/part6/slides/imgs/hpp_part6-30.png) -![Slides 31](/content/part6/slides/imgs/hpp_part6-31.png) -![Slides 32](/content/part6/slides/imgs/hpp_part6-32.png) -![Slides 33](/content/part6/slides/imgs/hpp_part6-33.png) diff --git a/content/part7/slides/README.md b/content/part7/slides/README.md deleted file mode 100644 index 5d0c579..0000000 --- a/content/part7/slides/README.md +++ /dev/null @@ -1,34 +0,0 @@ -# Slides - -![Slides 01](/content/part7/slides/imgs/hpp_part7-01.png) -![Slides 02](/content/part7/slides/imgs/hpp_part7-02.png) -![Slides 03](/content/part7/slides/imgs/hpp_part7-03.png) -![Slides 04](/content/part7/slides/imgs/hpp_part7-04.png) -![Slides 05](/content/part7/slides/imgs/hpp_part7-05.png) -![Slides 06](/content/part7/slides/imgs/hpp_part7-06.png) -![Slides 07](/content/part7/slides/imgs/hpp_part7-07.png) -![Slides 08](/content/part7/slides/imgs/hpp_part7-08.png) -![Slides 09](/content/part7/slides/imgs/hpp_part7-09.png) -![Slides 10](/content/part7/slides/imgs/hpp_part7-10.png) -![Slides 11](/content/part7/slides/imgs/hpp_part7-11.png) -![Slides 12](/content/part7/slides/imgs/hpp_part7-12.png) -![Slides 13](/content/part7/slides/imgs/hpp_part7-13.png) -![Slides 14](/content/part7/slides/imgs/hpp_part7-14.png) -![Slides 15](/content/part7/slides/imgs/hpp_part7-15.png) -![Slides 16](/content/part7/slides/imgs/hpp_part7-16.png) -![Slides 17](/content/part7/slides/imgs/hpp_part7-17.png) -![Slides 18](/content/part7/slides/imgs/hpp_part7-18.png) -![Slides 19](/content/part7/slides/imgs/hpp_part7-19.png) -![Slides 20](/content/part7/slides/imgs/hpp_part7-20.png) -![Slides 21](/content/part7/slides/imgs/hpp_part7-21.png) -![Slides 22](/content/part7/slides/imgs/hpp_part7-22.png) -![Slides 23](/content/part7/slides/imgs/hpp_part7-23.png) -![Slides 24](/content/part7/slides/imgs/hpp_part7-24.png) -![Slides 25](/content/part7/slides/imgs/hpp_part7-25.png) -![Slides 26](/content/part7/slides/imgs/hpp_part7-26.png) -![Slides 27](/content/part7/slides/imgs/hpp_part7-27.png) -![Slides 28](/content/part7/slides/imgs/hpp_part7-28.png) -![Slides 29](/content/part7/slides/imgs/hpp_part7-29.png) -![Slides 30](/content/part7/slides/imgs/hpp_part7-30.png) -![Slides 31](/content/part7/slides/imgs/hpp_part7-31.png) -![Slides 32](/content/part7/slides/imgs/hpp_part7-32.png) diff --git a/content/part7/slides/hpp_part7.pdf b/content/part7/slides/hpp_part7.pdf deleted file mode 100644 index 536dea7..0000000 Binary files a/content/part7/slides/hpp_part7.pdf and /dev/null differ diff --git a/content/part7/slides/imgs/hpp_part7-01.png b/content/part7/slides/imgs/hpp_part7-01.png deleted file mode 100644 index 4658b0e..0000000 Binary files a/content/part7/slides/imgs/hpp_part7-01.png and /dev/null differ diff --git a/content/part7/slides/imgs/hpp_part7-04.png b/content/part7/slides/imgs/hpp_part7-04.png deleted file mode 100644 index b5f9a06..0000000 Binary files a/content/part7/slides/imgs/hpp_part7-04.png and /dev/null differ diff --git a/content/part7/slides/imgs/hpp_part7-08.png b/content/part7/slides/imgs/hpp_part7-08.png deleted file mode 100644 index c0938f5..0000000 Binary files a/content/part7/slides/imgs/hpp_part7-08.png and /dev/null differ diff --git a/content/part7/slides/imgs/hpp_part7-10.png b/content/part7/slides/imgs/hpp_part7-10.png deleted file mode 100644 index ba75988..0000000 Binary files a/content/part7/slides/imgs/hpp_part7-10.png and /dev/null differ diff --git a/content/part7/slides/imgs/hpp_part7-13.png b/content/part7/slides/imgs/hpp_part7-13.png deleted file mode 100644 index d552ef4..0000000 Binary files a/content/part7/slides/imgs/hpp_part7-13.png and /dev/null differ diff --git a/content/part7/slides/imgs/hpp_part7-28.png b/content/part7/slides/imgs/hpp_part7-28.png deleted file mode 100644 index 6db078e..0000000 Binary files a/content/part7/slides/imgs/hpp_part7-28.png and /dev/null differ diff --git a/scripts/slides.sh b/scripts/slides.sh index 5dbe559..6ee4e02 100755 --- a/scripts/slides.sh +++ b/scripts/slides.sh @@ -2,18 +2,18 @@ # $1 Start Range for Slides # $2 End Range for Slides -# $3 Part +# $3 Chapter -SLIDES="content/part$3/slides" +SLIDES="src/chapter$3" mkdir -p "$SLIDES/imgs" -pdftoppm -png -f $1 -l $2 "$SLIDES/hpp_part$3.pdf" "$SLIDES/imgs/hpp_part$3" +pdftoppm -png -f $1 -l $2 "$SLIDES/hpp_chapter$3.pdf" "$SLIDES/imgs/hpp_chapter$3" echo "" > "$SLIDES/README.md" -echo -e "# Slides\n" > "$SLIDES/README.md" +echo -e "# Slides\n" > "$SLIDES/slides$3.md" for n in $(eval echo {$1..$2}) do - echo -e "![Slides $n](/$SLIDES/imgs/hpp_part$3-$n.png)" >> "$SLIDES/README.md" + echo -e "![Slides $n](./imgs/hpp_chapter$3-$n.png)" >> "$SLIDES/slides$3.md" done diff --git a/GODBOLT.md b/src/GODBOLT.md similarity index 97% rename from GODBOLT.md rename to src/GODBOLT.md index 6cd67fc..17e68e4 100644 --- a/GODBOLT.md +++ b/src/GODBOLT.md @@ -2,13 +2,13 @@ All Compiler Explorer links used. -format: +format: --- -1. [Example : 1.6.2](/content/part1/examples/hello/hello.cxx) -2. [Example 1.6.5](/content/part1/examples/hello-bpt) -3. [Example 1.7.1](https://www.godbolt.org/z/GKxzfees6) +1. [Example : 1.6.2](/content/chapter1/examples/hello/hello.cxx) +2. [Example : 1.6.5](/content/chapter1/examples/hello-bpt) +3. [Example : 1.7.1](https://www.godbolt.org/z/GKxzfees6) 4. [Example : 2.4.1~1](https://www.godbolt.org/z/xKMooTb4s) 5. [Example : 2.4.1~2](https://www.godbolt.org/z/eeYqPbcaT) 6. [Example : 2.4.1~3](https://www.godbolt.org/z/o9afoszjP) @@ -158,6 +158,3 @@ format: 150. [Example : 6.5.1](https://www.godbolt.org/z/sE5Eq5a3z) 151. [Example : 6.5.3](https://www.godbolt.org/z/brff8rY5T) 152. [Example : 6.5.5](https://www.godbolt.org/z/3fdW1P7hj) -153. [Example : ..]() -154. [Example : ..]() -155. [Example : ..]() diff --git a/src/SUMMARY.md b/src/SUMMARY.md new file mode 100644 index 0000000..ec726ad --- /dev/null +++ b/src/SUMMARY.md @@ -0,0 +1,85 @@ +# Summary + +[Home](./home.md) +[Foreword]() + +## Chapter 1 + +- [Getting Started](./chapter1/chapter1.md) + - [WSL](./chapter1/wsl.md) + - [Installing Software](./chapter1/software.md) + - [Hello World](./chapter1/helloworld.md) + - [Compiler Explorer](./chapter1/godbolt.md) + - [Slides](./chapter1/slides1.md) + +## Chapter 2 + +- [Basics of C++](./chapter2/chapter2.md) + - [The C++ Type System](./chapter2/typesystem.md) + - [Primitive Types](./chapter2/types.md) + - [Variables](./chapter2/variables.md) + - [Operators](./chapter2/operators.md) + - [IO](./chapter2/io.md) + - [Equality, Ordering & Logical Operators](./chapter2/eqordlogic.md) + - [Conditional Expressions](./chapter2/condexpr.md) + - [Loops](./chapter2/loops.md) + - [Functions](./chapter2/functions.md) + - [Slides](./chapter2/slides2.md) + +## Chapter 3 + +- [Memory](./chapter3/chapter3.md) + - [Pointers](./chapter3/pointers.md) + - [Slices](./chapter3/slices.md) + - [References](./chapter3/references.md) + - [Dynamic Memory](./chapter3/memory.md) + - [The Standard Library](./chapter3/stdlib.md) + - [Slides](./chapter3/slides3.md) + +## Chapter 4 + +- [Intermediate C++ Features](./chapter4/chapter4.md) + - [Advanced Function Concepts](./chapter4/advfunc.md) + - [Namespaces](./chapter4/namespaces.md) + - [Enumerations](./chapter4/enums.md) + - [Unions](./chapter4/unions.md) + - [Structures](./chapter4/structs.md) + - [Task 1](./chapter4/task1.md) + - [Slides](./chapter4/slides4.md) + +## Chapter 5 + +- [Generic Programming](./chapter5/chapter5.md) + - [Classes](./chapter5/classes.md) + - [Templates](./chapter5/templates.md) + - [Generics](./chapter5/generics.md) + - [Concepts](./chapter5/concepts.md) + - [Task 2](./chapter5/task2.md) + - [Slides](./chapter5/slides5.md) + +## Chapter 6 + +- [Algorithms & Data Structures](./chapter6/chapter6.md) + - [Iterators](./chapter6/iterators.md) + - [Data Structures](./chapter6/data-structures.md) + - [Algorithms](./chapter6/algorithms.md) + - [Ranges](./chapter6/ranges.md) + - [Views](./chapter6/views.md) + - [Task 3](./chapter6/task3.md) + - [Slides](./chapter6/slides6.md) + +## Chapter 7 + +- [Concurrent Computing](./chapter7/chapter7.md) + - [Parallel Algorithms](./chapter7/parallel-alg.md) + - [Atomics](./chapter7/atomics.md) + - [Threads](./chapter7/threads.md) + - [Mutexes](./chapter7/mutexes.md) + - [Asynchronous Programming](./chapter7/async.md) + - [Slides](./chapter7/slides7.md) + +## Appendix + +[Godbolt Examples](./GODBOLT.md) + +[Planned Additions](./planned.md) diff --git a/src/chapter1/chapter1.md b/src/chapter1/chapter1.md new file mode 100644 index 0000000..788a774 --- /dev/null +++ b/src/chapter1/chapter1.md @@ -0,0 +1,13 @@ +# Getting Started + +Let's begin by setting up your device for developing with C++. In this chapter we will discuss: + +- Installing WSL (Windows) +- Installing Homebrew for system package management +- Setting up Git and the basics of source version control +- Installing a C++ compiler +- Installing bpt, a C++ package and build tool +- Installing VSCode, a text editor +- Writing a C++ program that prints "Hello World!" +- How to compile and execute programs +- How to use Compiler Explorer to share code snippets. diff --git a/src/chapter1/examples/README.md b/src/chapter1/examples/README.md new file mode 100644 index 0000000..698575a --- /dev/null +++ b/src/chapter1/examples/README.md @@ -0,0 +1,4 @@ +# Table of Contents + +- [hello](/content/chapter1/examples/hello/README.md) - Basic 'hello world' example in C++. +- [hello-bpt](/content/chapter1/examples/hello-bpt/README.md) - Hello World using bpt. diff --git a/content/part1/examples/hello-bpt/.vscode/c_cpp_properties.json b/src/chapter1/examples/hello-bpt/.vscode/c_cpp_properties.json similarity index 100% rename from content/part1/examples/hello-bpt/.vscode/c_cpp_properties.json rename to src/chapter1/examples/hello-bpt/.vscode/c_cpp_properties.json diff --git a/content/part1/examples/hello-bpt/.vscode/launch.json b/src/chapter1/examples/hello-bpt/.vscode/launch.json similarity index 100% rename from content/part1/examples/hello-bpt/.vscode/launch.json rename to src/chapter1/examples/hello-bpt/.vscode/launch.json diff --git a/content/part1/examples/hello-bpt/.vscode/settings.json b/src/chapter1/examples/hello-bpt/.vscode/settings.json similarity index 100% rename from content/part1/examples/hello-bpt/.vscode/settings.json rename to src/chapter1/examples/hello-bpt/.vscode/settings.json diff --git a/content/part1/examples/hello-bpt/.vscode/tasks.json b/src/chapter1/examples/hello-bpt/.vscode/tasks.json similarity index 100% rename from content/part1/examples/hello-bpt/.vscode/tasks.json rename to src/chapter1/examples/hello-bpt/.vscode/tasks.json diff --git a/content/part1/examples/hello-bpt/README.md b/src/chapter1/examples/hello-bpt/README.md similarity index 100% rename from content/part1/examples/hello-bpt/README.md rename to src/chapter1/examples/hello-bpt/README.md diff --git a/content/part1/examples/hello-bpt/bpt.yaml b/src/chapter1/examples/hello-bpt/bpt.yaml similarity index 100% rename from content/part1/examples/hello-bpt/bpt.yaml rename to src/chapter1/examples/hello-bpt/bpt.yaml diff --git a/content/part1/examples/hello-bpt/src/hello.main.cxx b/src/chapter1/examples/hello-bpt/src/hello.main.cxx similarity index 100% rename from content/part1/examples/hello-bpt/src/hello.main.cxx rename to src/chapter1/examples/hello-bpt/src/hello.main.cxx diff --git a/content/part1/examples/hello/.vscode/c_cpp_properties.json b/src/chapter1/examples/hello/.vscode/c_cpp_properties.json similarity index 100% rename from content/part1/examples/hello/.vscode/c_cpp_properties.json rename to src/chapter1/examples/hello/.vscode/c_cpp_properties.json diff --git a/content/part1/examples/hello/.vscode/launch.json b/src/chapter1/examples/hello/.vscode/launch.json similarity index 100% rename from content/part1/examples/hello/.vscode/launch.json rename to src/chapter1/examples/hello/.vscode/launch.json diff --git a/content/part1/examples/hello/.vscode/settings.json b/src/chapter1/examples/hello/.vscode/settings.json similarity index 100% rename from content/part1/examples/hello/.vscode/settings.json rename to src/chapter1/examples/hello/.vscode/settings.json diff --git a/content/part1/examples/hello/.vscode/tasks.json b/src/chapter1/examples/hello/.vscode/tasks.json similarity index 100% rename from content/part1/examples/hello/.vscode/tasks.json rename to src/chapter1/examples/hello/.vscode/tasks.json diff --git a/content/part1/examples/hello/Makefile b/src/chapter1/examples/hello/Makefile similarity index 100% rename from content/part1/examples/hello/Makefile rename to src/chapter1/examples/hello/Makefile diff --git a/content/part1/examples/hello/README.md b/src/chapter1/examples/hello/README.md similarity index 65% rename from content/part1/examples/hello/README.md rename to src/chapter1/examples/hello/README.md index 2a64844..d844471 100644 --- a/content/part1/examples/hello/README.md +++ b/src/chapter1/examples/hello/README.md @@ -15,10 +15,6 @@ g++-12 -std=c++20 -o build/hello hello.cxx # With Makefile make ``` - -## Links - -- [HOME](/README.md) - [Content](/content/README.md) -- [Week 0](/content/part1/README.md) -- [Examples](/content/part1/examples/README.md) +- [Week 0](/content/chapter1/README.md) +- [Examples](/content/chapter1/examples/README.md) diff --git a/content/part1/examples/hello/hello.cxx b/src/chapter1/examples/hello/hello.cxx similarity index 100% rename from content/part1/examples/hello/hello.cxx rename to src/chapter1/examples/hello/hello.cxx diff --git a/src/chapter1/godbolt.md b/src/chapter1/godbolt.md new file mode 100644 index 0000000..da17fce --- /dev/null +++ b/src/chapter1/godbolt.md @@ -0,0 +1,9 @@ +# Compiler Explorer + +Compiler Explorer; sometimes referred to as Godbolt (after its creator Matthew Godbolt) is an online compiler for C++. It is good for testing and prototyping small code snippets from C++ across many different compiler versions, from different vendors and on different architectures. + +It also displays the assembly output allowing you to have a closer look at what goes on under the hood in C++. It also allows sharing permalinks to instances of Godbolt with specific code and configuration running so you xan distribute working code to anyone as long as they got a browser. + +## Godbolt ⚡ + +Head on over to [Compiler Explorer](https://www.godbolt.org/) and copy the "Hello World" program into the editor window. It should automatically compile, build and display the results in one of the screens. An example of a sharable link from Godbolt is [here](https://www.godbolt.org/z/GKxzfees6). diff --git a/content/part1/tasks/helloworld.md b/src/chapter1/helloworld.md similarity index 70% rename from content/part1/tasks/helloworld.md rename to src/chapter1/helloworld.md index 0dda243..4c84339 100644 --- a/content/part1/tasks/helloworld.md +++ b/src/chapter1/helloworld.md @@ -2,21 +2,7 @@ If you've never programmed before, a "Hello World" program is a simplest program and is often used to introduce a language. The first Hello World was created in Brian Kernighan's 1972 "A Tutorial Introduction to the Language B". -## Contents - -- [Hello World!](#hello-world) - - [Contents](#contents) - - [Task 6](#task-6) - - [6.1 : Introducing C++](#61--introducing-c) - - [6.2 : First C++](#62--first-c) - - [6.3 : Build and Run](#63--build-and-run) - - [6.4 : Debugging](#64--debugging) - - [6.5 : Hello World - bpt](#65--hello-world---bpt) - - [Links](#links) - -## Task 6 - -### 6.1 : Introducing C++ +## Introducing C++ Before you write you first C++ program I will cover a basic synopsis of the language's features. @@ -30,28 +16,28 @@ Because of C++ ability to run on baremetal, many people claim it is a "low-level But C++ can style more directly interact with the hardware, how can that be if it isn't a low level language. Two things give C++ its power over hardware, first is its _memory model_. Many languages have little or no notion of memory. Data is data and it is as big or small as it is. How big is `int` in Python? To many this doesn't cross their minds when writing Python because you don't need to and that is one of the many benefits of Python. However, there is limits to resources you can use in some circumstances and sometimes you need to be able to guarantee certain memory usages from your software. C++ is one of the language that has a "conscious" notion of memory usage and gives you control over these resources. There is one problem with this, not all computer architectures are the same and don't have the same notion of memory. To tackle this, C++ uses the notion of a universal abstract machine. This is C++ second power over hardware. It has mechanisms for interacting with the underlying hardware through the OS but how it gets there is not to the concern of the developer (unless developing in kernel-space as opposed to user-space). You can use standardized features to access these resources effectively. -I mentioned above that C++ is strongly typed with a static type system. What does this mean? A strong typing basically means that types will not be implicitly cast (converted) to a different type (there are some exceptions to this but we'll cover this in [week 1](/content/part2/README.md)). A static type system means that all data must have an explicit type that must be known at compile time. +I mentioned above that C++ is strongly typed with a static type system. What does this mean? A strong typing basically means that types will not be implicitly cast (converted) to a different type (there are some exceptions to this but we'll cover this in chapter 2). A static type system means that all data must have an explicit type that must be known at compile time. To wrap it off I'll briefly discuss the paradigms and styles you can write C++ in. The most obvious is procedural, similar to C. This paradigm simply uses free functions that operate on free data, performing instructions according to a procedure or set of instructions. Paired with procedural programming, C++ also allows for imperative programming style programming which consists of functions changing the systems state. This style centers mostly on telling the computer what exactly what you want done. C++ also support object-oriented-programming (OOP) with its primary IO library using many OOP patterns to create runtime polymorphism. The most popular paradigm used in C++ today is generic programming. C++ has many features that allows you to write code for generic types as opposed to creating new functions for every possible combination of types. Finally, C++ also supports functional programming patterns that allow for for creating general purpose algorithms that are composed create more specific data manipulation. -Hopefully this gives you an idea into the kind of language C++ is and how powerful of a language it is. +Hopefully this gives you an idea into the kind of language C++. -### 6.2 : First C++ +## Hello C++ -To begin we are going to open a new terminal window. We car going to create a directory called "hello", enter it and create some files and open VSCode there. +To begin we are going to open a new terminal window. We are going to create a directory called "hello", enter it and create some files and open VSCode there. ```sh # Makes new directory -mkdir hello +$ mkdir hello # Enter `hello` -cd hello +$ cd hello # Create files `hello.cxx` and `README.md` -touch hello.cxx README.md +$ touch hello.cxx README.md # Open VSCode -code . +$ code . ``` Open the `hello.cxx` file by clicking it on the left file view. @@ -82,11 +68,9 @@ auto main () -> int } ``` -[Example](/content/part1/examples/hello/hello.cxx) +[Example](./examples/hello/hello.cxx) -Don't worry too much about the details as we will discuss in greater detail during the meetup. - -### 6.3 : Build and Run +## Build and Run Press `` ctrl + ` `` to open an integrated terminal window in VSCode. Make a new directory called `build` and run the following command to compile the code. @@ -108,7 +92,7 @@ Let's break this command down. - `-o build/hello` - The `-o` flag indicates and output file name. Because we wrote it with a path in front of it (`build/*`), it will output to that path. - `hello.cxx` - The source file we want to compile. -### 6.4 : Debugging +## Debugging Debugging is the crux of fixing issues in code. Debuggers allow us to step through the running code and diagnose any issues that are occurring as they occur. Debugging a single executable is pretty trivial but a sufficiently large codebase can become quite complex. @@ -116,17 +100,17 @@ For that reason we are going to go into debugging a little bit more at the meetu If you know how a debugger works, you can have a play with VSCode and see if you can get it to work. -### 6.5 : Hello World - bpt +## Hello World using bpt -`make` is a useful tool and paired with Cmake you can configure and build very large and complex code bases, but these configuration files are hard to read, tedious to write and error prone. Cmake is also a good and pretty standard in industry for C and C++ developers, but this standard is pretty outdated. So for the majority of this series we're going to be using a new tool called `bpt`. bpt is a lot like `pip` (Python), `gem` (Ruby), `hackage` (Haskell) and `cargo` (Rust) allow near seamless control over control over dependencies, testing and distribution of our software. +`make` is a useful tool and paired with `cmake` you can configure and build very large and complex code bases, but these configuration files are hard to read, tedious to write and error prone. Cmake is also a good and pretty standard in industry for C and C++ developers, but this standard is pretty outdated. So for the majority of this series we're going to be using a new tool called `bpt`. bpt is a lot like `pip` (Python), `gem` (Ruby), `hackage` (Haskell) and `cargo` (Rust) allow near seamless control over control over dependencies, testing and distribution of our software. -One thing to note is bpt experimental, robust enough to handle most cases but has a few caveats, however, beyond a few libraries to ease utility, we won't need many dependencies as we are mostly look at the C++ language and C++ standard library and tus dependencies won't be a major issue. However, we using bpt as it has a pretty robust, plug-and-play testing framework and more intuitive build procedures. +> Note: bpt is experimental but robust enough to handle most cases. bpt only has a few libraries however, we won't need any dependencies as we are mostly look at the C++ language and C++ Standard Library. To start off open a new terminal window and run the following command. Keep the default options by pressing enter for each instruction. ```sh -bpt new hello-bpt -code hello-bpt +$ bpt new hello-bpt +$ code hello-bpt ``` The directory structure should look like this: @@ -141,14 +125,14 @@ hello-bpt └── hello-bpt.hpp ``` -You can delete the `hello-bpt` directory and its contents in the `src/` directory as these are just temporaries. Create a file in `src/` called `hello.main.cxx`. Copy the "Hello World" program from your other directory (or above again) and past into the newly created file. +You can delete the `hello-bpt` directory that is within the `src/` directory as these are just template files. Create a file in `src/` called `hello.main.cxx`. Copy the "Hello World" program from your other directory (or above again) and past into the newly created file. -> bpt uses 'stem-leaf' file extensions to determine the purpose of a file. e.g. the `*.main.*` middle stem indicates to bpt that this is a executable that is run (as opposed to a library). You'll learn more about these as we go along. +> Note: bpt uses 'stem-leaf' file extensions to determine the purpose of a file. e.g. the `*.main.*` middle stem indicates to bpt that this is a executable that is run (as opposed to a library). You'll learn more about these as we go along. Now simply run the following command to build the bpt project. ```sh -bpt build -t :c++20:gcc-12 -o build +$ bpt build -t :c++20:gcc-12 -o build ``` This will spit out the binary into `build/`, dropping both file extensions. To run the program, simply call. @@ -158,11 +142,4 @@ $ ./build/hello Hello World! ``` -[Example](/content/part1/examples/hello-bpt) - -## Links - -- [Previous Page : VSCode](/content/part1/tasks/vscode.md) -- [Next Page : Compiler Explorer](/content/part1/tasks/godbolt.md) -- [Content](/content/README.md) -- [HOME](/README.md) +[Example](./examples/hello-bpt/src/hello.main.cxx) diff --git a/content/part1/slides/hpp_part1.pdf b/src/chapter1/hpp_chapter1.pdf similarity index 63% rename from content/part1/slides/hpp_part1.pdf rename to src/chapter1/hpp_chapter1.pdf index 9e64ac5..f28342c 100644 Binary files a/content/part1/slides/hpp_part1.pdf and b/src/chapter1/hpp_chapter1.pdf differ diff --git a/content/part1/slides/hpp_part1.pptx b/src/chapter1/hpp_chapter1.pptx similarity index 100% rename from content/part1/slides/hpp_part1.pptx rename to src/chapter1/hpp_chapter1.pptx diff --git a/content/part1/slides/imgs/hpp_part1-01.png b/src/chapter1/imgs/hpp_chapter1-01.png similarity index 100% rename from content/part1/slides/imgs/hpp_part1-01.png rename to src/chapter1/imgs/hpp_chapter1-01.png diff --git a/content/part1/slides/imgs/hpp_part1-02.png b/src/chapter1/imgs/hpp_chapter1-02.png similarity index 100% rename from content/part1/slides/imgs/hpp_part1-02.png rename to src/chapter1/imgs/hpp_chapter1-02.png diff --git a/content/part1/slides/imgs/hpp_part1-03.png b/src/chapter1/imgs/hpp_chapter1-03.png similarity index 100% rename from content/part1/slides/imgs/hpp_part1-03.png rename to src/chapter1/imgs/hpp_chapter1-03.png diff --git a/content/part1/slides/imgs/hpp_part1-04.png b/src/chapter1/imgs/hpp_chapter1-04.png similarity index 100% rename from content/part1/slides/imgs/hpp_part1-04.png rename to src/chapter1/imgs/hpp_chapter1-04.png diff --git a/content/part1/slides/imgs/hpp_part1-05.png b/src/chapter1/imgs/hpp_chapter1-05.png similarity index 100% rename from content/part1/slides/imgs/hpp_part1-05.png rename to src/chapter1/imgs/hpp_chapter1-05.png diff --git a/content/part1/slides/imgs/hpp_part1-06.png b/src/chapter1/imgs/hpp_chapter1-06.png similarity index 100% rename from content/part1/slides/imgs/hpp_part1-06.png rename to src/chapter1/imgs/hpp_chapter1-06.png diff --git a/content/part1/slides/imgs/hpp_part1-07.png b/src/chapter1/imgs/hpp_chapter1-07.png similarity index 100% rename from content/part1/slides/imgs/hpp_part1-07.png rename to src/chapter1/imgs/hpp_chapter1-07.png diff --git a/content/part1/slides/imgs/hpp_part1-08.png b/src/chapter1/imgs/hpp_chapter1-08.png similarity index 100% rename from content/part1/slides/imgs/hpp_part1-08.png rename to src/chapter1/imgs/hpp_chapter1-08.png diff --git a/content/part1/slides/imgs/hpp_part1-09.png b/src/chapter1/imgs/hpp_chapter1-09.png similarity index 100% rename from content/part1/slides/imgs/hpp_part1-09.png rename to src/chapter1/imgs/hpp_chapter1-09.png diff --git a/content/part1/slides/imgs/hpp_part1-10.png b/src/chapter1/imgs/hpp_chapter1-10.png similarity index 100% rename from content/part1/slides/imgs/hpp_part1-10.png rename to src/chapter1/imgs/hpp_chapter1-10.png diff --git a/content/part1/slides/imgs/hpp_part1-11.png b/src/chapter1/imgs/hpp_chapter1-11.png similarity index 100% rename from content/part1/slides/imgs/hpp_part1-11.png rename to src/chapter1/imgs/hpp_chapter1-11.png diff --git a/content/part1/slides/imgs/hpp_part1-12.png b/src/chapter1/imgs/hpp_chapter1-12.png similarity index 100% rename from content/part1/slides/imgs/hpp_part1-12.png rename to src/chapter1/imgs/hpp_chapter1-12.png diff --git a/content/part1/slides/imgs/hpp_part1-13.png b/src/chapter1/imgs/hpp_chapter1-13.png similarity index 100% rename from content/part1/slides/imgs/hpp_part1-13.png rename to src/chapter1/imgs/hpp_chapter1-13.png diff --git a/content/part1/slides/imgs/hpp_part1-14.png b/src/chapter1/imgs/hpp_chapter1-14.png similarity index 100% rename from content/part1/slides/imgs/hpp_part1-14.png rename to src/chapter1/imgs/hpp_chapter1-14.png diff --git a/content/part1/slides/imgs/hpp_part1-15.png b/src/chapter1/imgs/hpp_chapter1-15.png similarity index 100% rename from content/part1/slides/imgs/hpp_part1-15.png rename to src/chapter1/imgs/hpp_chapter1-15.png diff --git a/content/part1/slides/imgs/hpp_part1-16.png b/src/chapter1/imgs/hpp_chapter1-16.png similarity index 100% rename from content/part1/slides/imgs/hpp_part1-16.png rename to src/chapter1/imgs/hpp_chapter1-16.png diff --git a/content/part1/slides/imgs/hpp_part1-17.png b/src/chapter1/imgs/hpp_chapter1-17.png similarity index 82% rename from content/part1/slides/imgs/hpp_part1-17.png rename to src/chapter1/imgs/hpp_chapter1-17.png index 9029cad..b6ebe3c 100644 Binary files a/content/part1/slides/imgs/hpp_part1-17.png and b/src/chapter1/imgs/hpp_chapter1-17.png differ diff --git a/content/part1/slides/imgs/hpp_part1-18.png b/src/chapter1/imgs/hpp_chapter1-18.png similarity index 100% rename from content/part1/slides/imgs/hpp_part1-18.png rename to src/chapter1/imgs/hpp_chapter1-18.png diff --git a/content/part1/slides/imgs/hpp_part1-19.png b/src/chapter1/imgs/hpp_chapter1-19.png similarity index 100% rename from content/part1/slides/imgs/hpp_part1-19.png rename to src/chapter1/imgs/hpp_chapter1-19.png diff --git a/content/part1/slides/imgs/hpp_part1-20.png b/src/chapter1/imgs/hpp_chapter1-20.png similarity index 100% rename from content/part1/slides/imgs/hpp_part1-20.png rename to src/chapter1/imgs/hpp_chapter1-20.png diff --git a/content/part1/slides/imgs/hpp_part1-21.png b/src/chapter1/imgs/hpp_chapter1-21.png similarity index 100% rename from content/part1/slides/imgs/hpp_part1-21.png rename to src/chapter1/imgs/hpp_chapter1-21.png diff --git a/content/part1/slides/imgs/hpp_part1-22.png b/src/chapter1/imgs/hpp_chapter1-22.png similarity index 100% rename from content/part1/slides/imgs/hpp_part1-22.png rename to src/chapter1/imgs/hpp_chapter1-22.png diff --git a/content/part1/tasks/imgs/taskmanager.png b/src/chapter1/imgs/taskmanager.png similarity index 100% rename from content/part1/tasks/imgs/taskmanager.png rename to src/chapter1/imgs/taskmanager.png diff --git a/src/chapter1/slides1.md b/src/chapter1/slides1.md new file mode 100644 index 0000000..376e297 --- /dev/null +++ b/src/chapter1/slides1.md @@ -0,0 +1,24 @@ +# Slides + +![Slides 01](./imgs/hpp_chapter1-01.png) +![Slides 02](./imgs/hpp_chapter1-02.png) +![Slides 03](./imgs/hpp_chapter1-03.png) +![Slides 04](./imgs/hpp_chapter1-04.png) +![Slides 05](./imgs/hpp_chapter1-05.png) +![Slides 06](./imgs/hpp_chapter1-06.png) +![Slides 07](./imgs/hpp_chapter1-07.png) +![Slides 08](./imgs/hpp_chapter1-08.png) +![Slides 09](./imgs/hpp_chapter1-09.png) +![Slides 10](./imgs/hpp_chapter1-10.png) +![Slides 11](./imgs/hpp_chapter1-11.png) +![Slides 12](./imgs/hpp_chapter1-12.png) +![Slides 13](./imgs/hpp_chapter1-13.png) +![Slides 14](./imgs/hpp_chapter1-14.png) +![Slides 15](./imgs/hpp_chapter1-15.png) +![Slides 16](./imgs/hpp_chapter1-16.png) +![Slides 17](./imgs/hpp_chapter1-17.png) +![Slides 18](./imgs/hpp_chapter1-18.png) +![Slides 19](./imgs/hpp_chapter1-19.png) +![Slides 20](./imgs/hpp_chapter1-20.png) +![Slides 21](./imgs/hpp_chapter1-21.png) +![Slides 22](./imgs/hpp_chapter1-22.png) diff --git a/src/chapter1/software.md b/src/chapter1/software.md new file mode 100644 index 0000000..ef0ef81 --- /dev/null +++ b/src/chapter1/software.md @@ -0,0 +1,104 @@ +# Installing Software + +In this section we will install all the relevant software for developing C++ programs. + +## WSL & Linux + +To get started open a new terminal session (for WSL, use the WSL terminal) and update your system package managers local package index. This is a list of all available packages and their versions. We can then install some system critical packages that we need in order to develop C++ programs. From there we can install Homebrew, a cross platform package manager which we will use to install our C++ compiler(s) and debuggers. + +```sh +# Update apt (replace apt with relevant package manager if you are not on Ubuntu) +$ sudo apt update +$ sudo apt upgrade -y + +# Install system packages +$ sudo apt install git curl wget ca-certificates build-essential + +# Install Homebrew and update +$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" +$ brew update +$ brew upgrade + +# Install C++ compiler(s), debuggers +$ brew install gcc llvm gdb +``` + +## MacOS + +To begin, open a new terminal session install Homebrew, a cross platform package manager which will then use to install our C++ compiler(s), debuggers, cURL and Git. + +```sh +$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" +$ brew update +$ brew upgrade +$ brew install gcc llvm gdb curl git +``` + +## Verify Installation + +You can verify that GCC installed the correct version by running the following command. The output should be similar to this. + +```sh +$ gcc-12 -v +Reading specs from /home/linuxbrew/.linuxbrew/Cellar/gcc/12.2.0/bin/../lib/gcc/current/gcc/x86_64-pc-linux-gnu/12/specs +COLLECT_GCC=gcc-12 + +# Other info ... + +gcc version 12.2.0 (Homebrew GCC 12.2.0) +``` + +## Authenticating Git with GitHub + +If you have a GitHub (or other) account and you want to link it to your machine, run the following commands, replacing `<>` with your personal details. + +```sh +$ git config --global user.name "" +$ git config --global user.email "" +``` + +## Installing bpt + +bpt is a build and packaging tool for C++. It makes consuming C++ libraries, running tests and packaging your code much easier compared to conventional methods (notably Cmake). + +```sh +# Linux (WSL included) +curl bpt.pizza/get/linux -Lo bpt + +# MacOS +curl bpt.pizza/get/macos -Lo bpt + +# Both +chmod a+x bpt +./bpt install-yourself +``` + +## Installing VSCode + +Go to [VSCode's Download page](https://code.visualstudio.com/download) and install it for your machines host OS. + +> Note: For WSL users, this means install on the Windows side. + +On its own VSCode is just a text editor like Windows Notepad but with coloured text however, using extensions we can set it up for developing with any language. Open VSCode as you would any other app in Windows, MacOS or Linux. In VSCode, open the extension marketplace tab. In the search bar, search for the following extensions click on the extension and click and click the install button for them. + +> Note: For WSL users, only install the extensions marked 'WSL only' on the Windows side. The other extensions must be installed on the WSL. Install the them after opening VSCode in WSL (instructions below). + +- C/C++ +- GitLens +- Git Graph +- GitHub Pull Requests and Issues +- Sonarlint +- Remote development (WSL only) +- WSL (WSL only) +- Remote SSH (WSL only) + +You may have to restart VSCode for the extensions to load. Finally, press `ctrl + ,` to open settings. in the search bar search for "cpp default standard". In the drop down select `c++20`. + +To open VSCode from the terminal, open a new terminal window and type. + +```sh +# `.` represents 'this' directory +$ code . +``` + +This will open VSCode in the current user directory which should be `~` which represents your users home directory. WSL users, make sure to launch VSCode from your WSL terminal this time. And that is it, everything should be set up and ready to go. diff --git a/content/part1/tasks/wsl.md b/src/chapter1/wsl.md similarity index 62% rename from content/part1/tasks/wsl.md rename to src/chapter1/wsl.md index 724386f..9adfe94 100644 --- a/content/part1/tasks/wsl.md +++ b/src/chapter1/wsl.md @@ -1,53 +1,43 @@ # WSL -## Contents +In this section we will install WSL. This is a virtualized Linux Kernel for Windows. This makes managing developer tools far easier and separates your development OS (Linux) from your personal OS (Windows). -- [WSL](#wsl) - - [Contents](#contents) - - [Operating System](#operating-system) - - [Note](#note) - - [Task 2](#task-2) - - [2.1 : Update Windows and Virtualization Check](#21--update-windows-and-virtualization-check) - - [2.2 : Windows Terminal](#22--windows-terminal) - - [2.3 : WSL](#23--wsl) - - [2.4 : APT & Packages](#24--apt--packages) - - [Links](#links) +> Note: This section only applies to Windows users. -## Operating System - -Developing C++ on Windows can be a bit of a hassle to setup and use beyond Windows. Instead, Microsoft offers virtualized OS called Windows Subsystem for Linux or WSL. WSL is a native Linux kernel running alongside your Windows OS but unlike dual booting, they share the same filesystem, allowing you to work on Linux inside Windows. Using Linux is much easier to develop C++ code. - -### Note - -> If you currently are running MacOS or Linux already (including WSL) you can skip this tasks and move onto the next one. - -## Task 2 - -### 2.1 : Update Windows and Virtualization Check +## Update Windows and Virtualization Check Before we begin, it is best to ensure we have the most recent Windows update available. Go to **Settings > Updates** and install any updates to your system. -Secondly, you will want to ensure that virtualization is enabled on your device. To do this open 'Task Manager', click more details, open the performance tab and make sure you are on the CPU performance section. In the details below the CPU's graph there should be an option called 'virtualization'. This should have the value 'Enabled' next to it. If it doesn't, you will need to enable a feature called SVM in your computers BIOS. If you are comfortable doing this; go for it but if you do not want to do this yourself do not worry. We will ensure everyone is setup correctly in the first meetup. Continue reading through as there will be a way you can start coding at the end of the tasks. +Secondly, you will want to ensure that virtualization is enabled on your device. To do this open 'Task Manager', click more details, open the performance tab and make sure you are on the CPU performance section. In the details below the CPU's graph there should be an option called 'virtualization'. This should have the value 'Enabled' next to it. If it doesn't, you will need to enable a feature called SVM in your computers BIOS. If you are comfortable doing this; go for it but if you do not want to do this yourself do not worry. We will ensure everyone is setup correctly in the first meetup. Continue reading through as there will be a way you can start coding at the end of the sections. -![Task Manager Example](/content/part1/tasks/imgs/taskmanager.png) +![Task Manager Example](./imgs/taskmanager.png) -### 2.2 : Windows Terminal +## Windows Terminal To get started with WSL we will want a new terminal environment for the WSL shell. Fortunately, Microsoft has an awesome project called Windows Terminal (WT). It is able to hold many instances of different shells an dis fully customizable. To install it, simply open the [Microsoft Store](https://www.microsoft.com/store/productId/9N0DX20HK701) apps and search for "Windows Terminal" and click "install". -### 2.3 : WSL +## WSL Install -To install WSL, we need to open PowerShell terminal with administrative privileges. Click on the Windows Start button (bottom left icon on the taskbar) and type "PowerShell", select "Run as Administrator". This will open a new shell. Now run: +To install WSL, we need to open PowerShell terminal with administrative privileges. Click on the Windows Start button (bottom left icon on the sectionbar) and type "PowerShell", select "Run as Administrator". This will open a new shell. Now run: ```ps -wsl --install -d Ubuntu-20.04 +> wsl --install -d Ubuntu-20.04 ``` This may require a reboot. This will install WSL as well as an image of Ubuntu. Click Start again and type "Ubuntu" and run the application. Follow the on screen instructions to create your user and password for WSL. This is different from you Windows credentials. Now open WT and press `ctrl + ,` again. On the settings page that pops up, the first drop down called "Default Profile" should now have an option called Ubuntu (or something similar). Choose this as your default profile. WSL is now installed. Create a new shell tab with `ctrl + shift + t` and the shell prompt should now display you WSL username. -### 2.4 : APT & Packages +> ### Command Line Notation +> +> In this chapter and throughout the book, we’ll show some commands used in the +> terminal. Lines that you should enter in a terminal all start with `$`. You +> don’t need to type the `$` character; it’s the command line prompt shown to +> indicate the start of each command. Lines that don’t start with `$` typically +> show the output of the previous command. Additionally, PowerShell-specific +> examples will use `>` rather than `$`. + +### APT & Packages Before you begin, you will need to update your systems packages. Packages on Ubuntu are managed by a tool called `apt`. For some context, updating packages takes two steps typically, first you update the package index, then you can update the relevant packages. @@ -55,26 +45,19 @@ Before you begin, you will need to update your systems packages. Packages on Ubu # `sudo` represents 'super user do'. # This runs a command with admin. privileges. # Update apt's local package index. -sudo apt update +$ sudo apt update # The `-y` flag means upgrade yes to all. # This bypasses confirming package upgrades. # Upgrade packages with new versions -sudo apt upgrade -y +$ sudo apt upgrade -y ``` You will also want some packages `apt` that we will need for C++ development. ```sh # Installs specified packages (separated by spaces). -sudo apt install git curl wget ca-certificates build-essential +$ sudo apt install git curl wget ca-certificates build-essential ``` WSL should be installed and ready to go. - -## Links - -- [Previous Page : Git & Github](/content/part1/tasks/github.md) -- [Next Page : Homebrew](/content/part1/tasks/homebrew.md) -- [Content](/content/README.md) -- [HOME](/README.md) diff --git a/src/chapter2/README.md b/src/chapter2/README.md new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/chapter2/README.md @@ -0,0 +1 @@ + diff --git a/src/chapter2/chapter2.md b/src/chapter2/chapter2.md new file mode 100644 index 0000000..cbcf384 --- /dev/null +++ b/src/chapter2/chapter2.md @@ -0,0 +1,3 @@ +# Basics of C++ + +In this chapter you will be introduced to C++ the type system, how it differs from other languages and how types reflect machine architecture. You will also learn about variable declarations, type qualifiers and a few of the key operators and IO facilities in C++. You will also be exposed to the concept of ordering, equality and the logical operators in C++. You will also learn about conditional logic and how it can be used to create structure and control the flow of a program. You will also learn about C++ looping facilities and how it can be used to perform iterative programming. Finally, you will learn the basics of functions in C++. diff --git a/content/part2/tasks/condexpr.md b/src/chapter2/condexpr.md similarity index 84% rename from content/part2/tasks/condexpr.md rename to src/chapter2/condexpr.md index 6b55558..1b4c3bb 100644 --- a/content/part2/tasks/condexpr.md +++ b/src/chapter2/condexpr.md @@ -1,21 +1,8 @@ # Conditional Expressions -## Contents +Conditional expressions use the concepts of equality and ordering to allow programs to branch. This means that different parts of a program will execute depending on the current state of a program. This allows for programs to be more adaptive and flexible to create. -- [Conditional Expressions](#conditional-expressions) - - [Contents](#contents) - - [Task 7](#task-7) - - [Task 7.1 : Scope](#task-71--scope) - - [Task 7.2 : if-expressions](#task-72--if-expressions) - - [Task 7.2.1 : else-expression](#task-721--else-expression) - - [Task 7.3 : Ternary Operator](#task-73--ternary-operator) - - [Task 7.4 : Switch Statements](#task-74--switch-statements) - - [Task 7.4.1 : Fallthroughs](#task-741--fallthroughs) - - [Links](#links) - -## Task 7 - -### Task 7.1 : Scope +## Scope One important concept in programming is the idea of scope. In C++, scope is very important as it can have an important impact on the design, performance in the safety of a program. Currently we have been running a program purely in the scope of the `main()` function. What denotes a scope in C++ is a pair of braces `{}`. Anything introduced within the braces is now in a new scope separate from the outside program. Objects from outside the new scope can be captured but anything created in a new scope is dropped at the end of the scope. @@ -43,7 +30,7 @@ auto main () -> int Scope blocks (or sometimes code blocks) allow us to encapsulate expressions. -### Task 7.2 : if-expressions +## if-expressions Control flow allows for programs to branch and follow non-linear execution patterns. In C++, this is done through structured conditional expressions. The primary one being an `if` expression. `if` expressions are followed by a code block surrounded in `{}`. If the condition is met, then the code block executes. @@ -97,7 +84,7 @@ auto main () -> int [Example](https://www.godbolt.org/z/31TcjvYrP) -### Task 7.2.1 : else-expression +## else-expression We can combine the `else` clause with an `if` expression to create and `else if` expression. This allows for you to create multiple branches in a single `if` statement. @@ -124,7 +111,7 @@ auto main () -> int [Example](https://www.godbolt.org/z/Md3Mfx3MK) -### Task 7.3 : Ternary Operator +## Ternary Operator `if` statements are the first step to building much more complex programs however, they are quite bulky in syntax for short conditional expressions. Instead we can use the ternary operator `?:` to build short and concise conditional expressions. A ternary expression has the following syntax. @@ -148,7 +135,7 @@ auto main () -> int [Example](https://www.godbolt.org/z/4n4xYh7T8) -### Task 7.4 : Switch Statements +## Switch Statements Another useful construct in C++ is a `switch` statement. `switch` statements encapsulate the idea of a jump table however, it is limited to integral types, thus the `switch` condition must be an integral type and have integral case labels. @@ -181,7 +168,7 @@ auto main () -> int [Example](https://www.godbolt.org/z/nz6TYWodK) -#### Task 7.4.1 : Fallthroughs +### Fallthroughs You will note that at the end of each of the case blocks there are `break` statements. These are used to exit the switch statement entirely. If this weren't there, each case would run in sequence. This is called fallthrough. most compilers will warn you of this. @@ -209,10 +196,3 @@ auto main () -> int ``` [Example](https://www.godbolt.org/z/9oEfYrMMq) - -## Links - -- [Previous Page : Equality, Ordering and Logical Operators](/content/part2/tasks/eqordlogic.md) -- [Next Page : Loops](/content/part2/tasks/loops.md) -- [Content](/content/README.md) -- [HOME](/README.md) diff --git a/content/part2/tasks/eqordlogic.md b/src/chapter2/eqordlogic.md similarity index 86% rename from content/part2/tasks/eqordlogic.md rename to src/chapter2/eqordlogic.md index c3c78e9..05bcd8c 100644 --- a/content/part2/tasks/eqordlogic.md +++ b/src/chapter2/eqordlogic.md @@ -1,22 +1,8 @@ # Equality, Ordering and Logical Operators -## Contents +The notion of equality and ordering is a common principle in Computer Science. It allows for data to be verified, organised and sorted. This fundamental principles underpin a lot of programming. C++ has many facilities not just for testing equality or ordering of types, value and other entities but also for customizing the behaviour. -- [Equality, Ordering and Logical Operators](#equality-ordering-and-logical-operators) - - [Contents](#contents) - - [Task 6](#task-6) - - [Task 6.1 : Equality](#task-61--equality) - - [Task 6.2 : Ordering](#task-62--ordering) - - [Task 6.3 : Spaceships and Ordering Types](#task-63--spaceships-and-ordering-types) - - [Task 6.3.1 : Strong Ordering](#task-631--strong-ordering) - - [Task 6.3.2 : Weak Ordering](#task-632--weak-ordering) - - [Task 6.3.3 : Partial Ordering](#task-633--partial-ordering) - - [Task 6.4 : Logical Operators](#task-64--logical-operators) - - [Links](#links) - -## Task 6 - -### Task 6.1 : Equality +## Equality A common operation in all of programming is to test for equality. In C++ primitive types are compared as arithmetic types, that is the systems ALU (Arithmetic and Logic Unit) will compare the bits of a value and return to the system whether the result is `true` or `false`. @@ -47,7 +33,7 @@ auto main () -> int [Example](https://www.godbolt.org/z/EK14h6fhd) -### Task 6.2 : Ordering +## Ordering Checking for equality is pretty straight forward. Some more interesting operations are the ordering operators. What is ordering? Ordering is a relationship of different values of the same type. Ordering is what gives numbers their sequence (`2 < 3`). Ordering operators allow use to check if some ordering condition is met. @@ -81,7 +67,7 @@ auto main () -> int [Example](https://www.godbolt.org/z/v4EYf1n3j) -### Task 6.3 : Spaceships and Ordering Types +## Spaceships and Ordering Types As of C++20 there as a new ordering operator introduced called the three-way-comparison operator or, the spaceship operator `<=>`. The spaceship operator different ordering types based on the strictness of the ordering. @@ -103,7 +89,7 @@ As of C++20 there as a new ordering operator introduced called the three-way-com > Note: floating point comparisons return `std::partial_ordering` -#### Task 6.3.1 : Strong Ordering +### Strong Ordering `std::strong_ordering` can have the values: @@ -114,7 +100,7 @@ As of C++20 there as a new ordering operator introduced called the three-way-com and can be implicitly converted into `std::partial_ordering` or `std::weak_ordering`. -#### Task 6.3.2 : Weak Ordering +### Weak Ordering `std::weak_ordering` can have the values: @@ -124,7 +110,7 @@ and can be implicitly converted into `std::partial_ordering` or `std::weak_order and can be implicitly converted into `std::partial_ordering`. -#### Task 6.3.3 : Partial Ordering +### Partial Ordering `std::partial_ordering` can have the values: @@ -161,7 +147,7 @@ auto main () -> int [Example](https://www.godbolt.org/z/asKsxKc1W) -### Task 6.4 : Logical Operators +## Logical Operators In programming, it is useful to be able to check a multitude of Boolean expression. This allows programs to have more complex conditional logic structures. @@ -204,10 +190,3 @@ auto main () -> int ``` [Example](https://www.godbolt.org/z/xqx3o4hW6) - -## Links - -- [Previous Page : IO](/content/part2/tasks/io.md) -- [Next Page : Conditional Expressions](/content/part2/tasks/condexpr.md) -- [Content](/content/README.md) -- [HOME](/README.md) diff --git a/content/part2/tasks/functions.md b/src/chapter2/functions.md similarity index 83% rename from content/part2/tasks/functions.md rename to src/chapter2/functions.md index 33813db..907b9a5 100644 --- a/content/part2/tasks/functions.md +++ b/src/chapter2/functions.md @@ -1,24 +1,12 @@ # Functions -## Contents - -- [Functions](#functions) - - [Contents](#contents) - - [Task 4](#task-4) - - [Task 9.1 : What is a functions?](#task-91--what-is-a-functions) - - [Task 9.2 : Function Syntax](#task-92--function-syntax) - - [Task 9.2.3 : Void Functions](#task-923--void-functions) - - [Links](#links) - -## Task 4 - -### Task 9.1 : What is a functions? +## What is a functions? A function is the most basic form of abstraction in programming. They allow software to be broken down into more simple pieces of code and compose and reuse them as we please. Much like functions in mathematics, functions in C++ (an every programming language) take in some input parameters (aka arguments or points) and return a single output value. This creates a transformation or mapping between input values and types to output values and types. -### Task 9.2 : Function Syntax +## Function Syntax Functions in C++ consist of a declaration and definition. A declaration is the functions signature which consists of the functions name, its points and its return type. The definition is a code block with at least on `return` expression. @@ -92,7 +80,7 @@ auto main () -> int [Example](https://www.godbolt.org/z/radjo93bx) -#### Task 9.2.3 : Void Functions +### Void Functions Functions can also return nothing. This is often the case when functions have side effects. Side effects are operations that occur outside the input and outputs domains of a function. Printing with `std::cout` (or rather the underlying function that `std::cout calls) is an example of a function with side effects. It takes the string literal as input and returns, nothing but the effect of the text printing still occurs. @@ -113,10 +101,3 @@ auto main () -> int ``` [Example](https://www.godbolt.org/z/jeb77d165) - -## Links - -- [Previous Page : Loops](/content/part2/tasks/loops.md) -- [Back to Part 2](/content/part2/README.md) -- [Content](/content/README.md) -- [HOME](/README.md) diff --git a/content/part2/slides/hpp_part2.pdf b/src/chapter2/hpp_chapter2.pdf similarity index 55% rename from content/part2/slides/hpp_part2.pdf rename to src/chapter2/hpp_chapter2.pdf index a782cd0..5bee305 100644 Binary files a/content/part2/slides/hpp_part2.pdf and b/src/chapter2/hpp_chapter2.pdf differ diff --git a/content/part2/slides/hpp_part2.pptx b/src/chapter2/hpp_chapter2.pptx similarity index 100% rename from content/part2/slides/hpp_part2.pptx rename to src/chapter2/hpp_chapter2.pptx diff --git a/content/part2/slides/imgs/hpp_part2-01.png b/src/chapter2/imgs/hpp_chapter2-01.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-01.png rename to src/chapter2/imgs/hpp_chapter2-01.png diff --git a/content/part2/slides/imgs/hpp_part2-02.png b/src/chapter2/imgs/hpp_chapter2-02.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-02.png rename to src/chapter2/imgs/hpp_chapter2-02.png diff --git a/content/part2/slides/imgs/hpp_part2-03.png b/src/chapter2/imgs/hpp_chapter2-03.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-03.png rename to src/chapter2/imgs/hpp_chapter2-03.png diff --git a/content/part2/slides/imgs/hpp_part2-04.png b/src/chapter2/imgs/hpp_chapter2-04.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-04.png rename to src/chapter2/imgs/hpp_chapter2-04.png diff --git a/content/part2/slides/imgs/hpp_part2-05.png b/src/chapter2/imgs/hpp_chapter2-05.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-05.png rename to src/chapter2/imgs/hpp_chapter2-05.png diff --git a/content/part2/slides/imgs/hpp_part2-06.png b/src/chapter2/imgs/hpp_chapter2-06.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-06.png rename to src/chapter2/imgs/hpp_chapter2-06.png diff --git a/content/part2/slides/imgs/hpp_part2-07.png b/src/chapter2/imgs/hpp_chapter2-07.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-07.png rename to src/chapter2/imgs/hpp_chapter2-07.png diff --git a/content/part2/slides/imgs/hpp_part2-08.png b/src/chapter2/imgs/hpp_chapter2-08.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-08.png rename to src/chapter2/imgs/hpp_chapter2-08.png diff --git a/content/part2/slides/imgs/hpp_part2-09.png b/src/chapter2/imgs/hpp_chapter2-09.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-09.png rename to src/chapter2/imgs/hpp_chapter2-09.png diff --git a/content/part2/slides/imgs/hpp_part2-10.png b/src/chapter2/imgs/hpp_chapter2-10.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-10.png rename to src/chapter2/imgs/hpp_chapter2-10.png diff --git a/content/part2/slides/imgs/hpp_part2-11.png b/src/chapter2/imgs/hpp_chapter2-11.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-11.png rename to src/chapter2/imgs/hpp_chapter2-11.png diff --git a/content/part2/slides/imgs/hpp_part2-12.png b/src/chapter2/imgs/hpp_chapter2-12.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-12.png rename to src/chapter2/imgs/hpp_chapter2-12.png diff --git a/content/part2/slides/imgs/hpp_part2-13.png b/src/chapter2/imgs/hpp_chapter2-13.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-13.png rename to src/chapter2/imgs/hpp_chapter2-13.png diff --git a/content/part2/slides/imgs/hpp_part2-14.png b/src/chapter2/imgs/hpp_chapter2-14.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-14.png rename to src/chapter2/imgs/hpp_chapter2-14.png diff --git a/content/part2/slides/imgs/hpp_part2-15.png b/src/chapter2/imgs/hpp_chapter2-15.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-15.png rename to src/chapter2/imgs/hpp_chapter2-15.png diff --git a/content/part2/slides/imgs/hpp_part2-16.png b/src/chapter2/imgs/hpp_chapter2-16.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-16.png rename to src/chapter2/imgs/hpp_chapter2-16.png diff --git a/content/part2/slides/imgs/hpp_part2-17.png b/src/chapter2/imgs/hpp_chapter2-17.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-17.png rename to src/chapter2/imgs/hpp_chapter2-17.png diff --git a/content/part2/slides/imgs/hpp_part2-18.png b/src/chapter2/imgs/hpp_chapter2-18.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-18.png rename to src/chapter2/imgs/hpp_chapter2-18.png diff --git a/content/part2/slides/imgs/hpp_part2-19.png b/src/chapter2/imgs/hpp_chapter2-19.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-19.png rename to src/chapter2/imgs/hpp_chapter2-19.png diff --git a/content/part2/slides/imgs/hpp_part2-20.png b/src/chapter2/imgs/hpp_chapter2-20.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-20.png rename to src/chapter2/imgs/hpp_chapter2-20.png diff --git a/content/part2/slides/imgs/hpp_part2-21.png b/src/chapter2/imgs/hpp_chapter2-21.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-21.png rename to src/chapter2/imgs/hpp_chapter2-21.png diff --git a/content/part2/slides/imgs/hpp_part2-22.png b/src/chapter2/imgs/hpp_chapter2-22.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-22.png rename to src/chapter2/imgs/hpp_chapter2-22.png diff --git a/content/part2/slides/imgs/hpp_part2-23.png b/src/chapter2/imgs/hpp_chapter2-23.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-23.png rename to src/chapter2/imgs/hpp_chapter2-23.png diff --git a/content/part2/slides/imgs/hpp_part2-24.png b/src/chapter2/imgs/hpp_chapter2-24.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-24.png rename to src/chapter2/imgs/hpp_chapter2-24.png diff --git a/content/part2/slides/imgs/hpp_part2-25.png b/src/chapter2/imgs/hpp_chapter2-25.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-25.png rename to src/chapter2/imgs/hpp_chapter2-25.png diff --git a/content/part2/slides/imgs/hpp_part2-26.png b/src/chapter2/imgs/hpp_chapter2-26.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-26.png rename to src/chapter2/imgs/hpp_chapter2-26.png diff --git a/content/part2/slides/imgs/hpp_part2-27.png b/src/chapter2/imgs/hpp_chapter2-27.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-27.png rename to src/chapter2/imgs/hpp_chapter2-27.png diff --git a/content/part2/slides/imgs/hpp_part2-28.png b/src/chapter2/imgs/hpp_chapter2-28.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-28.png rename to src/chapter2/imgs/hpp_chapter2-28.png diff --git a/content/part2/slides/imgs/hpp_part2-29.png b/src/chapter2/imgs/hpp_chapter2-29.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-29.png rename to src/chapter2/imgs/hpp_chapter2-29.png diff --git a/content/part2/slides/imgs/hpp_part2-30.png b/src/chapter2/imgs/hpp_chapter2-30.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-30.png rename to src/chapter2/imgs/hpp_chapter2-30.png diff --git a/content/part2/slides/imgs/hpp_part2-31.png b/src/chapter2/imgs/hpp_chapter2-31.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-31.png rename to src/chapter2/imgs/hpp_chapter2-31.png diff --git a/content/part2/slides/imgs/hpp_part2-32.png b/src/chapter2/imgs/hpp_chapter2-32.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-32.png rename to src/chapter2/imgs/hpp_chapter2-32.png diff --git a/content/part2/slides/imgs/hpp_part2-33.png b/src/chapter2/imgs/hpp_chapter2-33.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-33.png rename to src/chapter2/imgs/hpp_chapter2-33.png diff --git a/content/part2/slides/imgs/hpp_part2-34.png b/src/chapter2/imgs/hpp_chapter2-34.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-34.png rename to src/chapter2/imgs/hpp_chapter2-34.png diff --git a/content/part2/slides/imgs/hpp_part2-35.png b/src/chapter2/imgs/hpp_chapter2-35.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-35.png rename to src/chapter2/imgs/hpp_chapter2-35.png diff --git a/content/part2/slides/imgs/hpp_part2-36.png b/src/chapter2/imgs/hpp_chapter2-36.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-36.png rename to src/chapter2/imgs/hpp_chapter2-36.png diff --git a/content/part2/slides/imgs/hpp_part2-37.png b/src/chapter2/imgs/hpp_chapter2-37.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-37.png rename to src/chapter2/imgs/hpp_chapter2-37.png diff --git a/content/part2/slides/imgs/hpp_part2-38.png b/src/chapter2/imgs/hpp_chapter2-38.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-38.png rename to src/chapter2/imgs/hpp_chapter2-38.png diff --git a/content/part2/slides/imgs/hpp_part2-39.png b/src/chapter2/imgs/hpp_chapter2-39.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-39.png rename to src/chapter2/imgs/hpp_chapter2-39.png diff --git a/content/part2/slides/imgs/hpp_part2-40.png b/src/chapter2/imgs/hpp_chapter2-40.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-40.png rename to src/chapter2/imgs/hpp_chapter2-40.png diff --git a/content/part2/slides/imgs/hpp_part2-41.png b/src/chapter2/imgs/hpp_chapter2-41.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-41.png rename to src/chapter2/imgs/hpp_chapter2-41.png diff --git a/content/part2/slides/imgs/hpp_part2-42.png b/src/chapter2/imgs/hpp_chapter2-42.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-42.png rename to src/chapter2/imgs/hpp_chapter2-42.png diff --git a/content/part2/slides/imgs/hpp_part2-43.png b/src/chapter2/imgs/hpp_chapter2-43.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-43.png rename to src/chapter2/imgs/hpp_chapter2-43.png diff --git a/content/part2/slides/imgs/hpp_part2-44.png b/src/chapter2/imgs/hpp_chapter2-44.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-44.png rename to src/chapter2/imgs/hpp_chapter2-44.png diff --git a/content/part2/slides/imgs/hpp_part2-45.png b/src/chapter2/imgs/hpp_chapter2-45.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-45.png rename to src/chapter2/imgs/hpp_chapter2-45.png diff --git a/content/part2/slides/imgs/hpp_part2-46.png b/src/chapter2/imgs/hpp_chapter2-46.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-46.png rename to src/chapter2/imgs/hpp_chapter2-46.png diff --git a/content/part2/slides/imgs/hpp_part2-47.png b/src/chapter2/imgs/hpp_chapter2-47.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-47.png rename to src/chapter2/imgs/hpp_chapter2-47.png diff --git a/content/part2/slides/imgs/hpp_part2-48.png b/src/chapter2/imgs/hpp_chapter2-48.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-48.png rename to src/chapter2/imgs/hpp_chapter2-48.png diff --git a/content/part2/slides/imgs/hpp_part2-49.png b/src/chapter2/imgs/hpp_chapter2-49.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-49.png rename to src/chapter2/imgs/hpp_chapter2-49.png diff --git a/content/part2/slides/imgs/hpp_part2-50.png b/src/chapter2/imgs/hpp_chapter2-50.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-50.png rename to src/chapter2/imgs/hpp_chapter2-50.png diff --git a/content/part2/slides/imgs/hpp_part2-51.png b/src/chapter2/imgs/hpp_chapter2-51.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-51.png rename to src/chapter2/imgs/hpp_chapter2-51.png diff --git a/content/part2/slides/imgs/hpp_part2-52.png b/src/chapter2/imgs/hpp_chapter2-52.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-52.png rename to src/chapter2/imgs/hpp_chapter2-52.png diff --git a/content/part2/slides/imgs/hpp_part2-53.png b/src/chapter2/imgs/hpp_chapter2-53.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-53.png rename to src/chapter2/imgs/hpp_chapter2-53.png diff --git a/content/part2/slides/imgs/hpp_part2-54.png b/src/chapter2/imgs/hpp_chapter2-54.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-54.png rename to src/chapter2/imgs/hpp_chapter2-54.png diff --git a/content/part2/slides/imgs/hpp_part2-55.png b/src/chapter2/imgs/hpp_chapter2-55.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-55.png rename to src/chapter2/imgs/hpp_chapter2-55.png diff --git a/content/part2/slides/imgs/hpp_part2-56.png b/src/chapter2/imgs/hpp_chapter2-56.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-56.png rename to src/chapter2/imgs/hpp_chapter2-56.png diff --git a/content/part2/slides/imgs/hpp_part2-57.png b/src/chapter2/imgs/hpp_chapter2-57.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-57.png rename to src/chapter2/imgs/hpp_chapter2-57.png diff --git a/content/part2/slides/imgs/hpp_part2-58.png b/src/chapter2/imgs/hpp_chapter2-58.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-58.png rename to src/chapter2/imgs/hpp_chapter2-58.png diff --git a/content/part2/slides/imgs/hpp_part2-59.png b/src/chapter2/imgs/hpp_chapter2-59.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-59.png rename to src/chapter2/imgs/hpp_chapter2-59.png diff --git a/content/part2/slides/imgs/hpp_part2-60.png b/src/chapter2/imgs/hpp_chapter2-60.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-60.png rename to src/chapter2/imgs/hpp_chapter2-60.png diff --git a/content/part2/slides/imgs/hpp_part2-61.png b/src/chapter2/imgs/hpp_chapter2-61.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-61.png rename to src/chapter2/imgs/hpp_chapter2-61.png diff --git a/content/part2/slides/imgs/hpp_part2-62.png b/src/chapter2/imgs/hpp_chapter2-62.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-62.png rename to src/chapter2/imgs/hpp_chapter2-62.png diff --git a/content/part2/slides/imgs/hpp_part2-63.png b/src/chapter2/imgs/hpp_chapter2-63.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-63.png rename to src/chapter2/imgs/hpp_chapter2-63.png diff --git a/content/part2/slides/imgs/hpp_part2-64.png b/src/chapter2/imgs/hpp_chapter2-64.png similarity index 100% rename from content/part2/slides/imgs/hpp_part2-64.png rename to src/chapter2/imgs/hpp_chapter2-64.png diff --git a/content/part2/tasks/io.md b/src/chapter2/io.md similarity index 77% rename from content/part2/tasks/io.md rename to src/chapter2/io.md index 7cb3719..dc3342e 100644 --- a/content/part2/tasks/io.md +++ b/src/chapter2/io.md @@ -1,29 +1,18 @@ -# Streams +# IO -## Contents +IO means input and output. IO operations are used to consume or emit data at the boundary of a program. This allows for a program to interact with the outside would, including writing or reading from the console, displaying graphics, capturing images etc. In C++, almost all of the IO is performed through streams. -- [Streams](#streams) - - [Contents](#contents) - - [Task 5](#task-5) - - [Task 5.1 : What is a stream?](#task-51--what-is-a-stream) - - [Task 5.2 : C Standard Streams](#task-52--c-standard-streams) - - [Task 5.2.1 : Input](#task-521--input) - - [Task 5.3 : IO Manipulators](#task-53--io-manipulators) - - [Links](#links) - -## Task 5 - -### Task 5.1 : What is a stream? +## What is a stream? What is a stream. A stream is a sequence of an indeterminate amount of data connecting a source to a destination. In C++, streams are used to connect a perform a variety of IO operations. You have already used on of these streams in C++, this is of course `std::cout`. -### Task 5.2 : C Standard Streams +## C Standard Streams In C++ there are a few pre-defined stream objects. This are mounted to the the C languages `stdout`, `stdin` and `stderr`. These output devices are how C (and these stream objects) connect to the terminal screen and keyboard of your device. -- `std::cin` - Output stream to C's `stdin` +- `std::cin` - Output stream to C's `stdin` - `std::cout` - Output stream to C's `stdout` -- `std::cerr` - Output stream to C's `stderr` +- `std::cerr` - Output stream to C's `stderr` (dependent on `stdout`) - `std::clog` - Output stream to C's `stderr` (not dependent on `stdout`) These are pre-existing objects of the type `std::istream` and `std::ostream` respectively. The use of streams allows for C++ developer to have a uniform way of addressing different IO devices. In particular the `<<` operator is available to all streams types allowing for similar usage of streams that may be mounted to alternative IO devices, eg. files, graphics card, cameras etc. @@ -32,7 +21,7 @@ All stream objects and types are found in the `` header. [IO Library](https://en.cppreference.com/w/cpp/io) -#### Task 5.2.1 : Input +## Input We have seen how to print stuff to the console but how do we get input? There are two ways. One uses the stream directly with the `>>` operator while the other defers using a function call. We will only look at the direct usage for now. @@ -57,7 +46,7 @@ auto main () -> int [Example](https://www.godbolt.org/z/3zoz1517r) -### Task 5.3 : IO Manipulators +## IO Manipulators Because streams are used for IO operations in C++, they are naturally composable, allowing for the streams manipulation mid-stream. The C++ standard library has a variety of manipulators that allow you to change a streams format. Manipulators are found in the `` header. @@ -84,10 +73,3 @@ auto main () -> int ``` [Example](https://www.godbolt.org/z/s8rGc4heM) - -## Links - -- [Previous Page : Operators](/content/part2/tasks/operators.md) -- [Next Page : Equality, Ordering & Logical Operators](/content/part2/tasks/eqordlogic.md) -- [Content](/content/README.md) -- [HOME](/README.md) diff --git a/content/part2/tasks/loops.md b/src/chapter2/loops.md similarity index 79% rename from content/part2/tasks/loops.md rename to src/chapter2/loops.md index ae334a7..48d230e 100644 --- a/content/part2/tasks/loops.md +++ b/src/chapter2/loops.md @@ -1,21 +1,8 @@ # Loops -## Contents - -- [Loops](#loops) - - [Contents](#contents) - - [Task 8](#task-8) - - [Task 8.1 : While Loop](#task-81--while-loop) - - [Task 8.2 : Do-While Loop](#task-82--do-while-loop) - - [Task 8.3 : For Loop](#task-83--for-loop) - - [Task 8.4 : Range For](#task-84--range-for) - - [Links](#links) - -## Task 8 - Along with conditional expressions another powerful language facility is loops. Loops allow for programs to run in an iterative manner, that is a block will be executed in series. This is powerful feature that enables us to repeat a set of instructions effectively and efficiently. -### Task 8.1 : While Loop +## While Loop A `while` loop is the most basic kind of loop. `while` loops will repeat its code block as long as its condition is met. @@ -38,7 +25,7 @@ auto main () -> int [Example](https://www.godbolt.org/z/Pxa3G8T4o) -### Task 8.2 : Do-While Loop +## Do-While Loop There is another kind of `while` loop in C++ called a `do-while` loop. This works the exact same way a regular `while` loop works except that the condition is checked at the end of each loop rather than the start. This means that the code block will be executed at least once. @@ -63,7 +50,7 @@ auto main () -> int > Note: You can break out of a `while` or `do-while` loop with `break` or a `return`-expression. -### Task 8.3 : For Loop +## For Loop Another common loop in C++ is the `for` loop. `for` loops will generate an initial value, validate it meets a condition and proceed through the sequences. @@ -83,7 +70,7 @@ auto main () -> int As we can see, loops through the power of conditional checking make programs much smaller and allow us to abstract repeated actions into a single statement. -### Task 8.4 : Range For +## Range For There is one other loop in C++. This is the `range-for`. This is a special `for` loop that is able to iterate through a sequence of values, yielding a single value from the sequence each loop. It automatically knows the size of the sequence and when to stop. @@ -106,10 +93,3 @@ auto main () -> int ``` [Example](https://www.godbolt.org/z/P78T9c1Ev) - -## Links - -- [Previous Page : Conditional Expressions](/content/part2/tasks/condexpr.md) -- [Next Page : Functions](/content/part2/tasks/functions.md) -- [Content](/content/README.md) -- [HOME](/README.md) diff --git a/content/part2/tasks/operators.md b/src/chapter2/operators.md similarity index 92% rename from content/part2/tasks/operators.md rename to src/chapter2/operators.md index b7ac7ac..efb46ee 100644 --- a/content/part2/tasks/operators.md +++ b/src/chapter2/operators.md @@ -1,21 +1,8 @@ # Operators -## Contents +Operators are unique symbols that are used to perform changes to data. They often have infix notation with some having prefix or postfix notation. In C++, all operators are functions however, they are built into the language fpr primitive data types. -- [Operators](#operators) - - [Contents](#contents) - - [Task 4](#task-4) - - [4.1 : Basic Arithmetic](#41--basic-arithmetic) - - [4.2 : Casts](#42--casts) - - [4.3 : Bitwise Operations](#43--bitwise-operations) - - [4.3.1 : A bit about shift operations](#431--a-bit-about-shift-operations) - - [4.4 : Arithmetic Assignment](#44--arithmetic-assignment) - - [4.5 : Size Operator](#45--size-operator) - - [Links](#links) - -## Task 4 - -### 4.1 : Basic Arithmetic +## Basic Arithmetic So enough about types and values. Lets write some code that does something. In C++ there are a lot, and I mean a lot of operators but we will only cover the arithmetic based one this week. The first ones we will look at are the basic arithmetic operators. These include your standard: @@ -47,7 +34,7 @@ auto main () -> int [Example](https://www.godbolt.org/z/xKMooTb4s) -> Note: for those unaware, `%` returns the remained of the division of $\frac{a}{b}$ +> Note: for those unaware, `%` returns the remained of the division of \\( \frac{a}{b} \\) But hold up, why does `a / b` return `3`, should it not be `3.33...`? This correct.. sorta. In C++ when two integers divide it performs integer division, thus throwing away any remainder after the maximum even divisions. This is the same as Pythons `//` operator. To perform floating point division, either the numerator or denominator needs to be of a floating point type. This is so the alternate one (if it is an integer type) can be promoted to a floating point type to perform the floating point division. @@ -119,7 +106,7 @@ auto main () -> int [Example](https://www.godbolt.org/z/5Ps5ezhaT) -### 4.2 : Casts +## Casts In C++ you can change the type of an object via casting. There are quite a few different casting operators. @@ -149,7 +136,7 @@ auto main () -> int [Example](https://www.godbolt.org/z/E6GTExxEj) -### 4.3 : Bitwise Operations +## Bitwise Operations In C++ there is another category of operators called bitwise operators. These operators only apply to integer types but allow for you to individually control the bits of an integer. @@ -208,11 +195,11 @@ auto main () -> int [Example](https://www.godbolt.org/z/37b58aTjf) -#### 4.3.1 : A bit about shift operations +### A bit about shift operations For the shift operations, the general pattern is as follows ` `. This means the value that is being shifted is always on the left-hand-side and is always shifted by the number indicated on the right-hand-side. For left-shifts, the bit pattern is moved `N` spot to the left, pushing zeros at the end of the right side and popping any bit off the left end. For right shifts, the opposite occurs. The bit pattern is move right by `N` spots, popping any bit off the right end and push the same bit as the sign bit of the number being shifted (1's if negative and 0's if positive). -### 4.4 : Arithmetic Assignment +## Arithmetic Assignment There is one final set of arithmetic operators in C++. These are the arithmetic assignment operators. These will perform the operation between two points and assign the result to the left point. @@ -264,7 +251,7 @@ auto main () -> int Have a play with these operators and try and perform some computations that you might do in another languages. -### 4.5 : Size Operator +## Size Operator Another useful operator is the `sizeof` and `sizeof...` operator. It returns the number of bytes if a type parameter pack (more on parameter packs later). @@ -286,10 +273,3 @@ auto main () -> int ``` [Example](https://www.godbolt.org/z/8E4vTdPbc) - -## Links - -- [Previous Page : Variables](/content/part2/tasks/variables.md) -- [Next Page : IO](/content/part2/tasks/io.md) -- [Content](/content/README.md) -- [HOME](/README.md) diff --git a/src/chapter2/slides2.md b/src/chapter2/slides2.md new file mode 100644 index 0000000..59c0b5d --- /dev/null +++ b/src/chapter2/slides2.md @@ -0,0 +1,66 @@ +# Slides + +![Slides 01](./imgs/hpp_chapter2-01.png) +![Slides 02](./imgs/hpp_chapter2-02.png) +![Slides 03](./imgs/hpp_chapter2-03.png) +![Slides 04](./imgs/hpp_chapter2-04.png) +![Slides 05](./imgs/hpp_chapter2-05.png) +![Slides 06](./imgs/hpp_chapter2-06.png) +![Slides 07](./imgs/hpp_chapter2-07.png) +![Slides 08](./imgs/hpp_chapter2-08.png) +![Slides 09](./imgs/hpp_chapter2-09.png) +![Slides 10](./imgs/hpp_chapter2-10.png) +![Slides 11](./imgs/hpp_chapter2-11.png) +![Slides 12](./imgs/hpp_chapter2-12.png) +![Slides 13](./imgs/hpp_chapter2-13.png) +![Slides 14](./imgs/hpp_chapter2-14.png) +![Slides 15](./imgs/hpp_chapter2-15.png) +![Slides 16](./imgs/hpp_chapter2-16.png) +![Slides 17](./imgs/hpp_chapter2-17.png) +![Slides 18](./imgs/hpp_chapter2-18.png) +![Slides 19](./imgs/hpp_chapter2-19.png) +![Slides 20](./imgs/hpp_chapter2-20.png) +![Slides 21](./imgs/hpp_chapter2-21.png) +![Slides 22](./imgs/hpp_chapter2-22.png) +![Slides 23](./imgs/hpp_chapter2-23.png) +![Slides 24](./imgs/hpp_chapter2-24.png) +![Slides 25](./imgs/hpp_chapter2-25.png) +![Slides 26](./imgs/hpp_chapter2-26.png) +![Slides 27](./imgs/hpp_chapter2-27.png) +![Slides 28](./imgs/hpp_chapter2-28.png) +![Slides 29](./imgs/hpp_chapter2-29.png) +![Slides 30](./imgs/hpp_chapter2-30.png) +![Slides 31](./imgs/hpp_chapter2-31.png) +![Slides 32](./imgs/hpp_chapter2-32.png) +![Slides 33](./imgs/hpp_chapter2-33.png) +![Slides 34](./imgs/hpp_chapter2-34.png) +![Slides 35](./imgs/hpp_chapter2-35.png) +![Slides 36](./imgs/hpp_chapter2-36.png) +![Slides 37](./imgs/hpp_chapter2-37.png) +![Slides 38](./imgs/hpp_chapter2-38.png) +![Slides 39](./imgs/hpp_chapter2-39.png) +![Slides 40](./imgs/hpp_chapter2-40.png) +![Slides 41](./imgs/hpp_chapter2-41.png) +![Slides 42](./imgs/hpp_chapter2-42.png) +![Slides 43](./imgs/hpp_chapter2-43.png) +![Slides 44](./imgs/hpp_chapter2-44.png) +![Slides 45](./imgs/hpp_chapter2-45.png) +![Slides 46](./imgs/hpp_chapter2-46.png) +![Slides 47](./imgs/hpp_chapter2-47.png) +![Slides 48](./imgs/hpp_chapter2-48.png) +![Slides 49](./imgs/hpp_chapter2-49.png) +![Slides 50](./imgs/hpp_chapter2-50.png) +![Slides 51](./imgs/hpp_chapter2-51.png) +![Slides 52](./imgs/hpp_chapter2-52.png) +![Slides 53](./imgs/hpp_chapter2-53.png) +![Slides 54](./imgs/hpp_chapter2-54.png) +![Slides 55](./imgs/hpp_chapter2-55.png) +![Slides 56](./imgs/hpp_chapter2-56.png) +![Slides 57](./imgs/hpp_chapter2-57.png) +![Slides 58](./imgs/hpp_chapter2-58.png) +![Slides 59](./imgs/hpp_chapter2-59.png) +![Slides 60](./imgs/hpp_chapter2-60.png) +![Slides 61](./imgs/hpp_chapter2-61.png) +![Slides 62](./imgs/hpp_chapter2-62.png) +![Slides 63](./imgs/hpp_chapter2-63.png) +![Slides 64](./imgs/hpp_chapter2-64.png) diff --git a/content/part2/tasks/types.md b/src/chapter2/types.md similarity index 65% rename from content/part2/tasks/types.md rename to src/chapter2/types.md index e9c3a27..58e70e2 100644 --- a/content/part2/tasks/types.md +++ b/src/chapter2/types.md @@ -1,75 +1,53 @@ # Primitive Types -## Contents - -- [Primitive Types](#primitive-types) - - [Contents](#contents) - - [Task 2](#task-2) - - [2.1 : Size and Width](#21--size-and-width) - - [2.2 : Integral Types](#22--integral-types) - - [2.2.1 : Boolean Type](#221--boolean-type) - - [2.2.2 : Character Types](#222--character-types) - - [2.2.3 : Number Types](#223--number-types) - - [2.3 : Float Point Types](#23--float-point-types) - - [2.4 : Void](#24--void) - - [2.5 : Nullptr](#25--nullptr) - - [2.6 : Other Types](#26--other-types) - - [2.6 : Auto](#26--auto) - - [Links](#links) - -## Task 2 - -### 2.1 : Size and Width +Like most languages, C++ comes with a small set of types that are built into the language. Almost every other type created and used in the language is some combination or composition of these types. + +## Size and Width In C++, all types have an implicit property called width or size. This refers to how much memory; in bits or bytes, a given type maximally occupies. This leaves enough room for any value of the given type to fit in the allocated spot. The minimum size a type can occupy in C++ is 8-bits or a byte. -### 2.2 : Integral Types +## Integral Types + +Integral types are the most basic kind of type in C++. These types represent whole numerical values of varying sizes. Some are used to represent logical values, other character code point and some are just plain old number types. -#### 2.2.1 : Boolean Type +### Boolean Type The first type we will look at is `bool`. `bool` represents a Boolean value, meaning it is either `true` or `false`. This is a specialization of a unique type-function called a sum type. A sum type is a type that can hold one of its possible variants (also called 'appends' or 'injections'), in this case these are the type constructors `true` and `false`. However, in C++ `bool` is built-in to the language and thus these properties are hidden away. `bool` occupies a memory space of 8-bits or a byte. It is also worth pointing out that `true` and `false` are literals (as they are built-in keywords) holding there respective values independently. Booleans are used to denote truthiness and logic in a programming language. In C++, `bool` can be implicitly promoted to another integral type such as `int` with `false` becoming `0` and `true` becoming `1`. Other integral types also can be narrowed to a `bool` with `0` becoming `false` and anything else becoming `true`. -#### 2.2.2 : Character Types +### Character Types -The next type we will look is the `char`. This is C++ standard character type. These are values such as `'a'` or even escape characters like `'\n'`. It holds only a single byte (same as `bool`) allowing it to represent $2^8 = 256$ different values. Depending on the system is is either `signed` or `unsigned`, meaning either the leading bit is dedicated to the sign of the value or is another number point. Depending on the representation, `char` can have a value between `0..255` (unsigned) or `-127..128` (signed). Character literals exclusively use single quotes in C++. +The next type we will look is the `char`. This is C++ standard character type. These are values such as `'a'` or even escape characters like `'\n'`. It holds only a single byte (same as `bool`) allowing it to represent \\( 2^8 = 256 \\) different values. Depending on the system is is either `signed` or `unsigned`, meaning either the leading bit is dedicated to the sign of the value or is another number point. Depending on the representation, `char` can have a value between `0..255` (unsigned) or `-127..128` (signed). Character literals exclusively use single quotes in C++. There is another character type in C++ called `wchar_t`. This is a 'wide character' which can hold more bits than the `char` type. On Windows systems it is 16-bits (2-bytes) while on Unix based systems (Linux, macOS etc.) this is typically 32-bits (4-bytes). This allows for `wchar_t` to be to store many more different codepoints. A wide character literal also uses single quotes however, the quote pair is prefixed with a 'L' eg. 'a' as a `wchar_t` literal looks like `L'a'`. Like `bool`, `char` and `wchar_t` are integral types, this means that they are really numbers however, the system will treat them differently, eg. for IO. -#### 2.2.3 : Number Types +### Number Types -There is only one primary number type in C++ called `int`. This represents a (typically) 32-bit (4-byte), signed number. It can store $2^{32} = 4,294,967,296$ values has a value range of `-2'147'483'647..2'147'483'648`. `int` is probably the most basic type in terms of bit layout in C++ with every bit storing data from the number with only the first bit indicating the sign of the number. +There is only one primary number type in C++ called `int`. This represents a (typically) 32-bit (4-byte), signed number. It can store \\( 2^{32} = 4,294,967,296 \\) values has a value range of `-2'147'483'647..2'147'483'648`. `int` is probably the most basic type in terms of bit layout in C++ with every bit storing data from the number with only the first bit indicating the sign of the number. -### 2.3 : Float Point Types +## Float Point Types C++ has two distinct floating point number types. These are `float` and `double`. `float` implements the IEEE-754 binary32 floating point format while `double` implements the IEEE-754 binary64 floating point format, hence the name `double` indicating double floating point precision. -Floating point numbers are a unique problem in computing. It is impossible to represent all precisions a decimal number can have (number of decimal places) which still being able to compute large numbers with limited memory. To tackle this, floating point numbers break up the bit-space of the floating point into the sign, fraction and exponents parts. The IEEE-754 binary32 format uses 1-bit for the sign, 8-bits (a byte) for the exponent and and 23-bits (3-bytes - 1-bit) for the fraction. The IEEE-754 binary64 format has; again 1-bit for the sign, 11-bits for the exponent and 52-bits for the fraction part. This gives you (greater than) double the number bits you can use represent your fraction part or $536,870,912$ times more possible values for the fraction part of a `double` over a `float` ($2^{52}=4.5035996\cdot10^{15}$ vs $2^{23}=8,388,608$). +Floating point numbers are a unique problem in computing. It is impossible to represent all precisions a decimal number can have (number of decimal places) which still being able to compute large numbers with limited memory. To tackle this, floating point numbers break up the bit-space of the floating point into the sign, fraction and exponents chapters. The IEEE-754 binary32 format uses 1-bit for the sign, 8-bits (a byte) for the exponent and and 23-bits (3-bytes - 1-bit) for the fraction. The IEEE-754 binary64 format has; again 1-bit for the sign, 11-bits for the exponent and 52-bits for the fraction chapter. This gives you (greater than) double the number bits you can use represent your fraction chapter or \\( 536,870,912 \\) times more possible values for the fraction chapter of a `double` over a `float` (\\( 2^{52}=4.5035996\cdot10^{15} \\) vs \\( 2^{23}=8,388,608 \\)). -### 2.4 : Void +## Void In C++ there is a unique type called called `void`. This is an incomplete and it can not be completed. It is a unique type of literal but it holds no value. `void` is used to indicate the absence of a return value (and input parameter value in C). It is different from the unit type (which is not explicitly present in C++) which has the type `()` and value `()`, `void` has the type of `void` but not the value of `void`. It has no value. -### 2.5 : Nullptr +## Nullptr `nullptr` is a literal type which has type of `std::nullptr_t` and value of `nullptr`. This is a unique type used by pointers to indicate that they point to nothing. -### 2.6 : Other Types +## Other Types There are two more types in C++ that are worth talking about. These are `std::size_t` and `std::ptrdiff_t`. `std::size_t` is a platform dependent type that indicates the maximum possible size of an unsigned integer in C++. This is typically a 32-bit or 64-bit number types. `std::ptrdiff_t` is a signed number type that is returned by subtracting two pointers in C++. -### 2.6 : Auto +## Auto While C++ is a statically typed language, it is able to infer and deduce the types of many things at compile time. This is achieve with a non-type keyword called `auto`. While `auto` is used in many places that type specifiers are used (more on this in the next section), it is important to note that it itself is not a type but rather a automatic type, essentially a placeholder for the to-be deduced type. - -## Links - -- [Previous Page : The C++ Type System](/content/part2/tasks/typesystem.md) -- [Next Page : Variables](/content/part2/tasks/variables.md) -- [Content](/content/README.md) -- [HOME](/README.md) diff --git a/content/part2/tasks/typesystem.md b/src/chapter2/typesystem.md similarity index 70% rename from content/part2/tasks/typesystem.md rename to src/chapter2/typesystem.md index 97b59e8..7fccc7e 100644 --- a/content/part2/tasks/typesystem.md +++ b/src/chapter2/typesystem.md @@ -1,36 +1,24 @@ # The C++ Type System -## Contents +## Strong vs Weak Typing -- [The C++ Type System](#the-c-type-system) - - [Contents](#contents) - - [Task 1](#task-1) - - [Task 1.1 : Strong vs Weak Typing](#task-11--strong-vs-weak-typing) - - [Task 1.2 : Static vs Dynamic Type Systems](#task-12--static-vs-dynamic-type-systems) - - [Task 1.3 : A Pinch of Type Theory](#task-13--a-pinch-of-type-theory) - - [Links](#links) - -## Task 1 - -### Task 1.1 : Strong vs Weak Typing - -In [week 0 : "Hello World"](/content/part1/tasks/helloworld.md#61--introducing-c) we discussed a bit about C++'s types system. But what is a type system? A type system is a formal notion of which terms have which properties. The rules and constructs of a type system underpin the meaning help by any discourse written in any and all programming languages. Without a type system, programming languages cannot construct grammar or structure and thus cannot become coherent and cohesive expressions of language. +In [1.3 Hello World](../chapter1/helloworld.md) we discussed a bit about C++'s types system. But what is a type system? A type system is a formal notion of which terms have which properties. The rules and constructs of a type system underpin the meaning help by any discourse written in any and all programming languages. Without a type system, programming languages cannot construct grammar or structure and thus cannot become coherent and cohesive expressions of language. This is all a bit abstract and delves into [Type Theory](https://en.wikipedia.org/wiki/Type_theory) which is a more formal, mathematical notion of types. For our purposes we will just look at what C++'s type system does. -First and foremost, C++ is considered by many (but not universal) to be a strongly typed language. There isn't a universal definition of a strong or weak types but the basic premise is: +First and foremost, C++ is considered by many (but not universally) to be a strongly typed language. There isn't a universal definition of a strong or weak types but the basic premise is based around the question: > Does the type system allow implicit conversions between type? In the case of C++, 90% of types have no implicit conversions. The only contradiction to this is type promotion or narrowing, this is when types of the same _kind_ get promoted or narrowed to a similar yet different type. This occurs for some type in C++ because the bit width, layout and structure are so similar; due to how memory in computers work, that some types will implicitly meet the requirements of of another type. While this can occur in C++, it is limited to only a handful of primitive _data types_. Weaker typing allows for this implicit conversions to happen more frequently (think JavaScript's type system). -### Task 1.2 : Static vs Dynamic Type Systems +## Static vs Dynamic Type Systems So what about static and dynamic typing? These characterisations refer to the type checking techniques used in a language and how a language expresses the notion of types. These are the two key ways to look at either static or dynamic typing. In a dynamically typed language, the type of an object does not have to be explicitly stated, but is inferred at runtime based on its contexts and the surrounding expressions. Python is a good example of this as you can create an object and assign it a type without ever declaring what type the object should be. This allows interpreters to forego type checking until a particular operation is performed on an object which may or may not fail. In a statically typed language, this is the opposite. You must formally declare the type of an object and i must be known to the system before the program ever runs. Most often, it must be known at compile time. However, some languages can forego an explicit **notation** of an object type and allow the compiler to infer the type. C++ and many other compiled languages; like Rust, are capable of type inference using various **argument deduction** techniques. -### Task 1.3 : A Pinch of Type Theory +## A Pinch of Type Theory Before we move on, there a some important definitions that are good to know going forward. @@ -40,11 +28,4 @@ Before we move on, there a some important definitions that are good to know goin - Typeclasses - A typeclass is a polymorphic type constraint. It defines the expected properties of a type including methods, functions and patterns. In C++ typeclasses are created using the `concept` keyword. - Kinds - A kind is, well; to put it bluntly, a type of a type. It describes the type of a nullary type constructor, ie. the constructor of primitive data-types which take no parameters. What this basically means is something that can hold a value. -In C++ supports everything except Kinds. We will go more into a little more depth during [Week 5](/content/week5/README.md). - -## Links - -- [Previous Page : Week 1](/content/part2/README.md) -- [Next Page : Primitive Data Types](/content/part2/tasks/types.md) -- [Content](/content/README.md) -- [HOME](/README.md) +In C++ supports everything except Kinds. We will go more into a little more depth during Chapter 5. diff --git a/content/part2/tasks/variables.md b/src/chapter2/variables.md similarity index 86% rename from content/part2/tasks/variables.md rename to src/chapter2/variables.md index a010bb4..692d957 100644 --- a/content/part2/tasks/variables.md +++ b/src/chapter2/variables.md @@ -1,45 +1,16 @@ # Variables -## Contents - -- [Variables](#variables) - - [Contents](#contents) - - [Task 3](#task-3) - - [3.1 : Variables](#31--variables) - - [3.2 : Initialisation](#32--initialisation) - - [3.2.1 : Default Initialisation](#321--default-initialisation) - - [3.2.2 : Value Initialisation](#322--value-initialisation) - - [3.2.3 : Copy Initialisation](#323--copy-initialisation) - - [3.2.4 : Direct Initialisation](#324--direct-initialisation) - - [3.2.5 : Aggregate Initialisation](#325--aggregate-initialisation) - - [3.2.6 : List Initialisation](#326--list-initialisation) - - [3.3 : Qualifiers](#33--qualifiers) - - [3.3.1 : Signed-ness](#331--signed-ness) - - [3.3.2 : Size](#332--size) - - [3.3.3 : Storage](#333--storage) - - [3.3.4 : Mutability](#334--mutability) - - [3.4 : Automatic Types](#34--automatic-types) - - [3.5 : Value Categories](#35--value-categories) - - [3.5.2 : lvalues](#352--lvalues) - - [3.5.3 : rvalues](#353--rvalues) - - [3.5.1 : Literals](#351--literals) - - [Links](#links) - -## Task 3 - -### 3.1 : Variables - Variables are the first form of abstraction in any mathematical and logical system and computers are no exception. In C++ a variable is an owner of some value. You can use variables to store the value of something and use it in different places throughout your software. Variables can only be of one type, this is the type of the value they hold. To declare a variable in C++ is super simple and follows the following pattern ` ;`. That's it, pretty simple. However, like many things in C++ there is a slight catch. How does a variable acquire a value. In C++ there is a concept known as Resource Acquisition Is Initialisation (RAII). This essentially means that when a type obtains a resource; or rather, obtains all its necessary resources it can be considered initialised. So what does this all mean? This means that C++ has strict rules about how values can be given to variables and that certain requirements need to be made by the constructor of a type and the variable receiving the newly constructed value of that type. However, this is mostly technical speak but seeing a bit of it now can give you a better foundation to understand some weird quirks C++ has that you will most likely encounter in the future. We will cover constructors at a later date and focus on how to initialise a variable. -### 3.2 : Initialisation +## Initialisation -To begin open a new file or compiler explorer window so we can start writing. Make sure to have the main function so the program can run. Look in [/resources/blueprint.cxx](/resources/blueprint.cxx) for a copy of main. +To begin, open a new file or compiler explorer window so we can start writing. Make sure to have the main function so the program can run. Look in [/resources/blueprint.cxx](../../resources/blueprint.cxx) for a copy of main. -#### 3.2.1 : Default Initialisation +### Default Initialisation Before we saw that creating a variable has the pattern ` `. `` can be any type we've seen so far or the `auto` keyword. `` can be any alphanumeric (plus _) combination of characters (as long as the first character is not a number). For example an `int` called `i` would be. @@ -67,7 +38,7 @@ auto a = {1}; ///< must have initialiser for type deduction. [Default Initialisation](https://en.cppreference.com/w/cpp/language/default_initialization) -#### 3.2.2 : Value Initialisation +### Value Initialisation Value initialisation is used to zero-initialise a scalar variable (eg. `int` etc.) or default initialise a user defined type such as a `class`. The syntax for value initialisation varies but it typically uses ` {}` or ` ()`. This is the preferred and recommended way to to initialise variables without giving them an explicit value. @@ -77,10 +48,10 @@ int(); ///< zero-initialises a temporary to `0`. T t{}; ///< Default initialises `t` using `T` default constructor ``` -[Value Initialisation](https://en.cppreference.com/w/cpp/language/value_initialization) -[Zero Initialisation](https://en.cppreference.com/w/cpp/language/zero_initialization) +- [Value Initialisation](https://en.cppreference.com/w/cpp/language/value_initialization) +- [Zero Initialisation](https://en.cppreference.com/w/cpp/language/zero_initialization) -#### 3.2.3 : Copy Initialisation +### Copy Initialisation Copy initialisation is the most common type of initialisation found in C++ as it is the method originally derived from C. Copy initialisation revolves around the assignment operator `=` but is not exclusive to it. By default, most operations in C++ use copies and thus are initialised using copy initialisation. Copy initialisation copies any expression on the right-hand-side of the `=`, provided the type is correct. @@ -95,7 +66,7 @@ Up until now, we haven't been able to give our variables custom values. With cop [Copy Initialisation](https://en.cppreference.com/w/cpp/language/copy_initialization) -#### 3.2.4 : Direct Initialisation +### Direct Initialisation Direct initialisation allows you to initialise a variable with an explicit set of constructor arguments. This is mostly useful for custom constructor beyond the trivial ones the compiler can provide. @@ -109,7 +80,7 @@ Y(4, 6, 5); ///< Direct initialisation of temporary of type `Y` with lite [Direct Initialisation](https://en.cppreference.com/w/cpp/language/direct_initialization) -#### 3.2.5 : Aggregate Initialisation +### Aggregate Initialisation Aggregate initialisation is special list initialisation for aggregate types. These are slice, `struct`, `class` or `union` types with (for the formers) no private data-members or user-defined constructors. This allows them to be initialised with a list. @@ -124,7 +95,7 @@ We want use this directly all to much as list initialisation generally applies i [Aggregate Initialisation](https://en.cppreference.com/w/cpp/language/aggregate_initialization) -#### 3.2.6 : List Initialisation +### List Initialisation List initialisation is a generalisation of aggregate initialisation but can be applied to user-defined types. This allows you to specify a list of values to be used as arguments for a constructor. @@ -140,15 +111,15 @@ Have a play with with these and see what works with the compiler. In general, st [List Initialisation](https://en.cppreference.com/w/cpp/language/list_initialization) -### 3.3 : Qualifiers +## Qualifiers Types can have different qualifiers that change how a type behaves from its size to mutability. Qualifiers go before the type declaration. -#### 3.3.1 : Signed-ness +### Signed-ness The `signed` and `unsigned` qualifiers are used to indicate whether the first bit of the integral type is used for the sign of a number or not. All integral types are implicitly `signed` (`char` can vary). `unsigned` increases the maximum number an integral can be but disallows negative values. `unsigned` only works on integer types and not floating point types. -#### 3.3.2 : Size +### Size Size qualifiers are used to indicate the number of bits (which is platform specific) an `int` type must have at least. @@ -170,7 +141,7 @@ You can also combined size qualifiers with the `unsigned` (and `signed` though n [Fundamental Types](https://en.cppreference.com/w/cpp/language/types) -#### 3.3.3 : Storage +### Storage Storage qualifiers allow you to specify the lifetime of variables. All variables implicitly have automatic storage duration. The exist only in a certain scope, are created when the program enters that scope and dropped at the end of that scope. `static` (and implicitly global variables) are created at the beginning of the program and are dropped only at the end of the program. Only one variable of the same name can be declared static in a given translation unit. @@ -184,7 +155,7 @@ static int si = {1}; ///< static variables `inline` is more of a hint to the compiler for functions and methods. It indicates to the compiler that a function call should be inlined at call, ie. the functions definition gets moved to the call site. This qualifier is mostly used in OOP classes hierarchies as its more general use has be dropped in favour of a different qualifier. -#### 3.3.4 : Mutability +### Mutability In C++, variables are mutable by default. There are various ways to limit the mutability of variables as well as constrain the optimisations a compiler can apply. @@ -209,7 +180,7 @@ cv = 10; ///< Error > Note: The usage of `volatile` is highly discouraged. -### 3.4 : Automatic Types +## Automatic Types The final type we look at is an automatic type. As we will see later, declaring the type of variables can get cumbersome. Since C++11, a new type introducer was create with the keyword `auto`. Variables with type `auto` will have there true type deduced at compile time based on the initialiser. @@ -220,25 +191,18 @@ auto ac {'c'}; ///< `ac` deduced to have the type `char` auto as = "hello"; ///< `as` deduced to have the type `const char*` (more on these later) ``` -### 3.5 : Value Categories +## Value Categories In C++, there are different categories of values. These determine the operations that can be performed on them. There are a few value categories in C++ but we will focus on only two of them, lvalues and rvalues. -#### 3.5.2 : lvalues +### lvalues In C++ and lvalue is kind of value that you would find on the left-hand-side of the `=`, hence the name lvalue or 'left-value'. You can also find lvalues on the right-hand-side of `=`. This is the semantics of a copy (may or may not be an initialisation). Typically, a variable that has an assigned value is an lvalue. -#### 3.5.3 : rvalues +### rvalues rvalues are; as the name suggests, variables or values found on the right-hand-side of `=`. This includes literals, temporaries and moves. For example the literal `3` is an rvalue. rvalues are also used to indicate move-semantics (more on this later on). -#### 3.5.1 : Literals +### Literals Literals are types that have a explicit value to them. The literal `0` has the value of `int{0}` and type `int`. Literals allow the to be common code-point to define values into a specific character or character sequence. Essentially, literals hold the value and type they indicate. - -## Links - -- [Previous Page : Primitive Types](/content/part2/tasks/types.md) -- [Next Page : Operators](/content/part2/tasks/operators.md) -- [Content](/content/README.md) -- [HOME](/README.md) diff --git a/src/chapter3/README.md b/src/chapter3/README.md new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/chapter3/README.md @@ -0,0 +1 @@ + diff --git a/src/chapter3/chapter3.md b/src/chapter3/chapter3.md new file mode 100644 index 0000000..3d34e8d --- /dev/null +++ b/src/chapter3/chapter3.md @@ -0,0 +1,3 @@ +# Chapter 3 + +This week you will be introduced to C++'s memory model and how it allows us to have precise control over memory resources in C++. You will also cover the difference in stack and heap based memory and the facilities for obtaining memory. You will learn about pointers, references and how they allow you to reference data located elsewhere. You will also be introduced to C++'s slice type allowing to store multiple values in a single object. Finally, you get and introduction into a few fundamental types found in C++'s standard library that make working with memory and collections far easier. diff --git a/content/part3/slides/hpp_part3.pdf b/src/chapter3/hpp_chapter3.pdf similarity index 89% rename from content/part3/slides/hpp_part3.pdf rename to src/chapter3/hpp_chapter3.pdf index 637909b..2b502e4 100644 Binary files a/content/part3/slides/hpp_part3.pdf and b/src/chapter3/hpp_chapter3.pdf differ diff --git a/content/part3/slides/hpp_part3.pptx b/src/chapter3/hpp_chapter3.pptx similarity index 100% rename from content/part3/slides/hpp_part3.pptx rename to src/chapter3/hpp_chapter3.pptx diff --git a/content/part3/slides/imgs/hpp_part3-01.png b/src/chapter3/imgs/hpp_chapter3-01.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-01.png rename to src/chapter3/imgs/hpp_chapter3-01.png diff --git a/content/part3/slides/imgs/hpp_part3-02.png b/src/chapter3/imgs/hpp_chapter3-02.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-02.png rename to src/chapter3/imgs/hpp_chapter3-02.png diff --git a/content/part3/slides/imgs/hpp_part3-03.png b/src/chapter3/imgs/hpp_chapter3-03.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-03.png rename to src/chapter3/imgs/hpp_chapter3-03.png diff --git a/content/part3/slides/imgs/hpp_part3-04.png b/src/chapter3/imgs/hpp_chapter3-04.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-04.png rename to src/chapter3/imgs/hpp_chapter3-04.png diff --git a/content/part3/slides/imgs/hpp_part3-05.png b/src/chapter3/imgs/hpp_chapter3-05.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-05.png rename to src/chapter3/imgs/hpp_chapter3-05.png diff --git a/content/part3/slides/imgs/hpp_part3-06.png b/src/chapter3/imgs/hpp_chapter3-06.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-06.png rename to src/chapter3/imgs/hpp_chapter3-06.png diff --git a/content/part3/slides/imgs/hpp_part3-07.png b/src/chapter3/imgs/hpp_chapter3-07.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-07.png rename to src/chapter3/imgs/hpp_chapter3-07.png diff --git a/content/part3/slides/imgs/hpp_part3-08.png b/src/chapter3/imgs/hpp_chapter3-08.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-08.png rename to src/chapter3/imgs/hpp_chapter3-08.png diff --git a/content/part3/slides/imgs/hpp_part3-09.png b/src/chapter3/imgs/hpp_chapter3-09.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-09.png rename to src/chapter3/imgs/hpp_chapter3-09.png diff --git a/content/part3/slides/imgs/hpp_part3-10.png b/src/chapter3/imgs/hpp_chapter3-10.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-10.png rename to src/chapter3/imgs/hpp_chapter3-10.png diff --git a/content/part3/slides/imgs/hpp_part3-11.png b/src/chapter3/imgs/hpp_chapter3-11.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-11.png rename to src/chapter3/imgs/hpp_chapter3-11.png diff --git a/content/part3/slides/imgs/hpp_part3-12.png b/src/chapter3/imgs/hpp_chapter3-12.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-12.png rename to src/chapter3/imgs/hpp_chapter3-12.png diff --git a/content/part3/slides/imgs/hpp_part3-13.png b/src/chapter3/imgs/hpp_chapter3-13.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-13.png rename to src/chapter3/imgs/hpp_chapter3-13.png diff --git a/content/part3/slides/imgs/hpp_part3-14.png b/src/chapter3/imgs/hpp_chapter3-14.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-14.png rename to src/chapter3/imgs/hpp_chapter3-14.png diff --git a/content/part3/slides/imgs/hpp_part3-15.png b/src/chapter3/imgs/hpp_chapter3-15.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-15.png rename to src/chapter3/imgs/hpp_chapter3-15.png diff --git a/content/part3/slides/imgs/hpp_part3-16.png b/src/chapter3/imgs/hpp_chapter3-16.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-16.png rename to src/chapter3/imgs/hpp_chapter3-16.png diff --git a/content/part3/slides/imgs/hpp_part3-17.png b/src/chapter3/imgs/hpp_chapter3-17.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-17.png rename to src/chapter3/imgs/hpp_chapter3-17.png diff --git a/content/part3/slides/imgs/hpp_part3-18.png b/src/chapter3/imgs/hpp_chapter3-18.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-18.png rename to src/chapter3/imgs/hpp_chapter3-18.png diff --git a/content/part3/slides/imgs/hpp_part3-19.png b/src/chapter3/imgs/hpp_chapter3-19.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-19.png rename to src/chapter3/imgs/hpp_chapter3-19.png diff --git a/content/part3/slides/imgs/hpp_part3-20.png b/src/chapter3/imgs/hpp_chapter3-20.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-20.png rename to src/chapter3/imgs/hpp_chapter3-20.png diff --git a/content/part3/slides/imgs/hpp_part3-21.png b/src/chapter3/imgs/hpp_chapter3-21.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-21.png rename to src/chapter3/imgs/hpp_chapter3-21.png diff --git a/content/part3/slides/imgs/hpp_part3-22.png b/src/chapter3/imgs/hpp_chapter3-22.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-22.png rename to src/chapter3/imgs/hpp_chapter3-22.png diff --git a/content/part3/slides/imgs/hpp_part3-23.png b/src/chapter3/imgs/hpp_chapter3-23.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-23.png rename to src/chapter3/imgs/hpp_chapter3-23.png diff --git a/content/part3/slides/imgs/hpp_part3-24.png b/src/chapter3/imgs/hpp_chapter3-24.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-24.png rename to src/chapter3/imgs/hpp_chapter3-24.png diff --git a/content/part3/slides/imgs/hpp_part3-25.png b/src/chapter3/imgs/hpp_chapter3-25.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-25.png rename to src/chapter3/imgs/hpp_chapter3-25.png diff --git a/content/part3/slides/imgs/hpp_part3-26.png b/src/chapter3/imgs/hpp_chapter3-26.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-26.png rename to src/chapter3/imgs/hpp_chapter3-26.png diff --git a/content/part3/slides/imgs/hpp_part3-27.png b/src/chapter3/imgs/hpp_chapter3-27.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-27.png rename to src/chapter3/imgs/hpp_chapter3-27.png diff --git a/content/part3/slides/imgs/hpp_part3-28.png b/src/chapter3/imgs/hpp_chapter3-28.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-28.png rename to src/chapter3/imgs/hpp_chapter3-28.png diff --git a/content/part3/slides/imgs/hpp_part3-29.png b/src/chapter3/imgs/hpp_chapter3-29.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-29.png rename to src/chapter3/imgs/hpp_chapter3-29.png diff --git a/content/part3/slides/imgs/hpp_part3-30.png b/src/chapter3/imgs/hpp_chapter3-30.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-30.png rename to src/chapter3/imgs/hpp_chapter3-30.png diff --git a/content/part3/slides/imgs/hpp_part3-31.png b/src/chapter3/imgs/hpp_chapter3-31.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-31.png rename to src/chapter3/imgs/hpp_chapter3-31.png diff --git a/content/part3/slides/imgs/hpp_part3-32.png b/src/chapter3/imgs/hpp_chapter3-32.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-32.png rename to src/chapter3/imgs/hpp_chapter3-32.png diff --git a/content/part3/slides/imgs/hpp_part3-33.png b/src/chapter3/imgs/hpp_chapter3-33.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-33.png rename to src/chapter3/imgs/hpp_chapter3-33.png diff --git a/content/part3/slides/imgs/hpp_part3-34.png b/src/chapter3/imgs/hpp_chapter3-34.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-34.png rename to src/chapter3/imgs/hpp_chapter3-34.png diff --git a/content/part3/slides/imgs/hpp_part3-35.png b/src/chapter3/imgs/hpp_chapter3-35.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-35.png rename to src/chapter3/imgs/hpp_chapter3-35.png diff --git a/content/part3/slides/imgs/hpp_part3-36.png b/src/chapter3/imgs/hpp_chapter3-36.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-36.png rename to src/chapter3/imgs/hpp_chapter3-36.png diff --git a/content/part3/slides/imgs/hpp_part3-37.png b/src/chapter3/imgs/hpp_chapter3-37.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-37.png rename to src/chapter3/imgs/hpp_chapter3-37.png diff --git a/content/part3/slides/imgs/hpp_part3-38.png b/src/chapter3/imgs/hpp_chapter3-38.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-38.png rename to src/chapter3/imgs/hpp_chapter3-38.png diff --git a/content/part3/slides/imgs/hpp_part3-39.png b/src/chapter3/imgs/hpp_chapter3-39.png similarity index 100% rename from content/part3/slides/imgs/hpp_part3-39.png rename to src/chapter3/imgs/hpp_chapter3-39.png diff --git a/content/part3/tasks/memory.md b/src/chapter3/memory.md similarity index 70% rename from content/part3/tasks/memory.md rename to src/chapter3/memory.md index cdbb973..1b7437a 100644 --- a/content/part3/tasks/memory.md +++ b/src/chapter3/memory.md @@ -1,25 +1,14 @@ # Dynamic Memory -## Contents +C++ gives us precise control of how memory is used. This allows programs to be highly optimised and control the amount of overhead a program has but means that memory must be managed by manually. -- [Dynamic Memory](#dynamic-memory) - - [Contents](#contents) - - [Task 3](#task-3) - - [Task 3.1 : Stack vs Heap](#task-31--stack-vs-heap) - - [Task 3.2 : new and delete](#task-32--new-and-delete) - - [Task 3.3 : Dynamic Slices](#task-33--dynamic-slices) - - [Task 3.4 : Forewarning on Dynamic Memory Management](#task-34--forewarning-on-dynamic-memory-management) - - [Links](#links) - -## Task 3 - -### Task 3.1 : Stack vs Heap +## Stack vs Heap In almost all computers there are two kinds of memory resource pools. The first kind, which we have been using exclusively so far is called the stack. Stack memory is the local memory resources that the computers OS is willing give the program when it runs. However, the stack is limited in size and it is very easy to use up all of the stacks available memory very quickly. This is where the second memory resource pool comes in called the heap or the free store. The heap is a much larger pool of memory programs can access and utilise but there is a catch to its use. You must go through the operating system each time you want memory from the heap. You are also responsible for returning ownership of that memory to the OS when you are done. -### Task 3.2 : new and delete +## `new` and `delete` So, how do we get memory from the heap. This is done with a `new` expression. `new` is a keyword that invokes the OS's memory resource allocator giving you access to memory from the OS. `new` returns a pointer of the allocated resources type. You can use this pointer however you need to like any other pointer but, after you have finished using the memory resource you must relinquish ownership of it using `delete` on the pointer holding the resource. Not doing so will cause a memory leak. @@ -42,7 +31,7 @@ auto main () -> int [Example](https://www.godbolt.org/z/v13hfhM54) -### Task 3.3 : Dynamic Slices +## Dynamic Slices You can also allocate slices using `new[]` expressions and deallocate with `delete[]`. @@ -72,13 +61,6 @@ auto main () -> int [Example](https://www.godbolt.org/z/fx7136qnv) -### Task 3.4 : Forewarning on Dynamic Memory Management - -Dynamic memory management is hard to get right and very easy to get wrong. Memory leaks occur and cause dramatic problems for critical systems and slow a program and even an entire computer to a grinding halt. Avoid using raw `new` and `delete` expressions in anything beyond trivial programs or unless you know what you are doing. In [Week 5](/content/week5/README.md) we will look at various principles that will assists in resource usage; including memory, to ensure C++ program are safe. That being said, have a toy with `new` and `delete` now to get an idea of how they work. - -## Links +## Forewarning on Dynamic Memory Management -- [Previous Page : Slices](/content/part3/tasks/slices.md) -- [Next Page : References](/content/part3/tasks/references.md) -- [Content](/content/README.md) -- [HOME](/README.md) +Dynamic memory management is hard to get right and very easy to get wrong. Memory leaks occur and cause dramatic problems for critical systems and slow a program and even an entire computer to a grinding halt. Avoid using raw `new` and `delete` expressions in anything beyond trivial programs or unless you know what you are doing. In chapter 5 we will look at various principles that will assists in resource usage; including memory, to ensure C++ program are safe. That being said, have a toy with `new` and `delete` now to get an idea of how they work. diff --git a/content/part3/tasks/pointers.md b/src/chapter3/pointers.md similarity index 80% rename from content/part3/tasks/pointers.md rename to src/chapter3/pointers.md index 0855e8a..2ff808a 100644 --- a/content/part3/tasks/pointers.md +++ b/src/chapter3/pointers.md @@ -1,26 +1,10 @@ # Pointers -## Contents - -- [Pointers](#pointers) - - [Contents](#contents) - - [Task 1](#task-1) - - [Task 1.1 : What is a pointer?](#task-11--what-is-a-pointer) - - [Task 1.2 : Syntax](#task-12--syntax) - - [Task 1.3 : const qualifications](#task-13--const-qualifications) - - [Task 1.4 : void pointers](#task-14--void-pointers) - - [Task 1.5 : Pointer Arithmetic](#task-15--pointer-arithmetic) - - [Task 1.6 : Dereferencing nullptr](#task-16--dereferencing-nullptr) - - [Task 1.7 : Pointers to Pointers](#task-17--pointers-to-pointers) - - [Links](#links) - -## Task 1 - -### Task 1.1 : What is a pointer? +## What is a pointer? Many people seem to struggle with the concept of a pointer. This is mostly due to either, bad teaching or that someone learning C++ (or C or Rust) do not have a concise understanding of memory. Memory can be thought of as a cell that has some value and lives at some address or location in the physical memory. Cells can be as small as a byte and as large a single machine register, typically 8-bytes. -> Note: Registers are the circuit components that hold some value in the CPU that is be operated on. +> Note: Registers are the circuit components that hold some value in the CPU that is be operated on. It can be an instruction or some data. The following data can be mapped to a memory layout below it. @@ -36,30 +20,32 @@ int b {37365}; | 0x00007fff59ae6e94 | 0x000091f5 | | 0x00007fff59ae6e90 | ... | -> - Note: `...` means garbage values. -> - Note: `0x...` is just an indicator that the value is a hexadecimal value -> - Note: We jump backwards because the stack (local memory of your program) starts from the largest address and goes down. This is because the code when stored in memory (as instructions) starts from the lowest value and increases. This prevents overwrites between instructions and data, if managed correctly. -> - Note: The memory addresses here are just random, it differs on every computer and every run of the program, usually. +> ### Notes: +> +> - `...` means garbage values. +> - `0x...` is just an indicator that the value is a hexadecimal value +> - We jump backwards because the stack (local memory of your program) starts from the largest address and goes down. This is because the code when stored in memory (as instructions) starts from the lowest value and increases. This prevents overwrites between instructions and data, if managed correctly. +> - The memory addresses here are just random, it differs on every computer and every run of the program, usually. -We can see that the value of `a` is stored at address `0x00007fff59ae6e94` and `b` is stored at address `0x00007fff59ae6e9c`. The reason the memory address jumps by four is because each memory address stores a single byte, thus to store a 32-bit value (`int`) you need for bytes thus the next memory address will be four addresses away, in this case the value for `b`. +We can see that the value of `a` is stored at address `0x00007fff59ae6e99` and `b` is stored at address `0x00007fff59ae6e94`. The reason the memory address jumps by four is because each memory address stores a single byte, thus to store a 32-bit value (`int`) you need for bytes thus the next memory address will be four addresses away, in this case the value for `b`. But lets say we wanted to refer to the value already stored in `a`. We don't want a copy but we wanted some way to _point_ to the value at that address. Well we could store the address of `a` in another location in memory like so. | Address | Value | |:------------------:|:------------------:| -| 0x00007fff59ae6ea4 | ... | -| 0x00007fff59ae6e9d | 0x00000004 | -| 0x00007fff59ae6e99 | 0x000091f5 | -| 0x00007fff59ae6e94 | 0x00007fff59ae6e94 | -| 0x00007fff59ae6e90 | ... | +| 0x00007fff59ae6e9d | ... | +| 0x00007fff59ae6e99 | 0x00000004 | +| 0x00007fff59ae6e94 | 0x000091f5 | +| 0x00007fff59ae6e90 | 0x00007fff59ae6e99 | +| 0x00007fff59ae6e88 | ... | > Notes: We jump 8-bytes in the address space for the stored address as addresses (in the example at least) are 64-bit in size. -As we can see, address `0x00007fff59ae6e9d` stores the value `0x00007fff59ae6e94` which happens to be the number indicating the address where `a` is stored. +As we can see, address `0x00007fff59ae6e90` stores the value `0x00007fff59ae6e94` which happens to be the number indicating the address where `a` is stored. This is the premise of a pointer. It is a numerical value that holds some address in memory. This is address of another value in a program. -### Task 1.2 : Syntax +## Syntax To create a pointer in C++ is super simple. Given some type `T` the type of a pointer to a value of that type is `T*`. @@ -91,9 +77,10 @@ auto main () -> int ``` [Example](https://www.godbolt.org/z/aaf33YEYW) -[`std::addressof` : cppreference](https://en.cppreference.com/w/cpp/memory/addressof) -### Task 1.3 : const qualifications +[`std::addressof`](https://en.cppreference.com/w/cpp/memory/addressof) + +## const qualifications Because pointers are an independent type, they are able to have to have `const` (among other) qualifications however, the ordering of the qualifications can matter. @@ -127,7 +114,7 @@ auto main () -> int [Example](https://www.godbolt.org/z/sed7Wcf7s) -### Task 1.4 : void pointers +## void pointers Because of C++'s static type system, the type of a pointer must be declared however you can circumvent the type system using `void`. A pointer can be a `void*`, meaning that the type it points to is unbound. When you need to use the type you can then use `static_cast<>()` to create the type that you need. This is actually how C's `malloc()` function works. It returns a `void*` and it is up to the user to cast it to the desired type. @@ -151,7 +138,7 @@ auto main () -> int [C's `malloc()`](https://en.cppreference.com/w/c/memory/malloc) -### Task 1.5 : Pointer Arithmetic +## Pointer Arithmetic Because pointers are just numbers (addresses) we can add and subtract from then as if they were integral types. We can use the increment, decrement, addition, subtraction and subscript (index) operators on pointers (`+`, `-`, `++`, `--` and `[]` respectively). @@ -190,7 +177,7 @@ auto main () -> int [Example](https://www.godbolt.org/z/qdx6csE7x) -### Task 1.6 : Dereferencing nullptr +## Dereferencing nullptr In C++, any assignment and initialisation is is copy by default even when passed to functions. This can be really costly for objects that have a large amount of data stored in them. Pointers make it cheap to pass the data around as you now just have to pass a pointer to it instead of all the data. However, there is a catch to pointers. Pointers can point to nothing, this nothing value is actually the literal `nullptr` we saw in week 0. And you cannot dereference a pointer to `nullptr` as `nullptr` is nothing. This can be really dangerous as this is considered UB which may work, may not compile, may crash the entire program or do something entirely unexpected. @@ -212,7 +199,7 @@ auto main () -> int [Example](https://www.godbolt.org/z/594hMbcz6) -### Task 1.7 : Pointers to Pointers +## Pointers to Pointers It is also possible in C++ to have a pointer to a pointer. This mostly a feature inherited from C and remains in for C++ to interoperate with C and for completeness. Pointers to pointers may seem daunting but are straight forward if you apply the concept of a pointer again. The pointer-to-pointer object points to the address of the pointer object that holds the address of some other object. Pointer-to-pointers have the type `T**` and can be dereferenced to the their value, ie. the address the nested pointer points to or again to get the bottom value. @@ -237,10 +224,3 @@ auto main () -> int [Example](https://www.godbolt.org/z/MPPczrWzd) > Note: `auto` is able to deduce the type if the right-hand-side is a rvalue however, the `const` qualifications cannot be specified. ie. `T* -> auto` and `T** -> auto`. - -## Links - -- [Previous Page : Week 3](/content/part3/README.md) -- [Next Page : Slices](/content/part3/tasks/slices.md) -- [Content](/content/README.md) -- [HOME](/README.md) diff --git a/content/part3/tasks/references.md b/src/chapter3/references.md similarity index 82% rename from content/part3/tasks/references.md rename to src/chapter3/references.md index f8f0917..7c4c5c9 100644 --- a/content/part3/tasks/references.md +++ b/src/chapter3/references.md @@ -1,26 +1,12 @@ # References -## Contents - -- [References](#references) - - [Contents](#contents) - - [Task 4](#task-4) - - [Task 2.1 : What is a reference?](#task-21--what-is-a-reference) - - [Task 4.1.1 : Pointers vs References](#task-411--pointers-vs-references) - - [Task 4.2 : Syntax](#task-42--syntax) - - [Task 4.3 : const qualifications](#task-43--const-qualifications) - - [Task 4.4 : Move Semantics](#task-44--move-semantics) - - [Links](#links) - -## Task 4 - -### Task 2.1 : What is a reference? +## What is a reference? So far we have learnt about pointers and how they are useful in distributing access to a memory resource that is expensive to copy as well as create contiguous sequences of values or slices. We have also seen how to get larger memory resources from the OS using `new` and `delete` expressions. However, we have also seen that pointers have caveats. They can lead to memory leaks and other various issues about ownership and lifetime of objects. In C++ there is another facility that allows for you to refer to objects in different scopes that do not feature the same pitfalls of pointers. These are called references. References are; as the the name suggests a reference to an existing object or in other words an alias for an existing object. Operations done on a reference are truly done on the original object. This helps to avoid the cumbersome and error prone nature of pointers. -### Task 4.1.1 : Pointers vs References +## Pointers vs References | Pitfall | Pointers | References | Meaning | |:------------------------------:|:--------:|:----------:|:----------------------------------------------------------------------------------------------------------------------------:| @@ -30,7 +16,7 @@ In C++ there is another facility that allows for you to refer to objects in diff | Multiple levels of indirection | ✅ | ❌ | You cannot have a reference of a reference. | | Pointer arithmetic | ✅ | ❌ | You cannot increment (etc.) a reference like a pointer | -### Task 4.2 : Syntax +## Syntax References are declared as `T&`. References must also have an initialiser. @@ -57,7 +43,7 @@ auto main () -> int [Example](https://www.godbolt.org/z/7TWjK5rKe) -### Task 4.3 : const qualifications +## const qualifications Because references cannot be rebound to reference a new object `const` qualifications are must simpler than pointers. References themselves are alway constant, that is always point to the same thing however, you can specify that the object itself is constant with `const T&`. This means that the the object the reference refers to cannot be modified. @@ -91,15 +77,8 @@ auto main () -> int > Note: You can substitute just the type `T` of a reference for `auto` ie. `T& -> auto&` and `const T& -> const auto&` -### Task 4.4 : Move Semantics +## Move Semantics References are also used to denote move semantics in functions. So far we have only seen value, pointer and reference semantics. Move semantics allow for a function to take ownership of an objects resources. Move semantics are denoted using the `T&&` type signature, this is also called a rvalue. This allows us to rip out the guts of an object and use it how we please. To create a rvalue from an existing object we use the `std::move()` function from the `` header. -The difficulty of move semantics is it only applies to objects that can move ie. types with move constructors and move assignments. Without these constructors `T&&` just becomes a regular reference. This is the case for primitive types in C++. We will cover more on the specifics of moves in [Week 5](/content/week5/README.md). - -## Links - -- [Previous Page : Dynamic Memory](/content/part3/tasks/memory.md) -- [Next Page : Introduction to the Standard Library](/content/part3/tasks/stdlib.md) -- [Content](/content/README.md) -- [HOME](/README.md) +The difficulty of move semantics is it only applies to objects that can move ie. types with move constructors and move assignments. Without these constructors `T&&` just becomes a regular reference. This is the case for primitive types in C++. We will cover more on the specifics of moves in chapter 5. diff --git a/content/part3/tasks/slices.md b/src/chapter3/slices.md similarity index 66% rename from content/part3/tasks/slices.md rename to src/chapter3/slices.md index 2f26ba8..fe9f3e4 100644 --- a/content/part3/tasks/slices.md +++ b/src/chapter3/slices.md @@ -1,20 +1,6 @@ # Slices -## Contents - -- [Slices](#slices) - - [Contents](#contents) - - [Task 2](#task-2) - - [Task 2.1 : What is a slice?](#task-21--what-is-a-slice) - - [Task 2.2 : Syntax](#task-22--syntax) - - [Task 2.2.1 : Iteration](#task-221---iteration) - - [Task 2.3 : Slices vs Pointers](#task-23--slices-vs-pointers) - - [Task 2.3.1 : String Literals and Character Slices](#task-231--string-literals-and-character-slices) - - [Links](#links) - -## Task 2 - -### Task 2.1 : What is a slice? +## What is a slice? Working with single value objects and variables can be be tedious and doesn't allow for collecting common data efficiently into a single, easy to refer to object. This is were C++ slices come in. Slices are contiguous sequences of values. The length of a slice must be known at compile time and cannot change. Slices can hold any type including primitive types, user-defined types or even pointers. @@ -22,7 +8,7 @@ We have already been using slices in C++ thus far. String literals are actually > Note: Technically slices are called 'built-in arrays' in C++ but I'm opting for an alternative naming convention to avoid confusion later and because 'built-in arrays' is annoying to say. -### Task 2.2 : Syntax +## Syntax The syntax for a slice is strait forward and goes as follows: `T v[N] { ... };`, where @@ -34,7 +20,7 @@ The syntax for a slice is strait forward and goes as follows: `T v[N] { ... };`, > - Note: `N` can be elided if `{ ... }` is a fixed size. > - Note: `{ ... }` is called an aggregate initialiser -#### Task 2.2.1 : Iteration +### Iteration To access the elements of a slice you use the subscript (index) operator `[i]` where `i` is an unsigned integral from `0..N-1`, where `[0]` gets the first element and `[1]` gets the second element etc. @@ -61,7 +47,7 @@ auto main () -> int [Example](https://www.godbolt.org/z/eGs9PTvfb) -### Task 2.3 : Slices vs Pointers +## Slices vs Pointers In C++, slices can; and often will, decay into a pointer. This is because, under the hood, slices are just pointers to a sequence of elements that are contiguous in memory. This makes it efficient to refer to arrays as you can pass around the pointer to its first element. Using the same example as above, if we change `print()` to take an integer pointer `int* arr` instead of `int arr[]` we get the exact some behavior. This is because C++ efficiently packs data together so the exist next to each other in memory. @@ -88,13 +74,6 @@ auto main () -> int [Example](https://www.godbolt.org/z/r7or3x7Tj) -### Task 2.3.1 : String Literals and Character Slices - -In C++, the string literal is a `char _[]` or can (usually) decay into a `const char*`. This make them efficient to create and refer to but can have some unfortunate caveats. The biggest issue is that slices are not very user friendly. This is mostly due to them being inherited from C which is; in contrast to C++, a much simpler language that could not afford; at the time of its creation, the more user friendly abstractions C++ has available to it. - -## Links +## String Literals and Character Slices -- [Previous Page : Pointers](/content/part3/tasks/pointers.md) -- [Next Page : Dynamic Memory](/content/part3/tasks/memory.md) -- [Content](/content/README.md) -- [HOME](/README.md) +In C++, the string literal is a `char[]` or can (usually) decay into a `const char*`. This make them efficient to create and refer to but can have some unfortunate caveats. The biggest issue is that slices are not very user friendly. This is mostly due to them being inherited from C which is; in contrast to C++, a much simpler language that could not afford; at the time of its creation, the more user friendly abstractions C++ has available to it. diff --git a/src/chapter3/slides3.md b/src/chapter3/slides3.md new file mode 100644 index 0000000..b04f26e --- /dev/null +++ b/src/chapter3/slides3.md @@ -0,0 +1,41 @@ +# Slides + +![Slides 01](./imgs/hpp_chapter3-01.png) +![Slides 02](./imgs/hpp_chapter3-02.png) +![Slides 03](./imgs/hpp_chapter3-03.png) +![Slides 04](./imgs/hpp_chapter3-04.png) +![Slides 05](./imgs/hpp_chapter3-05.png) +![Slides 06](./imgs/hpp_chapter3-06.png) +![Slides 07](./imgs/hpp_chapter3-07.png) +![Slides 08](./imgs/hpp_chapter3-08.png) +![Slides 09](./imgs/hpp_chapter3-09.png) +![Slides 10](./imgs/hpp_chapter3-10.png) +![Slides 11](./imgs/hpp_chapter3-11.png) +![Slides 12](./imgs/hpp_chapter3-12.png) +![Slides 13](./imgs/hpp_chapter3-13.png) +![Slides 14](./imgs/hpp_chapter3-14.png) +![Slides 15](./imgs/hpp_chapter3-15.png) +![Slides 16](./imgs/hpp_chapter3-16.png) +![Slides 17](./imgs/hpp_chapter3-17.png) +![Slides 18](./imgs/hpp_chapter3-18.png) +![Slides 19](./imgs/hpp_chapter3-19.png) +![Slides 20](./imgs/hpp_chapter3-20.png) +![Slides 21](./imgs/hpp_chapter3-21.png) +![Slides 22](./imgs/hpp_chapter3-22.png) +![Slides 23](./imgs/hpp_chapter3-23.png) +![Slides 24](./imgs/hpp_chapter3-24.png) +![Slides 25](./imgs/hpp_chapter3-25.png) +![Slides 26](./imgs/hpp_chapter3-26.png) +![Slides 27](./imgs/hpp_chapter3-27.png) +![Slides 28](./imgs/hpp_chapter3-28.png) +![Slides 29](./imgs/hpp_chapter3-29.png) +![Slides 30](./imgs/hpp_chapter3-30.png) +![Slides 31](./imgs/hpp_chapter3-31.png) +![Slides 32](./imgs/hpp_chapter3-32.png) +![Slides 33](./imgs/hpp_chapter3-33.png) +![Slides 34](./imgs/hpp_chapter3-34.png) +![Slides 35](./imgs/hpp_chapter3-35.png) +![Slides 36](./imgs/hpp_chapter3-36.png) +![Slides 37](./imgs/hpp_chapter3-37.png) +![Slides 38](./imgs/hpp_chapter3-38.png) +![Slides 39](./imgs/hpp_chapter3-39.png) diff --git a/content/part3/tasks/stdlib.md b/src/chapter3/stdlib.md similarity index 68% rename from content/part3/tasks/stdlib.md rename to src/chapter3/stdlib.md index 40216d7..79ac1bd 100644 --- a/content/part3/tasks/stdlib.md +++ b/src/chapter3/stdlib.md @@ -1,53 +1,23 @@ # Introduction to the Standard Library -## Contents - -- [Introduction to the Standard Library](#introduction-to-the-standard-library) - - [Contents](#contents) - - [Task 5](#task-5) - - [Task 5.1 : What is the Standard Library](#task-51--what-is-the-standard-library) - - [Task 5.2 : Initializer Lists](#task-52--initializer-lists) - - [Task 5.3 : Arrays](#task-53--arrays) - - [Task 5.3.1 : Member Access](#task-531--member-access) - - [Task 5.4 : Spans](#task-54--spans) - - [Task 5.5 : Strings](#task-55--strings) - - [Task 5.5.1 : String Views](#task-551--string-views) - - [Task 5.5.2 : Literal Operators](#task-552--literal-operators) - - [Task 5.6 : Smart Pointers](#task-56--smart-pointers) - - [Task 5.6.1 : Unique Pointer](#task-561--unique-pointer) - - [Task 5.6.2 : Shared Pointer](#task-562--shared-pointer) - - [Task 5.6.3 : Weak Pointer](#task-563--weak-pointer) - - [Links](#links) - -## Task 5 - -### Task 5.1 : What is the Standard Library +## What is the Standard Library The Standard Library is the full set of features in C++ that are available outside the pure language. These include mathematical functions, IO facilities, containers, algorithms and much more. These are tools that abstract a lot of the useful mechanics of C++ into safe, efficient and fast facilities that are easier to use, more consistent and far superior in functionality. The C++ Standard Library is included using headers. These are the files we have been importing using the `#include` preprocessor directive. This week you will learn about the most useful and bare-bones features in the Standard Library that will make working with C++ much easier, more idiomatic and faster. -### Task 5.2 : Initializer Lists +## Initializer Lists -Throughout the last few weeks we have been using _brace-init-lists_ to initialise objects. This is super useful for _slice-like_ types to be initialised without using for loops. In C++ these brace-init-lists are converted to `std::initializer_list` (where `T` is the element type). This is a useful construct for building user-defined containers that are initialised using a brace-init-list. There is not much use for you in `std::initializer_list` now but it is useful to know about later. One important thing to know about `std::initializer_list` is that is is a construction only type. That is it is only used to create object, you cannot return a `std::initializer_list` from a function. +Throughout the last few weeks we have been using _brace-init-lists_ to initialise objects. This is super useful for _slice-like_ types to be initialised without using for loops. In C++ these brace-init-lists are converted to `std::initializer_list` (where `T` is the element type). This is a useful construct for building user-defined containers that are initialised using a brace-init-list. There is not much use for you in `std::initializer_list` now but it is useful to know about later. One important thing to know about `std::initializer_list` is that is is a construction only type. That is it is only used to create object, you cannot return a `std::initializer_list` from a function. -- Header - `` -- Type signature - `std::initializer_list` - - `E` - element type -- [`std::initializer_list` : cppreference](https://en.cppreference.com/w/cpp/utility/initializer_list) +[`std::initializer_list`](https://en.cppreference.com/w/cpp/utility/initializer_list) -### Task 5.3 : Arrays +## Arrays Slices are useful for packing contiguous data into a single object but because of the implicit nature of decaying into pointers they can be error prone. This is where C++'s array type come in. `std::array` comes in. This is a complete array type that store both its data and size. Like slices, `std::array` must know its type and size at compile time and the type must be the same throughout the array. Because `std::array` is a complete object you can use reference semantics on it in an intuitive way. It is highly recommended to use `std::array` instead of slices everywhere you can. -- Header - `` -- Type signature - `std::array` - - `T` - Element type - - `N` - Size of the array -- [`std::array` : cppreference](https://en.cppreference.com/w/cpp/container/array) - ```cxx #include #include @@ -74,19 +44,15 @@ auto main () -> int [Example](https://www.godbolt.org/z/dbcKqx53f) -### Task 5.3.1 : Member Access +[`std::array`](https://en.cppreference.com/w/cpp/container/array) -Because we are know looking at some custom types from C++'s standard library it is important to point out how to access member functions and variables of both objects and pointers. For an object `T t();` with a member variable you access it using the `.` operator like `t.foo`. If `t::foo` is a member function you postfix parentheses to call the function like `t.foo()`. If the object is a pointer say `T* tp = &t` then the `->` operator is used instead of `.`. +## Member Access -### Task 5.4 : Spans +Because we are know looking at some custom types from C++'s standard library it is important to point out how to access member functions and variables of both objects and pointers. For an object `T t();` with a member variable you access it using the `.` operator like `t.foo`. If `t::foo` is a member function you postfix parentheses to call the function like `t.foo()`. If the object is a pointer say `T* tp = &t` then the `->` operator is used instead of `.`. -Another useful _slice-like_ structure is a `std::span`. Remember the `print()` function in [Task 2.2-2.3](/content//part3/tasks/slices.md#task-22--syntax) that took a slice and a size. This is common place in many old C and C++ libraries that used pointer for all buffers. `std::span` removes the need for pointers altogether. `std::span` is a non-owning view of any object that has some contiguous data and a size. This allows libraries to accept a multitude of different intpu types that resemble the shape and work seamlessly with them all. +## Spans -- Header - `` -- Type signature - `std::span` - - `T` - Type of the elements - - `Extent` - Size of the span, can be dynamic or static -- [`std::span` : cppreference](https://en.cppreference.com/w/cpp/container/span) +Another useful _slice-like_ structure is a `std::span`. Remember the `print()` function (in slices section of this chapter) that took a slice and a size. This is common place in many old C and C++ libraries that used pointer for all buffers. `std::span` removes the need for pointers altogether. `std::span` is a non-owning view of any object that has some contiguous data and a size. This allows libraries to accept a multitude of different intpu types that resemble the shape and work seamlessly with them all. ```cxx #include @@ -115,15 +81,11 @@ auto main () -> int [Example](https://www.godbolt.org/z/4Yo93e7Tr) -### Task 5.5 : Strings - -Now that we have a much more powerful array type at out disposal it might be tempting to use it as a character array for strings and while this is viable we often want to form a very different set of operations on strings compared to arrays. For this we have `std::string`. `std::string` is a specialised type that has a much larger interface of string operations. +[`std::span`](https://en.cppreference.com/w/cpp/container/span) -> Note: There are also string type for all of C++'s character types eg. `wchar_t`. +## Strings -- Header - `` -- Type signature - `std::basic_string` -- [`std::string` : cppreference](https://en.cppreference.com/w/cpp/string/basic_string) +Now that we have a much more powerful array type at out disposal it might be tempting to use it as a character array for strings and while this is viable we often want to form a very different set of operations on strings compared to arrays. For this we have `std::string`. `std::string` is a specialised type that has a much larger interface of string operations. ```cxx #include @@ -141,15 +103,15 @@ auto main () -> int } ``` +> Note: There are also string type for all of C++'s character types eg. `wchar_t`. + [Example](https://www.godbolt.org/z/hqT44PM7M) -#### Task 5.5.1 : String Views +[`std::string`](https://en.cppreference.com/w/cpp/string/basic_string) -There are also span like views for strings. This is called `std::string_view`. Like span it doesn't own its string but can be used to access its value. This is designed to be a replacement for character slices. +### String Views -- Header - `` -- Type signature - `std::basic_string_view` -- [`std::string_view` : cppreference](https://en.cppreference.com/w/cpp/string/basic_string_view) +There are also span like views for strings. This is called `std::string_view`. Like span it doesn't own its string but can be used to access its value. This is designed to be a replacement for character slices. ```cxx #include @@ -168,11 +130,11 @@ auto main () -> int [Example](https://www.godbolt.org/z/cbb95YWWj) -#### Task 5.5.2 : Literal Operators +[`std::string_view`](https://en.cppreference.com/w/cpp/string/basic_string_view) -In C++ the is a cool operator called the literal operator `""`. This is used to construct literals from string literals. The are string literal operators for `std::string` and `std::string_view` which are `""s` and `""sv` respectively. +### Literal Operators -- namespace - `std::literals` +In C++ the is a cool operator called the literal operator `""`. This is used to construct literals from string literals. The are string literal operators for `std::string` and `std::string_view` which are `""s` and `""sv` respectively. ```cxx #include @@ -198,21 +160,16 @@ auto main () -> int [Example](https://www.godbolt.org/z/jcMfrG76c) -### Task 5.6 : Smart Pointers +## Smart Pointers The final facility we will look at is C++'s smart pointers. Smart pointers allow for automatic lifetime management of heap allocated memory resources. It is highly recommended to only use smart pointers for for any kind of head resource. All smart pointers are in the `` header. -#### Task 5.6.1 : Unique Pointer +### Unique Pointer `std::unique_ptr` is a pointer to a uniquely owned resource. It cannot be copied, only moved. When a `std::unique_ptr` goes out of scope it automatically deletes the allocated resource. Because `std::unique_ptr` is a complete object you can pass a reference of a `std::unique_ptr` and modify the underlying value like a pointer. It also offers a safer `std::unique_ptr::get()` method that returns `nullptr` if the `std::unique_ptr` points to nothing. -- Type signature - `std::unique_ptr` - - `T` - Type of pointed to object - - `Deleter` - Deleter functor -[`std::unique_ptr` : cppreference](https://en.cppreference.com/w/cpp/memory/unique_ptr) - ```cxx #include #include @@ -247,14 +204,11 @@ auto main () -> int [Example](https://www.godbolt.org/z/G1T1j84nE) -#### Task 5.6.2 : Shared Pointer +[`std::unique_ptr`](https://en.cppreference.com/w/cpp/memory/unique_ptr) -Sometimes it useful to have multiple pointers refer to the same dynamic memory resource. However, one issue of this is there is know way to know if the memory resource is still needed but another pointer meaning a memory resource can be released accidently leaving all other pointers to the now deleted resource a dangling pointer. This is where `std::shared_ptr` comes in handy. This pointer will maintain a count or how many pointers refer to it. Only when this count reaches zero, indicating no more pointers are using the resource will the resource get deleted. This gives the behavior of many garbage collected languages without the massive overhead of a global gabage collecting program. +### Shared Pointer -- Type signature - `std::shared_ptr` - - `T` - Element type - - `Deleter` - Deleter functor -- [`std::shared_ptr` : cppreference](https://en.cppreference.com/w/cpp/memory/shared_ptr) +Sometimes it useful to have multiple pointers refer to the same dynamic memory resource. However, one issue of this is there is know way to know if the memory resource is still needed but another pointer meaning a memory resource can be released accidently leaving all other pointers to the now deleted resource a dangling pointer. This is where `std::shared_ptr` comes in handy. This pointer will maintain a count or how many pointers refer to it. Only when this count reaches zero, indicating no more pointers are using the resource will the resource get deleted. This gives the behavior of many garbage collected languages without the massive overhead of a global gabage collecting program. ```cxx #include @@ -285,13 +239,11 @@ auto main () -> int [Example](https://www.godbolt.org/z/39dPYooTW) -#### Task 5.6.3 : Weak Pointer +[`std::shared_ptr`](https://en.cppreference.com/w/cpp/memory/shared_ptr) -Sometimes it is useful to observe an existing resource that is managed by `std::shared_ptr` and only assume temporary ownership if the object still exists. This is where `std::weak_ptr` is used. It is constructed from an existing `std::shared_ptr` and observes the memory resource and is able to be converted to a `std::shared_ptr` when it needs to access the resource. This is useful for breaking reference cycles of `std::shared_ptr`'s and extend the lifetime of a memory resource to the scope of a `std::weak_ptr`. It is also able to check if the resource has been deleted already. +### Weak Pointer -- Type signature - `std::weak_ptr` - - `T` - Element type -- [`std::weak_ptr` : cppreference](https://en.cppreference.com/w/cpp/memory/weak_ptr) +Sometimes it is useful to observe an existing resource that is managed by `std::shared_ptr` and only assume temporary ownership if the object still exists. This is where `std::weak_ptr` is used. It is constructed from an existing `std::shared_ptr` and observes the memory resource and is able to be converted to a `std::shared_ptr` when it needs to access the resource. This is useful for breaking reference cycles of `std::shared_ptr`'s and extend the lifetime of a memory resource to the scope of a `std::weak_ptr`. It is also able to check if the resource has been deleted already. ```cxx #include @@ -325,9 +277,4 @@ auto main () -> int [Example](https://www.godbolt.org/z/PaonscnEG) -## Links - -- [Previous Page : References](/content/part3/tasks/references.md) -- [Back to Part 3](/content/part3/README.md) -- [Content](/content/README.md) -- [HOME](/README.md) +[`std::weak_ptr`](https://en.cppreference.com/w/cpp/memory/weak_ptr) diff --git a/src/chapter4/README.md b/src/chapter4/README.md new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/chapter4/README.md @@ -0,0 +1 @@ + diff --git a/content/part4/tasks/advfunc.md b/src/chapter4/advfunc.md similarity index 76% rename from content/part4/tasks/advfunc.md rename to src/chapter4/advfunc.md index f6551b5..73121f8 100644 --- a/content/part4/tasks/advfunc.md +++ b/src/chapter4/advfunc.md @@ -1,37 +1,13 @@ # Advanced Functions -## Contents - -- [Advanced Functions](#advanced-functions) - - [Contents](#contents) - - [Task 1](#task-1) - - [Task 1.1 : Advanced Functions Specification](#task-11--advanced-functions-specification) - - [Task 1.1.1 : No exception optimization](#task-111--no-exception-optimization) - - [Task 1.1.2 : Attributes](#task-112--attributes) - - [Task 1.1.3 : Auto Function](#task-113--auto-function) - - [Task 1.2 : Function Overloading](#task-12--function-overloading) - - [Task 1.2.1 : Operator Overloading](#task-121--operator-overloading) - - [Task 1.3 : Function Utilities](#task-13--function-utilities) - - [Task 1.3.1 : Perfect Forwarding](#task-131--perfect-forwarding) - - [Task 1.3.2 : Value and Type Helpers](#task-132--value-and-type-helpers) - - [Task 1.4 : Functional Programming](#task-14--functional-programming) - - [Task 1.4.1 : Function Types](#task-141--function-types) - - [Task 1.4.2 : Lambdas and Closures](#task-142--lambdas-and-closures) - - [Task 1.4.3 : Partial Application](#task-143--partial-application) - - [Links](#links) - -## Task 1 - -### Task 1.1 : Advanced Functions Specification - -We saw in [part 2](/content/part2/README.md) how to create functions to abstract usable pieces of code into smaller and more modular components. This is the bare-bones of functions of C++. Functions come in a lot of forms in C++ and have to make different guarantees about how they operate. This is done with various specifiers and labels that indicate to the compiler what a function is expected to do. Some of these we have seen including parameter and return value types along with these types various there CV-qualifications however, there are a few that have not been covered yet. Throughout this page we will build up a function signature from the blueprint below by adding new specifiers to showcase the syntax. +We saw in chapter 2 how to create functions to abstract usable pieces of code into smaller and more modular components. This is the bare-bones of functions of C++. Functions come in a lot of forms in C++ and have to make different guarantees about how they operate. This is done with various specifiers and labels that indicate to the compiler what a function is expected to do. Some of these we have seen including parameter and return value types along with these types various there CV-qualifications however, there are a few that have not been covered yet. Throughout this page we will build up a function signature from the blueprint below by adding new specifiers to showcase the syntax. ```cxx int f(int n) { return n; } ``` -#### Task 1.1.1 : No exception optimization +## No exception optimization WE won't be covering exceptions in this course as they are quite an advanced topic that is hard to use and costly to get wrong. We may cover exceptions at a later date. In C++ some functions may throw exceptions when ill-formed behavior occurs and but it can be handled so the system can remain operational. However, some functions we can make guarantees at compile time that they will not throw an exception. This allows the compiler to optimise the execution path knowing that it will not need to recover the stack. To do this, we mark a function `noexcept` keyword. If a `noexcept` functions does throw, the program calls `std::terminate`. @@ -40,9 +16,9 @@ int f(int n) noexcept { return n; } ``` -[`noexcept` : cppreference](https://en.cppreference.com/w/cpp/language/noexcept_spec) +[`noexcept`](https://en.cppreference.com/w/cpp/language/noexcept_spec) -#### Task 1.1.2 : Attributes +## Attributes Attributes are a declarator that indicates a condition of a function. Attributes are prefixed before the return type of the function using the double square-bracket notation `[[attribute-name]]`. C++ only has a few standard attributes so far but compilers often introduce their own for optimisation of the compiler. @@ -57,9 +33,9 @@ int f(int n) noexcept { return n; } ``` -[**_attributes_** : cppreference](https://en.cppreference.com/w/cpp/language/attributes) +[**_attributes_**](https://en.cppreference.com/w/cpp/language/attributes) -#### Task 1.1.3 : Auto Function +## Auto Function Sometimes the return value of a function is a complicated type or depends on the type of the parameters of the function. This can be solved using an `auto` declared function with a trailing-return-type. @@ -70,15 +46,15 @@ auto f(int n) noexcept { return n; } ``` -[**_Function Declarations_** : cppreference](https://en.cppreference.com/w/cpp/language/function) +[**_Function Declarations_**](https://en.cppreference.com/w/cpp/language/function) > Note: The styling used above is my own personal syntax styling. You are free to use your own. -### Task 1.2 : Function Overloading +## Function Overloading One difficulty in many programing languages is that you cannot have function symbols with the same name. This creates clashes and ambiguity meaning the compiler doesn't know which function to use. In C++ however, you can have functions with the same symbol (name) as long as there parameters are different. This is called function overloading. This is is achieved due to what is called name mangling. Function names are not simply just the name, say `f` from above but are mangled to include the type of the parameters the function takes. Thus `int f(int n)` is a different function to `float f(float n)`. This powerful feature allows us to create multiple functions that perform the same action but for multiple different types and move type resolution to compile time. -#### Task 1.2.1 : Operator Overloading +### Operator Overloading Function overloading opens the opportunity to create user defined operators. This means you can overload the `+` or `<<` operators to work for custom types or introduce new functionality. This is how the `<<` and `>>` works for stream in C++. The `<<` and `>>` are overloaded to work differently for stream objects. @@ -102,15 +78,15 @@ auto main() -> int [Example](https://www.godbolt.org/z/jaevh6dna) -### Task 1.3 : Function Utilities +## Function Utilities -#### Task 1.3.1 : Perfect Forwarding +### Perfect Forwarding Often in C++ we want to pass arguments from one function to another without modification. An example of this is passing arguments to a wrapper function that might call some old legacy API. However, there can be issues with value categories, const-ness and reference values of parameters that create undefined behaviour, compiler errors etc. To fix this, C++ introduced perfect forwarding, a way to perfectly pass arguments from on function call to another without losing or changing the value category of the parameters. This is done with `std::forward`. I am glossing over the details of this but if you are interested, this [SO answer](https://stackoverflow.com/a/3582313/13429386) gives a great explanation of the problem, attempted solutions and the solution in C++ now. -[`std::forward` : cppreference](https://en.cppreference.com/w/cpp/utility/forward) +[`std::forward`](https://en.cppreference.com/w/cpp/utility/forward) -#### Task 1.3.2 : Value and Type Helpers +### Value and Type Helpers Sometimes it is useful to work with the type of an object, not the value. To obtain the type of an object the `decltype` keyword. This declares the type of the entity or expression passed to the keyword in a function call style. This is useful for deducing the type of an expression once it has been evaluated. @@ -131,9 +107,8 @@ auto main() -> int [Example](https://www.godbolt.org/z/6Gco6zsvs) -[`` : cppreference](https://en.cppreference.com/w/cpp/header/type_traits) - -[`decltype` : cppreference](https://en.cppreference.com/w/cpp/language/decltype) +- [``](https://en.cppreference.com/w/cpp/header/type_traits) +- [`decltype`](https://en.cppreference.com/w/cpp/language/decltype) Sometimes though, it is impossible to find the return type of objects method calls as it requires constructing an actual value. To overcome this, C++ has a neat function called `std::declval`. This is able to construct an rvalue (temporary) in order to access object methods. @@ -151,11 +126,11 @@ auto main() -> int [Example](https://www.godbolt.org/z/qbzqKcffa) -[`std::declval` : cppreference](https://en.cppreference.com/w/cpp/utility/declval) +[`std::declval`](https://en.cppreference.com/w/cpp/utility/declval) -### Task 1.4 : Functional Programming +## Functional Programming -#### Task 1.4.1 : Function Types +### Function Types Functions; like variables, have a type. This makes it possible to use functions are variables that can be passed to other functions. But what is the type of a function? In general the type of a function is composed of its return type and the type of its arguments, ie. `R(P1, P2, P3, ...)`. In C functions are passed as function pointers. It is a powerful utility but can be error prone due to the nature of pointers. Instead, C++ has `std::function` which is able to bind to a function to a variable that can be easily passed around to other functions, copied and moved. @@ -189,9 +164,9 @@ auto main() -> int [Example](https://www.godbolt.org/z/TjrWfM5Th) -[`std::function` : cppreference](https://en.cppreference.com/w/cpp/utility/functional/function) +[`std::function`](https://en.cppreference.com/w/cpp/utility/functional/function) -#### Task 1.4.2 : Lambdas and Closures +### Lambdas and Closures Sometimes functions need to be able to enclose information about the global environment. This requires the use of closures, a local environment that can access the parent environment in which the closure exists in. In C++ this is accomplished with a lambda. Lambdas are anonymous functions that can capture local variables. Anonymous functions are able to be created and passed to other functions without having to exist as a stored function. Lambdas have a unique syntax consisting of three distinct sets of brackets. `[]` is used to specified the captured variables, `()` is the same as regular functions indicating the formal parameters of the lambda that are used when the lambda is invoked, and finally `{}` holds the body of the lambda. @@ -239,9 +214,9 @@ auto main() -> int [Example](https://www.godbolt.org/z/he59bKxPf) -[Lambdas : cppreference](https://en.cppreference.com/w/cpp/language/lambda) +[Lambdas](https://en.cppreference.com/w/cpp/language/lambda) -#### Task 1.4.3 : Partial Application +### Partial Application Another useful technique when working with functions is a technique known as partial application. This is similar to how closures with lambda work with a few key differences. Partial application allows you to partially apply the certain parameters of a function while leaving other empty to be passed at a later invocation. This is done with with the `std::bind` function which takes the function and a variable list of arguments that will be bound to the function in their respective order. The returned function can be invoked like any other function and will be invoked as if the bound variables were passed to it. The power of `std::bind` comes from its ability to accept placeholder values. These values follow the pattern of `_N` where N is any number starting at `1`. Placeholders are passed to `std::bind` can can be placed anywhere in the variable argument list. When the resulting function is invoked, any arguments passed to it will be passed to the underlying function. The first passed argument from the partially applied function will be passed to all instances of the `_1` placeholder and so on. @@ -285,11 +260,9 @@ auto main() -> int [Example](https://www.godbolt.org/z/79T3hYvea) -[`std::bind` : cppreference](https://en.cppreference.com/w/cpp/utility/functional/bind) - -[`std::placeholders` : cppreference](https://en.cppreference.com/w/cpp/utility/functional/placeholders) - -[`std::ref` & `std::cref` : cppreference](https://en.cppreference.com/w/cpp/utility/functional/ref) +- [`std::bind`](https://en.cppreference.com/w/cpp/utility/functional/bind) +- [`std::placeholders`](https://en.cppreference.com/w/cpp/utility/functional/placeholders) +- [`std::ref` & `std::cref`](https://en.cppreference.com/w/cpp/utility/functional/ref) There is also two new functions that have been added to the standard library. These are `std::bind_front` (C++20) and `std::bind_back` (C++23) that allow for efficiently binding parameters to the front or back of a function. These functions do not support the placeholder values like `std::bind`. @@ -318,10 +291,3 @@ auto main() -> int [Example](https://www.godbolt.org/z/vfxG95Eqr) [`std::bind_front` & `std::bind_back`](https://en.cppreference.com/w/cpp/utility/functional/bind_front) - -## Links - -- [Previous Page : Part 4](/content/part4/README.md) -- [Next Page : Namespaces](/content/part4/tasks/namespaces.md) -- [Content](/content/README.md) -- [HOME](/README.md) diff --git a/src/chapter4/chapter4.md b/src/chapter4/chapter4.md new file mode 100644 index 0000000..b2055b9 --- /dev/null +++ b/src/chapter4/chapter4.md @@ -0,0 +1,3 @@ +# Intermediate C++ Features + +Throughout this chapter you will delve deeper into the practical abilities of C++ from advanced function usage and functional programming idioms to logical code separation and modularization. You will also be introduced to a features that allow for the creation of custom types. diff --git a/content/part4/tasks/enums.md b/src/chapter4/enums.md similarity index 80% rename from content/part4/tasks/enums.md rename to src/chapter4/enums.md index bb9c4e3..62a488f 100644 --- a/content/part4/tasks/enums.md +++ b/src/chapter4/enums.md @@ -1,19 +1,5 @@ # Enumerations -## Contents - -- [Enumerations](#enumerations) - - [Contents](#contents) - - [Task 3](#task-3) - - [Task 3.1 : Enumerations](#task-31--enumerations) - - [Task 3.1.2 : Underlying Types and Values](#task-312--underlying-types-and-values) - - [Task 3.2 : Enum Class](#task-32--enum-class) - - [Links](#links) - -## Task 3 - -### Task 3.1 : Enumerations - Enumerations (enums) are a distinct types whose value is one of a restricted range of named integral constants called enumerators. Enums allow for specify a type that may have a value of one of many possible named values. Enums have an underlying integral type where each enumerator is of the underlying type. Enums allow for the restriction of the possible values a type can hold. The value of the enumerators of an enum have begin at 0 and increment. ```cxx @@ -59,15 +45,17 @@ auto main() -> int [Example](https://www.godbolt.org/z/8PMbxxehb) -[Enumerations : cppreference](https://en.cppreference.com/w/cpp/language/enum) +[Enumerations](https://en.cppreference.com/w/cpp/language/enum) -#### Task 3.1.2 : Underlying Types and Values +## Underlying Types and Values In C++ you can specify the underlying type and and value of an enum. To specify the type, the enum's identifier can be followed by a colon with a integral type. To specify the values an enums enumerators are aliasing for, the enumerator name can be followed by a assignment operator and the integral value. -- > Note: Not all enumerators have to have an explicit value if one or more other enumerators do. -- > Note: If an enumerator has an explicit value and the proceeding one is not specified, the proceeding one will assume the next value after the explicit enumerator. -- > Note: Enumerators can have the same underlying value. +> ### Notes: +> +> - Not all enumerators have to have an explicit value if one or more other enumerators do. +> - If an enumerator has an explicit value and the proceeding one is not specified, the proceeding one will assume the next value after the explicit enumerator. +> - Enumerators can have the same underlying value. ```cxx #include @@ -116,7 +104,7 @@ auto main() -> int [Example](https://www.godbolt.org/z/c6E1vjzoK) -### Task 3.2 : Enum Class +## Enum Class Unscoped enums, which is all we have seen thus far can be implicitly converted into there underlying type. This can cause unwanted conversions. To accommodate for this C++ has _scoped enums_ which are declared as `enum class` (or `struct`). They cannot be implicitly converted there underlying type, they have `int` as there underlying type by default and can only be accessed using the names scope resolution operator (`::`) with the name being the name of the enum class. @@ -166,10 +154,3 @@ auto main() -> int ``` [Example](https://www.godbolt.org/z/Kqs6rvvMr) - -## Links - -- [Previous Page : Namespaces](/content/part4/tasks/namespaces.md) -- [Next Page : Unions](/content/part4/tasks/unions.md) -- [Content](/content/README.md) -- [HOME](/README.md) diff --git a/content/part4/slides/hpp_part4.pdf b/src/chapter4/hpp_chapter4.pdf similarity index 99% rename from content/part4/slides/hpp_part4.pdf rename to src/chapter4/hpp_chapter4.pdf index 363488a..91519c6 100644 Binary files a/content/part4/slides/hpp_part4.pdf and b/src/chapter4/hpp_chapter4.pdf differ diff --git a/content/part4/slides/hpp_part4.pptx b/src/chapter4/hpp_chapter4.pptx similarity index 100% rename from content/part4/slides/hpp_part4.pptx rename to src/chapter4/hpp_chapter4.pptx diff --git a/content/part4/slides/imgs/hpp_part4-01.png b/src/chapter4/imgs/hpp_chapter4-01.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-01.png rename to src/chapter4/imgs/hpp_chapter4-01.png diff --git a/content/part4/slides/imgs/hpp_part4-02.png b/src/chapter4/imgs/hpp_chapter4-02.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-02.png rename to src/chapter4/imgs/hpp_chapter4-02.png diff --git a/content/part4/slides/imgs/hpp_part4-03.png b/src/chapter4/imgs/hpp_chapter4-03.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-03.png rename to src/chapter4/imgs/hpp_chapter4-03.png diff --git a/content/part4/slides/imgs/hpp_part4-04.png b/src/chapter4/imgs/hpp_chapter4-04.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-04.png rename to src/chapter4/imgs/hpp_chapter4-04.png diff --git a/content/part4/slides/imgs/hpp_part4-05.png b/src/chapter4/imgs/hpp_chapter4-05.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-05.png rename to src/chapter4/imgs/hpp_chapter4-05.png diff --git a/content/part4/slides/imgs/hpp_part4-06.png b/src/chapter4/imgs/hpp_chapter4-06.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-06.png rename to src/chapter4/imgs/hpp_chapter4-06.png diff --git a/content/part4/slides/imgs/hpp_part4-07.png b/src/chapter4/imgs/hpp_chapter4-07.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-07.png rename to src/chapter4/imgs/hpp_chapter4-07.png diff --git a/content/part4/slides/imgs/hpp_part4-08.png b/src/chapter4/imgs/hpp_chapter4-08.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-08.png rename to src/chapter4/imgs/hpp_chapter4-08.png diff --git a/content/part4/slides/imgs/hpp_part4-09.png b/src/chapter4/imgs/hpp_chapter4-09.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-09.png rename to src/chapter4/imgs/hpp_chapter4-09.png diff --git a/content/part4/slides/imgs/hpp_part4-10.png b/src/chapter4/imgs/hpp_chapter4-10.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-10.png rename to src/chapter4/imgs/hpp_chapter4-10.png diff --git a/content/part4/slides/imgs/hpp_part4-11.png b/src/chapter4/imgs/hpp_chapter4-11.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-11.png rename to src/chapter4/imgs/hpp_chapter4-11.png diff --git a/content/part4/slides/imgs/hpp_part4-12.png b/src/chapter4/imgs/hpp_chapter4-12.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-12.png rename to src/chapter4/imgs/hpp_chapter4-12.png diff --git a/content/part4/slides/imgs/hpp_part4-13.png b/src/chapter4/imgs/hpp_chapter4-13.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-13.png rename to src/chapter4/imgs/hpp_chapter4-13.png diff --git a/content/part4/slides/imgs/hpp_part4-14.png b/src/chapter4/imgs/hpp_chapter4-14.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-14.png rename to src/chapter4/imgs/hpp_chapter4-14.png diff --git a/content/part4/slides/imgs/hpp_part4-15.png b/src/chapter4/imgs/hpp_chapter4-15.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-15.png rename to src/chapter4/imgs/hpp_chapter4-15.png diff --git a/content/part4/slides/imgs/hpp_part4-16.png b/src/chapter4/imgs/hpp_chapter4-16.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-16.png rename to src/chapter4/imgs/hpp_chapter4-16.png diff --git a/content/part4/slides/imgs/hpp_part4-17.png b/src/chapter4/imgs/hpp_chapter4-17.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-17.png rename to src/chapter4/imgs/hpp_chapter4-17.png diff --git a/content/part4/slides/imgs/hpp_part4-18.png b/src/chapter4/imgs/hpp_chapter4-18.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-18.png rename to src/chapter4/imgs/hpp_chapter4-18.png diff --git a/content/part4/slides/imgs/hpp_part4-19.png b/src/chapter4/imgs/hpp_chapter4-19.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-19.png rename to src/chapter4/imgs/hpp_chapter4-19.png diff --git a/content/part4/slides/imgs/hpp_part4-20.png b/src/chapter4/imgs/hpp_chapter4-20.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-20.png rename to src/chapter4/imgs/hpp_chapter4-20.png diff --git a/content/part4/slides/imgs/hpp_part4-21.png b/src/chapter4/imgs/hpp_chapter4-21.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-21.png rename to src/chapter4/imgs/hpp_chapter4-21.png diff --git a/content/part4/slides/imgs/hpp_part4-22.png b/src/chapter4/imgs/hpp_chapter4-22.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-22.png rename to src/chapter4/imgs/hpp_chapter4-22.png diff --git a/content/part4/slides/imgs/hpp_part4-23.png b/src/chapter4/imgs/hpp_chapter4-23.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-23.png rename to src/chapter4/imgs/hpp_chapter4-23.png diff --git a/content/part4/slides/imgs/hpp_part4-24.png b/src/chapter4/imgs/hpp_chapter4-24.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-24.png rename to src/chapter4/imgs/hpp_chapter4-24.png diff --git a/content/part4/slides/imgs/hpp_part4-25.png b/src/chapter4/imgs/hpp_chapter4-25.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-25.png rename to src/chapter4/imgs/hpp_chapter4-25.png diff --git a/content/part4/slides/imgs/hpp_part4-26.png b/src/chapter4/imgs/hpp_chapter4-26.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-26.png rename to src/chapter4/imgs/hpp_chapter4-26.png diff --git a/content/part4/slides/imgs/hpp_part4-27.png b/src/chapter4/imgs/hpp_chapter4-27.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-27.png rename to src/chapter4/imgs/hpp_chapter4-27.png diff --git a/content/part4/slides/imgs/hpp_part4-28.png b/src/chapter4/imgs/hpp_chapter4-28.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-28.png rename to src/chapter4/imgs/hpp_chapter4-28.png diff --git a/content/part4/slides/imgs/hpp_part4-29.png b/src/chapter4/imgs/hpp_chapter4-29.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-29.png rename to src/chapter4/imgs/hpp_chapter4-29.png diff --git a/content/part4/slides/imgs/hpp_part4-30.png b/src/chapter4/imgs/hpp_chapter4-30.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-30.png rename to src/chapter4/imgs/hpp_chapter4-30.png diff --git a/content/part4/slides/imgs/hpp_part4-31.png b/src/chapter4/imgs/hpp_chapter4-31.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-31.png rename to src/chapter4/imgs/hpp_chapter4-31.png diff --git a/content/part4/slides/imgs/hpp_part4-32.png b/src/chapter4/imgs/hpp_chapter4-32.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-32.png rename to src/chapter4/imgs/hpp_chapter4-32.png diff --git a/content/part4/slides/imgs/hpp_part4-33.png b/src/chapter4/imgs/hpp_chapter4-33.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-33.png rename to src/chapter4/imgs/hpp_chapter4-33.png diff --git a/content/part4/slides/imgs/hpp_part4-34.png b/src/chapter4/imgs/hpp_chapter4-34.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-34.png rename to src/chapter4/imgs/hpp_chapter4-34.png diff --git a/content/part4/slides/imgs/hpp_part4-35.png b/src/chapter4/imgs/hpp_chapter4-35.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-35.png rename to src/chapter4/imgs/hpp_chapter4-35.png diff --git a/content/part4/slides/imgs/hpp_part4-36.png b/src/chapter4/imgs/hpp_chapter4-36.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-36.png rename to src/chapter4/imgs/hpp_chapter4-36.png diff --git a/content/part4/slides/imgs/hpp_part4-37.png b/src/chapter4/imgs/hpp_chapter4-37.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-37.png rename to src/chapter4/imgs/hpp_chapter4-37.png diff --git a/content/part4/slides/imgs/hpp_part4-38.png b/src/chapter4/imgs/hpp_chapter4-38.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-38.png rename to src/chapter4/imgs/hpp_chapter4-38.png diff --git a/content/part4/slides/imgs/hpp_part4-39.png b/src/chapter4/imgs/hpp_chapter4-39.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-39.png rename to src/chapter4/imgs/hpp_chapter4-39.png diff --git a/content/part4/slides/imgs/hpp_part4-40.png b/src/chapter4/imgs/hpp_chapter4-40.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-40.png rename to src/chapter4/imgs/hpp_chapter4-40.png diff --git a/content/part4/slides/imgs/hpp_part4-41.png b/src/chapter4/imgs/hpp_chapter4-41.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-41.png rename to src/chapter4/imgs/hpp_chapter4-41.png diff --git a/content/part4/slides/imgs/hpp_part4-42.png b/src/chapter4/imgs/hpp_chapter4-42.png similarity index 100% rename from content/part4/slides/imgs/hpp_part4-42.png rename to src/chapter4/imgs/hpp_chapter4-42.png diff --git a/content/part4/tasks/namespaces.md b/src/chapter4/namespaces.md similarity index 72% rename from content/part4/tasks/namespaces.md rename to src/chapter4/namespaces.md index 8654814..f885d78 100644 --- a/content/part4/tasks/namespaces.md +++ b/src/chapter4/namespaces.md @@ -1,19 +1,5 @@ # Namespaces -## Contents - -- [Namespaces](#namespaces) - - [Contents](#contents) - - [Task 2](#task-2) - - [Task 2.1 : Namespaces](#task-21--namespaces) - - [Task 2.2 : Duplicate Namespaces](#task-22--duplicate-namespaces) - - [Task 2.3 : Nested Namespaces](#task-23--nested-namespaces) - - [Links](#links) - -## Task 2 - -### Task 2.1 : Namespaces - Namespaces create separation of symbols and names in C++. This allows for types, functions and variables to have the same name without causing collisions and ambiguity. We have already been using a namespace throughout this series, this being the `std` namespace. Namespaces a named scopes whose members can be accessed using the scope resolution operator `::`. To create a namespace you use the `namespace` keyword followed by the namespace name and a new scope. To use a namespace without having to go through scope resolution you can declare a namespaces use by `using namespace /* name */`. > Note: Using `::` with no name looks in the global namespace eg. `::a`. @@ -44,9 +30,9 @@ auto main() -> int [Example](https://www.godbolt.org/z/9oon3r944) -[Namespaces : cppreference](https://en.cppreference.com/w/cpp/language/namespace) +[Namespaces](https://en.cppreference.com/w/cpp/language/namespace) -### Task 2.2 : Duplicate Namespaces +## Duplicate Namespaces Two namespaces with the same name will logically be merged, members and symbols from both can be looked up using the same namespace name given both headers containing the namespace symbols is available to be searched. This is how the `std` namespace can have all its components across different headers but be looked up using `std::`. @@ -78,9 +64,9 @@ auto main() -> int [Example](https://www.godbolt.org/z/r9PPxbYh5) -### Task 2.3 : Nested Namespaces +## Nested Namespaces -Namespaces can also be declared to be nested. We saw this in the previous set of tasks with the `std::placeholders` namespace. To access a nested namespace you use a double scope resolution operator `::`. +Namespaces can also be declared to be nested. We saw this in the previous set of sections with the `std::placeholders` namespace. To access a nested namespace you use a double scope resolution operator `::`. ```cxx #include @@ -109,10 +95,3 @@ auto main() -> int ``` [Example](https://www.godbolt.org/z/afj6eEYe7) - -## Links - -- [Previous Page : Advanced Functions](/content/part4/tasks/advfunc.md) -- [Next Page : Enumerations](/content/part4/tasks/enums.md) -- [Content](/content/README.md) -- [HOME](/README.md) diff --git a/src/chapter4/slides4.md b/src/chapter4/slides4.md new file mode 100644 index 0000000..9f8f4a2 --- /dev/null +++ b/src/chapter4/slides4.md @@ -0,0 +1,44 @@ +# Slides + +![Slides 01](./imgs/hpp_chapter4-01.png) +![Slides 02](./imgs/hpp_chapter4-02.png) +![Slides 03](./imgs/hpp_chapter4-03.png) +![Slides 04](./imgs/hpp_chapter4-04.png) +![Slides 05](./imgs/hpp_chapter4-05.png) +![Slides 06](./imgs/hpp_chapter4-06.png) +![Slides 07](./imgs/hpp_chapter4-07.png) +![Slides 08](./imgs/hpp_chapter4-08.png) +![Slides 09](./imgs/hpp_chapter4-09.png) +![Slides 10](./imgs/hpp_chapter4-10.png) +![Slides 11](./imgs/hpp_chapter4-11.png) +![Slides 12](./imgs/hpp_chapter4-12.png) +![Slides 13](./imgs/hpp_chapter4-13.png) +![Slides 14](./imgs/hpp_chapter4-14.png) +![Slides 15](./imgs/hpp_chapter4-15.png) +![Slides 16](./imgs/hpp_chapter4-16.png) +![Slides 17](./imgs/hpp_chapter4-17.png) +![Slides 18](./imgs/hpp_chapter4-18.png) +![Slides 19](./imgs/hpp_chapter4-19.png) +![Slides 20](./imgs/hpp_chapter4-20.png) +![Slides 21](./imgs/hpp_chapter4-21.png) +![Slides 22](./imgs/hpp_chapter4-22.png) +![Slides 23](./imgs/hpp_chapter4-23.png) +![Slides 24](./imgs/hpp_chapter4-24.png) +![Slides 25](./imgs/hpp_chapter4-25.png) +![Slides 26](./imgs/hpp_chapter4-26.png) +![Slides 27](./imgs/hpp_chapter4-27.png) +![Slides 28](./imgs/hpp_chapter4-28.png) +![Slides 29](./imgs/hpp_chapter4-29.png) +![Slides 30](./imgs/hpp_chapter4-30.png) +![Slides 31](./imgs/hpp_chapter4-31.png) +![Slides 32](./imgs/hpp_chapter4-32.png) +![Slides 33](./imgs/hpp_chapter4-33.png) +![Slides 34](./imgs/hpp_chapter4-34.png) +![Slides 35](./imgs/hpp_chapter4-35.png) +![Slides 36](./imgs/hpp_chapter4-36.png) +![Slides 37](./imgs/hpp_chapter4-37.png) +![Slides 38](./imgs/hpp_chapter4-38.png) +![Slides 39](./imgs/hpp_chapter4-39.png) +![Slides 40](./imgs/hpp_chapter4-40.png) +![Slides 41](./imgs/hpp_chapter4-41.png) +![Slides 42](./imgs/hpp_chapter4-42.png) diff --git a/src/chapter4/structs.md b/src/chapter4/structs.md new file mode 100644 index 0000000..ea904a6 --- /dev/null +++ b/src/chapter4/structs.md @@ -0,0 +1,61 @@ +# Structures + +Structures (structs) are fundamental to developing with C++. They allow for creating custom types that can have member variables, and member functions (methods). They allow for packing any amalgamation of data into a single type. Structures are created using the `struct` keyword. To access the members and methods of a struct the member access operator `.` is used. For pointers to struct types, the pointer member access operator `->` is used. + +> Note: The definition of a structure must have an `;` after the last brace. + +```cxx +#include +#include + +struct PairInt +{ + int first; + int second; + + /// Adds members of two `PairInt` + constexpr auto + add(const PairInt& o) + const noexcept + -> PairInt + { return PairInt{first + o.first, second + o.second}; } + + /// Overload `+~ cleaner `PairInt::add` call + friend constexpr auto + operator+ (const PairInt& x, const PairInt& y) + noexcept + -> PairInt + { return x.add(y); } + + /// Overload `<<` for printing + friend auto + operator<< (std::ostream& os, const PairInt& v) + -> std::ostream& + { + os << "(.first: " << v.first << ", .second: " << v.second << ")"; + return os; + } +}; + +auto main() -> int +{ + auto a = PairInt{5, 7}; + auto b = PairInt{.first = 2, .second = 9}; ///< Named aggregate initialisation + auto p = std::addressof(b); ///< Pointer to struct type + + std::cout << "a = " << a << std::endl; ///< `PairInt` works with `std::cout` + std::cout << "b = " << b << std::endl; + + std::cout << "a + b = " << a + b << std::endl; ///< Call to overloaded `+` + std::cout << "a + c = " << a + *p << std::endl; ///< Pointer to structs works like regular pointers + + std::cout << "a.add(b) = " << a.add(b) << std::endl; ///< Method access + std::cout << "p->add(a) = " << p->add(a) << std::endl; ///< Pointer member access + + return 0; +} +``` + +[Example](https://www.godbolt.org/z/6MbYMGGMz) + +> Note: Ignore the `friend` keyword for now. diff --git a/src/chapter4/task1.md b/src/chapter4/task1.md new file mode 100644 index 0000000..98353ed --- /dev/null +++ b/src/chapter4/task1.md @@ -0,0 +1,34 @@ +# Task 1 + +Having learnt a massive chunk of C++ now I want you to try and right some code for yourself. Your section is to create a triple struct, ie. like a 3D point but semantically more general. You must demonstrate and run all of the properties of the struct. The program should be called `triple.cxx` (or `triple.main.cxx` if using bpt) + +## Requirements + +- Must have three members of the same type (either `int`, `float` or `double`) +- A way to add two points +- A way to subtract two points +- A way to multiply a point by a scalar (of the same underlying type) +- A way to divide a point by a scalar (of the same underlying type) +- A way to be print a formatted output using `std::cout` + +### Bonus + +- A way to be created using input from `std::cin` +- Create a 'triple' structure for the other underlying types. + +## Submitting + +You can use Godbolt or bpt to build and test your struct. Once you have created your implementation: + +- Clone this repo using `git clone https://github.com/MonashDeepNeuron/HPP.git`. +- Create a new branch using `git checkout -b triple/`. +- Create a folder in the `/submissions` directory with your name. +- Create a folder with the name of this task. +- Copy your mini project into this directory (bpt setup, cmake scripts etc.) with a `README.md` or comment in the code on how to run the program (verify it still works). There is a sample header file in `/templates` that you can use. +- Go to and click 'New pull request'. +- Change the branches in the drop down so that your branch is going into `main` and `Create new pull request. +- Give the pull request a title and briefly describe what you were able to implement and any struggles you had. +- On the right side-panel, under the 'Assignees' section, click the cog and assign me. +- Click 'Create pull request' and I'll take it from there. + +> Note: If you created a GodBolt instance, put the link in a comment at the top of the file (under your copy comments). This is generated by clicking the `share` button in the top-right-most corner of the webpage and clicking the 'short link' option. diff --git a/content/part4/tasks/unions.md b/src/chapter4/unions.md similarity index 79% rename from content/part4/tasks/unions.md rename to src/chapter4/unions.md index 65e43cc..bdfc817 100644 --- a/content/part4/tasks/unions.md +++ b/src/chapter4/unions.md @@ -1,21 +1,5 @@ # Unions -## Contents - -- [Unions](#unions) - - [Contents](#contents) - - [Task 4](#task-4) - - [Task 4.1 : Unions](#task-41--unions) - - [Task 4.2 : Limitations](#task-42--limitations) - - [Task 4.3 : Type Safe Algebraic Data Types](#task-43--type-safe-algebraic-data-types) - - [Task 4.3.1 : Option](#task-431--option) - - [Task 4.3.2 : Variant](#task-432--variant) - - [Links](#links) - -## Task 4 - -### Task 4.1 : Unions - Unions are a special kind of type known as an algebraic data type. This means the type of a union object can vary between a small list of possible types. This allows for a single type to be one of many possible types that can change throughout the lifetime of the program. The members of a union occupy the same memory space, thus the size of a union is the size of the largest possible member. Constructing a union object will always need to construct the first variant. Accessing the non-activate member is UB. ```cxx @@ -45,14 +29,14 @@ auto main() -> int [Example](https://www.godbolt.org/z/zGeTs8ozn) -[Unions : cppreference](https://en.cppreference.com/w/cpp/language/union) +[Unions](https://en.cppreference.com/w/cpp/language/union) -### Task 4.2 : Limitations +## Limitations Unions are quite powerful but have a few limitations. - There is no default mechanism for inspecting the current variant of a union. -- They can have member functions including constructors and destructors but cannot have virtual functions (more in [Part 5](/content/part5/README.md)). +- They can have member functions including constructors and destructors but cannot have virtual functions (more on this in chapter 5). - They cannot have base classes nor can be used as a base class. - They cannot have non-static members of reference types. - If any variant types have a non-trivial special member function it is deleted for the union and must be declared explicitly for the union type. @@ -88,11 +72,11 @@ int main() [Example](https://www.godbolt.org/z/rqPz5hK45) -### Task 4.3 : Type Safe Algebraic Data Types +## Type Safe Algebraic Data Types While unions are powerful, they are very error prone and can lead to hard to diagnose bugs. Instead, in C++17 type-safe algebraic types that more intuitive to use and far safer. -#### Task 4.3.1 : Option +### Options One of the most common uses of algebraic data types is `std::optional` which can represent a type that may _optionally_ contain some value or non at all. `std::optional` is often used as the return type if a function that might expectedly fail. `std::optional` can contain any type or has the type of `std::nullopt`. @@ -132,9 +116,9 @@ auto main() -> int [Example](https://www.godbolt.org/z/aGvnrYPzn) -[`std::optional` : cppreference](https://en.cppreference.com/w/cpp/utility/optional) +[`std::optional`](https://en.cppreference.com/w/cpp/utility/optional) -#### Task 4.3.2 : Variant +### Variants The is also a more generic algebraic data type in C++ called `std::variant` which is implemented as a tagged union; that is, you are able to inspect which type is currently active, validate the state of the variant and perform a simply form of pattern matching. Empty variants can be simulated by using the `std::monospace` type variant. @@ -168,13 +152,5 @@ auto main() -> int [Example](https://www.godbolt.org/z/fzMKbjWW3) -[`std::variant` : cppreference](https://en.cppreference.com/w/cpp/utility/variant) - -[`std::visit()` : cppreference](https://en.cppreference.com/w/cpp/utility/variant/visit) - -## Links - -- [Previous Page : Enumerations](/content/part4/tasks/enums.md) -- [Next Page : Unions](/content/part4/tasks/structs.md) -- [Content](/content/README.md) -- [HOME](/README.md) +- [`std::variant`](https://en.cppreference.com/w/cpp/utility/variant) +- [`std::visit()`](https://en.cppreference.com/w/cpp/utility/variant/visit) diff --git a/src/chapter5/README.md b/src/chapter5/README.md new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/chapter5/README.md @@ -0,0 +1 @@ + diff --git a/src/chapter5/chapter5.md b/src/chapter5/chapter5.md new file mode 100644 index 0000000..011a9a0 --- /dev/null +++ b/src/chapter5/chapter5.md @@ -0,0 +1,3 @@ +# Generic Programming + +Throughout this chapter you will discover C++ immensely customizable type system. How you can utilise structures and classes to create your own types from abstract base classes, data structures. You will also learn briefly about C++ Object Orientated facilities and how to utilise dynamic and static inheritance. You will also be introduced to generic programming through templates and metaprogramming. Finally you will learn about constraining your programs and enforcing requirements using C++ new concept faculties. diff --git a/content/part5/tasks/classes.md b/src/chapter5/classes.md similarity index 82% rename from content/part5/tasks/classes.md rename to src/chapter5/classes.md index 4c2e842..98e36f9 100644 --- a/content/part5/tasks/classes.md +++ b/src/chapter5/classes.md @@ -1,43 +1,10 @@ # Classes -## Contents - -- [Classes](#classes) - - [Contents](#contents) - - [Task 1](#task-1) - - [Task 1.1 : What Is a Class?](#task-11--what-is-a-class) - - [Task 1.2 : Defining a Class](#task-12--defining-a-class) - - [Task 1.2.1 : Member Access](#task-121--member-access) - - [Task 1.2.1.1 : General Access](#task-1211--general-access) - - [Task 1.2.1.2 : Access in Derived Classes](#task-1212--access-in-derived-classes) - - [Task 1.3 : Constructors and Destructors](#task-13--constructors-and-destructors) - - [Task 1.3.1 : Explicit Constructors](#task-131--explicit-constructors) - - [Task 1.3.1.1 : Member Initialisers Lists](#task-1311--member-initialisers-lists) - - [Task 1.3.2 : Default Constructor](#task-132--default-constructor) - - [Task 1.3.3 : Copy Constructors](#task-133--copy-constructors) - - [Task 1.3.4 : Move Constructors](#task-134--move-constructors) - - [Task 1.3.5 : Destructors](#task-135--destructors) - - [Task 1.3.6 : RAII](#task-136--raii) - - [Task 1.3.7 : Letting the compiler do the work for you](#task-137--letting-the-compiler-do-the-work-for-you) - - [Task 1.4 : Members \& Methods](#task-14--members--methods) - - [Task 1.4.1 : Const and Ref Qualifiers](#task-141--const-and-ref-qualifiers) - - [Task 1.4.2 : This](#task-142--this) - - [Task 1.4.3 : Operator Overloading](#task-143--operator-overloading) - - [Task 1.4.3.1 : Assignment Overloads](#task-1431--assignment-overloads) - - [Task 1.4.4 : Friend Methods](#task-144--friend-methods) - - [Task 1.5 : Dynamic Inheritance](#task-15--dynamic-inheritance) - - [Task 1.5.1 : Virtual Methods](#task-151--virtual-methods) - - [Task 1.5.2 : Virtual Inheritance](#task-152--virtual-inheritance) - - [Task 1.5.3 : Abstract Classes](#task-153--abstract-classes) - - [Links](#links) - -## Task 1 - -### Task 1.1 : What Is a Class? - -What is a class? Classes are the same as types. They allow for defining a set of valid operations on a particular configuration or amalgamation of data. In C++ there are two category of types, primitives and classes. Primitives are the basic types your were first introduced to in Part 2. Many other programming languages do not primitives because the language undergoes many more transformations before becoming machine code. As an example, `int` in Python is an object. It meets all the basic requirements of an object same as any other object in Python. This is not the case in C++. `int` in C++ is directly lowered (translated) into a assembly or machine type. You can a can access the bits that represent the `int`, even mutate them. They have a fixed width in memory (although varying from platform-to-platform) and cannot have their interfaces changes or adapted. Classes are different, they are much like object from Python (although, due to C++'s zero overhead principle, you only pay for what you ask for). Class are custom types that anyone can define and even modify through hierarchy structures and inheritance. - -### Task 1.2 : Defining a Class +## What Is a Class? + +What is a class? Classes are the same as types. They allow for defining a set of valid operations on a particular configuration or amalgamation of data. In C++ there are two category of types, primitives and classes. Primitives are the basic types your were first introduced to in Chapter 2. Many other programming languages do not primitives because the language undergoes many more transformations before becoming machine code. As an example, `int` in Python is an object. It meets all the basic requirements of an object same as any other object in Python. This is not the case in C++. `int` in C++ is directly lowered (translated) into a assembly or machine type. You can a can access the bits that represent the `int`, even mutate them. They have a fixed width in memory (although varying from platform-to-platform) and cannot have their interfaces changes or adapted. Classes are different, they are much like object from Python (although, due to C++'s zero overhead principle, you only pay for what you ask for). Class are custom types that anyone can define and even modify through hierarchy structures and inheritance. + +## Defining a Class A class is defined identically to a structure. In fact, to C++ they are identical. You can use either keyword to create a class type. Typically however, `struct` is reserved for simple structures while `class` are use for more complex types by convention. There is one distinction between the two declarations, `class` will make all class members (methods and variables) private by default while `struct` will make them public by default. @@ -64,15 +31,15 @@ auto main() -> int [Example](https://www.godbolt.org/z/MrorPKKxW) -#### Task 1.2.1 : Member Access +### Member Access Classes allow for you to specify the access rights of its members. There are three member access categories. Each allows for a different level of access permissions from both direct users of the class and the children (derived) of the class. > Note: The term 'Member' means any method (function) or variable owned by a class, structure or type. -##### Task 1.2.1.1 : General Access +#### General Access -When defining a class, you can specify parts of its definition to be either `private`, `protected` or `public`. This is done by putting an accessor label (with the keyword being one of the previously mentioned accessor categories with a `:` suffix) in a region of the classes body. All declared members following the label will adopt the accessor policy. You can reuse access specifiers as much as you want. +When defining a class, you can specify chapters of its definition to be either `private`, `protected` or `public`. This is done by putting an accessor label (with the keyword being one of the previously mentioned accessor categories with a `:` suffix) in a region of the classes body. All declared members following the label will adopt the accessor policy. You can reuse access specifiers as much as you want. Here are the rules for the different accessor policies. @@ -104,7 +71,7 @@ auto main() -> int [Example](https://www.godbolt.org/z/1hWjrhee7) -##### Task 1.2.1.2 : Access in Derived Classes +#### Access in Derived Classes When deriving from another classes (more on inheritance [here](#task-16--dynamic-inheritance)), you can specify the access rights of the parent classes members through the base class. @@ -148,17 +115,17 @@ auto main() -> int > Note: Classes can access their own members regardless of the access policy even if it is a different instance. -### Task 1.3 : Constructors and Destructors +## Constructors and Destructors So far we haven't seen much difference from classes than just using them as aggregate structures. One of the unique benefits of classes in C++ is the ability to explicitly define and control how structures are created and destroyed. This gives you powerful control over the lifetime of a type and how its resources are managed at the definition stage removing the need for manual management at runtime. This is done through constructors and destructors. These are special members (functions) with the same name as the class. A class can have any number of constructors (following the normal function overloading rules) but can only have one destructor. > Note: Creation or construction of a type refers to the explicit instantiation of an object with a particular class type. -#### Task 1.3.1 : Explicit Constructors +### Explicit Constructors The most useful kind of constructors for defining custom creation of a class are explicit constructors. These constructors take explicitly specified arguments, usually used to initialise member variables with a particular value. Explicit constructors are often marked with the `explicit` keyword in their function signature. Means the constructor must be explicitly called, ie. passed the correct types. -Throughout this part we are going to build up the `Point` class. Lets start by making it possible to define the point from two `int`. I've defined the explicit constructor for initialising the members `Point::x` and `Point::y` as well as temporary getters/setters. +Throughout this chapter we are going to build up the `Point` class. Lets start by making it possible to define the point from two `int`. I've defined the explicit constructor for initialising the members `Point::x` and `Point::y` as well as temporary getters/setters. ```cxx #include @@ -202,7 +169,7 @@ auto main() -> int > Note: Even though it is taught often in; OOP centric or even OOP enabled languages, to define 'getters' and 'setters' for member variables. This is bad practice as it often leads to users of types and classes manually mutating the data themselves instead of defining access patterns and stateful transitions through methods or algorithms. If you must use 'getter' or 'setter' access patterns then you member variables should be publicly accessible. -##### Task 1.3.1.1 : Member Initialisers Lists +#### Member Initialisers Lists You may notice the comma separated 'list' under the constructors declaration. This is called an member initialiser list. It is used to initialise the members of a class from the arguments of the called constructor or from other members of the class. Member initialiser lists are specified between a constructors declaration and its body. Members are initialised in the following order regardless of the order specified by the member initialiser list. @@ -213,7 +180,7 @@ You may notice the comma separated 'list' under the constructors declaration. Th [Constructors and member initializer lists](https://en.cppreference.com/w/cpp/language/constructor) -#### Task 1.3.2 : Default Constructor +### Default Constructor Sometimes, you don't know the state a type should by in when it is being initialised. In these cases it is useful to have a fallback state. To achieve this we use a default constructor. This will usually take no parameters. @@ -265,7 +232,7 @@ auto main() -> int [Example](https://www.godbolt.org/z/Wrne3b1nd) -#### Task 1.3.3 : Copy Constructors +### Copy Constructors Constructors allow for defining custom semantics for common meta-like operations. For example, if you define a constructor that takes a constant reference to another `Point`, the only thing to can do is copy the data from the other class. This constructor pattern is called Copy Semantics. We can also overload the `=` operator so we can perform copy assignments. Let's define a copy constructor for `Point`. @@ -328,7 +295,7 @@ auto main() -> int [Example](https://www.godbolt.org/z/YYhf9baW3) -#### Task 1.3.4 : Move Constructors +### Move Constructors While our `Point` class has gotten pretty sophisticated there is one file base constructor we need in order to complete its baseline functionality. In C++, all data has an owner. We can get pointers and references to data so that other can borrow the data. We can even copy data so that a new owner can have the same values as another however, there is one missing piece. The transfer of ownership, what if we want to give ownership of some data to a new owner. We see this principle with rvalue references. When we initialise an `int` with a literal; say `1`, we are transferring ownership of the data associated with the literal `1` to the named variable. In C++ this is called a move. Moves occur when a constructor (or assignment) of a type is called on a rvalue reference which invokes the class's move constructor. Moves will rip the data of a type out of it and transfer the ownership of the data and resource to the new object, leaving the old owner in a default initialised state (usually). Moves can be induced using the `std::move()` function from the `` header. @@ -398,10 +365,10 @@ auto main() -> int [Example](https://www.godbolt.org/z/TfGEWW7qM) -- [`std::move()` : cppreference](https://en.cppreference.com/w/cpp/utility/move) -- [`` : cppreference](https://en.cppreference.com/w/cpp/header/utility) +- [`std::move()`](https://en.cppreference.com/w/cpp/utility/move) +- [``](https://en.cppreference.com/w/cpp/header/utility) -#### Task 1.3.5 : Destructors +### Destructors So far we have built a pretty sophisticated type of our own with many ways to construct it however, what happens when it gets destroyed. This will invoke the classes destructor. The destructor is declared the same as the default constructor however, it is prefixed with a tilde ('~') in the constructors name. Destructors are used to properly free resources from the type. Resources include things such as dynamic memory, device handles, web sockets etc. For our `Point` class our destructor is really a no-op as all of its members are trivial to destruct and will automatically occur. A trivial constructor will look like this. @@ -413,7 +380,7 @@ constexpr ~Point() noexcept {} /// ... Members variables ``` -#### Task 1.3.6 : RAII +### RAII So why have all these means of specifying creation and deletion of objects? One of the core faults of many programs in C is the requirement to explicitly create and destroy resources, even of structures. One of the first things introduced to C++ where constructors and destructors so that the creation of object of a type and its subsequent destruction were tied to the type itself anf could be implicitly handled by the compiler. It also allowed for classes to acquire all resources they needed at the time of construction. This principle is known as 'Resource Acquisition Is Initialisation' or RAII. This means that the lifetime of any resource owned by a class is tied to the lifetime of an instance of that class. @@ -423,7 +390,7 @@ This also means that if a constructor should fail (by throwing an exception), an Classes with member functions named `open()`/`close()`, `lock()`/`unlock()`, or `init()`/`copyFrom()`/`destroy()` (or similar, carrying the same semantics meaning) are typical examples of non-RAII classes. -#### Task 1.3.7 : Letting the compiler do the work for you +### Letting the compiler do the work for you Because our `Point` class is superficial and almost trivial, it can be annoying to define all the constructors and when the resources being initialised are trivial. It would be nice to not have to specify every constructor. What if we could make the compiler generate the constructors for us? Well, we can. By just declaring the constructors signature with no member initialiser list or body, we can use the `= default` suffix specifier indicating for the compiler to generate the constructor for us. We will do this for the default constructor. @@ -447,7 +414,7 @@ constexpr Point(const Point& p) noexcept = delete; ///< Point objects cannot be /// ... Point details ``` -### Task 1.4 : Members & Methods +## Members & Methods While constructors and destructors ensure resource and lifetime safety for classes they are only half the story. Member functions or methods allow us to define operations that we want to on or using the data help by a class. They allow for stateful modification of data while ensuring type safety. To define a methods for a class you simply define a function within the classes body. Normal rules for naming and overloading apply however methods are able to access all members (function and variable) of the immediate class and any `protected` and `public` members of parent classes. In our `Point` class we already have to members; `Point::X()` and `Point::Y()` which return `int&` of the members `Point::x` and `Point::y` respectively. @@ -465,7 +432,7 @@ Y() noexcept -> int& /// ... Point details ``` -#### Task 1.4.1 : Const and Ref Qualifiers +### Const and Reference Qualifiers Members can restrict and customize their usage on particular instances of its class through the class objects value category and cv-qualifiers. By postfixing the symbols `const`, `&` and `&&` to a member function we can restrict the usage of that member function to instances of the class object to being a constant object and/or having either value category of lvalue or rvalue respectively. @@ -529,7 +496,7 @@ auto main() -> int [Example](https://www.godbolt.org/z/TGoh9Yrjc) -#### Task 1.4.2 : This +### This It is useful for a class to be self aware and have some means of referring to itself, for example when working with another instance of the same class in a method it can be ambiguous when you are using members from your instance and from the other objects instance. Classes in C++ implicitly have a member called `this`. `this` is a pointer to the current instance of a class in memory. Using `this` allows for qualified lookup of names for the current object. Like any other pointer it can be dereferenced so that it can be used as a reference or have its members accessed using `this->`. `this` can only be used in methods and has the type of the class type the method was called with including cv-qualifications. @@ -549,7 +516,7 @@ Y() noexcept -> int& [The `this` pointer](https://en.cppreference.com/w/cpp/language/this) -#### Task 1.4.3 : Operator Overloading +### Operator Overloading Much like how you can overload operators as free functions, classes can define there own overloads for operators. operator overloads for classes are defined just like regular methods for classes however, the first argument is implicitly `this` object. @@ -579,7 +546,7 @@ noexcept -> bool [Example](https://www.godbolt.org/z/TG9WW74bo) -#### Task 1.4.3.1 : Assignment Overloads +### Assignment Overloads One of the most useful operator overloads we can define for a class is an overload for `=`; two in fact, one for each of copy semantics and move semantics. This methods work identical to their constructor counterparts except they must have an explicit return type and value, cannot have a member initializer list and must only be defined for a single argument. @@ -617,12 +584,14 @@ operator= (Point&& p) noexcept -> Point& [Example](https://www.godbolt.org/z/xvcf57xcT) -#### Task 1.4.4 : Friend Methods +### Friend Methods Sometimes it is useful to access the internal `private` and `protected` data of a class without having to make it exposed to everyone. This is were friends come in handy. The `friend` keyword can be attached to nested class forward specifications and functions. This makes free functions able to access and modify the internal data of a class. Friendship is most useful for creating relationships between hierarchal unrelated classes interoperate with each other such as in certain operator overloads. -- > Note: Friendship is not transitive - A friend of your friend is not your friend -- > Note: Friendship is not inherited - Your friends children are not your friends +> #### Notes: +> +> - Friendship is not transitive - A friend of your friend is not your friend +> - Friendship is not inherited - Your friends children are not your friends Here I've defined an overload for `<<` as a `friend` function. This is because `std::ostream` is an unrelated type to `Point` but we want to be able to access the non-public members of a `Point` object. With this, we can delete the `Point::X()` and `Point::Y()` methods. @@ -642,13 +611,13 @@ operator<< (std::ostream& os, const Point& p) [Example](https://www.godbolt.org/z/MxacvscTY) -[Version 1 of `Point`](/content/part5/examples/point-v1.hxx) +[Version 1 of `Point`](/content/chapter5/examples/point-v1.hxx) -### Task 1.5 : Dynamic Inheritance +## Dynamic Inheritance You are able to inherit the members of another class into your own class. This allows for many OOP concepts to be applied such as inheritance and polymorphism. Base classes are specified after the derived classes name specification. All classes can be inherited from (unless declared as `final`). -> Note: OOP principles are not the focus of this series and is only covered lightly. C++ is by no means a Object Oriented language (despite similar naming). Rather C++ supports OOP principles in order to benefit from these principles however, many parts of the language (Standard Library) will utilise these features and principles in a far more general sense. +> Note: OOP principles are not the focus of this series and is only covered lightly. C++ is by no means a Object Oriented language (despite similar naming). Rather C++ supports OOP principles in order to benefit from these principles however, many chapters of the language (Standard Library) will utilise these features and principles in a far more general sense. ```cxx #include @@ -686,7 +655,7 @@ auto main() -> int [Example](https://www.godbolt.org/z/xvMdeq3n5) -#### Task 1.5.1 : Virtual Methods +### Virtual Methods A method can be marked as virtual with the `virtual` specifier. This means that classes that derive this method can override them by specifying them as overridden with the `override` keyword in the derived class. @@ -724,10 +693,10 @@ auto main() -> int [Example](https://www.godbolt.org/z/zrMs4EhKn) -- [`virtual` function specifier : cppreference](https://en.cppreference.com/w/cpp/language/virtual) -- [`override` specifier : cppreference](https://en.cppreference.com/w/cpp/language/override) +- [`virtual` function specifier](https://en.cppreference.com/w/cpp/language/virtual) +- [`override` specifier](https://en.cppreference.com/w/cpp/language/override) -#### Task 1.5.2 : Virtual Inheritance +### Virtual Inheritance Classes can also inherit base classes virtually. For each base class that is specified as virtual, the most derived object will contain only one sub-object of that `virtual` base class, even if the class appears many times in the inheritance hierarchy (as long as it is inherited `virtual` every time)*. @@ -765,11 +734,11 @@ auto main() -> int [Example](https://www.godbolt.org/z/qT5v7aEPx) -[Derived Classes : cppreference](https://en.cppreference.com/w/cpp/language/derived_class) +[Derived Classes](https://en.cppreference.com/w/cpp/language/derived_class) > *Note: This is an adaptation (paraphrase) from [cppreference](https://en.cppreference.com/w/cpp/language/derived_class#:~:text=initializer%20list.-,Virtual%20base%20classes,-For%20each%20distinct) -#### Task 1.5.3 : Abstract Classes +### Abstract Classes Abstract classes are classes which define or inherit at least one 'pure' `virtual` methods. Pure `virtual` methods are `virtual` methods whose declaration are suffixed by the `= 0;` pure-specifier expression. Abstract classes cannot be instantiated but can be pointer to or referred to. @@ -808,11 +777,4 @@ auto main() -> int [Example](https://www.godbolt.org/z/axj9Tbr4v) -[Abstract class : cppreference](https://en.cppreference.com/w/cpp/language/abstract_class) - -## Links - -- [Previous Page : Part 5](/content/part5/README.md) -- [Next Page : Templates](/content/part5/tasks/templates.md) -- [Content](/content/README.md) -- [HOME](/README.md) +[Abstract class](https://en.cppreference.com/w/cpp/language/abstract_class) diff --git a/content/part5/tasks/concepts.md b/src/chapter5/concepts.md similarity index 80% rename from content/part5/tasks/concepts.md rename to src/chapter5/concepts.md index ebb2d66..eab2a1a 100644 --- a/content/part5/tasks/concepts.md +++ b/src/chapter5/concepts.md @@ -1,28 +1,8 @@ # Concepts -## Contents - -- [Concepts](#concepts) - - [Contents](#contents) - - [Task 4](#task-4) - - [Task 4.1 : Limitations to templates](#task-41--limitations-to-templates) - - [Task 4.2 : What is a Concept?](#task-42--what-is-a-concept) - - [Task 4.3 : Constrained templates](#task-43--constrained-templates) - - [Task 4.4 : Requires expressions](#task-44--requires-expressions) - - [Task 4.4.1 : Requires expression](#task-441--requires-expression) - - [Task 4.4.2 : Compound requirements](#task-442--compound-requirements) - - [Task 4.5 : Constrained variables](#task-45--constrained-variables) - - [Assignment 2](#assignment-2) - - [Requirements](#requirements) - - [Bonus](#bonus) - - [Submitting](#submitting) - - [Links](#links) - -## Task 4 - -### Task 4.1 : Limitations to templates - -Templates are extremely powerful allow us to create reusable and extendible code however there is a caveat to this. Take for example our `Point` class from Tasks 1-2. `Point` just takes a single type `T`. This can be absolutely any type. This can become a problem though later for the user. Say we have a `Point`. This will cause an error for the user of our `Point` class if they try to take two `Point` because `-` is not supported by `std::string`. This can be a major problem as the error produced can be ambiguous to the user and require looking at the source code in depth to diagnose. +## Limitations to templates + +Templates are extremely powerful allow us to create reusable and extendible code however there is a caveat to this. Take for example our `Point` class from Sections 1-2. `Point` just takes a single type `T`. This can be absolutely any type. This can become a problem though later for the user. Say we have a `Point`. This will cause an error for the user of our `Point` class if they try to take two `Point` because `-` is not supported by `std::string`. This can be a major problem as the error produced can be ambiguous to the user and require looking at the source code in depth to diagnose. ```cxx /// ... Point implementation @@ -177,7 +157,7 @@ Execution build compiler returned: 1 To address this C++20 introduced concepts. A mechanism for imposing constraints on types. -### Task 4.2 : What is a Concept? +## What is a Concept? A concepts is a set of conditions and requirements imposed on a type that is checked at compile time and evaluates as a Boolean. Before C++20, template metaprogramming and SFINAE where used to statically impose constraints on types but they had limitations and were highly verbose. Concepts allow us to define syntactic constraints on a template type and then impose those constraints on other types. Concepts are introduced using a template declaration followed by a concept declaration (similar to a class declaration but replace the keyword `class` with `concept`). Concepts can be composed of other concepts using `||` and `&&` (holding similar semantics to there Boolean equivalents). It is difficult to create meaningful concepts as one, they are very new to both C++ but also programming in general, instead try and use the concepts defined by the standard library; from the `` header, first and impose them on a case by case basis using the techniques we are going to learn below. @@ -214,10 +194,10 @@ auto main() -> int [Example](https://www.godbolt.org/z/Px75v8ssf) -- [`` : cppreference](https://en.cppreference.com/w/cpp/concepts) -- [Constraints and concepts : cppreference](https://en.cppreference.com/w/cpp/language/constraints) +- [``](https://en.cppreference.com/w/cpp/concepts) +- [Constraints and concepts](https://en.cppreference.com/w/cpp/language/constraints) -### Task 4.3 : Constrained templates +## Constrained templates Concepts are easiest to use when constraining templates type parameters. Instead of the using the keyword `typename` when can instead use a concept. This will impose the rules on the template type at the point of instantiation. We can see this best with our `Point` class. Being that a 'point' is a numerical value in a field; say coordinates on a cartesian plane we might want to restrict the type parameter `T` of `Point` to a number type. C++'s concepts library already has a concept for this called `std::integral`. Lets impose this new template type parameter constraint on `T`. @@ -260,9 +240,9 @@ In file included from :1: [Example](https://www.godbolt.org/z/1f1x8MTer) -[`std::integral` : cppreference](https://en.cppreference.com/w/cpp/concepts/integral) +[`std::integral`](https://en.cppreference.com/w/cpp/concepts/integral) -### Task 4.4 : Requires expressions +## Requires expressions The is a slight problem with our reformed `Point` class. It no longer can accept floating point types as they are not considered integrals in C++. Instead we need to constraint `Point` to a type `T` by creating a conjunction (`&&`) or disjunction (`||`) of multiple concepts. To do this we use a requires clause. Requires clause are introduced just after (often syntactically below) a template declaration and consist of a list of requirements in the form of a Boolean concept expression. We can create a disjunction of the `std::integral` and `std::floating_point` allowing floating point types and integral types to be valid `T` for `Point`. @@ -290,10 +270,10 @@ auto main() -> int [Example](https://www.godbolt.org/z/55dhT6W6j) -- [`std::floating_point` : cppreference](https://en.cppreference.com/w/cpp/concepts/floating_point) -- [`requires` clause : cppreference](https://en.cppreference.com/w/cpp/language/constraints#:~:text=on%20constraint%20normalization.-,Requires%20clauses,-The%20keyword) +- [`std::floating_point`](https://en.cppreference.com/w/cpp/concepts/floating_point) +- [`requires` clause](https://en.cppreference.com/w/cpp/language/constraints#:~:text=on%20constraint%20normalization.-,Requires%20clauses,-The%20keyword) -#### Task 4.4.1 : Requires expression +### Requires expression Sometimes more complicated requirements need to be specified in order to fine the allowed behaviour of the program. Require expressions allow for mock values of template types to bne created and specify patterns that a value of the type parameter must provide. In the case of our `Point` class, we may want to also allow other types that support `+` and `-` binary operator overloads. Because this check depends on the type parameter of another `Point` we can't declare it at the requires clause at the template declaration of `Point`. Instead we need to create a requires clause at the operator overloads template declaration. We then declare our requires expression, enforcing the semantic and syntactic rules on the type. We can declare as many of these rules in a requires expression as we like. For `Point` we will ensure that for a value of type `T` called `a` and for a value of type `U` of name `b`, `a + b` and `a - b` is valid. @@ -327,9 +307,9 @@ operator- (const Point& p) [Example](https://www.godbolt.org/z/763Y6fjjc) -[`requires` expression : cppreference](https://en.cppreference.com/w/cpp/language/requires) +[`requires` expression](https://en.cppreference.com/w/cpp/language/requires) -#### Task 4.4.2 : Compound requirements +### Compound requirements We can also apply constraints on the expressions within a requires expression, ensuring the types or properties these expressions will have. These are called compound expressions, which we create by wrapping our individual rules from a requires expression in braces and use a `->` followed by a constraint on the return type of the expression. @@ -361,11 +341,11 @@ operator- (const Point& p) [Example](https://www.godbolt.org/z/nqxoE7466) -[Compound requirements : cppreference](https://en.cppreference.com/w/cpp/language/requires#:~:text=%3B%20%0A%7D%3B-,Compound%20Requirements,-A%20compound%20requirement) +[Compound requirements](https://en.cppreference.com/w/cpp/language/requires#:~:text=%3B%20%0A%7D%3B-,Compound%20Requirements,-A%20compound%20requirement) -[Version 3 of `Point`](/content/part5/tasks/concepts.md) +[Version 3 of `Point`](/content/chapter5/tasks/concepts.md) -### Task 4.5 : Constrained variables +## Constrained variables We can also use concepts to constrain variables declared with the `auto` specifier. Gives a more robust option for constraining function and method parameters without the need for template declarations or requires clauses. @@ -388,64 +368,3 @@ auto main() -> int [Example](https://www.godbolt.org/z/vcGW1qPY9) > Note: We've applied concepts at the user definition level for classes. These concepts [ideas] can be applied to template functions as well. They are also the basic for defining your own concepts. - -## Assignment 2 - -Having learnt about classes, templates and concepts I want you to reimplement your `Triple` class so that it behaves more like a standard type and has a more sophisticated implementation and interface. Similar to Assignment 1, you will submit using a pull request on GitHub to this repo. - -### Requirements - -- Must be templated for a single type `T` -- A way to add two points of different `T` -- A way to subtract two points of different `T` -- A way to multiply a point by a scalar of different `T` -- A way to divide a point by a scalar of different `T` -- A way to be print a formatted output using `std::cout` -- Using concepts ensure that `T` satisfies only: - - `std::integral` -- or - - `std::floating_point` -- or - - `T` and `U` support - - `T + U` - - `T - U` - - `U * T` - - `T / U` - - and doesn't support - - `is_pointer` - - `is_reference` - - `is_enum` etc. -- and - - `T` supports `<<` to an `std::ostream` - -> Note: Let me know if the concept requirements are confusing - -### Bonus - -- A way to be created using input from `std::cin` -- Allow three different type parameter; say `T`, `U` and `V` for the member variables while still maintaining the base requirements [hard] - -### Submitting - -You can use Godbolt or bpt to build and test your struct. Once you have created your implementation: - -- clone this repo using `git clone https://github.com/MonashDeepNeuron/HPP.git`. -- create a new branch using `git checkout -b triple/`. -- create a folder in the `/content/part5` directory called `submissions/`. -- Copy your mini project into this directory (bpt setup, cmake scripts etc.) with a `README.md` or comment in the code on how to run the program (verify it still works). There is a sample header file in `/templates` that you can use. -- Go to and click 'New pull request'. -- Change the branches in the drop down so that your branch is going into `main` and `Create new pull request. -- Give the pull request a title and briefly describe what you were able to implement and any struggles you had. -- On the right side-panel, under the 'Assignees' section, click the cog and assign me. -- Click 'Create pull request' and I'll take it from there. - -> Note: If you created a GodBolt instance, put the link in a comment at the top of the file (under your copy comments). This is generated by clicking the `share` button in the top-right-most corner of the webpage and clicking the 'short link' option. - -This, ideally should be submitted before our meetup on 18/01/2023. Please note that I will be asking each of you a few questions about how you went and your thought processes in throughout the implementation. - -## Links - -- [Previous Page : Generics](/content/part5/tasks/generics.md) -- [Back to Part 5](/content/part5/README.md) -- [Content](/content/README.md) -- [HOME](/README.md) diff --git a/content/part5/examples/point-v1.hxx b/src/chapter5/examples/point-v1.hxx similarity index 100% rename from content/part5/examples/point-v1.hxx rename to src/chapter5/examples/point-v1.hxx diff --git a/content/part5/examples/point-v2.hxx b/src/chapter5/examples/point-v2.hxx similarity index 100% rename from content/part5/examples/point-v2.hxx rename to src/chapter5/examples/point-v2.hxx diff --git a/content/part5/examples/point-v3.hxx b/src/chapter5/examples/point-v3.hxx similarity index 100% rename from content/part5/examples/point-v3.hxx rename to src/chapter5/examples/point-v3.hxx diff --git a/content/part5/tasks/generics.md b/src/chapter5/generics.md similarity index 72% rename from content/part5/tasks/generics.md rename to src/chapter5/generics.md index 6254f47..b6fa11a 100644 --- a/content/part5/tasks/generics.md +++ b/src/chapter5/generics.md @@ -1,28 +1,10 @@ -# Generics - -## Contents - -- [Generics](#generics) - - [Contents](#contents) - - [Task 3](#task-3) - - [Task 3.1 : Generic Programming](#task-31--generic-programming) - - [Task 3.2 : Parameter Packs](#task-32--parameter-packs) - - [Task 3.2.1 : Parameter pack size](#task-321--parameter-pack-size) - - [Task 3.2.2 : Fold Expressions](#task-322--fold-expressions) - - [Task 3.3 : Tuples](#task-33--tuples) - - [Task 3.3.1 : Pairs](#task-331--pairs) - - [Task 3.3.2 : Destructuring](#task-332--destructuring) - - [Links](#links) - -## Task 3 - -### Task 3.1 : Generic Programming +# Generics Programming Generic programming is a style of programming that involves defining algorithms and data structures in terms of generic types. This allows the behaviour of the program to be adapted according to the types, which can be resolved at compile or pre-process time as opposed to through runtime resolution. It also allows for programs to work in a more adaptive way so that, regardless of the type that used at instantiation time, the program will adapt and work accordingly. -### Task 3.2 : Parameter Packs +## Parameter Packs -Part of C++ generic programming facilities that go hand-in-hand with templates is template parameter packs. These are heterogenous objects that can contain an arbitrary number of elements that gets instantiated at compile time. Parameter packs allows for C++ to generalize the idea passing an around an arbitrary number of different typed arguments. This can be utilised by template functions and classes alike. Parameter packs can also have a single type which indicates an arbitrary number of values with the same type. Parameter packs are denoted by an ellipsis `Ts...` where `Ts` is either a parameter pack template type parameter from the template declaration of the form `template`, or the single type of a value parameter pack with the function signature of the form `f(int... ints)`. We can combine these two notations to create functions of variadic type arguments `f(Ts... ts)` where `Ts` is a template type parameter pack and `ts` is a template value parameter pack. +Chapter of C++ generic programming facilities that go hand-in-hand with templates is template parameter packs. These are heterogenous objects that can contain an arbitrary number of elements that gets instantiated at compile time. Parameter packs allows for C++ to generalize the idea passing an around an arbitrary number of different typed arguments. This can be utilised by template functions and classes alike. Parameter packs can also have a single type which indicates an arbitrary number of values with the same type. Parameter packs are denoted by an ellipsis `Ts...` where `Ts` is either a parameter pack template type parameter from the template declaration of the form `template`, or the single type of a value parameter pack with the function signature of the form `f(int... ints)`. We can combine these two notations to create functions of variadic type arguments `f(Ts... ts)` where `Ts` is a template type parameter pack and `ts` is a template value parameter pack. ```cxx #include @@ -55,9 +37,9 @@ auto main() -> int [Example](https://www.godbolt.org/z/sMxWcd1fM) -[Parameter Packs : cppreference](https://en.cppreference.com/w/cpp/language/parameter_pack) +[Parameter Packs](https://en.cppreference.com/w/cpp/language/parameter_pack) -#### Task 3.2.1 : Parameter pack size +### Parameter pack size The size of a pack can be obtained by using the `sizeof...` operator. This will return a `std::size_t` with the number of either types or values in the parameter pack. @@ -78,9 +60,9 @@ auto main() -> int [Example](https://www.godbolt.org/z/nhnj3Ehne) -[`sizeof...` : cppreference](https://en.cppreference.com/w/cpp/language/sizeof...) +[`sizeof...`](https://en.cppreference.com/w/cpp/language/sizeof...) -#### Task 3.2.2 : Fold Expressions +### Fold Expressions Fold expressions allow for unary and binary operations to be performed on packs of elements. This allows us to 'loop' through a pack and perform compile type computation such as sums, printing and more. Fold expressions can operate just on the pack ot can have an initialiser that is separate from the pack. @@ -107,9 +89,9 @@ auto main() -> int [Example](https://www.godbolt.org/z/zh97vevo3) -[Fold expressions : cppreference](https://en.cppreference.com/w/cpp/language/fold) +[Fold expressions](https://en.cppreference.com/w/cpp/language/fold) -### Task 3.3 : Tuples +## Tuples Because of the introduction of parameter packs in C++11, C++ was finally able to have a tuple data structure called `std::tuple`. Tuples are a formalisation of parameter packs, tieing a heterogeneous pack of types to a heterogeneously types pack of values. Tuples are incredibly powerful in programming as they formalise the idea of being able to cluster together elements of any type where the types might not be immediately be known at definition. This is; normally, incredibly difficult to do in a typed language like C++ with the solution before being to create aggregate classes to store the required data together. Tuples make this far easier and can be used anywhere. ANother benefit is any tuple has a common interface allowing anyone to manipulate them as they need. `std::tuple` structure is immutable however, its elements can be modified in place making them extremely versatile. `std::tuple` comes with a host of powerful helper functions and classes that allow for compile time inspection of a tuples size, element type and value access, creation of `std::tuple` and destructuring. @@ -150,9 +132,9 @@ auto main() -> int [Example](https://www.godbolt.org/z/v5sP6TjYs) -[`std::tuple` : cppreference](https://en.cppreference.com/w/cpp/utility/tuple) +[`std::tuple`](https://en.cppreference.com/w/cpp/utility/tuple) -#### Task 3.3.1 : Pairs +### Pairs It is often common place to just need to return a two values of possibly different types and not have to go through the hassle of uses `std::tuple` generic (yet admittedly cumbersome) access methods. This is where `std::pair` comes in. `std::pair` is a specific use case of a `std::tuple`. Accessing the elements of a pair can be done directly using class dot access of the members name. @@ -182,9 +164,9 @@ auto main() -> int [Example](https://www.godbolt.org/z/ax688eds3) -[`std::pair` : cppreference](https://en.cppreference.com/w/cpp/utility/pair) +[`std::pair`](https://en.cppreference.com/w/cpp/utility/pair) -#### Task 3.3.2 : Destructuring +### Destructuring Since C++17, `std::pair` and `std::tuple` can be accessed using structured bindings. This can make it easier to manipulate the data of a pair, tuple, arrays, slices and even aggregate classes. Structured bindings are declared by an `auto` specifier (which can have reference, storage and cv qualifiers) followed by square brackets containing comma separated variable names that will bind to the sequence of values ie. `/*cv-qual (optional) */auto/*& or && (optional)*/ [/* names */] = /* tuple-like */`. @@ -211,11 +193,4 @@ auto main() -> int [Example](https://www.godbolt.org/z/5v8zb998o) -[Structured bindings : cppreference](https://en.cppreference.com/w/cpp/language/structured_binding) - -## Links - -- [Previous Page : Templates](/content/part5/tasks/templates.md) -- [Next Page : Concepts](/content/part5/tasks/concepts.md) -- [Content](/content/README.md) -- [HOME](/README.md) +[Structured bindings](https://en.cppreference.com/w/cpp/language/structured_binding) diff --git a/content/part5/slides/hpp_part5.pdf b/src/chapter5/hpp_chapter5.pdf similarity index 53% rename from content/part5/slides/hpp_part5.pdf rename to src/chapter5/hpp_chapter5.pdf index 98f26fa..ca544fc 100644 Binary files a/content/part5/slides/hpp_part5.pdf and b/src/chapter5/hpp_chapter5.pdf differ diff --git a/content/part5/slides/hpp_part5.pptx b/src/chapter5/hpp_chapter5.pptx similarity index 100% rename from content/part5/slides/hpp_part5.pptx rename to src/chapter5/hpp_chapter5.pptx diff --git a/content/part5/slides/imgs/hpp_part5-01.png b/src/chapter5/imgs/hpp_chapter5-01.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-01.png rename to src/chapter5/imgs/hpp_chapter5-01.png diff --git a/content/part5/slides/imgs/hpp_part5-02.png b/src/chapter5/imgs/hpp_chapter5-02.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-02.png rename to src/chapter5/imgs/hpp_chapter5-02.png diff --git a/content/part5/slides/imgs/hpp_part5-03.png b/src/chapter5/imgs/hpp_chapter5-03.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-03.png rename to src/chapter5/imgs/hpp_chapter5-03.png diff --git a/content/part5/slides/imgs/hpp_part5-04.png b/src/chapter5/imgs/hpp_chapter5-04.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-04.png rename to src/chapter5/imgs/hpp_chapter5-04.png diff --git a/content/part5/slides/imgs/hpp_part5-05.png b/src/chapter5/imgs/hpp_chapter5-05.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-05.png rename to src/chapter5/imgs/hpp_chapter5-05.png diff --git a/content/part5/slides/imgs/hpp_part5-06.png b/src/chapter5/imgs/hpp_chapter5-06.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-06.png rename to src/chapter5/imgs/hpp_chapter5-06.png diff --git a/content/part5/slides/imgs/hpp_part5-07.png b/src/chapter5/imgs/hpp_chapter5-07.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-07.png rename to src/chapter5/imgs/hpp_chapter5-07.png diff --git a/content/part5/slides/imgs/hpp_part5-08.png b/src/chapter5/imgs/hpp_chapter5-08.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-08.png rename to src/chapter5/imgs/hpp_chapter5-08.png diff --git a/content/part5/slides/imgs/hpp_part5-09.png b/src/chapter5/imgs/hpp_chapter5-09.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-09.png rename to src/chapter5/imgs/hpp_chapter5-09.png diff --git a/content/part5/slides/imgs/hpp_part5-10.png b/src/chapter5/imgs/hpp_chapter5-10.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-10.png rename to src/chapter5/imgs/hpp_chapter5-10.png diff --git a/content/part5/slides/imgs/hpp_part5-11.png b/src/chapter5/imgs/hpp_chapter5-11.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-11.png rename to src/chapter5/imgs/hpp_chapter5-11.png diff --git a/content/part5/slides/imgs/hpp_part5-12.png b/src/chapter5/imgs/hpp_chapter5-12.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-12.png rename to src/chapter5/imgs/hpp_chapter5-12.png diff --git a/content/part5/slides/imgs/hpp_part5-13.png b/src/chapter5/imgs/hpp_chapter5-13.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-13.png rename to src/chapter5/imgs/hpp_chapter5-13.png diff --git a/content/part5/slides/imgs/hpp_part5-14.png b/src/chapter5/imgs/hpp_chapter5-14.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-14.png rename to src/chapter5/imgs/hpp_chapter5-14.png diff --git a/content/part5/slides/imgs/hpp_part5-15.png b/src/chapter5/imgs/hpp_chapter5-15.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-15.png rename to src/chapter5/imgs/hpp_chapter5-15.png diff --git a/content/part5/slides/imgs/hpp_part5-16.png b/src/chapter5/imgs/hpp_chapter5-16.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-16.png rename to src/chapter5/imgs/hpp_chapter5-16.png diff --git a/content/part5/slides/imgs/hpp_part5-17.png b/src/chapter5/imgs/hpp_chapter5-17.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-17.png rename to src/chapter5/imgs/hpp_chapter5-17.png diff --git a/content/part5/slides/imgs/hpp_part5-18.png b/src/chapter5/imgs/hpp_chapter5-18.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-18.png rename to src/chapter5/imgs/hpp_chapter5-18.png diff --git a/content/part5/slides/imgs/hpp_part5-19.png b/src/chapter5/imgs/hpp_chapter5-19.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-19.png rename to src/chapter5/imgs/hpp_chapter5-19.png diff --git a/content/part5/slides/imgs/hpp_part5-20.png b/src/chapter5/imgs/hpp_chapter5-20.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-20.png rename to src/chapter5/imgs/hpp_chapter5-20.png diff --git a/content/part5/slides/imgs/hpp_part5-21.png b/src/chapter5/imgs/hpp_chapter5-21.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-21.png rename to src/chapter5/imgs/hpp_chapter5-21.png diff --git a/content/part5/slides/imgs/hpp_part5-22.png b/src/chapter5/imgs/hpp_chapter5-22.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-22.png rename to src/chapter5/imgs/hpp_chapter5-22.png diff --git a/content/part5/slides/imgs/hpp_part5-23.png b/src/chapter5/imgs/hpp_chapter5-23.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-23.png rename to src/chapter5/imgs/hpp_chapter5-23.png diff --git a/content/part5/slides/imgs/hpp_part5-24.png b/src/chapter5/imgs/hpp_chapter5-24.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-24.png rename to src/chapter5/imgs/hpp_chapter5-24.png diff --git a/src/chapter5/imgs/hpp_chapter5-25.png b/src/chapter5/imgs/hpp_chapter5-25.png new file mode 100644 index 0000000..c763628 Binary files /dev/null and b/src/chapter5/imgs/hpp_chapter5-25.png differ diff --git a/content/part5/slides/imgs/hpp_part5-26.png b/src/chapter5/imgs/hpp_chapter5-26.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-26.png rename to src/chapter5/imgs/hpp_chapter5-26.png diff --git a/content/part5/slides/imgs/hpp_part5-27.png b/src/chapter5/imgs/hpp_chapter5-27.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-27.png rename to src/chapter5/imgs/hpp_chapter5-27.png diff --git a/content/part5/slides/imgs/hpp_part5-28.png b/src/chapter5/imgs/hpp_chapter5-28.png similarity index 88% rename from content/part5/slides/imgs/hpp_part5-28.png rename to src/chapter5/imgs/hpp_chapter5-28.png index 339438b..e187074 100644 Binary files a/content/part5/slides/imgs/hpp_part5-28.png and b/src/chapter5/imgs/hpp_chapter5-28.png differ diff --git a/content/part5/slides/imgs/hpp_part5-29.png b/src/chapter5/imgs/hpp_chapter5-29.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-29.png rename to src/chapter5/imgs/hpp_chapter5-29.png diff --git a/content/part5/slides/imgs/hpp_part5-30.png b/src/chapter5/imgs/hpp_chapter5-30.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-30.png rename to src/chapter5/imgs/hpp_chapter5-30.png diff --git a/content/part5/slides/imgs/hpp_part5-31.png b/src/chapter5/imgs/hpp_chapter5-31.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-31.png rename to src/chapter5/imgs/hpp_chapter5-31.png diff --git a/content/part5/slides/imgs/hpp_part5-32.png b/src/chapter5/imgs/hpp_chapter5-32.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-32.png rename to src/chapter5/imgs/hpp_chapter5-32.png diff --git a/content/part5/slides/imgs/hpp_part5-33.png b/src/chapter5/imgs/hpp_chapter5-33.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-33.png rename to src/chapter5/imgs/hpp_chapter5-33.png diff --git a/content/part5/slides/imgs/hpp_part5-34.png b/src/chapter5/imgs/hpp_chapter5-34.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-34.png rename to src/chapter5/imgs/hpp_chapter5-34.png diff --git a/content/part5/slides/imgs/hpp_part5-35.png b/src/chapter5/imgs/hpp_chapter5-35.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-35.png rename to src/chapter5/imgs/hpp_chapter5-35.png diff --git a/content/part5/slides/imgs/hpp_part5-36.png b/src/chapter5/imgs/hpp_chapter5-36.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-36.png rename to src/chapter5/imgs/hpp_chapter5-36.png diff --git a/content/part5/slides/imgs/hpp_part5-37.png b/src/chapter5/imgs/hpp_chapter5-37.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-37.png rename to src/chapter5/imgs/hpp_chapter5-37.png diff --git a/content/part5/slides/imgs/hpp_part5-38.png b/src/chapter5/imgs/hpp_chapter5-38.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-38.png rename to src/chapter5/imgs/hpp_chapter5-38.png diff --git a/src/chapter5/imgs/hpp_chapter5-39.png b/src/chapter5/imgs/hpp_chapter5-39.png new file mode 100644 index 0000000..81f095b Binary files /dev/null and b/src/chapter5/imgs/hpp_chapter5-39.png differ diff --git a/content/part5/slides/imgs/hpp_part5-40.png b/src/chapter5/imgs/hpp_chapter5-40.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-40.png rename to src/chapter5/imgs/hpp_chapter5-40.png diff --git a/content/part5/slides/imgs/hpp_part5-41.png b/src/chapter5/imgs/hpp_chapter5-41.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-41.png rename to src/chapter5/imgs/hpp_chapter5-41.png diff --git a/content/part5/slides/imgs/hpp_part5-42.png b/src/chapter5/imgs/hpp_chapter5-42.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-42.png rename to src/chapter5/imgs/hpp_chapter5-42.png diff --git a/content/part5/slides/imgs/hpp_part5-43.png b/src/chapter5/imgs/hpp_chapter5-43.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-43.png rename to src/chapter5/imgs/hpp_chapter5-43.png diff --git a/content/part5/slides/imgs/hpp_part5-44.png b/src/chapter5/imgs/hpp_chapter5-44.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-44.png rename to src/chapter5/imgs/hpp_chapter5-44.png diff --git a/content/part5/slides/imgs/hpp_part5-45.png b/src/chapter5/imgs/hpp_chapter5-45.png similarity index 100% rename from content/part5/slides/imgs/hpp_part5-45.png rename to src/chapter5/imgs/hpp_chapter5-45.png diff --git a/src/chapter5/slides5.md b/src/chapter5/slides5.md new file mode 100644 index 0000000..c9c1db7 --- /dev/null +++ b/src/chapter5/slides5.md @@ -0,0 +1,47 @@ +# Slides + +![Slides 01](./imgs/hpp_chapter5-01.png) +![Slides 02](./imgs/hpp_chapter5-02.png) +![Slides 03](./imgs/hpp_chapter5-03.png) +![Slides 04](./imgs/hpp_chapter5-04.png) +![Slides 05](./imgs/hpp_chapter5-05.png) +![Slides 06](./imgs/hpp_chapter5-06.png) +![Slides 07](./imgs/hpp_chapter5-07.png) +![Slides 08](./imgs/hpp_chapter5-08.png) +![Slides 09](./imgs/hpp_chapter5-09.png) +![Slides 10](./imgs/hpp_chapter5-10.png) +![Slides 11](./imgs/hpp_chapter5-11.png) +![Slides 12](./imgs/hpp_chapter5-12.png) +![Slides 13](./imgs/hpp_chapter5-13.png) +![Slides 14](./imgs/hpp_chapter5-14.png) +![Slides 15](./imgs/hpp_chapter5-15.png) +![Slides 16](./imgs/hpp_chapter5-16.png) +![Slides 17](./imgs/hpp_chapter5-17.png) +![Slides 18](./imgs/hpp_chapter5-18.png) +![Slides 19](./imgs/hpp_chapter5-19.png) +![Slides 20](./imgs/hpp_chapter5-20.png) +![Slides 21](./imgs/hpp_chapter5-21.png) +![Slides 22](./imgs/hpp_chapter5-22.png) +![Slides 23](./imgs/hpp_chapter5-23.png) +![Slides 24](./imgs/hpp_chapter5-24.png) +![Slides 25](./imgs/hpp_chapter5-25.png) +![Slides 26](./imgs/hpp_chapter5-26.png) +![Slides 27](./imgs/hpp_chapter5-27.png) +![Slides 28](./imgs/hpp_chapter5-28.png) +![Slides 29](./imgs/hpp_chapter5-29.png) +![Slides 30](./imgs/hpp_chapter5-30.png) +![Slides 31](./imgs/hpp_chapter5-31.png) +![Slides 32](./imgs/hpp_chapter5-32.png) +![Slides 33](./imgs/hpp_chapter5-33.png) +![Slides 34](./imgs/hpp_chapter5-34.png) +![Slides 35](./imgs/hpp_chapter5-35.png) +![Slides 36](./imgs/hpp_chapter5-36.png) +![Slides 37](./imgs/hpp_chapter5-37.png) +![Slides 38](./imgs/hpp_chapter5-38.png) +![Slides 39](./imgs/hpp_chapter5-39.png) +![Slides 40](./imgs/hpp_chapter5-40.png) +![Slides 41](./imgs/hpp_chapter5-41.png) +![Slides 42](./imgs/hpp_chapter5-42.png) +![Slides 43](./imgs/hpp_chapter5-43.png) +![Slides 44](./imgs/hpp_chapter5-44.png) +![Slides 45](./imgs/hpp_chapter5-45.png) diff --git a/src/chapter5/task2.md b/src/chapter5/task2.md new file mode 100644 index 0000000..d01b4e8 --- /dev/null +++ b/src/chapter5/task2.md @@ -0,0 +1,52 @@ +# Task 2 : Templated Triple + +Having learnt about classes, templates and concepts I want you to reimplement your `Triple` class so that it behaves more like a standard type and has a more sophisticated implementation and interface. Similar to Assignment 1, you will submit using a pull request on GitHub to this repo. + +## Requirements + +- Must be templated for a single type `T` +- A way to add two points of different `T` +- A way to subtract two points of different `T` +- A way to multiply a point by a scalar of different `T` +- A way to divide a point by a scalar of different `T` +- A way to be print a formatted output using `std::cout` +- Using concepts ensure that `T` satisfies only: + - `std::integral` +- or + - `std::floating_point` +- or + - `T` and `U` support + - `T + U` + - `T - U` + - `U * T` + - `T / U` + - and doesn't support + - `is_pointer` + - `is_reference` + - `is_enum` etc. +- and + - `T` supports `<<` to an `std::ostream` + +> Note: Let me know if the concept requirements are confusing + +### Bonus + +- A way to be created using input from `std::cin` +- Allow three different type parameter; say `T`, `U` and `V` for the member variables while still maintaining the base requirements [hard] + +### Submitting + +You can use Godbolt or bpt to build and test your struct. Once you have created your implementation: + +- Clone this repo using `git clone https://github.com/MonashDeepNeuron/HPP.git`. +- Create a new branch using `git checkout -b triple/`. +- Create a folder in the `/submissions` directory with your name. +- Create a folder with the name of this task. +- Copy your mini project into this directory (bpt setup, cmake scripts etc.) with a `README.md` or comment in the code on how to run the program (verify it still works). There is a sample header file in `/templates` that you can use. +- Go to and click 'New pull request'. +- Change the branches in the drop down so that your branch is going into `main` and `Create new pull request. +- Give the pull request a title and briefly describe what you were able to implement and any struggles you had. +- On the right side-panel, under the 'Assignees' section, click the cog and assign me. +- Click 'Create pull request' and I'll take it from there. + +> Note: If you created a GodBolt instance, put the link in a comment at the top of the file (under your copy comments). This is generated by clicking the `share` button in the top-right-most corner of the webpage and clicking the 'short link' option. diff --git a/content/part5/tasks/templates.md b/src/chapter5/templates.md similarity index 72% rename from content/part5/tasks/templates.md rename to src/chapter5/templates.md index 936844a..521fe8b 100644 --- a/content/part5/tasks/templates.md +++ b/src/chapter5/templates.md @@ -1,33 +1,16 @@ # Templates -## Contents +## Why templates? -- [Templates](#templates) - - [Contents](#contents) - - [Task 2](#task-2) - - [Task 2.1 : Why templates?](#task-21--why-templates) - - [Task 2.2 : What are templates?](#task-22--what-are-templates) - - [Task 2.3 : Template Parameters](#task-23--template-parameters) - - [Task 2.4 : Template Functions](#task-24--template-functions) - - [Task 2.5 : Template Classes](#task-25--template-classes) - - [Task 2.5.1 : Class Template Methods](#task-251--class-template-methods) - - [Task 2.6: Template Variables](#task-26-template-variables) - - [Task 2.7 : Template Metaprogramming Basics](#task-27--template-metaprogramming-basics) - - [Links](#links) +Everything we have learnt about C++ relies on the fact the type of any object must be known at compile time. This can be quite constricting on the kinds of programs we are able to right. Just think back to Assignment 1 where you were sectioned with creating a class called `Triple` with a single underlying type (either `int`, `float` or `double`). Imagine you create `TripleInt` but now had to create a class with the same interface but for the other underlying types (`float` and `double` in this case) that you did not implement (well some of you may have). This can dramatically increase code duplication. One might think to solve this through class inheritance. Somehow define a common abstract interface that derived classes could inherit from and then override the methods in order to implement the interface for each underlying type. However, this requires more work still as anyone that wants to implement `Triple` would have to inherit from it and implement the same interface and logic for there own underlying type. Another caveat is this requires every `Triple` object to have a vtable to there underlying methods resulting in dynamic dispatch of method calling which, is something that has a lot of runtime overhead. The real solution is to have a single interface that can working for any desired type. This is where templates come in. -## Task 2 - -### Task 2.1 : Why templates? - -Everything we have learnt about C++ relies on the fact the type of any object must be known at compile time. This can be quite constricting on the kinds of programs we are able to right. Just think back to Assignment 1 where you were tasked with creating a class called `Triple` with a single underlying type (either `int`, `float` or `double`). Imagine you create `TripleInt` but now had to create a class with the same interface but for the other underlying types (`float` and `double` in this case) that you did not implement (well some of you may have). This can dramatically increase code duplication. One might think to solve this through class inheritance. Somehow define a common abstract interface that derived classes could inherit from and then override the methods in order to implement the interface for each underlying type. However, this requires more work still as anyone that wants to implement `Triple` would have to inherit from it and implement the same interface and logic for there own underlying type. Another caveat is this requires every `Triple` object to have a vtable to there underlying methods resulting in dynamic dispatch of method calling which, is something that has a lot of runtime overhead. The real solution is to have a single interface that can working for any desired type. This is where templates come in. - -### Task 2.2 : What are templates? +## What are templates? Templates can be thought of as blueprints for function, variable or class. They allow for defining interfaces in terms of template parameters which can be types or compile-time variables. Templates can then be instantiated for a given set of valid template parameters which results in the function, variable or class being fully defined meaning they can now be instantiated themselves. Templates are created by using a `template<>` declaration above the definition of a function, variable or class with the template parameters being specified within the angle brackets (`<>`). -[Templates : cppreference](https://en.cppreference.com/w/cpp/language/templates) +[Templates](https://en.cppreference.com/w/cpp/language/templates) -### Task 2.3 : Template Parameters +## Template Parameters There are three categories of template parameters; type, non-type and template-template. We wont cover template-template parameters as they are used for advanced specialisation. Type template parameters are template parameters that accept a type as an argument. These are used to create generic functions, variables and classes that can be defined in terms of many different types. These are the most common use of templates. Type arguments are declared as `template` with T being the name of the type argument and will be an alias to the type we later instantiate the template with. Non-type arguments are used to pass values at compile time to a function, variable or class. The type of a non-type template argument must be explicitly declared eg. `template`, Non-type template arguments are constant and thus cannot be mutated. Here is an example of a template declaration that takes type and non-type template arguments. @@ -38,9 +21,9 @@ template This is the template signature of `std::array`. -[Template Arguments : cppreference](https://en.cppreference.com/w/cpp/language/template_parameters) +[Template Arguments](https://en.cppreference.com/w/cpp/language/template_parameters) -### Task 2.4 : Template Functions +## Template Functions To begin, we will look at defining template functions. Template functions are defined identically to regular functions except that before the functions signature we use a template declaration. As we can see below, regardless of the type of the array or the its size we can call `print<>()`. Also, thanks to C++17 we don't have to call it with specific template arguments as the can be deduced from the array itself. @@ -79,11 +62,11 @@ auto main() -> int [Example](https://www.godbolt.org/z/WxsGsfna4) -[Function template : cppreference](https://en.cppreference.com/w/cpp/language/function_template) +[Function template](https://en.cppreference.com/w/cpp/language/function_template) -### Task 2.5 : Template Classes +## Template Classes -Template classes allow us to define generic types. Almost all of C++ standard library types are template classes, even `std::cout` which is a static instance of the class `std::basic_ostream`. Template classes allow us to create a blueprint of a class and then instantiate the class definition which a particular type. We can see this with out `Point` class from the previous task section. Now we define `Point` in terms of a template type `T` which we will specify later. This allows us to create `Point` objects of `float` and `double` as well while still only defining a single interface. +Template classes allow us to define generic types. Almost all of C++ standard library types are template classes, even `std::cout` which is a static instance of the class `std::basic_ostream`. Template classes allow us to create a blueprint of a class and then instantiate the class definition which a particular type. We can see this with out `Point` class from the previous section section. Now we define `Point` in terms of a template type `T` which we will specify later. This allows us to create `Point` objects of `float` and `double` as well while still only defining a single interface. > Note: For copy and move constructors, the template type parameters can be elided as copy and move semantics must preserve the type. Converting constructors (a type of explicit constructor) are used to convert between template types. @@ -199,9 +182,9 @@ auto main() -> int [Example](https://www.godbolt.org/z/nhbsbnE9b) -[Class Template : cppreference](https://en.cppreference.com/w/cpp/language/class_template) +[Class Template](https://en.cppreference.com/w/cpp/language/class_template) -### Task 2.5.1 : Class Template Methods +## Class Template Methods Just like how free functions can be templated, we can also specify methods of classes to be templated. This allows use to customize classes methods not just in terms of its template types and parameters but also in terms of templates of objects that we may need to pass to the method of a class. This useful for creating overloaded methods that are not just customized by type but also the template signature pattern they have. @@ -250,10 +233,10 @@ private: [Example](https://www.godbolt.org/z/4WKKrMsqn) - [Member templates](https://en.cppreference.com/w/cpp/language/member_template) -- [`std::common_type` : cppreference](https://en.cppreference.com/w/cpp/types/common_type) -- [Version 2 of `Point`](/content/part5/examples/point-v2.hxx) +- [`std::common_type`](https://en.cppreference.com/w/cpp/types/common_type) +- [Version 2 of `Point`](/content/chapter5/examples/point-v2.hxx) -### Task 2.6: Template Variables +### Section 2.6: Template Variables Is is also possible to define variables as templates. This allows for variables to take on different forms depending on the underlying type. Template variables are typically `static` or `constexpr` free variables or `static` members of a class. A common use of template variables is mathematical constants that have different underlying types. We can see this in use with `e` and `std::numeric_limits` members. @@ -283,22 +266,15 @@ auto main() -> int [Example](https://www.godbolt.org/z/4eqKcTT4s) -- [Variable Templates : cppreference](https://en.cppreference.com/w/cpp/language/variable_template) -- [`std::numeric_limits` : cppreference](https://en.cppreference.com/w/cpp/types/numeric_limits) +- [Variable Templates](https://en.cppreference.com/w/cpp/language/variable_template) +- [`std::numeric_limits`](https://en.cppreference.com/w/cpp/types/numeric_limits) -### Task 2.7 : Template Metaprogramming Basics +## Template Metaprogramming Basics We've seen a bit of metaprogramming in C++ already. Metaprogramming is the ability to influence the structure of your code at compile time using the language itself. Templates are a simple form of metaprogramming and allow us to change the behaviour of our code based on the types and values we instantiate our templates with. Using templates, the C++ standard library has many metaprogramming objects that allow us to customize our code even more. Most of the standard libraries metaprogramming objects are in the form of type analysis from the `` header. These allow us to inspect the properties of any type (template or known) and customize based on the results. There is much more to metaprogramming that is beyond the scope of this course. -- [Metaprogramming Library : cppreference](https://en.cppreference.com/w/cpp/meta) -- [Compile-time rational arithmetic : cppreference](https://en.cppreference.com/w/cpp/numeric/ratio) -- [SFINAE : cppreference](https://en.cppreference.com/w/cpp/language/sfinae) -- [`` : cppreference](https://en.cppreference.com/w/cpp/header/type_traits) -- [`std::integer_sequence` : cppreference](https://en.cppreference.com/w/cpp/utility/integer_sequence) - -## Links - -- [Previous Page : Classes](/content/part5/tasks/classes.md) -- [Next Page : Generics](/content/part5/tasks/generics.md) -- [Content](/content/README.md) -- [HOME](/README.md) +- [Metaprogramming Library](https://en.cppreference.com/w/cpp/meta) +- [Compile-time rational arithmetic](https://en.cppreference.com/w/cpp/numeric/ratio) +- [SFINAE](https://en.cppreference.com/w/cpp/language/sfinae) +- [``](https://en.cppreference.com/w/cpp/header/type_traits) +- [`std::integer_sequence`](https://en.cppreference.com/w/cpp/utility/integer_sequence) diff --git a/src/chapter6/README.md b/src/chapter6/README.md new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/chapter6/README.md @@ -0,0 +1 @@ + diff --git a/content/part6/tasks/algorithms.md b/src/chapter6/algorithms.md similarity index 78% rename from content/part6/tasks/algorithms.md rename to src/chapter6/algorithms.md index 918d818..ab82baf 100644 --- a/content/part6/tasks/algorithms.md +++ b/src/chapter6/algorithms.md @@ -1,70 +1,20 @@ # Algorithms -## Contents - -- [Algorithms](#algorithms) - - [Contents](#contents) - - [Task 3](#task-3) - - [Task 3.1 : What is an algorithm?](#task-31--what-is-an-algorithm) - - [Task 3.1.1 : Algorithm Intuition](#task-311--algorithm-intuition) - - [Task 3.2 : The Standard Template Library](#task-32--the-standard-template-library) - - [Task 3.3 : General](#task-33--general) - - [Task 3.4 : Sorting](#task-34--sorting) - - [Task 3.4.1 : Sort](#task-341--sort) - - [Task 3.4.2 : Partition](#task-342--partition) - - [Task 3.4.3 : Nth Element](#task-343--nth-element) - - [Task 3.5 : Searching](#task-35--searching) - - [Task 3.5.1 : Find](#task-351--find) - - [Task 3.5.2 : Search](#task-352--search) - - [Task 3.5.3 : Adjacent Find](#task-353--adjacent-find) - - [Task 3.5.4 : Binary Search](#task-354--binary-search) - - [Task 3.5.5 : Equal Range, Lower Bound \& Upper Bound](#task-355--equal-range-lower-bound--upper-bound) - - [Task 3.6 : Modifiers](#task-36--modifiers) - - [Task 3.6.1 : Copy \& Move](#task-361--copy--move) - - [Task 3.6.2 : Swap Range](#task-362--swap-range) - - [Task 3.6.3 : Remove \& Replace](#task-363--remove--replace) - - [Task 3.6.4 : Reverse](#task-364--reverse) - - [Task 3.6.5 : Transform](#task-365--transform) - - [Task 3.6.6 : Rotate](#task-366--rotate) - - [Task 3.6.7 : Sample](#task-367--sample) - - [Task 3.6.8 : Shuffle](#task-368--shuffle) - - [Task 3.7 : Numeric](#task-37--numeric) - - [Task 3.7.1 : Minimums \& Maximums](#task-371--minimums--maximums) - - [Task 3.7.2 : Count](#task-372--count) - - [Task 3.7.3 : Clamp](#task-373--clamp) - - [Task 3.7.4 : Accumulate](#task-374--accumulate) - - [Task 3.7.5 : Inner Product](#task-375--inner-product) - - [Task 3.7.6 : Partial Sum](#task-376--partial-sum) - - [Task 3.7.7 : Adjacent Difference](#task-377--adjacent-difference) - - [Task 3.8 : Comparisons](#task-38--comparisons) - - [Task 3.8.1 : Equal](#task-381--equal) - - [Task 3.8.2 : Lexicographical Compare](#task-382--lexicographical-compare) - - [Task 3.8.3 : All, Any \& None Of](#task-383--all-any--none-of) - - [Task 3.8.4 : Mismatch](#task-384--mismatch) - - [Task 3.9 : Generators](#task-39--generators) - - [Task 3.9.1 : Fill](#task-391--fill) - - [Task 3.9.2 : Iota](#task-392--iota) - - [Task 3.9.3 : Generate](#task-393--generate) - - [Task 3.10 : Algorithm Extensions](#task-310--algorithm-extensions) - - [Links](#links) - -## Task 3 - -### Task 3.1 : What is an algorithm? +## What is an algorithm? What is an algorithm? The simplest definition is that is is a function. The longer definition is that an algorithm is a set of instructions that occur in a finite number of steps. Algorithms are used to manipulate data, perform computation or even perform introspection on data. Powerful algorithms when paired with efficient data structures are what make programs. So far we have seen how to create our own data structures in C++ through classes and concepts. We have also seen the data structures already offered by C++, we will now look at how you can use any algorithm available in C++ with all of these data structures and perform computation (almost) entirely independent of how it is organised. -#### Task 3.1.1 : Algorithm Intuition +### Algorithm Intuition This section is not really about how to implement any particular algorithm. Instead it is aimed at building what is called algorithm intuition. This focuses not on how I do make an algorithm that performs the steps X, Y and Z to some data, taking into account A, B and C but rather on knowing about existing algorithms, what they do and how you can piece and compose different algorithms together to create a more general solution. This idea of composition is a super power to programming as it enables creating solutions from smaller reusable components. -### Task 3.2 : The Standard Template Library +## The Standard Template Library The C++ algorithms library as it stands today was created by the brilliant mind of [Alexander Stepanov](https://en.wikipedia.org/wiki/Alexander_Stepanov). Alex Stepanov was a pioneer in practical generic programming and created what is known as the Standard Template Library (STL). The STL was the predecessor to everything in the C++ Standard Library that uses templates which is almost everything. The biggest edition to the C++ standard from the STL was the container and algorithm libraries. All algorithms in C++ use iterator pairs (with identical types), one to the beginning of a sequence and one to the end. This means that any container just has to provide an iterator to its first and last elements and any algorithm can work with it. A pair of iterators is called a range in C++. All algorithms take at least a pair of iterators with some taking more. -[`` : cppreference](https://en.cppreference.com/w/cpp/algorithm) +[``](https://en.cppreference.com/w/cpp/algorithm) -### Task 3.3 : General +## General The most general algorithm is `std::for_each`. This algorithm can take a single ranges and an unary function that will be applied to each element. `std::for_each` is often used to replace for-loops in certain context, mostly when a function has a side effect. @@ -85,13 +35,13 @@ auto main() -> int [Example](https://www.godbolt.org/z/W1croE686) -[`std::for_each` : cppreference](https://en.cppreference.com/w/cpp/algorithm/for_each) +[`std::for_each`](https://en.cppreference.com/w/cpp/algorithm/for_each) -### Task 3.4 : Sorting +## Sorting Sorting is a very common operation in programming. It allows us to more efficiently search for particular elements and guarantee certain properties and relationships between elements. In C++ there are a few different kinds of sorting algorithms including partitioning and introspection of data. -#### Task 3.4.1 : Sort +### Sort `std::sort` is C++ sorting algorithm. Along with the input range, it can also take in a predicate (a binary function returning a Boolean) which is used for the comparison. This defaults to `<` making `std::sort` sort in ascending order. `std::sort` sorts in-place and is often implemented as an Introsort algorithm. @@ -118,9 +68,9 @@ auto main() -> int [Example](https://www.godbolt.org/z/d9K618hhn) -[`std::sort` : cppreference](https://en.cppreference.com/w/cpp/algorithm/sort) +[`std::sort`](https://en.cppreference.com/w/cpp/algorithm/sort) -#### Task 3.4.2 : Partition +### Partition Partitioning is the process of sorting elements based on a predicate such that any element for which the predicate is `true` precedes any element for which the predicate is `false`. This can be used to separate evens and odds or positive and negatives or even implement quicksort. The individual partitions are not necessarily sorted. @@ -147,9 +97,9 @@ auto main() -> int [Example](https://www.godbolt.org/z/48jfqqdcd) -[`std::partition` : cppreference](https://en.cppreference.com/w/cpp/algorithm/partition) +[`std::partition`](https://en.cppreference.com/w/cpp/algorithm/partition) -#### Task 3.4.3 : Nth Element +### Nth Element `std::nth_element` sorts a range such that the element pointed to by nth is the element that would occur in that position if the range was sorted. `std::nth_element` is a partial sorting algorithm. @@ -179,13 +129,13 @@ auto main() -> int [Example](https://www.godbolt.org/z/GM1rrW68P) -[`std::nth_element` : cppreference](https://en.cppreference.com/w/cpp/algorithm/nth_element) +[`std::nth_element`](https://en.cppreference.com/w/cpp/algorithm/nth_element) -### Task 3.5 : Searching +## Searching -More often than not, you do not know anything about which values actually exists in your range. This is why searching algorithms are important part of computer programming. They allow us to find elements what we need or handle the case when they do not exist. +More often than not, you do not know anything about which values actually exists in your range. This is why searching algorithms are important chapter of computer programming. They allow us to find elements what we need or handle the case when they do not exist. -#### Task 3.5.1 : Find +### Find `std::find` is used to find a particular value in range. returning the iterator to its location. It is not very efficient but is the most general searcher. @@ -215,9 +165,9 @@ auto main() -> int [Example](https://www.godbolt.org/z/KhqvGao43) -[`std::find` : cppreference](https://en.cppreference.com/w/cpp/algorithm/find) +[`std::find`](https://en.cppreference.com/w/cpp/algorithm/find) -#### Task 3.5.2 : Search +### Search `std::search` is used fo find the first occurrence of a subsequence in a range. `std::search` can also be passed a different searcher to change how it searches for the subsequence. @@ -246,9 +196,9 @@ auto main() -> int [Example](https://www.godbolt.org/z/51cqjG8Pb) -[`std::` : cppreference](https://en.cppreference.com/w/cpp/algorithm/search) +[`std::`](https://en.cppreference.com/w/cpp/algorithm/search) -#### Task 3.5.3 : Adjacent Find +### Adjacent Find `std::adjacent_find` returns the location of the first pair of adjacent elements in a ranges that satisfy a predicate. The default predicate is `==`. @@ -279,9 +229,9 @@ auto main() -> int [Example](https://www.godbolt.org/z/WMxqEezfn) -[`std::adjacent_find` : cppreference](https://en.cppreference.com/w/cpp/algorithm/adjacent_find) +[`std::adjacent_find`](https://en.cppreference.com/w/cpp/algorithm/adjacent_find) -#### Task 3.5.4 : Binary Search +### Binary Search Everyone knows the binary search algorithm however, `std::binary_search` is a little different. Instead of returning the location of the desired element it returns `true` if the desired value exists in the range and `false` otherwise. `std::binary_search` iin C++ is more commonly spelt **_in_**. `std::binary_search` one works on a partially ordered ranged with respect to the desired value. Partitioning with respect to the desired value is the minimum sorting requirement. @@ -313,9 +263,9 @@ auto main() -> int [Example](https://www.godbolt.org/z/xq7cerxYf) -[`std::binary_search` : cppreference](https://en.cppreference.com/w/cpp/algorithm/binary_search) +[`std::binary_search`](https://en.cppreference.com/w/cpp/algorithm/binary_search) -#### Task 3.5.5 : Equal Range, Lower Bound & Upper Bound +### Equal Range, Lower Bound & Upper Bound These algorithms work on partitioned ranges with respect to some value (similar to `std::binary_search`). `std::equal_range` returns a pair of iterators representing the sub-range of elements that are equal to the desired value. `std::lower_bound` and `std::upper_bound` will return an iterator representing the first value do not satisfy a predicate (default `<`) with the right argument always being the desired value for `std::lower_bound` and the left argument always being the desired value for `std::upper_bound`. @@ -349,15 +299,15 @@ auto main() -> int [Example](https://www.godbolt.org/z/eTK3jaKb7) -- [`std::equal_range` : cppreference](https://en.cppreference.com/w/cpp/algorithm/equal_range) -- [`std::lower_bound` : cppreference](https://en.cppreference.com/w/cpp/algorithm/lower_bound) -- [`std::upper_bound` : cppreference](https://en.cppreference.com/w/cpp/algorithm/upper_bound) +- [`std::equal_range`](https://en.cppreference.com/w/cpp/algorithm/equal_range) +- [`std::lower_bound`](https://en.cppreference.com/w/cpp/algorithm/lower_bound) +- [`std::upper_bound`](https://en.cppreference.com/w/cpp/algorithm/upper_bound) -### Task 3.6 : Modifiers +## Modifiers Modifiers are the bread and butter of the algorithms library. They are used to modify the values of sequences sometimes in-place and other times using an output iterator that becomes the writer of the algorithm. The writer iterator can be the same iterator as the one representing the start of the input ranges as long as it supports write operations (assignment to). These algorithms will often return `void` for in-place modifications or return the end iterator of the output range. -#### Task 3.6.1 : Copy & Move +### Copy & Move The copy and move algorithms are pretty self explanatory, they well copy of move the elements from one range to another. These algorithms eliminate 90% of the use of a manual for-loop and allow for copying and moving from completely different ranges, as long as the underlying copy of move is support ie. they types are copyable or movable. @@ -396,10 +346,10 @@ auto main() -> int [Example](https://www.godbolt.org/z/jrhM39hz4) -- [`std::copy` : cppreference](https://en.cppreference.com/w/cpp/algorithm/copy) -- [`std::move` : cppreference](https://en.cppreference.com/w/cpp/algorithm/move) +- [`std::copy`](https://en.cppreference.com/w/cpp/algorithm/copy) +- [`std::move`](https://en.cppreference.com/w/cpp/algorithm/move) -#### Task 3.6.2 : Swap Range +### Swap Range `std::swap_range` is a range based form of `std::swap`. It will swap the values of two ranges until the end of the first rnage is reached. @@ -429,9 +379,9 @@ auto main() -> int [Example](https://www.godbolt.org/z/3eqcdfG4f) -[`std::swap_ranges` : cppreference](https://en.cppreference.com/w/cpp/algorithm/swap_ranges) +[`std::swap_ranges`](https://en.cppreference.com/w/cpp/algorithm/swap_ranges) -#### Task 3.6.3 : Remove & Replace +### Remove & Replace `std::remove` and `std::replace` are also fairly simple algorithms. They will remove or replace all instances of a particular value or replacing it with a new value respectively. `std::remove` doesn't actually free memory, usually it just moves any other value forward in the range. To free the removed memory, a call to `std::remove` is followed by a call to the containers erase method or `std::erase` (for sequence containers), taking the iterator returned by `std::remove` and the containers end iterator forming the _remove-erase idiom_. @@ -461,10 +411,10 @@ auto main() -> int [Example](https://www.godbolt.org/z/Er64q3T3b) -- [`std::remove` : cppreference](https://en.cppreference.com/w/cpp/algorithm/remove) -- [`std::replace` : cppreference](https://en.cppreference.com/w/cpp/algorithm/replace) +- [`std::remove`](https://en.cppreference.com/w/cpp/algorithm/remove) +- [`std::replace`](https://en.cppreference.com/w/cpp/algorithm/replace) -#### Task 3.6.4 : Reverse +### Reverse `std::reverse` is an in-place modifier that reverses the elements of the container by swapping iterators. @@ -487,9 +437,9 @@ auto main() -> int [Example](https://www.godbolt.org/z/cjT6vEd7M) -[`std::reverse` : cppreference](https://en.cppreference.com/w/cpp/algorithm/reverse) +[`std::reverse`](https://en.cppreference.com/w/cpp/algorithm/reverse) -#### Task 3.6.5 : Transform +### Transform `std::transform` one of the most important algorithms in any programming language. `std::transform` will apply an unary function on every element in a range, writing it to a new output range. It also is overloaded to take an additional input iterator allowing for binary transformations. `std::transform` is most commonly spelt as **_map_** in Computer Science however, this name was taken be `std::map`. @@ -524,9 +474,9 @@ auto main() -> int [Example](https://www.godbolt.org/z/9n9WjerzG) -[`std::transform` : cppreference](https://en.cppreference.com/w/cpp/algorithm/transform) +[`std::transform`](https://en.cppreference.com/w/cpp/algorithm/transform) -#### Task 3.6.6 : Rotate +### Rotate `std::rotate` takes three iterators first, pivot and end respectively. As normal, first and end form the range the algorithm operates on while pivot is swapped such that it becomes the new starting element of the range and the element preceding the pivot becomes the new end of the range. @@ -550,11 +500,11 @@ auto main() -> int [Example](https://www.godbolt.org/z/YTnEn1o7d) -[`std::rotate` : cppreference](https://en.cppreference.com/w/cpp/algorithm/rotate) +[`std::rotate`](https://en.cppreference.com/w/cpp/algorithm/rotate) -#### Task 3.6.7 : Sample +### Sample -`std::sample` will sample $n$ random elements a range without replacement such that each sampled element has an equal probability of appearing. `std::sample` takes in a random number generator from the `` header in order to generate the random access. +`std::sample` will sample \\( n \\) random elements a range without replacement such that each sampled element has an equal probability of appearing. `std::sample` takes in a random number generator from the `` header in order to generate the random access. ```cxx #include @@ -579,12 +529,12 @@ auto main() -> int [Example](https://www.godbolt.org/z/rr6PPbb8a) -- [`std::sample` : cppreference](https://en.cppreference.com/w/cpp/algorithm/sample) -- [`` : cppreference](https://en.cppreference.com/w/cpp/header/random) -- [Pseudo-random number generation : cppreference](https://en.cppreference.com/w/cpp/numeric/random) -- [`std::mersenne_twister_engine` : cppreference](https://en.cppreference.com/w/cpp/numeric/random/mersenne_twister_engine) +- [`std::sample`](https://en.cppreference.com/w/cpp/algorithm/sample) +- [``](https://en.cppreference.com/w/cpp/header/random) +- [`std::mersenne_twister_engine`](https://en.cppreference.com/w/cpp/numeric/random/mersenne_twister_engine) +- [Pseudo-random number generation](https://en.cppreference.com/w/cpp/numeric/random) -#### Task 3.6.8 : Shuffle +### Shuffle `std::shuffle` will randomly reorganize a range. Like `std::sample`, `std::shuffle` takes in a random number generator in order to randomly generate the index sequence. @@ -608,15 +558,15 @@ auto main() -> int [Example](https://www.godbolt.org/z/cjY6W7cPe) -[`std::shuffle` : cppreference](https://en.cppreference.com/w/cpp/algorithm/shuffle) +[`std::shuffle`](https://en.cppreference.com/w/cpp/algorithm/) -### Task 3.7 : Numeric +## Numeric Numerical algorithms are powerful algorithms for performing numerical computation on ranges. Many of the numerical algorithms in C++ are specialised forms of a reduction. Reductions will take a range of values and reduce the the number of elements in the resulting range. Reductions often come in the form of a folding algorithm which take and initial value, a range and a binary function. They break a range of elements into a _Head_ and _Tail_ component, with the _Head_ being the first element and _Tail_ being the rest. There are two version folds called left and right folds. A left fold will apply the initial value along with the result of left folding the _Tail_; with _Head_ being the new initial value, to the binary function. Right folds will invert this process applying _Head_ and the result of right folding the _Tail_ of the range; passing the initial value to the bottom of the fold, to the binary function. Folds spelt as reductions are often left folds with the initial value being the _Head_ of the range. [Fold](https://docs.google.com/spreadsheets/d/16isUb2rsuzSmkJLO_FtjGCzsQJOAeRKWARBUGn_mrHI/edit#gid=631619717) -#### Task 3.7.1 : Minimums & Maximums +### Minimums & Maximums Minimum and maximum reductions are used to find the smallest and largest number in a range. In C++ these are spelt as `std::min_element`, `std::max_element`. These algorithms return an iterator to the element most satisfying the predicate which is defaulted to `<` but can be customised. There is also `std::minmax_element` which returns a pair of iterators indicating the minimum and maximum element in a range. @@ -651,11 +601,11 @@ auto main() -> int [Example](https://www.godbolt.org/z/G8Y9dchEv) -[`std::min_element` : cppreference](https://en.cppreference.com/w/cpp/algorithm/min_element) -[`std::max_element` : cppreference](https://en.cppreference.com/w/cpp/algorithm/max_element) -[`std::minmax_element` : cppreference](https://en.cppreference.com/w/cpp/algorithm/minmax_element) +[`std::min_element`](https://en.cppreference.com/w/cpp/algorithm/min_element) +[`std::max_element`](https://en.cppreference.com/w/cpp/algorithm/max_element) +[`std::minmax_element`](https://en.cppreference.com/w/cpp/algorithm/minmax_element) -#### Task 3.7.2 : Count +### Count `std::count` will count that number of occurrences of a particular value. The default predicate is `==` but it can be customised. @@ -678,9 +628,9 @@ auto main() -> int [Example](https://www.godbolt.org/z/5xejqWf6s) -[`std::count` : cppreference](https://en.cppreference.com/w/cpp/algorithm/count) +[`std::count`](https://en.cppreference.com/w/cpp/algorithm/count) -#### Task 3.7.3 : Clamp +### Clamp `std::clamp` is a scalar algorithm (doesn't work for ranges) that will clamp a value between a set range. If the value is smaller then the lower bound it is clamped to the lower bound and if it is larger than the upper bound it clamps to the upper bound, returning the value otherwise. `std::clamp` is not a reduction. @@ -710,13 +660,13 @@ auto main() -> int [Example](https://www.godbolt.org/z/q5sWsrK1x) -[`std::clamp` : cppreference](https://en.cppreference.com/w/cpp/algorithm/clamp) +[`std::clamp`](https://en.cppreference.com/w/cpp/algorithm/clamp) -#### Task 3.7.4 : Accumulate +### Accumulate `std::accumulate` is the most general numeric algorithm and can be used to implement almost all of the algorithms in the C++ standard. Accumulate takes a range of values, an initial value and a binary function defaulting to `+`. Accumulate is most commonly spelt as left-fold or foldl. `std::accumulate` is one of the only algorithms that returns a value. One point to note about `std::accumulate` is that the initial values type is unrelated to the type of the range of elements. This can cause unintended side effects due to implicit conversions. `std::accumulate` is not found in `` but rather ``. -> One algorithm `std::accumulate` should not try and model is function application of maps (ie. `std::transform`). +> One algorithm `std::accumulate` should not try and model is function application or maps (ie. `std::transform`). ```cxx #include @@ -741,9 +691,9 @@ auto main() -> int [Example](https://www.godbolt.org/z/v3jEMP4c1) -[`std::accumulate` : cppreference](https://en.cppreference.com/w/cpp/algorithm/accumulate) +[`std::accumulate`](https://en.cppreference.com/w/cpp/algorithm/accumulate) -#### Task 3.7.5 : Inner Product +### Inner Product `std::inner_product` is a very powerful algorithm. It performs a binary transformation of two ranges and then performs a reduction on the resulting range. The most common form of this algorithm is known as the dot-product which applies the binary `*` on the two sets of coordinates and then a binary reduction on the resulting range using `+`. This is the default operation set for C++ `std::inner_product` but it can be customised to using any binary transformation and reduction. Like `std::accumulate` is takes an initial value which is applied to the and returns the result of the reduction. `std::inner_product` also lives in the `` header. @@ -771,9 +721,9 @@ auto main() -> int [Example](https://www.godbolt.org/z/schxqWbo3) -[`std::inner_product` : cppreference](https://en.cppreference.com/w/cpp/algorithm/inner_product) +[`std::inner_product`](https://en.cppreference.com/w/cpp/algorithm/inner_product) -#### Task 3.7.6 : Partial Sum +### Partial Sum `std::partial_sum` is another reduction algorithm but with a twist. Instead of reducing the range to a scalar, it partially reduces the range, saving the intermediate accumulation values. `std::partial_sum` does not take an initial but does take an iterator to the beginning of the output range. Returns the element pointing to one-past-the-end element of the output range. This algorithm is most commonly spelt as left scan or `scanl` (in particular `scanl1` due to it not taking an initial accumulator value).`std::partial_sum` is in the `` header. The default binary function is `+`. @@ -802,9 +752,9 @@ auto main() -> int [Example](https://www.godbolt.org/z/YnWdvq1nv) -[`std::partial_sum` : cppreference](https://en.cppreference.com/w/cpp/algorithm/partial_sum) +[`std::partial_sum`](https://en.cppreference.com/w/cpp/algorithm/partial_sum) -#### Task 3.7.7 : Adjacent Difference +### Adjacent Difference `std::adjacent_difference` applies the the binary function `-` (by default) to every pair of neighboring elements writing them to a new range. This range begins at one after the passed output iterator. @@ -835,13 +785,13 @@ auto main() -> int [Example](https://www.godbolt.org/z/rbvK3P1ah) -[`std::adjacent_difference` : cppreference](https://en.cppreference.com/w/cpp/algorithm/adjacent_difference) +[`std::adjacent_difference`](https://en.cppreference.com/w/cpp/algorithm/adjacent_difference) -### Task 3.8 : Comparisons +## Comparisons The following algorithms are used to perform comparisons and conditional checks both between ranges and within a range. They all return a Boolean indicating the result of the comparison. -#### Task 3.8.1 : Equal +### Equal `std::equal` performs applies a predicate to two ranges. The default predicate is `==` but any can be used. @@ -868,9 +818,9 @@ auto main() -> int [Example](https://www.godbolt.org/z/fs1T64vq5) -[`std::equal` : cppreference](https://en.cppreference.com/w/cpp/algorithm/equal) +[`std::equal`](https://en.cppreference.com/w/cpp/algorithm/equal) -#### Task 3.8.2 : Lexicographical Compare +### Lexicographical Compare `std::lexicographical_compare` checks if the first range is lexicographically less then the second range. The predicate _less_ can be changed. @@ -899,9 +849,9 @@ auto main() -> int [Example](https://www.godbolt.org/z/YqovzcTYM) -[`std::lexicographical_compare` : cppreference](https://en.cppreference.com/w/cpp/algorithm/lexicographical_compare) +[`std::lexicographical_compare`](https://en.cppreference.com/w/cpp/algorithm/lexicographical_compare) -#### Task 3.8.3 : All, Any & None Of +### All, Any & None Of The three algorithms `std::all_of`, `std::any_of` and `std::none_of` will apply an unary predicate on a range returning `true` if all of, any of or none of the elements satisfy the predicate and `false` otherwise. @@ -933,9 +883,9 @@ auto main() -> int [Example](https://www.godbolt.org/z/hddx535Wj) -[`std::all_of`, `std::any_of` & `std::none_of` : cppreference](https://en.cppreference.com/w/cpp/algorithm/all_any_none_of) +[`std::all_of`, `std::any_of` & `std::none_of`](https://en.cppreference.com/w/cpp/algorithm/all_any_none_of) -#### Task 3.8.4 : Mismatch +### Mismatch Finds the first mismatch between two ranges returning an `std::pair` of the iterators to the mismatch in the ranges. The binary predicate (default `==`) can be changed so that mismatch triggers on the first evaluation of `false` from the predicate. @@ -965,13 +915,13 @@ auto main() -> int [Example](https://www.godbolt.org/z/jj69vr5qe) -[`std::mismatch` : cppreference](https://en.cppreference.com/w/cpp/algorithm/mismatch) +[`std::mismatch`](https://en.cppreference.com/w/cpp/algorithm/mismatch) -### Task 3.9 : Generators +## Generators Generators allow for ranges to be filled with values after their initial construction. They are useful for manufacturing values without the need of literals. -#### Task 3.9.1 : Fill +### Fill `std::fill` is the most simple generator. It fills an entire range with a single value, modifying the range in-place. @@ -994,11 +944,11 @@ auto main() -> int [Example](https://www.godbolt.org/z/57ssP7P36) -[`std::fill` : cppreference](https://en.cppreference.com/w/cpp/algorithm/fill) +[`std::fill`](https://en.cppreference.com/w/cpp/algorithm/fill) -#### Task 3.9.2 : Iota +### Iota -`std::iota` is a powerful factory based generator. It is supplied and initial value and will increment (using `++`) that initial value as it iterates through the range and assigns the current iterator with the incremented value. Iota is a common factory used in many different programming languages. Its original name is iota but it is often spelt **_range_**. `std::iota` is part of the `` header. Like `std::fill`, `std::iota` modifies a sequence in-place. +`std::iota` is a powerful factory based generator. It is supplied and initial value and will increment (using `++`) that initial value as it iterates through the range and assigns the current iterator with the incremented value. Iota is a common factory used in many different programming languages. Its original name is iota but it is often spelt **_range_**. `std::iota` is chapter of the `` header. Like `std::fill`, `std::iota` modifies a sequence in-place. ```cxx #include @@ -1019,9 +969,9 @@ auto main() -> int [Example](https://www.godbolt.org/z/oz1179Gn6) -[`std::iota` : cppreference](https://en.cppreference.com/w/cpp/algorithm/iota) +[`std::iota`](https://en.cppreference.com/w/cpp/algorithm/iota) -#### Task 3.9.3 : Generate +### Generate `std::generate` is the most primitive generator algorithm. Instead of taking an initial value, it takes a function that gets called repeatedly on each iteration. This algorithm modifies the range in-place. @@ -1048,15 +998,8 @@ auto main() -> int [Example](https://www.godbolt.org/z/s3GrYnv1a) -[`std::generate` : cppreference](https://en.cppreference.com/w/cpp/algorithm/generate) +[`std::generate`](https://en.cppreference.com/w/cpp/algorithm/generate) -### Task 3.10 : Algorithm Extensions +## Algorithm Extensions Many algorithms have customised counterparts. These customisations include variants that take a predicate, or a size `n` instead of and end iterator. This are suffixed with markers such as `_if` or `_n` in the algorithm functions name. Look at cppreference for a comprehensive list of these variants. - -## Links - -- [Previous Page : Data Structures](/content/part6/tasks/data-structures.md) -- [Next Page : Ranges](/content/part6/tasks/ranges.md) -- [Content](/content/README.md) -- [HOME](/README.md) diff --git a/src/chapter6/chapter6.md b/src/chapter6/chapter6.md new file mode 100644 index 0000000..bc3e46c --- /dev/null +++ b/src/chapter6/chapter6.md @@ -0,0 +1,3 @@ +# Algorithms & Data Structures + +So far you have learnt a lot about the C++ language from user-defined types with classes, to generic programming with templates and concepts as well as (almost) all of the languages primitive types, control flow and looping mechanisms. With all of this you can pretty much get a computer to do anything. However, this is only the foundation; mind you all taught at once, what comes next is the fun chapter. We cover some the of facilities, techniques and practices focused on actually manipulating data and performing actual computation. Many of these facilities are available in the C++ standard library; after all this isn't C, we don't have to build everything from scratch. This will include everything from building up your algorithm intuition to exploring different data structures and how they work under the hood. We will also cover topics such as evaluation techniques, function composition and lifting. diff --git a/content/part6/tasks/data-structures.md b/src/chapter6/data-structures.md similarity index 74% rename from content/part6/tasks/data-structures.md rename to src/chapter6/data-structures.md index fd04f14..22725a4 100644 --- a/content/part6/tasks/data-structures.md +++ b/src/chapter6/data-structures.md @@ -1,45 +1,18 @@ # Data Structures -## Contents - -- [Data Structures](#data-structures) - - [Contents](#contents) - - [Task 2](#task-2) - - [Task 2.1 : What is a Data Structure](#task-21--what-is-a-data-structure) - - [Task 2.2 : Sequence Containers](#task-22--sequence-containers) - - [Task 2.2.1 : Vector](#task-221--vector) - - [Task 2.2.2 : Deque](#task-222--deque) - - [Task 2.2.3 : Forward List](#task-223--forward-list) - - [Task 2.2.4 : List](#task-224--list) - - [Task 2.2.5 : A harsh truth](#task-225--a-harsh-truth) - - [Task 2.3 : Associative Containers](#task-23--associative-containers) - - [Task 2.3.1 : Set](#task-231--set) - - [Task 2.3.2 : Map](#task-232--map) - - [Task 2.3.3 : Multiset \& Multimap](#task-233--multiset--multimap) - - [Task 2.4 : Unordered Associative Containers](#task-24--unordered-associative-containers) - - [Task 2.4.1 : Unordered Set](#task-241--unordered-set) - - [Task 2.4.2 : Unordered Map](#task-242--unordered-map) - - [Task 2.4.3 : Unordered Multiset \& Multimap](#task-243--unordered-multiset--multimap) - - [Task 2.5 : Miscellaneous](#task-25--miscellaneous) - - [Task 2.5.1 : Bitset](#task-251--bitset) - - [Task 2.5.2 : Any](#task-252--any) - - [Links](#links) - -## Task 2 - -### Task 2.1 : What is a Data Structure +## What is a Data Structure Data structures are a fundamental concept in computer science. Data structures are types or classes used to organise and manage data. Data structures differ primarily by their internal means of organising the data they manage to be as optimal as possible and often support various different operations. Using the correct data structure can be a difficult question to answer, particularly in C++ where many operation on these most basic data structures are expected to have as little size and time overhead. This section mostly goes into a high level look at the data structures or containers available in C++, how they work and to give an idea of when one might use them. All containers have methods for obtaining iterators to their first and last element and all work with a _range-for_ loop. -### Task 2.2 : Sequence Containers +## Sequence Containers Sequence containers are _Array-Like_ containers in the sense that they model their data as a 1D array of values. Along with slices and `std::array`, C++ offers four other sequence based containers. -#### Task 2.2.1 : Vector +### Vector -`std::vector` is the most fundamental container in C++. It models a contiguous dynamic array. It has constant ($O(1)$) index-based random access to elements. Vectors offer random access insertion and erasure of elements as well as efficient pushing and popping of elements at the end of the vector. Indexing is **0-based** which is the same for all index based containers. Insertion and erasure is less efficient anywhere in the vector that is not the back ($O(n)$ where $n$ is the number elements past the insertion or erasure) as all elements past the insertion or erasure have to be moved back one cell. Insertion and erasure also (has a chance of \[invalidating\]) invalidates any iterators or references of the shifted elements. Vectors can reserve more memory then it currently uses in order to make any operations involving potential allocations more efficient by pre-allocating the resources. Erasures also do not remove the memory owned by the vector but save it for later use. +`std::vector` is the most fundamental container in C++. It models a contiguous dynamic array. It has constant (\\( O(1) \\)) index-based random access to elements. Vectors offer random access insertion and erasure of elements as well as efficient pushing and popping of elements at the end of the vector. Indexing is **0-based** which is the same for all index based containers. Insertion and erasure is less efficient anywhere in the vector that is not the back (\\( O(n) \\) where \\( n \\) is the number elements past the insertion or erasure) as all elements past the insertion or erasure have to be moved back one cell. Insertion and erasure also (has a chance of \[invalidating\]) invalidates any iterators or references of the shifted elements. Vectors can reserve more memory then it currently uses in order to make any operations involving potential allocations more efficient by pre-allocating the resources. Erasures also do not remove the memory owned by the vector but save it for later use. ```cxx #include @@ -96,11 +69,11 @@ auto main() -> int [Exmaple](https://www.godbolt.org/z/sYhf5rG6r) -[`std::vector` : cppreference](https://en.cppreference.com/w/cpp/container/vector) +[`std::vector`](https://en.cppreference.com/w/cpp/container/vector) -#### Task 2.2.2 : Deque +### Deque -`std::deque` is a double ended queue that offers efficient ($O(1)$) insertion and erasure at both the front and back of a deque while also never invalidating iterators and references to the rest of the elements. Deques elements are not stored contiguously resulting in a larger memory footprint due to 'book-keeping' data for smaller deques when compared to vectors. Deques also have two indirections to get elements compared to vectors single indirection. Deques also cannot reserve extra memory for later use. +`std::deque` is a double ended queue that offers efficient (\\( O(1) \\)) insertion and erasure at both the front and back of a deque while also never invalidating iterators and references to the rest of the elements. Deques elements are not stored contiguously resulting in a larger memory footprint due to 'book-keeping' data for smaller deques when compared to vectors. Deques also have two indirections to get elements compared to vectors single indirection. Deques also cannot reserve extra memory for later use. ```cxx #include @@ -163,9 +136,9 @@ auto main() -> int [Exmaple](https://www.godbolt.org/z/Tnx49fajv) -[`std::deque` : cppreference](https://en.cppreference.com/w/cpp/container/deque) +[`std::deque`](https://en.cppreference.com/w/cpp/container/deque) -#### Task 2.2.3 : Forward List +### Forward List `std::forward_list` is an implementation of a singly-linked-list offering fast access, insertion and erasure to the beginning of the list. Forward lists also allows for easy merging of two sorted lists as well as operations for reversing and sorting the list. Insertion and erasure has `_after` semantics meaning that these operations occur to the element after the passed iterator. Forward lists are not indexable. @@ -210,11 +183,11 @@ auto main() -> int [Exmaple](https://www.godbolt.org/z/Y5c4z67Pz) -[`std::forward_list` : cppreference](https://en.cppreference.com/w/cpp/container/forward_list) +[`std::forward_list`](https://en.cppreference.com/w/cpp/container/forward_list) -#### Task 2.2.4 : List +### List -Along with a singly-linked-list C++ offers a doubly-linked-list called `std::list`. This offers constant ($O(1)$) insertion and erasure anywhere within the container with the biggest benefits occurring at the beginning and end of the list. Lists allow for bidirectional iteration through the container. Iterators and references are not invalidated during insertion and erasure except for the element that got erased. +Along with a singly-linked-list C++ offers a doubly-linked-list called `std::list`. This offers constant (\\( O(1) \\)) insertion and erasure anywhere within the container with the biggest benefits occurring at the beginning and end of the list. Lists allow for bidirectional iteration through the container. Iterators and references are not invalidated during insertion and erasure except for the element that got erased. ```cxx #include @@ -264,23 +237,23 @@ auto main() -> int [Exmaple](https://www.godbolt.org/z/YfoWacKcK) -[`std::list` : cppreference](https://en.cppreference.com/w/cpp/container/list) +[`std::list`](https://en.cppreference.com/w/cpp/container/list) -#### Task 2.2.5 : A harsh truth +### A harsh truth While many of these sequences offer a variety of different ways to organise data and offer different performance guarantees to fit different needs when it comes to searching, insertion and erasure, the harsh reality is often this doesn't matter outside of semantics. 99.9% of the time (I'm exaggerating a bit) the best data structure; particularly for sequences based organisation of data, are vectors. Even for searching, sorting, insertion and erasure. This is because computers are so much faster then they were two decades ago and CPU's have much larger (L2) caches. What does this have to do with it? Well, computer memory is sequential in nature meaning that all data that is stored contiguously. Copying, allocating and transfer of sequential memory is almost always faster as the CPU will often vectorize the operation, assuming that it can move sequential from memory to the cache even if it doesn't explicitly know this. Compare this to other data structures, particularly linked-lists which 'optimise' insertion and erasure by having nodes of data spread out throughout memory, removing the restriction on the data needing to be contiguous. What this actually does is prevent the CPU from predicting what memory it might use maximizing the opportunity for a cache miss to occur which is much slower than copying more data. Copies are cheap, especially for `std::vector` as it contains only three pointers. One to the start of the data, one to the end of the used memory and one to the end of the owned memory. All of this pointers are reachable from each other. To get to the data, it costs one pointer indirection to the data and one jump of size `n` to the desired value. This jump happens in constant time as the CPU will already know exactly how many bytes over this is (exactly $n \cdot sizeof(element)$) and can add this directly to the pointer to the start of the data. If the CPU can figure out that memory near the current memory being fetched will ned to be fetched as well it will take as much as it can from the region, optimising the IO the CPU does which is one of the largest bottlenecks of performance. Compare this to many pointer indirections that have to go into getting a single node from a linked list. Not to mention the CPU has no way of determining where the next memory it needs might be, increasing the fetching time the CPU execute. Not to mention that is has to make room in its cache and eject memory every time it reads. -What does this all mean? Don't think too much about which data structure is best based on the $BigO$ complexities. Start with using vectors and arrays and adapt your programs to use specific data structures as you need. After all; for C++, the $BigO$ complexity are minimum requirements for the standard library that must be met by a particular implementation and not their real world average performance. That is not to say that linked lists or deques do not have there uses. Linked lists are used in the Linux kernel to connect and organise related data. It looks very different to lists in C++ but has a pretty intuitive implementation and use. It is implemented as a intrusive linked list. How this works is that a data structure will have a member that is node containing a pointer to the previous and next node. The benefit to this is that the list is not tied to any type as the nodes don't hold any data themselves, instead the data holds information on how to get to the nxe or previous node. This list structure is used everywhere in the Linux kernel and is very efficient. +What does this all mean? Don't think too much about which data structure is best based on the \\( BigO \\) complexities. Start with using vectors and arrays and adapt your programs to use specific data structures as you need. After all; for C++, the \\( BigO \\) complexity are minimum requirements for the standard library that must be met by a particular implementation and not their real world average performance. That is not to say that linked lists or deques do not have there uses. Linked lists are used in the Linux kernel to connect and organise related data. It looks very different to lists in C++ but has a pretty intuitive implementation and use. It is implemented as a intrusive linked list. How this works is that a data structure will have a member that is node containing a pointer to the previous and next node. The benefit to this is that the list is not tied to any type as the nodes don't hold any data themselves, instead the data holds information on how to get to the nxe or previous node. This list structure is used everywhere in the Linux kernel and is very efficient. -### Task 2.3 : Associative Containers +## Associative Containers Associative containers are used for sorted data. They allow for very fast searching as well as efficient insertion, erasure and access. Associative containers work by ordering keys and (sometimes) mapping values to these keys. -#### Task 2.3.1 : Set +### Set -`std::set` is an ordered collections of unique keys usually sorted in ascending order. Search, insertion and erasure occur in logarithmic time ($O(\log{n})$). Sets also offer merging operations for combining two sets into a single set with all elements merged and sorted. Sets can be accessed using extraction methods that moves the _node-type_ that owns the key value out of the set and gives it to the caller. +`std::set` is an ordered collections of unique keys usually sorted in ascending order. Search, insertion and erasure occur in logarithmic time (\\( O(\log{n}) \\)). Sets also offer merging operations for combining two sets into a single set with all elements merged and sorted. Sets can be accessed using extraction methods that moves the _node-type_ that owns the key value out of the set and gives it to the caller. -> _node-type_ is an exposition only type that is implemented as part of the set. It is not to be used as an independent type. +> Note: _node-type_ is an exposition only type that is implemented as chapter of the set. It is not to be used as an independent type. ```cxx #include @@ -323,11 +296,11 @@ auto main() -> int [Exmaple](https://www.godbolt.org/z/P8E99q43c) -[`std::set` : cppreference](https://en.cppreference.com/w/cpp/container/set) +[`std::set`](https://en.cppreference.com/w/cpp/container/set) -#### Task 2.3.2 : Map +### Map -`std::map` is the most general associative container available in C++. Maps are made up of ordered key value pairs with strictly unique key values. Searching, key-indexing, insertion and erasure of elements is logarithmic ($O(\log{n})$) in time. Values are obtained using the associated key using indexing syntax. It also offers similar extraction and merging functionalities as sets. Maps in C++ are typically implemented as [Red-Black Trees](https://en.wikipedia.org/wiki/Red%E2%80%93black_tree). +`std::map` is the most general associative container available in C++. Maps are made up of ordered key value pairs with strictly unique key values. Searching, key-indexing, insertion and erasure of elements is logarithmic (\\( O(\log{n}) \\)) in time. Values are obtained using the associated key using indexing syntax. It also offers similar extraction and merging functionalities as sets. Maps in C++ are typically implemented as [Red-Black Trees](https://en.wikipedia.org/wiki/Red%E2%80%93black_tree). ```cxx #include @@ -377,11 +350,11 @@ auto main() -> int [Exmaple](https://www.godbolt.org/z/Wb5xPhraq) -[`std::map` : cppreference](https://en.cppreference.com/w/cpp/container/map) +[`std::map`](https://en.cppreference.com/w/cpp/container/map) -#### Task 2.3.3 : Multiset & Multimap +### Multiset & Multimap -Along with the regular set and map classes, C++ offers `std::multiset` and `std::multimap` which hold ordered keys (and values) but allow for duplicate keys. They offer pretty much the exact same interface as the key-exclusive counterparts except that the order of duplicate keys is the same order as their insertion. This order between duplicates remains constant unless the node holding a particular key (and value) is extracted and it's ownership given to the caller. Searching, insertion and erasure take logarithmic time ($O(\log{n})$). +Along with the regular set and map classes, C++ offers `std::multiset` and `std::multimap` which hold ordered keys (and values) but allow for duplicate keys. They offer pretty much the exact same interface as the key-exclusive counterparts except that the order of duplicate keys is the same order as their insertion. This order between duplicates remains constant unless the node holding a particular key (and value) is extracted and it's ownership given to the caller. Searching, insertion and erasure take logarithmic time (\\( O(\log{n}) \\)). ```cxx #include @@ -421,16 +394,16 @@ auto main() -> int [Exmaple](https://www.godbolt.org/z/ro5MaxeEG) -[`std::multiset` : cppreference](https://en.cppreference.com/w/cpp/container/multiset) -[`std::multimap` : cppreference](https://en.cppreference.com/w/cpp/container/multimap) +[`std::multiset`](https://en.cppreference.com/w/cpp/container/multiset) +[`std::multimap`](https://en.cppreference.com/w/cpp/container/multimap) -### Task 2.4 : Unordered Associative Containers +## Unordered Associative Containers Unordered associative containers are data structures that do not sort their key values but instead use a hashing function to create bucket based access to elements. Hashing functions are designed to avoid hash collisions however, many hashed data structures account for hash collisions. Hashing is the process of computing a discrete hash value for a key indicating the index in an internalised array or _bucket_. Which bucket a key (and value) is placed in relies solely on the result of hashing that key, with keys creating duplicate hash results being placed in the same bucket (typically). -#### Task 2.4.1 : Unordered Set +### Unordered Set -`std::unordered_set` is the first of our unordered associative containers. Unlike sets, hashed sets do not need to order their keys. Searching, insertion and erasure in a hashed set occurs in constant time ($O(1)$). Elements of a hashed set cannot be changes as this would invalidate the hash table. Instead erasure and insertion must be used instead. +`std::unordered_set` is the first of our unordered associative containers. Unlike sets, hashed sets do not need to order their keys. Searching, insertion and erasure in a hashed set occurs in constant time (\\( O(1) \\)). Elements of a hashed set cannot be changes as this would invalidate the hash table. Instead erasure and insertion must be used instead. ```cxx #include @@ -483,11 +456,11 @@ auto main() -> int [Exmaple](https://www.godbolt.org/z/G97n97r3G) -[`std::unordered_set` : cppreference](https://en.cppreference.com/w/cpp/container/unordered_set) +[`std::unordered_set`](https://en.cppreference.com/w/cpp/container/unordered_set) -#### Task 2.4.2 : Unordered Map +### Unordered Map -`std::unordered_map` is a hashed version of a regular map but like its hash set counterpart, instead of ordering keys it uses a hashing functions to create an index into buckets. Search, insertion and erasure all happen in constant time ($O(1)$). Unlike hashed sets, values can be accessed and inserted using key-based indexing. +`std::unordered_map` is a hashed version of a regular map but like its hash set counterpart, instead of ordering keys it uses a hashing functions to create an index into buckets. Search, insertion and erasure all happen in constant time (\\( O(1) \\)). Unlike hashed sets, values can be accessed and inserted using key-based indexing. ```cxx #include @@ -546,11 +519,11 @@ auto main() -> int [Exmaple](https://www.godbolt.org/z/qj5bq9fze) -[`std::unordered_map` : cppreference](https://en.cppreference.com/w/cpp/container/unordered_map) +[`std::unordered_map`](https://en.cppreference.com/w/cpp/container/unordered_map) -#### Task 2.4.3 : Unordered Multiset & Multimap +### Unordered Multiset & Multimap -Much like how there are sets and maps that can store duplicate keys, there are hashed versions of these data structures called `std::unordered_multiset` and `std::unordered_multimap` respectively. Search, insertion and erasure occur in constant time ($O(n)$). Hashed multimaps cannot be accessed using key-based indexing as it cannot be determined which key to return if duplicates exist. +Much like how there are sets and maps that can store duplicate keys, there are hashed versions of these data structures called `std::unordered_multiset` and `std::unordered_multimap` respectively. Search, insertion and erasure occur in constant time (\\( O(n) \\)). Hashed multimaps cannot be accessed using key-based indexing as it cannot be determined which key to return if duplicates exist. ```cxx #include @@ -615,12 +588,12 @@ auto main() -> int [Exmaple](https://www.godbolt.org/z/heKfcz6K1) -[`std::unordered_multiset` : cppreference](https://en.cppreference.com/w/cpp/container/unordered_multiset) -[`std::unordered_multimap` : cppreference](https://en.cppreference.com/w/cpp/container/unordered_multimap) +[`std::unordered_multiset`](https://en.cppreference.com/w/cpp/container/unordered_multiset) +[`std::unordered_multimap`](https://en.cppreference.com/w/cpp/container/unordered_multimap) -### Task 2.5 : Miscellaneous +## Miscellaneous -#### Task 2.5.1 : Bitset +### Bitset `std::bitset` allows for efficient storage of individually addressable bits. The size of a bitset is fixed at compile time allowing for bitsets to be evaluated in `constexpr` context. The standard bit manipulation operators are available for bitwise manipulation between bitsets. Bitset also allow for single bit access as well as testing of single or all bits in the bitset. Bitsets also have conversion methods for obtaining the string, and integral representations of the bits. Bitsets can be constructed from string representations of bits or or from binary literal integrals. The bit to the right is the least significant bit ie. the first bit. @@ -662,9 +635,9 @@ auto main() -> int [Exmaple](https://www.godbolt.org/z/1qnYTWxMb) -[`std::bitset` : cppreference](https://en.cppreference.com/w/cpp/utility/bitset) +[`std::bitset`](https://en.cppreference.com/w/cpp/utility/bitset) -#### Task 2.5.2 : Any +### Any `std::any` is a unique data structure that can hold any _Copy-Constructable_ type. It can also be changed to any new type simply through assignment. You can introspect the type contained as well as destroy the contained object. The only way to access the contained value is through an `std::any_cast<>` which will yield the value which is cast to the template type of the any cast. Any also comes with a factory function for creating a any object. @@ -698,11 +671,4 @@ auto main() -> int [Exmaple](https://www.godbolt.org/z/n57nYonqs) -[`std::any` : cppreference](https://en.cppreference.com/w/cpp/utility/any) - -## Links - -- [Previous Page : Iterators](/content/part6/tasks/iterators.md) -- [Next Page : Algorithms](/content/part6/tasks/algorithms.md) -- [Content](/content/README.md) -- [HOME](/README.md) +[`std::any`](https://en.cppreference.com/w/cpp/utility/any) diff --git a/content/part6/assignment/tyler-ring/README.md b/src/chapter6/examples/tyler-ring/README.md similarity index 100% rename from content/part6/assignment/tyler-ring/README.md rename to src/chapter6/examples/tyler-ring/README.md diff --git a/content/part6/assignment/tyler-ring/bpt.yaml b/src/chapter6/examples/tyler-ring/bpt.yaml similarity index 86% rename from content/part6/assignment/tyler-ring/bpt.yaml rename to src/chapter6/examples/tyler-ring/bpt.yaml index 5897b0f..f01e24a 100644 --- a/content/part6/assignment/tyler-ring/bpt.yaml +++ b/src/chapter6/examples/tyler-ring/bpt.yaml @@ -1,5 +1,5 @@ # Project 'tyler-ring' created by 'bpt new' -name: tyler-ring +name: ring version: 0.1.0 readme: README.md diff --git a/content/part6/assignment/tyler-ring/src/ring.main.cxx b/src/chapter6/examples/tyler-ring/src/ring.main.cxx similarity index 100% rename from content/part6/assignment/tyler-ring/src/ring.main.cxx rename to src/chapter6/examples/tyler-ring/src/ring.main.cxx diff --git a/content/part6/slides/hpp_part6.pdf b/src/chapter6/hpp_chapter6.pdf similarity index 51% rename from content/part6/slides/hpp_part6.pdf rename to src/chapter6/hpp_chapter6.pdf index 3469d5f..f41180d 100644 Binary files a/content/part6/slides/hpp_part6.pdf and b/src/chapter6/hpp_chapter6.pdf differ diff --git a/content/part6/slides/hpp_part6.pptx b/src/chapter6/hpp_chapter6.pptx similarity index 96% rename from content/part6/slides/hpp_part6.pptx rename to src/chapter6/hpp_chapter6.pptx index 45f0fa9..9c0dfdd 100644 Binary files a/content/part6/slides/hpp_part6.pptx and b/src/chapter6/hpp_chapter6.pptx differ diff --git a/src/chapter6/imgs/hpp_chapter6-01.png b/src/chapter6/imgs/hpp_chapter6-01.png new file mode 100644 index 0000000..f5ecd53 Binary files /dev/null and b/src/chapter6/imgs/hpp_chapter6-01.png differ diff --git a/content/part6/slides/imgs/hpp_part6-02.png b/src/chapter6/imgs/hpp_chapter6-02.png similarity index 100% rename from content/part6/slides/imgs/hpp_part6-02.png rename to src/chapter6/imgs/hpp_chapter6-02.png diff --git a/content/part6/slides/imgs/hpp_part6-03.png b/src/chapter6/imgs/hpp_chapter6-03.png similarity index 100% rename from content/part6/slides/imgs/hpp_part6-03.png rename to src/chapter6/imgs/hpp_chapter6-03.png diff --git a/content/part6/slides/imgs/hpp_part6-04.png b/src/chapter6/imgs/hpp_chapter6-04.png similarity index 100% rename from content/part6/slides/imgs/hpp_part6-04.png rename to src/chapter6/imgs/hpp_chapter6-04.png diff --git a/content/part6/slides/imgs/hpp_part6-05.png b/src/chapter6/imgs/hpp_chapter6-05.png similarity index 100% rename from content/part6/slides/imgs/hpp_part6-05.png rename to src/chapter6/imgs/hpp_chapter6-05.png diff --git a/content/part6/slides/imgs/hpp_part6-06.png b/src/chapter6/imgs/hpp_chapter6-06.png similarity index 100% rename from content/part6/slides/imgs/hpp_part6-06.png rename to src/chapter6/imgs/hpp_chapter6-06.png diff --git a/content/part6/slides/imgs/hpp_part6-07.png b/src/chapter6/imgs/hpp_chapter6-07.png similarity index 100% rename from content/part6/slides/imgs/hpp_part6-07.png rename to src/chapter6/imgs/hpp_chapter6-07.png diff --git a/content/part6/slides/imgs/hpp_part6-08.png b/src/chapter6/imgs/hpp_chapter6-08.png similarity index 100% rename from content/part6/slides/imgs/hpp_part6-08.png rename to src/chapter6/imgs/hpp_chapter6-08.png diff --git a/content/part6/slides/imgs/hpp_part6-09.png b/src/chapter6/imgs/hpp_chapter6-09.png similarity index 100% rename from content/part6/slides/imgs/hpp_part6-09.png rename to src/chapter6/imgs/hpp_chapter6-09.png diff --git a/content/part6/slides/imgs/hpp_part6-10.png b/src/chapter6/imgs/hpp_chapter6-10.png similarity index 100% rename from content/part6/slides/imgs/hpp_part6-10.png rename to src/chapter6/imgs/hpp_chapter6-10.png diff --git a/content/part6/slides/imgs/hpp_part6-11.png b/src/chapter6/imgs/hpp_chapter6-11.png similarity index 100% rename from content/part6/slides/imgs/hpp_part6-11.png rename to src/chapter6/imgs/hpp_chapter6-11.png diff --git a/content/part6/slides/imgs/hpp_part6-12.png b/src/chapter6/imgs/hpp_chapter6-12.png similarity index 100% rename from content/part6/slides/imgs/hpp_part6-12.png rename to src/chapter6/imgs/hpp_chapter6-12.png diff --git a/src/chapter6/imgs/hpp_chapter6-13.png b/src/chapter6/imgs/hpp_chapter6-13.png new file mode 100644 index 0000000..aa497d1 Binary files /dev/null and b/src/chapter6/imgs/hpp_chapter6-13.png differ diff --git a/content/part6/slides/imgs/hpp_part6-14.png b/src/chapter6/imgs/hpp_chapter6-14.png similarity index 100% rename from content/part6/slides/imgs/hpp_part6-14.png rename to src/chapter6/imgs/hpp_chapter6-14.png diff --git a/content/part6/slides/imgs/hpp_part6-15.png b/src/chapter6/imgs/hpp_chapter6-15.png similarity index 100% rename from content/part6/slides/imgs/hpp_part6-15.png rename to src/chapter6/imgs/hpp_chapter6-15.png diff --git a/content/part6/slides/imgs/hpp_part6-16.png b/src/chapter6/imgs/hpp_chapter6-16.png similarity index 100% rename from content/part6/slides/imgs/hpp_part6-16.png rename to src/chapter6/imgs/hpp_chapter6-16.png diff --git a/content/part6/slides/imgs/hpp_part6-17.png b/src/chapter6/imgs/hpp_chapter6-17.png similarity index 100% rename from content/part6/slides/imgs/hpp_part6-17.png rename to src/chapter6/imgs/hpp_chapter6-17.png diff --git a/content/part6/slides/imgs/hpp_part6-18.png b/src/chapter6/imgs/hpp_chapter6-18.png similarity index 100% rename from content/part6/slides/imgs/hpp_part6-18.png rename to src/chapter6/imgs/hpp_chapter6-18.png diff --git a/content/part6/slides/imgs/hpp_part6-19.png b/src/chapter6/imgs/hpp_chapter6-19.png similarity index 100% rename from content/part6/slides/imgs/hpp_part6-19.png rename to src/chapter6/imgs/hpp_chapter6-19.png diff --git a/content/part6/slides/imgs/hpp_part6-20.png b/src/chapter6/imgs/hpp_chapter6-20.png similarity index 100% rename from content/part6/slides/imgs/hpp_part6-20.png rename to src/chapter6/imgs/hpp_chapter6-20.png diff --git a/content/part6/slides/imgs/hpp_part6-21.png b/src/chapter6/imgs/hpp_chapter6-21.png similarity index 100% rename from content/part6/slides/imgs/hpp_part6-21.png rename to src/chapter6/imgs/hpp_chapter6-21.png diff --git a/content/part6/slides/imgs/hpp_part6-22.png b/src/chapter6/imgs/hpp_chapter6-22.png similarity index 100% rename from content/part6/slides/imgs/hpp_part6-22.png rename to src/chapter6/imgs/hpp_chapter6-22.png diff --git a/content/part6/slides/imgs/hpp_part6-23.png b/src/chapter6/imgs/hpp_chapter6-23.png similarity index 100% rename from content/part6/slides/imgs/hpp_part6-23.png rename to src/chapter6/imgs/hpp_chapter6-23.png diff --git a/content/part6/slides/imgs/hpp_part6-24.png b/src/chapter6/imgs/hpp_chapter6-24.png similarity index 100% rename from content/part6/slides/imgs/hpp_part6-24.png rename to src/chapter6/imgs/hpp_chapter6-24.png diff --git a/content/part6/slides/imgs/hpp_part6-25.png b/src/chapter6/imgs/hpp_chapter6-25.png similarity index 100% rename from content/part6/slides/imgs/hpp_part6-25.png rename to src/chapter6/imgs/hpp_chapter6-25.png diff --git a/content/part6/slides/imgs/hpp_part6-26.png b/src/chapter6/imgs/hpp_chapter6-26.png similarity index 100% rename from content/part6/slides/imgs/hpp_part6-26.png rename to src/chapter6/imgs/hpp_chapter6-26.png diff --git a/content/part6/slides/imgs/hpp_part6-27.png b/src/chapter6/imgs/hpp_chapter6-27.png similarity index 100% rename from content/part6/slides/imgs/hpp_part6-27.png rename to src/chapter6/imgs/hpp_chapter6-27.png diff --git a/content/part6/slides/imgs/hpp_part6-28.png b/src/chapter6/imgs/hpp_chapter6-28.png similarity index 100% rename from content/part6/slides/imgs/hpp_part6-28.png rename to src/chapter6/imgs/hpp_chapter6-28.png diff --git a/content/part6/slides/imgs/hpp_part6-29.png b/src/chapter6/imgs/hpp_chapter6-29.png similarity index 100% rename from content/part6/slides/imgs/hpp_part6-29.png rename to src/chapter6/imgs/hpp_chapter6-29.png diff --git a/content/part6/slides/imgs/hpp_part6-30.png b/src/chapter6/imgs/hpp_chapter6-30.png similarity index 100% rename from content/part6/slides/imgs/hpp_part6-30.png rename to src/chapter6/imgs/hpp_chapter6-30.png diff --git a/content/part6/slides/imgs/hpp_part6-31.png b/src/chapter6/imgs/hpp_chapter6-31.png similarity index 100% rename from content/part6/slides/imgs/hpp_part6-31.png rename to src/chapter6/imgs/hpp_chapter6-31.png diff --git a/content/part6/slides/imgs/hpp_part6-32.png b/src/chapter6/imgs/hpp_chapter6-32.png similarity index 100% rename from content/part6/slides/imgs/hpp_part6-32.png rename to src/chapter6/imgs/hpp_chapter6-32.png diff --git a/content/part6/slides/imgs/hpp_part6-33.png b/src/chapter6/imgs/hpp_chapter6-33.png similarity index 100% rename from content/part6/slides/imgs/hpp_part6-33.png rename to src/chapter6/imgs/hpp_chapter6-33.png diff --git a/content/part6/tasks/iterators.md b/src/chapter6/iterators.md similarity index 68% rename from content/part6/tasks/iterators.md rename to src/chapter6/iterators.md index 8e0c862..49cdf3c 100644 --- a/content/part6/tasks/iterators.md +++ b/src/chapter6/iterators.md @@ -1,27 +1,10 @@ # Iterators -## Contents - -- [Iterators](#iterators) - - [Contents](#contents) - - [Task 1](#task-1) - - [Task 1.1 : What is an iterator?](#task-11--what-is-an-iterator) - - [Task 1.2 : Iterator Categories](#task-12--iterator-categories) - - [Task 1.3 : Obtaining Iterators](#task-13--obtaining-iterators) - - [Task 1.4 : Iterator Functionalities](#task-14--iterator-functionalities) - - [Task 1.4.1 : Common Operator Interface](#task-141--common-operator-interface) - - [Task 1.4.2 : Iterator Functions](#task-142--iterator-functions) - - [Task 1.5 : Sentinels](#task-15--sentinels) - - [Task 1.6 : Iterator Adaptors](#task-16--iterator-adaptors) - - [Links](#links) - -## Task 1 - -### Task 1.1 : What is an iterator? +## What is an iterator? An iterator is an abstraction for representing an item, element, value etc. in a collection or container of values that also has some notion how to get to a obtain or yield a new item from the container. In C++ iterators a lot like pointers in the sense that they hold some value, usually the location of it and has a means of either yielding the value for reading or allows for writing to that value. -### Task 1.2 : Iterator Categories +## Iterator Categories There are 6 main iterator categories considered in C++. Each subsequent iterator category builds upon the previous categories requirements with increasingly more requirements. @@ -54,7 +37,7 @@ There are 6 main iterator categories considered in C++. Each subsequent iterator Input - ❓(might support writing) + might support writing ✅ ✅ @@ -64,7 +47,7 @@ There are 6 main iterator categories considered in C++. Each subsequent iterator Forward
(Satisfies Input) - + ✅ ✅ ✅ ✅ @@ -74,7 +57,7 @@ There are 6 main iterator categories considered in C++. Each subsequent iterator Bidirectional
(Satisfies Forward) - + ✅ ✅ ✅ ✅ @@ -84,7 +67,7 @@ There are 6 main iterator categories considered in C++. Each subsequent iterator Random Access
(Satisfies Bidirectional) - + ✅ ✅ ✅ ✅ @@ -94,7 +77,7 @@ There are 6 main iterator categories considered in C++. Each subsequent iterator Contiguous
(Satisfies Random Access) - + ✅ ✅ ✅ ✅ @@ -109,7 +92,7 @@ There are 6 main iterator categories considered in C++. Each subsequent iterator Before C++20, there were empty structs used as tags to help categorise an iterator into its respective category. Since C++ there have been concepts introduces to perform this check more elegantly along with other iterator-related concepts to all for anything modelling an iterator to satisfy the constraints. -### Task 1.3 : Obtaining Iterators +## Obtaining Iterators Almost all collections or containers have iterators to their first and last element. To obtain these iterator from any container kinds we call the `std::begin()` and `std::end` functions from the `` header respectively. There are also constant and reverse and constant reverse versions of the functions. @@ -133,17 +116,17 @@ auto main() -> int [Example](https://www.godbolt.org/z/MG7q3d63a) -- [`` : cppreference](https://en.cppreference.com/w/cpp/header/iterator) -- [`std::begin()` & `std::cbegin()` : cppreference](https://en.cppreference.com/w/cpp/iterator/begin) -- [`std::end()` & std::cend()` : cppreference](https://en.cppreference.com/w/cpp/iterator/end) -- [`std::rbegin()` & std::crbegin()` : cppreference](https://en.cppreference.com/w/cpp/iterator/rbegin) -- [`std::rend()` & std::crend()` : cppreference](https://en.cppreference.com/w/cpp/iterator/rend) +- [``](https://en.cppreference.com/w/cpp/header/iterator) +- [`std::begin()` & `std::cbegin()`](https://en.cppreference.com/w/cpp/iterator/begin) +- [`std::end()` & std::cend()`](https://en.cppreference.com/w/cpp/iterator/end) +- [`std::rbegin()` & std::crbegin()`](https://en.cppreference.com/w/cpp/iterator/rbegin) +- [`std::rend()` & std::crend()`](https://en.cppreference.com/w/cpp/iterator/rend) -### Task 1.4 : Iterator Functionalities +## Iterator Functionalities There are a few ways to interact with an iterator directly. One is to use the overloaded operators for the iterator object. Most iterators implement and overload the same operator set that is used by pointers. The other way is to use functions to interact with iterators, allowing for a more generic interface if a iterator doesn't support the common operator overload set and the implementer preferred to overload the functions. The only way to yield or write to the item held by an iterator is to use the dereference operator `*`. -#### Task 1.4.1 : Common Operator Interface +### Common Operator Interface | Operation | | | | |:-----------:|:-------:|:--------:|:--------:| @@ -154,7 +137,7 @@ There are a few ways to interact with an iterator directly. One is to use the ov | advance | `i + n` | `i - n` | | | index | `i[n]` | | | -> Where `i` is an iterator object +> Note: Where `i` is an iterator object ```cxx #include @@ -186,7 +169,7 @@ auto main() -> int [Example](https://www.godbolt.org/z/jeGjnrWvn) -#### Task 1.4.2 : Iterator Functions +### Iterator Functions There are four functions involved in manipulating an object of iterator kind. These are used to move an iterator between elements. @@ -225,12 +208,12 @@ auto main() -> int [Example](https://www.godbolt.org/z/P17PEnsaE) -- [`std::next()` : cppreference](https://en.cppreference.com/w/cpp/iterator/next) -- [`std::prev()` : cppreference](https://en.cppreference.com/w/cpp/iterator/prev) -- [`std::distance()` : cppreference](https://en.cppreference.com/w/cpp/iterator/distance) -- [`std::advance()` : cppreference](https://en.cppreference.com/w/cpp/iterator/advance) +- [`std::next()`](https://en.cppreference.com/w/cpp/iterator/next) +- [`std::prev()`](https://en.cppreference.com/w/cpp/iterator/prev) +- [`std::distance()`](https://en.cppreference.com/w/cpp/iterator/distance) +- [`std::advance()`](https://en.cppreference.com/w/cpp/iterator/advance) -### Task 1.5 : Sentinels +## Sentinels Iterators are able to move through a container indefinitely however this can lead to iterators being dereferenced for a value that doesn't belong to the container. To fix this, we need some notion of the end of a container. Sentinels are a kind that behaves like a marker representing the end of a container. There are many different things you can use as a sentinel from specific values that appear in a container (`\0` is used as a sentinel for char slices in C), to iterators. Before C++20, the 'end' iterator was the most common sentinel kind used. The iterator holds the item that is one-past-the-end of a container. When another iterator reaches it the container has been exhausted. Since C++20, the notion of the end of a container has been formalised to be sentinels over 'end' iterators. This allows for containers to be infinite with an unreachable sentinel type or have regular bounds. @@ -253,29 +236,22 @@ auto main() -> int [Example](https://www.godbolt.org/z/9dzsjn1eM) -- [`std::default_sentinel_t` : cppreference](https://en.cppreference.com/w/cpp/iterator/default_sentinel_t) -- [`std::unreachable_sentinel_t` : cppreference](https://en.cppreference.com/w/cpp/iterator/unreachable_sentinel_t) -- [`std::move_sentinel` : cppreference](https://en.cppreference.com/w/cpp/iterator/move_sentinel) +- [`std::default_sentinel_t`](https://en.cppreference.com/w/cpp/iterator/default_sentinel_t) +- [`std::unreachable_sentinel_t`](https://en.cppreference.com/w/cpp/iterator/unreachable_sentinel_t) +- [`std::move_sentinel`](https://en.cppreference.com/w/cpp/iterator/move_sentinel) -### Task 1.6 : Iterator Adaptors +## Iterator Adaptors There are a few iterator adaptors in the C++ standard library allowing for regular iterators, often supplied by container kind types have certain operational semantics. This include a reverse, inserter, counted and move iterators. This allows for efficient operations between containers and containers to be implemented through iterators. Many of these iterators come with a factory function (often prefixed with `make_`) that can make the desired iterator and perform the necessary argument type deductions. -- [`std::reverse_iterator` : cppreference](https://en.cppreference.com/w/cpp/iterator/reverse_iterator) -- [`std::move_iterator` : cppreference](https://en.cppreference.com/w/cpp/iterator/move_iterator) -- [`std::common_iterator` : cppreference](https://en.cppreference.com/w/cpp/iterator/common_iterator) -- [`std::counted_iterator` : cppreference](https://en.cppreference.com/w/cpp/iterator/counted_iterator) -- [`std::back_insert_iterator` : cppreference](https://en.cppreference.com/w/cpp/iterator/back_insert_iterator) -- [`std::front_insert_iterator` : cppreference](https://en.cppreference.com/w/cpp/iterator/front_insert_iterator) -- [`std::insert_iterator` : cppreference](https://en.cppreference.com/w/cpp/iterator/insert_iterator) -- [`std::istream_iterator` : cppreference](https://en.cppreference.com/w/cpp/iterator/istream_iterator) -- [`std::ostream_iterator` : cppreference](https://en.cppreference.com/w/cpp/iterator/ostream_iterator) -- [`std::istreambuf_iterator` : cppreference](https://en.cppreference.com/w/cpp/iterator/istreambuf_iterator) -- [`std::ostreambuf_iterator` : cppreference](https://en.cppreference.com/w/cpp/iterator/ostreambuf_iterator) - -## Links - -- [Previous Page : Part 6](/content/part6/README.md) -- [Next Page : Data Structures](/content/part6/tasks/data-structures.md) -- [Content](/content/README.md) -- [HOME](/README.md) +- [`std::reverse_iterator`](https://en.cppreference.com/w/cpp/iterator/reverse_iterator) +- [`std::move_iterator`](https://en.cppreference.com/w/cpp/iterator/move_iterator) +- [`std::common_iterator`](https://en.cppreference.com/w/cpp/iterator/common_iterator) +- [`std::counted_iterator`](https://en.cppreference.com/w/cpp/iterator/counted_iterator) +- [`std::back_insert_iterator`](https://en.cppreference.com/w/cpp/iterator/back_insert_iterator) +- [`std::front_insert_iterator`](https://en.cppreference.com/w/cpp/iterator/front_insert_iterator) +- [`std::insert_iterator`](https://en.cppreference.com/w/cpp/iterator/insert_iterator) +- [`std::istream_iterator`](https://en.cppreference.com/w/cpp/iterator/istream_iterator) +- [`std::ostream_iterator`](https://en.cppreference.com/w/cpp/iterator/ostream_iterator) +- [`std::istreambuf_iterator`](https://en.cppreference.com/w/cpp/iterator/istreambuf_iterator) +- [`std::ostreambuf_iterator`](https://en.cppreference.com/w/cpp/iterator/ostreambuf_iterator) diff --git a/content/part6/tasks/ranges.md b/src/chapter6/ranges.md similarity index 81% rename from content/part6/tasks/ranges.md rename to src/chapter6/ranges.md index 8258e66..40fa5cd 100644 --- a/content/part6/tasks/ranges.md +++ b/src/chapter6/ranges.md @@ -1,17 +1,6 @@ # Ranges -## Contents - -- [Ranges](#ranges) - - [Contents](#contents) - - [Task 4](#task-4) - - [Task 4.1 : What is a range?](#task-41--what-is-a-range) - - [Task 4.2 : Range Concepts \& Categories](#task-42--range-concepts--categories) - - [Links](#links) - -## Task 4 - -### Task 4.1 : What is a range? +## What is a range? What is a range? So far we have considered a range as a pair of iterators pointing to the beginning and end of a collection of elements. C++ formalised this idea by defining a range as an iterator and sentinel pair. This allowed for C++ to introduced the Ranges Library. One problem with the main C++ standard algorithms library is that is was made in the 1990's. As such the algorithms were designed with implicit constraints but had no way to enforce them. Because of backwards compatibility the standard library algorithms could not be updated to use concepts, instead C++ introduces new overloads for the standard library algorithms in the nested `std::ranges` namespace. Along with the original iterator (now iterator and sentinel design) interface, these algorithms accept a range object as an input sequence (output ranges are still modelled using an output iterator). This allowed for algorithm calls to be much simpler while also enforcing constraints on ranges. Almost all of the original algorithms have a `std::ranges` counterpart. If you can use the range version, even with the iterator interfaces as they impose stricter but safer requirements on the iterators to ensure that algorithms behave correctly. Range algorithms also support projections, allowing for in-place temporary transformations of data. This is defaulted to `std::identity`. All containers in the C++ standard library are considered valid ranges. @@ -34,10 +23,10 @@ auto main() -> int [Example](https://www.godbolt.org/z/6bdKa63j4) -- [Constrained Algorithms : cppreference](https://en.cppreference.com/w/cpp/algorithm/ranges) -- [`std::ranges::transform` : cppreference](https://en.cppreference.com/w/cpp/algorithm/ranges/transform) +- [Constrained Algorithms](https://en.cppreference.com/w/cpp/algorithm/ranges) +- [`std::ranges::transform`](https://en.cppreference.com/w/cpp/algorithm/ranges/transform) -### Task 4.2 : Range Concepts & Categories +## Range Concepts & Categories Like iterators, there are different categories describing the requirements of a range type. These categories have concept definitions so you can constrain your own algorithms. Here is a table of different sequence containers and how they match up against the different range concepts. @@ -50,10 +39,3 @@ Like iterators, there are different categories describing the requirements of a | `std::ranges::contiguous_range` | | | | ✅ | ✅ | > Note: `std::output_range` is not shown here. This is because an `std::output_range` is similar to `std::input_range` except it models writing to as opposed to reading. - -## Links - -- [Previous Page : Algorithms](/content/part6/tasks/algorithms.md) -- [Next Page : Views](/content/part6/tasks/views.md) -- [Content](/content/README.md) -- [HOME](/README.md) diff --git a/src/chapter6/slides6.md b/src/chapter6/slides6.md new file mode 100644 index 0000000..9bcec5e --- /dev/null +++ b/src/chapter6/slides6.md @@ -0,0 +1,35 @@ +# Slides + +![Slides 01](./imgs/hpp_chapter6-01.png) +![Slides 02](./imgs/hpp_chapter6-02.png) +![Slides 03](./imgs/hpp_chapter6-03.png) +![Slides 04](./imgs/hpp_chapter6-04.png) +![Slides 05](./imgs/hpp_chapter6-05.png) +![Slides 06](./imgs/hpp_chapter6-06.png) +![Slides 07](./imgs/hpp_chapter6-07.png) +![Slides 08](./imgs/hpp_chapter6-08.png) +![Slides 09](./imgs/hpp_chapter6-09.png) +![Slides 10](./imgs/hpp_chapter6-10.png) +![Slides 11](./imgs/hpp_chapter6-11.png) +![Slides 12](./imgs/hpp_chapter6-12.png) +![Slides 13](./imgs/hpp_chapter6-13.png) +![Slides 14](./imgs/hpp_chapter6-14.png) +![Slides 15](./imgs/hpp_chapter6-15.png) +![Slides 16](./imgs/hpp_chapter6-16.png) +![Slides 17](./imgs/hpp_chapter6-17.png) +![Slides 18](./imgs/hpp_chapter6-18.png) +![Slides 19](./imgs/hpp_chapter6-19.png) +![Slides 20](./imgs/hpp_chapter6-20.png) +![Slides 21](./imgs/hpp_chapter6-21.png) +![Slides 22](./imgs/hpp_chapter6-22.png) +![Slides 23](./imgs/hpp_chapter6-23.png) +![Slides 24](./imgs/hpp_chapter6-24.png) +![Slides 25](./imgs/hpp_chapter6-25.png) +![Slides 26](./imgs/hpp_chapter6-26.png) +![Slides 27](./imgs/hpp_chapter6-27.png) +![Slides 28](./imgs/hpp_chapter6-28.png) +![Slides 29](./imgs/hpp_chapter6-29.png) +![Slides 30](./imgs/hpp_chapter6-30.png) +![Slides 31](./imgs/hpp_chapter6-31.png) +![Slides 32](./imgs/hpp_chapter6-32.png) +![Slides 33](./imgs/hpp_chapter6-33.png) diff --git a/src/chapter6/task3.md b/src/chapter6/task3.md new file mode 100644 index 0000000..b865513 --- /dev/null +++ b/src/chapter6/task3.md @@ -0,0 +1,56 @@ +# Task 3 : Circular Buffer + +This assignment is a tricker one. Your job is to implement a [circular buffer](https://en.wikipedia.org/wiki/Circular_buffer) or a ring buffer. Circular buffers are First-In-First-Out buffers + +## Requirements + +- Must be a `class` (or `struct`). +- Must have these constructors + - Default + - Copy + - Move + - Assignment Copy + - Assignment Move + - A destructor +- Must be templated for any element type `T`. +- Can either be dynamic in size (adds memory as it needs) or semi-static (fixed maximum but variable current size) +- Methods for pushing in a new element to the front and popping the oldest from the back. +- Introspection methods + - Current size + - Current capacity + - One that returns a pointer to the first element + - A method to check if the buffer is full + - A method to check if the buffer is empty +- Element access + - _at-like_ method with index checking + - subscript operator overload (`[]`) + +You can manually create and destroy the memory, use smart pointers or use a container to store the underlying memory. + +### Optional + +- Have a custom iterator type with the relevant methods in the circular buffer for obtaining them. +- front and and back element access. +- Equality (`==`) and inequality (`!=`) operator overloads. +- Output stream operator overload (`>>`). +- Constructor and assignment operator overload (`=`) that take an `std::initializer_list`. +- Uses an allocator (eg. `std::allocator`) to allocate memory. +- Takes an additional template argument that correlates to a generic allocator type. +- Takes an additional template parameter that correlates to the type of the underlying container used to for storage of elements (eg. `std::vector`) making the circular buffer an adaptor. + +## Submitting + +You can use Godbolt or bpt to build and test your struct. Once you have created your implementation: + +- Clone this repo using `git clone https://github.com/MonashDeepNeuron/HPP.git`. +- Create a new branch using `git checkout -b triple/`. +- Create a folder in the `/submissions` directory with your name. +- Create a folder with the name of this task. +- Copy your mini project into this directory (bpt setup, cmake scripts etc.) with a `README.md` or comment in the code on how to run the program (verify it still works). There is a sample header file in `/templates` that you can use. +- Go to and click 'New pull request'. +- Change the branches in the drop down so that your branch is going into `main` and `Create new pull request. +- Give the pull request a title and briefly describe what you were able to implement and any struggles you had. +- On the right side-panel, under the 'Assignees' section, click the cog and assign me. +- Click 'Create pull request' and I'll take it from there. + +> Note: If you created a GodBolt instance, put the link in a comment at the top of the file (under your copy comments). This is generated by clicking the `share` button in the top-right-most corner of the webpage and clicking the 'short link' option. diff --git a/src/chapter6/views.md b/src/chapter6/views.md new file mode 100644 index 0000000..0b5e6c1 --- /dev/null +++ b/src/chapter6/views.md @@ -0,0 +1,124 @@ +# Views + +## What is a View? + +A view is a simple abstraction on a range. Views can be thought of as a reference or pointer to a range that is cheap to copy, move, assign and destroy. Views allow for a ranges to be used in a lazy evaluation contexts. Views are found in the `std::ranges` namespace from the `` header, often with a '_view' suffix or can be found in the `std::views` namespace of the same header without the suffix. Views can be passed to range based algorithms or even used as the range evaluated in a range-for. + +Ranges can be created from an iterator and sentinel pair or a range using `std::subrange`. + +```cxx +#include +#include +#include +#include + +auto main() -> int +{ + auto v = std::vector{ 1, 2, 3, 4, 5 }; + + /// Note: This is unnecessary and is only a showcase + for (const auto& e : std::ranges::subrange(v.begin(), v.end())) + std::cout << e << " "; + + std::cout << std::endl; + + return 0; +} +``` + +[Example](https://www.godbolt.org/z/sE5Eq5a3z) + +## Lazy Evaluation + +What is lazy evaluation? Lazy evaluation is the process of delaying evaluation of functions and expressions until the result of the evaluation is actually needed. This reduces the amount of memory, compute cycles and evaluations the function undergoes and allows for easier composition of functions. + +## Factories + +Some views are used convert ranges and scalars into views. These views are called factories as they generate a view from its arguments. + +- `std::views::empty` - A view containing no element. It still takes an unused template type parameter. +- `std::views::single` - A owning view containing a single element. +- `std::views::iota` - A range factory, generating a elements from a repeatedly incremented initial value. This view can be bound to a final value or unbounded, generating an infinite view. Bounded iota views are exclusive ie. the bound is excluded from the resulting range. +- `std::views::istream` - A range factory, generating elements by repeated calls to `>>` on a input stream eg. `std::cin`. + +```cxx +#include +#include +#include + +auto main() -> int +{ + /// Prints "0 1 2 3 4 5 6 7 8 9 10" + std::ranges::copy(std::views::iota(0, 11), std::ostream_iterator(std::cout, " ")); + + return 0; +} +``` + +[Example](https://www.godbolt.org/z/brff8rY5T) + +- [`std::views::empty`](https://en.cppreference.com/w/cpp/ranges/empty_view) +- [`std::views::single`](https://en.cppreference.com/w/cpp/ranges/single_view) +- [`std::views::iota`](https://en.cppreference.com/w/cpp/ranges/iota_view) +- [`std::views::istream`](https://en.cppreference.com/w/cpp/ranges/basic_istream_view) + +## Range Adaptors, Composition & The Pipe Operators + +So far views aren't all that interesting. The true power of views comes from their ability to be composed. Composition allows for views to be combined to build more complex views over data while still adhering to lazy evaluation. Instead of evaluating each function one at a time a single function, which is the composition of all the view functions gets evaluated once for every access to the element. Views are composed using the pipe operator (`|`) and are read from left-to-right as opposed to inside-out. This makes function composition far more expressible and extensible. Range (including containers) or view object are 'piped' to the range adaptor with the resulting view; when evaluated, applying the range adaptor on the every element. + +## Standard View Range Adaptors + +- `std::views::transform` - a range adapter whose resulting view maps an unary function to the input range. +- `std::views::filter` - a range adaptor that whose resulting view excludes any element that do not satisfy an unary predicate. +- `std::views::reverse` - a range adaptor returning a view of the input range as if its order was reversed. +- `std::views::take` - a range adaptor whose resulting view take only \\( n \\) elements from the input range. Performs bound checks to ensure that it doesn't take more elements then the view can see. +- `std::views::take_while` - a range adaptor whose resulting view contains every element until an unary predicate returns `false`. +- `std::views::drop` - a range adapter whose resulting view skips the first \\( n \\) elements from a input range. +- `std::views::drop_while` - a range adaptor whose resulting view starts at the first element for which the unary predicate evaluates `false`. +- `std::views::join` - a range adaptor whose resulting view will flatten nested range or view object a single view. +- `std::views::split` - a range adaptor whose resulting view contains subranges split by a given deliminator. Is not entirely lazy and will eagerly move forward through the view at each iteration during evaluation. +- `std::views::lazy_split` - a range adaptor whose resulting view contains subranges split by a given deliminator Is entirely lazy evaluated but is unable to model the subranges as a [common range](https://en.cppreference.com/w/cpp/ranges/common_range)(a range with the same type for the iterator and sentinel) and cannot be used in algorithms expecting a bidirectional range (or higher). +- `std::views::common` - a range adaptor whose resulting view adapts the input range to have the same type for its iterator and sentinels. +- `std::views::element` - a range adaptor that accepts an input range with _Tuple-Like_ elements and whose resulting view contains the \\( Nth \\) entry from every _Tuple-Like_ element of the input range. +- `std::views::keys` - a range adaptor who is a specialisations of `std::views::elements` taking the \\( 0th \\) entry of a view of _Tuple-Like_ elements. This can be used to obtain a view of just the keys of an associative container. +- `std::views::values` - a range adaptor who is a specialisations of `std::views::elements` taking the \\( 1st \\) entry of a view of _Tuple-Like_ elements. This can be used to obtain a view of just the values of an associative container. + +```cxx +#include +#include +#include + +auto square = [](const auto& x){ return x * x; }; +auto even = [](const auto& x){ return x % 2 == 0; }; + +auto main() -> int +{ + auto nums = std::views::iota(0) + | std::views::transform(square) + | std::views::filter(even) + | std::views::take(10); + + std::ranges::copy(nums, std::ostream_iterator(std::cout, " ")); + + std::cout << std::endl; + + return 0; +} +``` + +[Example](https://www.godbolt.org/z/3fdW1P7hj) + +- [`std::views::transform`](https://en.cppreference.com/w/cpp/ranges/transform_view) +- [`std::views::filter`](https://en.cppreference.com/w/cpp/ranges/filter_view) +- [`std::views::reverse`](https://en.cppreference.com/w/cpp/ranges/reverse_view) +- [`std::views::take`](https://en.cppreference.com/w/cpp/ranges/take_view) +- [`std::views::take_while`](https://en.cppreference.com/w/cpp/ranges/take_while_view) +- [`std::views::drop`](https://en.cppreference.com/w/cpp/ranges/drop_view) +- [`std::views::drop_while`](https://en.cppreference.com/w/cpp/ranges/drop_while_view) +- [`std::views::join`](https://en.cppreference.com/w/cpp/ranges/join_view) +- [`std::views::split`](https://en.cppreference.com/w/cpp/ranges/split_view) +- [`std::views::lazy_split`](https://en.cppreference.com/w/cpp/ranges/lazy_split_view) +- [`std::views::common`](https://en.cppreference.com/w/cpp/ranges/common_view) +- [`std::views::elements`](https://en.cppreference.com/w/cpp/ranges/elements_view) +- [`std::views::keys`](https://en.cppreference.com/w/cpp/ranges/keys_view) +- [`std::views::values`](https://en.cppreference.com/w/cpp/ranges/values_view) diff --git a/src/chapter7/README.md b/src/chapter7/README.md new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/chapter7/README.md @@ -0,0 +1 @@ + diff --git a/content/part7/tasks/async.md b/src/chapter7/async.md similarity index 78% rename from content/part7/tasks/async.md rename to src/chapter7/async.md index a62ed2d..e4d9ade 100644 --- a/content/part7/tasks/async.md +++ b/src/chapter7/async.md @@ -1,18 +1,8 @@ -# Async +# Asynchronous Programming -## Contents +Asynchronous programming is the ability to run functions an computations simultaneously while being able to communicate the results between different functions and execution paths. -- [Async](#async) - - [Contents](#contents) - - [Task 5](#task-5) - - [Task 5.1 : Futures and Promises](#task-51--futures-and-promises) - - [Task 5.2 : Async](#task-52--async) - - [Task 5.3 : Packaged Tasks](#task-53--packaged-tasks) - - [Links](#links) - -## Task 5 - -### Task 5.1 : Futures and Promises +## Futures and Promises A promise; represented by the class `std::promise`, is a object that stores a value or exception that is retrieved by a `std::future` object. Semantically, this means that a; generally asynchronous function has promised a value to the caller of the asynchronous function but however, does not yet have the value. The future of a promised value is obtained directly from the `std::promise` object. The caller of the promised value can query, wait for or extract the value from the corresponding `std::future` object however, these may block if the result is not yet ready. The timeout methods will return a `std::future_status` object which is an enum indicating if the wait timed out, if the future is deferred (_lazy_ loading) or ready. The value of a promise is communicated via a shared memory state between the `std::future` and `std::promise` objects. This shared state cannot be shared between different threads meaning that only one `std::future` can be used to obtain the result of a promised value. To enforce this `std::future` is move-only. A shared future can be obtained by called `std::future::share` to create a `std::shared_future` which claims ownership of the shared state such that the future can be copied between different threads. Promises and futures are found in the `` header. @@ -67,16 +57,16 @@ Result: 9 Took: 3000 ms ``` -[Example](/content/part7/examples/async/src/futures.main.cxx) +[Example](./examples/async/src/futures.main.cxx) -- [`std::future` : cppreference](https://en.cppreference.com/w/cpp/thread/future) -- [`std::shared_future` : cppreference](https://en.cppreference.com/w/cpp/thread/shared_future) -- [`std::future` : cppreference](https://en.cppreference.com/w/cpp/thread/shared_future) -- [`std::promise` : cppreference](https://en.cppreference.com/w/cpp/thread/promise) +- [`std::future`](https://en.cppreference.com/w/cpp/thread/future) +- [`std::shared_future`](https://en.cppreference.com/w/cpp/thread/shared_future) +- [`std::future`](https://en.cppreference.com/w/cpp/thread/shared_future) +- [`std::promise`](https://en.cppreference.com/w/cpp/thread/promise) -### Task 5.2 : Async +## Async -Another way to create asynchronous functions without having to deal with threads directly is to use `std::async`. This function will create an asynchronous task that will run according to a launch policy. The standard only defines two policies, this being `std::launch::async`; which will run a function a separate thread, or `std::launch::deferred` which will run the function lazily on the calling thread the first time the value is requested. `std::async` returns a `std::future` object that is used to query, wait for or extract the result of the asynchronous function. `std::async` is found in the `` header. +Another way to create asynchronous functions without having to deal with threads directly is to use `std::async`. This function will create an asynchronous section that will run according to a launch policy. The standard only defines two policies, this being `std::launch::async`; which will run a function a separate thread, or `std::launch::deferred` which will run the function lazily on the calling thread the first time the value is requested. `std::async` returns a `std::future` object that is used to query, wait for or extract the result of the asynchronous function. `std::async` is found in the `` header. ```cxx #include @@ -190,14 +180,14 @@ Time: 153180 us Result: 10000000.68113 ``` -[Example](/content/part7/examples/async/src/async.main.cxx) +[Example](./examples/async/src/async.main.cxx) -- [`std::async` : cppreference](https://en.cppreference.com/w/cpp/thread/async) -- [`std::launch` : cppreference](https://en.cppreference.com/w/cpp/thread/launch) +- [`std::async`](https://en.cppreference.com/w/cpp/thread/async) +- [`std::launch`](https://en.cppreference.com/w/cpp/thread/launch) -### Task 5.3 : Packaged Tasks +## Packaged Sections -The final way to create a future value is the use of `std::packaged_task`. This wraps a callable such that its result type is held in a shared state that can be accesses by a `std::future` object created from the task. `std::packaged_task` objects can be moved to `std::thread` and `std::jthread` objects so that the return value of a task can be acquired from a thread (which usually discards it). `std::packaged_task` is move-only and is found in the `` header. +The final way to create a future value is the use of `std::packaged_task`. This wraps a callable such that its result type is held in a shared state that can be accesses by a `std::future` object created from the section. `std::packaged_task` objects can be moved to `std::thread` and `std::jthread` objects so that the return value of a section can be acquired from a thread (which usually discards it). `std::packaged_task` is move-only and is found in the `` header. ```cxx #include @@ -249,13 +239,6 @@ Result: 9 Took: 300 ms ``` -[Example](/content/part7/examples/async/src/packaged_task.main.cxx) - -[`std::packaged_task` : cppreference](https://en.cppreference.com/w/cpp/thread/packaged_task) - -## Links +[Example](./examples/async/src/packaged_task.main.cxx) -- [Previous Page : Mutexes & Locks](/content/part7/tasks/mutexes.md) -- [Back to Part 7](/content/part7/README.md) -- [Content](/content/README.md) -- [HOME](/README.md) +[`std::packaged_task`](https://en.cppreference.com/w/cpp/thread/packaged_task) diff --git a/content/part7/tasks/atomics.md b/src/chapter7/atomics.md similarity index 64% rename from content/part7/tasks/atomics.md rename to src/chapter7/atomics.md index 71cd8ab..391ca13 100644 --- a/content/part7/tasks/atomics.md +++ b/src/chapter7/atomics.md @@ -1,21 +1,10 @@ # Atomics -## Contents +## Data Races & Shared Resources -- [Atomics](#atomics) - - [Contents](#contents) - - [Task 2](#task-2) - - [Task 2.1 : Data Races \& Shared Resources](#task-21--data-races--shared-resources) - - [Task 2.2 : Atomic Types](#task-22--atomic-types) - - [Links](#links) +In any program, data is shared across multiple chapters of the system. This is largely not a problem because there is only a single thread accessing the data meaning all operations occur sequentially. This guarantees that data will only every be read from or written to but not both at the same time. However, when a program starts to introduce concurrency data now may be shared between different execution processes. This means that data can be read from or written at the same time causing a _Race Condition_. _Race Conditions_ are UB in almost all programming languages as there is no way for the compiler or interpreter to tell which operation will happen first. There are many techniques to prevent and outright disallow race conditions from occur while still allowing for data to exist in a shared state. The first of which we will look at is `std::atomic`. -## Task 2 - -### Task 2.1 : Data Races & Shared Resources - -In any program, data is shared across multiple parts of the system. This is largely not a problem because there is only a single thread accessing the data meaning all operations occur sequentially. This guarantees that data will only every be read from or written to but not both at the same time. However, when a program starts to introduce concurrency data now may be shared between different execution processes. This means that data can be read from or written at the same time causing a _Race Condition_. _Race Conditions_ are UB in almost all programming languages as there is no way for the compiler or interpreter to tell which operation will happen first. There are many techniques to prevent and outright disallow race conditions from occur while still allowing for data to exist in a shared state. The first of which we will look at is `std::atomic`. - -### Task 2.2 : Atomic Types +## Atomic Types `std::atomic` is a template class type that represents an _atomic-object_. Reading from and writing to an _atomic-object_ at the same time is considered well defined. This is because operations are performed atomically meaning that no race conditions can occur as the [memory order](https://en.cppreference.com/w/cpp/atomic/memory_order) must be specified. `std::atomic` can accept template types that are integrals, floating-points, pointers, `std::shared_ptr` or `std::weak_ptr`. It can also accept custom types that are trivially copyable and copy and move constructible/assignable. `std::atomic` also can be used to synchronize execution by blocking and notifying different executions processes. `std::atomic` itself cannot be copied or move. There is also `std::atomic_ref` which creates a reference to existing data for which all operations are atomic. The referred object's lifetime must exceed that of the atomic reference the underlying object can only be access through atomic references for the lifetime of all atomic references. `std::atomic_ref` can by copied. @@ -89,14 +78,7 @@ Time: 1,699,214 us Atomic Count: 100,000,007 ``` -[Example](/content/part7/examples/atomic/src/atomic.main.cxx) - -- [`std::atomic` : cppreference](https://en.cppreference.com/w/cpp/atomic/atomic) -- [`std::atomic_ref` : cppreference](https://en.cppreference.com/w/cpp/atomic/atomic_ref) - -## Links +[Example](./examples/atomic/src/atomic.main.cxx) -- [Previous Page : Parallel Algorithms](/content/part7/tasks/parallel-alg.md) -- [Next Page : Threads](/content/part7/tasks/threads.md) -- [Content](/content/README.md) -- [HOME](/README.md) +- [`std::atomic`](https://en.cppreference.com/w/cpp/atomic/atomic) +- [`std::atomic_ref`](https://en.cppreference.com/w/cpp/atomic/atomic_ref) diff --git a/src/chapter7/chapter7.md b/src/chapter7/chapter7.md new file mode 100644 index 0000000..7d0f320 --- /dev/null +++ b/src/chapter7/chapter7.md @@ -0,0 +1,3 @@ +# Concurrent Programming + +The focus of this chapter is parallelism and concurrency. Parallelism allows for large amount data to be broken into smaller chunks and processed at the same time. Even undergoing different transformations. Concurrency is the ability to run multiple jobs, sections or functions simultaneously and communicate data and transfer between the states of the jobs. Together, these allow programs to expand the amount of work they are able to do and separate a program into multiple moving pieces. C++ has many primitives that make parallel and concurrent programming simple and effective. diff --git a/content/part7/examples/async/README.md b/src/chapter7/examples/async/README.md old mode 100644 new mode 100755 similarity index 100% rename from content/part7/examples/async/README.md rename to src/chapter7/examples/async/README.md diff --git a/content/part7/examples/async/bpt.yaml b/src/chapter7/examples/async/bpt.yaml old mode 100644 new mode 100755 similarity index 100% rename from content/part7/examples/async/bpt.yaml rename to src/chapter7/examples/async/bpt.yaml diff --git a/content/part7/examples/async/build.yaml b/src/chapter7/examples/async/build.yaml old mode 100644 new mode 100755 similarity index 100% rename from content/part7/examples/async/build.yaml rename to src/chapter7/examples/async/build.yaml diff --git a/content/part7/examples/async/src/async.main.cxx b/src/chapter7/examples/async/src/async.main.cxx old mode 100644 new mode 100755 similarity index 100% rename from content/part7/examples/async/src/async.main.cxx rename to src/chapter7/examples/async/src/async.main.cxx diff --git a/content/part7/examples/async/src/futures.main.cxx b/src/chapter7/examples/async/src/futures.main.cxx old mode 100644 new mode 100755 similarity index 100% rename from content/part7/examples/async/src/futures.main.cxx rename to src/chapter7/examples/async/src/futures.main.cxx diff --git a/content/part7/examples/async/src/packaged_task.main.cxx b/src/chapter7/examples/async/src/packaged_task.main.cxx old mode 100644 new mode 100755 similarity index 100% rename from content/part7/examples/async/src/packaged_task.main.cxx rename to src/chapter7/examples/async/src/packaged_task.main.cxx diff --git a/content/part7/examples/atomic/README.md b/src/chapter7/examples/atomic/README.md old mode 100644 new mode 100755 similarity index 100% rename from content/part7/examples/atomic/README.md rename to src/chapter7/examples/atomic/README.md diff --git a/content/part7/examples/atomic/bpt.yaml b/src/chapter7/examples/atomic/bpt.yaml old mode 100644 new mode 100755 similarity index 100% rename from content/part7/examples/atomic/bpt.yaml rename to src/chapter7/examples/atomic/bpt.yaml diff --git a/content/part7/examples/atomic/build.yaml b/src/chapter7/examples/atomic/build.yaml old mode 100644 new mode 100755 similarity index 100% rename from content/part7/examples/atomic/build.yaml rename to src/chapter7/examples/atomic/build.yaml diff --git a/content/part7/examples/atomic/src/atomic.main.cxx b/src/chapter7/examples/atomic/src/atomic.main.cxx old mode 100644 new mode 100755 similarity index 100% rename from content/part7/examples/atomic/src/atomic.main.cxx rename to src/chapter7/examples/atomic/src/atomic.main.cxx diff --git a/content/part7/examples/mutex/README.md b/src/chapter7/examples/mutex/README.md old mode 100644 new mode 100755 similarity index 100% rename from content/part7/examples/mutex/README.md rename to src/chapter7/examples/mutex/README.md diff --git a/content/part7/examples/mutex/bpt.yaml b/src/chapter7/examples/mutex/bpt.yaml old mode 100644 new mode 100755 similarity index 100% rename from content/part7/examples/mutex/bpt.yaml rename to src/chapter7/examples/mutex/bpt.yaml diff --git a/content/part7/examples/mutex/src/barrier.main.cxx b/src/chapter7/examples/mutex/src/barrier.main.cxx old mode 100644 new mode 100755 similarity index 100% rename from content/part7/examples/mutex/src/barrier.main.cxx rename to src/chapter7/examples/mutex/src/barrier.main.cxx diff --git a/content/part7/examples/mutex/src/latch.main.cxx b/src/chapter7/examples/mutex/src/latch.main.cxx old mode 100644 new mode 100755 similarity index 100% rename from content/part7/examples/mutex/src/latch.main.cxx rename to src/chapter7/examples/mutex/src/latch.main.cxx diff --git a/content/part7/examples/mutex/src/locks.main.cxx b/src/chapter7/examples/mutex/src/locks.main.cxx old mode 100644 new mode 100755 similarity index 100% rename from content/part7/examples/mutex/src/locks.main.cxx rename to src/chapter7/examples/mutex/src/locks.main.cxx diff --git a/content/part7/examples/mutex/src/mutex.main.cxx b/src/chapter7/examples/mutex/src/mutex.main.cxx old mode 100644 new mode 100755 similarity index 100% rename from content/part7/examples/mutex/src/mutex.main.cxx rename to src/chapter7/examples/mutex/src/mutex.main.cxx diff --git a/content/part7/examples/mutex/src/semaphores.main.cxx b/src/chapter7/examples/mutex/src/semaphores.main.cxx old mode 100644 new mode 100755 similarity index 100% rename from content/part7/examples/mutex/src/semaphores.main.cxx rename to src/chapter7/examples/mutex/src/semaphores.main.cxx diff --git a/content/part7/examples/par-algs/README.md b/src/chapter7/examples/par-algs/README.md old mode 100644 new mode 100755 similarity index 100% rename from content/part7/examples/par-algs/README.md rename to src/chapter7/examples/par-algs/README.md diff --git a/content/part7/examples/par-algs/bpt.yaml b/src/chapter7/examples/par-algs/bpt.yaml old mode 100644 new mode 100755 similarity index 100% rename from content/part7/examples/par-algs/bpt.yaml rename to src/chapter7/examples/par-algs/bpt.yaml diff --git a/content/part7/examples/par-algs/build.yaml b/src/chapter7/examples/par-algs/build.yaml old mode 100644 new mode 100755 similarity index 100% rename from content/part7/examples/par-algs/build.yaml rename to src/chapter7/examples/par-algs/build.yaml diff --git a/content/part6/slides/README.md b/src/chapter7/examples/par-algs/content/part6/slides/README.md old mode 100644 new mode 100755 similarity index 100% rename from content/part6/slides/README.md rename to src/chapter7/examples/par-algs/content/part6/slides/README.md diff --git a/content/part7/examples/par-algs/src/exclusive_scan.main.cxx b/src/chapter7/examples/par-algs/src/exclusive_scan.main.cxx old mode 100644 new mode 100755 similarity index 100% rename from content/part7/examples/par-algs/src/exclusive_scan.main.cxx rename to src/chapter7/examples/par-algs/src/exclusive_scan.main.cxx diff --git a/content/part7/examples/par-algs/src/inclusive_scan.main.cxx b/src/chapter7/examples/par-algs/src/inclusive_scan.main.cxx old mode 100644 new mode 100755 similarity index 100% rename from content/part7/examples/par-algs/src/inclusive_scan.main.cxx rename to src/chapter7/examples/par-algs/src/inclusive_scan.main.cxx diff --git a/content/part7/examples/par-algs/src/reduce.main.cxx b/src/chapter7/examples/par-algs/src/reduce.main.cxx old mode 100644 new mode 100755 similarity index 100% rename from content/part7/examples/par-algs/src/reduce.main.cxx rename to src/chapter7/examples/par-algs/src/reduce.main.cxx diff --git a/content/part7/examples/par-algs/src/transform_exclusive_scan.main.cxx b/src/chapter7/examples/par-algs/src/transform_exclusive_scan.main.cxx old mode 100644 new mode 100755 similarity index 100% rename from content/part7/examples/par-algs/src/transform_exclusive_scan.main.cxx rename to src/chapter7/examples/par-algs/src/transform_exclusive_scan.main.cxx diff --git a/content/part7/examples/par-algs/src/transform_inclusive_scan.main.cxx b/src/chapter7/examples/par-algs/src/transform_inclusive_scan.main.cxx old mode 100644 new mode 100755 similarity index 100% rename from content/part7/examples/par-algs/src/transform_inclusive_scan.main.cxx rename to src/chapter7/examples/par-algs/src/transform_inclusive_scan.main.cxx diff --git a/content/part7/examples/par-algs/src/transform_reduce.main.cxx b/src/chapter7/examples/par-algs/src/transform_reduce.main.cxx old mode 100644 new mode 100755 similarity index 100% rename from content/part7/examples/par-algs/src/transform_reduce.main.cxx rename to src/chapter7/examples/par-algs/src/transform_reduce.main.cxx diff --git a/content/part7/examples/threads/README.md b/src/chapter7/examples/threads/README.md old mode 100644 new mode 100755 similarity index 100% rename from content/part7/examples/threads/README.md rename to src/chapter7/examples/threads/README.md diff --git a/content/part7/examples/threads/bpt.yaml b/src/chapter7/examples/threads/bpt.yaml old mode 100644 new mode 100755 similarity index 100% rename from content/part7/examples/threads/bpt.yaml rename to src/chapter7/examples/threads/bpt.yaml diff --git a/content/part7/examples/threads/build.yaml b/src/chapter7/examples/threads/build.yaml old mode 100644 new mode 100755 similarity index 100% rename from content/part7/examples/threads/build.yaml rename to src/chapter7/examples/threads/build.yaml diff --git a/content/part7/examples/threads/src/jthread.main.cxx b/src/chapter7/examples/threads/src/jthread.main.cxx old mode 100644 new mode 100755 similarity index 100% rename from content/part7/examples/threads/src/jthread.main.cxx rename to src/chapter7/examples/threads/src/jthread.main.cxx diff --git a/content/part7/examples/threads/src/thread-pools.main.cxx b/src/chapter7/examples/threads/src/thread-pools.main.cxx old mode 100644 new mode 100755 similarity index 100% rename from content/part7/examples/threads/src/thread-pools.main.cxx rename to src/chapter7/examples/threads/src/thread-pools.main.cxx diff --git a/content/part7/examples/threads/src/thread.main.cxx b/src/chapter7/examples/threads/src/thread.main.cxx old mode 100644 new mode 100755 similarity index 100% rename from content/part7/examples/threads/src/thread.main.cxx rename to src/chapter7/examples/threads/src/thread.main.cxx diff --git a/src/chapter7/hpp_chapter7.pdf b/src/chapter7/hpp_chapter7.pdf new file mode 100644 index 0000000..2dbbb84 Binary files /dev/null and b/src/chapter7/hpp_chapter7.pdf differ diff --git a/content/part7/slides/hpp_part7.pptx b/src/chapter7/hpp_chapter7.pptx similarity index 97% rename from content/part7/slides/hpp_part7.pptx rename to src/chapter7/hpp_chapter7.pptx index 59256fb..8c9839c 100644 Binary files a/content/part7/slides/hpp_part7.pptx and b/src/chapter7/hpp_chapter7.pptx differ diff --git a/src/chapter7/imgs/hpp_chapter7-01.png b/src/chapter7/imgs/hpp_chapter7-01.png new file mode 100644 index 0000000..898f971 Binary files /dev/null and b/src/chapter7/imgs/hpp_chapter7-01.png differ diff --git a/content/part7/slides/imgs/hpp_part7-02.png b/src/chapter7/imgs/hpp_chapter7-02.png similarity index 100% rename from content/part7/slides/imgs/hpp_part7-02.png rename to src/chapter7/imgs/hpp_chapter7-02.png diff --git a/content/part7/slides/imgs/hpp_part7-03.png b/src/chapter7/imgs/hpp_chapter7-03.png similarity index 100% rename from content/part7/slides/imgs/hpp_part7-03.png rename to src/chapter7/imgs/hpp_chapter7-03.png diff --git a/src/chapter7/imgs/hpp_chapter7-04.png b/src/chapter7/imgs/hpp_chapter7-04.png new file mode 100644 index 0000000..be6de51 Binary files /dev/null and b/src/chapter7/imgs/hpp_chapter7-04.png differ diff --git a/content/part7/slides/imgs/hpp_part7-05.png b/src/chapter7/imgs/hpp_chapter7-05.png similarity index 100% rename from content/part7/slides/imgs/hpp_part7-05.png rename to src/chapter7/imgs/hpp_chapter7-05.png diff --git a/content/part7/slides/imgs/hpp_part7-06.png b/src/chapter7/imgs/hpp_chapter7-06.png similarity index 100% rename from content/part7/slides/imgs/hpp_part7-06.png rename to src/chapter7/imgs/hpp_chapter7-06.png diff --git a/content/part7/slides/imgs/hpp_part7-07.png b/src/chapter7/imgs/hpp_chapter7-07.png similarity index 100% rename from content/part7/slides/imgs/hpp_part7-07.png rename to src/chapter7/imgs/hpp_chapter7-07.png diff --git a/src/chapter7/imgs/hpp_chapter7-08.png b/src/chapter7/imgs/hpp_chapter7-08.png new file mode 100644 index 0000000..984ba52 Binary files /dev/null and b/src/chapter7/imgs/hpp_chapter7-08.png differ diff --git a/content/part7/slides/imgs/hpp_part7-09.png b/src/chapter7/imgs/hpp_chapter7-09.png similarity index 100% rename from content/part7/slides/imgs/hpp_part7-09.png rename to src/chapter7/imgs/hpp_chapter7-09.png diff --git a/src/chapter7/imgs/hpp_chapter7-10.png b/src/chapter7/imgs/hpp_chapter7-10.png new file mode 100644 index 0000000..431cf6a Binary files /dev/null and b/src/chapter7/imgs/hpp_chapter7-10.png differ diff --git a/content/part7/slides/imgs/hpp_part7-11.png b/src/chapter7/imgs/hpp_chapter7-11.png similarity index 100% rename from content/part7/slides/imgs/hpp_part7-11.png rename to src/chapter7/imgs/hpp_chapter7-11.png diff --git a/content/part7/slides/imgs/hpp_part7-12.png b/src/chapter7/imgs/hpp_chapter7-12.png similarity index 100% rename from content/part7/slides/imgs/hpp_part7-12.png rename to src/chapter7/imgs/hpp_chapter7-12.png diff --git a/src/chapter7/imgs/hpp_chapter7-13.png b/src/chapter7/imgs/hpp_chapter7-13.png new file mode 100644 index 0000000..54b3aa7 Binary files /dev/null and b/src/chapter7/imgs/hpp_chapter7-13.png differ diff --git a/content/part7/slides/imgs/hpp_part7-14.png b/src/chapter7/imgs/hpp_chapter7-14.png similarity index 100% rename from content/part7/slides/imgs/hpp_part7-14.png rename to src/chapter7/imgs/hpp_chapter7-14.png diff --git a/content/part7/slides/imgs/hpp_part7-15.png b/src/chapter7/imgs/hpp_chapter7-15.png similarity index 100% rename from content/part7/slides/imgs/hpp_part7-15.png rename to src/chapter7/imgs/hpp_chapter7-15.png diff --git a/content/part7/slides/imgs/hpp_part7-16.png b/src/chapter7/imgs/hpp_chapter7-16.png similarity index 100% rename from content/part7/slides/imgs/hpp_part7-16.png rename to src/chapter7/imgs/hpp_chapter7-16.png diff --git a/content/part7/slides/imgs/hpp_part7-17.png b/src/chapter7/imgs/hpp_chapter7-17.png similarity index 100% rename from content/part7/slides/imgs/hpp_part7-17.png rename to src/chapter7/imgs/hpp_chapter7-17.png diff --git a/content/part7/slides/imgs/hpp_part7-18.png b/src/chapter7/imgs/hpp_chapter7-18.png similarity index 100% rename from content/part7/slides/imgs/hpp_part7-18.png rename to src/chapter7/imgs/hpp_chapter7-18.png diff --git a/content/part7/slides/imgs/hpp_part7-19.png b/src/chapter7/imgs/hpp_chapter7-19.png similarity index 100% rename from content/part7/slides/imgs/hpp_part7-19.png rename to src/chapter7/imgs/hpp_chapter7-19.png diff --git a/content/part7/slides/imgs/hpp_part7-20.png b/src/chapter7/imgs/hpp_chapter7-20.png similarity index 100% rename from content/part7/slides/imgs/hpp_part7-20.png rename to src/chapter7/imgs/hpp_chapter7-20.png diff --git a/content/part7/slides/imgs/hpp_part7-21.png b/src/chapter7/imgs/hpp_chapter7-21.png similarity index 100% rename from content/part7/slides/imgs/hpp_part7-21.png rename to src/chapter7/imgs/hpp_chapter7-21.png diff --git a/content/part7/slides/imgs/hpp_part7-22.png b/src/chapter7/imgs/hpp_chapter7-22.png similarity index 57% rename from content/part7/slides/imgs/hpp_part7-22.png rename to src/chapter7/imgs/hpp_chapter7-22.png index d1f8d15..4827ff5 100644 Binary files a/content/part7/slides/imgs/hpp_part7-22.png and b/src/chapter7/imgs/hpp_chapter7-22.png differ diff --git a/content/part7/slides/imgs/hpp_part7-23.png b/src/chapter7/imgs/hpp_chapter7-23.png similarity index 100% rename from content/part7/slides/imgs/hpp_part7-23.png rename to src/chapter7/imgs/hpp_chapter7-23.png diff --git a/content/part7/slides/imgs/hpp_part7-24.png b/src/chapter7/imgs/hpp_chapter7-24.png similarity index 100% rename from content/part7/slides/imgs/hpp_part7-24.png rename to src/chapter7/imgs/hpp_chapter7-24.png diff --git a/content/part7/slides/imgs/hpp_part7-25.png b/src/chapter7/imgs/hpp_chapter7-25.png similarity index 100% rename from content/part7/slides/imgs/hpp_part7-25.png rename to src/chapter7/imgs/hpp_chapter7-25.png diff --git a/content/part7/slides/imgs/hpp_part7-26.png b/src/chapter7/imgs/hpp_chapter7-26.png similarity index 100% rename from content/part7/slides/imgs/hpp_part7-26.png rename to src/chapter7/imgs/hpp_chapter7-26.png diff --git a/content/part7/slides/imgs/hpp_part7-27.png b/src/chapter7/imgs/hpp_chapter7-27.png similarity index 100% rename from content/part7/slides/imgs/hpp_part7-27.png rename to src/chapter7/imgs/hpp_chapter7-27.png diff --git a/src/chapter7/imgs/hpp_chapter7-28.png b/src/chapter7/imgs/hpp_chapter7-28.png new file mode 100644 index 0000000..a1d1e4f Binary files /dev/null and b/src/chapter7/imgs/hpp_chapter7-28.png differ diff --git a/content/part7/slides/imgs/hpp_part7-29.png b/src/chapter7/imgs/hpp_chapter7-29.png similarity index 100% rename from content/part7/slides/imgs/hpp_part7-29.png rename to src/chapter7/imgs/hpp_chapter7-29.png diff --git a/content/part7/slides/imgs/hpp_part7-30.png b/src/chapter7/imgs/hpp_chapter7-30.png similarity index 100% rename from content/part7/slides/imgs/hpp_part7-30.png rename to src/chapter7/imgs/hpp_chapter7-30.png diff --git a/content/part7/slides/imgs/hpp_part7-31.png b/src/chapter7/imgs/hpp_chapter7-31.png similarity index 100% rename from content/part7/slides/imgs/hpp_part7-31.png rename to src/chapter7/imgs/hpp_chapter7-31.png diff --git a/content/part7/slides/imgs/hpp_part7-32.png b/src/chapter7/imgs/hpp_chapter7-32.png similarity index 100% rename from content/part7/slides/imgs/hpp_part7-32.png rename to src/chapter7/imgs/hpp_chapter7-32.png diff --git a/content/part7/tasks/mutexes.md b/src/chapter7/mutexes.md similarity index 83% rename from content/part7/tasks/mutexes.md rename to src/chapter7/mutexes.md index 0478584..861953d 100644 --- a/content/part7/tasks/mutexes.md +++ b/src/chapter7/mutexes.md @@ -1,22 +1,6 @@ # Mutexes & Locks -## Contents - -- [Mutexes \& Locks](#mutexes--locks) - - [Contents](#contents) - - [Task 4](#task-4) - - [Task 4.1 : What is a Mutex?](#task-41--what-is-a-mutex) - - [Task 4.2 : Other Mutex Types](#task-42--other-mutex-types) - - [Task 4.3 : What is a lock?](#task-43--what-is-a-lock) - - [Task 4.4 : Semaphores](#task-44--semaphores) - - [Task 4.5 : Lock Types](#task-45--lock-types) - - [Task 4.6 : Latches](#task-46--latches) - - [Task 4.7 : Barriers](#task-47--barriers) - - [Links](#links) - -## Task 4 - -### Task 4.1 : What is a Mutex? +## What is a Mutex? A mutex is a _mutually-exclusive-object_. It is used to synchronize access to shared memory resources across multiple threads. C++ mutex type is called `std::mutex` from the `` header. Threads can own a `std::mutex` by locking it. Other threads will block when they try to lock a `std::mutex` owned by another thread. `std::mutex` also implement a try-lock that returns a Boolean indicating the result off the lock attempt. A thread cannot own a `std::mutex` before it tries to lock it. Mutexes are generally implemented as a OS primitive. Because `std::mutex` (and C++ other mutex types) use locking and unlocking methods to control access, these types are not considered to be RAII types. Instead there are locking types that will lock a mutex on construction and unlock it on destruction (more below). @@ -83,11 +67,11 @@ bpt build -t build.yaml -o build { 0: 140667719128640, 1: 140667710735936, 2: 140667702343232, 3: 140667693950528, 4: 140667685557824, 5: 140667677165120, 6: 140667668772416, 7: 140667660379712, 8: 140667651987008, 9: 140667643594304, 10: 140667635201600, 11: 140667626808896, 12: 140667618416192, 13: 140667610023488, 14: 140667601630784, 15: 140667593238080, } ``` -[Example](/content/part7/examples/mutex/src/mutex.main.cxx) +[Example](./examples/mutex/src/mutex.main.cxx) -[`std::mutex` : cppreference](https://en.cppreference.com/w/cpp/thread/mutex) +[`std::mutex`](https://en.cppreference.com/w/cpp/thread/mutex) -### Task 4.2 : Other Mutex Types +## Other Mutex Types - `std::timed_mutex` - Mutex that offers timeout based locking methods. Locking will be attempted for a certain duration. - `std::recursive_mutex` - Mutex that can be repeatedly locked by the same thread multiple times. Must be unlocked the same number of times to become fully unlocked. @@ -95,17 +79,17 @@ bpt build -t build.yaml -o build - `std::shared_mutex` - A mutex that offers to levels of access, _shared_ or _exclusive_. Shared locking allows for multiple threads to share a mutex and read the shared memory resources while exclusive only allows one thread to access the shared resources with write privileges. If one thread has a shared lock an a mutex other threads can only gain a shared lock on it as well prohibiting the ability to gain exclusive access from another thread until all threads have unlocked the shared lock. Similarly, a thread with an exclusive lock on a thread disallows other threads from gaining any lock on the mutex until it has been unlocked. - `std::shared_timed_mutex` - Same as a `std::shared_mutex` but offers timeout based exclusive and shared locking. -- [`std::timed_mutex` : cppreference](https://en.cppreference.com/w/cpp/thread/timed_mutex) -- [`std::recursive_mutex` : cppreference](https://en.cppreference.com/w/cpp/thread/recursive_mutex) -- [`std::recursive_timed_mutex` : cppreference](https://en.cppreference.com/w/cpp/thread/recursive_timed_mutex) -- [`std::shared_mutex` : cppreference](https://en.cppreference.com/w/cpp/thread/shared_mutex) -- [`std::shared_timed_mutex` : cppreference](https://en.cppreference.com/w/cpp/thread/shared_timed_mutex) +- [`std::timed_mutex`](https://en.cppreference.com/w/cpp/thread/timed_mutex) +- [`std::recursive_mutex`](https://en.cppreference.com/w/cpp/thread/recursive_mutex) +- [`std::recursive_timed_mutex`](https://en.cppreference.com/w/cpp/thread/recursive_timed_mutex) +- [`std::shared_mutex`](https://en.cppreference.com/w/cpp/thread/shared_mutex) +- [`std::shared_timed_mutex`](https://en.cppreference.com/w/cpp/thread/shared_timed_mutex) -### Task 4.3 : What is a lock? +## What is a lock? A lock is another kind of synchronization primitive. Locks can be used to wrap other synchronization primitives like mutexes and bind the locking and unlocking if the mutex to the lifetime of the lock using RAII or can themselves be synchronization primitives that must be acquires and released. Most locks in C++ perform the former which allow for mutex locking to be scoped ensuring proper releasing of resources even if exceptions are thrown. Locks however, can also be used erroneously creating _deadlocks_ for which two threads rely on the releasing of each others locks in order to release their respective locks. They also have a little more overhead as you have to create and destroy locks. Locks will often be created in an unnamed scope to ensure that it only lives as long as it needs. -### Task 4.4 : Semaphores +## Semaphores The most simple type of lock is a semaphore. Semaphores allow multiple threads to access the same resource. The number of accessors is dictated by a count which decrements when the semaphore is acquires and blocks for any acquisitions for which the count is zero. C++ semaphore type which supports arbitrary size counts is called `std::counting_semaphore`. There is also a specialisation for which only a single accessor is allowed, called `std::binary_semaphore`. Both of these live in the `semaphore` header. @@ -158,11 +142,11 @@ $ ./build/semaphores [Main]: Got signal ``` -[Example](/content/part7/examples/mutex/src/semaphores.main.cxx) +[Example](./examples/mutex/src/semaphores.main.cxx) -[`std::counting_semaphore` & `std::binary_semaphore` : cppreference](https://en.cppreference.com/w/cpp/thread/counting_semaphore) +[`std::counting_semaphore` & `std::binary_semaphore`](https://en.cppreference.com/w/cpp/thread/counting_semaphore) -### Task 4.5 : Lock Types +## Lock Types - `std::lock_guard` - The most basic kind of mutex locking wrapper. It binds the locking lifetime of a mutex to the lifetime of the lock. It takes a template type parameter of the mutex type and a mutex as a constructor argument. It can also adopt the ownership of a mutex by passing a second constructor argument `std::adopt_lock` which does not lock the mutex but ensuring the calling thread will unlock it. `std::lock_guard` is non-copyable. - `std::scoped_lock` - A lock for acquiring ownership of zero or more mutexes for the duration of a scope block. When constructed and given ownership of multiple mutexes, the locking and unlocking of mutexes uses a deadlock avoidance algorithm. @@ -233,15 +217,15 @@ $ ./build/locks { 0: 139998766057024, 1: 139998757664320, 2: 139998749271616, 3: 139998740878912, 4: 139998732486208, 5: 139998724093504, 6: 139998715700800, 7: 139998707308096, 8: 139998698915392, 9: 139998690522688, 10: 139998682129984, 11: 139998673737280, 12: 139998665344576, 13: 139998656951872, 14: 139998648559168, 15: 139998640166464, } ``` -[Example](/content/part7/examples/mutex/src/locks.main.cxx) +[Example](./examples/mutex/src/locks.main.cxx) -- [`std::lock_guard` : cppreference](https://en.cppreference.com/w/cpp/thread/lock_guard) -- [`std:scoped_lock` : cppreference](https://en.cppreference.com/w/cpp/thread/scoped_lock) -- [`std::unique_lock` : cppreference](https://en.cppreference.com/w/cpp/thread/unique_lock) -- [`std::shared_lock` : cppreference](https://en.cppreference.com/w/cpp/thread/shared_lock) -- [Locking Strategies : cppreference](https://en.cppreference.com/w/cpp/thread/lock_tag) +- [`std::lock_guard`](https://en.cppreference.com/w/cpp/thread/lock_guard) +- [`std:scoped_lock`](https://en.cppreference.com/w/cpp/thread/scoped_lock) +- [`std::unique_lock`](https://en.cppreference.com/w/cpp/thread/unique_lock) +- [`std::shared_lock`](https://en.cppreference.com/w/cpp/thread/shared_lock) +- [Locking Strategies](https://en.cppreference.com/w/cpp/thread/lock_tag) -### Task 4.6 : Latches +## Latches A `std::latch` is count-down synchronization primitive with the count is initialized on construction. Threads can wait at a `std::latch` until the count reaches zero. Once this happens, all the threads waiting on the latch are released. `std::latch` cannot increment or reset its counter after construction making it a single use barrier. `std::latch` is non-copyable and lives in the `` header. @@ -337,11 +321,11 @@ Job 1 cleaned up. All jobs cleaned up. ``` -[Example](/content/part7/examples/mutex/src/latch.main.cxx) +[Example](./examples/mutex/src/latch.main.cxx) -[`std::latch` : cppreference](https://en.cppreference.com/w/cpp/thread/latch) +[`std::latch`](https://en.cppreference.com/w/cpp/thread/latch) -### Task 4.7 : Barriers +## Barriers `std::barrier` is a more general version of `std::latch`. The lifetime of a `std::barrier` consists of one or more phases. The first is a synchronization phase for which threads will block where once the counter has reach zero for the `std::barrier` the threads will unblock. Right before unblocking, a completion function will run which is optionally supplied at the `std::barrier` construction. After this the `std::barrier` will reset its counter and can be reused. The overall count can be reduced on arrival by a thread. `std::barrier` is non-copyable and lives in the `` header. @@ -439,13 +423,6 @@ Job 10 cleaned up. All cleaned up. ``` -[Example](/content/part7/examples/mutex/src/barrier.main.cxx) - -[`std::barrier` : cppreference](https://en.cppreference.com/w/cpp/thread/barrier) - -## Links +[Example](./examples/mutex/src/barrier.main.cxx) -- [Previous Page : Threads](/content/part7/tasks/threads.md) -- [Next Page : Async](/content/part7/tasks/async.md) -- [Content](/content/README.md) -- [HOME](/README.md) +[`std::barrier`](https://en.cppreference.com/w/cpp/thread/barrier) diff --git a/content/part7/tasks/parallel-alg.md b/src/chapter7/parallel-alg.md similarity index 93% rename from content/part7/tasks/parallel-alg.md rename to src/chapter7/parallel-alg.md index ceaa9d2..3635ede 100644 --- a/content/part7/tasks/parallel-alg.md +++ b/src/chapter7/parallel-alg.md @@ -1,23 +1,6 @@ # Parallel Algorithms -## Contents - -- [Parallel Algorithms](#parallel-algorithms) - - [Contents](#contents) - - [Task 1](#task-1) - - [Task 1.1 : Execution Policies](#task-11--execution-policies) - - [Task 1.2 : Alternative Algorithms](#task-12--alternative-algorithms) - - [Task 1.2.1 : Reduce](#task-121--reduce) - - [Task 1.2.2 : Transform Reduce](#task-122--transform-reduce) - - [Task 1.2.3 : Exclusive Scan](#task-123--exclusive-scan) - - [Task 1.2.4 : Inclusive Scan](#task-124--inclusive-scan) - - [Task 1.2.5 : Transform Exclusive Scan](#task-125--transform-exclusive-scan) - - [Task 1.2.6 : Transform Inclusive Scan](#task-126--transform-inclusive-scan) - - [Links](#links) - -## Task 1 - -### Task 1.1 : Execution Policies +## Execution Policies The most basic parallelism comes from the algorithms library. Since C++17 almost all of the algorithms (iterator-based not range-based) in the standard library feature an overload that allows for the algorithm to potentially perform in parallel. These overloads accepts as their first arguments an execution policy. This is an object that represent the level of freedom an algorithms implementation has to try and parallelize its operation. Execution policies are found in the `` header under the `std::execution` namespace. Execution policies are suggestions, they indicate that a algorithm may be able to be parallelized. How the parallelism is achieve is up to the implementation and requires a parallelism backend library that the implementations will use. The most common is Intel's Thread Building Blocks (TBB) library. Using parallel overloads does require some due-diligence from the programmer to not create deadlocks or data races. The parallel algorithms will not automatically stop these from happening. @@ -28,13 +11,13 @@ The most basic parallelism comes from the algorithms library. Since C++17 almost | `std::execution::unseq` | Specifies that an algorithm can be vectorized such that a single thread using instructions that operate on multiple data items. | | `std::execution::par_unseq` | Specifies that an algorithm can be parallelized, vectorized or migrated across threads. Invocations of element access functions within the algorithm are permitted to execute in unordered fashion in unspecified threads and can be un-sequenced with respect to one another within each thread. | -[Execution Policies : cppreference](https://en.cppreference.com/w/cpp/algorithm/execution_policy_tag_t) +[Execution Policies](https://en.cppreference.com/w/cpp/algorithm/execution_policy_tag_t) -### Task 1.2 : Alternative Algorithms +## Alternative Algorithms There are a few algorithms in C++ that did not get parallel overloads. Namely a few of the numerical reductions. This is because reduction algorithms typically use binary operators in order to combine elements. The issue with this is not all binary operators are commutative or associative. This can cause problems when making an algorithm work in parallel because the order of operations can affect the result of the reduction. C++ regular reduction algorithms apply their operations in-order meaning that the commutative and associative properties of the binary operator do not matter. For parallel algorithms, commutativity and associativity must be assumed of the binary operator so that operations can be out-of-order. -#### Task 1.2.1 : Reduce +### Reduce `std::reduce` is the parallel form of `std::accumulate`. It performs a regular left-fold and can take an optional initial value. @@ -122,11 +105,11 @@ $ ./build/reduce +-----------------+-------------+-----------+--------+------------+----------------+ ``` -[Example](/content/part7/examples/par-algs/src/reduce.main.cxx) +[Example](./examples/par-algs/src/reduce.main.cxx) -[`std::reduce` : cppreference](https://en.cppreference.com/w/cpp/algorithm/reduce) +[`std::reduce`](https://en.cppreference.com/w/cpp/algorithm/reduce) -#### Task 1.2.2 : Transform Reduce +### Transform Reduce `std::transform_reduce` is akin to `std::inner_product` performing the same default unary transformation (`*`) and reduction (`+`). Takes an initial value that is used as the base accumulator. @@ -215,13 +198,13 @@ $ bpt build -t build.yaml -o build +-----------------------+-------------+------------+--------+------------+----------------+ ``` -[Example](/content/part7/examples/par-algs/src/transform_reduce.main.cxx) +[Example](./examples/par-algs/src/transform_reduce.main.cxx) -[`std::transform_reduce` : cppreference](https://en.cppreference.com/w/cpp/algorithm/transform_reduce) +[`std::transform_reduce`](https://en.cppreference.com/w/cpp/algorithm/transform_reduce) -#### Task 1.2.3 : Exclusive Scan +### Exclusive Scan -`std::exclusive_scan` is akin to `std::partial_sum` except is takes in an initial value and excludes the $ith$ input element from the $ith$ sum (reduction). +`std::exclusive_scan` is akin to `std::partial_sum` except is takes in an initial value and excludes the \\( ith \\) input element from the \\( ith \\) sum (reduction). ```cxx #include @@ -323,13 +306,13 @@ $ bpt build -t build.yaml -o build +---------------------+-------------+-----------+--------+------------+-----------------------------------------------+ ``` -[Example](/content/part7/examples/par-algs/src/exclusive_scan.main.cxx) +[Example](./examples/par-algs/src/exclusive_scan.main.cxx) -[`std::exclusive_scan` : cppreference](https://en.cppreference.com/w/cpp/algorithm/exclusive_scan) +[`std::exclusive_scan`](https://en.cppreference.com/w/cpp/algorithm/exclusive_scan) -#### Task 1.2.4 : Inclusive Scan +### Inclusive Scan -`std::inclusive_scan` is identical to `std::partial_sum`. It does not take an initial value and unlike `std::exclusive_scan` includes the $ith$ element from the input range in the $ith$ reduction. +`std::inclusive_scan` is identical to `std::partial_sum`. It does not take an initial value and unlike `std::exclusive_scan` includes the \\( ith \\) element from the input range in the \\( ith \\) reduction. ```cxx #include @@ -431,11 +414,11 @@ $ bpt build -t build.yaml -o build +---------------------+-------------+-----------+--------+------------+-----------------------------------------------+ ``` -[Example](/content/part7/examples/par-algs/src/inclusive_scan.main.cxx) +[Example](./examples/par-algs/src/inclusive_scan.main.cxx) -[`std::inclusive_scan` : cppreference](https://en.cppreference.com/w/cpp/algorithm/inclusive_scan) +[`std::inclusive_scan`](https://en.cppreference.com/w/cpp/algorithm/inclusive_scan) -#### Task 1.2.5 : Transform Exclusive Scan +### Transform Exclusive Scan `std::transform_exclusive_scan` will perform a unary transformation and then performs a left exclusive scan on a range. @@ -533,11 +516,11 @@ $ bpt build -t build.yaml -o build +--------------------+----------+-------------+-------------+--------+------------+-----------------------------------------------+ ``` -[Example](/content/part7/examples/par-algs/src/transform_exclusive_scan.main.cxx) +[Example](./examples/par-algs/src/transform_exclusive_scan.main.cxx) -[`std::transform_exclusive_scan` : cppreference](https://en.cppreference.com/w/cpp/algorithm/transform_exclusive_scan) +[`std::transform_exclusive_scan`](https://en.cppreference.com/w/cpp/algorithm/transform_exclusive_scan) -#### Task 1.2.6 : Transform Inclusive Scan +### Transform Inclusive Scan `std::transform_inclusive_scan` will perform a unary transformation and then performs a left inclusive scan on a range. @@ -635,13 +618,6 @@ $ bpt build -t build.yaml -o build +--------------------+----------+-------------+-------------+--------+------------+-----------------------------------------------+ ``` -[Example](/content/part7/examples/par-algs/src/transform_inclusive_scan.main.cxx) - -[`std::transform_inclusive_scan` : cppreference](https://en.cppreference.com/w/cpp/algorithm/transform_inclusive_scan) - -## Links +[Example](./examples/par-algs/src/transform_inclusive_scan.main.cxx) -- [Previous Page : Part 7](/content/part7/README.md) -- [Next Page : Atomics](/content/part7/tasks/atomics.md) -- [Content](/content/README.md) -- [HOME](/README.md) +[`std::transform_inclusive_scan`](https://en.cppreference.com/w/cpp/algorithm/transform_inclusive_scan) diff --git a/src/chapter7/slides7.md b/src/chapter7/slides7.md new file mode 100644 index 0000000..da635a1 --- /dev/null +++ b/src/chapter7/slides7.md @@ -0,0 +1,34 @@ +# Slides + +![Slides 01](./imgs/hpp_chapter7-01.png) +![Slides 02](./imgs/hpp_chapter7-02.png) +![Slides 03](./imgs/hpp_chapter7-03.png) +![Slides 04](./imgs/hpp_chapter7-04.png) +![Slides 05](./imgs/hpp_chapter7-05.png) +![Slides 06](./imgs/hpp_chapter7-06.png) +![Slides 07](./imgs/hpp_chapter7-07.png) +![Slides 08](./imgs/hpp_chapter7-08.png) +![Slides 09](./imgs/hpp_chapter7-09.png) +![Slides 10](./imgs/hpp_chapter7-10.png) +![Slides 11](./imgs/hpp_chapter7-11.png) +![Slides 12](./imgs/hpp_chapter7-12.png) +![Slides 13](./imgs/hpp_chapter7-13.png) +![Slides 14](./imgs/hpp_chapter7-14.png) +![Slides 15](./imgs/hpp_chapter7-15.png) +![Slides 16](./imgs/hpp_chapter7-16.png) +![Slides 17](./imgs/hpp_chapter7-17.png) +![Slides 18](./imgs/hpp_chapter7-18.png) +![Slides 19](./imgs/hpp_chapter7-19.png) +![Slides 20](./imgs/hpp_chapter7-20.png) +![Slides 21](./imgs/hpp_chapter7-21.png) +![Slides 22](./imgs/hpp_chapter7-22.png) +![Slides 23](./imgs/hpp_chapter7-23.png) +![Slides 24](./imgs/hpp_chapter7-24.png) +![Slides 25](./imgs/hpp_chapter7-25.png) +![Slides 26](./imgs/hpp_chapter7-26.png) +![Slides 27](./imgs/hpp_chapter7-27.png) +![Slides 28](./imgs/hpp_chapter7-28.png) +![Slides 29](./imgs/hpp_chapter7-29.png) +![Slides 30](./imgs/hpp_chapter7-30.png) +![Slides 31](./imgs/hpp_chapter7-31.png) +![Slides 32](./imgs/hpp_chapter7-32.png) diff --git a/content/part7/tasks/threads.md b/src/chapter7/threads.md similarity index 79% rename from content/part7/tasks/threads.md rename to src/chapter7/threads.md index a4e967a..96c7d91 100644 --- a/content/part7/tasks/threads.md +++ b/src/chapter7/threads.md @@ -1,23 +1,10 @@ # Threads -## Contents +## What are Threads? -- [Threads](#threads) - - [Contents](#contents) - - [Task 3](#task-3) - - [Task 3.1 : What are Threads?](#task-31--what-are-threads) - - [Task 3.2 : Thread](#task-32--thread) - - [Task 3.3 : Automatic Threads](#task-33--automatic-threads) - - [Task 3.4 : Thread Pools](#task-34--thread-pools) - - [Links](#links) +Threads or threads of execution are the smallest sequence of instructions that is managed by a schedular of an operating system. Threads are a sub-object of a process. A process can have multiple threads allowing chapters of a process to run concurrently. In C++ we can spawn thread objects that will run a function until completion and then must be rejoined to the main thread or detached. -## Task 3 - -### Task 3.1 : What are Threads? - -Threads or threads of execution are the smallest sequence of instructions that is managed by a schedular of an operating system. Threads are a sub-object of a process. A process can have multiple threads allowing parts of a process to run concurrently. In C++ we can spawn thread objects that will run a function until completion and then must be rejoined to the main thread or detached. - -### Task 3.2 : Thread +## Thread C++ thread object is called `std::thread`. It takes as its first argument a function to run as well as any arguments that must be forwarded to the function. The function will begin to run immediately at the threads construction. Along with `std::thread` there is the `std::this_thread` namespaces which can get the ID or make the current thread sleep for some time. `std::thread` cannot be copied but can be moved. @@ -83,11 +70,11 @@ Thread 139836165793344 Done! Thread 139836174186048 Done! ``` -[Example](/content/part7/examples/thread/src/thread.main.cxx) +[Example](./examples/thread/src/thread.main.cxx) -[`std::thread` : cppreference](https://en.cppreference.com/w/cpp/thread/thread) +[`std::thread`](https://en.cppreference.com/w/cpp/thread/thread) -### Task 3.3 : Automatic Threads +## Automatic Threads Since C++20 there has been a thread type that automatically joins on destruction. This is called `std::jthread`. `std::jthread` also supports the use of `std::stop_token` and `std::stop_source`. These are primitives for preemptively cancelling a `std::jthread` from other threads. The `std::stop_source` is obtained from a `std::jthread` object and can be passed to other threads. For a `std::jthread` to be able to listen for stop requests, the function it runs must takes as its first argument a `std::stop_token`. @@ -154,13 +141,13 @@ Request stop for worker via source The job has be requested to stop ``` -[Example](/content/part7/examples/threads/src/jthread.main.cxx) +[Example](./examples/threads/src/jthread.main.cxx) -[`std::jthread` : cppreference](https://en.cppreference.com/w/cpp/thread/jthread) +[`std::jthread`](https://en.cppreference.com/w/cpp/thread/jthread) -### Task 3.4 : Thread Pools +## Thread Pools -A thread pool is a very common idiom in Computer Science. It involves creating a pool or array of threads that sit idle, waiting for work. Jobs are then pushed to the pool which get assigned to an available thread. Once the thread has finished the task the thread goes idle again. The most basic way to create a thread pool is to use a vector of threads and emplace jobs at the back of the vector and then join all joinable threads. +A thread pool is a very common idiom in Computer Science. It involves creating a pool or array of threads that sit idle, waiting for work. Jobs are then pushed to the pool which get assigned to an available thread. Once the thread has finished the section the thread goes idle again. The most basic way to create a thread pool is to use a vector of threads and emplace jobs at the back of the vector and then join all joinable threads. ```cxx #include @@ -226,13 +213,6 @@ Thread: 140166791448128 is running job: 12 Thread: 140166808233536 is running job: 10 ``` -[Example](/content/part7/examples/threads/src/thread-pools.main.cxx) - -[Thread Pool](https://en.wikipedia.org/wiki/Thread_pool) - -## Links +[Example](./examples/threads/src/thread-pools.main.cxx) -- [Previous Page : Atomics](/content/part7/tasks/atomics.md) -- [Next Page : Mutexes & Locks](/content/part7/tasks/mutexes.md) -- [Content](/content/README.md) -- [HOME](/README.md) +[Thread Pools](https://en.wikipedia.org/wiki/Thread_pool) diff --git a/src/foreword.md b/src/foreword.md new file mode 100644 index 0000000..96d2dec --- /dev/null +++ b/src/foreword.md @@ -0,0 +1,23 @@ +# Foreword + +Welcome + +## Source + +~ diff --git a/src/home.md b/src/home.md new file mode 100644 index 0000000..e6b268b --- /dev/null +++ b/src/home.md @@ -0,0 +1,39 @@ +# High Performance Programming + +_by Tyler Swann, in collaboration with Monash DeepNeuron_ + +## Welcome + +Welcome to Monash DeepNeuron's _High Performance Programming (C++ edition)_, a book aimed at teaching techniques for developing programs that are both fast and safe. Throughout this book you will be learning the C++ programming language along with techniques for; computer memory, algorithm intuition, parallel computing and more. + +## How to use this book + +This book is designed to be read cover-to-cover. Concepts in later chapters will build upon concepts from previous chapters. On either side of the page there are arrow buttons that will move you between pages and chapters. You can also search for specific content using the search button in the top left or by pressing the S key. + +## Synopsis + +- [Chapter 1 - Getting Started](./chapter1/chapter1.md) - Setup & Introduction to C++ +- [Chapter 2 - Basics of C++](./chapter2/chapter2.md) - Types, Variables, Operators, IO, Conditionals, Loops and Functions +- [Chapter 3 - Memory](./chapter3/chapter3.md) - Pointers, Slices, References, Dynamic Memory and The Standard Library +- [Chapter 4 - Intermediate C++](./chapter4/chapter4.md) - Functional Programming, Namespaces, Enumerations, Unions, Structures +- [Chapter 5 - Generic Programming](./chapter5/chapter5.md) - Classes, Templates, Generics and Concepts +- [Chapter 6 - Algorithms & Data Structures](./chapter6/chapter6.md) - Iterators, Data Structures, Algorithms, Ranges and Views +- [Chapter 7 - Parallel Programming](./chapter7/chapter7.md) - Parallel Algorithms, Atomics, Threads, Mutexes & Locks and Async + +## Suggestions, Fixes and Contributions + +Refer to the [source code](https://github.com/MonashDeepNeuron/HPP) of this book for details on how to contribute changes, fix typos or create new content for this book. + +## External Resources + +- [cppreference](https://en.cppreference.com/w/Main_Page) +- [Compiler Explorer](https://www.godbolt.org/) +- [bpt docs](https://bpt.pizza/docs/latest/index.html) + +
+
+ + {{ #include ./version.md }} + +
+
diff --git a/src/planned.md b/src/planned.md new file mode 100644 index 0000000..1d30823 --- /dev/null +++ b/src/planned.md @@ -0,0 +1,8 @@ +# Planned Additions + +- Separate installation for different OS + - Windows + - Linux + - MacOS + - WSL +- Coroutines (Chapter 7) diff --git a/src/version.md b/src/version.md new file mode 100644 index 0000000..6132e9d --- /dev/null +++ b/src/version.md @@ -0,0 +1 @@ +version: 0.1.1 \ No newline at end of file diff --git a/content/part4/submissions/nguyen/triple.cxx b/submissions/nguyen/triple/triple.cxx similarity index 96% rename from content/part4/submissions/nguyen/triple.cxx rename to submissions/nguyen/triple/triple.cxx index a9f392f..a392eca 100644 --- a/content/part4/submissions/nguyen/triple.cxx +++ b/submissions/nguyen/triple/triple.cxx @@ -5,7 +5,7 @@ /// To run this in VS code: /// Check if g++ is available: g++ --version -/// Go to Terminal -> Run Build Task -> Choose C/C++: g++ build active file +/// Go to Terminal -> Run Build Section -> Choose C/C++: g++ build active file /// When the file is executing, there will be output at the end asking for some input which must be in number, and can be whole or decimal number #include diff --git a/slides/presentation.pptx b/templates/presentation.pptx similarity index 100% rename from slides/presentation.pptx rename to templates/presentation.pptx diff --git a/templates/task.md b/templates/task.md index 673eaaf..70dd5f1 100644 --- a/templates/task.md +++ b/templates/task.md @@ -1,22 +1,7 @@ # A -## Contents +## Section n -- [A](#a) - - [Contents](#contents) - - [Task n](#task-n) - - [Task n.1 :](#task-n1-) - - [Links](#links) +### Section n.1 : -## Task n -### Task n.1 : - - - -## Links - -- [Previous Page : Week 2](/content/part2/README.md) -- [Next Page : Primitive Data Types](/content/part2/tasks/.md) -- [Content](/content/README.md) -- [HOME](/README.md)