├── .github └── workflows │ └── docs.yml ├── .gitignore ├── README.md ├── docs ├── requirements.txt └── source │ ├── conf.py │ └── index.rst └── notebooks ├── lecture-template.ipynb ├── lecture1.ipynb ├── lecture2.ipynb ├── lecture3.ipynb ├── lecture4.ipynb ├── lecture5.ipynb ├── lecture6.ipynb ├── lecture7.ipynb ├── plots ├── .DS_Store ├── OOPs-Concepts.jpg ├── address-of.png ├── class_lego.png ├── cppexample1.png ├── cppexample2.png ├── cppexample3.png ├── cppprocon1.png ├── doublepointer.png ├── dynamicarray.png ├── flashback.png ├── historycpp.png ├── lecture1-4.ipynb ├── lecture2_abstract_classes.png ├── lecture2_gaussrule.png ├── lecture2_program_design.png ├── lecture2_program_design_02.png ├── lecture2_program_design_03.png ├── lecture3_StaticPolyRoT.png ├── lecture3_overloadingvsoverriding.png ├── lecture3cat.gif ├── lecture4_cat.png ├── lecture5-doublelinkedlist.gif ├── lecture5-it0.png ├── lecture5-it9.png ├── lecture5-itend.png ├── lecture5-iterator.gif ├── lecture6-happy-holiday.png ├── lecture6-smart_pointers.png ├── lecture7-LAexpression.png ├── lecture7-LAexpression2.png ├── lecture7-buildmodel.png ├── lecture7-class_chart.png ├── lecture7-cmake1.png ├── lecture7-cmakememe.png ├── lecture7-decl_def.png ├── lecture7-gismo.png ├── lecture7-include_problem1.png ├── lecture7-include_problem2.png ├── lecture7-include_problem3.png ├── lecture7-iterator1.png ├── lecture7-iterator10.png ├── lecture7-iterator11.png ├── lecture7-iterator2.png ├── lecture7-iterator3.png ├── lecture7-iterator4.png ├── lecture7-iterator5.png ├── lecture7-iterator6.png ├── lecture7-iterator7.png ├── lecture7-iterator8.png ├── lecture7-iterator9.png ├── lecture7-preprocessor.png ├── lecture7-preprocessormeme.jpg ├── object_lego.png ├── paymentmethod1.png ├── paymentmethod2.png ├── pythonprocon.png └── squarewheelcar.png └── rise.css /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | name: docs 2 | 3 | on: 4 | push 5 | 6 | jobs: 7 | build_docs: 8 | 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - uses: actions/checkout@v3 13 | - name: Set up python 14 | uses: actions/setup-python@v3 15 | with: 16 | python-version: "3.10" 17 | 18 | - name: install dependencies 19 | run: | 20 | pip install -r ./docs/requirements.txt 21 | sudo apt-get install -y wkhtmltopdf 22 | 23 | - name: create slides 24 | run: | 25 | jupyter nbconvert --to slides --embed-images --template reveal --output-dir docs/source/_static "notebooks/*.ipynb" 26 | 27 | - name: Convert notebooks to PDF 28 | run: | 29 | for html_file in docs/source/_static/*.html; do 30 | # Create the PDF file name from the HTML file name 31 | pdf_file="${html_file%.html}.pdf" 32 | 33 | # Convert HTML to PDF using wkhtmltopdf (or replace with google-chrome for headless conversion) 34 | wkhtmltopdf --orientation landscape "$html_file" "$pdf_file" 35 | 36 | done 37 | 38 | - name: convert md to rst # md reference is not recognized with md_include 39 | uses: docker://pandoc/core:latest 40 | with: 41 | args: --from=markdown --to=rst --output=docs/source/README.rst README.md 42 | 43 | - name: build docs 44 | run: | 45 | sphinx-build -W -b html docs/source docs/build -j auto 46 | 47 | - name: deploy docs only if it is pushed to main 48 | uses: peaceiris/actions-gh-pages@v3 49 | # publish every time there's a push to the 2024 branch 50 | if: ${{ github.event_name == 'push' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }} 51 | with: 52 | github_token: ${{ secrets.GITHUB_TOKEN }} 53 | publish_dir: ./docs/build 54 | force_orphan: true 55 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # poetry 98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 99 | # This is especially recommended for binary packages to ensure reproducibility, and is more 100 | # commonly ignored for libraries. 101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 102 | #poetry.lock 103 | 104 | # pdm 105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 106 | #pdm.lock 107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 108 | # in version control. 109 | # https://pdm.fming.dev/#use-with-ide 110 | .pdm.toml 111 | 112 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 113 | __pypackages__/ 114 | 115 | # Celery stuff 116 | celerybeat-schedule 117 | celerybeat.pid 118 | 119 | # SageMath parsed files 120 | *.sage.py 121 | 122 | # Environments 123 | .env 124 | .venv 125 | env/ 126 | venv/ 127 | ENV/ 128 | env.bak/ 129 | venv.bak/ 130 | 131 | # Spyder project settings 132 | .spyderproject 133 | .spyproject 134 | 135 | # Rope project settings 136 | .ropeproject 137 | 138 | # mkdocs documentation 139 | /site 140 | 141 | # mypy 142 | .mypy_cache/ 143 | .dmypy.json 144 | dmypy.json 145 | 146 | # Pyre type checker 147 | .pyre/ 148 | 149 | # pytype static type analyzer 150 | .pytype/ 151 | 152 | # Cython debug symbols 153 | cython_debug/ 154 | 155 | # PyCharm 156 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 157 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 158 | # and can be added to the global gitignore or merged into this file. For a more nuclear 159 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 160 | #.idea/ 161 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Object-oriented scientific programming with C++ 2 | 3 | This repository contains the slides of the course _Object-oriented scientific programming with C++_ given at TU Delft under the two course codes TW3720TW (bachelor programme) and WI4771TU (master programme). The slides are offered in three different variants: 4 | - `notebooks` are jupyterlab notebooks meant for studying the material before or after the lecture 5 | - `interactive slides` will be used during the lecture with the option to adjust the content interactively 6 | - `static slides` are static versions of the lecture slides 7 | 8 | 9 | We strongly recomment using the notebooks and slides in the provided binder environment. Slides and notebooks **will not run** on a local JupyterLab installation because they require the [Jupyter kernel for C++](https://github.com/jupyter-xeus/xeus-cling) to be installed and configured properly. Note that **no support will be given** to make the slides and notebooks run on a local JupyterLab installation. 10 | 11 | ## Lectures 12 | 13 | | lecture no. | notebooks | interactive slides | static slides | 14 | | :---------: | :-------: | :----------------: | :-----------: | 15 | | 1 | [![Lecture 1][badge-binder-lecture]][binder-jupyterlab-lecture1] | [![Lecture 1][badge-binder-lecture]][binder-jupyternb-lecture1] | [![Lecture 1][badge-pages-lecture]][pages-lecture1] | 16 | | 2 | [![Lecture 2][badge-binder-lecture]][binder-jupyterlab-lecture2] | [![Lecture 2][badge-binder-lecture]][binder-jupyternb-lecture2] | [![Lecture 2][badge-pages-lecture]][pages-lecture2] | 17 | | 3 | [![Lecture 3][badge-binder-lecture]][binder-jupyterlab-lecture3] | [![Lecture 3][badge-binder-lecture]][binder-jupyternb-lecture3] | [![Lecture 3][badge-pages-lecture]][pages-lecture3] | 18 | | 4 | [![Lecture 4][badge-binder-lecture]][binder-jupyterlab-lecture4] | [![Lecture 4][badge-binder-lecture]][binder-jupyternb-lecture4] | [![Lecture 4][badge-pages-lecture]][pages-lecture4] | 19 | | 5 | [![Lecture 5][badge-binder-lecture]][binder-jupyterlab-lecture5] | [![Lecture 5][badge-binder-lecture]][binder-jupyternb-lecture5] | [![Lecture 5][badge-pages-lecture]][pages-lecture5] | 20 | | 6 | [![Lecture 6][badge-binder-lecture]][binder-jupyterlab-lecture6] | [![Lecture 6][badge-binder-lecture]][binder-jupyternb-lecture6] | [![Lecture 6][badge-pages-lecture]][pages-lecture6] | 21 | | 7 | [![Lecture 7][badge-binder-lecture]][binder-jupyterlab-lecture7] | [![Lecture 7][badge-binder-lecture]][binder-jupyternb-lecture7] | [![Lecture 7][badge-pages-lecture]][pages-lecture7] | 22 | 23 | 24 | 34 | 35 | [badge-binder-lecture]: https://img.shields.io/badge/interactive-lecture-579ACA.svg?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFkAAABZCAMAAABi1XidAAAB8lBMVEX///9XmsrmZYH1olJXmsr1olJXmsrmZYH1olJXmsr1olJXmsrmZYH1olL1olJXmsr1olJXmsrmZYH1olL1olJXmsrmZYH1olJXmsr1olL1olJXmsrmZYH1olL1olJXmsrmZYH1olL1olL0nFf1olJXmsrmZYH1olJXmsq8dZb1olJXmsrmZYH1olJXmspXmspXmsr1olL1olJXmsrmZYH1olJXmsr1olL1olJXmsrmZYH1olL1olLeaIVXmsrmZYH1olL1olL1olJXmsrmZYH1olLna31Xmsr1olJXmsr1olJXmsrmZYH1olLqoVr1olJXmsr1olJXmsrmZYH1olL1olKkfaPobXvviGabgadXmsqThKuofKHmZ4Dobnr1olJXmsr1olJXmspXmsr1olJXmsrfZ4TuhWn1olL1olJXmsqBi7X1olJXmspZmslbmMhbmsdemsVfl8ZgmsNim8Jpk8F0m7R4m7F5nLB6jbh7jbiDirOEibOGnKaMhq+PnaCVg6qWg6qegKaff6WhnpKofKGtnomxeZy3noG6dZi+n3vCcpPDcpPGn3bLb4/Mb47UbIrVa4rYoGjdaIbeaIXhoWHmZYHobXvpcHjqdHXreHLroVrsfG/uhGnuh2bwj2Hxk17yl1vzmljzm1j0nlX1olL3AJXWAAAAbXRSTlMAEBAQHx8gICAuLjAwMDw9PUBAQEpQUFBXV1hgYGBkcHBwcXl8gICAgoiIkJCQlJicnJ2goKCmqK+wsLC4usDAwMjP0NDQ1NbW3Nzg4ODi5+3v8PDw8/T09PX29vb39/f5+fr7+/z8/Pz9/v7+zczCxgAABC5JREFUeAHN1ul3k0UUBvCb1CTVpmpaitAGSLSpSuKCLWpbTKNJFGlcSMAFF63iUmRccNG6gLbuxkXU66JAUef/9LSpmXnyLr3T5AO/rzl5zj137p136BISy44fKJXuGN/d19PUfYeO67Znqtf2KH33Id1psXoFdW30sPZ1sMvs2D060AHqws4FHeJojLZqnw53cmfvg+XR8mC0OEjuxrXEkX5ydeVJLVIlV0e10PXk5k7dYeHu7Cj1j+49uKg7uLU61tGLw1lq27ugQYlclHC4bgv7VQ+TAyj5Zc/UjsPvs1sd5cWryWObtvWT2EPa4rtnWW3JkpjggEpbOsPr7F7EyNewtpBIslA7p43HCsnwooXTEc3UmPmCNn5lrqTJxy6nRmcavGZVt/3Da2pD5NHvsOHJCrdc1G2r3DITpU7yic7w/7Rxnjc0kt5GC4djiv2Sz3Fb2iEZg41/ddsFDoyuYrIkmFehz0HR2thPgQqMyQYb2OtB0WxsZ3BeG3+wpRb1vzl2UYBog8FfGhttFKjtAclnZYrRo9ryG9uG/FZQU4AEg8ZE9LjGMzTmqKXPLnlWVnIlQQTvxJf8ip7VgjZjyVPrjw1te5otM7RmP7xm+sK2Gv9I8Gi++BRbEkR9EBw8zRUcKxwp73xkaLiqQb+kGduJTNHG72zcW9LoJgqQxpP3/Tj//c3yB0tqzaml05/+orHLksVO+95kX7/7qgJvnjlrfr2Ggsyx0eoy9uPzN5SPd86aXggOsEKW2Prz7du3VID3/tzs/sSRs2w7ovVHKtjrX2pd7ZMlTxAYfBAL9jiDwfLkq55Tm7ifhMlTGPyCAs7RFRhn47JnlcB9RM5T97ASuZXIcVNuUDIndpDbdsfrqsOppeXl5Y+XVKdjFCTh+zGaVuj0d9zy05PPK3QzBamxdwtTCrzyg/2Rvf2EstUjordGwa/kx9mSJLr8mLLtCW8HHGJc2R5hS219IiF6PnTusOqcMl57gm0Z8kanKMAQg0qSyuZfn7zItsbGyO9QlnxY0eCuD1XL2ys/MsrQhltE7Ug0uFOzufJFE2PxBo/YAx8XPPdDwWN0MrDRYIZF0mSMKCNHgaIVFoBbNoLJ7tEQDKxGF0kcLQimojCZopv0OkNOyWCCg9XMVAi7ARJzQdM2QUh0gmBozjc3Skg6dSBRqDGYSUOu66Zg+I2fNZs/M3/f/Grl/XnyF1Gw3VKCez0PN5IUfFLqvgUN4C0qNqYs5YhPL+aVZYDE4IpUk57oSFnJm4FyCqqOE0jhY2SMyLFoo56zyo6becOS5UVDdj7Vih0zp+tcMhwRpBeLyqtIjlJKAIZSbI8SGSF3k0pA3mR5tHuwPFoa7N7reoq2bqCsAk1HqCu5uvI1n6JuRXI+S1Mco54YmYTwcn6Aeic+kssXi8XpXC4V3t7/ADuTNKaQJdScAAAAAElFTkSuQmCC&style=flat-square 36 | 37 | [badge-pages-lecture]: https://img.shields.io/badge/static-lecture-579ACA.svg?style=flat-square 38 | 39 | [binder-jupyterlab-lecture1]: https://mybinder.org/v2/gh/mmoelle1/OospCpp/binder?urlpath=git-pull%3Frepo%3Dhttps%253A%252F%252Fgithub.com%252Fmmoelle1%252FOospCpp%26urlpath%3Dlab%252Ftree%252FOospCpp%252Fnotebooks%252Flecture1.ipynb%26branch%3D2024 40 | [binder-jupyterlab-lecture2]: https://mybinder.org/v2/gh/mmoelle1/OospCpp/binder?urlpath=git-pull%3Frepo%3Dhttps%253A%252F%252Fgithub.com%252Fmmoelle1%252FOospCpp%26urlpath%3Dlab%252Ftree%252FOospCpp%252Fnotebooks%252Flecture2.ipynb%26branch%3D2024 41 | [binder-jupyterlab-lecture3]: https://mybinder.org/v2/gh/mmoelle1/OospCpp/binder?urlpath=git-pull%3Frepo%3Dhttps%253A%252F%252Fgithub.com%252Fmmoelle1%252FOospCpp%26urlpath%3Dlab%252Ftree%252FOospCpp%252Fnotebooks%252Flecture3.ipynb%26branch%3D2024 42 | [binder-jupyterlab-lecture4]: https://mybinder.org/v2/gh/mmoelle1/OospCpp/binder?urlpath=git-pull%3Frepo%3Dhttps%253A%252F%252Fgithub.com%252Fmmoelle1%252FOospCpp%26urlpath%3Dlab%252Ftree%252FOospCpp%252Fnotebooks%252Flecture4.ipynb%26branch%3D2024 43 | [binder-jupyterlab-lecture5]: https://mybinder.org/v2/gh/mmoelle1/OospCpp/binder?urlpath=git-pull%3Frepo%3Dhttps%253A%252F%252Fgithub.com%252Fmmoelle1%252FOospCpp%26urlpath%3Dlab%252Ftree%252FOospCpp%252Fnotebooks%252Flecture5.ipynb%26branch%3D2024 44 | [binder-jupyterlab-lecture6]: https://mybinder.org/v2/gh/mmoelle1/OospCpp/binder?urlpath=git-pull%3Frepo%3Dhttps%253A%252F%252Fgithub.com%252Fmmoelle1%252FOospCpp%26urlpath%3Dlab%252Ftree%252FOospCpp%252Fnotebooks%252Flecture6.ipynb%26branch%3D2024 45 | [binder-jupyterlab-lecture7]: https://mybinder.org/v2/gh/mmoelle1/OospCpp/binder?urlpath=git-pull%3Frepo%3Dhttps%253A%252F%252Fgithub.com%252Fmmoelle1%252FOospCpp%26urlpath%3Dlab%252Ftree%252FOospCpp%252Fnotebooks%252Flecture7.ipynb%26branch%3D2024 46 | 47 | [binder-jupyternb-lecture1]: 48 | https://mybinder.org/v2/gh/mmoelle1/OospCpp/binder?urlpath=git-pull%3Frepo%3Dhttps%253A%252F%252Fgithub.com%252Fmmoelle1%252FOospCpp%26urlpath%3Dtree%252FOospCpp%252Fnotebooks%252Flecture1.ipynb%26branch%3D2024 49 | [binder-jupyternb-lecture2]: 50 | https://mybinder.org/v2/gh/mmoelle1/OospCpp/binder?urlpath=git-pull%3Frepo%3Dhttps%253A%252F%252Fgithub.com%252Fmmoelle1%252FOospCpp%26urlpath%3Dtree%252FOospCpp%252Fnotebooks%252Flecture2.ipynb%26branch%3D2024 51 | [binder-jupyternb-lecture3]: 52 | https://mybinder.org/v2/gh/mmoelle1/OospCpp/binder?urlpath=git-pull%3Frepo%3Dhttps%253A%252F%252Fgithub.com%252Fmmoelle1%252FOospCpp%26urlpath%3Dtree%252FOospCpp%252Fnotebooks%252Flecture3.ipynb%26branch%3D2024 53 | [binder-jupyternb-lecture4]: 54 | https://mybinder.org/v2/gh/mmoelle1/OospCpp/binder?urlpath=git-pull%3Frepo%3Dhttps%253A%252F%252Fgithub.com%252Fmmoelle1%252FOospCpp%26urlpath%3Dtree%252FOospCpp%252Fnotebooks%252Flecture4.ipynb%26branch%3D2024 55 | [binder-jupyternb-lecture5]: 56 | https://mybinder.org/v2/gh/mmoelle1/OospCpp/binder?urlpath=git-pull%3Frepo%3Dhttps%253A%252F%252Fgithub.com%252Fmmoelle1%252FOospCpp%26urlpath%3Dtree%252FOospCpp%252Fnotebooks%252Flecture5.ipynb%26branch%3D2024 57 | [binder-jupyternb-lecture6]: 58 | https://mybinder.org/v2/gh/mmoelle1/OospCpp/binder?urlpath=git-pull%3Frepo%3Dhttps%253A%252F%252Fgithub.com%252Fmmoelle1%252FOospCpp%26urlpath%3Dtree%252FOospCpp%252Fnotebooks%252Flecture6.ipynb%26branch%3D2024 59 | [binder-jupyternb-lecture7]: 60 | https://mybinder.org/v2/gh/mmoelle1/OospCpp/binder?urlpath=git-pull%3Frepo%3Dhttps%253A%252F%252Fgithub.com%252Fmmoelle1%252FOospCpp%26urlpath%3Dtree%252FOospCpp%252Fnotebooks%252Flecture7.ipynb%26branch%3D2024 61 | 62 | [pages-lecture1]: https://mmoelle1.github.io/OospCpp/_static/lecture1.slides.html 63 | [pages-lecture2]: https://mmoelle1.github.io/OospCpp/_static/lecture2.slides.html 64 | [pages-lecture3]: https://mmoelle1.github.io/OospCpp/_static/lecture3.slides.html 65 | [pages-lecture4]: https://mmoelle1.github.io/OospCpp/_static/lecture4.slides.html 66 | [pages-lecture5]: https://mmoelle1.github.io/OospCpp/_static/lecture5.slides.html 67 | [pages-lecture6]: https://mmoelle1.github.io/OospCpp/_static/lecture6.slides.html 68 | [pages-lecture7]: https://mmoelle1.github.io/OospCpp/_static/lecture7.slides.html 69 | 70 | 71 | 80 | © Copyright 2024, Matthias Möller. 81 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | pydata-sphinx-theme 2 | sphinx 3 | jupyter 4 | -------------------------------------------------------------------------------- /docs/source/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # For the full list of built-in configuration values, see the documentation: 4 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 5 | 6 | 7 | # -- Project information ----------------------------------------------------- 8 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information 9 | 10 | project = "OospCpp" 11 | copyright = "2023, Matthias Möller" 12 | author = "Matthias Möller" 13 | release = "2023" 14 | 15 | # -- General configuration --------------------------------------------------- 16 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration 17 | 18 | source_suffix = { 19 | ".rst": "restructuredtext", 20 | ".txt": "markdown", 21 | ".md": "markdown", 22 | } 23 | 24 | extensions = [ 25 | ] 26 | 27 | 28 | templates_path = ["_templates"] 29 | exclude_patterns = [] 30 | 31 | pygments_style = "sphinx" 32 | 33 | 34 | # -- Options for HTML output ------------------------------------------------- 35 | 36 | html_theme = "pydata_sphinx_theme" 37 | html_title = "OospCpp" 38 | html_static_path = ["_static"] 39 | 40 | -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | .. include:: README.rst 2 | 3 | References 4 | ---------- 5 | .. toctree:: 6 | :maxdepth: 1 7 | 8 | Github 9 | -------------------------------------------------------------------------------- /notebooks/lecture-template.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "raw_mimetype": "", 7 | "slideshow": { 8 | "slide_type": "slide" 9 | }, 10 | "tags": [] 11 | }, 12 | "source": [ 13 | "# Object-oriented scientific programming with C++\n", 14 | "\n", 15 | "Matthias Möller, Jonas Thies, Cálin Georgescu, Jingya Li (Numerical Analysis, DIAM)\n", 16 | "\n", 17 | "Lecture 1" 18 | ] 19 | }, 20 | { 21 | "cell_type": "markdown", 22 | "metadata": { 23 | "editable": false, 24 | "slideshow": { 25 | "slide_type": "slide" 26 | }, 27 | "tags": [] 28 | }, 29 | "source": [ 30 | "## What's this course about" 31 | ] 32 | }, 33 | { 34 | "cell_type": "markdown", 35 | "metadata": { 36 | "slideshow": { 37 | "slide_type": "subslide" 38 | }, 39 | "tags": [] 40 | }, 41 | "source": [ 42 | "### Object oriented programming\n", 43 | "\n", 44 | "Learn the **design principles** of OOP (not restricted to C++)" 45 | ] 46 | }, 47 | { 48 | "cell_type": "markdown", 49 | "metadata": { 50 | "editable": false, 51 | "slideshow": { 52 | "slide_type": "subslide" 53 | }, 54 | "tags": [] 55 | }, 56 | "source": [ 57 | "### Matlab example\n", 58 | "\n", 59 | "```Matlab\n", 60 | "A = [1 2; 3 4]\n", 61 | "size(A)\n", 62 | "```\n", 63 | "\n", 64 | "Here, the `size` **functions** is applied to the matrix `A` and determines its size from outside. That means the function `size` must be able to deduce the matrix size. In other words, the matrix size is publicly visible." 65 | ] 66 | }, 67 | { 68 | "cell_type": "markdown", 69 | "metadata": { 70 | "editable": false, 71 | "slideshow": { 72 | "slide_type": "subslide" 73 | }, 74 | "tags": [] 75 | }, 76 | "source": [ 77 | "### Python example\n", 78 | "\n", 79 | "```python\n", 80 | "A = numpy.matrix([[1, 2], [3, 4]])\n", 81 | "A.shape\n", 82 | "```\n", 83 | "\n", 84 | "Here, the matrix `A` provides a _member function_ to determine its size from inside." 85 | ] 86 | }, 87 | { 88 | "cell_type": "markdown", 89 | "metadata": { 90 | "editable": false, 91 | "slideshow": { 92 | "slide_type": "slide" 93 | }, 94 | "tags": [] 95 | }, 96 | "source": [ 97 | "### Header files\n", 98 | "\n", 99 | "At the beginning of each C++ code you include some **header files**, for instance the one for input and output streams" 100 | ] 101 | }, 102 | { 103 | "cell_type": "code", 104 | "execution_count": 2, 105 | "metadata": { 106 | "editable": true, 107 | "slideshow": { 108 | "slide_type": "fragment" 109 | }, 110 | "tags": [] 111 | }, 112 | "outputs": [], 113 | "source": [ 114 | "#include " 115 | ] 116 | }, 117 | { 118 | "cell_type": "markdown", 119 | "metadata": { 120 | "editable": false, 121 | "slideshow": { 122 | "slide_type": "fragment" 123 | }, 124 | "tags": [] 125 | }, 126 | "source": [ 127 | "Now, we can write our first C++ instruction" 128 | ] 129 | }, 130 | { 131 | "cell_type": "code", 132 | "execution_count": 3, 133 | "metadata": { 134 | "editable": true, 135 | "slideshow": { 136 | "slide_type": "fragment" 137 | }, 138 | "tags": [] 139 | }, 140 | "outputs": [ 141 | { 142 | "name": "stdout", 143 | "output_type": "stream", 144 | "text": [ 145 | "Hello World!\n" 146 | ] 147 | } 148 | ], 149 | "source": [ 150 | "std::cout << \"Hello World!\\n\";" 151 | ] 152 | } 153 | ], 154 | "metadata": { 155 | "kernelspec": { 156 | "display_name": "Python 3 (ipykernel)", 157 | "language": "python", 158 | "name": "python3" 159 | }, 160 | "language_info": { 161 | "codemirror_mode": { 162 | "name": "ipython", 163 | "version": 3 164 | }, 165 | "file_extension": ".py", 166 | "mimetype": "text/x-python", 167 | "name": "python", 168 | "nbconvert_exporter": "python", 169 | "pygments_lexer": "ipython3", 170 | "version": "3.11.6" 171 | }, 172 | "rise": { 173 | "autolaunch": true, 174 | "enable_chalkboard": true 175 | } 176 | }, 177 | "nbformat": 4, 178 | "nbformat_minor": 4 179 | } 180 | -------------------------------------------------------------------------------- /notebooks/lecture4.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "metadata": { 5 | "slideshow": { 6 | "slide_type": "slide" 7 | } 8 | }, 9 | "id": "35dcd074", 10 | "cell_type": "markdown", 11 | "source": "# Object-oriented scientific programming with C++\n\nMatthias Möller, Jonas Thies, Cálin Georgescu, Jingya Li (Numerical Analysis, DIAM)\n\nLecture 4" 12 | }, 13 | { 14 | "metadata": { 15 | "slideshow": { 16 | "slide_type": "slide" 17 | } 18 | }, 19 | "id": "3a57f6c5", 20 | "cell_type": "markdown", 21 | "source": "# Overview\n\nLast lecture we started with **template meta programming**\n- Implement type-independent functionality\n - Class templates/function templates\n - Generic attributes being able to hold arbitrary data type\n - Generic member function realizing the default behaviour\n- Implement specialized variants of member functions to support special behaviour, e.g., dot product for complex types\n- Instantiate class with concrete types (double, float, etc.)" 22 | }, 23 | { 24 | "metadata": { 25 | "slideshow": { 26 | "slide_type": "skip" 27 | }, 28 | "tags": [] 29 | }, 30 | "id": "2f3c3e9b-8ea1-4d44-97f9-8019a125d916", 31 | "cell_type": "markdown", 32 | "source": "# Overview\n\n
" 33 | }, 34 | { 35 | "metadata": { 36 | "slideshow": { 37 | "slide_type": "slide" 38 | }, 39 | "tags": [] 40 | }, 41 | "id": "8e82d027", 42 | "cell_type": "markdown", 43 | "source": "# Instantiate class with concrete types (double, float, etc.)\n\nC++ allows you to **partially specialize** class templates" 44 | }, 45 | { 46 | "metadata": { 47 | "trusted": false 48 | }, 49 | "id": "d2748b0d-58f7-4456-9c0f-79645cd4d71c", 50 | "cell_type": "code", 51 | "source": "template\nstd::complex Vector >::dot(const Vector > other) const \n{ \n std::complex d=0;\n for (auto i=0; i\n#include \n\ntemplate\nstruct Demo\n{\n static void info() {\n std::cout << \"Generic info\" << \"\\n\";\n }\n \n static void test() {\n std::cout << \"Generic test\" << \"\\n\";\n }\n};\n\nDemo::info(); // Outputs: Generic info\nDemo, char>::test(); // Outputs: Generic test", 91 | "execution_count": null, 92 | "outputs": [] 93 | }, 94 | { 95 | "metadata": {}, 96 | "id": "5399e025-7451-42bb-bdfa-8481218425bf", 97 | "cell_type": "markdown", 98 | "source": "Go here for visualization: https://www.online-ide.com/GWnUgMLJ3N" 99 | }, 100 | { 101 | "metadata": { 102 | "slideshow": { 103 | "slide_type": "subslide" 104 | } 105 | }, 106 | "id": "c300db4a", 107 | "cell_type": "markdown", 108 | "source": "# Class template specialization\n\n**Task:** implement a template specialization of the entire\n`struct Demo` for `T=float` and `I=long`\n\nNote that template specialization does not imply class inheritance; that is, all attributes/functions that you want to have in a specialized class have to be implemented\n\nThink of class specialization as implementing a new independent `struct Demo` thatjusthasthe same name as the generic `struct Demo`" 109 | }, 110 | { 111 | "metadata": { 112 | "slideshow": { 113 | "slide_type": "subslide" 114 | } 115 | }, 116 | "id": "ad514241", 117 | "cell_type": "markdown", 118 | "source": "**Fully specialized** implementation of the entire **structure**" 119 | }, 120 | { 121 | "metadata": { 122 | "trusted": false 123 | }, 124 | "id": "901443ec-9210-416c-934e-1d0d2e885be2", 125 | "cell_type": "code", 126 | "source": "template<>\nstruct Demo \n{\n static void info() {\n std::cout << \"Fully specialized info\" << std::endl;\n }\n \n static void test() {\n std::cout << \"Fully specialized test\" << std::endl;\n }\n};\n\nDemo::info(); // Outputs: Fully specialized info\nDemo::test(); // Outputs: Fully specialized test", 127 | "execution_count": null, 128 | "outputs": [] 129 | }, 130 | { 131 | "metadata": { 132 | "slideshow": { 133 | "slide_type": "subslide" 134 | } 135 | }, 136 | "id": "aab2b26c", 137 | "cell_type": "markdown", 138 | "source": "**Fully specialized** implementation of the entire **structure**\nbut without a member function test()\n\nNote: run here https://www.online-ide.com/1xpEOkqRAr" 139 | }, 140 | { 141 | "metadata": { 142 | "tags": [], 143 | "trusted": false 144 | }, 145 | "id": "bccf3d70", 146 | "cell_type": "code", 147 | "source": "template\nstruct Demo\n{\n static void info() {\n std::cout << \"Generic info\" << std::endl;\n }\n \n static void test() {\n std::cout << \"Generic test\" << std::endl;\n }\n};\n\n// Full specialization of the Demo class for float and long\ntemplate<>\nstruct Demo \n{\n static void info() {\n std::cout << \"Fully specialized info\" << std::endl;\n }\n \n // Optionally, provide a specialized version of test() if needed\n // static void test() {\n // std::cout << \"Fully specialized test\" << std::endl;\n // }\n};\n\nDemo::info(); // Calls the specialized info\n//Demo::test(); // Calls the specialized test (if defined)", 148 | "execution_count": 2, 149 | "outputs": [] 150 | }, 151 | { 152 | "metadata": { 153 | "slideshow": { 154 | "slide_type": "slide" 155 | } 156 | }, 157 | "id": "6cb3b556", 158 | "cell_type": "markdown", 159 | "source": "# Class-function template specialization\n\n**Task:** implement a specialization of the member function `info()` for `T=float` and `I=long`\n\nSince we only implement a specialization for the individual function `info()`, the implementation of function `test()` from the non-specialized `struct Demo` remains available\n\nThink of member function specialization as superseding individual member functions by specialized variants" 160 | }, 161 | { 162 | "metadata": { 163 | "slideshow": { 164 | "slide_type": "subslide" 165 | } 166 | }, 167 | "id": "40b21ae7", 168 | "cell_type": "markdown", 169 | "source": "**Fully specialized** implementation of **function** `info()`\n```C++\ntemplate<>\nvoid Demo::info() {\n std::cout << \"Fully specialised info\" << std::endl; } \n```\nThis implementation provides the specialization of function\n`info()` and the generic implementation of function `test()`\n```C++\nDemo::info(); // Calls the class-function specialization\nDemo::test(); // Calls the generic implementation\n```" 170 | }, 171 | { 172 | "metadata": { 173 | "slideshow": { 174 | "slide_type": "slide" 175 | } 176 | }, 177 | "id": "6948a035", 178 | "cell_type": "markdown", 179 | "source": "# Class template partial specialization\n\n**Task:** implement a specialization of the entire `struct Demo` for `T=float` and arbitrary template parameter value `I`" 180 | }, 181 | { 182 | "metadata": { 183 | "slideshow": { 184 | "slide_type": "subslide" 185 | } 186 | }, 187 | "id": "b26bf024", 188 | "cell_type": "markdown", 189 | "source": "**Partially specialized** implementation of the **structure**\n\nNote: click here https://www.online-ide.com/bpLsXnCKG8" 190 | }, 191 | { 192 | "metadata": { 193 | "tags": [], 194 | "trusted": false 195 | }, 196 | "id": "db707020", 197 | "cell_type": "code", 198 | "source": "template\nstruct Demo \n{\n static void info() {\n std::cout << \"Generic info\" << std::endl;\n }\n \n static void test() {\n std::cout << \"Generic test\" << std::endl;\n }\n};\n\n// Partial specialization of the Demo class for the first parameter being double\ntemplate\nstruct Demo \n{\n static void info() {\n std::cout << \"Partially specialized info\" << std::endl;\n }\n \n static void test() {\n std::cout << \"Partially specialized test\" << std::endl;\n }\n};\n\nDemo::info(); // Outputs: Partially specialized info\nDemo::test(); // Outputs: Partially specialized test\nDemo::info(); // Outputs: Generic info", 199 | "execution_count": 27, 200 | "outputs": [] 201 | }, 202 | { 203 | "metadata": { 204 | "slideshow": { 205 | "slide_type": "slide" 206 | }, 207 | "tags": [] 208 | }, 209 | "id": "be640e26", 210 | "cell_type": "markdown", 211 | "source": "# Class-function template partial specialization\n\n**Task:** implement a specialization of member function `info()` for `T=float` and arbitrary template parameter value `I`\n\nPartial function template specialization is not **possible in C++**\n```C++\ntemplate\nvoid Demo::info() {...}\n```\n\nStay tuned, there are tricks to solve this problem" 212 | }, 213 | { 214 | "metadata": { 215 | "slideshow": { 216 | "slide_type": "slide" 217 | } 218 | }, 219 | "id": "0d8f79de", 220 | "cell_type": "markdown", 221 | "source": "# Summary template specialization\n\nGiven a templated class with member functions\n- Entire class can be fully or partially specialized\n- Individual member functions can be fully specialized\n- Individual member functions **cannot** be partially specialized\n\nFull/partial class specialization is like implementing a new individual class that can be accessed by the same name\n\nFull function specialization is like superseding individual member functions by specialized variants" 222 | }, 223 | { 224 | "metadata": { 225 | "slideshow": { 226 | "slide_type": "slide" 227 | } 228 | }, 229 | "id": "3daf7ddd", 230 | "cell_type": "markdown", 231 | "source": "# Quiz\n\nRemember the specialized dot product for complex-valued\nvectors from the previous session, will this work?" 232 | }, 233 | { 234 | "metadata": { 235 | "trusted": false 236 | }, 237 | "id": "22bfa419-9a17-45c2-b074-e3130253ff24", 238 | "cell_type": "code", 239 | "source": "template class Vector {\n T dot(const Vector& other) const {...}\n};\n\ntemplate std::complex \nVector >::dot(const Vector > other) const \n{\n std::complex d=0;\n for (auto i=0; iIf a substitution results in an invalid type or expression, type deduction fails. An invalid type or expression is one that would be ill-formed if written using the substituted arguments. Only invalid types and expressions in the immediate context of the function type and its template parameter types can result in a deduction failure.\n\n**SFINAE:** Substitution Failure Is Not An Error" 262 | }, 263 | { 264 | "metadata": { 265 | "slideshow": { 266 | "slide_type": "subslide" 267 | } 268 | }, 269 | "id": "e3dee20b", 270 | "cell_type": "markdown", 271 | "source": "C++11 standard rephrased for our purpose:\n\nIf a template substitution leads to invalid code then the compiler must not throw an error but look for another candidate (i.e. the second templated implementation of our function); an error is just thrown if no other candidate can be found so that the function call remains unresolved" 272 | }, 273 | { 274 | "metadata": { 275 | "slideshow": { 276 | "slide_type": "subslide" 277 | } 278 | }, 279 | "id": "be2aa4cf", 280 | "cell_type": "markdown", 281 | "source": "**SFINAE:** Substitution Failure Is Not An Error\n\n- Write multiple implementations of the same function with\n - the **same name** and\n - the **same input parameters**\n- Ensure – via template meta programming – that **exactly one** at a time results in **valid code** upon substitution of the template parameters and **all other** candidates yield **invalid expressions**" 282 | }, 283 | { 284 | "metadata": { 285 | "slideshow": { 286 | "slide_type": "slide" 287 | } 288 | }, 289 | "id": "d7007a07", 290 | "cell_type": "markdown", 291 | "source": "# Intermezzo: Traits\n\nConsider the `is_double` **function** which returns `true`/`false` depending on the type of the parameter passed via explicit template specialization" 292 | }, 293 | { 294 | "metadata": { 295 | "tags": [], 296 | "trusted": false 297 | }, 298 | "id": "a115b21c", 299 | "cell_type": "code", 300 | "source": "#include \n#include \n\ntemplate\nbool is_double(T a) { return false; }\n\ntemplate<>\nbool is_double(double a) { return true; }\n\nstd::cout << std::boolalpha; // Print 'true' or 'false' for bool values\n\nstd::cout << \"is_int(42): \" << is_double(42) << std::endl; // Prints 'true'\nstd::cout << \"is_int(42.0): \" << is_double(42.0) << std::endl; // Prints 'true'\nstd::cout << \"is_int('A'): \" << is_double('A') << std::endl; // Prints 'false'", 301 | "execution_count": 26, 302 | "outputs": [] 303 | }, 304 | { 305 | "metadata": {}, 306 | "id": "8bb168e2-ff9a-46cb-8a9e-9259eff58749", 307 | "cell_type": "markdown", 308 | "source": "NOTE: Go to this link to run https://www.online-ide.com/wkmgjVG8yH" 309 | }, 310 | { 311 | "metadata": { 312 | "slideshow": { 313 | "slide_type": "subslide" 314 | } 315 | }, 316 | "id": "709a9bef", 317 | "cell_type": "markdown", 318 | "source": "Consider the templated `is_double` **structure** with specialization" 319 | }, 320 | { 321 | "metadata": { 322 | "tags": [], 323 | "trusted": false 324 | }, 325 | "id": "f9e81705", 326 | "cell_type": "code", 327 | "source": "#include \n\ntemplate\nstruct is_double\n{\n const static bool value = false;\n};\n\ntemplate<>\nstruct is_double\n{\n const static bool value = true;\n};\n\nstd::cout << \"is_double::value: \" << is_double::value << std::endl; // Prints 'false'\nstd::cout << \"is_double::value: \" << is_double::value << std::endl; // Prints 'true'", 328 | "execution_count": 9, 329 | "outputs": [] 330 | }, 331 | { 332 | "metadata": {}, 333 | "id": "63fc9020-0bea-41e2-a065-6aa20c973f26", 334 | "cell_type": "markdown", 335 | "source": "NOTE: Go to this link to run https://www.online-ide.com/0RIfmNvHFK" 336 | }, 337 | { 338 | "metadata": { 339 | "slideshow": { 340 | "slide_type": "subslide" 341 | } 342 | }, 343 | "id": "3577d66d", 344 | "cell_type": "markdown", 345 | "source": "Detect if a given type is `double` without passing a parameter\n```C++\nstd::cout << is_double::value << std::endl;\nstd::cout << is_double::value << std::endl;\n```\nThe `is_double` **type trait** can be used in templated functions\n```C++\ntemplate\nvoid test(T a)\n{\n if (is_double::value)\n std::cout << \"Double :\" << a << std::endl;\n else\n std::cout << \"Non-Double :\" << a << std::endl;\n}\n```" 346 | }, 347 | { 348 | "metadata": { 349 | "slideshow": { 350 | "slide_type": "subslide" 351 | } 352 | }, 353 | "id": "5ab6d885", 354 | "cell_type": "markdown", 355 | "source": "The `is_double` **type trait** is evaluated at compile time in contrast to the `is_double()` **function** which (theoretically) might trigger an extra function call at run time (slow!)\n\nA smart compiler will eliminate the if-else clause\n\n```C++\nvoid test(double a)\n {\n if (is_double::value)\n std::cout << \"Double :\" << a << std::endl;\n else\n std::cout << \"Non-Double :\" << a << std::endl;\n}\n```" 356 | }, 357 | { 358 | "metadata": { 359 | "slideshow": { 360 | "slide_type": "subslide" 361 | } 362 | }, 363 | "id": "7e5e9d04", 364 | "cell_type": "markdown", 365 | "source": "C++ brings many **type traits** via `#include `\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
FunctionDescription
is_class<T>Type T is of class type
is_const<T>Type T has const qualifier
is_floating_point<T>Type T is floating point (float, double, long)
is_fundamental<T>Type T is of fundamental type (int, double, ...)
is_integral<T>Type T is of integral type (int, long int, ...)
is_pointer<T>Type T is of pointer type
\n\nFor a complete list of standard type traits look at:http://www.cplusplus.com/reference/type_traits/" 366 | }, 367 | { 368 | "metadata": { 369 | "slideshow": { 370 | "slide_type": "subslide" 371 | } 372 | }, 373 | "id": "9c0b9ee8", 374 | "cell_type": "markdown", 375 | "source": "The aforementioned C++ **standard type traits** provide\n- Member constants:\n `value (=true/false)`\n- Member types:\n `value_type (=bool)` and `type (=true_type/false_type)`\n\nMember constants/types can be directly accessed\n```C++\nis_fundamental::value // true\nis_fundamental::value_type // bool \n```" 376 | }, 377 | { 378 | "metadata": { 379 | "slideshow": { 380 | "slide_type": "subslide" 381 | } 382 | }, 383 | "id": "4fccc3ef", 384 | "cell_type": "markdown", 385 | "source": "# Intermezzo: Types Traits\n\nC++ provides type traits that **operate on the type**" 386 | }, 387 | { 388 | "metadata": { 389 | "slideshow": { 390 | "slide_type": "subslide" 391 | }, 392 | "tags": [], 393 | "trusted": false 394 | }, 395 | "id": "ad1c76b2", 396 | "cell_type": "code", 397 | "source": "#include \n#include \n#include \n\ntypedef std::add_const::type A;\ntypedef std::add_const::type B;\ntypedef std::add_pointer::type C;\ntypedef std::add_pointer::type D;\ntypedef std::add_pointer::type E;\ntypedef std::add_pointer::type F;\ntypedef std::add_pointer::type G;\n\nstd::cout << \"Type A: \" << typeid(A).name() << \" (expected: const int)\" << std::endl;\nstd::cout << \"Type B: \" << typeid(B).name() << \" (expected: const int)\" << std::endl;\nstd::cout << \"Type C: \" << typeid(C).name() << \" (expected: int*)\" << std::endl;\nstd::cout << \"Type D: \" << typeid(D).name() << \" (expected: const int*)\" << std::endl;\nstd::cout << \"Type E: \" << typeid(E).name() << \" (expected: int*)\" << std::endl;\nstd::cout << \"Type F: \" << typeid(F).name() << \" (expected: int**)\" << std::endl;\nstd::cout << \"Type G: \" << typeid(G).name() << \" (expected: int(*)(int))\" << std::endl;", 398 | "execution_count": 17, 399 | "outputs": [ 400 | { 401 | "name": "stdout", 402 | "output_type": "stream", 403 | "text": "Type A: i (expected: const int)\nType B: i (expected: const int)\nType C: Pi (expected: int*)\nType D: PKi (expected: const int*)\nType E: Pi (expected: int*)\nType F: PPi (expected: int**)\nType G: PFiiE (expected: int(*)(int))\n" 404 | }, 405 | { 406 | "execution_count": 17, 407 | "output_type": "execute_result", 408 | "data": { 409 | "text/plain": "@0x7efd5e99dde0" 410 | }, 411 | "metadata": {} 412 | } 413 | ] 414 | }, 415 | { 416 | "metadata": { 417 | "slideshow": { 418 | "slide_type": "subslide" 419 | } 420 | }, 421 | "id": "30ccb64c", 422 | "cell_type": "markdown", 423 | "source": "C++ provides type traits that **operate on the type**\n\n```C++\ntypedef remove_const< int> A; // int (unchanged)\ntypedef remove_const B; // int\n\ntypedef remove_pointer C; // int\ntypedef remove_pointer D; // int\ntypedef remove_pointer E; // int*\ntypedef remove_pointer F; // const int\ntypedef remove_pointer G; // const int\ntypedef remove_pointer H; // int\n```" 424 | }, 425 | { 426 | "metadata": { 427 | "slideshow": { 428 | "slide_type": "subslide" 429 | } 430 | }, 431 | "id": "1855cf1b", 432 | "cell_type": "markdown", 433 | "source": "C++ provides type traits that **operate on two types**\n\nCheck if two types are **exactly** the same (including qualifiers)\n\n```C++\nbool is_same::value\n\nbool is_same::value // true\nbool is_same::value // false\nbool is_same,\n remove_const >::value // true\n```" 434 | }, 435 | { 436 | "metadata": { 437 | "slideshow": { 438 | "slide_type": "skip" 439 | }, 440 | "tags": [], 441 | "trusted": false 442 | }, 443 | "id": "a9ec0cfb", 444 | "cell_type": "code", 445 | "source": "#include \n#include \n\ntypedef std::remove_const< int>::type A; // int\ntypedef std::remove_const::type B; // int\n\nstd::cout << std::boolalpha; // Print 'true' or 'false' for bool values\n\nstd::cout << \"is_same::value: \" << std::is_same::value << '\\n'; // true\nstd::cout << \"is_same::value: \" << std::is_same::value << '\\n'; // true\nstd::cout << \"is_same::value: \" << std::is_same::value << '\\n'; // false\nstd::cout << \"is_same, remove_const>::value: \" \n << std::is_same::type, std::remove_const::type>::value << '\\n'; // true", 446 | "execution_count": 25, 447 | "outputs": [ 448 | { 449 | "name": "stdout", 450 | "output_type": "stream", 451 | "text": "is_same::value: true\nis_same::value: true\nis_same::value: false\nis_same, remove_const>::value: true\n" 452 | }, 453 | { 454 | "execution_count": 25, 455 | "output_type": "execute_result", 456 | "data": { 457 | "text/plain": "@0x7efd5e99dde0" 458 | }, 459 | "metadata": {} 460 | } 461 | ] 462 | }, 463 | { 464 | "metadata": { 465 | "slideshow": { 466 | "slide_type": "subslide" 467 | } 468 | }, 469 | "id": "15351b18", 470 | "cell_type": "markdown", 471 | "source": "C++ provides type traits that **operate on two types**\n\nCheck if type B is derived from type A" 472 | }, 473 | { 474 | "metadata": { 475 | "tags": [], 476 | "trusted": false 477 | }, 478 | "id": "0328f4f4", 479 | "cell_type": "code", 480 | "source": "#include \n#include \n\nstruct A {};\nstruct B : A {};\n\nstd::cout << std::boolalpha; // Print 'true' or 'false' for bool values\n\nstd::cout << \"is_base_of::value: \" << std::is_base_of::value << '\\n'; // true\nstd::cout << \"is_base_of::value: \" << std::is_base_of::value << '\\n'; // true\nstd::cout << \"is_base_of::value: \" << std::is_base_of::value << '\\n'; // false\nstd::cout << \"is_base_of::value: \" << std::is_base_of::value << '\\n'; // true", 481 | "execution_count": 19, 482 | "outputs": [ 483 | { 484 | "name": "stdout", 485 | "output_type": "stream", 486 | "text": "is_base_of::value: true\nis_base_of::value: true\nis_base_of::value: false\nis_base_of::value: true\n" 487 | }, 488 | { 489 | "execution_count": 19, 490 | "output_type": "execute_result", 491 | "data": { 492 | "text/plain": "@0x7efd5e99dde0" 493 | }, 494 | "metadata": {} 495 | } 496 | ] 497 | }, 498 | { 499 | "metadata": { 500 | "slideshow": { 501 | "slide_type": "subslide" 502 | } 503 | }, 504 | "id": "b821d37a", 505 | "cell_type": "markdown", 506 | "source": "C++ provides type trait to **enable types conditionally**\n\nIf `is_odd` is called with an **integral type** (e.g., `int`) the compiler\nexpands the following templated function as follows\n\n```C++\nbool is_odd(int i) { return bool(i%2); }\n```\nNOTE: Go to this link to run https://www.online-ide.com/R5hs4oQSAD" 507 | }, 508 | { 509 | "metadata": { 510 | "tags": [], 511 | "trusted": false 512 | }, 513 | "id": "a07ea5df", 514 | "cell_type": "code", 515 | "source": "#include \n#include \n\ntemplate\ntypename std::enable_if::value, bool>::type\nis_odd(T i) {\n return bool(i % 2);\n}\n\n\nint i = 2;\nstd::cout << \"i is odd: \" << is_odd(i) << std::endl;", 516 | "execution_count": null, 517 | "outputs": [] 518 | }, 519 | { 520 | "metadata": { 521 | "slideshow": { 522 | "slide_type": "subslide" 523 | } 524 | }, 525 | "id": "211c8f0f", 526 | "cell_type": "markdown", 527 | "source": "C++ provides type trait to **enable types conditionally**\n\n```C++\ntemplate\ntypename std::enable_if::value, bool>::type\nis_odd(T i) { \n return bool(i%2); \n}\n\nfloat i=2;\nstd::cout << \"i is odd :\" << is_odd(i) << std::endl;\n```\n\nIf `is_odd` is called with a **non-integral type** (e.g., `float`) the compiler expands the above templated function as follows\n\n```C++\nis_odd(float i) { return bool(i%2); } // compiler error\n```" 528 | }, 529 | { 530 | "metadata": { 531 | "slideshow": { 532 | "slide_type": "slide" 533 | } 534 | }, 535 | "id": "f8522388", 536 | "cell_type": "markdown", 537 | "source": "# SFINAE revisited\n\n**SFINAE:** Substitution Failure Is Not An Error\n\n- Write multiple implementations of the same function with\n - the **same name** and\n - the **same input parameters**\n- Ensure using the `enable_if` **type trait** that exactly one at a time results in **valid code** upon substitution of template parameters and **all other** candidates yield **invalid expressions**" 538 | }, 539 | { 540 | "metadata": { 541 | "slideshow": { 542 | "slide_type": "subslide" 543 | } 544 | }, 545 | "id": "719e97ce", 546 | "cell_type": "markdown", 547 | "source": "Consider the `info()` member function\n```C++\ntemplate \nstruct Demo {\n static void info() { ... };\n};\n```\n\nEnable return type `void` only in case `I=int` and let `info()` have\nno return type (=invalid code) if I is of any other type\n```C++\nbool v = std::is_same::value // either true or false\nstd::enable_if::type // either void or empty \n```" 548 | }, 549 | { 550 | "metadata": { 551 | "slideshow": { 552 | "slide_type": "slide" 553 | }, 554 | "tags": [] 555 | }, 556 | "id": "f60bae8f", 557 | "cell_type": "markdown", 558 | "source": "# SFINAE revisited\n\nFirst attempt of partially specialized `info()` member function\n\n```C++\ntemplate\nstruct Demo \n{\n // partial specialization for I=int\n typename std::enable_if< std::is_same::value, void>::type\n static info() { ... };\n\n // partial specialization for I!=int\n typename std::enable_if::value, void>::type\n static info() { ... };\n};\n```\n\nThis code will **not compile**; we need to introduce an extra function template parameter for the `info()` function" 559 | }, 560 | { 561 | "metadata": { 562 | "slideshow": { 563 | "slide_type": "subslide" 564 | } 565 | }, 566 | "id": "10df3932", 567 | "cell_type": "markdown", 568 | "source": "Partially specialized `info()` member function (now working!)\n```C++\ntemplate\nstruct Demo \n{\n template\n typename std::enable_if< std::is_same::value, void>::type\n static info() { ... };\n \n template\n typename std::enable_if::value, void>::type\n static info() { ... };\n};\n```" 569 | }, 570 | { 571 | "metadata": { 572 | "slideshow": { 573 | "slide_type": "subslide" 574 | } 575 | }, 576 | "id": "32dcd7f4", 577 | "cell_type": "markdown", 578 | "source": "In words...\n- Introduce an **extra function template parameter** `J` that, by\ndefault, takes the value of the class template parameter `I`\n```C++\ntemplate\n```\n- Make type traits depend on extra template parameter `J`\n```C++\ntypename std::enable_if< std::is_same::value, void>::type\n```\n\n- Make sure that exactly one member function leads to valid code\n```C++\ntypename std::enable_if::value, void>::type\n```" 579 | }, 580 | { 581 | "metadata": { 582 | "slideshow": { 583 | "slide_type": "slide" 584 | }, 585 | "tags": [] 586 | }, 587 | "id": "1aff9496", 588 | "cell_type": "markdown", 589 | "source": "# Dot product revisited\n\nLet us reconsider the dot product for complex-valued vectors\n\nUse **SFINAE paradigm** to realise alternative implementations\nof the dot product for real- and complex-valued types\n\nStrategy:\n- Write **type trait** `is_complex` that has `value=true`if `T` is of type `std::complex` and `value=false` otherwise\n- Use **type trait** `std::enable_if<...>` to distinguish between real- and complex-valued implementation of the dot product" 590 | }, 591 | { 592 | "metadata": { 593 | "slideshow": { 594 | "slide_type": "slide" 595 | } 596 | }, 597 | "id": "ed93f696", 598 | "cell_type": "markdown", 599 | "source": "# Type trait `is_complex`\n\nFirst implementation of type trait `is_complex` (will suffice for\nour purpose but is not really in line with standard traits)\n\n```C++\ntemplate\nstruct is_complex\n { static const bool value = false; };\n\ntemplate<>\nstruct is_complex > \n { static const bool value = true; };\n\ntemplate<>\nstruct is_complex > \n { static const bool value = true; };\n```" 600 | }, 601 | { 602 | "metadata": { 603 | "slideshow": { 604 | "slide_type": "subslide" 605 | } 606 | }, 607 | "id": "18f44fd1", 608 | "cell_type": "markdown", 609 | "source": "C++ standard way to implement type traits is by deriving\n`is_complex` from structure `std::integral_constant`\n\n```C++\ntemplate\nstruct is_complex\n: std::integral_constant >::value || \n std::is_same >::value > {};\n```\nLogical combination (`&&`, `||`) of all `std::complex` types that should be supported by the `is_complex` type trait" 610 | }, 611 | { 612 | "metadata": { 613 | "slideshow": { 614 | "slide_type": "subslide" 615 | } 616 | }, 617 | "id": "e54332b8", 618 | "cell_type": "markdown", 619 | "source": "Implementation of dot product for **complex-valued types** \n```C++\ntemplate\nclass Vector {\n...\n template\n typename std::enable_if::value, U>::type \n dot(const Vector& other) const {\n T d=0;\n for (auto i=0; i\nclass Vector {\n...\n template\n typename std::enable_if::value, U>::type \n dot(const Vector& other) const {\n T d=0;\n for (auto i=0; i`)are a new feature in C++11\n\nFor a complete list of standard type traits look at: http://www.cplusplus.com/reference/type_traits/" 640 | }, 641 | { 642 | "metadata": { 643 | "slideshow": { 644 | "slide_type": "slide" 645 | } 646 | }, 647 | "id": "abfa4db2", 648 | "cell_type": "markdown", 649 | "source": "# SFINAE Quiz\n\nWhat does this code do?\n```c++\nstruct A {};\nstruct B : A {};\nstruct C {};\n\ntemplate\ntypename auto get_base_type(T t) {\n typename std::conditional::value, A, T>::type ReturnType;\n return ReturnType(t);\n}\n```" 650 | }, 651 | { 652 | "metadata": { 653 | "slideshow": { 654 | "slide_type": "subslide" 655 | } 656 | }, 657 | "id": "3eeb6b59", 658 | "cell_type": "markdown", 659 | "source": "See the `get_base_type` function in action\n```C++\nA a; B b; C c;\ntypeid(a).name() // -> 1A\ntypeid(b).name() // -> 1B\ntypeid(c).name() // -> 1C\n\ntypeid(get_base_type(a)).name() // -> 1A\ntypeid(get_base_type(b)).name() // -> 1A\ntypeid(get_base_type(c)).name() // -> 1C\n```" 660 | }, 661 | { 662 | "metadata": { 663 | "slideshow": { 664 | "slide_type": "slide" 665 | } 666 | }, 667 | "id": "423c1730", 668 | "cell_type": "markdown", 669 | "source": "# Final word on SFINAE\n\nRecall that we started the SFINAE-journey since we needed partial specialization of the dot-product member function\n\nIt is also possible to **specialize the conj-function** instead\n\nHow would you implement the function `std::conj(...)`?\n\n- What return type should we expect for real-valued data?\n- What return type should we expect for complex-valued data?" 670 | }, 671 | { 672 | "metadata": { 673 | "slideshow": { 674 | "slide_type": "subslide" 675 | } 676 | }, 677 | "id": "cac5b03e", 678 | "cell_type": "markdown", 679 | "source": "A possible implementation of the function `std::conj(...)` that uses the self-written `is_complex` type trait\n```C++\ntemplate\ntypename std::enable_if::value, T>::type static conj(T t)\n{ return T(t.real(), -t.imag()); }\n\ntemplate\ntypename std::enable_if::value, T>::type static conj(T t)\n{ return T(t); }\n```" 680 | } 681 | ], 682 | "metadata": { 683 | "celltoolbar": "Slideshow", 684 | "kernelspec": { 685 | "name": "xcpp17", 686 | "display_name": "C++17", 687 | "language": "C++17" 688 | }, 689 | "language_info": { 690 | "codemirror_mode": "text/x-c++src", 691 | "file_extension": ".cpp", 692 | "mimetype": "text/x-c++src", 693 | "name": "c++", 694 | "version": "17" 695 | }, 696 | "rise": { 697 | "autolaunch": true, 698 | "enable_chalkboard": true 699 | } 700 | }, 701 | "nbformat": 4, 702 | "nbformat_minor": 5 703 | } 704 | -------------------------------------------------------------------------------- /notebooks/lecture5.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "f02b0e2e", 6 | "metadata": { 7 | "slideshow": { 8 | "slide_type": "slide" 9 | } 10 | }, 11 | "source": [ 12 | "# Object-oriented scientific programming with C++\n", 13 | "\n", 14 | "Matthias Möller, Jonas Thies, Cálin Georgescu, Jingya Li (Numerical Analysis, DIAM)\n", 15 | "\n", 16 | "Lecture 5" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "id": "d2392445", 22 | "metadata": { 23 | "cell_style": "center", 24 | "slideshow": { 25 | "slide_type": "slide" 26 | } 27 | }, 28 | "source": [ 29 | "##
Goal of this lecture
\n", 30 | "\n", 31 | "Enumerators \n", 32 | "\n", 33 | "Type aliases \n", 34 | "\n", 35 | "Variadic template parameters\n", 36 | "\n", 37 | "C++ standard container classes and algorithms\n", 38 | "\n", 39 | "Iterators\n", 40 | "\n", 41 | "Range-based and for-each for loops" 42 | ] 43 | }, 44 | { 45 | "cell_type": "markdown", 46 | "id": "4500c017", 47 | "metadata": { 48 | "cell_style": "center", 49 | "slideshow": { 50 | "slide_type": "slide" 51 | } 52 | }, 53 | "source": [ 54 | "##
Enumerators
\n", 55 | "Enumerators make it possible to collect named values\n", 56 | "`enum Color { red, green, blue };`\n", 57 | "\n", 58 | "Named values are mapped to, e.g., `red=0, green=1, blue=2`\n", 59 | "\n", 60 | "Usage\n", 61 | "\n", 62 | "```C++\n", 63 | "Color col = Color::red; switch col {\n", 64 | " case Color::red: // do something\n", 65 | " break;\n", 66 | " case Color::green: // do something else\n", 67 | " break;\n", 68 | "}\n", 69 | "```" 70 | ] 71 | }, 72 | { 73 | "cell_type": "markdown", 74 | "id": "41d1727b", 75 | "metadata": { 76 | "slideshow": { 77 | "slide_type": "subslide" 78 | } 79 | }, 80 | "source": [ 81 | "##
Enumerators
\n", 82 | "Enumerators can be initialised explicitly\n", 83 | "```C++\n", 84 | "enum Color { red=2, green=4, blue=8 };\n", 85 | "```\n", 86 | "Enumerators can be derived from a particular integral type\n", 87 | "```C++\n", 88 | "enum Color : int { red=2, green=4, blue=8 };\n", 89 | "```\n", 90 | "Enumerators can make use of arithmetic operations\n", 91 | "```C++\n", 92 | "enum Color { red=2, green=4, blue=8,\n", 93 | " cyan = red + green };\n", 94 | "```\n", 95 | "However, an enumerator must not occur more than once\n", 96 | "\n", 97 | "`enum TrafficLight {`~~red~~`, yellow,`~~green~~` };`" 98 | ] 99 | }, 100 | { 101 | "cell_type": "markdown", 102 | "id": "3e4e8395", 103 | "metadata": { 104 | "slideshow": { 105 | "slide_type": "subslide" 106 | } 107 | }, 108 | "source": [ 109 | "##
Scoped Enumerators
\n", 110 | "C++11 introduces **scoped enumerators** which can occur\n", 111 | "more than once (since they have different scopes!)\n", 112 | "```C++\n", 113 | "enum class Color { red, green, blue };\n", 114 | "enum class TrafficLight { red, yellow, green };\n", 115 | "```\n", 116 | "For the rest, scoped enumerators can be used exactly in the same way as non-scoped enumerators\n", 117 | "\n", 118 | "```C++\n", 119 | "enum class Color { red=2, green=4, blue=8 };\n", 120 | "enum class Color : int { red=2, green=4, blue=8 };\n", 121 | "enum class Color { red=2, green=4, blue=8,\n", 122 | " cyan = red + green };\n", 123 | "```" 124 | ] 125 | }, 126 | { 127 | "cell_type": "markdown", 128 | "id": "04c79a21", 129 | "metadata": { 130 | "slideshow": { 131 | "slide_type": "slide" 132 | } 133 | }, 134 | "source": [ 135 | "##
Type aliases
\n", 136 | "_Implementation I_: type aliases via typedef\n", 137 | "```C++\n", 138 | "template\n", 139 | "struct trait {\n", 140 | " typedef T type; // type is a type\n", 141 | " static const T value = v; // value is a variable\n", 142 | " };\n", 143 | "```\n", 144 | "\n", 145 | "_Implementation II (since C++11)_: type aliases via using\n", 146 | "\n", 147 | "```C++\n", 148 | "template\n", 149 | "struct trait {\n", 150 | " using type = T; // type is a type\n", 151 | " static const T value = v; // value is a variable\n", 152 | " };\n", 153 | "```" 154 | ] 155 | }, 156 | { 157 | "cell_type": "markdown", 158 | "id": "05157fab", 159 | "metadata": { 160 | "slideshow": { 161 | "slide_type": "subslide" 162 | } 163 | }, 164 | "source": [ 165 | "##
Type aliases
\n", 166 | "\n", 167 | "https://www.online-ide.com/RLlfvTsGpK" 168 | ] 169 | }, 170 | { 171 | "cell_type": "code", 172 | "execution_count": 1, 173 | "id": "b3d1e71d", 174 | "metadata": { 175 | "tags": [] 176 | }, 177 | "outputs": [], 178 | "source": [ 179 | "#include \n", 180 | "#include \n", 181 | "\n", 182 | "\n", 183 | "template\n", 184 | "struct trait {\n", 185 | " typedef T type; // type is a type\n", 186 | " static const T value = v; // value is a variable\n", 187 | "};\n", 188 | "\n", 189 | "int main() {\n", 190 | " typedef trait mytrait; // before C++11\n", 191 | " // using mytrait = trait; // since C++11\n", 192 | "\n", 193 | " std::cout << mytrait::value << \" \"\n", 194 | " << typeid(mytrait::type).name()\n", 195 | " << std::endl;\n", 196 | "\n", 197 | " return 0;\n", 198 | "}" 199 | ] 200 | }, 201 | { 202 | "cell_type": "markdown", 203 | "id": "90b71d8f", 204 | "metadata": { 205 | "slideshow": { 206 | "slide_type": "slide" 207 | } 208 | }, 209 | "source": [ 210 | "##
Intermezzo: `using` vs. `typedef`
\n", 211 | "Remember the function pointers from session 3" 212 | ] 213 | }, 214 | { 215 | "cell_type": "code", 216 | "execution_count": 9, 217 | "id": "c4b39694-cc0e-410a-ac97-a8e425b0d0c3", 218 | "metadata": { 219 | "tags": [] 220 | }, 221 | "outputs": [ 222 | { 223 | "name": "stdout", 224 | "output_type": "stream", 225 | "text": [ 226 | "2.3\n" 227 | ] 228 | } 229 | ], 230 | "source": [ 231 | "#include \n", 232 | "double myfunc0(double x) { return x; }\n", 233 | "\n", 234 | "using funcPtr = double(*) (double);\n", 235 | "funcPtr f = myfunc0;\n", 236 | "std::cout << f(2.3) << std::endl;" 237 | ] 238 | }, 239 | { 240 | "cell_type": "markdown", 241 | "id": "ac86bbc5", 242 | "metadata": { 243 | "slideshow": { 244 | "slide_type": "subslide" 245 | } 246 | }, 247 | "source": [ 248 | "##
Intermezzo: `using` vs. `typedef`
\n", 249 | "This becomes much less intuitive with typedef" 250 | ] 251 | }, 252 | { 253 | "cell_type": "code", 254 | "execution_count": 1, 255 | "id": "162a617c", 256 | "metadata": { 257 | "tags": [] 258 | }, 259 | "outputs": [ 260 | { 261 | "name": "stdout", 262 | "output_type": "stream", 263 | "text": [ 264 | "2.3\n" 265 | ] 266 | }, 267 | { 268 | "data": { 269 | "text/plain": [ 270 | "@0x7f2a8206dde0" 271 | ] 272 | }, 273 | "execution_count": 1, 274 | "metadata": {}, 275 | "output_type": "execute_result" 276 | } 277 | ], 278 | "source": [ 279 | "#include \n", 280 | "\n", 281 | "double myfunc1(double x) {\n", 282 | " return x;\n", 283 | "}\n", 284 | "\n", 285 | "typedef double (funcPtr)(double); // Function pointer type\n", 286 | "funcPtr* f = myfunc1; // Assign myfunc1 to pointer f\n", 287 | "std::cout << f(2.3) << std::endl; // Use the function pointer to call myfunc1\n" 288 | ] 289 | }, 290 | { 291 | "cell_type": "markdown", 292 | "id": "36d2bda4", 293 | "metadata": { 294 | "slideshow": { 295 | "slide_type": "slide" 296 | } 297 | }, 298 | "source": [ 299 | "##
Variadic templates
\n", 300 | "**Task:** implement a function that takes an **arbitrary number** of possibly **different variables** and computes their sum\n", 301 | "```C++\n", 302 | "cout << sum(1.0) << endl;\n", 303 | "cout << sum(1.0, 1.0) << endl;\n", 304 | "cout << sum(1.0, (int)1) << endl;\n", 305 | "cout << sum(1.0, (int)1, (float)1.3, (double)1.3) << endl;\n", 306 | "```" 307 | ] 308 | }, 309 | { 310 | "cell_type": "markdown", 311 | "id": "11616b1c", 312 | "metadata": { 313 | "slideshow": { 314 | "slide_type": "subslide" 315 | } 316 | }, 317 | "source": [ 318 | "##
Variadic templates
\n", 319 | "None of the template meta programming techniques we know so far will solve this problem with satisfaction\n", 320 | "\n", 321 | "New concept in C++11: **variadic template parameters**\n", 322 | "\n", 323 | "**Idea:** reformulate the problem as “one + rest”:\n", 324 | "\n", 325 | "`sum(x1,x2,x3,...,xn) = x1 + sum(x2,x3,...,xn)`\n", 326 | "\n", 327 | "That is, we combine recursion and function overloading with the ability to accept an arbitrary parameter list" 328 | ] 329 | }, 330 | { 331 | "cell_type": "markdown", 332 | "id": "9b28ce5d", 333 | "metadata": { 334 | "slideshow": { 335 | "slide_type": "subslide" 336 | } 337 | }, 338 | "source": [ 339 | "##
Variadic templates
\n", 340 | "Function overload for **one argument**\n", 341 | "```C++\n", 342 | "template\n", 343 | "double sum(T arg) { return arg; }\n", 344 | "```\n", 345 | "Function overload for **more than one argument**\n", 346 | "```C++\n", 347 | "template\n", 348 | "double sum(T arg, Ts ... args)\n", 349 | "{ return arg + sum(args...); }\n", 350 | "```\n", 351 | "The **template parameter pack** \n", 352 | "```C++\n", 353 | "template\n", 354 | "```\n", 355 | "accepts zero or more template arguments but there can only be one template parameter pack per function." 356 | ] 357 | }, 358 | { 359 | "cell_type": "markdown", 360 | "id": "f2af3edd", 361 | "metadata": { 362 | "slideshow": { 363 | "slide_type": "subslide" 364 | } 365 | }, 366 | "source": [ 367 | "##
Variadic templates
\n", 368 | "The number of arguments in the parameter pack can be\n", 369 | "detected using the `sizeof...()` function\n", 370 | "```C++\n", 371 | "template\n", 372 | " int length(Ts ... args)\n", 373 | " {\n", 374 | " return sizeof...(args);\n", 375 | " }\n", 376 | "```\n", 377 | "**Task:** Write a type trait that determines the number of arguments passed to a function as parameter pack. In other words, implement the `sizeof...()` function yourself." 378 | ] 379 | }, 380 | { 381 | "cell_type": "markdown", 382 | "id": "5a819ea4", 383 | "metadata": { 384 | "slideshow": { 385 | "slide_type": "slide" 386 | } 387 | }, 388 | "source": [ 389 | "##
Automatic return type deduction
\n", 390 | "**Task:** Implement the sum function for an arbitrary number of parameters using automatic return type deduction\n", 391 | "\n", 392 | "Function overload for **one argument** (with C++11)\n", 393 | "```C++\n", 394 | "template\n", 395 | "auto sum(T arg) -> decltype(arg)\n", 396 | "{ return arg; }\n", 397 | "```\n", 398 | "\n", 399 | "Function overload for **one argument** (with C++14)\n", 400 | "```C++\n", 401 | "template\n", 402 | "auto sum(T arg)\n", 403 | "{ return arg; }\n", 404 | "```" 405 | ] 406 | }, 407 | { 408 | "cell_type": "markdown", 409 | "id": "e56389b6", 410 | "metadata": { 411 | "slideshow": { 412 | "slide_type": "subslide" 413 | } 414 | }, 415 | "source": [ 416 | "##
Automatic return type deduction
\n", 417 | "Function overload for **more than one argument** (C++11)\n", 418 | "```C++\n", 419 | "template\n", 420 | "auto sum(T arg, Ts ... args)\n", 421 | "-> typename std::common_type::type\n", 422 | " { return arg + sum(args...); }\n", 423 | "```\n", 424 | "Function overload for **more than one argument** (C++14)\n", 425 | "```C++\n", 426 | "template\n", 427 | " auto sum(T arg, Ts ... args)\n", 428 | " { return arg + sum(args...); }\n", 429 | "```" 430 | ] 431 | }, 432 | { 433 | "cell_type": "markdown", 434 | "id": "2e56f068", 435 | "metadata": { 436 | "slideshow": { 437 | "slide_type": "slide" 438 | } 439 | }, 440 | "source": [ 441 | "##
C++ standard containers
\n", 442 | "**Aim:** provide a set of universal container classes that\n", 443 | " - can **store arbitrary types** (in general, only objects of the same type (in each container; `std::tuple` for multi-type containers)\n", 444 | " - provide a **uniform interface** to insert, delete, access, and manipulate, items and iterate over the items stored\n", 445 | " - provide optimal implementations of **standard data structures**, e.g., double-linked lists, balanced trees (red-black tree)" 446 | ] 447 | }, 448 | { 449 | "cell_type": "markdown", 450 | "id": "545f9a34", 451 | "metadata": { 452 | "slideshow": { 453 | "slide_type": "subslide" 454 | } 455 | }, 456 | "source": [ 457 | "##
C++ standard containers
\n", 458 | "• `std::array`:array with compile-time size (non-resizable) \n", 459 | "\n", 460 | "• `std::vector`:array with run-time size (resizable)\n", 461 | "\n", 462 | "• `std::list`:double-linked list\n", 463 | "\n", 464 | "• `std::forward_list`:single-linked list\n", 465 | "\n", 466 | "• `std::stack`:Last-In-First-Out stack\n", 467 | "\n", 468 | "• `std::queue`:First-In-First-Out queue\n", 469 | "\n", 470 | "• `std::set/std::multiset`:Set of unique elements\n", 471 | "\n", 472 | "• `std::map/std::multimap`:Set of (key,value) elements" 473 | ] 474 | }, 475 | { 476 | "cell_type": "markdown", 477 | "id": "4867d151", 478 | "metadata": { 479 | "slideshow": { 480 | "slide_type": "subslide" 481 | } 482 | }, 483 | "source": [ 484 | "##
C++ standard containers
\n", 485 | "Container classes support the following base functionality\n", 486 | " - `size()`: returns the size of the container\n", 487 | " - `empty()`: returns true of the container is empty\n", 488 | " - `swap(container& other)`: swaps contents of containers\n", 489 | "Many container classes provide so-called **iterators**\n", 490 | " - `begin()`, `end()`: editable iterator\n", 491 | " - `cbegin()`, `cend()`: constant, i.e., non-editable iterator\n" 492 | ] 493 | }, 494 | { 495 | "cell_type": "markdown", 496 | "id": "9836b2d8", 497 | "metadata": { 498 | "slideshow": { 499 | "slide_type": "subslide" 500 | } 501 | }, 502 | "source": [ 503 | "##
Simple array example
\n", 504 | "https://www.online-ide.com/VxJaDz7Avm\n", 505 | "```C++\n", 506 | "#include \n", 507 | "std::array a = {1, 2, 3, 4, 5};\n", 508 | "std::cout << \"empty: \" << a.empty() << ”\\n”; \n", 509 | "std::cout << \"size: \" << (int) a.size() << ”\\n”; \n", 510 | "std::cout << \"max_size:\" << (int) a.max_size() << “\\n”;\n", 511 | "for (auto i = 0; i < a.size(); i++)\n", 512 | " std::cout << a[i] << “\\n”;\n", 513 | "```" 514 | ] 515 | }, 516 | { 517 | "cell_type": "markdown", 518 | "id": "1aaf95eb", 519 | "metadata": { 520 | "slideshow": { 521 | "slide_type": "subslide" 522 | } 523 | }, 524 | "source": [ 525 | "##
Simple array example
" 526 | ] 527 | }, 528 | { 529 | "cell_type": "code", 530 | "execution_count": 7, 531 | "id": "86768d81-c79a-413a-921d-c25f710850d4", 532 | "metadata": { 533 | "tags": [] 534 | }, 535 | "outputs": [ 536 | { 537 | "name": "stdout", 538 | "output_type": "stream", 539 | "text": [ 540 | "size: 5\n", 541 | "size: 4\n" 542 | ] 543 | } 544 | ], 545 | "source": [ 546 | "#include \n", 547 | "#include \n", 548 | "\n", 549 | "\n", 550 | "std::array a = {1, 2, 3, 4, 5};\n", 551 | "std::array b = {6, 7, 8, 9};\n", 552 | "\n", 553 | "//a.swap(b); //Uncomment this line to see what will happen\n", 554 | "\n", 555 | "std::cout << \"size: \" << (int) a.size() << \"\\n\";\n", 556 | "std::cout << \"size: \" << (int) b.size() << \"\\n\";\n" 557 | ] 558 | }, 559 | { 560 | "cell_type": "markdown", 561 | "id": "c663b729", 562 | "metadata": { 563 | "slideshow": { 564 | "slide_type": "subslide" 565 | } 566 | }, 567 | "source": [ 568 | "##
Simple vector example
\n", 569 | "https://www.online-ide.com/OSemrgPAEK\n", 570 | "```C++\n", 571 | "#include \n", 572 | "#include \n", 573 | "\n", 574 | " std::vector v;\n", 575 | " v.reserve(20);\n", 576 | " v.push_back(42);\n", 577 | " v.push_back(11);\n", 578 | " v.push_back(1);\n", 579 | "// ... additional push_back operations if needed\n", 580 | " for (auto i = 0; i < v.size(); ++i)\n", 581 | " std::cout << v[i] << \"\\n\";\n", 582 | "```\n" 583 | ] 584 | }, 585 | { 586 | "cell_type": "markdown", 587 | "id": "b3535bda", 588 | "metadata": { 589 | "slideshow": { 590 | "slide_type": "slide" 591 | } 592 | }, 593 | "source": [ 594 | "##
Iterators
\n", 595 | "Fixed size arrays\n", 596 | "
" 597 | ] 598 | }, 599 | { 600 | "cell_type": "markdown", 601 | "id": "96a0dc21", 602 | "metadata": { 603 | "slideshow": { 604 | "slide_type": "subslide" 605 | } 606 | }, 607 | "source": [ 608 | "##
Iterators
\n", 609 | "Fixed size arrays\n", 610 | "
" 611 | ] 612 | }, 613 | { 614 | "cell_type": "markdown", 615 | "id": "ed7c98e7", 616 | "metadata": { 617 | "slideshow": { 618 | "slide_type": "subslide" 619 | } 620 | }, 621 | "source": [ 622 | "##
Iterators
\n", 623 | "Fixed size arrays\n", 624 | "
" 625 | ] 626 | }, 627 | { 628 | "cell_type": "markdown", 629 | "id": "365dafa8", 630 | "metadata": { 631 | "slideshow": { 632 | "slide_type": "subslide" 633 | } 634 | }, 635 | "source": [ 636 | "##
Iterators
\n", 637 | "Fixed size arrays\n", 638 | "
" 639 | ] 640 | }, 641 | { 642 | "cell_type": "markdown", 643 | "id": "39ca7f09", 644 | "metadata": { 645 | "slideshow": { 646 | "slide_type": "slide" 647 | } 648 | }, 649 | "source": [ 650 | "##
Simple vector example
\n", 651 | "**Constant iterator** over all entries\n", 652 | "```C++\n", 653 | "for (auto it = a.cbegin(); it != a.cend(); ++it)\n", 654 | " std::cout << *it << “\\n”;\n", 655 | "```\n", 656 | "**Non-constant iterator** over all entries\n", 657 | "```C++\n", 658 | "for (auto it = a.begin(); it != a.end(); ++it)\n", 659 | " *it++;\n", 660 | "```\n", 661 | "More elegant screen output using **ternary operator**\n", 662 | "```C++\n", 663 | "for (auto it = a.cbegin(); it != a.cend(); ++it)\n", 664 | " std::cout << *it\n", 665 | " << (std::next(it,1) != a.cend() ? \",\" : \"\\n\");\n", 666 | "```" 667 | ] 668 | }, 669 | { 670 | "cell_type": "markdown", 671 | "id": "34fc03d2", 672 | "metadata": { 673 | "slideshow": { 674 | "slide_type": "subslide" 675 | } 676 | }, 677 | "source": [ 678 | "##
Simple vector example
\n", 679 | "The **ternary operator** `?:` implements an **inline if**\n", 680 | "```C++\n", 681 | "(condition ? true case : false case)\n", 682 | "```\n", 683 | "Usage:\n", 684 | "```C++\n", 685 | "– std::cout << (x>y ? x : y) << “\\n”;\n", 686 | "– (x>y ? x : y) = 1;\n", 687 | "– auto myfunc(int x, double y) // in C++14 {\n", 688 | " return (x>y ? x : y);\n", 689 | " }\n", 690 | "```" 691 | ] 692 | }, 693 | { 694 | "cell_type": "markdown", 695 | "id": "4ca89248", 696 | "metadata": { 697 | "slideshow": { 698 | "slide_type": "slide" 699 | } 700 | }, 701 | "source": [ 702 | "##
Simple vector example
\n", 703 | "**Range-based for loop** (since C++11)\n", 704 | "```C++\n", 705 | "// access by constant reference (cannot modify i at all) for ( const auto& i : a )\n", 706 | " std::cout << i << “\\n”;\n", 707 | " // access by value (modify the local copy)\n", 708 | " for ( auto i : a )\n", 709 | " std::cout << i++ << “\\n”;\n", 710 | "// access by reference (modify the original data) for ( auto&& i : a )\n", 711 | " std::cout << i++ << “\\n”;\n", 712 | "```" 713 | ] 714 | }, 715 | { 716 | "cell_type": "markdown", 717 | "id": "1cec16e9", 718 | "metadata": { 719 | "slideshow": { 720 | "slide_type": "slide" 721 | } 722 | }, 723 | "source": [ 724 | "##
Range-based for loops
\n", 725 | "Range-based for loops can be used with nearly all types" 726 | ] 727 | }, 728 | { 729 | "cell_type": "code", 730 | "execution_count": 4, 731 | "id": "9a97991e-7dd2-4871-a471-4b36ce77d248", 732 | "metadata": { 733 | "tags": [] 734 | }, 735 | "outputs": [ 736 | { 737 | "name": "stdout", 738 | "output_type": "stream", 739 | "text": [ 740 | "0 1 2 3 4 " 741 | ] 742 | } 743 | ], 744 | "source": [ 745 | "#include \n", 746 | "#include \n", 747 | "for ( int n : {0, 1, 2, 3, 4} )\n", 748 | " std::cout << n << \" \";\n", 749 | "for ( double h : {0.1, 0.05, 0.025, 0.0125} )\n", 750 | " //auto sol = solve_poisson(h); //Here you can iteratively call the function" 751 | ] 752 | }, 753 | { 754 | "cell_type": "markdown", 755 | "id": "28390b1f-f1ba-4774-9234-fd82337b1d34", 756 | "metadata": {}, 757 | "source": [ 758 | "Why **nearly**?\n", 759 | "```C++\n", 760 | "for ( auto c : {std::array(); std::array()}) \n", 761 | " std::cout << c.size() << \"\\n\";\n", 762 | "```" 763 | ] 764 | }, 765 | { 766 | "cell_type": "code", 767 | "execution_count": 2, 768 | "id": "d64df973-d4ea-4364-8539-a00529187948", 769 | "metadata": { 770 | "tags": [] 771 | }, 772 | "outputs": [ 773 | { 774 | "name": "stdout", 775 | "output_type": "stream", 776 | "text": [ 777 | "St5arrayIiLm5EE\n", 778 | "St5arrayIiLm1EE\n" 779 | ] 780 | } 781 | ], 782 | "source": [ 783 | "auto array1 = std::array();\n", 784 | "std::cout << typeid(array1).name() << \"\\n\";\n", 785 | "auto array2 = std::array();\n", 786 | "std::cout << typeid(array2).name() << \"\\n\";" 787 | ] 788 | }, 789 | { 790 | "cell_type": "markdown", 791 | "id": "076730b3", 792 | "metadata": { 793 | "slideshow": { 794 | "slide_type": "slide" 795 | } 796 | }, 797 | "source": [ 798 | "##
C++ standard algorithms
\n", 799 | "Header file `algorithm` provides many standard algorithms\n", 800 | "\n", 801 | "– `for_each(begin, end, function)`\n", 802 | "\n", 803 | "– `position = find(begin, end, x)`\n", 804 | "\n", 805 | "– `position = find_if(begin, end, function)` \n", 806 | "\n", 807 | "– `number = count(begin, end, x)`\n", 808 | "\n", 809 | "– `number = count_if(begin, end, function)`\n", 810 | "\n", 811 | "– `sort(begin, end)`\n", 812 | "\n", 813 | "– `sort(begin, end, function)`\n", 814 | "\n", 815 | "– `position = merge(begin1, end1, begin2, end2, out)` \n" 816 | ] 817 | }, 818 | { 819 | "cell_type": "markdown", 820 | "id": "2af69daa", 821 | "metadata": { 822 | "slideshow": { 823 | "slide_type": "slide" 824 | } 825 | }, 826 | "source": [ 827 | "##
For-each loops
\n", 828 | "For-each loop iterates over all items and applies a user- defined unary function realized as lambda expression\n", 829 | "\n", 830 | "https://www.online-ide.com/VrE05oFfZe\n", 831 | "```C++\n", 832 | "std::vector v = {1, 2, 3, 4, 5};\n", 833 | "std::for_each(v.begin(), v.end(),\n", 834 | " [](const int& n) { std::cout << \" \" << n; }); \n", 835 | "std::for_each(v.begin(), v.end(), [](int &n){ n++; });\n", 836 | "```" 837 | ] 838 | }, 839 | { 840 | "cell_type": "markdown", 841 | "id": "fc3ce7e7", 842 | "metadata": { 843 | "slideshow": { 844 | "slide_type": "subslide" 845 | } 846 | }, 847 | "source": [ 848 | "##
For-each loops
\n", 849 | "For-each loop iterates over all items and applies a user- defined unary function realized as function object\n", 850 | "\n", 851 | "https://www.online-ide.com/PNHB7kuGvX\n", 852 | "```C++\n", 853 | "struct Sum {\n", 854 | " Sum() : sum(0) {}\n", 855 | " void operator()(int n) { sum += n; }\n", 856 | " int sum;\n", 857 | "};\n", 858 | "\n", 859 | "Sum s = std::for_each(v.begin(), v.end(), Sum()); \n", 860 | "std::cout << “sum: “ << s.sum << “\\n”;\n", 861 | "```" 862 | ] 863 | }, 864 | { 865 | "cell_type": "markdown", 866 | "id": "8169f944", 867 | "metadata": { 868 | "slideshow": { 869 | "slide_type": "slide" 870 | } 871 | }, 872 | "source": [ 873 | "##
Simple vector example
\n", 874 | "https://www.online-ide.com/fgqks71DQc\n", 875 | "```C++\n", 876 | "#include \n", 877 | "#include \n", 878 | " std::vector v;\n", 879 | " v.reserve(20);\n", 880 | " v.push_back(42);\n", 881 | " v.push_back(11);\n", 882 | " v.push_back(1);\n", 883 | " std::sort(v.begin(), v.end());\n", 884 | " for (const auto& i : v)\n", 885 | " std::cout << i << std::endl;\n", 886 | "```" 887 | ] 888 | }, 889 | { 890 | "cell_type": "markdown", 891 | "id": "81a72296", 892 | "metadata": { 893 | "slideshow": { 894 | "slide_type": "subslide" 895 | } 896 | }, 897 | "source": [ 898 | "##
Simple vector example
\n", 899 | "Provide standard library **compare function object**\n", 900 | "```C++\n", 901 | "#include \n", 902 | "std::sort(v.begin(), v.end(), std::greater() );\n", 903 | "```\n", 904 | "Provide user-defined **comparison as lambda expression**\n", 905 | "```C++\n", 906 | "std::sort(v.begin(), v.end(),\n", 907 | " [](int x, int y) { return ySimple vector example\n", 921 | "Provide user-defined **comparison as function object**\n", 922 | "```C++\n", 923 | "struct {\n", 924 | " bool operator()(int x, int y) { return y>x; }\n", 925 | " } customGreater;\n", 926 | "std::sort(v.begin(), v.end(), customGreater );\n", 927 | "```" 928 | ] 929 | }, 930 | { 931 | "cell_type": "markdown", 932 | "id": "3e76d4e4", 933 | "metadata": { 934 | "slideshow": { 935 | "slide_type": "slide" 936 | } 937 | }, 938 | "source": [ 939 | "##
The power of iterators
\n", 940 | "C++ standard library functionality is largely based on iterators rather than absolute access via `operator[]`\n", 941 | "\n", 942 | "For data structures like `std::list` the `operator[]` is not even defined since items can be inserted arbitrarily" 943 | ] 944 | }, 945 | { 946 | "cell_type": "code", 947 | "execution_count": 2, 948 | "id": "e9bfa0dd-db82-43f6-91dd-83d2c8cd404a", 949 | "metadata": { 950 | "tags": [] 951 | }, 952 | "outputs": [ 953 | { 954 | "name": "stdout", 955 | "output_type": "stream", 956 | "text": [ 957 | "3\n", 958 | "4\n", 959 | "13\n" 960 | ] 961 | } 962 | ], 963 | "source": [ 964 | "#include \n", 965 | "#include \n", 966 | "\n", 967 | "std::list L;\n", 968 | "L.push_back(13);\n", 969 | "L.push_front(3);\n", 970 | "L.insert(++L.begin(), 4);\n", 971 | "\n", 972 | "for (const auto& i : L) {\n", 973 | " std::cout << i << \"\\n\";\n", 974 | "}" 975 | ] 976 | }, 977 | { 978 | "cell_type": "markdown", 979 | "id": "2ccc8846", 980 | "metadata": { 981 | "slideshow": { 982 | "slide_type": "slide" 983 | } 984 | }, 985 | "source": [ 986 | "##
Iterators
\n", 987 | "
" 988 | ] 989 | }, 990 | { 991 | "cell_type": "markdown", 992 | "id": "b0119d9d", 993 | "metadata": { 994 | "slideshow": { 995 | "slide_type": "slide" 996 | } 997 | }, 998 | "source": [ 999 | "##
Maps
\n", 1000 | "`std::map` handles key-value pairs efficiently\n", 1001 | "\n", 1002 | "https://www.online-ide.com/jbpHoZer2X\n", 1003 | "```C++\n", 1004 | "enum class Color { red, green, blue };\n", 1005 | "\n", 1006 | "std::map ColorMap = {\n", 1007 | " {Color::red, “red”},\n", 1008 | " {Color::green, “green”},\n", 1009 | " {Color::blue, ”blue”}\n", 1010 | " };\n", 1011 | "std::cout << ColorMap[Color::green] << \"\\n\";\n", 1012 | "```" 1013 | ] 1014 | }, 1015 | { 1016 | "cell_type": "markdown", 1017 | "id": "f28da6d0", 1018 | "metadata": { 1019 | "slideshow": { 1020 | "slide_type": "subslide" 1021 | } 1022 | }, 1023 | "source": [ 1024 | "##
Maps
\n", 1025 | "`std::map` handles key-value pairs efficiently\n", 1026 | "\n", 1027 | "https://www.online-ide.com/Qekz72cqHF\n", 1028 | "```C++\n", 1029 | "enum class Color { red, green, blue };\n", 1030 | "\n", 1031 | "std::map ColorMapReverse = { \n", 1032 | " {\"red\", Color::red},\n", 1033 | " {\"green\", Color::green},\n", 1034 | " {\"blue\", Color::blue}\n", 1035 | " };\n", 1036 | " \n", 1037 | "auto it = ColorMapReverse.find(\"green\");\n", 1038 | " \n", 1039 | "std::cout << it->first // key\n", 1040 | " << (int)it->second // value\n", 1041 | " << \"\\n\";\n", 1042 | "```" 1043 | ] 1044 | }, 1045 | { 1046 | "cell_type": "markdown", 1047 | "id": "ea3d25e1", 1048 | "metadata": { 1049 | "slideshow": { 1050 | "slide_type": "slide" 1051 | } 1052 | }, 1053 | "source": [ 1054 | "##
Tuples
\n", 1055 | "Container `std::tuples` stores **heterogeneous types**\n", 1056 | "```C++\n", 1057 | "#include \n", 1058 | "auto t = std::make_tuple(3.8, ‘A’, “String”);\n", 1059 | "```\n", 1060 | "Access to individual elements\n", 1061 | "```C++\n", 1062 | "std::cout << std::get<0>(t) << std::endl; //Output: 3.8\n", 1063 | "std::cout << std::get<1>(t) << std::endl; //Output: A\n", 1064 | "std::cout << std::get<2>(t) << std::endl; //Output: String\n", 1065 | "```\n", 1066 | "Create tuple from parameter pack\n", 1067 | "```C++\n", 1068 | "auto t = std::tuple(args...);\n", 1069 | "```" 1070 | ] 1071 | }, 1072 | { 1073 | "cell_type": "markdown", 1074 | "id": "b16014a9", 1075 | "metadata": { 1076 | "slideshow": { 1077 | "slide_type": "subslide" 1078 | } 1079 | }, 1080 | "source": [ 1081 | "##
Tuples
\n", 1082 | "Get the size of the tuple\n", 1083 | "```C++\n", 1084 | "std::cout << std::tuple_size::value;\n", 1085 | "```\n", 1086 | "However, it is impossible to iterate over the elements of a tuple using any of the run-time techniques seen before\n", 1087 | "- No operator[]\n", 1088 | "- No iterators\n", 1089 | "- No range-based or for-each loops\n", 1090 | "\n", 1091 | "**Task:** Find a way to iterate over the elements of a tuple using compile-time techniques" 1092 | ] 1093 | }, 1094 | { 1095 | "cell_type": "markdown", 1096 | "id": "30981057", 1097 | "metadata": { 1098 | "slideshow": { 1099 | "slide_type": "subslide" 1100 | } 1101 | }, 1102 | "source": [ 1103 | "##
Tuples
\n", 1104 | "https://www.online-ide.com/cygjF7U2vI\n", 1105 | "```C++\n", 1106 | "template struct printer {\n", 1107 | " static void print(Tuple t) {\n", 1108 | " printer::print(t);\n", 1109 | " std::cout << std::get(t) << \"\\n\";\n", 1110 | "}};\n", 1111 | " // Specialization for first entry\n", 1112 | " template\n", 1113 | " struct printer<0,Tuple> {\n", 1114 | " static void print(Tuple t) {\n", 1115 | " std::cout << std::get<0>(t) << \"\\n\";\n", 1116 | "}};\n", 1117 | "```" 1118 | ] 1119 | }, 1120 | { 1121 | "cell_type": "markdown", 1122 | "id": "424ee4a4", 1123 | "metadata": { 1124 | "slideshow": { 1125 | "slide_type": "subslide" 1126 | } 1127 | }, 1128 | "source": [ 1129 | "##
Tuples
\n", 1130 | "Usage\n", 1131 | "```C++\n", 1132 | "int main() {\n", 1133 | " auto t = std::make_tuple(3.8, ‘A’, “String”);\n", 1134 | " printer::value-1, \n", 1135 | " decltype(t)>::print(t);\n", 1136 | "}\n", 1137 | "```" 1138 | ] 1139 | }, 1140 | { 1141 | "cell_type": "code", 1142 | "execution_count": null, 1143 | "id": "81d3d273", 1144 | "metadata": {}, 1145 | "outputs": [], 1146 | "source": [] 1147 | } 1148 | ], 1149 | "metadata": { 1150 | "celltoolbar": "Slideshow", 1151 | "kernelspec": { 1152 | "display_name": "C++17", 1153 | "language": "C++17", 1154 | "name": "xcpp17" 1155 | }, 1156 | "language_info": { 1157 | "codemirror_mode": "text/x-c++src", 1158 | "file_extension": ".cpp", 1159 | "mimetype": "text/x-c++src", 1160 | "name": "c++", 1161 | "version": "17" 1162 | }, 1163 | "rise": { 1164 | "autolaunch": true, 1165 | "enable_chalkboard": true 1166 | } 1167 | }, 1168 | "nbformat": 4, 1169 | "nbformat_minor": 5 1170 | } 1171 | -------------------------------------------------------------------------------- /notebooks/lecture6.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "f02b0e2e", 6 | "metadata": { 7 | "slideshow": { 8 | "slide_type": "slide" 9 | } 10 | }, 11 | "source": [ 12 | "# Object-oriented scientific programming with C++\n", 13 | "\n", 14 | "Matthias Möller, Jonas Thies, Cálin Georgescu, Jingya Li (Numerical Analysis, DIAM)\n", 15 | "\n", 16 | "Lecture 6" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "id": "d2392445", 22 | "metadata": { 23 | "cell_style": "center", 24 | "slideshow": { 25 | "slide_type": "slide" 26 | } 27 | }, 28 | "source": [ 29 | "# Goal of this lecture\n", 30 | "\n", 31 | "- Self-written iterators for user-defined containers\n", 32 | "\n", 33 | "- Introduction to the concept of expression templates\n", 34 | "\n", 35 | "- Memory management with smart pointers\n", 36 | "\n", 37 | "- Latest and greatest features of C++17 and 20\n", 38 | "\n", 39 | "- ..." 40 | ] 41 | }, 42 | { 43 | "cell_type": "markdown", 44 | "id": "4500c017", 45 | "metadata": { 46 | "cell_style": "center", 47 | "slideshow": { 48 | "slide_type": "slide" 49 | } 50 | }, 51 | "source": [ 52 | "# Iterators\n", 53 | "
" 54 | ] 55 | }, 56 | { 57 | "cell_type": "markdown", 58 | "id": "04f3e137", 59 | "metadata": { 60 | "slideshow": { 61 | "slide_type": "subslide" 62 | } 63 | }, 64 | "source": [ 65 | "
" 66 | ] 67 | }, 68 | { 69 | "cell_type": "markdown", 70 | "id": "9513957c", 71 | "metadata": { 72 | "slideshow": { 73 | "slide_type": "subslide" 74 | } 75 | }, 76 | "source": [ 77 | "
" 78 | ] 79 | }, 80 | { 81 | "cell_type": "markdown", 82 | "id": "39b90744", 83 | "metadata": { 84 | "slideshow": { 85 | "slide_type": "subslide" 86 | } 87 | }, 88 | "source": [ 89 | "**Constant iterator** over all entries\n", 90 | "```C++\n", 91 | "for (auto it = a.cbegin(); it != a.cend(); ++it)\n", 92 | " std::cout << *it << \"\\n\";\n", 93 | "```\n", 94 | "\n", 95 | "**Non-constant iterator** over all entries\n", 96 | "```C++\n", 97 | "for (auto it = a.begin(); it != a.end(); ++it)\n", 98 | " *it++;\n", 99 | "```" 100 | ] 101 | }, 102 | { 103 | "cell_type": "markdown", 104 | "id": "86db7f06", 105 | "metadata": { 106 | "slideshow": { 107 | "slide_type": "slide" 108 | } 109 | }, 110 | "source": [ 111 | "# Iterators for user-defined containers\n", 112 | "
" 113 | ] 114 | }, 115 | { 116 | "cell_type": "markdown", 117 | "id": "39d4474b", 118 | "metadata": { 119 | "slideshow": { 120 | "slide_type": "subslide" 121 | } 122 | }, 123 | "source": [ 124 | "
" 125 | ] 126 | }, 127 | { 128 | "cell_type": "markdown", 129 | "id": "b311c25a", 130 | "metadata": { 131 | "slideshow": { 132 | "slide_type": "subslide" 133 | } 134 | }, 135 | "source": [ 136 | "
" 137 | ] 138 | }, 139 | { 140 | "cell_type": "markdown", 141 | "id": "38c5de33", 142 | "metadata": { 143 | "slideshow": { 144 | "slide_type": "subslide" 145 | } 146 | }, 147 | "source": [ 148 | "
" 149 | ] 150 | }, 151 | { 152 | "cell_type": "markdown", 153 | "id": "5b415d3b", 154 | "metadata": { 155 | "slideshow": { 156 | "slide_type": "subslide" 157 | } 158 | }, 159 | "source": [ 160 | "
" 161 | ] 162 | }, 163 | { 164 | "cell_type": "markdown", 165 | "id": "d52a8b5d", 166 | "metadata": { 167 | "slideshow": { 168 | "slide_type": "subslide" 169 | } 170 | }, 171 | "source": [ 172 | "
" 173 | ] 174 | }, 175 | { 176 | "cell_type": "markdown", 177 | "id": "5741620c", 178 | "metadata": { 179 | "slideshow": { 180 | "slide_type": "subslide" 181 | } 182 | }, 183 | "source": [ 184 | "
" 185 | ] 186 | }, 187 | { 188 | "cell_type": "markdown", 189 | "id": "aabe5a06", 190 | "metadata": { 191 | "slideshow": { 192 | "slide_type": "subslide" 193 | } 194 | }, 195 | "source": [ 196 | "
" 197 | ] 198 | }, 199 | { 200 | "cell_type": "markdown", 201 | "id": "e98140a2", 202 | "metadata": { 203 | "slideshow": { 204 | "slide_type": "subslide" 205 | } 206 | }, 207 | "source": [ 208 | "
" 209 | ] 210 | }, 211 | { 212 | "cell_type": "markdown", 213 | "id": "f2ca538e", 214 | "metadata": { 215 | "slideshow": { 216 | "slide_type": "subslide" 217 | } 218 | }, 219 | "source": [ 220 | "
" 221 | ] 222 | }, 223 | { 224 | "cell_type": "markdown", 225 | "id": "13a4f0ef", 226 | "metadata": { 227 | "slideshow": { 228 | "slide_type": "subslide" 229 | } 230 | }, 231 | "source": [ 232 | "
" 233 | ] 234 | }, 235 | { 236 | "cell_type": "markdown", 237 | "id": "58ee7615", 238 | "metadata": { 239 | "slideshow": { 240 | "slide_type": "subslide" 241 | } 242 | }, 243 | "source": [ 244 | "# Example: Sorting of Vectors\n", 245 | "Create unsorted Vector object and sort it" 246 | ] 247 | }, 248 | { 249 | "cell_type": "code", 250 | "execution_count": null, 251 | "id": "674a49a7", 252 | "metadata": {}, 253 | "outputs": [], 254 | "source": [ 255 | "#include \n", 256 | "#include \n", 257 | "#include \n", 258 | "\n", 259 | "std::vector v = { 4, 2, 3, 7, 5, 8, 9, 1, 10, 6 };\n", 260 | "std::sort(v.begin(), v.end());\n", 261 | "\n", 262 | "std::cout << \"v = [\";\n", 263 | "for (auto it = v.begin(); it != v.end(); it++) {\n", 264 | " std::cout << *it << (std::next(it, 1) != v.end() ? \", \" : \"]\\n\");\n", 265 | " }" 266 | ] 267 | }, 268 | { 269 | "cell_type": "markdown", 270 | "id": "622100ed", 271 | "metadata": { 272 | "slideshow": { 273 | "slide_type": "slide" 274 | } 275 | }, 276 | "source": [ 277 | "# Linear algebra library\n", 278 | "**Task:** Let us design our own linear algebra library that supports the following operations:\n", 279 | " - Element-wise Add, Sub, Div, Mul of vectors \n", 280 | " - Add, Sub, Div, Mul of a vector with a scalar\n", 281 | " - Copy assignment (other functionality can be added later)\n", 282 | " \n", 283 | "Additional requirements:\n", 284 | " - Support for arbitrary types: template metaprogramming\n", 285 | " - Mathematical notation: operator overloading" 286 | ] 287 | }, 288 | { 289 | "cell_type": "markdown", 290 | "id": "b32c0b31", 291 | "metadata": { 292 | "slideshow": { 293 | "slide_type": "subslide" 294 | } 295 | }, 296 | "source": [ 297 | "**Vector class:** Attributes\n", 298 | "\n", 299 | "For the whole program: https://www.online-cpp.com/3DwpTrm4qB\n", 300 | "\n", 301 | "```C++\n", 302 | "template class vector {\n", 303 | "private:\n", 304 | " // Attributes\n", 305 | " T* data;\n", 306 | " std::size_t n;\n", 307 | "```" 308 | ] 309 | }, 310 | { 311 | "cell_type": "markdown", 312 | "id": "9ee9f501", 313 | "metadata": { 314 | "slideshow": { 315 | "slide_type": "subslide" 316 | } 317 | }, 318 | "source": [ 319 | "**Vector class:** Constructors\n", 320 | "```C++\n", 321 | "template class vector {\n", 322 | "public:\n", 323 | " // Default constructor\n", 324 | " vector()\n", 325 | " : n(0), data(nullptr) {}\n", 326 | " // Size constructor\n", 327 | " vector(std::size_t n)\n", 328 | " : n(n), data(new T[n]) {}\n", 329 | "... \n", 330 | "```" 331 | ] 332 | }, 333 | { 334 | "cell_type": "markdown", 335 | "id": "abcd2c1a", 336 | "metadata": { 337 | "slideshow": { 338 | "slide_type": "subslide" 339 | } 340 | }, 341 | "source": [ 342 | "**Vector class:** Constructors\n", 343 | "```C++\n", 344 | "template\n", 345 | "class vector {\n", 346 | " // Copy constructor\n", 347 | " vector(const vector& other)\n", 348 | " : vector(other.size())\n", 349 | " {\n", 350 | " for (std::size_t i=0; i\n", 369 | "class vector {\n", 370 | " // Move constructor\n", 371 | " vector(vector&& other)\n", 372 | " {\n", 373 | " data = other.data; \n", 374 | " other.data = nullptr;\n", 375 | " n = other.n; \n", 376 | " other.n = 0;\n", 377 | " }\n", 378 | " ...\n", 379 | "```" 380 | ] 381 | }, 382 | { 383 | "cell_type": "markdown", 384 | "id": "dada4fd9", 385 | "metadata": { 386 | "slideshow": { 387 | "slide_type": "subslide" 388 | } 389 | }, 390 | "source": [ 391 | "**Vector class:** Destructor and helper functions\n", 392 | "```C++\n", 393 | "template\n", 394 | "class vector {\n", 395 | " // Destructor\n", 396 | " ~vector() { delete[] data; data=nullptr; n=0; }\n", 397 | " // Return size\n", 398 | " inline const std::size_t size() const { return n; }\n", 399 | "```" 400 | ] 401 | }, 402 | { 403 | "cell_type": "markdown", 404 | "id": "f8b683c8", 405 | "metadata": { 406 | "slideshow": { 407 | "slide_type": "subslide" 408 | } 409 | }, 410 | "source": [ 411 | "**Vector class:** Helper functions\n", 412 | "```C++\n", 413 | "template\n", 414 | "class vector {\n", 415 | " // Get data pointer (by constant reference)\n", 416 | " inline const T& get(const std::size_t& i) const { \n", 417 | " return data[i];\n", 418 | " }\n", 419 | " // Get data pointer (by reference)\n", 420 | " inline T& get(const std::size_t& i) {\n", 421 | " return data[i];\n", 422 | " }\n", 423 | "```" 424 | ] 425 | }, 426 | { 427 | "cell_type": "markdown", 428 | "id": "b8f8c6f2", 429 | "metadata": { 430 | "slideshow": { 431 | "slide_type": "subslide" 432 | } 433 | }, 434 | "source": [ 435 | "**Vector class:** Assignment operator\n", 436 | "```C++\n", 437 | "template\n", 438 | "class vector {\n", 439 | " // Scalar assignment operator\n", 440 | " vector& operator=(const T& value) {\n", 441 | " for (std::size_t i = 0; i < size(); i++)\n", 442 | " data[i] = value;\n", 443 | " return *this;\n", 444 | "}\n", 445 | "```" 446 | ] 447 | }, 448 | { 449 | "cell_type": "markdown", 450 | "id": "c2196aff", 451 | "metadata": { 452 | "slideshow": { 453 | "slide_type": "subslide" 454 | } 455 | }, 456 | "source": [ 457 | "**Vector class:** Assignment operator\n", 458 | "```C++\n", 459 | "template\n", 460 | "class vector {\n", 461 | " // Copy assignment operator\n", 462 | " const vector& operator=(const vector& other) const { \n", 463 | " if (this != &other) {\n", 464 | " delete[] data; n = other.size(); data = new T[n];\n", 465 | " for (std::size_t i = 0; i < other.size(); i++)\n", 466 | " data[i] = other.data[i];\n", 467 | " }\n", 468 | " return *this;\n", 469 | "}\n", 470 | "```" 471 | ] 472 | }, 473 | { 474 | "cell_type": "markdown", 475 | "id": "f767f6e3", 476 | "metadata": { 477 | "slideshow": { 478 | "slide_type": "subslide" 479 | } 480 | }, 481 | "source": [ 482 | "**Vector class:** Assignment operator\n", 483 | "```C++\n", 484 | "template\n", 485 | "class vector {\n", 486 | " // Move assignment operator\n", 487 | " vector& operator=(vector&& other) { \n", 488 | " if (this != &other) {\n", 489 | " std::swap(this->data, other.data);\n", 490 | " std::swap(this->n, other.n);\n", 491 | " other.n = 0; delete[] other.data; other.data = nullptr;\n", 492 | " }\n", 493 | " return *this;\n", 494 | "}\n", 495 | "```" 496 | ] 497 | }, 498 | { 499 | "cell_type": "markdown", 500 | "id": "0cc238b1", 501 | "metadata": { 502 | "slideshow": { 503 | "slide_type": "subslide" 504 | } 505 | }, 506 | "source": [ 507 | "**Vector class:** Binary vector-vector operators **(outside class!)**\n", 508 | "```C++\n", 509 | "template\n", 510 | "auto operator+(const vector& v1,\n", 511 | " const vector& v2) { \n", 512 | " vector::type>\n", 513 | " v(v1.size());\n", 514 | " for (std::size_t i=0; i\n", 534 | "auto operator+(const vector& v1,\n", 535 | " const T2& s2) { \n", 536 | " vector::type>\n", 537 | " v(v1.size());\n", 538 | " for (std::size_t i=0; i x(10), y(10), z(10); x=1.0; y=2.0; \n", 585 | " z=2*x+y/(x-3);\n", 586 | "}\n", 587 | "```" 588 | ] 589 | }, 590 | { 591 | "cell_type": "markdown", 592 | "id": "c177045a", 593 | "metadata": { 594 | "slideshow": { 595 | "slide_type": "fragment" 596 | } 597 | }, 598 | "source": [ 599 | "- Five loads and three stores each of length `n`" 600 | ] 601 | }, 602 | { 603 | "cell_type": "markdown", 604 | "id": "05d2b29c", 605 | "metadata": { 606 | "slideshow": { 607 | "slide_type": "slide" 608 | } 609 | }, 610 | "source": [ 611 | "# Expression template library for linear algebra\n", 612 | "\n", 613 | "
" 614 | ] 615 | }, 616 | { 617 | "cell_type": "markdown", 618 | "id": "97c4a541", 619 | "metadata": { 620 | "slideshow": { 621 | "slide_type": "subslide" 622 | } 623 | }, 624 | "source": [ 625 | "Implement templated vector class (derived from base class `vectorBase`) as before but remove all operators (`+`,`-`,`*`,`/`)\n", 626 | "\n", 627 | "Implement an additional **assignment operator**, which loops through the expression e and assigns the value to `data[i]`\n", 628 | "```C++\n", 629 | "template \n", 630 | "vector& operator=(const E& e) {\n", 631 | " for (std::size_t i = 0; i < size(); i++)\n", 632 | " data[i] = e.get(i);\n", 633 | " return *this;\n", 634 | "}\n", 635 | "```" 636 | ] 637 | }, 638 | { 639 | "cell_type": "markdown", 640 | "id": "1642ba6e", 641 | "metadata": { 642 | "slideshow": { 643 | "slide_type": "subslide" 644 | } 645 | }, 646 | "source": [ 647 | "For each **binary operator** we need to implement a helper class that represents the operation in the expression tree\n", 648 | "```C++\n", 649 | "template\n", 650 | "class VectorAdd : vectorBase {\n", 651 | "private:\n", 652 | " const E1& e1;\n", 653 | " const E2& e2;\n", 654 | " \n", 655 | "public:\n", 656 | " VectorAdd(const E1& e1, const E2& e2)\n", 657 | " : e1(e1), e2(e2)\n", 658 | "{}\n", 659 | "...\n", 660 | "```" 661 | ] 662 | }, 663 | { 664 | "cell_type": "markdown", 665 | "id": "1c1ff576", 666 | "metadata": { 667 | "slideshow": { 668 | "slide_type": "subslide" 669 | } 670 | }, 671 | "source": [ 672 | "For each **binary operator** we need to implement a helper class that represents the operation in the expression tree\n", 673 | "```C++\n", 674 | "template\n", 675 | "class VectorAdd : vectorBase {\n", 676 | "...\n", 677 | " inline const\n", 678 | " typename std::common_type::type\n", 680 | " get(std::size_t index) const {\n", 681 | " return e1.get(index) + e2.get(index);\n", 682 | " }\n", 683 | "};\n", 684 | "```" 685 | ] 686 | }, 687 | { 688 | "cell_type": "markdown", 689 | "id": "3069b373", 690 | "metadata": { 691 | "slideshow": { 692 | "slide_type": "subslide" 693 | } 694 | }, 695 | "source": [ 696 | "For each **binary operator** we need to implement a helper class that represents the operation in the expression tree\n", 697 | "```C++\n", 698 | "template\n", 699 | "class VectorAdd : vectorBase { ... };\n", 700 | "```\n", 701 | "Base class `vectorBase` has no functionality and is used to check if a template argument belongs to the expression tree\n", 702 | "```C++\n", 703 | "typename std::enable_if< \n", 704 | " std::is_base_of::value\n", 705 | " >::type\n", 706 | "```" 707 | ] 708 | }, 709 | { 710 | "cell_type": "markdown", 711 | "id": "3c9345a5", 712 | "metadata": { 713 | "slideshow": { 714 | "slide_type": "subslide" 715 | } 716 | }, 717 | "source": [ 718 | "Implement the corresponding binary operator overload\n", 719 | "```C++\n", 720 | "template\n", 721 | "auto operator+(const E1& e1, const E2& e2) {\n", 722 | " return VectorAdd(e1,e2);\n", 723 | " };\n", 724 | "```\n", 725 | "
\n", 726 | " Now, expression auto e=x+y creates a new item in the expression tree and keeps constant references to x and y\n", 727 | " \n", 728 | "Expression evaluation for a single index is triggered by e.get(index)\n", 729 | "
\n", 730 | "\n", 731 | "
\n", 732 | "
\n", 733 | "
" 734 | ] 735 | }, 736 | { 737 | "cell_type": "markdown", 738 | "id": "850dd770", 739 | "metadata": { 740 | "slideshow": { 741 | "slide_type": "subslide" 742 | } 743 | }, 744 | "source": [ 745 | "The expression auto e=x+y+z has the type\n", 746 | "\n", 747 | "VectorAdd< VectorAdd< Vector<X>, Vector<Y> >, Vector<Z> >\n", 748 | "\n", 749 | "During the assignment of this expression to a vector object `vector v=e` the `get(index)` function is called for each single index. The overall computation takes place in a\n", 750 | "**single for loop** as if we had written the following code\n", 751 | "\n", 752 | "

for (std::size_t i=0; i<x.size(); i++)\n", 753 | " v.get(i) = x.get(i) + y.get(i) + z.get(i);\n", 754 | "

" 755 | ] 756 | }, 757 | { 758 | "cell_type": "markdown", 759 | "id": "633ffa17", 760 | "metadata": { 761 | "slideshow": { 762 | "slide_type": "subslide" 763 | } 764 | }, 765 | "source": [ 766 | "**A word of caution:** Expression templates (ET) are very powerful (for you as a user) but writing an **efficient** ET linear algebra library takes much time and is not trivial\n", 767 | "\n", 768 | "ET eliminate multiple for-loops but they do by no means imply parallelism, use of SIMD intrinsics, etcetera\n", 769 | "\n", 770 | "A recent trend is to use the ET concept as high-level user- interface and implement all the dirty tricks (inlined assembler code, vector intrinsics, ...) in helper classes" 771 | ] 772 | }, 773 | { 774 | "cell_type": "markdown", 775 | "id": "02b5f082", 776 | "metadata": { 777 | "slideshow": { 778 | "slide_type": "slide" 779 | } 780 | }, 781 | "source": [ 782 | "# Overview of linear algebra expression template libraries\n", 783 | "[**Armadillo**:](https://arma.sourceforge.net/docs.html) MATLAB-like notation\n", 784 | "\n", 785 | "[**ArrayFire:**](https://github.com/arrayfire/arrayfire) broad support on ARM/x86 CPUs and GPUs\n", 786 | "\n", 787 | "[**Blaze:**](https://bitbucket.org/blaze-lib/blaze/src/master/) aims for ultimate performance\n", 788 | "\n", 789 | "[**Eigen:**](https://eigen.tuxfamily.org/dox/GettingStarted.html) easy usage and broad user community\n", 790 | "\n", 791 | "[**IT++:**](https://itpp.sourceforge.net/4.3.1/) grandfather of all ET LA libraries\n", 792 | "\n", 793 | "[**MTL4:**](https://cs.brown.edu/people/jwicks/mtl_reference/) distributed HPC + fast linear solvers\n", 794 | "\n", 795 | "[**VexCL:**](https://vexcl.readthedocs.io/en/latest/) broad support on CPUs and GPUs\n", 796 | "\n", 797 | "[**ViennaCL:**](https://viennacl.sourceforge.net/#:~:text=ViennaCL%20is%20a%20free%20open,(including%20switches%20at%20runtime).) fast linear solvers" 798 | ] 799 | }, 800 | { 801 | "cell_type": "markdown", 802 | "id": "527006e6", 803 | "metadata": { 804 | "slideshow": { 805 | "slide_type": "slide" 806 | } 807 | }, 808 | "source": [ 809 | "# Example: Eigen library\n", 810 | "```C++\n", 811 | "#include \n", 812 | "using namespace Eigen; \n", 813 | "int main() {\n", 814 | " MatrixXd A(3,3), B(3,3);\n", 815 | " VectorXd x(3), y(3), z(3);\n", 816 | " A << 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0;\n", 817 | " B << 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0;\n", 818 | " x <<-1.0,-2.0,-3.0;\n", 819 | " y << 4.0, 5.0, 6.0;\n", 820 | " z = A.transpose() * x.array().abs().sqrt().matrix();\n", 821 | " std::cout \"z = A^T * sqrt(|x|)\\n\" << z << \"\\n\\n\";\n", 822 | " }\n", 823 | "```" 824 | ] 825 | }, 826 | { 827 | "cell_type": "markdown", 828 | "id": "88978d14", 829 | "metadata": { 830 | "slideshow": { 831 | "slide_type": "slide" 832 | } 833 | }, 834 | "source": [ 835 | "# Smart Pointers\n", 836 | "Dynamically allocated memory must be deallocated explicitly by the user to prevent memory leaks\n", 837 | "\n", 838 | "https://www.online-cpp.com/ueBnpEWSU9\n", 839 | "```C++\n", 840 | "{\n", 841 | "\n", 842 | " // Traditional dynamic memory allocation with raw pointer\n", 843 | " double* raw_ptr = new double[42];\n", 844 | " \n", 845 | " // Perform operations on raw_ptr\n", 846 | " for (int i = 0; i < 42; ++i)\n", 847 | " raw_ptr[i] = i;\n", 848 | " \n", 849 | " // Explicitly deallocating memory\n", 850 | " delete[] raw_ptr;\n", 851 | "\n", 852 | "} // raw_ptr goes out of scope but is not destroyed automatically\n", 853 | "```" 854 | ] 855 | }, 856 | { 857 | "cell_type": "markdown", 858 | "id": "f368f1a6", 859 | "metadata": { 860 | "slideshow": { 861 | "slide_type": "subslide" 862 | } 863 | }, 864 | "source": [ 865 | "```C++\n", 866 | "#include \n", 867 | "\n", 868 | "{\n", 869 | " std::unique_ptr scoped_ptr(new double[42]);\n", 870 | " \n", 871 | " // Perform operations on the scoped_ptr\n", 872 | " for (int i = 0; i < 42; ++i)\n", 873 | " scoped_ptr[i] = i;\n", 874 | "\n", 875 | "} // scoped_ptr goes out of scope and is destroyed automatically\n", 876 | "```" 877 | ] 878 | }, 879 | { 880 | "cell_type": "markdown", 881 | "id": "8f86120d", 882 | "metadata": { 883 | "slideshow": { 884 | "slide_type": "slide" 885 | } 886 | }, 887 | "source": [ 888 | "# Smart Pointers – use-case\n", 889 | "\n", 890 | "
" 891 | ] 892 | }, 893 | { 894 | "cell_type": "markdown", 895 | "id": "45926fbf", 896 | "metadata": { 897 | "slideshow": { 898 | "slide_type": "subslide" 899 | } 900 | }, 901 | "source": [ 902 | "# Smart Pointers\n", 903 | "\n", 904 | "The `unique_ptr` owns and manages its data exclusively, i.e. the data can be owned by only one pointer at a time\n", 905 | "```C++\n", 906 | "std::unique_ptr data(new double[42]);\n", 907 | "std::unique_ptr other(data.release());\n", 908 | "```\n", 909 | "\n", 910 | "One can easily check if managed data is associated\n", 911 | "```C++\n", 912 | "if (data)\n", 913 | " std::cout << \"Data is associated\\n\";\n", 914 | "else\n", 915 | " std::cout << \"No data is associated\\n\";\n", 916 | "```\n" 917 | ] 918 | }, 919 | { 920 | "cell_type": "markdown", 921 | "id": "ef4b88fb", 922 | "metadata": { 923 | "slideshow": { 924 | "slide_type": "subslide" 925 | } 926 | }, 927 | "source": [ 928 | "# Smart Pointers\n", 929 | "Managed data can be updated\n", 930 | "```C++\n", 931 | "data.reset(new double[42]);\n", 932 | "```\n", 933 | "Managed data can be swapped\n", 934 | "```C++\n", 935 | "data.swap(other);\n", 936 | "```\n", 937 | "\n", 938 | "A class with a `unique_ptr` member is not default copiable\n", 939 | "\n", 940 | "A `unique_ptr[]` argument may allow more aggressive compiler optimizatiohn in a function than a raw pointer `T*`" 941 | ] 942 | }, 943 | { 944 | "cell_type": "markdown", 945 | "id": "ab64b60a", 946 | "metadata": { 947 | "slideshow": { 948 | "slide_type": "subslide" 949 | } 950 | }, 951 | "source": [ 952 | "# Smart Pointers with reference counting\n", 953 | "\n", 954 | "The `shared_ptr` shares ownership of the managed content with other smart pointers\n", 955 | "```C++\n", 956 | "std::shared_ptr data(new double[42]);\n", 957 | "std::shared_ptr other(data);\n", 958 | "```\n", 959 | "\n", 960 | "Content is deallocated when last pointer goes out of scope\n", 961 | "```C++\n", 962 | "std::cout << data.use_count(); // -> 2\n", 963 | "```\n", 964 | "Example: multiple data sets 'living' on the same mesh\n", 965 | "```C++\n", 966 | "class DataSet {\n", 967 | " std::shared_ptr mesh;\n", 968 | " };\n", 969 | "```" 970 | ] 971 | }, 972 | { 973 | "cell_type": "markdown", 974 | "id": "eee4fa90", 975 | "metadata": { 976 | "slideshow": { 977 | "slide_type": "slide" 978 | } 979 | }, 980 | "source": [ 981 | "# Bundle references with `std::tie`\n", 982 | "\n", 983 | "Example: use tuple comparison for own structure\n", 984 | "```C++\n", 985 | "struct S {\n", 986 | " int n;\n", 987 | " std::string s;\n", 988 | " float d;\n", 989 | " bool operator<(const S& rhs) const {\n", 990 | " // true if any comparison yields true \n", 991 | " return std::tie(n, s, d) < \n", 992 | " std::tie(rhs.n, rhs.s, rhs.d);\n", 993 | " }\n", 994 | "```" 995 | ] 996 | }, 997 | { 998 | "cell_type": "markdown", 999 | "id": "bb81131a", 1000 | "metadata": { 1001 | "slideshow": { 1002 | "slide_type": "subslide" 1003 | } 1004 | }, 1005 | "source": [ 1006 | "# Bundle multiple return values with `std::tie`\n", 1007 | "\n", 1008 | "Inserting an object into `std::set` with C++11/14\n", 1009 | "```C++\n", 1010 | "std::set Set;\n", 1011 | "S value{42, \"Test\", 3.14};\n", 1012 | "std::set::iterator iter;\n", 1013 | "bool inserted;\n", 1014 | "// unpacks return val of insert\n", 1015 | "std::tie(iter, inserted) = Set.insert(value);\n", 1016 | "```" 1017 | ] 1018 | }, 1019 | { 1020 | "cell_type": "markdown", 1021 | "id": "97ddca35", 1022 | "metadata": { 1023 | "slideshow": { 1024 | "slide_type": "slide" 1025 | } 1026 | }, 1027 | "source": [ 1028 | "# Structured bindings (C++17)\n", 1029 | "\n", 1030 | "Inserting an object into `std::set` with C++17\n", 1031 | "```C++\n", 1032 | "std::set Set;\n", 1033 | "S value{42, \"Test\", 3.14};\n", 1034 | "\n", 1035 | "// structured bindings\n", 1036 | "auto [iter, inserted] = Set.insert(value);\n", 1037 | "```\n" 1038 | ] 1039 | }, 1040 | { 1041 | "cell_type": "markdown", 1042 | "id": "f8de421c", 1043 | "metadata": { 1044 | "slideshow": { 1045 | "slide_type": "subslide" 1046 | } 1047 | }, 1048 | "source": [ 1049 | "# Structured bindings (C++17)\n", 1050 | "\n", 1051 | "Retrieving individual elements of an array\n", 1052 | "```C++\n", 1053 | "double Array[3] = { 1.0, 2.0, 3.0 };\n", 1054 | "auto [ a, b, c ] = Array;\n", 1055 | "```\n", 1056 | "\n", 1057 | "Retrieving individual elements of a `std::map`\n", 1058 | "```C++\n", 1059 | "std::map Map;\n", 1060 | "for (const auto & [k,v] : Map)\n", 1061 | "{\n", 1062 | " // k – key\n", 1063 | " // v – value \n", 1064 | "}\n", 1065 | "```" 1066 | ] 1067 | }, 1068 | { 1069 | "cell_type": "markdown", 1070 | "id": "43034412", 1071 | "metadata": { 1072 | "slideshow": { 1073 | "slide_type": "slide" 1074 | } 1075 | }, 1076 | "source": [ 1077 | "# Constexpr (C++11)\n", 1078 | "\n", 1079 | "C++11 introduced the constexpr specifier (constant\n", 1080 | "expression), which declares that the value of the function\n", 1081 | "or variable can be evaluated at compile time.\n", 1082 | "```C++\n", 1083 | "constexpr int factorial(int n)\n", 1084 | "{ return n <= 1 ? 1 : (n * factorial(n - 1)); }\n", 1085 | "```\n", 1086 | "\n", 1087 | "Such functions or variables can then be used where only\n", 1088 | "compile-time expressions are allowed\n", 1089 | "```C++\n", 1090 | "Vector v;\n", 1091 | "```" 1092 | ] 1093 | }, 1094 | { 1095 | "cell_type": "markdown", 1096 | "id": "04a7008e", 1097 | "metadata": { 1098 | "slideshow": { 1099 | "slide_type": "subslide" 1100 | } 1101 | }, 1102 | "source": [ 1103 | "# Constexpr (C++14)\n", 1104 | "\n", 1105 | "C++14 further allows `constexpr` functions to have local variables, which is not allowed in C++11\n", 1106 | "\n", 1107 | "```C++\n", 1108 | "constexpr int factorial(int n)\n", 1109 | "{\n", 1110 | " int val = (n <= 1 ? 1 : (n * factorial(n - 1)));\n", 1111 | " return val; \n", 1112 | "}\n", 1113 | "```" 1114 | ] 1115 | }, 1116 | { 1117 | "cell_type": "markdown", 1118 | "id": "3c784047", 1119 | "metadata": { 1120 | "slideshow": { 1121 | "slide_type": "subslide" 1122 | } 1123 | }, 1124 | "source": [ 1125 | "# If Constexpr (C++17)\n", 1126 | "\n", 1127 | "C++17 introduces if constexpr, which allows to discard branches of an if statement at compile-time based on a\n", 1128 | "`constexpr` condition (no more SFINAE and specialization?).\n", 1129 | "\n", 1130 | "```C++\n", 1131 | "template\n", 1132 | "constexpr int fibonacci()\n", 1133 | "{\n", 1134 | " if constexpr (N>=2)\n", 1135 | " return fibonacci() + fibonacci();\n", 1136 | " else\n", 1137 | " return N;\n", 1138 | "}\n", 1139 | "```" 1140 | ] 1141 | }, 1142 | { 1143 | "cell_type": "markdown", 1144 | "id": "4de5712c", 1145 | "metadata": { 1146 | "slideshow": { 1147 | "slide_type": "slide" 1148 | } 1149 | }, 1150 | "source": [ 1151 | "# Template argument deduction\n", 1152 | "\n", 1153 | "C++11/14: Template arguments can be deduced automatically by the compiler for functions only\n", 1154 | "```C++\n", 1155 | "template \n", 1156 | "auto sum (A a, B b) \n", 1157 | " -> typename std::common_type::type\n", 1158 | "{ return a + b; }\n", 1159 | "\n", 1160 | "auto result1 = sum(1.0, 2.0f);\n", 1161 | "auto result2 = sum(1.0, 2.0f);\n", 1162 | "```" 1163 | ] 1164 | }, 1165 | { 1166 | "cell_type": "markdown", 1167 | "id": "589e5c52", 1168 | "metadata": { 1169 | "slideshow": { 1170 | "slide_type": "subslide" 1171 | } 1172 | }, 1173 | "source": [ 1174 | "# Template argument deduction\n", 1175 | "\n", 1176 | "C++11/14: Template argument deduction for classes and\n", 1177 | "structures requires the use of auxiliary maker functions\n", 1178 | "```C++\n", 1179 | "auto t = std::make_tuple(\"Hello\", 42);\n", 1180 | "auto p = std::make_pair (\"Hello\", 42);\n", 1181 | "```\n", 1182 | "C++17 enables automatic template argument deduction directly for classes and structures\n", 1183 | "```C++\n", 1184 | "auto t = std::tuple(\"Hello\", 42);\n", 1185 | "auto p = std::pair(\"Hello\", 42);\n", 1186 | "```" 1187 | ] 1188 | }, 1189 | { 1190 | "cell_type": "markdown", 1191 | "id": "fd768151", 1192 | "metadata": { 1193 | "slideshow": { 1194 | "slide_type": "slide" 1195 | } 1196 | }, 1197 | "source": [ 1198 | "# Fold expressions (C++17)\n", 1199 | "\n", 1200 | "C++11 introduced variadic templates, which often require\n", 1201 | "recursive calls and an overloaded \"termination condition\"\n", 1202 | "\n", 1203 | "```C++\n", 1204 | "template\n", 1205 | "auto static sum(T arg)\n", 1206 | "{ return a; }\n", 1207 | " \n", 1208 | "template\n", 1209 | "auto sum(T arg, Ts... args)\n", 1210 | "{ return arg + sum(args...); }\n", 1211 | "```" 1212 | ] 1213 | }, 1214 | { 1215 | "cell_type": "markdown", 1216 | "id": "776e988e", 1217 | "metadata": { 1218 | "slideshow": { 1219 | "slide_type": "subslide" 1220 | } 1221 | }, 1222 | "source": [ 1223 | "# Fold expressions (C++17)\n", 1224 | "\n", 1225 | "C++17 introduces fold expressions, which reduce (=fold) a\n", 1226 | "parameter pack over a binary operator\n", 1227 | "```C++\n", 1228 | "template\n", 1229 | "auto sum(Ts... args)\n", 1230 | "{ return (args + ...); }\n", 1231 | "```\n", 1232 | "\n", 1233 | "Fold expressions can be used in more complex expressions\n", 1234 | "```C++\n", 1235 | "template\n", 1236 | "auto expression(Ts... args)\n", 1237 | "{ return (3 * args + 1 + ... + 10); }\n", 1238 | "```" 1239 | ] 1240 | }, 1241 | { 1242 | "cell_type": "markdown", 1243 | "id": "d8bb10e2", 1244 | "metadata": { 1245 | "slideshow": { 1246 | "slide_type": "subslide" 1247 | } 1248 | }, 1249 | "source": [ 1250 | "# Fold expressions (C++17)\n", 1251 | "\n", 1252 | "Associativity of fold expressions\n", 1253 | "```C++\n", 1254 | "return (args + ...); // arg0 + (arg1 + arg2)\n", 1255 | "return (... + args); // (arg0 + arg1) + arg2\n", 1256 | "```\n", 1257 | "\n", 1258 | "An example where associativity matters\n", 1259 | "```C++\n", 1260 | "return (args - ...); // arg0 - (arg1 - arg2) \n", 1261 | "return (... - args); // (arg0 - arg1) - arg2\n", 1262 | "```" 1263 | ] 1264 | }, 1265 | { 1266 | "cell_type": "markdown", 1267 | "id": "48f610ec", 1268 | "metadata": { 1269 | "slideshow": { 1270 | "slide_type": "subslide" 1271 | } 1272 | }, 1273 | "source": [ 1274 | "# Fold expressions (C++17)\n", 1275 | "\n", 1276 | "Incorrect treatment of empty parameter packs\n", 1277 | "```C++\n", 1278 | "template\n", 1279 | "auto sum(Ts... args)\n", 1280 | " {\n", 1281 | " return (args + ...);\n", 1282 | " }\n", 1283 | "```\n", 1284 | "What happens for `sum()`?\n", 1285 | "\n", 1286 | "-> error: fold of empty expansion over sum" 1287 | ] 1288 | }, 1289 | { 1290 | "cell_type": "markdown", 1291 | "id": "0b4b876a", 1292 | "metadata": { 1293 | "slideshow": { 1294 | "slide_type": "subslide" 1295 | } 1296 | }, 1297 | "source": [ 1298 | "# Fold expressions (C++17)\n", 1299 | "\n", 1300 | "Correct treatment of empty parameter packs\n", 1301 | "```C++\n", 1302 | "template\n", 1303 | "auto sum(Ts... args)\n", 1304 | " {\n", 1305 | " return (0 + ... + args);\n", 1306 | " }\n", 1307 | "```\n", 1308 | "Note that the 0 must be inside of the expression, i.e. **not**\n", 1309 | "```C++\n", 1310 | "return 0 + (... + args);\n", 1311 | "```" 1312 | ] 1313 | }, 1314 | { 1315 | "cell_type": "markdown", 1316 | "id": "437e3516", 1317 | "metadata": { 1318 | "slideshow": { 1319 | "slide_type": "subslide" 1320 | } 1321 | }, 1322 | "source": [ 1323 | "# Fold expressions (C++17)\n", 1324 | "\n", 1325 | "Print an arbitrary number of arguments\n", 1326 | "```C++\n", 1327 | "template\n", 1328 | "void FoldPrint(Args&&... args)\n", 1329 | "{ (std::cout << ... << args) << std::endl; }\n", 1330 | "```\n", 1331 | "\n", 1332 | "Fold over a comma operator\n", 1333 | "```C++\n", 1334 | "template\n", 1335 | "void push_back_vec(std::vector& v, Args&&... args) \n", 1336 | "{ (v.push_back(args), ...); }\n", 1337 | "```" 1338 | ] 1339 | }, 1340 | { 1341 | "cell_type": "markdown", 1342 | "id": "26d78bf6", 1343 | "metadata": { 1344 | "slideshow": { 1345 | "slide_type": "slide" 1346 | } 1347 | }, 1348 | "source": [ 1349 | "# Concepts (C++20)\n", 1350 | "\n", 1351 | "Recall homework assignment\n", 1352 | "```C++\n", 1353 | "template\n", 1354 | "struct Measure_add\n", 1355 | " {\n", 1356 | " static const int value = m1::value+m2::value;\n", 1357 | " static const Unit unit = m1::unit;\n", 1358 | " };\n", 1359 | "```\n", 1360 | "We assume that `m1` and `m2` provide a `value` and `unit` attribute. If another type without these attributes is passed the compiler throws an error." 1361 | ] 1362 | }, 1363 | { 1364 | "cell_type": "markdown", 1365 | "id": "f66c98a3", 1366 | "metadata": { 1367 | "slideshow": { 1368 | "slide_type": "subslide" 1369 | } 1370 | }, 1371 | "source": [ 1372 | "# Concepts (C++20)\n", 1373 | "\n", 1374 | "Manual workaround\n", 1375 | "```C++\n", 1376 | "template\n", 1377 | "struct Measure_add; // leave unimplemented\n", 1378 | "\n", 1379 | "template\n", 1380 | "struct Measure_add, Measure>\n", 1381 | " {\n", 1382 | " static const int value = v1+v2;\n", 1383 | " static const Unit unit = u1;\n", 1384 | " };\n", 1385 | "```" 1386 | ] 1387 | }, 1388 | { 1389 | "cell_type": "markdown", 1390 | "id": "96b7c005", 1391 | "metadata": { 1392 | "slideshow": { 1393 | "slide_type": "subslide" 1394 | } 1395 | }, 1396 | "source": [ 1397 | "# Concepts (C++20)\n", 1398 | "\n", 1399 | "```C++\n", 1400 | "#include \n", 1401 | "\n", 1402 | "template\n", 1403 | "concept Measurable = requires(){T::value; T::unit;};\n", 1404 | " \n", 1405 | "template\n", 1406 | "struct Measure_add{...};\n", 1407 | "```" 1408 | ] 1409 | }, 1410 | { 1411 | "cell_type": "markdown", 1412 | "id": "7be28872", 1413 | "metadata": { 1414 | "slideshow": { 1415 | "slide_type": "slide" 1416 | } 1417 | }, 1418 | "source": [ 1419 | "# Happy Holidays!\n", 1420 | "\n", 1421 | "
Please bring any questions you have about the projects to the office hour after Christmas!
\n", 1422 | "\n", 1423 | "
" 1424 | ] 1425 | }, 1426 | { 1427 | "cell_type": "code", 1428 | "execution_count": 8, 1429 | "id": "0191c688", 1430 | "metadata": { 1431 | "tags": [] 1432 | }, 1433 | "outputs": [ 1434 | { 1435 | "name": "stdout", 1436 | "output_type": "stream", 1437 | "text": [ 1438 | " *\n", 1439 | " ***\n", 1440 | " *****\n", 1441 | " *******\n", 1442 | " *********\n", 1443 | " ***********\n", 1444 | " *************\n", 1445 | " ***************\n", 1446 | " *****************\n", 1447 | "*******************\n", 1448 | " *****\n", 1449 | " *****\n", 1450 | " *****\n", 1451 | " Happy Holidays!\n" 1452 | ] 1453 | } 1454 | ], 1455 | "source": [ 1456 | "#include \n", 1457 | "#include \n", 1458 | "\n", 1459 | "int treeheight = 10;\n", 1460 | "int height = 3;\n", 1461 | "for (int i = 1; i <= treeheight; ++i) {\n", 1462 | " // Print spaces\n", 1463 | " std::cout << std::string(treeheight - i, ' ');\n", 1464 | " // Print asterisks for the tree\n", 1465 | " std::cout << std::string(2 * i - 1, '*');\n", 1466 | " std::cout << std::endl;\n", 1467 | "}\n", 1468 | "for (int i = 1; i <= height; ++i) {\n", 1469 | " // Print spaces\n", 1470 | " std::cout << std::string(treeheight/2+2, ' ');\n", 1471 | " // Print asterisks for the tree\n", 1472 | " std::cout << std::string(treeheight/2, '*');\n", 1473 | " std::cout << std::endl;\n", 1474 | "}\n", 1475 | "std::cout << \" Happy Holidays!\" << std::endl;" 1476 | ] 1477 | }, 1478 | { 1479 | "cell_type": "code", 1480 | "execution_count": null, 1481 | "id": "d44b895c-ca76-445a-ade8-cdd81ab3b076", 1482 | "metadata": {}, 1483 | "outputs": [], 1484 | "source": [] 1485 | } 1486 | ], 1487 | "metadata": { 1488 | "celltoolbar": "Slideshow", 1489 | "kernelspec": { 1490 | "display_name": "C++17", 1491 | "language": "C++17", 1492 | "name": "xcpp17" 1493 | }, 1494 | "language_info": { 1495 | "codemirror_mode": "text/x-c++src", 1496 | "file_extension": ".cpp", 1497 | "mimetype": "text/x-c++src", 1498 | "name": "c++", 1499 | "version": "17" 1500 | }, 1501 | "rise": { 1502 | "autolaunch": true, 1503 | "enable_chalkboard": true 1504 | } 1505 | }, 1506 | "nbformat": 4, 1507 | "nbformat_minor": 5 1508 | } 1509 | -------------------------------------------------------------------------------- /notebooks/lecture7.ipynb: -------------------------------------------------------------------------------- 1 | {"metadata":{"celltoolbar":"Slideshow","kernelspec":{"name":"xcpp17","display_name":"C++17","language":"C++17"},"language_info":{"codemirror_mode":"text/x-c++src","file_extension":".cpp","mimetype":"text/x-c++src","name":"c++","version":"17"},"rise":{"autolaunch":true,"enable_chalkboard":true}},"nbformat_minor":5,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Object-oriented scientific programming with C++\n\nMatthias Möller, Jonas Thies, Cálin Georgescu, Jingya Li (Numerical Analysis, DIAM)\n\nLecture 7","metadata":{"slideshow":{"slide_type":"slide"}},"id":"775247b4"},{"cell_type":"markdown","source":"## Goal of this lecture\n\n- advanced data structures (union, std::any, std::variant, std::tuple)\n- structuring C++ code into multiple files (build process: preprocessor, compiler, linker)\n- building code with CMake","metadata":{"slideshow":{"slide_type":"slide"},"tags":[]},"id":"c1aae2d4"},{"cell_type":"markdown","source":"## Unions\n\nC++ is a **strongly typed** programming language meaning that each object has a fixed type. \n\nDon't confuse this with *casting*, e.g., int i = 1.6f;. Here, variable i is of type int and the value 1.6f is downcasted.\n\nA union is a special class type that can hold one of its non-static data member at a time. \n\n**Example**:","metadata":{"slideshow":{"slide_type":"slide"},"tags":[]},"id":"1498cf93-24ae-4f3f-af13-1672f6f5bed3"},{"cell_type":"code","source":"union S {\n int i;\n float f;\n};","metadata":{"tags":[]},"execution_count":1,"outputs":[],"id":"d42b7834-cb09-4e3e-a1bc-3ea176f7738f"},{"cell_type":"markdown","source":"We can now create an object and assign a value to the first data member (int i):","metadata":{"slideshow":{"slide_type":"subslide"},"tags":[]},"id":"a98f5080-b65f-4c5e-a88d-7e954f3fb658"},{"cell_type":"code","source":"#include \n\nS s{1234};\nstd::cout << s.i << std::endl;","metadata":{"tags":[]},"execution_count":12,"outputs":[{"name":"stdout","text":"1234\n","output_type":"stream"}],"id":"729357c6-bbab-40d3-b639-90da2a95007f"},{"cell_type":"markdown","source":"The content of the second data member is undefined/meaningless","metadata":{"tags":[]},"id":"fd0aa248-932f-4d9d-8f25-e5d3b50e50bf"},{"cell_type":"code","source":"std::cout << s.f << std::endl;","metadata":{"tags":[]},"execution_count":11,"outputs":[{"name":"stdout","text":"1.7292e-42\n","output_type":"stream"}],"id":"3d303912-5d02-478c-b652-934221be2da9"},{"cell_type":"markdown","source":"We can assign new values to the existing object s even for different data members","metadata":{"slideshow":{"slide_type":"subslide"},"tags":[]},"id":"93e00211-902c-4baf-9af9-75167d72b5c2"},{"cell_type":"code","source":"s.i = 4321; std::cout << s.i << std::endl;\ns.f = 1.6f; std::cout << s.f << std::endl;","metadata":{"tags":[]},"execution_count":13,"outputs":[{"name":"stdout","text":"4321\n1.6\n","output_type":"stream"}],"id":"8add11f2-3326-4b72-8241-ce861885b582"},{"cell_type":"markdown","source":"A union always holds the value of the most recently assigned data member. Reading from another data member is undefined behavior.","metadata":{"tags":[]},"id":"bd567df3-d37a-4b45-ae5e-1a6efb91b7d1"},{"cell_type":"markdown","source":"Unions are a special class type with some **limitations** over regular classes and structures:\n\n- a union can have member functions (including constructors and destructors), but not virtual functions.\n- a union cannot have base classes and cannot be used as a base class.\n- a union cannot have non-static data members of reference types.\n- a union is at least as big as necessary to hold its largest data member.","metadata":{"tags":[],"slideshow":{"slide_type":"slide"}},"id":"006e84dd-1165-4c14-a546-4c897265896d"},{"cell_type":"markdown","source":"## std::variant\n\nIn C++17 and later, the std::variant class is a type-safe alternative for a union.\n\n**Example**:","metadata":{"slideshow":{"slide_type":"slide"},"tags":[]},"id":"5e18ca00-ec54-4bd5-a56f-0b797ca6db9b"},{"cell_type":"code","source":"#include \n#include \n\nstd::variant v{1234};\nstd::cout << std::get(v) << std::endl;\nstd::cout << std::get(v) << std::endl;","metadata":{"tags":[]},"execution_count":1,"outputs":[{"name":"stdout","text":"1234\n","output_type":"stream"},{"ename":"Standard Exception","evalue":"std::get: wrong index for variant","traceback":["Standard Exception: std::get: wrong index for variant"],"output_type":"error"}],"id":"ac822d46-2a9b-49af-8102-5357c3daed8e"},{"cell_type":"code","source":"v = 1.6f;\nstd::cout << std::get(v) << std::endl;\nstd::cout << std::get(v) << std::endl;","metadata":{"tags":[]},"execution_count":2,"outputs":[{"name":"stdout","text":"1.6\n","output_type":"stream"},{"ename":"Standard Exception","evalue":"std::get: wrong index for variant","traceback":["Standard Exception: std::get: wrong index for variant"],"output_type":"error"}],"id":"af17b44f-a7b7-4509-b0a7-bdc14777a2e5"},{"cell_type":"markdown","source":"Since std::get<TYPE> throws an exception if the wrong TYPE is requested one can catch inappropriate accesses with a try-catch construction.\n\nAlternatively, one can use std::get_if which returns a pointer to the value of a pointed-to variant or null. But don't forget to pass the argument by address and be aware that you get a pointer in return.\n\n**Example**:","metadata":{"slideshow":{"slide_type":"subslide"},"tags":[]},"id":"b9a591e4-d224-43e7-856d-c2786255309b"},{"cell_type":"code","source":"auto p = std::get_if(&v); std::cout << (p ? (*p) : 0) << std::endl;\nauto q = std::get_if(&v); std::cout << (q ? (*q) : 0) << std::endl;","metadata":{"tags":[]},"execution_count":3,"outputs":[{"name":"stdout","text":"1.6\n0\n","output_type":"stream"}],"id":"7abb8e0e-5641-4692-bdf7-9b1a03f5758c"},{"cell_type":"markdown","source":"## std::any\n\nA union or std::variant can only hold values of predefined type, i.e. it is not possible to hold *any* data type. Since C++17, the container class std::any can hold single values of *any* copy constructible type.\n\n**Example**:","metadata":{"slideshow":{"slide_type":"slide"},"tags":[]},"id":"1e1b6a05-6825-4416-b134-e744844d2330"},{"cell_type":"code","source":"#include \n#include \n\nstd::any a = 1234;\nstd::cout << a.type().name() << \": \" << std::any_cast(a) << std::endl;\n\na = 1.6f;\nstd::cout << a.type().name() << \": \" << std::any_cast(a) << std::endl;","metadata":{"tags":[]},"execution_count":3,"outputs":[{"name":"stdout","text":"i: 1234\nf: 1.6\n","output_type":"stream"}],"id":"66893bbd-87f0-46e7-9243-50cbbf533720"},{"cell_type":"markdown","source":"**Note**: An std::any object cannot be accessed without std::any_cast","metadata":{"slideshow":{"slide_type":"subslide"},"tags":[]},"id":"042bddde-87c2-4de2-aeab-205418f25eb8"},{"cell_type":"code","source":"std::cout << a << std::endl;","metadata":{"tags":[]},"execution_count":4,"outputs":[{"name":"stderr","text":"input_line_13:2:12: error: invalid operands to binary expression ('std::ostream' (aka 'basic_ostream') and 'std::any')\n std::cout << a << std::endl;\n ~~~~~~~~~ ^ ~\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/ostream:245:7: note: candidate function not viable: no known conversion from 'std::any' to 'const void *' for 1st argument; take the address of the argument with &\n operator<<(const void* __p)\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/cstddef:125:5: note: candidate function template not viable: no known conversion from 'std::ostream' (aka 'basic_ostream') to 'std::byte' for 1st argument\n operator<<(byte __b, _IntegerType __shift) noexcept\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/system_error:262:5: note: candidate function template not viable: no known conversion from 'std::any' to 'const std::error_code' for 2nd argument\n operator<<(basic_ostream<_CharT, _Traits>& __os, const error_code& __e)\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/ostream:108:7: note: candidate function not viable: no known conversion from 'std::any' to 'std::basic_ostream >::__ostream_type &(*)(std::basic_ostream >::__ostream_type &)' (aka 'basic_ostream > &(*)(basic_ostream > &)') for 1st argument\n operator<<(__ostream_type& (*__pf)(__ostream_type&))\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/ostream:117:7: note: candidate function not viable: no known conversion from 'std::any' to 'std::basic_ostream >::__ios_type &(*)(std::basic_ostream >::__ios_type &)' (aka 'basic_ios > &(*)(basic_ios > &)') for 1st argument\n operator<<(__ios_type& (*__pf)(__ios_type&))\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/ostream:127:7: note: candidate function not viable: no known conversion from 'std::any' to 'std::ios_base &(*)(std::ios_base &)' for 1st argument\n operator<<(ios_base& (*__pf) (ios_base&))\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/ostream:166:7: note: candidate function not viable: no known conversion from 'std::any' to 'long' for 1st argument\n operator<<(long __n)\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/ostream:170:7: note: candidate function not viable: no known conversion from 'std::any' to 'unsigned long' for 1st argument\n operator<<(unsigned long __n)\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/ostream:174:7: note: candidate function not viable: no known conversion from 'std::any' to 'bool' for 1st argument\n operator<<(bool __n)\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/ostream:178:7: note: candidate function not viable: no known conversion from 'std::any' to 'short' for 1st argument\n operator<<(short __n);\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/ostream:181:7: note: candidate function not viable: no known conversion from 'std::any' to 'unsigned short' for 1st argument\n operator<<(unsigned short __n)\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/ostream:189:7: note: candidate function not viable: no known conversion from 'std::any' to 'int' for 1st argument\n operator<<(int __n);\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/ostream:192:7: note: candidate function not viable: no known conversion from 'std::any' to 'unsigned int' for 1st argument\n operator<<(unsigned int __n)\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/ostream:201:7: note: candidate function not viable: no known conversion from 'std::any' to 'long long' for 1st argument\n operator<<(long long __n)\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/ostream:205:7: note: candidate function not viable: no known conversion from 'std::any' to 'unsigned long long' for 1st argument\n operator<<(unsigned long long __n)\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/ostream:220:7: note: candidate function not viable: no known conversion from 'std::any' to 'double' for 1st argument\n operator<<(double __f)\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/ostream:224:7: note: candidate function not viable: no known conversion from 'std::any' to 'float' for 1st argument\n operator<<(float __f)\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/ostream:232:7: note: candidate function not viable: no known conversion from 'std::any' to 'long double' for 1st argument\n operator<<(long double __f)\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/ostream:250:7: note: candidate function not viable: no known conversion from 'std::any' to 'std::nullptr_t' (aka 'nullptr_t') for 1st argument\n operator<<(nullptr_t)\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/ostream:276:7: note: candidate function not viable: no known conversion from 'std::any' to 'std::basic_ostream >::__streambuf_type *' (aka 'basic_streambuf > *') for 1st argument\n operator<<(__streambuf_type* __sb);\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/ostream:511:5: note: candidate function template not viable: no known conversion from 'std::any' to 'char' for 2nd argument\n operator<<(basic_ostream<_CharT, _Traits>& __out, char __c)\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/ostream:517:5: note: candidate function template not viable: no known conversion from 'std::any' to 'char' for 2nd argument\n operator<<(basic_ostream& __out, char __c)\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/ostream:523:5: note: candidate function template not viable: no known conversion from 'std::any' to 'signed char' for 2nd argument\n operator<<(basic_ostream& __out, signed char __c)\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/ostream:528:5: note: candidate function template not viable: no known conversion from 'std::any' to 'unsigned char' for 2nd argument\n operator<<(basic_ostream& __out, unsigned char __c)\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/ostream:606:5: note: candidate function template not viable: no known conversion from 'std::any' to 'const char *' for 2nd argument\n operator<<(basic_ostream& __out, const char* __s)\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/ostream:619:5: note: candidate function template not viable: no known conversion from 'std::any' to 'const signed char *' for 2nd argument\n operator<<(basic_ostream& __out, const signed char* __s)\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/ostream:624:5: note: candidate function template not viable: no known conversion from 'std::any' to 'const unsigned char *' for 2nd argument\n operator<<(basic_ostream& __out, const unsigned char* __s)\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/bits/ostream.tcc:321:5: note: candidate function template not viable: no known conversion from 'std::any' to 'const char *' for 2nd argument\n operator<<(basic_ostream<_CharT, _Traits>& __out, const char* __s)\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/ostream:506:5: note: candidate template ignored: deduced conflicting types for parameter '_CharT' ('char' vs. 'std::any')\n operator<<(basic_ostream<_CharT, _Traits>& __out, _CharT __c)\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/string_view:621:5: note: candidate template ignored: could not match 'basic_string_view' against 'std::any'\n operator<<(basic_ostream<_CharT, _Traits>& __os,\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/bits/basic_string.h:6480:5: note: candidate template ignored: could not match 'basic_string' against 'std::any'\n operator<<(basic_ostream<_CharT, _Traits>& __os,\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/bits/shared_ptr.h:69:5: note: candidate template ignored: could not match '__shared_ptr' against 'std::any'\n operator<<(std::basic_ostream<_Ch, _Tr>& __os,\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/bits/valarray_after.h:413:5: note: candidate template ignored: could not match '_Expr' against 'basic_ostream'\n _DEFINE_EXPR_BINARY_OPERATOR(<<, struct std::__shift_left)\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/bits/valarray_after.h:344:5: note: expanded from macro '_DEFINE_EXPR_BINARY_OPERATOR'\n operator _Op(const _Expr<_Dom1, typename _Dom1::value_type>& __v, \\\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/bits/valarray_after.h:413:5: note: candidate template ignored: could not match '_Expr' against 'basic_ostream'\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/bits/valarray_after.h:357:5: note: expanded from macro '_DEFINE_EXPR_BINARY_OPERATOR'\n operator _Op(const _Expr<_Dom, typename _Dom::value_type>& __v, \\\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/bits/valarray_after.h:413:5: note: candidate template ignored: could not match '_Expr' against 'std::any'\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/bits/valarray_after.h:370:5: note: expanded from macro '_DEFINE_EXPR_BINARY_OPERATOR'\n operator _Op(const typename _Dom::value_type& __t, \\\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/bits/valarray_after.h:413:5: note: candidate template ignored: could not match '_Expr' against 'basic_ostream'\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/bits/valarray_after.h:383:5: note: expanded from macro '_DEFINE_EXPR_BINARY_OPERATOR'\n operator _Op(const _Expr<_Dom,typename _Dom::value_type>& __e, \\\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/bits/valarray_after.h:413:5: note: candidate template ignored: could not match '_Expr' against 'std::any'\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/bits/valarray_after.h:396:5: note: expanded from macro '_DEFINE_EXPR_BINARY_OPERATOR'\n operator _Op(const valarray& __v, \\\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/valarray:1193:1: note: candidate template ignored: could not match 'valarray' against 'basic_ostream'\n_DEFINE_BINARY_OPERATOR(<<, __shift_left)\n^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/valarray:1155:5: note: expanded from macro '_DEFINE_BINARY_OPERATOR'\n operator _Op(const valarray<_Tp>& __v, const valarray<_Tp>& __w) \\\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/valarray:1193:1: note: candidate template ignored: could not match 'valarray' against 'basic_ostream'\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/valarray:1166:5: note: expanded from macro '_DEFINE_BINARY_OPERATOR'\n operator _Op(const valarray<_Tp>& __v, \\\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/valarray:1193:1: note: candidate template ignored: could not match 'valarray' against 'std::any'\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/valarray:1177:5: note: expanded from macro '_DEFINE_BINARY_OPERATOR'\n operator _Op(const typename valarray<_Tp>::value_type& __t, \\\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/ostream:589:5: note: candidate template ignored: could not match 'const _CharT *' against 'std::any'\n operator<<(basic_ostream<_CharT, _Traits>& __out, const _CharT* __s)\n ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/10.4.0/ostream:773:5: note: candidate template ignored: requirement '__and_ &> >, std::__is_convertible_to_basic_ostream &>, std::__is_insertable &, const std::any &, void> >::value' was not satisfied [with _Ostream = std::basic_ostream &, _Tp = std::any]\n operator<<(_Ostream&& __os, const _Tp& __x)\n ^\n","output_type":"stream"},{"ename":"Interpreter Error","evalue":"","traceback":["Interpreter Error: "],"output_type":"error"}],"id":"898c1a5a-b86d-4690-9b1b-203020285e9a"},{"cell_type":"markdown","source":"## Separate compilation\n\nC++ programs can vary greatly in size and complexity, as well as the number of people involved in the development. \n
\n\n
","metadata":{"slideshow":{"slide_type":"slide"}},"id":"4b4dd4f3"},{"cell_type":"markdown","source":"## Single-file programs\n
\n
\n

Problem

\n
\n \n
  • Many people work on the same project.
  • \n
  • A lot of source code.
  • \n
  • Need long time to compile.
  • \n
  • Want to share codes among different projects.
  • \n
    \n
    \n
    \n\n
    \n
    \n

    Solution: Multi-file programs

    \n
    \n \n
  • Divide source code into seperate files.
  • \n
  • Compile files separately.
  • \n
  • Only recompile files when modified.
  • \n
    \n
    \n
    ","metadata":{"slideshow":{"slide_type":"subslide"}},"id":"a8e77157"},{"cell_type":"markdown","source":"## Single-file programs vs. multi-file programs\n
    \n\n\n\n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n
    Single-file programsMulti-file programs
    SuitabilityIdeal for small, simple projects
    (Most assignments in this course)
    Large, complex projects
    Compilation TimeVery long for large programs,
    taking hours or days
    Much faster as files are compiled
    separately. Only changed files
    need recompilation.
    Impact on CompilerLarge single files might strain
    or even break the compiler due
    to resource demands.
    Less strain on the compiler as each
    file is smaller and compiled
    individually.
    Team CollaborationDifficult for team collaboration.
    Team members might interfere with
    each other's work.
    Facilitates parallel work.
    Team members can work on separate
    files without interference, enhancing
    productivity and minimizing conflicts.
    Modularity and MaintenanceLow.High.
    Linking vs. Compilation TimeNot applicable as there is only
    one compilation step.
    Linking is required to combine
    the separately compiled files into a
    single executable. Linking is generally
    much faster than compilation.
    ","metadata":{"slideshow":{"slide_type":"subslide"}},"id":"ec13410b"},{"cell_type":"markdown","source":"## Seperate compilation\nEvery **_source code_** file is transformed through compilation into an **_object code_** file. These object code files are then **_linked together_** to create the final **_executable program_**.\n\n**Source Code:** \n- Program in human-readable form (C++ language).\n\n**Object Code:**\n- Binary code: low-level representation of the source code, it's not yet a standalone program.\n- Exact addresses of variables and functions not known, represented by symbols.\n","metadata":{"slideshow":{"slide_type":"slide"}},"id":"9ea817db"},{"cell_type":"markdown","source":"## Seperate compilation\n**Linking:** \n- The linker takes all the object code files and combines them to create a single executable file.\n- It resolves references to symbols that are defined in different object files or libraries. For example, if one object file has a function call to a function defined in another object file, the linker connects these two.\n\n**Executable:** \n- Output of the linking process is the executable file, which can be run on a computer. \n- This file contains all the code and resources needed to execute the program.","metadata":{"slideshow":{"slide_type":"subslide"}},"id":"0468a513"},{"cell_type":"markdown","source":"## C++ build process\n- **Headers** (*.h) + **Translation Units** (*.cpp) contain source code.\n- **Preprocessor** performs text substitutions.\n- **Compiler** translates translation units into object files.\n- **Linker** links object files and _external libraries_ into an executable.\n
    ","metadata":{"slideshow":{"slide_type":"slide"}},"id":"92a9ced0"},{"cell_type":"markdown","source":"## C++ build process\n
    \nBased on Weblab assignment\n
    ","metadata":{"slideshow":{"slide_type":"subslide"}},"id":"9cfebd54"},{"cell_type":"markdown","source":"## Preprocessor \\#\nIn the C++ build process, the preprocessor is the first step that runs before the actual compilation.\n
    \n
    \n
    \n

    The primary functions of the preprocessor include:

    \n
    \n \n
  • modifying the source code
  • \n
  • processing preprocessor instructions (handling lines beginning with #)
  • \n
  • stripping out comments
  • \n
    \n
    \n
    \n","metadata":{"slideshow":{"slide_type":"slide"}},"id":"28a40252"},{"cell_type":"markdown","source":"## Preprocessor \\#\n
    \n
    \n

    Usage in C++ (and you should limit it to that)

    \n
    \n \n
  • combining source code (#include)
  • \n
  • conditional compilation
  • \n
  • obtaining platform information during compilation
  • \n
    \n
    \n
    ","metadata":{"slideshow":{"slide_type":"subslide"}},"id":"be5388f7"},{"cell_type":"markdown","source":"## Preprocessor MACROs\n**Macro**: a powerful feature provided by the C++ preprocessor, a tool that processes your code before it is compiled. \n\n1. **Constant definitions**: Macros are often used to define constants. For example:\n```C++\n#define PI 3.14159\n```\n2. **Function-like macro:** Macros can also mimic functions. These are useful for small, repetitive code that doesn't need the overhead of a function call. For instance:\n```C++\n#define SQUARE(x) ((x)*(x))\n```\n\n**NOTE**: it is important to use parentheses around parameters and the entire definition to ensure correct order of operations when the macro is used.\n","metadata":{"slideshow":{"slide_type":"slide"}},"id":"81bc16d9"},{"cell_type":"markdown","source":"## Preprocessor MACROs\n3. **Conditional compliation:** Macros can be used in conjunction with `#if`, `#ifdef`, `#ifndef`, and other preprocessor directives for conditional compilation.\n```C++\n#define DEBUG\n\n#ifdef DEBUG\n// Your own debug code goes there\n#endif\n```\n\n4. **Platform-specific code:** They can be used to compile code conditionally for different platforms or compilers.\n```C++\n#ifdef _WIN32\n// Windows-specific code\n#endif\n```","metadata":{"slideshow":{"slide_type":"subslide"}},"id":"3a69fa20"},{"cell_type":"markdown","source":"## Preprocessor MACROs \n5. And more... (but don't do it!)\n
    ","metadata":{"slideshow":{"slide_type":"subslide"}},"id":"db9f95ee"},{"cell_type":"markdown","source":"## Special MACROs\n- `__FILE__` (current file name), `__LINE__` (current line number), `__DATE__`(MMM DD YYYY) and `__TIME__` (hh:mm:ss)\n- `__cplusplus`: This macro is defined when a source code file is being compiled by the C++ compiler. Its value reflects the version of the C++ standard used by the compiler. \n - C++98: 199711L\n - C++11: 201103L\n - C++14: 201402L\n - C++17: 201703L\n - C++20: 202002L\n \nExample usage:\n```C++\n#if __cplusplus >= 201703L\n // C++17 (and later) code goes here\n#endif\n```","metadata":{"slideshow":{"slide_type":"subslide"}},"id":"762d6b63"},{"cell_type":"markdown","source":"## #include directive\n#include: used for including other files into the source file, typically header files.\n\nThere are two common usages:\n\n- Inserts a system header file from a location defined when the compiler was installed `#include `. Example:\n```C++\n#include // As we mentioned during lecture 1\n```\n- Inserts a file from the current directory. Example:\n```C++\n#include \"filename\"\n```\n\n
    \nNOTE: \n
      \n
    • Since header files are included in one or more *.cpp files using the #include directive, the content of these header files can be compiled multiple times -- once for each *.cpp that includes them. \n
    • \n
    • Each *.cpp file is compiled only once to produce its corresponding object file (*.o). \n
    • \n
    \n
    \n","metadata":{"slideshow":{"slide_type":"slide"}},"id":"953c4ba3"},{"cell_type":"markdown","source":"## Problems with the #include directive\n
    \n
    ","metadata":{"slideshow":{"slide_type":"slide"}},"id":"b1c0e83f"},{"cell_type":"markdown","source":"## Problems with the #include directive continued\n\nThe definition of square(int x) is processed two times during the compilation of main.cpp.\n\n
    ","metadata":{"slideshow":{"slide_type":"subslide"}},"id":"94052f7f"},{"cell_type":"markdown","source":"## Dealing with repeated #includes\nThe repeated inclusion of the same header file(s) can lead to **multiple definition errors** (conflicts during the linking stage) if not managed correctly.\n\nTo manage these issues, two common techniques can be used:\n
    \n
    \n \n
  • Include guards
  • \n
  • #pragma once
  • \n
    \n
    \n
    \n","metadata":{"slideshow":{"slide_type":"slide"}},"id":"24c83a33"},{"cell_type":"markdown","source":"## Include guards\n
    ","metadata":{"slideshow":{"slide_type":"subslide"}},"id":"63996008"},{"cell_type":"markdown","source":"## #pragma directive\n#pragma: a special preprocessor directive used to provide additional instructions to the compiler. \n\nIt is easier to use and less error-prone compared to traditional include guards.\n\n```C++\n#pragma once // tells the compiler to include a file only once in a single compilation\n```\n\nOther usage:\n```C++\n#pragma warning(disable: 4507) // disables a specific warning with the number 4507\n#pragma warning(default: 4507) // re-enables the warning\n```","metadata":{"slideshow":{"slide_type":"subslide"}},"id":"b24b8564"},{"cell_type":"markdown","source":"## Review: Declarations and definitions\n\nA *declaration* in C++ serves to introduce or reiterate the name of an entity in the program.\n```C++\nextern int globalVar; // Declaration of a variable\nvoid printMessage(); // Declaration of a function\nclass MyClass; // Forward declaration of a class\n```\n\nA *definition* in C++ goes beyond the declaration by not only **introducing or reiterating the name and specifying the type** but also by **providing the actual implementation or value and allocating storage**.\n\n```C++\nint globalVar = 10; // Definition of a variable\nvoid printMessage() { // Definition of a function\n std::cout << \"Hello\";\n}\nclass MyClass { // Definition of a class\npublic:\n void doSomething() {}\n};\n```","metadata":{"slideshow":{"slide_type":"slide"}},"id":"a592ff22"},{"cell_type":"markdown","source":"## Organizing declarations and definitions into multiple files\n\nSimple example:\n
    ","metadata":{"slideshow":{"slide_type":"slide"}},"id":"93cadf19"},{"cell_type":"markdown","source":"## What's in a header file ?\nHeader files are intended to contain:\n- **Function declarations**: declare the functions you intend to use or implement. This tells the compiler about their existence and how they should be called.\n- **Class declarations**: declare the classes you intend to use of implement. This tells the compiler about their existence and how they should be instantiated.\n- **Templates**: since templates need to be known at compile time in every file where they are used, they are usually defined in header files.\n- **Global constants and macros**: define constants and macros that are to be shared across multiple source files.\n- **Inline functions**: small functions that benefit from being inline (like getters and setters) can be defined in header files.","metadata":{"slideshow":{"slide_type":"slide"}},"id":"62b7d583"},{"cell_type":"markdown","source":"## Best practices\n- **Include guards:** always use include guards (`#ifndef`, `#define`, `#endif`) or `#pragma once` in header files to prevent multiple inclusion issues.\n- **Minimize dependencies:** include only what is **necessary** in header files to reduce compilation times and dependencies.\n- **Consistent file naming:** keep a consistent naming scheme for your files. Typically, class names are used for the names of the corresponding header and source files.\n- **Avoid using directives in headers**","metadata":{"slideshow":{"slide_type":"slide"}},"id":"4c50ad14"},{"cell_type":"markdown","source":"## Namespace pollution\n
    \n
    \n

    Avoid in headers

    \n
    \n\n- using namespaces\n```C++\nusing namespace std;\n```\n- using symbols of a namespace\n```C++\nusing std::cout;\n```\n\n
    \n

    WHY?

    \n
    \n\n>It forces all symbols from the specified namespace into the global namespace for all source files that include that header. This can lead to unexpected name conflicts and **namespace pollution**.","metadata":{"slideshow":{"slide_type":"subslide"}},"id":"0d669312"},{"cell_type":"markdown","source":"## Linking\n
    \n
    $ g++ -c main.cpp -o main.o\n$ g++ -c math_util.cpp -o math_util.o\n$ g++ main.o math_util.o -o myexe\n$ ./myexe\n
    \n
    \n
    \n

    Explanation:

    \n
    \n\n- Preprocessing and compiling `main.cpp` yields `main.o`\n- Preprocessing and compiling `math_util.cpp` yields `math_util.o`\n- Linking `math_util.o` and `main.o` yields executable `myexe`\n- Run program `myexe`","metadata":{"slideshow":{"slide_type":"slide"}},"id":"56257468"},{"cell_type":"markdown","source":"## CMake: depart from the Weblab nutshell to the great universe\nA solution to streamline the often tedious and complex task of managing linking in C++ projects. \n\nCMake is **not** a build system like [Unix Make](https://en.wikipedia.org/wiki/Make_(software)) but a **build system generator**. \n\nIt provides a family of tools and a _domain-specific_ language (DSL) to describe what the build system should achieve, you can reuse the same CMake scripts to obtain native build systems on any platform.\n\n","metadata":{"slideshow":{"slide_type":"slide"}},"id":"6ed0498e"},{"cell_type":"markdown","source":"## Generate and Build\nThe process of generating a Makefile and compiling with CMake on a Linux platform is as follows:\n
    \n
      \n
    • Write the configuration file CMakeLists.txt.
    • \n
    • Run the command cmake path/to/your/CMakeLists.txt to generate a Makefile.
    • \n
    • Run the command make to compile your project.
    • \n
    \n
    ","metadata":{"slideshow":{"slide_type":"subslide"}},"id":"6dadbc10"},{"cell_type":"markdown","source":"
    ","metadata":{"slideshow":{"slide_type":"subslide"}},"id":"d8219615"},{"cell_type":"markdown","source":"## Hello CMake!\nA minimal project:\n```C++\n#include \n\nint main(){\n std::cout << \"Hello CMake!\" << std::endl;\n return 0;\n}\n```\nAssuming the working directory only contains ``main.cpp``. We need to add ``CMakeLists.txt``.\n```cmake\n# Set the requirement on minimum version of CMake\ncmake_minimum_required(VERSION 3.9)\n\n# Declare project and its programming language.\nproject(HelloCMake)\nset(CMAKE_CXX_STANDARD 11)\n\n# Create executable target and linking\nadd_executable(hellocmake main.cpp)\n```\n","metadata":{"slideshow":{"slide_type":"slide"}},"id":"ec3d895e"},{"cell_type":"markdown","source":"## Hello CMake!\nNow we are ready to call CMake and generate the Makefile: \n```bash\ncmake .\n```\n`.` represents the current directory.\n\n
    \n
    \n

    Best practice: out-of-source build

    \n
    \n\nBy specifying the project source root (**-S** option) and target build location (**-B** option) on the command line:\n```bash\ncmake -S . -B build/\n```","metadata":{"slideshow":{"slide_type":"subslide"}},"id":"36da0cb0"},{"cell_type":"markdown","source":"## Hello CMake!\n
    \n
    \n

    Classic Approach

    \n
    \n\nThe older CMake approach was to change to the build folder to explicitly run the build tool (**make**) from that folder:\n```bash\nmkdir build\ncd build\ncmake ..\nmake\n```\nThe output should be look like this:\n\n```bash\nScanning dependencies of target hellocmake\n[ 50%] Building CXX object CMakeFiles/hellocmake.dir/main.cpp.o\n[100%] Linking CXX executable hellocmake\n[100%] Build target hellocmake\n```","metadata":{"slideshow":{"slide_type":"subslide"}},"id":"f5e6d853"},{"cell_type":"markdown","source":"## END ...\n
    \n
    \n

    For more information about CMake

    \n
    \n\nCMake – The Dark Arts: https://blog.feabhas.com/2021/07/cmake-part-1-the-dark-arts/\n\nCMake Documentation: https://cmake.org/documentation/\n\nCMake hands-on workshop: https://enccs.github.io/cmake-workshop/\n\nC++ Starter Project with Complete CMake Setup by Jason Turner: https://github.com/cpp-best-practices/cmake_template\n
    \n
    \n

    For more information about C++ program structure

    \n
    \n\nBack to Basics: Compiling and Linking - Ben Saks: https://www.youtube.com/watch?v=cpkDQaYttR4\n\nBeginner's Guide to Linkers: https://www.lurklurk.org/linkers/linkers.html\n","metadata":{"slideshow":{"slide_type":"slide"}},"id":"d441ef00"},{"cell_type":"markdown","source":"","metadata":{"slideshow":{"slide_type":"slide"}},"id":"6bf44800"}]} -------------------------------------------------------------------------------- /notebooks/plots/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/.DS_Store -------------------------------------------------------------------------------- /notebooks/plots/OOPs-Concepts.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/OOPs-Concepts.jpg -------------------------------------------------------------------------------- /notebooks/plots/address-of.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/address-of.png -------------------------------------------------------------------------------- /notebooks/plots/class_lego.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/class_lego.png -------------------------------------------------------------------------------- /notebooks/plots/cppexample1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/cppexample1.png -------------------------------------------------------------------------------- /notebooks/plots/cppexample2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/cppexample2.png -------------------------------------------------------------------------------- /notebooks/plots/cppexample3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/cppexample3.png -------------------------------------------------------------------------------- /notebooks/plots/cppprocon1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/cppprocon1.png -------------------------------------------------------------------------------- /notebooks/plots/doublepointer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/doublepointer.png -------------------------------------------------------------------------------- /notebooks/plots/dynamicarray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/dynamicarray.png -------------------------------------------------------------------------------- /notebooks/plots/flashback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/flashback.png -------------------------------------------------------------------------------- /notebooks/plots/historycpp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/historycpp.png -------------------------------------------------------------------------------- /notebooks/plots/lecture2_abstract_classes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture2_abstract_classes.png -------------------------------------------------------------------------------- /notebooks/plots/lecture2_gaussrule.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture2_gaussrule.png -------------------------------------------------------------------------------- /notebooks/plots/lecture2_program_design.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture2_program_design.png -------------------------------------------------------------------------------- /notebooks/plots/lecture2_program_design_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture2_program_design_02.png -------------------------------------------------------------------------------- /notebooks/plots/lecture2_program_design_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture2_program_design_03.png -------------------------------------------------------------------------------- /notebooks/plots/lecture3_StaticPolyRoT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture3_StaticPolyRoT.png -------------------------------------------------------------------------------- /notebooks/plots/lecture3_overloadingvsoverriding.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture3_overloadingvsoverriding.png -------------------------------------------------------------------------------- /notebooks/plots/lecture3cat.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture3cat.gif -------------------------------------------------------------------------------- /notebooks/plots/lecture4_cat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture4_cat.png -------------------------------------------------------------------------------- /notebooks/plots/lecture5-doublelinkedlist.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture5-doublelinkedlist.gif -------------------------------------------------------------------------------- /notebooks/plots/lecture5-it0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture5-it0.png -------------------------------------------------------------------------------- /notebooks/plots/lecture5-it9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture5-it9.png -------------------------------------------------------------------------------- /notebooks/plots/lecture5-itend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture5-itend.png -------------------------------------------------------------------------------- /notebooks/plots/lecture5-iterator.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture5-iterator.gif -------------------------------------------------------------------------------- /notebooks/plots/lecture6-happy-holiday.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture6-happy-holiday.png -------------------------------------------------------------------------------- /notebooks/plots/lecture6-smart_pointers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture6-smart_pointers.png -------------------------------------------------------------------------------- /notebooks/plots/lecture7-LAexpression.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture7-LAexpression.png -------------------------------------------------------------------------------- /notebooks/plots/lecture7-LAexpression2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture7-LAexpression2.png -------------------------------------------------------------------------------- /notebooks/plots/lecture7-buildmodel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture7-buildmodel.png -------------------------------------------------------------------------------- /notebooks/plots/lecture7-class_chart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture7-class_chart.png -------------------------------------------------------------------------------- /notebooks/plots/lecture7-cmake1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture7-cmake1.png -------------------------------------------------------------------------------- /notebooks/plots/lecture7-cmakememe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture7-cmakememe.png -------------------------------------------------------------------------------- /notebooks/plots/lecture7-decl_def.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture7-decl_def.png -------------------------------------------------------------------------------- /notebooks/plots/lecture7-gismo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture7-gismo.png -------------------------------------------------------------------------------- /notebooks/plots/lecture7-include_problem1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture7-include_problem1.png -------------------------------------------------------------------------------- /notebooks/plots/lecture7-include_problem2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture7-include_problem2.png -------------------------------------------------------------------------------- /notebooks/plots/lecture7-include_problem3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture7-include_problem3.png -------------------------------------------------------------------------------- /notebooks/plots/lecture7-iterator1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture7-iterator1.png -------------------------------------------------------------------------------- /notebooks/plots/lecture7-iterator10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture7-iterator10.png -------------------------------------------------------------------------------- /notebooks/plots/lecture7-iterator11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture7-iterator11.png -------------------------------------------------------------------------------- /notebooks/plots/lecture7-iterator2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture7-iterator2.png -------------------------------------------------------------------------------- /notebooks/plots/lecture7-iterator3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture7-iterator3.png -------------------------------------------------------------------------------- /notebooks/plots/lecture7-iterator4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture7-iterator4.png -------------------------------------------------------------------------------- /notebooks/plots/lecture7-iterator5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture7-iterator5.png -------------------------------------------------------------------------------- /notebooks/plots/lecture7-iterator6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture7-iterator6.png -------------------------------------------------------------------------------- /notebooks/plots/lecture7-iterator7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture7-iterator7.png -------------------------------------------------------------------------------- /notebooks/plots/lecture7-iterator8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture7-iterator8.png -------------------------------------------------------------------------------- /notebooks/plots/lecture7-iterator9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture7-iterator9.png -------------------------------------------------------------------------------- /notebooks/plots/lecture7-preprocessor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture7-preprocessor.png -------------------------------------------------------------------------------- /notebooks/plots/lecture7-preprocessormeme.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/lecture7-preprocessormeme.jpg -------------------------------------------------------------------------------- /notebooks/plots/object_lego.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/object_lego.png -------------------------------------------------------------------------------- /notebooks/plots/paymentmethod1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/paymentmethod1.png -------------------------------------------------------------------------------- /notebooks/plots/paymentmethod2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/paymentmethod2.png -------------------------------------------------------------------------------- /notebooks/plots/pythonprocon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/pythonprocon.png -------------------------------------------------------------------------------- /notebooks/plots/squarewheelcar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmoelle1/OospCpp/a187663901864d46497f6d097cc1afa6d04a121a/notebooks/plots/squarewheelcar.png -------------------------------------------------------------------------------- /notebooks/rise.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Roboto+Slab:100,200,300,400,500,600,700,800,900&lang=en'); 2 | @import url('https://fonts.googleapis.com/css?family=Open+Sans:100,200,300,400,500,600,700,800,900&lang=en'); 3 | 4 | .rise-enabled { 5 | background-color: #f7f7f7 !important; 6 | border-top: 30px #00A6D6 solid; 7 | border-bottom: 30px #00A6D6 solid; 8 | } 9 | 10 | .question { 11 | color: #009B77; 12 | } 13 | 14 | .your_turn { 15 | color: #EC6842; 16 | font-size: 150%; 17 | font-weight: bold; 18 | } 19 | 20 | .rendered_html h1 { 21 | color: #00A6D6; 22 | font-family: 'Roboto Slab', sans-serif; 23 | font-weight: 500; 24 | font-size: 90%; 25 | } 26 | 27 | .rendered_html { 28 | font-family: 'Open Sans', sans-serif; 29 | font-weight: 100; 30 | font-size: 80%; 31 | } 32 | 33 | .rendered_html code { 34 | font-weight: 100; 35 | font-size: 80%; 36 | } 37 | 38 | .rendered_html table, .rendered_html th, .rendered_html tr, .rendered_html td { 39 | font-size: 100%; 40 | } 41 | 42 | .container.slides .celltoolbar, .container.slides .hide-in-slideshow { 43 | display: None ! important; 44 | } 45 | --------------------------------------------------------------------------------