├── .clang-format ├── .github ├── stale.yml └── workflows │ ├── build.yml │ └── docs.yml ├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── cmake ├── FindAsio.cmake ├── FindConcepts.cmake ├── FindExecution.cmake ├── FindFilesystem.cmake ├── FindPMR.cmake ├── FindTBB.cmake ├── functions.cmake └── functions │ ├── project_flags.cmake │ ├── qt_helpers.cmake │ ├── sanitizers.cmake │ └── target_options.cmake ├── docs ├── algorithms-data-structures │ ├── algorithm │ │ ├── basic-algorithms.md │ │ ├── ranges.md │ │ ├── searching.md │ │ └── sorting.md │ ├── data-structures │ │ ├── associative-containers.md │ │ ├── bitset.md │ │ ├── build-script.md │ │ ├── memory-resources.md │ │ ├── sequence-containers.md │ │ ├── span.md │ │ └── spatial-containers.md │ ├── date-and-time │ │ ├── clock.md │ │ └── datetime.md │ ├── heterogeneous-types │ │ ├── any.md │ │ ├── optional.md │ │ ├── tuples.md │ │ └── variant.md │ ├── random │ │ ├── pcg.md │ │ └── random.md │ └── templates │ │ ├── concepts.md │ │ ├── metaprogramming.md │ │ ├── sfinae.md │ │ ├── template-aliases.md │ │ └── template-parameters.md ├── basic-syntax │ ├── basic-data-types │ │ ├── aggregate-initialization.md │ │ ├── arrays.md │ │ ├── build-script.md │ │ ├── move.md │ │ ├── raw-arrays.md │ │ ├── strings.md │ │ ├── structured-binding.md │ │ └── vectors.md │ ├── control-flow │ │ ├── conditional.md │ │ ├── loops.md │ │ ├── scopes.md │ │ └── sequential.md │ ├── data-types │ │ ├── auto.md │ │ ├── constants.md │ │ ├── fundamental-data-types.md │ │ └── operators.md │ ├── files │ │ ├── file-streams.md │ │ └── filesystem.md │ ├── functions │ │ ├── build-script.md │ │ ├── function.md │ │ └── lambda.md │ ├── input-output │ │ ├── format.md │ │ ├── hello-world.md │ │ ├── input.md │ │ └── output.md │ └── pointers │ │ ├── address-operator.md │ │ ├── build-script.md │ │ ├── raw-pointers.md │ │ ├── references.md │ │ └── smart-pointers.md ├── cmake-functions │ ├── project-flags.md │ ├── qt-helpers.md │ ├── sanitizers.md │ └── target-options.md ├── contributors.md ├── guis │ ├── imgui.md │ ├── opengl-glfw.md │ ├── opengl-sdl.md │ ├── qt.md │ ├── system-tray.md │ └── webview.md ├── img │ ├── banner.png │ ├── banner.xcf │ ├── hello_cling.png │ ├── hello_emscripten.png │ ├── pedantic_clion.png │ └── set_compiler.png ├── index.md ├── installing-cpp │ ├── cling.md │ ├── cmake.md │ ├── compiler.md │ ├── ides.md │ └── webassembly.md ├── javascripts │ └── extra.js ├── macros.py ├── overrides │ └── main.html ├── programming-paradigms │ ├── basic-paradigms │ │ ├── crtp.md │ │ ├── polymorphism.md │ │ └── shared-from-this.md │ └── parallelism │ │ ├── async.md │ │ ├── build-script.md │ │ ├── execution-policies.md │ │ ├── executors.md │ │ ├── signals.md │ │ ├── threads.md │ │ └── timers.md ├── quickstart.md ├── testing │ ├── boostut.md │ ├── catch2.md │ ├── plots.md │ └── source-location.md └── utilities │ ├── networking │ ├── async-network.md │ ├── http-server.md │ └── network.md │ └── regular-expressions │ └── regex.md ├── examples ├── CMakeLists.txt ├── algorithm │ ├── CMakeLists.txt │ ├── algorithm.cpp │ ├── searching.cpp │ └── sorting.cpp ├── basic_types │ ├── CMakeLists.txt │ └── vector_matrix.cpp ├── control_flow │ ├── CMakeLists.txt │ └── calculator.cpp ├── data_structures │ ├── CMakeLists.txt │ └── graph_example.cpp ├── datetime │ ├── CMakeLists.txt │ └── flushtime.cpp ├── functions │ ├── CMakeLists.txt │ └── recursive_bench.cpp ├── gui │ └── qt │ │ └── warehouse │ │ ├── CMakeLists.txt │ │ ├── lib │ │ ├── CMakeLists.txt │ │ ├── product.cpp │ │ ├── product.h │ │ ├── warehouse.cpp │ │ └── warehouse.h │ │ └── standalone │ │ ├── CMakeLists.txt │ │ ├── cli │ │ ├── CMakeLists.txt │ │ ├── application.cpp │ │ ├── application.h │ │ └── main.cpp │ │ └── gui │ │ └── CMakeLists.txt └── paradigms │ └── oop │ ├── CMakeLists.txt │ ├── main.cpp │ ├── product.cpp │ ├── product.h │ ├── warehouse.cpp │ └── warehouse.h ├── mkdocs.yml └── snippets ├── CMakeLists.txt ├── algorithm ├── CMakeLists.txt ├── algorithms.cpp ├── ranges.cpp ├── searching.cpp └── sorting.cpp ├── basic_types ├── CMakeLists.txt ├── aggregate_initialization.cpp ├── arrays.cpp ├── move.cpp ├── raw_arrays.cpp ├── strings.cpp ├── struct.cpp ├── structured_binding.cpp └── vectors.cpp ├── control_flow ├── CMakeLists.txt ├── conditional.cpp ├── loops.cpp ├── scopes.cpp └── sequential.cpp ├── data_structures ├── CMakeLists.txt ├── associative_containers.cpp ├── bitset.cpp ├── container_adapters.cpp ├── memory_resources.cpp ├── sequence_containers.cpp ├── span.cpp └── spatial_containers.cpp ├── data_types ├── CMakeLists.txt ├── auto.cpp ├── constants.cpp ├── data_types.cpp └── operators.cpp ├── datetime ├── CMakeLists.txt ├── clock.cpp └── datetime.cpp ├── files ├── CMakeLists.txt ├── files.cpp └── filesystem.cpp ├── functions ├── CMakeLists.txt ├── functions.cpp └── lambda.cpp ├── gui ├── CMakeLists.txt ├── imgui │ ├── CMakeLists.txt │ └── imgui_hello.cpp ├── opengl │ ├── CMakeLists.txt │ ├── glfw │ │ ├── CMakeLists.txt │ │ └── opengl_hello.cpp │ └── sdl │ │ ├── CMakeLists.txt │ │ └── sdl_hello.cpp ├── qt │ ├── CMakeLists.txt │ └── qt_hello.cpp ├── tray │ ├── CMakeLists.txt │ └── tray_hello.cpp └── webview │ ├── CMakeLists.txt │ └── webview_hello.cpp ├── heterogeneous_types ├── CMakeLists.txt ├── any.cpp ├── optional.cpp ├── tuples.cpp └── variant.cpp ├── input_output ├── CMakeLists.txt ├── cin.cpp ├── format.cpp ├── hello_world.cpp ├── iomanip.cpp └── output.cpp ├── networking ├── CMakeLists.txt ├── network.cpp ├── network_async.cpp └── server │ ├── .gitignore │ ├── CMakeLists.txt │ ├── connection.cpp │ ├── connection.hpp │ ├── connection_manager.cpp │ ├── connection_manager.hpp │ ├── header.hpp │ ├── main.cpp │ ├── mime_types.cpp │ ├── mime_types.hpp │ ├── reply.cpp │ ├── reply.hpp │ ├── request.hpp │ ├── request_handler.cpp │ ├── request_handler.hpp │ ├── request_parser.cpp │ ├── request_parser.hpp │ ├── server.cpp │ └── server.hpp ├── paradigms ├── CMakeLists.txt ├── CRTP.cpp ├── polymorphism.cpp └── shared_from_this.cpp ├── parallel ├── CMakeLists.txt ├── async_pools.cpp ├── executors.cpp ├── multithreading.cpp ├── policies.cpp ├── signals.cpp └── timers.cpp ├── pointers ├── CMakeLists.txt ├── address_operator.cpp ├── raw_pointers.cpp ├── references.cpp └── smart_pointers.cpp ├── random ├── CMakeLists.txt ├── pcg.cpp └── random.cpp ├── templates ├── CMakeLists.txt ├── concepts.cpp ├── metaprogramming.cpp ├── sfinae.cpp ├── template_alias.cpp └── template_functions.cpp ├── tests ├── CMakeLists.txt ├── plots.cpp ├── source_location.cpp ├── source_location.h ├── unit_tests_catch.cpp └── unit_tests_ut.cpp └── utilities ├── CMakeLists.txt └── regex.cpp /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 60 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 7 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - pinned 8 | - security 9 | # Label to use when marking an issue as stale 10 | staleLabel: wontfix 11 | # Comment to post when marking an issue as stale. Set to `false` to disable 12 | markComment: > 13 | This issue has been automatically marked as stale because it has not had 14 | recent activity. It will be closed if no further activity occurs. Thank you 15 | for your contributions. -------------------------------------------------------------------------------- /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | name: Docs Generator 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | 9 | jobs: 10 | generateDOC: 11 | name: Docs Generator 12 | runs-on: ubuntu-20.04 13 | steps: 14 | - uses: actions/checkout@v2 15 | - name: Update Contributors 16 | uses: akhilmhdh/contributors-readme-action@v2.3.3 17 | env: 18 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 19 | with: 20 | image_size: 100 21 | columns_per_row: 6 22 | readme_path: docs/contributors.md 23 | - name: Setup Python 24 | uses: actions/setup-python@v2 25 | with: 26 | python-version: 3.x 27 | - name: Install Mkdocs Material 28 | run: pip install mkdocs-material 29 | - name: Install Macros for Mkdocs 30 | run: pip install mkdocs-macros-plugin 31 | - name: Deploy mkdocs to gh-pages branch 32 | run: mkdocs gh-deploy --force -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build directories 2 | build 3 | cmake-build-* 4 | cmake-build-debug 5 | cmake-build-release 6 | cmake-build-debug-gcc 7 | cmake-build-release-gcc 8 | cmake-build-debug-msvc 9 | cmake-build-release-msvc 10 | cmake-build-debug-* 11 | cmake-build-release-* 12 | build*/ 13 | out 14 | 15 | # IDE settings 16 | .idea 17 | codealike.json 18 | .vs 19 | CMakeLists.txt.user 20 | CMakeSettings.json 21 | gh-md-toc 22 | /.vs 23 | /CMakeSettings.json 24 | 25 | # Hidden files 26 | .DS_Store 27 | 28 | # Prerequisites 29 | *.d 30 | 31 | # Compiled Object files 32 | *.slo 33 | *.lo 34 | *.o 35 | *.obj 36 | 37 | # Precompiled Headers 38 | *.gch 39 | *.pch 40 | 41 | # Compiled Dynamic libraries 42 | *.so 43 | *.dylib 44 | *.dll 45 | 46 | # Fortran module files 47 | *.mod 48 | *.smod 49 | 50 | # Compiled Static libraries 51 | *.lai 52 | *.la 53 | *.a 54 | *.lib 55 | 56 | # Executables 57 | *.exe 58 | *.out 59 | *.app 60 | 61 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Alan de Freitas 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /cmake/FindConcepts.cmake: -------------------------------------------------------------------------------- 1 | include(CheckCXXSourceCompiles) 2 | 3 | check_cxx_source_compiles(" 4 | #include 5 | #include 6 | template concept Number = std::is_arithmetic_v; 7 | int main() { return 0; } 8 | " Concepts_FOUND) 9 | 10 | if (Concepts_FOUND AND NOT (TARGET std::concepts)) 11 | add_library (std::concepts INTERFACE IMPORTED) 12 | set_target_properties (std::concepts 13 | PROPERTIES 14 | INTERFACE_COMPILE_OPTIONS $<$:-fconcepts>) 15 | endif () -------------------------------------------------------------------------------- /cmake/FindExecution.cmake: -------------------------------------------------------------------------------- 1 | include(CheckCXXSourceCompiles) 2 | 3 | if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") 4 | find_package(TBB QUIET) 5 | if (NOT TBB_FOUND) 6 | set(Execution_FOUND OFF) 7 | return() 8 | else() 9 | add_library(std::execution INTERFACE IMPORTED) 10 | target_link_libraries(std::execution INTERFACE tbb) 11 | endif() 12 | endif () 13 | 14 | check_cxx_source_compiles(" 15 | #include 16 | #include 17 | int main() { 18 | std::vector x{5,7,6,4,8,2}; 19 | std::sort(std::execution::par, x.begin(), x.end()); 20 | return 0; 21 | } 22 | " Execution_FOUND) 23 | 24 | if (Execution_FOUND AND NOT (TARGET std::execution)) 25 | add_library(std::execution INTERFACE IMPORTED) 26 | endif () -------------------------------------------------------------------------------- /cmake/FindPMR.cmake: -------------------------------------------------------------------------------- 1 | include(CheckCXXSourceCompiles) 2 | 3 | check_cxx_source_compiles(" 4 | #include 5 | #include 6 | #include 7 | int main() { 8 | std::pmr::unsynchronized_pool_resource pool; 9 | std::pmr::vector vec{ &pool }; 10 | printf(\"%d\", vec.size()); 11 | return EXIT_SUCCESS; 12 | } 13 | " PMR_FOUND) 14 | 15 | # If compiled correctly (concepts found) 16 | if (PMR_FOUND AND NOT (TARGET std::pmr)) 17 | add_library(std::pmr INTERFACE IMPORTED) 18 | endif () -------------------------------------------------------------------------------- /cmake/functions.cmake: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_LIST_DIR}/functions/project_flags.cmake) 2 | include(${CMAKE_CURRENT_LIST_DIR}/functions/sanitizers.cmake) 3 | include(${CMAKE_CURRENT_LIST_DIR}/functions/target_options.cmake) 4 | include(${CMAKE_CURRENT_LIST_DIR}/functions/qt_helpers.cmake) -------------------------------------------------------------------------------- /cmake/functions/target_options.cmake: -------------------------------------------------------------------------------- 1 | # @brief Enable pedantic warnings for a target 2 | # - This does not propagate to other targets 3 | function(target_pedantic_warnings TARGET_NAME) 4 | #[target_pedantic_warnings Enable pedantic warnings for a target 5 | # Set warning levels to about the same level for MSVC, GCC, and Clang 6 | if (MSVC) 7 | target_compile_options(${TARGET_NAME} PRIVATE /W4 /WX) 8 | else () 9 | target_compile_options(${TARGET_NAME} PRIVATE -Wall -Wextra -pedantic -Werror) 10 | endif () 11 | #] 12 | endfunction() 13 | 14 | # @brief Sets pedantic compiler options for all target 15 | # - In a more serious project, we would do that per target 16 | # - Setting it for all targets unfortunately affects 17 | # external libraries, which often lead to some warnings. 18 | macro(add_pedantic_warnings) 19 | #[target_pedantic_warnings Enable pedantic compiler options for all targets 20 | if (MSVC) 21 | add_compile_options(/W4 /WX) 22 | else () 23 | add_compile_options(-Wall -Wextra -pedantic -Werror) 24 | endif () 25 | #] 26 | endmacro() 27 | 28 | # @brief Enable compile options for MSVC only 29 | # - Adding special compile options to make your code work on MSVC 30 | # is unfortunately very common, so this pattern becomes useful. 31 | function(target_msvc_compile_options TARGET_NAME DEFINITION) 32 | if (MSVC) 33 | target_compile_options(${TARGET_NAME} PUBLIC ${DEFINITION}) 34 | endif () 35 | endfunction() 36 | 37 | # Enable exceptions for the target 38 | function(target_exception_options TARGET_NAME) 39 | # MSVC requires this flag if the code uses C++ exception handling 40 | target_msvc_compile_options(${TARGET_NAME} PRIVATE /EHsc) 41 | endfunction() 42 | 43 | # @brief Enable big object files for the target 44 | function(target_bigobj_options TARGET_NAME) 45 | # MSVC requires this flag if the file has a lot of code 46 | target_msvc_compile_options(${TARGET_NAME} PRIVATE /bigobj) 47 | endfunction() -------------------------------------------------------------------------------- /docs/algorithms-data-structures/algorithm/basic-algorithms.md: -------------------------------------------------------------------------------- 1 | # Basic Algorithms 2 | 3 | {{ all_code_snippets("snippets/algorithm/algorithms.cpp") }} 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /docs/algorithms-data-structures/algorithm/ranges.md: -------------------------------------------------------------------------------- 1 | # Ranges 2 | 3 | !!! note "Ranges" 4 | 5 | The [ranges library](https://en.cppreference.com/w/cpp/ranges) is an extension and generalization of the algorithms 6 | and iterator libraries that makes them more powerful by making them composable and less error-prone. 7 | 8 | All algorithms that take iterator pairs have overloads that accept ranges (e.g ranges::sort). 9 | 10 | The library creates and manipulates range views, lightweight objects that indirectly represent iterable sequences 11 | (ranges). Ranges are an abstraction on top of [begin, end) iterator pairs, e.g. ranges made by implicit conversion 12 | from containers. 13 | 14 | The ranges library was originally developed as the 15 | [range-v3 library](https://github.com/ericniebler/range-v3), and was finally merged to ISO C++ as of C++20. 16 | The range-v3 implementation is currently available on more compilers and platforms than the C++20 library. 17 | 18 | 19 | {{ code_snippet("snippets/algorithm/CMakeLists.txt", "ranges", "cmake") }} 20 | 21 |
22 | 23 | {{ all_code_snippets("snippets/algorithm/ranges.cpp") }} 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /docs/algorithms-data-structures/algorithm/searching.md: -------------------------------------------------------------------------------- 1 | # Searching 2 | 3 | {{ all_code_snippets("snippets/algorithm/searching.cpp") }} 4 | 5 | -------------------------------------------------------------------------------- /docs/algorithms-data-structures/algorithm/sorting.md: -------------------------------------------------------------------------------- 1 | # Sorting 2 | 3 | !!! hint 4 | 5 | The standard [algorithms](basic-algorithms.md) for sorting containers are `std::sort` and `std::stable_sort`. 6 | 7 | These snippets include extra functions describing how these tasks can be implemented with many other classic 8 | sorting algorithms. They are mostly relevant for people studying sorting algorithms for the first time. 9 | 10 | {{ all_code_snippets("snippets/algorithm/sorting.cpp") }} 11 | 12 | -------------------------------------------------------------------------------- /docs/algorithms-data-structures/data-structures/associative-containers.md: -------------------------------------------------------------------------------- 1 | # Associative Containers 2 | 3 | !!! note "Associative Containers" 4 | 5 | [Associative containers](https://en.cppreference.com/w/cpp/container) implement sorted data structures that can 6 | be quickly searched (O(log n) complexity. They are usually implemented as binary trees. 7 | 8 | - set: collection of unique keys, sorted by keys 9 | - map: collection of key-value pairs, sorted by keys, keys are unique 10 | - multiset: collection of keys, sorted by keys 11 | - multimap: collection of key-value pairs, sorted by keys 12 | 13 | [Unordered associative containers](https://en.cppreference.com/w/cpp/container) implement unsorted (hashed) data 14 | structures that can be quickly searched (O(1) amortized, O(n) worst-case complexity). They are usually implemented 15 | as hash tables. 16 | 17 | - unordered_set (C++11): collection of unique keys, hashed by keys 18 | - unordered_map (C++11): collection of key-value pairs, hashed by keys, keys are unique 19 | - unordered_multiset (C++11): collection of keys, hashed by keys 20 | - unordered_multimap (C++11): collection of key-value pairs, hashed by keys 21 | 22 | {{ all_code_snippets("snippets/data_structures/associative_containers.cpp") }} 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /docs/algorithms-data-structures/data-structures/bitset.md: -------------------------------------------------------------------------------- 1 | # Bitset 2 | 3 | !!! note "Bitset" 4 | 5 | The class template [bitset](https://en.cppreference.com/w/cpp/utility/bitset) represents a fixed-size sequence of 6 | N bits. Bitsets can be manipulated by standard logic operators and converted to and from strings and integers. 7 | 8 | {{ code_snippet("snippets/data_structures/CMakeLists.txt", "bitset", "cmake") }} 9 | 10 |
11 | 12 | {{ all_code_snippets("snippets/data_structures/bitset.cpp") }} 13 | 14 | -------------------------------------------------------------------------------- /docs/algorithms-data-structures/data-structures/build-script.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Build script 4 | nav_order: 1 5 | has_children: false 6 | parent: Data structures 7 | grand_parent: Algorithms / Data Structures 8 | has_toc: false 9 | --- 10 | # Build script 11 | 12 | ```cmake 13 | --8<-- "snippets/data_structures/CMakeLists.txt" 14 | ``` 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /docs/algorithms-data-structures/data-structures/memory-resources.md: -------------------------------------------------------------------------------- 1 | # Memory resources 2 | 3 | !!! note "Memory resources" 4 | 5 | The class std::pmr::memory_resource is an abstract interface to an unbounded set of classes encapsulating memory 6 | resources. The class template [std::pmr::polymorphic_allocator](https://en.cppreference.com/w/cpp/memory/polymorphic_allocator) 7 | is an `Allocator` which exhibits different allocation behavior depending upon the std::pmr::memory_resource from 8 | which it is constructed. This allows us to control how a given container allocates memory. 9 | 10 | Since memory_resource uses runtime polymorphism to manage allocations, different container instances 11 | with polymorphic_allocator as their static allocator type are interoperable, but can behave as if they had 12 | different allocator types. 13 | 14 | Not all compilers implement PMR yet, even though it's a C++17 feature. We need a CMake script such as 15 | [`FindPMR.cmake`](https://github.com/alandefreitas/moderncpp/blob/master/cmake/FindPMR.cmake) to identify if your 16 | compiler implements it. Another option is using [`__has_include`](https://en.cppreference.com/w/cpp/preprocessor/include) 17 | to identify if the appropriate headers are available. 18 | 19 | {{ code_snippet("snippets/data_structures/CMakeLists.txt", "pmr", "cmake") }} 20 | 21 |
22 | 23 | {{ all_code_snippets("snippets/data_structures/memory_resources.cpp") }} 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /docs/algorithms-data-structures/data-structures/sequence-containers.md: -------------------------------------------------------------------------------- 1 | # Sequence Containers 2 | 3 | !!! note "Sequence Containers" 4 | 5 | [Sequence containers](https://en.cppreference.com/w/cpp/container) implement data structures which can be 6 | accessed sequentially. 7 | 8 | - array (C++11): static contiguous array 9 | - vector: dynamic contiguous array 10 | - deque: double-ended queue 11 | - forward_list (C++11): singly-linked list 12 | - list: doubly-linked list 13 | 14 | {{ all_code_snippets("snippets/data_structures/sequence_containers.cpp") }} 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /docs/algorithms-data-structures/data-structures/span.md: -------------------------------------------------------------------------------- 1 | # Span 2 | 3 | !!! note "Span" 4 | 5 | The class template [`span`](https://en.cppreference.com/w/cpp/container/span) describes an object that can refer 6 | to a contiguous sequence of objects with the first element of the sequence at position zero. 7 | 8 | A span can either have a static extent, in which case the number of elements in the sequence is known at 9 | compile-time and encoded in the type, or a dynamic extent. 10 | 11 | {{ code_snippet("snippets/data_structures/CMakeLists.txt", "span", "cmake") }} 12 | 13 |
14 | 15 | {{ all_code_snippets("snippets/data_structures/span.cpp") }} 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /docs/algorithms-data-structures/data-structures/spatial-containers.md: -------------------------------------------------------------------------------- 1 | # Spatial Containers 2 | 3 | !!! note "Spatial Containers" 4 | 5 | Spatial container are an extension of sets and maps that allow us to order data according to multiple dimensions. 6 | This is particularly useful in games and graphical interfaces, where objects need to be mapped in space. 7 | The standard library does not include spatial containers so an external library needs to be used. 8 | 9 | {{ code_snippet("snippets/data_structures/CMakeLists.txt", "pareto", "cmake") }} 10 | 11 |
12 | 13 | {{ all_code_snippets("snippets/data_structures/spatial_containers.cpp") }} 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /docs/algorithms-data-structures/date-and-time/clock.md: -------------------------------------------------------------------------------- 1 | # Clock 2 | 3 | !!!note "Clock" 4 | 5 | A clock consists of a starting point (or epoch) and a tick rate. For example, a clock may have an epoch of 6 | January 1, 1970 and tick every second. C++ defines several clock types: 7 | 8 | - `system_clock` (C++11): wall clock time from the system-wide realtime clock 9 | - `steady_clock` (C++11): monotonic clock that will never be adjusted 10 | - `high_resolution_clock` (C++11): the clock with the shortest tick period available 11 | - `utc_clock` (C++20): Clock for Coordinated Universal Time (UTC) 12 | - `tai_clock` (C++20): Clock for International Atomic Time (TAI) 13 | - `gps_clock` (C++20): Clock for GPS time 14 | - `file_clock` (C++20): Clock used for file time 15 | - `local_t` (C++20): pseudo-clock representing local time 16 | 17 | C++ also inherits the C `clock` function, which returns the approximate processor time used by the process 18 | since the beginning of an implementation-defined era related to the program's execution. 19 | To convert result value to seconds divide it by CLOCKS_PER_SEC. The `clock` function: 20 | 21 | - The only method specified in the standard to measure CPU time 22 | - It's up to the user to keep track of the duration unit 23 | - It doesn't work well with threads 24 | - Ignores the time spent on `this_thread::sleep_for` 25 | 26 | {{ all_code_snippets("snippets/datetime/clock.cpp") }} 27 | 28 | -------------------------------------------------------------------------------- /docs/algorithms-data-structures/date-and-time/datetime.md: -------------------------------------------------------------------------------- 1 | # Datetime 2 | 3 | !!!note "Datetime" 4 | 5 | C++20 includes [date and time utilities](https://en.cppreference.com/w/cpp/chrono) in the chrono library. 6 | 7 | These utilities were originally developed as the [date](https://github.com/HowardHinnant/date) library, 8 | and were finally merged to ISO C++ as of C++20. 9 | 10 | date.h contains chrono extensions to deal with dates: 11 | - https://howardhinnant.github.io/date/date.html 12 | - https://howardhinnant.github.io/date/tz.html 13 | 14 | The date library implementation is currently available on more compilers and platforms than the C++20 library. 15 | 16 | {{ code_snippet("snippets/datetime/CMakeLists.txt", "datetime", "cmake") }} 17 | 18 |
19 | 20 | {{ all_code_snippets("snippets/datetime/datetime.cpp") }} 21 | 22 | -------------------------------------------------------------------------------- /docs/algorithms-data-structures/heterogeneous-types/any.md: -------------------------------------------------------------------------------- 1 | # Any 2 | 3 | !!! note "Any" 4 | 5 | The class [`std::any`](https://en.cppreference.com/w/cpp/utility/any) describes a type-safe container for single 6 | values of any copy constructible type. 7 | 8 | 1) An object of class `any` stores an instance of any type that satisfies the constructor requirements or is empty, 9 | and this is referred to as the state of the class any object. The stored instance is called the contained object. 10 | Two states are equivalent if they are either both empty or if both are not empty and if the contained objects 11 | are equivalent. 12 | 2) The non-member any_cast functions provide type-safe access to the contained object. Implementations are 13 | encouraged to avoid dynamic allocations for small objects, but such an optimization may only be applied to 14 | types for which `std::is_nothrow_move_constructible` returns `true`. 15 | 16 | {{ all_code_snippets("snippets/heterogeneous_types/any.cpp") }} 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /docs/algorithms-data-structures/heterogeneous-types/optional.md: -------------------------------------------------------------------------------- 1 | # Optional 2 | 3 | !!! note "Optional" 4 | 5 | The class template [`std::optional`](https://en.cppreference.com/w/cpp/utility/optional) manages an optional 6 | contained value, i.e. a value that may or may not be present. 7 | 8 | A common use case for optional is the return value of a function that may fail. As opposed to other approaches, 9 | such as std::pair, optional handles expensive-to-construct objects well and is more readable, as the intent 10 | is expressed explicitly. 11 | 12 | Any instance of `optional` at any given point in time either contains a value or does not contain a value. 13 | 14 | {{ all_code_snippets("snippets/heterogeneous_types/optional.cpp") }} 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /docs/algorithms-data-structures/heterogeneous-types/tuples.md: -------------------------------------------------------------------------------- 1 | # Tuples 2 | 3 | !!! note "Tuples" 4 | 5 | Class template [`std::tuple`](https://en.cppreference.com/w/cpp/utility/tuple) is a fixed-size collection of 6 | heterogeneous values. It is a generalization of std::pair for more than 2 values. 7 | 8 | {{ all_code_snippets("snippets/heterogeneous_types/tuples.cpp") }} 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /docs/algorithms-data-structures/heterogeneous-types/variant.md: -------------------------------------------------------------------------------- 1 | # Variant 2 | 3 | !!! note "Variant" 4 | 5 | The class template [`std::variant`](https://en.cppreference.com/w/cpp/utility/variant) (C++17) represents a 6 | type-safe union. An instance of `std::variant` at any given time either holds a value of one of its alternative 7 | types, or in the case of error - no value. 8 | 9 | If we define a variant `v` including lots of types, including booleans and lists, this would be somewhat similar to: 10 | 11 | - PHP: `$v = 3.14;` // see https://bit.ly/3cVuJvb 12 | - Python: `v = 3.14;` 13 | - Javascript: `var v = 3.14;` 14 | 15 | As with unions, if a variant holds a value of some object type `T`, the object representation of `T` is allocated 16 | directly within the object representation of the variant itself. Variant is not allowed to allocate additional 17 | (dynamic) memory. 18 | 19 | A variant is not permitted to hold references, arrays, or the type `void`. Empty variants are also ill-formed 20 | (std::variant can be used instead). 21 | 22 | A variant is permitted to hold the same type more than once, and to hold differently cv-qualified versions of the same type. 23 | 24 | Consistent with the behavior of unions during aggregate initialization, a default-constructed variant holds a value 25 | of its first alternative, unless that alternative is not default-constructible 26 | (in which case the variant is not default-constructible either). The helper class `std::monostate` can be used 27 | to make such variants default-constructible. 28 | 29 | {{ all_code_snippets("snippets/heterogeneous_types/variant.cpp") }} 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /docs/algorithms-data-structures/random/pcg.md: -------------------------------------------------------------------------------- 1 | # PCG 2 | 3 | !!!note "PCG" 4 | 5 | The [PCG library](https://www.pcg-random.org/) provides a number of better random number generators. 6 | 7 | The library has a interface that resembles standard C++ number generators with generators that: 8 | 9 | - Do not fail statistical tests for randomness 10 | - Ensure unpredictability and safety 11 | - Are fast and don't require large amounts of memory 12 | - Provide useful features such as "jump ahead" 13 | 14 | {{ code_snippet("snippets/random/CMakeLists.txt", "pcg", "cmake") }} 15 | 16 |
17 | 18 | {{ all_code_snippets("snippets/random/pcg.cpp") }} 19 | 20 | -------------------------------------------------------------------------------- /docs/algorithms-data-structures/random/random.md: -------------------------------------------------------------------------------- 1 | # Random 2 | 3 | !!!note "Random" 4 | 5 | The [random number library](https://en.cppreference.com/w/cpp/numeric/random) provides classes that generate random 6 | and pseudo-random numbers. These classes include: 7 | 8 | - Uniform random bit generators (URBGs), which include both random number engines, which are pseudo-random number 9 | generators that generate integer sequences with a uniform distribution, and true random number generators if 10 | available; 11 | - Random number distributions (e.g. uniform, normal, or poisson distributions) which convert the output of URBGs 12 | into various statistical distributions 13 | 14 | URBGs and distributions are designed to be used together to produce random values. All of the random number engines 15 | may be specifically seeded, serialized, and deserialized for use with repeatable simulators. 16 | 17 | {{ all_code_snippets("snippets/random/random.cpp") }} 18 | 19 | -------------------------------------------------------------------------------- /docs/algorithms-data-structures/templates/concepts.md: -------------------------------------------------------------------------------- 1 | # Concepts 2 | 3 | !!!note "Concepts" 4 | 5 | Concepts (C++20) define named sets of template requirements. 6 | 7 | Class templates, function templates, and non-template functions (typically members of class templates) may be 8 | associated with a template constraint, which specifies the requirements on template arguments, which can be used 9 | to select the most appropriate function overloads and template specializations. 10 | 11 | Each concept is a predicate, evaluated at compile time, and becomes a part of the interface of a template where 12 | it is used as a constraint: 13 | 14 | {{ code_snippet("snippets/templates/CMakeLists.txt", "concepts", "cmake") }} 15 | 16 |
17 | 18 | {{ all_code_snippets("snippets/templates/concepts.cpp") }} 19 | 20 | -------------------------------------------------------------------------------- /docs/algorithms-data-structures/templates/metaprogramming.md: -------------------------------------------------------------------------------- 1 | # Metaprogramming 2 | 3 | !!!note "Metaprogramming" 4 | 5 | [Template metaprogramming](https://en.cppreference.com/w/cpp/language/template_metaprogramming) is a family of 6 | techniques to create new types and compute values at compile time. C++ templates are Turing complete if there are 7 | no limits to the amount of recursive instantiations and the number of allowed state variables. 8 | 9 | Erwin Unruh was the first to demonstrate template metaprogramming at a committee meeting by instructing the 10 | compiler to print out prime numbers in error messages. The standard recommends an implementation support at least 11 | 1024 levels of recursive instantiation, and infinite recursion in template instantiations is undefined behavior. 12 | 13 | {{ all_code_snippets("snippets/templates/metaprogramming.cpp") }} 14 | -------------------------------------------------------------------------------- /docs/algorithms-data-structures/templates/sfinae.md: -------------------------------------------------------------------------------- 1 | # Substitution Failure Is Not An Error 2 | 3 | !!!note "Substitution Failure Is Not An Error" 4 | 5 | This [rule](https://en.cppreference.com/w/cpp/language/sfinae) applies during overload resolution of function 6 | templates: When substituting the explicitly specified or deduced type for the template parameter fails, the 7 | specialization is discarded from the overload set instead of causing a compile error. 8 | 9 | Because the attempted substitution is not an error, SFINAE is used as alternative to concepts in compilers 10 | that do not support C++20. The technique specifies the template parameters is such a way that only the intended 11 | template types are instanciated. 12 | 13 | {{ all_code_snippets("snippets/templates/sfinae.cpp") }} 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /docs/algorithms-data-structures/templates/template-aliases.md: -------------------------------------------------------------------------------- 1 | # Template Aliases 2 | 3 | !!!note "Template Aliases" 4 | 5 | A type alias is a name that refers to a previously defined type. Alias template is a name that refers to a family 6 | of types. 7 | 8 | {{ all_code_snippets("snippets/templates/template_alias.cpp") }} 9 | 10 | -------------------------------------------------------------------------------- /docs/algorithms-data-structures/templates/template-parameters.md: -------------------------------------------------------------------------------- 1 | # Template Parameters 2 | 3 | !!!note "Template Parameters" 4 | 5 | A template defines a family of functions and classes. A template by itself is not a type, or a function, or 6 | any other entity. No code is generated from a source file that contains only template definitions. 7 | 8 | In order for any code to appear, a template must be instantiated: the template arguments must be determined so 9 | that the compiler can generate an actual function (or class, from a class template). 10 | 11 | Templates allow us to reuse the logic of algorithms for different data types. Without templates, our alternative 12 | for generic algorithms would be type erasing types. 13 | 14 | {{ all_code_snippets("snippets/templates/template_functions.cpp") }} 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /docs/basic-syntax/basic-data-types/aggregate-initialization.md: -------------------------------------------------------------------------------- 1 | # Aggregate initialization 2 | 3 | !!!note "Aggregate initialization" 4 | 5 | Aggregate initialization initializes aggregate types. 6 | 7 | {{ code_snippet("snippets/basic_types/CMakeLists.txt", "aggregate_initialization", "cmake") }} 8 | 9 |
10 | 11 | {{ all_code_snippets("snippets/basic_types/aggregate_initialization.cpp") }} 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /docs/basic-syntax/basic-data-types/arrays.md: -------------------------------------------------------------------------------- 1 | # Arrays 2 | 3 | !!!note "Arrays" 4 | 5 | In modern C++, `std::array` is a safe container that encapsulates fixed size arrays. 6 | 7 | {{ all_code_snippets("snippets/basic_types/arrays.cpp") }} 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/basic-syntax/basic-data-types/build-script.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Build script 4 | nav_order: 1 5 | has_children: false 6 | parent: Basic Data Types 7 | grand_parent: Basic Syntax 8 | has_toc: false 9 | --- 10 | # Build script 11 | 12 | ```cmake 13 | --8<-- "snippets/basic_types/CMakeLists.txt" 14 | ``` 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /docs/basic-syntax/basic-data-types/move.md: -------------------------------------------------------------------------------- 1 | # Move 2 | 3 | !!!note "Move" 4 | 5 | `std::move` is used to indicate that an object t may be "moved from", i.e. allowing the efficient transfer 6 | of resources from one object to another. 7 | 8 | {{ all_code_snippets("snippets/basic_types/move.cpp") }} 9 | 10 | -------------------------------------------------------------------------------- /docs/basic-syntax/basic-data-types/raw-arrays.md: -------------------------------------------------------------------------------- 1 | # Raw arrays 2 | 3 | !!!note "Raw arrays" 4 | 5 | An array is a sequence of objects of the same type that occupy a contiguous area of memory. 6 | 7 | Traditional C-style arrays, or Raw Arrays, are the source of many bugs, but are still common, especially in older 8 | code bases. 9 | 10 | In modern C++, we strongly recommend using `std::vector` or `std::array` instead of C-style arrays. 11 | 12 | {{ all_code_snippets("snippets/basic_types/raw_arrays.cpp") }} 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /docs/basic-syntax/basic-data-types/strings.md: -------------------------------------------------------------------------------- 1 | # Strings 2 | 3 | !!!note "Strings" 4 | 5 | `std::string` is a safe container for `char` strings of dynamic size. 6 | 7 | It automatically coordinates the process of allocating and deallocating memory for the elements as required. 8 | 9 | {{ all_code_snippets("snippets/basic_types/strings.cpp") }} 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /docs/basic-syntax/basic-data-types/structured-binding.md: -------------------------------------------------------------------------------- 1 | # Structured binding 2 | 3 | !!!note "Structured binding" 4 | 5 | Structured binding binds the specified names to subobjects or elements of the initializer. 6 | 7 | Like a reference, a structured binding is an alias to an existing object. 8 | 9 | {{ code_snippet("snippets/basic_types/CMakeLists.txt", "structured_binding", "cmake") }} 10 | 11 |
12 | 13 | {{ all_code_snippets("snippets/basic_types/structured_binding.cpp") }} 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /docs/basic-syntax/basic-data-types/vectors.md: -------------------------------------------------------------------------------- 1 | # Vectors 2 | 3 | !!!note "Vectors" 4 | 5 | `std::vector` is a safe container for arrays of dynamic size. 6 | 7 | It automatically coordinates the process of allocating and deallocating memory for the elements as required. 8 | 9 | {{ all_code_snippets("snippets/basic_types/vectors.cpp") }} 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /docs/basic-syntax/control-flow/conditional.md: -------------------------------------------------------------------------------- 1 | # Conditional 2 | 3 | !!!note "Conditional control flow" 4 | 5 | Conditional expressions and conditional constructs are features of a programming language which perform different 6 | computations or actions depending on whether a programmer-specified boolean condition evaluates to true or false 7 | 8 | {{ all_code_snippets("snippets/control_flow/conditional.cpp") }} 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /docs/basic-syntax/control-flow/loops.md: -------------------------------------------------------------------------------- 1 | # Loops 2 | 3 | !!!note "Loops" 4 | 5 | A loop is a sequence of statements which is specified once but which may be carried out several times in succession. 6 | The code "inside" the loop (the body of the loop) is obeyed a specified number of times, or once for each of a 7 | collection of items, or until some condition is met, or indefinitely. 8 | 9 | {{ all_code_snippets("snippets/control_flow/loops.cpp") }} 10 | -------------------------------------------------------------------------------- /docs/basic-syntax/control-flow/scopes.md: -------------------------------------------------------------------------------- 1 | # Scopes 2 | 3 | !!!note "Scopes" 4 | 5 | The context in which a name is visible is called its scope. For example, if you declare a variable x within a 6 | function, x is only visible within that function body. It has local scope. 7 | 8 | {{ all_code_snippets("snippets/control_flow/scopes.cpp") }} 9 | -------------------------------------------------------------------------------- /docs/basic-syntax/control-flow/sequential.md: -------------------------------------------------------------------------------- 1 | # Sequential 2 | 3 | !!!note "Sequential control flow" 4 | 5 | In structured programming, the ordered sequencing of successive commands is considered one of the basic control 6 | structures, which is used as a building block for programs alongside iteration, recursion and conditionals. 7 | 8 | 9 | {{ all_code_snippets("snippets/control_flow/sequential.cpp") }} 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /docs/basic-syntax/data-types/auto.md: -------------------------------------------------------------------------------- 1 | # Type deduction 2 | 3 | !!!note "Type deduction" 4 | 5 | The `auto` keyword declares a variable whose type is deduced from the initialization expression in its declaration. 6 | 7 | Auto for fundamental data types: 8 | 9 | - Avoid using `auto` for fundamental data types! 10 | - This is a bad place for `auto` 11 | - It does not avoid a long type name 12 | - It creates ambiguity 13 | - `auto x = 87` could *semantically* be any number type 14 | - This is somewhat equivalent to: 15 | - swift: `var dont_do_that = 87` 16 | - rust: `let mut dont_do_that = 87` 17 | 18 | On the other hand, `auto` is very useful in generic functions where there types are not ambiguous. 19 | 20 | {{ all_code_snippets("snippets/data_types/auto.cpp") }} 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /docs/basic-syntax/data-types/constants.md: -------------------------------------------------------------------------------- 1 | # Constants 2 | 3 | !!!note "constants" 4 | 5 | When you do not want others (or yourself) to override existing variable values, use the `const` keyword. This will 6 | declare the variable as "constant", which means unchangeable and read-only. 7 | 8 | {{ all_code_snippets("snippets/data_types/constants.cpp") }} 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /docs/basic-syntax/data-types/fundamental-data-types.md: -------------------------------------------------------------------------------- 1 | # Fundamental Data Types 2 | 3 | !!!note "Fundamental Data Types" 4 | 5 | A fundamental or primitive type is a data type where the values that it can represent have a very simple nature 6 | (a number, a character or a truth-value); the primitive types are the most basic building blocks for any 7 | programming language and are the base for more complex data types. 8 | 9 | {{ all_code_snippets("snippets/data_types/data_types.cpp") }} 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /docs/basic-syntax/data-types/operators.md: -------------------------------------------------------------------------------- 1 | # Operators 2 | 3 | !!!note "Operators" 4 | 5 | Operators are symbols that perform operations on variables and values. For example, `+` is an operator used for 6 | addition, while `-` is an operator used for subtraction. 7 | 8 | {{ all_code_snippets("snippets/data_types/operators.cpp") }} 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /docs/basic-syntax/files/file-streams.md: -------------------------------------------------------------------------------- 1 | # File streams 2 | 3 | !!!note "File streams" 4 | 5 | C++ provides file streams to perform output and input of characters to/from files. These classes are derived 6 | directly or indirectly from the classes std::istream and std::ostream. 7 | 8 | We have already used objects whose types were these classes: `std::cin` is an object of class `std::istream` and 9 | `std::cout` is an object of class ostream. 10 | 11 | We can use our file streams the same way we are already used to use `std::cin` and `std::cout`, with the only 12 | difference that we have to associate these streams with physical files.: 13 | 14 | {{ all_code_snippets("snippets/files/files.cpp") }} 15 | 16 | 17 | -------------------------------------------------------------------------------- /docs/basic-syntax/files/filesystem.md: -------------------------------------------------------------------------------- 1 | # Filesystem 2 | 3 | !!!note "Filesystem" 4 | 5 | The Filesystem library provides facilities for performing operations on file systems and their components, such as 6 | paths, regular files, and directories. 7 | 8 | The filesystem library was originally developed as 9 | [boost.filesystem](https://www.boost.org/doc/libs/1_78_0/libs/filesystem/doc/index.htm), was published as the 10 | technical specification ISO/IEC TS 18822:2015, and finally merged to ISO C++ as of C++17. 11 | 12 | The boost implementation is currently available on more compilers and platforms than the C++17 library. 13 | 14 | {{ code_snippet("snippets/files/CMakeLists.txt", "find_filesystem", "cmake") }} 15 | 16 |
17 | 18 | {{ code_snippet("snippets/files/CMakeLists.txt", "find_boost_filesystem", "cmake") }} 19 | 20 |
21 | 22 | {{ code_snippet("snippets/files/CMakeLists.txt", "link_filesystem", "cmake") }} 23 | 24 |
25 | 26 | {{ all_code_snippets("snippets/files/filesystem.cpp") }} 27 | 28 | 29 | -------------------------------------------------------------------------------- /docs/basic-syntax/functions/build-script.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Build script 4 | nav_order: 1 5 | has_children: false 6 | parent: Functions 7 | grand_parent: Basic Syntax 8 | has_toc: false 9 | --- 10 | # Build script 11 | 12 | ```cmake 13 | --8<-- "snippets/functions/CMakeLists.txt" 14 | ``` 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /docs/basic-syntax/functions/function.md: -------------------------------------------------------------------------------- 1 | # Functions 2 | 3 | !!! warning "About functions" 4 | 5 | These snippets are about the syntax for defining functions. They are *not* about how to achieve tasks with these 6 | functions. The tasks are just placeholders and the C++ STL already provides much better alternatives for most of 7 | these [algorithms](../../algorithms-data-structures/algorithm/basic-algorithms.md). 8 | 9 | {{ all_code_snippets("snippets/functions/functions.cpp") }} 10 | -------------------------------------------------------------------------------- /docs/basic-syntax/functions/lambda.md: -------------------------------------------------------------------------------- 1 | # Lambda Functions 2 | 3 | !!!note "Lambda functions" 4 | 5 | A lambda is a convenient way of defining an anonymous function object right at the location where it's invoked. 6 | 7 | Typically lambdas are used to encapsulate a few lines of code that are passed to algorithms to customize their 8 | behavior. 9 | 10 | {{ all_code_snippets("snippets/functions/lambda.cpp") }} 11 | -------------------------------------------------------------------------------- /docs/basic-syntax/input-output/format.md: -------------------------------------------------------------------------------- 1 | # Format 2 | 3 | !!! info "About `fmt`/`format`" 4 | 5 | - fmt/format has been accepted into C++20 6 | - It has the best of `printf` and `cout` 7 | - Many compilers don't implement it yet 8 | - We still depend on `` 9 | 10 | {{ code_snippet("snippets/input_output/CMakeLists.txt", "fmt", "cmake") }} 11 | 12 |
13 | 14 | {{ all_code_snippets("snippets/input_output/format.cpp") }} 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /docs/basic-syntax/input-output/hello-world.md: -------------------------------------------------------------------------------- 1 | # Hello World 2 | 3 | {{ code_snippet("snippets/input_output/hello_world.cpp", "hello", "cpp") }} 4 | 5 | {{ code_snippet("snippets/input_output/CMakeLists.txt", "hello_world", "cmake") }} 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /docs/basic-syntax/input-output/input.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Input 4 | nav_order: 3 5 | has_children: false 6 | parent: Input / Output 7 | grand_parent: Basic Syntax 8 | has_toc: false 9 | --- 10 | # Input 11 | 12 | {{ all_code_snippets("snippets/input_output/cin.cpp") }} 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /docs/basic-syntax/pointers/address-operator.md: -------------------------------------------------------------------------------- 1 | # Address Operator 2 | 3 | !!!note "Address Operator" 4 | 5 | An address-of operator is a mechanism within C++ that returns the memory address of a variable. These addresses 6 | returned by the address-of operator are known as pointers, because they "point" to the variable in memory. 7 | 8 | {{ all_code_snippets("snippets/pointers/address_operator.cpp") }} 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /docs/basic-syntax/pointers/build-script.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Build script 4 | nav_order: 1 5 | has_children: false 6 | parent: Pointers 7 | grand_parent: Basic Syntax 8 | has_toc: false 9 | --- 10 | # Build script 11 | 12 | ```cmake 13 | --8<-- "snippets/pointers/CMakeLists.txt" 14 | ``` 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /docs/basic-syntax/pointers/raw-pointers.md: -------------------------------------------------------------------------------- 1 | # Raw pointers 2 | 3 | !!!note "Raw pointers" 4 | 5 | A pointer is a type of variable. It stores the address of an object in memory, and is used to access that object. 6 | A raw pointer is a pointer whose lifetime isn't controlled by an encapsulating object, such as a smart pointer. 7 | 8 | Raw pointers might be dangerous. Try to avoid them. 9 | 10 | {{ all_code_snippets("snippets/pointers/raw_pointers.cpp") }} 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/basic-syntax/pointers/references.md: -------------------------------------------------------------------------------- 1 | # References 2 | 3 | !!!note "References" 4 | 5 | - They solve some problems with raw pointers 6 | - Once initialized, a reference cannot be changed. This makes them less dangerous. 7 | - Instead of "pointing" to an address, a reference only "refers" to a fixed address / variable 8 | 9 | {{ all_code_snippets("snippets/pointers/references.cpp") }} 10 | 11 | -------------------------------------------------------------------------------- /docs/basic-syntax/pointers/smart-pointers.md: -------------------------------------------------------------------------------- 1 | # Smart pointers 2 | 3 | !!!note "Smart pointers" 4 | 5 | Use smart pointers instead of raw pointer whenever possible: 6 | 7 | - But you can't do it without understanding raw pointers 8 | - Recur to raw *non-owning* pointers if they are needed 9 | 10 | In general, use: 11 | 12 | 1) No pointers at all 13 | 14 | 2) Raw non-owning pointers or references if they are needed 15 | 16 | 3) Smart pointers IF owning pointers can not be averted 17 | 18 | 4) Owning raw pointers if you know exactly what you are doing 19 | and need them (e.g. interfacing with C code). 20 | 21 | There are 2 important types of smart pointers: 22 | 23 | - Unique pointer: 24 | - Only one pointer can point to an address 25 | - Deletes data automatically when the pointer is destroyed 26 | - Shared pointer: 27 | - More than one pointer can point to the same address 28 | - Deletes data automatically when the last pointer is destroyed 29 | - More expensive than unique pointers 30 | 31 | {{ all_code_snippets("snippets/pointers/smart_pointers.cpp") }} 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /docs/cmake-functions/project-flags.md: -------------------------------------------------------------------------------- 1 | # Project Flags 2 | 3 | {{ all_code_snippets("cmake/functions/project_flags.cmake", "cmake") }} 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /docs/cmake-functions/qt-helpers.md: -------------------------------------------------------------------------------- 1 | # Qt Helpers 2 | 3 | {{ all_code_snippets("cmake/functions/qt_helpers.cmake", "cmake") }} 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /docs/cmake-functions/sanitizers.md: -------------------------------------------------------------------------------- 1 | # Sanitizers 2 | 3 | {{ all_code_snippets("cmake/functions/sanitizers.cmake", "cmake") }} 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /docs/cmake-functions/target-options.md: -------------------------------------------------------------------------------- 1 | # Target Options 2 | 3 | {{ all_code_snippets("cmake/functions/target_options.cmake", "cmake") }} 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /docs/contributors.md: -------------------------------------------------------------------------------- 1 | # Contributors 2 | 3 | 4 | 5 | 6 | 13 | 20 |
7 | 8 | alandefreitas 9 |
10 | Alan De Freitas 11 |
12 |
14 | 15 | unnamedk 16 |
17 | João Vitor Vieira 18 |
19 |
21 | 22 | 23 | ## Discussions 24 | 25 | Discussions are concentrated on our GitHub [discussions](https://github.com/alandefreitas/moderncpp/discussions) page. 26 | Don't refrain from asking questions and proposing ideas. 27 | 28 | If you are a programmer with good ideas, please [share](https://github.com/alandefreitas/moderncpp/discussions/new) 29 | these ideas with us. 30 | 31 | Academic collaboration is more than welcome. 32 | 33 | ## Contributing 34 | 35 | Feel free to contribute with new snippets to this repository. For complex features and changes, 36 | consider [getting feedback](https://github.com/alandefreitas/moderncpp/discussions/new) from the community first. 37 | 38 | There are many ways in which you can contribute to this library: 39 | 40 | * Testing the library in new environments 41 | * Contributing with interesting snippets 42 | * Finding problems in the documentation 43 | * Finding bugs in general 44 | * Whatever idea seems interesting to you 45 | 46 | The only thing we ask you is to make sure your contribution is not destructive. Some contributions in which we are not 47 | interested are: 48 | 49 | * "I don't like this optional feature so I removed/deprecated it" 50 | * "I removed this feature to support older versions of C++" but have not provided an equivalent alternative. This 51 | repository is focused on Modern C++. 52 | * "I removed this feature, so I don't have to install/update ______" but have not provided an equivalent alternative 53 | * "I'm creating this high-cost promise that we'll support ________ forever" but I'm not sticking around to keep that 54 | promise 55 | 56 | In doubt, please open a [discussion](https://github.com/alandefreitas/moderncpp/discussions) first. 57 | 58 |
59 | 60 | ## Guidelines 61 | 62 | If contributing with code, please leave the pedantic warnings ON. You can use the helper CMake options 63 | `-DBUILD_WITH_PEDANTIC_WARNINGS=ON`: 64 | 65 | ![CLion Settings with Pedantic Mode](img/pedantic_clion.png) 66 | 67 | -------------------------------------------------------------------------------- /docs/guis/imgui.md: -------------------------------------------------------------------------------- 1 | # ImGUI 2 | 3 | {{ all_code_snippets("snippets/gui/imgui/CMakeLists.txt", "cmake") }} 4 | 5 |
6 | 7 | {{ all_code_snippets("snippets/gui/imgui/imgui_hello.cpp") }} 8 | 9 | -------------------------------------------------------------------------------- /docs/guis/opengl-glfw.md: -------------------------------------------------------------------------------- 1 | # SDL 2 | 3 | {{ all_code_snippets("snippets/gui/opengl/glfw/CMakeLists.txt", "cmake") }} 4 | 5 |
6 | 7 | {{ all_code_snippets("snippets/gui/opengl/glfw/opengl_hello.cpp") }} 8 | 9 | 10 | -------------------------------------------------------------------------------- /docs/guis/opengl-sdl.md: -------------------------------------------------------------------------------- 1 | # SDL 2 | 3 | {{ all_code_snippets("snippets/gui/opengl/sdl/CMakeLists.txt", "cmake") }} 4 | 5 |
6 | 7 | {{ all_code_snippets("snippets/gui/opengl/sdl/sdl_hello.cpp") }} 8 | -------------------------------------------------------------------------------- /docs/guis/qt.md: -------------------------------------------------------------------------------- 1 | # Qt 2 | 3 | {{ all_code_snippets("snippets/gui/qt/CMakeLists.txt", "cmake") }} 4 | 5 |
6 | 7 | {{ all_code_snippets("snippets/gui/qt/qt_hello.cpp") }} 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /docs/guis/system-tray.md: -------------------------------------------------------------------------------- 1 | # System tray 2 | 3 | {{ all_code_snippets("snippets/gui/tray/CMakeLists.txt", "cmake") }} 4 | 5 |
6 | 7 | {{ all_code_snippets("snippets/gui/tray/tray_hello.cpp") }} 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /docs/guis/webview.md: -------------------------------------------------------------------------------- 1 | # Webview 2 | 3 | {{ all_code_snippets("snippets/gui/webview/CMakeLists.txt", "cmake") }} 4 | 5 |
6 | 7 | {{ all_code_snippets("snippets/gui/webview/webview_hello.cpp") }} 8 | 9 | -------------------------------------------------------------------------------- /docs/img/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alandefreitas/moderncpp/8972b3f12b2f98944b78337a99abfac26ff1a722/docs/img/banner.png -------------------------------------------------------------------------------- /docs/img/banner.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alandefreitas/moderncpp/8972b3f12b2f98944b78337a99abfac26ff1a722/docs/img/banner.xcf -------------------------------------------------------------------------------- /docs/img/hello_cling.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alandefreitas/moderncpp/8972b3f12b2f98944b78337a99abfac26ff1a722/docs/img/hello_cling.png -------------------------------------------------------------------------------- /docs/img/hello_emscripten.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alandefreitas/moderncpp/8972b3f12b2f98944b78337a99abfac26ff1a722/docs/img/hello_emscripten.png -------------------------------------------------------------------------------- /docs/img/pedantic_clion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alandefreitas/moderncpp/8972b3f12b2f98944b78337a99abfac26ff1a722/docs/img/pedantic_clion.png -------------------------------------------------------------------------------- /docs/img/set_compiler.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alandefreitas/moderncpp/8972b3f12b2f98944b78337a99abfac26ff1a722/docs/img/set_compiler.png -------------------------------------------------------------------------------- /docs/installing-cpp/cling.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Interpreter / Cling 4 | nav_order: 5 5 | has_children: false 6 | parent: Installing C++20 7 | has_toc: false 8 | --- 9 | # Interpreter / Cling 10 | 11 | If you are using C++ for scientific computing or learning C++, it's often useful to have a C++ interpreter for short experiments. 12 | 13 | You can install Cling from most package managers for [Linux](https://pkgs.org/download/cling) or [Mac OS](https://formulae.brew.sh/formula/cling). You can also follow the [instructions](https://root.cern/cling/cling_build_instructions/) on their website to download the binaries or build it from source. 14 | 15 | Although you can use `cling` directly, it is much more convenient to use the interpreter as a Jupyter notebook kernel. You can follow [these instructions](https://jupyter.org/install.html) to install Jupyter Lab, and [these instructions](https://xeus-cling.readthedocs.io/en/latest/installation.html) to install the `xeus-cling` kernel. 16 | 17 | This creates a beautiful environment for playing with C++ interactively: 18 | 19 | ![](../img/hello_cling.png) 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /docs/installing-cpp/cmake.md: -------------------------------------------------------------------------------- 1 | ## CMake 2 | 3 | CMake is the most common build system for C++. Instead of using the compiler directly, CMake controls the compilation 4 | process through platform independent configuration files. 5 | 6 | ## Install CMake 7 | 8 | CMake can be downloaded from [cmake.org](https://cmake.org/) or from a package manager: 9 | 10 | === "apt-get" 11 | 12 | ```console 13 | sudo apt-get -y install cmake 14 | ``` 15 | 16 | === "Homebrew" 17 | 18 | ```console 19 | brew install cmake 20 | ``` 21 | 22 | ## Configuration files 23 | 24 | There should be a file named `CMakeLists.txt` in the root directory of your project. A starting point is: 25 | 26 | ```cmake 27 | cmake_minimum_required(VERSION 3.10) 28 | 29 | # set the project name 30 | project(my_project_name) 31 | 32 | # add the executable 33 | add_executable(my_project_name main.cpp) 34 | ``` 35 | 36 | ## Building with CMake 37 | 38 | Create a build directory: 39 | 40 | ```bash 41 | mkdir build 42 | ``` 43 | 44 | Navigate to the build directory and run CMake: 45 | 46 | ```bash 47 | cd build 48 | cmake .. 49 | ``` 50 | 51 | This will configure the project and generate a native build system scripts. 52 | 53 | Then call that build system to actually compile/link the project: 54 | 55 | ```bash 56 | cmake --build . 57 | ``` 58 | 59 | The executable file must have been generated. Note how CMake abstracts the differences between compilers and platforms. 60 | 61 | ## Configure compiler 62 | 63 | Set the variable `CMAKE_CXX_COMPILER` from the command line to let CMake know what compiler to use: 64 | 65 | ```bash 66 | cmake -D CMAKE_C_COMPILER="/path/to/your/c/compiler/executable" -D CMAKE_CXX_COMPILER "/path/to/your/cpp/compiler/executable" /path/to/directory/containing/CMakeLists.txt 67 | ``` 68 | 69 | If you want this to be your default compiler, you can set the `CXX` environment variable: 70 | 71 | ```bash 72 | export CXX=/path/to/your/cpp/compiler/executable 73 | ``` 74 | 75 | If you want to use this compiler in a single project, always run CMake with these options: 76 | 77 | ```bash 78 | -DCMAKE_C_COMPILER=/path/to/your/c/compiler/executable -DCMAKE_CXX_COMPILER=/path/to/your/cpp/compiler/executable 79 | ``` 80 | 81 | Or tell your IDE to pass these options to CMake: 82 | 83 | ![](../img/set_compiler.png) 84 | 85 | -------------------------------------------------------------------------------- /docs/installing-cpp/compiler.md: -------------------------------------------------------------------------------- 1 | ## Windows + MSVC 2 | 3 | Update your [Visual Studio](https://visualstudio.microsoft.com) Compiler. The most recent version of Visual Studio 4 | should include C++20. 5 | 6 | ## Linux + GCC 7 | 8 | Update GCC: 9 | 10 | ```bash 11 | # Repository 12 | sudo apt install build-essential 13 | sudo add-apt-repository ppa:ubuntu-toolchain-r/test 14 | sudo apt-get update 15 | # Install 16 | sudo apt install gcc-11 17 | sudo apt install g++-11 18 | # Install as compiler alternative 19 | sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-11 11 20 | sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-11 11 21 | ``` 22 | 23 | Set your default compiler with: 24 | 25 | ```bash 26 | update-alternatives --config g++ 27 | ``` 28 | 29 | ## Mac OS + Clang 30 | 31 | Download a [recent version](https://releases.llvm.org/download.html) of Clang: 32 | 33 | ```bash 34 | curl --output clang.tar.xz -L https://github.com/llvm/llvm-project/releases/download/llvmorg-13.0.1/clang+llvm-13.0.1-x86_64-apple-darwin.tar.xz 35 | mkdir clang 36 | tar -xvJf clang.tar.xz -C clang 37 | ``` 38 | 39 | Copy these files to `usr/local/`: 40 | 41 | ```bash 42 | cd clang/clang+llvm-13.0.1-x86_64-apple-darwin 43 | sudo cp -R * /usr/local/ 44 | ``` 45 | 46 | -------------------------------------------------------------------------------- /docs/installing-cpp/ides.md: -------------------------------------------------------------------------------- 1 | # IDEs 2 | 3 | These are the most common IDEs and text editors [most commonly used](http://blog.davidecoppola.com/2018/02/market-share-most-used-c-cpp-ides-in-2018-statistics-estimates/) for C++ programming: 4 | 5 | | IDE or Text Editor | Users | Notes | 6 | |--------------------|-------|-------------------| 7 | | Visual Studio | 28% | Windows | 8 | | Vim | 17% | (Text Editor) | 9 | | Qt Creator | 12% | Best for Qt Users | 10 | | Visual Studio Code | 10% | | 11 | | CLion | 9% | | 12 | | Emacs | 7% | (Text Editor) | 13 | | Xcode | 4% | Mac OS | 14 | | Eclipse | 4% | | 15 | | Others | 9% | | 16 | 17 | !!! warning 18 | These numbers are constantly changing. 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /docs/installing-cpp/webassembly.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: WebAssembly / Emscripten 4 | nav_order: 4 5 | has_children: false 6 | parent: Installing C++20 7 | has_toc: false 8 | --- 9 | # WebAssembly / Emscripten 10 | 11 | If you are programming for the web, a common option for C++ and WebAssembly is [emscripten](https://emscripten.org/docs/getting_started/index.html). 12 | 13 | You can install emscripten from most package managers for [Windows](https://chocolatey.org/packages/emscripten), [Linux](https://pkgs.org/search/?q=emscripten), or [Mac OS](https://formulae.brew.sh/formula/emscripten). You can also follow the [instructions](https://emscripten.org/docs/getting_started/downloads.html) on their website to build from source. 14 | 15 | Then follow [these instructions](https://emscripten.org/docs/getting_started/Tutorial.html) to compile your first "Hello World!" for the web. Your C++ program will become this beautiful webpage: 16 | 17 | ![](../img/hello_emscripten.png) 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /docs/javascripts/extra.js: -------------------------------------------------------------------------------- 1 | // When the page is loaded 2 | document.addEventListener("DOMContentLoaded", () => { 3 | // Make all external links open on a new tab 4 | // - https://www.w3schools.com/css/css_attribute_selectors.asp 5 | let external_links = Array.from(document.querySelectorAll(".md-typeset a[href^=http]")); 6 | let repo_link = Array.from(document.querySelectorAll(".md-header__source a[href^=http]")); 7 | for (const link of external_links.concat(repo_link)) { 8 | link.target = "_blank" 9 | } 10 | 11 | // Put around cpp reference links regardless of macros 12 | let cpp_reference_links = Array.from(document.querySelectorAll('.md-typeset a[href*="cppreference"]')); 13 | let open_std_links = Array.from(document.querySelectorAll('.md-typeset a[href*="open-std"]')); 14 | let futures_reference_link = Array.from(document.querySelectorAll('.md-typeset a[href*="/futures/reference/"]')); 15 | for (const link of cpp_reference_links.concat(open_std_links).concat(futures_reference_link)) { 16 | let already_inside_code_tag = link.parentElement.tagName !== undefined && link.parentElement.tagName.toUpperCase() === 'CODE' 17 | let already_has_code_tag = link.firstChild.tagName !== undefined && link.firstChild.tagName.toUpperCase() === 'CODE' 18 | let is_code_reference = link.innerHTML.startsWith('std::') || link.href.includes('/futures/reference/') 19 | if (already_inside_code_tag || already_has_code_tag || !is_code_reference) { 20 | continue; 21 | } 22 | link.innerHTML = "" + link.innerHTML + "" 23 | } 24 | 25 | // Fix bug in doxybook reference anchors 26 | let brokenAnchors = ['#function-', '#variable-', '#using-'] 27 | for (const anchor of brokenAnchors) { 28 | for (const link of futures_reference_link) { 29 | anchorPos = link.href.lastIndexOf(anchor); 30 | if (anchorPos !== -1) { 31 | let splitPos = anchorPos + anchor.length; 32 | let linkLhs = link.href.substr(0, splitPos); 33 | let linkRhs = link.href.substr(splitPos); 34 | link.href = linkLhs + linkRhs.replaceAll('-', '_'); 35 | } 36 | } 37 | } 38 | }) -------------------------------------------------------------------------------- /docs/overrides/main.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 | {{ super() }} 5 | 6 | 11 | {% endblock %} 12 | 13 | 14 | {% block site_nav %} 15 | 16 | {% if nav %} 17 | {% if page and page.meta and page.meta.hide %} 18 | {% set hidden = "hidden" if "navigation" in page.meta.hide %} 19 | {% endif %} 20 | 31 | {% endif %} 32 | 33 | 34 |
35 |
36 |
37 |
38 | {% include "partials/toc.html" %} 39 |
40 |
41 |
42 | {% endblock %} -------------------------------------------------------------------------------- /docs/programming-paradigms/basic-paradigms/crtp.md: -------------------------------------------------------------------------------- 1 | # Curiously Recurring Template Pattern 2 | 3 | !!! note "Curiously Recurring Template Pattern" 4 | 5 | The [Curiously Recurring Template Pattern](https://en.cppreference.com/w/cpp/language/crtp) is an idiom in which 6 | a class `X` derives from a class template `Y`, taking a template parameter `Z`, where `Y` is instantiated with `Z=X`. 7 | 8 | CRTP may be used to implement "compile-time polymorphism", when a base class exposes an interface, and derived 9 | classes implement such interface. 10 | 11 | {{ all_code_snippets("snippets/paradigms/CRTP.cpp") }} 12 | 13 | 14 | -------------------------------------------------------------------------------- /docs/programming-paradigms/basic-paradigms/polymorphism.md: -------------------------------------------------------------------------------- 1 | # Polymorphism 2 | 3 | !!! note "Polymorphism" 4 | 5 | [Object Oriented programming](https://www.educative.io/blog/object-oriented-programming) (OOP) is a programming 6 | paradigm that relies on the concept of classes and objects. 7 | It is used to structure a software program into simple, reusable pieces of code blueprints (usually called classes), 8 | which are used to create individual instances of objects. 9 | 10 | One of the key features of class inheritance is that a pointer to a derived class is type-compatible with a pointer 11 | to its base class. [Polymorphism](https://www.cplusplus.com/doc/tutorial/polymorphism/) is the art of taking 12 | advantage of this simple but powerful and versatile feature. 13 | 14 | {{ all_code_snippets("snippets/paradigms/polymorphism.cpp") }} 15 | 16 | 17 | -------------------------------------------------------------------------------- /docs/programming-paradigms/basic-paradigms/shared-from-this.md: -------------------------------------------------------------------------------- 1 | # Shared from this 2 | 3 | !!! note "Shared from this" 4 | 5 | [`std::enable_shared_from_this`](https://en.cppreference.com/w/cpp/memory/enable_shared_from_this) allows an 6 | object `t` that is currently managed by a `std::shared_ptr` named `pt` to safely generate additional 7 | `std::shared_ptr` instances `pt1`, `pt2`, ... that all share ownership of `t` with `pt`. 8 | 9 | Publicly inheriting from `std::enable_shared_from_this` provides the type `T` with a member function 10 | `shared_from_this`. If an object `t` of type `T` is managed by a `std::shared_ptr` named `pt`, then calling 11 | `T::shared_from_this` will return a new `std::shared_ptr` that shares ownership of `t` with `pt`. 12 | 13 | {{ all_code_snippets("snippets/paradigms/shared_from_this.cpp") }} 14 | 15 | 16 | -------------------------------------------------------------------------------- /docs/programming-paradigms/parallelism/async.md: -------------------------------------------------------------------------------- 1 | # Async++ 2 | 3 | !!! note "Async++" 4 | 5 | There have been many proposals to extend the C++ model of futures. Most proposals involve the capability of 6 | continuations without polling. One of this proposals is N3428, inspired by the Microsoft PPL library. 7 | [Async++](https://github.com/Amanieu/asyncplusplus) is a lightweight library that implements the concept. 8 | 9 | {{ code_snippet("snippets/parallel/CMakeLists.txt", "asyncplusplus", "cmake") }} 10 | 11 |
12 | 13 | {{ all_code_snippets("snippets/parallel/async_pools.cpp") }} 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /docs/programming-paradigms/parallelism/build-script.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Build script 4 | nav_order: 1 5 | has_children: false 6 | parent: Parallelism 7 | grand_parent: Programming Paradigms 8 | has_toc: false 9 | --- 10 | # Build script 11 | 12 | ```cmake 13 | --8<-- "snippets/parallel/CMakeLists.txt" 14 | ``` 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /docs/programming-paradigms/parallelism/execution-policies.md: -------------------------------------------------------------------------------- 1 | # Execution Policies 2 | 3 | !!! note "Execution Policies" 4 | 5 | Most algorithms have overloads that accept [execution policies](https://en.cppreference.com/w/cpp/algorithm). The 6 | standard library algorithms support several execution policies, and the library provides corresponding execution 7 | policy types and objects. Users may select an execution policy statically by invoking a parallel algorithm with 8 | an execution policy object of the corresponding type. 9 | 10 | {{ code_snippet("snippets/parallel/CMakeLists.txt", "policies", "cmake") }} 11 | 12 |
13 | 14 | {{ all_code_snippets("snippets/parallel/policies.cpp") }} 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /docs/programming-paradigms/parallelism/executors.md: -------------------------------------------------------------------------------- 1 | # Executors 2 | 3 | !!! note "Executors" 4 | 5 | A standard executor represents a policy as to how, when, and where a piece of code should be executed. 6 | The standard library does not include executors for parallel algorihms. 7 | 8 | [Boost.Asio](https://www.boost.org/doc/libs/1_78_0/doc/html/boost_asio/std_executors.html) provides a complete 9 | implementation of the proposed standard executors. 10 | 11 | Creating an execution context, such as a thread pool 12 | 13 | - Execution context: place where we can execute functions 14 | - A thread pool is an execution context. 15 | 16 | An execution context is: 17 | 18 | - Usually long lived. 19 | - Non-copyable. 20 | - May contain additional state, such as timers, and threads 21 | 22 | Creating an executor from an executor context: 23 | 24 | - Executor: set of rules governing where, when and how to run a function object 25 | - A thread pool _has_ executors that send tasks to it. 26 | - Its executor rule is: Run function objects in the pool and nowhere else. 27 | 28 | An executor is: 29 | 30 | - May be long or short lived. 31 | - Lightweight and copyable. 32 | - May be customized on a fine-grained basis, such as exception behavior, 33 | and order 34 | 35 | Some references: 36 | 37 | - https://think-async.com/Asio/ 38 | - https://think-async.com/Asio/asio-1.18.1/doc/asio/std_executors.html 39 | - https://github.com/chriskohlhoff/executors 40 | - https://taskflow.github.io/taskflow/index.html 41 | - Read the unit tests, such as asio/src/tests/unit/thread_pool.cpp 42 | 43 | {{ code_snippet("snippets/parallel/CMakeLists.txt", "find_asio", "cmake") }} 44 | 45 |
46 | 47 | {{ code_snippet("snippets/parallel/CMakeLists.txt", "executors", "cmake") }} 48 | 49 |
50 | 51 | {{ all_code_snippets("snippets/parallel/executors.cpp") }} 52 | 53 | -------------------------------------------------------------------------------- /docs/programming-paradigms/parallelism/signals.md: -------------------------------------------------------------------------------- 1 | # Signals 2 | 3 | !!! note "Signals" 4 | 5 | Signals might be important to properly stop asynchronous operations, such as servers. 6 | 7 | [Boost.Asio](https://www.boost.org/doc/libs/1_78_0/doc/html/boost_asio/overview/signals.html) supports signal 8 | handling using a class called `signal_set`. Programs may add one or more signals to the set, and then perform an 9 | `async_wait()` operation. 10 | 11 | The specified handler will be called when one of the signals occurs. The same signal number may be registered 12 | with multiple `signal_set` objects, however the signal number must be used only with `Boost.Asio`. 13 | 14 | {{ code_snippet("snippets/parallel/CMakeLists.txt", "find_asio", "cmake") }} 15 | 16 |
17 | 18 | {{ code_snippet("snippets/parallel/CMakeLists.txt", "signals", "cmake") }} 19 | 20 |
21 | 22 | {{ all_code_snippets("snippets/parallel/signals.cpp") }} 23 | 24 | -------------------------------------------------------------------------------- /docs/programming-paradigms/parallelism/threads.md: -------------------------------------------------------------------------------- 1 | # Threads 2 | 3 | !!! note "Threads" 4 | 5 | The [C++ thread support library](https://en.cppreference.com/w/cpp/thread) includes built-in support for threads, 6 | mutual exclusion, condition variables, and futures. 7 | 8 | {{ code_snippet("snippets/parallel/CMakeLists.txt", "threads", "cmake") }} 9 | 10 |
11 | 12 | {{ all_code_snippets("snippets/parallel/multithreading.cpp") }} 13 | 14 | -------------------------------------------------------------------------------- /docs/programming-paradigms/parallelism/timers.md: -------------------------------------------------------------------------------- 1 | # Timers 2 | 3 | !!! note "Timers" 4 | 5 | Timers are useful to applications that need to perform 6 | some operations once every x time units, including timeouts 7 | for servers 8 | 9 | {{ code_snippet("snippets/parallel/CMakeLists.txt", "find_asio", "cmake") }} 10 | 11 |
12 | 13 | {{ code_snippet("snippets/parallel/CMakeLists.txt", "timers", "cmake") }} 14 | 15 |
16 | 17 | {{ all_code_snippets("snippets/parallel/timers.cpp") }} 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /docs/testing/boostut.md: -------------------------------------------------------------------------------- 1 | # boost.ut 2 | 3 | {{ code_snippet("snippets/tests/CMakeLists.txt", "fetch_boostut", "cmake") }} 4 | 5 |
6 | 7 | {{ code_snippet("snippets/tests/CMakeLists.txt", "link_boostut", "cmake") }} 8 | 9 |
10 | 11 | {{ all_code_snippets("snippets/tests/unit_tests_ut.cpp") }} 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /docs/testing/catch2.md: -------------------------------------------------------------------------------- 1 | # Catch2 2 | 3 | {{ code_snippet("snippets/tests/CMakeLists.txt", "fetch_catch2", "cmake") }} 4 | 5 |
6 | 7 | {{ code_snippet("snippets/tests/CMakeLists.txt", "link_catch2", "cmake") }} 8 | 9 |
10 | 11 | {{ all_code_snippets("snippets/tests/unit_tests_catch.cpp") }} 12 | 13 | -------------------------------------------------------------------------------- /docs/testing/plots.md: -------------------------------------------------------------------------------- 1 | # Plots 2 | 3 | {{ code_snippet("snippets/tests/CMakeLists.txt", "find_matplot", "cmake") }} 4 | 5 |
6 | 7 | {{ code_snippet("snippets/tests/CMakeLists.txt", "link_matplot", "cmake") }} 8 | 9 |
10 | 11 | {{ all_code_snippets("snippets/tests/plots.cpp") }} 12 | 13 | -------------------------------------------------------------------------------- /docs/testing/source-location.md: -------------------------------------------------------------------------------- 1 | # Source Location 2 | 3 | {{ all_code_snippets("snippets/tests/source_location.cpp") }} 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /docs/utilities/networking/async-network.md: -------------------------------------------------------------------------------- 1 | # Async Network 2 | 3 | {{ code_snippet("snippets/parallel/CMakeLists.txt", "find_asio", "cmake") }} 4 | 5 |
6 | 7 | {{ code_snippet("snippets/networking/CMakeLists.txt", "network", "cmake") }} 8 | 9 |
10 | 11 | {{ all_code_snippets("snippets/networking/network_async.cpp") }} 12 | -------------------------------------------------------------------------------- /docs/utilities/networking/http-server.md: -------------------------------------------------------------------------------- 1 | # Http server 2 | 3 | {{ code_snippet("snippets/parallel/CMakeLists.txt", "find_asio", "cmake") }} 4 | 5 |
6 | 7 | {{ code_snippet("snippets/networking/server/CMakeLists.txt", "server", "cmake") }} 8 | 9 |
10 | 11 | {{ all_code_snippets("snippets/networking/server/main.cpp") }} 12 | 13 |
14 | 15 | {{ all_code_snippets("snippets/networking/server/server.hpp") }} 16 | 17 |
18 | 19 | {{ all_code_snippets("snippets/networking/server/server.cpp") }} 20 | 21 |
22 | 23 | {{ all_code_snippets("snippets/networking/server/connection_manager.hpp") }} 24 | 25 |
26 | 27 | {{ all_code_snippets("snippets/networking/server/connection_manager.cpp") }} 28 | 29 |
30 | 31 | {{ all_code_snippets("snippets/networking/server/connection.hpp") }} 32 | 33 |
34 | 35 | {{ all_code_snippets("snippets/networking/server/connection.cpp") }} 36 | 37 |
38 | 39 | {{ all_code_snippets("snippets/networking/server/reply.hpp") }} 40 | 41 |
42 | 43 | {{ all_code_snippets("snippets/networking/server/reply.cpp") }} 44 | 45 |
46 | 47 | {{ all_code_snippets("snippets/networking/server/header.hpp") }} 48 | 49 |
50 | 51 | {{ all_code_snippets("snippets/networking/server/request.hpp") }} 52 | 53 |
54 | 55 | {{ all_code_snippets("snippets/networking/server/request_parser.hpp") }} 56 | 57 |
58 | 59 | {{ all_code_snippets("snippets/networking/server/request_parser.cpp") }} 60 | 61 |
62 | 63 | {{ all_code_snippets("snippets/networking/server/request_handler.hpp") }} 64 | 65 |
66 | 67 | {{ all_code_snippets("snippets/networking/server/request_handler.cpp") }} 68 | 69 |
70 | 71 | {{ all_code_snippets("snippets/networking/server/mime_types.hpp") }} 72 | 73 |
74 | 75 | {{ all_code_snippets("snippets/networking/server/mime_types.cpp") }} 76 | 77 |
78 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /docs/utilities/networking/network.md: -------------------------------------------------------------------------------- 1 | # Network 2 | 3 | {{ code_snippet("snippets/parallel/CMakeLists.txt", "find_asio", "cmake") }} 4 | 5 |
6 | 7 | {{ code_snippet("snippets/networking/CMakeLists.txt", "network", "cmake") }} 8 | 9 |
10 | 11 | {{ all_code_snippets("snippets/networking/network.cpp") }} 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /docs/utilities/regular-expressions/regex.md: -------------------------------------------------------------------------------- 1 | # Regex 2 | 3 | !!! note "Regex" 4 | 5 | The [regular expressions library](https://en.cppreference.com/w/cpp/regex) provides a class that represents 6 | regular expressions, which are a kind of mini-language used to perform pattern matching within strings. 7 | 8 | {{ all_code_snippets("snippets/utilities/regex.cpp") }} 9 | 10 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(basic_types) 2 | add_subdirectory(control_flow) 3 | add_subdirectory(algorithm) 4 | add_subdirectory(functions) 5 | add_subdirectory(data_structures) 6 | add_subdirectory(datetime) 7 | add_subdirectory(paradigms/oop) -------------------------------------------------------------------------------- /examples/algorithm/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package(Matplot++ QUIET) 2 | if (Matplot++_FOUND) 3 | add_executable(algorithm_example algorithm.cpp) 4 | target_link_libraries(algorithm_example PRIVATE Matplot++::matplot) 5 | 6 | add_executable(searching_benchmark searching.cpp) 7 | target_link_libraries(searching_benchmark PRIVATE Matplot++::matplot) 8 | 9 | add_executable(sorting_benchmark sorting.cpp) 10 | target_link_libraries(sorting_benchmark PRIVATE Matplot++::matplot) 11 | endif () 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /examples/basic_types/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(vector_matrix vector_matrix.cpp) -------------------------------------------------------------------------------- /examples/basic_types/vector_matrix.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | using namespace std; 7 | array,3> a{ 8 | array{3, 4, 7, 4}, 9 | array{4, 7, 4, 2}, 10 | array{7, 8, 3, 6} 11 | }; 12 | cout << a[0][0] << endl; 13 | cout << a[0][1] << endl; 14 | cout << a[0][2] << endl; 15 | cout << a[0][3] << endl; 16 | cout << a[1][0] << endl; 17 | cout << a[1][1] << endl; 18 | cout << a[1][2] << endl; 19 | cout << a[1][3] << endl; 20 | cout << a[2][0] << endl; 21 | cout << a[2][1] << endl; 22 | cout << a[2][2] << endl; 23 | cout << a[2][3] << endl; 24 | 25 | cout << &a[0][0] << endl; 26 | cout << &a[0][1] << endl; 27 | cout << &a[0][2] << endl; 28 | cout << &a[0][3] << endl; 29 | cout << &a[1][0] << endl; 30 | cout << &a[1][1] << endl; 31 | cout << &a[1][2] << endl; 32 | cout << &a[1][3] << endl; 33 | cout << &a[2][0] << endl; 34 | cout << &a[2][1] << endl; 35 | cout << &a[2][2] << endl; 36 | cout << &a[2][3] << endl; 37 | return 0; 38 | } -------------------------------------------------------------------------------- /examples/control_flow/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(calculator calculator.cpp) -------------------------------------------------------------------------------- /examples/control_flow/calculator.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | using namespace std; 6 | 7 | int option; 8 | double n1, n2, res; 9 | do { 10 | cout << "=== Options ===" << endl; 11 | cout << "[1] Summation" << endl; 12 | cout << "[2] Subtraction" << endl; 13 | cout << "[3] Multiply" << endl; 14 | cout << "[4] Divide" << endl; 15 | cout << "[0] Quit" << endl; 16 | 17 | cout << "Enter an option: "; 18 | cin >> option; 19 | bool valid_range = option >= 0 && option <= 4; 20 | while (!cin.good() || !valid_range) { 21 | if (!cin.good()) { 22 | cin.clear(); 23 | cin.ignore(std::numeric_limits::max(), '\n'); 24 | cout << "!! Enter a NUMERIC option: "; 25 | cin >> option; 26 | } else { 27 | cout << "!! Enter a VALID option: "; 28 | cin >> option; 29 | } 30 | valid_range = option >= 0 && option <= 4; 31 | } 32 | 33 | if (option != 0) { 34 | cout << "Enter the first number: "; 35 | cin >> n1; 36 | cout << "Enter the second number: "; 37 | cin >> n2; 38 | switch (option) { 39 | case 1: 40 | res = n1 + n2; 41 | cout << n1 << " + " << n2 << " = " << res << endl; 42 | break; 43 | case 2: 44 | res = n1 - n2; 45 | cout << n1 << " - " << n2 << " = " << res << endl; 46 | break; 47 | case 3: 48 | res = n1 * n2; 49 | cout << n1 << " * " << n2 << " = " << res << endl; 50 | break; 51 | case 4: 52 | res = n1 / n2; 53 | cout << n1 << " / " << n2 << " = " << res << endl; 54 | break; 55 | default: 56 | cout << "!!! Invalid option !!!" << endl; 57 | break; 58 | } 59 | } else { 60 | cout << "Thank you. Bye." << endl; 61 | } 62 | } while (option != 0); 63 | 64 | return 0; 65 | } -------------------------------------------------------------------------------- /examples/data_structures/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(graph_example graph_example.cpp) -------------------------------------------------------------------------------- /examples/datetime/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(flushtime flushtime.cpp) 2 | -------------------------------------------------------------------------------- /examples/functions/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | FetchContent_Declare(tabulate GIT_REPOSITORY https://github.com/p-ranav/tabulate.git GIT_TAG v1.4) 2 | FetchContent_MakeAvailable(tabulate) 3 | add_executable(recursive_bench recursive_bench.cpp) 4 | target_link_libraries(recursive_bench PRIVATE tabulate) -------------------------------------------------------------------------------- /examples/functions/recursive_bench.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | // Iterative function 8 | int fibonacci_iterative(int n); 9 | 10 | // Recursive function 11 | int fibonacci_recursive(int n); 12 | 13 | int main() { 14 | // Comparing time 15 | // - This is a classic case where: 16 | // - Iterative algorithms are more efficient 17 | // - Recursive algorithms are easier to write 18 | tabulate::Table results; 19 | results.add_row({"i", "fib(i)", "Iterative Time (ns)", 20 | "Recursive Time (ns)"}); 21 | for (int i = 3; i < 60; ++i) { 22 | auto start1 = chrono::steady_clock::now(); 23 | int result1 = fibonacci_iterative(i); 24 | auto duration1 = chrono::duration_cast(std::chrono::steady_clock::now() - start1); 25 | 26 | auto start2 = chrono::steady_clock::now(); 27 | int result2 = fibonacci_recursive(i); 28 | auto duration2 = chrono::duration_cast(std::chrono::steady_clock::now() - start2); 29 | 30 | if (result1 == result2) { 31 | results.add_row({"i = " + to_string(i), 32 | "fib(i) = " + to_string(result1), 33 | to_string(duration1.count()) + "ns", 34 | to_string(duration2.count()) + "ns"}); 35 | } else { 36 | cerr << "The results don't match\n"; 37 | return 0; 38 | } 39 | 40 | std::cout << results << std::endl; 41 | } 42 | 43 | return 0; 44 | } 45 | 46 | int fibonacci_iterative(int n) { 47 | if (n <= 2) { 48 | return 1; 49 | } 50 | int fn; 51 | int fn_1 = 1; 52 | int fn_2 = 1; 53 | for (int i = 3; i <= n; ++i) { 54 | fn = fn_1 + fn_2; 55 | fn_2 = fn_1; 56 | fn_1 = fn; 57 | } 58 | return fn; 59 | } 60 | 61 | // NOLINTNEXTLINE(misc-no-recursion): making a point 62 | int fibonacci_recursive(int n) { 63 | if (n > 2) { 64 | return fibonacci_recursive(n - 1) + fibonacci_recursive(n - 2); 65 | } else { 66 | return 1; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /examples/gui/qt/warehouse/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(lib) 2 | add_subdirectory(standalone) -------------------------------------------------------------------------------- /examples/gui/qt/warehouse/lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(warehouse_lib 2 | warehouse.cpp 3 | warehouse.h 4 | product.cpp 5 | product.h 6 | ) 7 | target_include_directories(warehouse_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -------------------------------------------------------------------------------- /examples/gui/qt/warehouse/lib/product.cpp: -------------------------------------------------------------------------------- 1 | #include "product.h" 2 | #include 3 | #include 4 | 5 | void product::print() { 6 | std::cout << *this << std::endl; 7 | } 8 | 9 | std::ostream &operator<<(std::ostream &os, const product &product1) { 10 | os << "#" << product1.id_ << " \t" << std::setw(15) << product1.name_ << " \tR$" << product1.price_; 11 | return os; 12 | } 13 | 14 | product::product(int id_, double price_, const std::string &_name_) : 15 | id_(id_), price_(price_), name_(_name_) {} 16 | 17 | void product::set_name(const std::string& _name_) { 18 | product::name_ = _name_; 19 | } 20 | 21 | const std::string& product::get_name() { 22 | return name_; 23 | } 24 | 25 | void product::set_price(double price) { 26 | price_ = price; 27 | } 28 | 29 | double product::get_price() { 30 | return price_; 31 | } 32 | 33 | void product::set_id(int id) { 34 | id_ = id; 35 | } 36 | 37 | int product::get_id() { 38 | return id_; 39 | } 40 | 41 | bool product::operator<(const product &rhs) const { 42 | if (id_ < rhs.id_) 43 | return true; 44 | if (rhs.id_ < id_) 45 | return false; 46 | if (price_ < rhs.price_) 47 | return true; 48 | if (rhs.price_ < price_) 49 | return false; 50 | return name_ < rhs.name_; 51 | } 52 | 53 | bool product::operator>(const product &rhs) const { 54 | return rhs < *this; 55 | } 56 | 57 | bool product::operator<=(const product &rhs) const { 58 | return !(rhs < *this); 59 | } 60 | 61 | bool product::operator>=(const product &rhs) const { 62 | return !(*this < rhs); 63 | } 64 | -------------------------------------------------------------------------------- /examples/gui/qt/warehouse/lib/product.h: -------------------------------------------------------------------------------- 1 | #ifndef BCC702_PRODUTO_H 2 | #define BCC702_PRODUTO_H 3 | 4 | #include 5 | #include 6 | 7 | class warehouse; 8 | class product { 9 | public: 10 | /// Create product 11 | product(int id, double price, const std::string &name); 12 | 13 | /// Create product vazio 14 | product() = default; 15 | 16 | /// Print product 17 | void print(); 18 | void set_name(const std::string &name); 19 | const std::string& get_name(); 20 | void set_price(double price); 21 | double get_price(); 22 | void set_id(int id); 23 | int get_id(); 24 | 25 | /// Stream 26 | friend std::ostream &operator<<(std::ostream &os, const product &product1); 27 | 28 | /// Relational 29 | bool operator<(const product &rhs) const; 30 | bool operator>(const product &rhs) const; 31 | bool operator<=(const product &rhs) const; 32 | bool operator>=(const product &rhs) const; 33 | 34 | private: 35 | int id_; 36 | double price_; 37 | std::string name_; 38 | }; 39 | 40 | #endif //BCC702_PRODUTO_H 41 | -------------------------------------------------------------------------------- /examples/gui/qt/warehouse/lib/warehouse.h: -------------------------------------------------------------------------------- 1 | #ifndef BCC702_WAREHOUSE_H 2 | #define BCC702_WAREHOUSE_H 3 | 4 | #include 5 | #include "product.h" 6 | 7 | class warehouse { 8 | public: 9 | /// Create warehouse 10 | warehouse(); 11 | 12 | /// Destroy warehouse 13 | virtual ~warehouse(); 14 | 15 | void add_product(); 16 | 17 | void find_by_name(); 18 | 19 | void find_by_code(); 20 | 21 | void remove_product(); 22 | 23 | void list_products(); 24 | 25 | void save_products(const std::string &filename); 26 | 27 | void load_products(const std::string &filename); 28 | 29 | private: 30 | std::map products_; 31 | }; 32 | 33 | 34 | #endif //BCC702_WAREHOUSE_H 35 | -------------------------------------------------------------------------------- /examples/gui/qt/warehouse/standalone/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(cli) 2 | add_subdirectory(gui) -------------------------------------------------------------------------------- /examples/gui/qt/warehouse/standalone/cli/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(warehouse_cli 2 | main.cpp 3 | application.h 4 | application.cpp 5 | ) 6 | target_link_libraries(warehouse_cli PRIVATE warehouse_lib) -------------------------------------------------------------------------------- /examples/gui/qt/warehouse/standalone/cli/application.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Alan Freitas on 2/7/21. 3 | // 4 | 5 | #include 6 | 7 | #ifndef MODERNCPP_APPLICATION_H 8 | #define MODERNCPP_APPLICATION_H 9 | 10 | class application { 11 | public: 12 | void run(); 13 | int show_menu(); 14 | void add_product(); 15 | void find_by_name(); 16 | void find_by_code(); 17 | void remove_product(); 18 | void list_products(); 19 | 20 | private: 21 | warehouse q_; 22 | }; 23 | 24 | 25 | #endif // MODERNCPP_APPLICATION_H 26 | -------------------------------------------------------------------------------- /examples/gui/qt/warehouse/standalone/cli/main.cpp: -------------------------------------------------------------------------------- 1 | #include "application.h" 2 | 3 | int main() { 4 | application app; 5 | app.run(); 6 | return 0; 7 | } -------------------------------------------------------------------------------- /examples/gui/qt/warehouse/standalone/gui/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Try to add Qt path to CMAKE_PREFIX_PATH 2 | add_qt_to_cmake_paths() 3 | -------------------------------------------------------------------------------- /examples/paradigms/oop/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(warehouse 2 | main.cpp 3 | warehouse.cpp 4 | warehouse.h 5 | product.cpp 6 | product.h 7 | ) -------------------------------------------------------------------------------- /examples/paradigms/oop/main.cpp: -------------------------------------------------------------------------------- 1 | #include "warehouse.h" 2 | 3 | int main() { 4 | warehouse q; 5 | q.interface(); 6 | return 0; 7 | } -------------------------------------------------------------------------------- /examples/paradigms/oop/product.cpp: -------------------------------------------------------------------------------- 1 | #include "product.h" 2 | #include 3 | #include 4 | 5 | void product::print() { 6 | std::cout << *this << std::endl; 7 | } 8 | 9 | std::ostream &operator<<(std::ostream &os, const product &product1) { 10 | os << "#" << product1.id_ << " \t" << std::setw(15) << product1.name_ << " \tR$" << product1.price_; 11 | return os; 12 | } 13 | 14 | product::product(int id_, double price_, const std::string &_name_) : 15 | id_(id_), price_(price_), name_(_name_) {} 16 | 17 | void product::set_name(const std::string& _name_) { 18 | product::name_ = _name_; 19 | } 20 | 21 | bool product::operator<(const product &rhs) const { 22 | if (id_ < rhs.id_) 23 | return true; 24 | if (rhs.id_ < id_) 25 | return false; 26 | if (price_ < rhs.price_) 27 | return true; 28 | if (rhs.price_ < price_) 29 | return false; 30 | return name_ < rhs.name_; 31 | } 32 | 33 | bool product::operator>(const product &rhs) const { 34 | return rhs < *this; 35 | } 36 | 37 | bool product::operator<=(const product &rhs) const { 38 | return !(rhs < *this); 39 | } 40 | 41 | bool product::operator>=(const product &rhs) const { 42 | return !(*this < rhs); 43 | } 44 | -------------------------------------------------------------------------------- /examples/paradigms/oop/product.h: -------------------------------------------------------------------------------- 1 | #ifndef BCC702_PRODUTO_H 2 | #define BCC702_PRODUTO_H 3 | 4 | #include 5 | #include 6 | 7 | class warehouse; 8 | class product { 9 | public: 10 | friend warehouse; 11 | 12 | /// Create product 13 | product(int id, double price, const std::string &name); 14 | 15 | /// Create product vazio 16 | product() = default; 17 | 18 | /// Print product 19 | void print(); 20 | void set_name(const std::string &name); 21 | 22 | /// Stream 23 | friend std::ostream &operator<<(std::ostream &os, const product &product1); 24 | 25 | /// Relational 26 | bool operator<(const product &rhs) const; 27 | bool operator>(const product &rhs) const; 28 | bool operator<=(const product &rhs) const; 29 | bool operator>=(const product &rhs) const; 30 | 31 | private: 32 | int id_; 33 | double price_; 34 | std::string name_; 35 | }; 36 | 37 | #endif //BCC702_PRODUTO_H 38 | -------------------------------------------------------------------------------- /examples/paradigms/oop/warehouse.h: -------------------------------------------------------------------------------- 1 | #ifndef BCC702_WAREHOUSE_H 2 | #define BCC702_WAREHOUSE_H 3 | 4 | #include 5 | #include "product.h" 6 | 7 | class warehouse { 8 | public: 9 | /// Create warehouse 10 | warehouse(); 11 | 12 | /// Destroy warehouse 13 | virtual ~warehouse(); 14 | 15 | /// Interface 16 | void interface(); 17 | 18 | private: 19 | int show_menu(); 20 | 21 | void add_product(); 22 | 23 | void find_by_name(); 24 | 25 | void find_by_code(); 26 | 27 | void remove_product(); 28 | 29 | void list_products(); 30 | 31 | void save_products(const std::string &filename); 32 | 33 | void load_products(const std::string &filename); 34 | 35 | private: 36 | std::map products_; 37 | }; 38 | 39 | 40 | #endif //BCC702_WAREHOUSE_H 41 | -------------------------------------------------------------------------------- /snippets/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Basics 2 | add_subdirectory(control_flow) 3 | add_subdirectory(input_output) 4 | add_subdirectory(data_types) 5 | add_subdirectory(basic_types) 6 | add_subdirectory(pointers) 7 | add_subdirectory(functions) 8 | add_subdirectory(files) 9 | 10 | # Algorithms and Data Structures 11 | add_subdirectory(datetime) 12 | add_subdirectory(random) 13 | add_subdirectory(templates) 14 | add_subdirectory(algorithm) 15 | add_subdirectory(data_structures) 16 | add_subdirectory(heterogeneous_types) 17 | 18 | # Paradigms 19 | add_subdirectory(paradigms) 20 | add_subdirectory(parallel) 21 | 22 | # Utilities 23 | add_subdirectory(networking) 24 | add_subdirectory(utilities) 25 | 26 | # Interfaces 27 | add_subdirectory(gui) 28 | 29 | # Testing 30 | add_subdirectory(tests) -------------------------------------------------------------------------------- /snippets/algorithm/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(algorithms algorithms.cpp) 2 | 3 | # Failing on Clang-13: 4 | # associated_types.hpp:270:60: error: too many template arguments for class template '__iterator_traits' 5 | if (NOT CLANG) 6 | #[ranges CMakeLists.txt 7 | # Ranges in C++20: https://en.cppreference.com/w/cpp/ranges 8 | # Use range-v3 for now: https://github.com/ericniebler/range-v3 9 | find_package(range-v3 QUIET) 10 | if (NOT range-v3_FOUND) 11 | FetchContent_Declare(range-v3 URL https://github.com/ericniebler/range-v3/archive/0.11.0.zip) 12 | FetchContent_GetProperties(range-v3) 13 | if (NOT range-v3_POPULATED) 14 | FetchContent_Populate(range-v3) 15 | add_library(range-v3 INTERFACE IMPORTED) 16 | target_include_directories(range-v3 INTERFACE "${range-v3_SOURCE_DIR}/include") 17 | endif () 18 | endif() 19 | add_executable(ranges ranges.cpp) 20 | target_link_libraries(ranges PUBLIC range-v3) 21 | #] 22 | endif() 23 | 24 | add_executable(searching searching.cpp) 25 | 26 | add_executable(sorting sorting.cpp) 27 | 28 | -------------------------------------------------------------------------------- /snippets/algorithm/ranges.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | //[headers Headers 6 | #include 7 | //] 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | int main() { 14 | std::random_device rd; 15 | std::mt19937 generator{rd()}; 16 | std::uniform_int_distribution distribution(1, 30); 17 | 18 | //[iota Sequentially increasing range 19 | std::vector v(30); 20 | ranges::iota(v, 1); 21 | //] 22 | 23 | //[count Counting 24 | std::cout << ranges::count(v, 0) << '\n'; 25 | //] 26 | 27 | //[accumulate Accumulating 28 | std::cout << ranges::accumulate(v, 0) << '\n'; 29 | //] 30 | 31 | //[sort Sorting 32 | ranges::sort(v); 33 | //] 34 | 35 | //[binary_search Binary Search 36 | std::cout << ranges::binary_search(v, 15) << '\n'; 37 | //] 38 | 39 | //[is_sorted Check if sorted 40 | std::cout << ranges::is_sorted(v) << '\n'; 41 | //] 42 | 43 | //[for_each For each 44 | ranges::for_each(v, [](const int c) { std::cout << c << " "; }); 45 | std::cout << '\n'; 46 | //] 47 | 48 | //[filter Filter views 49 | std::array a{{0, 5, 2, 1, 3, 4}}; 50 | auto filtered_range = ranges::views::filter(a, [](int i) { return i > 2; }); 51 | std::vector v2(filtered_range.begin(), filtered_range.end()); 52 | //] 53 | // This failed in some compilers: 54 | // ranges::copy(filtered_range, std::back_inserter(v2)); 55 | // `std::back_inserter(v2)` did not satisfy `weakly_incrementable` 56 | 57 | //[reverse_view Reversed view 58 | auto reversed_range = ranges::views::reverse(a); 59 | for (int x : reversed_range) { 60 | std::cout << x << ' '; 61 | } 62 | //] 63 | 64 | //[unique Unique view 65 | ranges::sort(a); 66 | auto unique_range = ranges::views::unique(a); 67 | for (int x : unique_range) { 68 | std::cout << x << ' '; 69 | } 70 | //] 71 | 72 | //[keys Keys view 73 | std::map m; 74 | m["a"] = 0; 75 | m["b"] = 1; 76 | m["c"] = 2; 77 | auto map_keys = ranges::views::keys(m); 78 | for (const std::string &k : map_keys) { 79 | std::cout << k << ","; 80 | } 81 | //] 82 | 83 | //[tokenize Tokenize view 84 | std::string s = "The range v3 library"; 85 | std::regex expr{"[\\w+]+"}; 86 | auto tokenizer = ranges::views::tokenize( 87 | s, expr, 0, std::regex_constants::match_default); 88 | for (auto &x : tokenizer) { 89 | std::cout << x << ","; 90 | } 91 | //] 92 | 93 | //[ints Integer views 94 | auto ir = ranges::views::ints(0, 3); 95 | for (auto x : ir) { 96 | std::cout << x << ","; 97 | } 98 | //] 99 | 100 | return 0; 101 | } -------------------------------------------------------------------------------- /snippets/basic_types/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(raw_arrays raw_arrays.cpp) 2 | 3 | add_executable(arrays arrays.cpp) 4 | 5 | add_executable(vectors vectors.cpp) 6 | 7 | add_executable(strings strings.cpp) 8 | 9 | add_executable(move move.cpp) 10 | 11 | add_executable(struct struct.cpp) 12 | 13 | #[aggregate_initialization CMakeLists.txt 14 | add_executable(aggregate_initialization aggregate_initialization.cpp) 15 | target_compile_features(aggregate_initialization PRIVATE cxx_std_20) 16 | #] 17 | 18 | #[structured_binding CMakeLists.txt 19 | add_executable(structured_binding structured_binding.cpp) 20 | target_compile_features(structured_binding PRIVATE cxx_std_17) 21 | #] 22 | -------------------------------------------------------------------------------- /snippets/basic_types/aggregate_initialization.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | 6 | 7 | //[aggregate_type_a An aggregate type 8 | struct A { 9 | int x; 10 | int y; 11 | int z; 12 | }; 13 | //] 14 | 15 | auto print_a = [](const A &a) { 16 | std::cout << "a: {" << a.x << ", " << a.y << ", " << a.z << "}" 17 | << std::endl; 18 | }; 19 | 20 | //[init Initialize type with designated initializers 21 | A a{.x = 1, .y = 4, .z = 2}; 22 | //] 23 | print_a(a); 24 | 25 | A b{.x = 1, .y = 2, .z = 6}; 26 | print_a(b); 27 | 28 | //[list List initialization 29 | A c{1, 2, 3}; 30 | //] 31 | print_a(c); 32 | 33 | //[nested Nested type 34 | struct B { 35 | int x; 36 | A y; 37 | int z; 38 | }; 39 | //] 40 | 41 | auto print_b = 42 | [](const B &a) { 43 | std::cout << "a: {" << a.x << ", {" << a.y.x << ", " << a.y.y 44 | << ", " << a.y.z << "}, " << a.z << "}" << std::endl; 45 | }; 46 | 47 | //[nested_init Nested initialization 48 | B d{.x = 1, .y = {2, 6, 5}, .z = 3}; 49 | //] 50 | print_b(d); 51 | 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /snippets/basic_types/arrays.cpp: -------------------------------------------------------------------------------- 1 | //[headers Headers 2 | #include 3 | //] 4 | #include 5 | #include 6 | 7 | int main() { 8 | //[fixed Fixed size array 9 | constexpr int n = 3; 10 | std::array a = {1, 2, 3}; 11 | //] 12 | 13 | //[iter Iterate arrays 14 | for (size_t i = 0; i < a.size(); ++i) { 15 | std::cout << "a[" << i << "]: " << a[i] << '\n'; 16 | } 17 | //] 18 | 19 | //[member Member functions 20 | std::cout << "a.size(): " << a.size() << '\n'; 21 | std::cout << "a.empty(): " << a.empty() << '\n'; 22 | std::cout << "a.front(): " << a.front() << '\n'; 23 | std::cout << "a.back(): " << a.back() << '\n'; 24 | //] 25 | 26 | //[access Accessing elements 27 | std::cout << "a[0]: " << a[0] << '\n'; 28 | std::cout << "a[1]: " << a[1] << '\n'; 29 | std::cout << "a[2]: " << a[2] << '\n'; 30 | //] 31 | 32 | //[access Accessing addresses 33 | std::cout << "&a: " << &a << '\n'; 34 | std::cout << "&a[0]: " << &a[0] << '\n'; 35 | std::cout << "&a[1]: " << &a[1] << '\n'; 36 | std::cout << "&a[2]: " << &a[2] << '\n'; 37 | //] 38 | 39 | //[get Underlying raw array 40 | // We might still need the underlying raw array 41 | // to interact with old code 42 | std::cout << "Underlying raw array - a.data(): " << a.data() << '\n'; 43 | //] 44 | 45 | //[size Array size 46 | // array has a fixed size in bytes 47 | std::cout << "sizeof(a): " << sizeof(a) << '\n'; 48 | //] 49 | 50 | //[multidim Multidimensional array 51 | std::array, 10> matrix; 52 | for (size_t i = 0; i < matrix.size(); ++i) { 53 | for (size_t j = 0; j < matrix[i].size(); ++j) { 54 | matrix[i][j] = 0.5 * i + 0.8 * j; 55 | } 56 | } 57 | //] 58 | 59 | //[forrange Range-based loop 60 | for (const auto &row : matrix) { 61 | double sum = 0.; 62 | for (const auto &col : row) { 63 | sum += col; 64 | } 65 | std::cout << "Row average " << sum / row.size() << '\n'; 66 | } 67 | //] 68 | 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /snippets/basic_types/move.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | //[headers Headers 6 | #include 7 | //] 8 | 9 | int main() { 10 | //[copy Copying a vector 11 | std::vector v1(30, 1.0); 12 | std::vector v2 = v1; 13 | //] 14 | 15 | //[iterate_1 Both vectors are valid 16 | std::cout << "v1: "; 17 | for (double x: v1) { 18 | std::cout << x << " "; 19 | } 20 | std::cout << '\n'; 21 | 22 | std::cout << "v2: "; 23 | for (double x: v2) { 24 | std::cout << x << " "; 25 | } 26 | std::cout << '\n'; 27 | //] 28 | 29 | //[copy Moving a vector 30 | std::vector v3 = std::move(v1); 31 | //] 32 | 33 | //[iterate_2 The vector moved-from is invalidated 34 | std::cout << "v1: "; 35 | // NOLINTNEXTLINE(bugprone-use-after-move): making a point 36 | for (double x: v1) { 37 | std::cout << x << " "; // prints nothing 38 | } 39 | std::cout << '\n'; 40 | 41 | std::cout << "v3: "; 42 | for (double x: v3) { 43 | std::cout << x << " "; 44 | } 45 | std::cout << '\n'; 46 | //] 47 | 48 | return 0; 49 | } -------------------------------------------------------------------------------- /snippets/basic_types/raw_arrays.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | int main() { 7 | 8 | // Raw arrays 9 | // - Examples only: don't use raw arrays! 10 | 11 | //[explicit Explicit size 12 | constexpr int n = 3; 13 | int a[n]; 14 | a[0] = 1; 15 | a[1] = 2; 16 | a[2] = 3; 17 | std::cout << "a: " << a << '\n'; 18 | //] 19 | 20 | //[accessing Accessing elements 21 | std::cout << "a[0]: " << a[0] << '\n'; 22 | std::cout << "a[1]: " << a[1] << '\n'; 23 | std::cout << "a[2]: " << a[2] << '\n'; 24 | //] 25 | 26 | //[accessing_address Accessing element address 27 | std::cout << "&a[0]: " << &a[0] << '\n'; 28 | std::cout << "&a[1]: " << &a[1] << '\n'; 29 | std::cout << "&a[2]: " << &a[2] << '\n'; 30 | //] 31 | 32 | //[implicit Implicit size 33 | int b[] = {1, 2, 3}; 34 | //] 35 | 36 | //[accessing_loop Accessing elements in a loop 37 | for (size_t i = 0; i < n; ++i) { 38 | std::cout << "b[" << i << "]: " << b[i] << '\n'; 39 | } 40 | //] 41 | 42 | //[print Array is converted to its initial pointer 43 | std::cout << "b: " << b << '\n'; 44 | std::cout << "&b: " << &b << '\n'; 45 | std::cout << "b[0]: " << b[0] << '\n'; 46 | std::cout << "&b[0]: " << &b[0] << '\n'; 47 | //] 48 | 49 | //[print_sequence Array addresses are sequential 50 | std::cout << "b[1]: " << b[1] << '\n'; 51 | std::cout << "&b[1]: " << &b[1] << '\n'; 52 | std::cout << "b[2]: " << b[2] << '\n'; 53 | std::cout << "&b[2]: " << &b[2] << '\n'; 54 | //] 55 | 56 | //[string_array Raw strings are just arrays of chars 57 | char c[] = { 'a', 'b', 't', '\0' }; 58 | // same as: 59 | char d[] = "abt"; 60 | //] 61 | 62 | //[string_cout Raw strings are streamed until '\0' is found 63 | std::cout << "c: " << c << '\n'; 64 | std::cout << "d: " << d << '\n'; 65 | //] 66 | 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /snippets/basic_types/strings.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | //[headers Headers 4 | #include 5 | //] 6 | 7 | int main() { 8 | //[construct Create string 9 | // Strings are dynamic arrays of chars 10 | std::string str = "avocado"; 11 | //] 12 | 13 | //[print Print the whole string 14 | std::cout << str << '\n'; 15 | //] 16 | 17 | //[print_chars Iterate the string chars 18 | for (size_t i = 0; i < str.size(); ++i) { 19 | std::cout << "str[" << i << "]: " << str[i] << '\n'; 20 | } 21 | //] 22 | 23 | //[access Access index 24 | if (str.size() >= 10) { 25 | std::cout << "str[10]: " << str[10] << '\n'; 26 | } else { 27 | std::cout << "str[10]: (does not exist)" << '\n'; 28 | } 29 | //] 30 | 31 | //[member Container functions 32 | std::cout << "str.size(): " << str.size() << '\n'; 33 | std::cout << "str.empty(): " << str.empty() << '\n'; 34 | std::cout << "str.front(): " << str.front() << '\n'; 35 | std::cout << "str.back(): " << str.back() << '\n'; 36 | //] 37 | 38 | //[access_address Contiguous addresses (like any array) 39 | std::cout << "&str: " << &str << '\n'; 40 | std::cout << "str.data(): " << str.data() << '\n'; 41 | //] 42 | 43 | //[subscript The subscript operator accesses a single char 44 | std::cout << "str[0]: " << str[0] << '\n'; 45 | std::cout << "str[1]: " << str[1] << '\n'; 46 | std::cout << "str[2]: " << str[2] << '\n'; 47 | //] 48 | 49 | //[position The address of a `char` prints from that position 50 | std::cout << "&str[0]: " << &str[0] << '\n'; 51 | std::cout << "&str[1]: " << &str[1] << '\n'; 52 | std::cout << "&str[2]: " << &str[2] << '\n'; 53 | //] 54 | 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /snippets/basic_types/struct.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | struct product { 6 | std::string name; 7 | double weight; 8 | double price; 9 | }; 10 | 11 | int main() { 12 | 13 | 14 | product apple; 15 | 16 | apple.name = "Apple X"; 17 | apple.price = 2.4; 18 | apple.weight = 7.8; 19 | 20 | std::cout << "sizeof(product): " << sizeof(product) << " bytes\n"; 21 | std::cout << "sizeof(double): " << sizeof(double) << " bytes\n"; 22 | std::cout << "sizeof(std::string): " << sizeof(std::string) << " bytes\n"; 23 | 24 | std::array ps; 25 | for (size_t i = 0; i < ps.size(); ++i) { 26 | ps[i].name = "Apple X"; 27 | ps[i].price = 2.4 + i; 28 | ps[i].weight = 7.8 + i; 29 | } 30 | 31 | for (auto &p : ps) { 32 | std::cout << p.name << std::endl; 33 | std::cout << p.price << std::endl; 34 | std::cout << p.weight << std::endl; 35 | } 36 | 37 | product *cheapest = &ps[0]; 38 | for (size_t i = 1; i < ps.size(); ++i) { 39 | std::cout << "cheapest->name: " << cheapest->name << '\n'; 40 | std::cout << "(*cheapest).name: " << (*cheapest).name << '\n'; 41 | if (ps[i].price < cheapest->price) { 42 | cheapest = &ps[i]; 43 | } 44 | } 45 | 46 | return 0; 47 | } -------------------------------------------------------------------------------- /snippets/basic_types/vectors.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | //[headers Headers 4 | #include 5 | //] 6 | #include 7 | 8 | int main() { 9 | //[declare Dynamic size vector 10 | std::vector v = {1, 2, 3}; 11 | //] 12 | 13 | //[iter Iterate vector elements 14 | for (size_t i = 0; i < v.size(); ++i) { 15 | std::cout << "v[" << i << "]: " << v[i] << '\n'; 16 | } 17 | //] 18 | 19 | //[member Member functions 20 | std::cout << "v.size(): " << v.size() << '\n'; 21 | std::cout << "v.empty(): " << v.empty() << '\n'; 22 | std::cout << "v.front(): " << v.front() << '\n'; 23 | std::cout << "v.back(): " << v.back() << '\n'; 24 | //] 25 | 26 | //[addresses Access addresses 27 | std::cout << "&v: " << &v << '\n'; 28 | std::cout << "&v[0]: " << &v[0] << '\n'; 29 | std::cout << "&v[1]: " << &v[1] << '\n'; 30 | std::cout << "&v[2]: " << &v[2] << '\n'; 31 | //] 32 | 33 | //[iter Iterators 34 | auto it = v.begin(); 35 | std::cout << *it << '\n'; 36 | //] 37 | 38 | //[modify Modify vector 39 | v.push_back(5); 40 | //] 41 | 42 | //[get Underlying array 43 | // We might still need the underlying raw array to interact with old code 44 | std::cout << "Underlying raw vector: " << v.data() << '\n'; 45 | //] 46 | 47 | //[sizeof Vector inline size 48 | // vector has no fixed size in bytes 49 | // sizeof(v) has only the size of the pointers to manage v 50 | std::cout << "sizeof(v): " << sizeof(v) << '\n'; 51 | //] 52 | 53 | //[multidim Multidimensional vector 54 | std::vector> matrix(10, std::vector(3, 0)); 55 | for (size_t i = 0; i < matrix.size(); ++i) { 56 | for (size_t j = 0; j < matrix[i].size(); ++j) { 57 | matrix[i][j] = 0.5 * i + 0.8 * j; 58 | } 59 | } 60 | //] 61 | 62 | //[multidim_range Multidimensional range-based loops 63 | for (const auto &row : matrix) { 64 | double sum = 0.; 65 | for (const auto &col : row) { 66 | sum += col; 67 | } 68 | std::cout << "Row average " << sum / row.size() << '\n'; 69 | } 70 | //] 71 | 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /snippets/control_flow/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(sequential sequential.cpp) 2 | 3 | add_executable(conditional conditional.cpp) 4 | 5 | add_executable(loops loops.cpp) 6 | 7 | add_executable(scopes scopes.cpp) 8 | 9 | 10 | -------------------------------------------------------------------------------- /snippets/control_flow/scopes.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | //[scopes External and internal scopes 5 | int x = 1; 6 | std::cout << "External x: " << x << '\n'; 7 | for (int i = 0; i < 2; ++i) { 8 | int y = 2; 9 | std::cout << "Internal i: " << i << '\n'; 10 | std::cout << "External x: " << x << '\n'; 11 | std::cout << "Internal y: " << y << '\n'; 12 | } 13 | std::cout << "External x: " << x << '\n'; 14 | //] 15 | 16 | //[fail Variables outside their scope 17 | // This won't work: 18 | // std::cout << "Internal i: " << i << '\n'; 19 | // std::cout << "Internal y: " << y << '\n'; 20 | //] 21 | return 0; 22 | } -------------------------------------------------------------------------------- /snippets/control_flow/sequential.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | int main() { 5 | 6 | 7 | //[values Store and output values 8 | double l = 4; 9 | double area = l * l; 10 | std::cout << "Area: " << area << '\n'; 11 | //] 12 | 13 | //[values Store and output expressions 14 | double height = 1.90; 15 | double weight = 90; 16 | std::cout << "BMI: " << weight / (height * height) << '\n'; 17 | //] 18 | 19 | //[values Calculate and output expressions 20 | int a = 4; 21 | int b = 7; 22 | int fx = (b * b * b + a * b) - 2 * b + a % b; 23 | std::cout << "f(x) = " << fx << '\n'; 24 | //] 25 | 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /snippets/data_structures/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Data structures 2 | add_executable(sequence_containers sequence_containers.cpp) 3 | 4 | add_executable(associative_containers associative_containers.cpp) 5 | 6 | add_executable(container_adapters container_adapters.cpp) 7 | 8 | #[pmr CMakeLists.txt 9 | find_package(PMR) 10 | if (PMR_FOUND) 11 | add_executable(memory_resource memory_resources.cpp) 12 | else () 13 | message("Your compiler does not support *PMR* yet") 14 | endif () 15 | #] 16 | 17 | #[span CMakeLists.txt 18 | add_executable(span span.cpp) 19 | target_compile_features(span PRIVATE cxx_std_20) 20 | #] 21 | 22 | #[bitset CMakeLists.txt 23 | add_executable(bitset bitset.cpp) 24 | #] 25 | 26 | #[pareto CMakeLists.txt 27 | # Set options to not build pareto examples 28 | # - Cache our own BUILD_EXAMPLES var so that pareto 29 | # doesn't mess with it 30 | set(BUILD_MATPLOT_TARGETS OFF CACHE BOOL "" FORCE) 31 | set(BUILD_EXAMPLES_PREV ${BUILD_EXAMPLES}) 32 | set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) 33 | FetchContent_Declare(pareto GIT_REPOSITORY https://github.com/alandefreitas/pareto.git GIT_TAG v1.2.0) 34 | FetchContent_MakeAvailable(pareto) 35 | set(BUILD_EXAMPLES ${BUILD_EXAMPLES_PREV} CACHE BOOL "" FORCE) 36 | add_executable(spatial_containers spatial_containers.cpp) 37 | target_link_libraries(spatial_containers PUBLIC pareto) 38 | #] 39 | 40 | -------------------------------------------------------------------------------- /snippets/data_structures/container_adapters.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int main() { 10 | // Container adapters 11 | std::stack> s; 12 | std::queue> q; 13 | std::priority_queue> p; 14 | 15 | // Print sizes 16 | std::cout << "s.size(): " << s.size() << '\n'; 17 | std::cout << "q.size(): " << q.size() << '\n'; 18 | std::cout << "p.size(): " << p.size() << '\n'; 19 | 20 | // Push back / Append 21 | s.push(6); 22 | q.push(6); 23 | p.push(6); 24 | 25 | std::cout << "s.size(): " << s.size() << '\n'; 26 | std::cout << "q.size(): " << q.size() << '\n'; 27 | std::cout << "p.size(): " << p.size() << '\n'; 28 | 29 | // Top 30 | std::cout << "s.top(): " << s.top() << '\n'; 31 | std::cout << "p.top(): " << p.top() << '\n'; 32 | 33 | // Front/Back 34 | std::cout << "q.front(): " << q.front() << '\n'; 35 | std::cout << "q.back(): " << q.back() << '\n'; 36 | 37 | // Pop element 38 | s.pop(); 39 | q.pop(); 40 | p.pop(); 41 | 42 | std::cout << "s.size(): " << s.size() << '\n'; 43 | std::cout << "q.size(): " << q.size() << '\n'; 44 | std::cout << "p.size(): " << p.size() << '\n'; 45 | 46 | } -------------------------------------------------------------------------------- /snippets/data_structures/memory_resources.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | //[headers Headers 5 | #include 6 | //] 7 | 8 | int main() { 9 | //[buffer Construct a buffer where to allocate memory 10 | char buffer[64] = {}; // a small buffer on the stack 11 | std::fill_n(std::begin(buffer), std::size(buffer) - 1, '_'); 12 | std::cout << buffer << '\n'; 13 | //] 14 | 15 | //[pool Create a memory resource with the buffer 16 | std::pmr::monotonic_buffer_resource pool{std::data(buffer), 17 | std::size(buffer)}; 18 | //] 19 | 20 | //[pmr_vector Create a vector that allocates memory from the pool 21 | std::pmr::vector vec{&pool}; 22 | for (char ch = 'a'; ch <= 'z'; ++ch) { 23 | vec.push_back(ch); 24 | } 25 | std::cout << buffer << '\n'; 26 | //] 27 | 28 | //[pool2 Create a pool for memory allocations and a vector using the pool 29 | std::pmr::unsynchronized_pool_resource pool2; 30 | std::pmr::vector vec2{&pool2}; 31 | for (char ch = 'a'; ch <= 'z'; ++ch) { 32 | vec2.push_back(ch); 33 | } 34 | //] 35 | std::copy(vec2.begin(), vec2.end(), 36 | std::ostream_iterator(std::cout, " ")); 37 | } -------------------------------------------------------------------------------- /snippets/data_structures/span.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | //[headers Headers 6 | #include 7 | //] 8 | 9 | //[slide Slide a span 10 | template 11 | [[nodiscard]] 12 | constexpr auto slide(std::span s, std::size_t offset, std::size_t width) { 13 | return s.subspan(offset, offset + width <= s.size() ? width : 0U); 14 | } 15 | //] 16 | 17 | //[starts_with Check if span starts_with the specified prefix 18 | template 19 | [[nodiscard]] 20 | constexpr bool starts_with(std::span data, std::span prefix) { 21 | return data.size() >= prefix.size() 22 | && std::equal(prefix.begin(), prefix.end(), data.begin()); 23 | } 24 | //] 25 | 26 | //[ends_with Check if span ends_with the specified suffix 27 | template 28 | [[nodiscard]] 29 | constexpr bool ends_with(std::span data, std::span suffix) { 30 | return data.size() >= suffix.size() 31 | && std::equal(data.end() - suffix.size(), data.end(), 32 | suffix.end() - suffix.size()); 33 | } 34 | //] 35 | 36 | //[contains Check if span contains the specified element 37 | template 38 | [[nodiscard]] 39 | constexpr bool contains(std::span span, std::span sub) { 40 | return std::search(span.begin(), span.end(), sub.begin(), sub.end()) 41 | != span.end(); 42 | } 43 | //] 44 | 45 | void print(const auto &seq) { 46 | for (const auto &elem : seq) std::cout << elem << ' '; 47 | std::cout << '\n'; 48 | } 49 | 50 | int main() { 51 | //[construct Construct two arrays 52 | constexpr int a[]{0, 1, 2, 3, 4, 5, 6, 7, 8}; 53 | constexpr int b[]{8, 7, 6}; 54 | //] 55 | 56 | //[print Slide spans 57 | for (std::size_t offset{};; ++offset) { 58 | constexpr std::size_t width{6}; 59 | auto s = slide(std::span{a}, offset, width); 60 | if (s.empty()) 61 | break; 62 | print(s); 63 | } 64 | //] 65 | 66 | //[use_fn Check span properties at compile time 67 | static_assert(starts_with(std::span{a}, std::span{a, 4}) 68 | && starts_with(std::span{a + 1, 4}, std::span{a + 1, 3}) 69 | && !starts_with(std::span{a}, std::span{b}) 70 | && !starts_with(std::span{a, 8}, std::span{a + 1, 3}) 71 | && ends_with(std::span{a}, std::span{a + 6, 3}) 72 | && !ends_with(std::span{a}, std::span{a + 6, 2}) 73 | && contains(std::span{a}, std::span{a + 1, 4}) 74 | && !contains(std::span{a, 8}, std::span{a, 9})); 75 | //] 76 | } -------------------------------------------------------------------------------- /snippets/data_structures/spatial_containers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | //[headers Headers 3 | #include 4 | //] 5 | 6 | int main() { 7 | //[construct Construct map 8 | // Unlike a map>, which represents a disjunction of indexes, 9 | // a spatial map represents a conjunction of indexes. 10 | pareto::spatial_map m; 11 | //] 12 | 13 | //[insert Inserting 14 | m(-2.5, -1.5) = 17; 15 | m(-2.1, -0.5) = 32; 16 | m(-1.6, 0.9) = 36; 17 | m(-0.6, 0.9) = 13; 18 | m(-0.5, 0.8) = 32; 19 | //] 20 | 21 | //[query Querying nearest 22 | std::cout << "Closest elements to [0, 0]:" << std::endl; 23 | for (auto it = m.find_nearest({0.,0.}, 2); it != m.end(); ++it) { 24 | std::cout << it->first << ": " << it->second << std::endl; 25 | } 26 | //] 27 | 28 | //[intersection Querying intersection 29 | std::cout << "Elements between [-1, -1] and [+1, +1]:" << std::endl; 30 | for (auto it = m.find_intersection({-1.,-1.}, {+1, +1}); it != m.end(); ++it) { 31 | std::cout << it->first << ": " << it->second << std::endl; 32 | } 33 | //] 34 | } -------------------------------------------------------------------------------- /snippets/data_types/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(data_types data_types.cpp) 2 | 3 | add_executable(operators operators.cpp) 4 | 5 | add_executable(auto auto.cpp) 6 | 7 | add_executable(constants constants.cpp) 8 | -------------------------------------------------------------------------------- /snippets/data_types/auto.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | //[auto_pod Auto for fundamental data types 6 | auto dont_do_that = 87; 7 | std::cout << "dont_do_that: " << dont_do_that << '\n'; 8 | //] 9 | 10 | //[container Creating a hash table for the next snippet 11 | std::unordered_map t; 12 | t["zero"] = 0.0; 13 | t["pi"] = 3.14; 14 | t["ten"] = 10.0; 15 | //] 16 | 17 | //[no_auto Accessing container without `auto` 18 | // NOLINTNEXTLINE(modernize-use-auto) 19 | std::unordered_map::iterator it = t.find("pi"); 20 | if (it != t.end()) { 21 | std::cout << it->first << ": " << it->second << '\n'; 22 | } 23 | //] 24 | 25 | //[with_auto Accessing container with `auto` 26 | // This is the perfect place for auto 27 | // - It avoids a long type name 28 | // - There's no ambiguity 29 | // - Find will always return an iterator 30 | auto it2 = t.find("zero"); 31 | if (it2 != t.end()) { 32 | std::cout << it2->first << ": " << it2->second << '\n'; 33 | } 34 | //] 35 | 36 | //[decltype Get type from another variable 37 | decltype(it) it3; 38 | it3 = it; 39 | ++it3; 40 | if (it3 != t.end()) { 41 | std::cout << it3->first << ": " << it3->second << '\n'; 42 | } 43 | //] 44 | 45 | //[functions `auto` in generic functions 46 | auto print_map_container = [](const auto &m) { 47 | for (auto &&item : m) { 48 | std::cout << item.first << ": " << item.second << '\n'; 49 | } 50 | }; 51 | print_map_container(t); 52 | //] 53 | 54 | return 0; 55 | } -------------------------------------------------------------------------------- /snippets/data_types/constants.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | //[mutable Mutable variable 6 | int a = 2; 7 | a = 3; 8 | std::cout << "a : " << a << '\n'; 9 | //] 10 | 11 | //[const Constants as a promise 12 | const int b = 3; 13 | // b = 4; <- this fails. `b` is constant. 14 | std::cout << "b : " << b << '\n'; 15 | //] 16 | 17 | //[const_2 `const` from mutable value 18 | // `b2` can be initialized with any value, but cannot be changed after this. 19 | // This is possible, but makes it impossible to know b2 in compile-time. 20 | const int b2 = a; 21 | std::cout << "b2 : " << b2 << '\n'; 22 | //] 23 | 24 | //[constexpr Constant "more constant than const" 25 | // `c` can only use values available at compile-time 26 | // `c` cannot be initialized with a mutable value 27 | constexpr int c = 4; 28 | std::cout << "c : " << c << '\n'; 29 | //] 30 | 31 | //[constexpr `constexpr` from mutable value 32 | // Impossible, we wouldn't know c2 in compile-time. 33 | // constexpr int c2 = a; 34 | //] 35 | 36 | 37 | //[array Creating arrays from mutable value 38 | // The compiler needs to know the size at compile time 39 | // Impossible: 40 | // std::array v1; 41 | //] 42 | 43 | //[array_2 Creating arrays from compile-time `const` values 44 | // Sometimes possible, if b was not initialized with a mutable value 45 | std::array v2 = {5, 6, 5}; 46 | std::cout << "v2.size(): " << v2.size() << '\n'; 47 | //] 48 | 49 | //[array_3 Creating arrays from runtime `const` values 50 | // Impossible (b2 depends on a variable): 51 | // std::array v2b; 52 | //] 53 | 54 | //[array_4 Creating arrays from compile-time `constexpr` values 55 | // Always possible 56 | std::array v3 = {7, 8, 7, 8}; 57 | std::cout << "v3.size(): " << v3.size() << '\n'; 58 | //] 59 | 60 | return 0; 61 | } -------------------------------------------------------------------------------- /snippets/data_types/operators.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | 6 | 7 | //[operators Operators 8 | int n1 = 8; 9 | int n2 = 3; 10 | std::cout << n1 << " + " << n2 << ": " << n1 + n2 << '\n'; 11 | std::cout << n1 << " - " << n2 << ": " << n1 - n2 << '\n'; 12 | std::cout << n1 << " * " << n2 << ": " << n1 * n2 << '\n'; 13 | std::cout << n1 << " / " << n2 << ": " << n1 / n2 << '\n'; 14 | std::cout << n1 << " % " << n2 << ": " << n1 % n2 << '\n'; 15 | //] 16 | 17 | //[float Operators for floating point types 18 | double n3 = 8.; 19 | double n4 = 3.; 20 | std::cout << n3 << " + " << n4 << ": " << n3 + n4 << '\n'; 21 | std::cout << n3 << " - " << n4 << ": " << n3 - n4 << '\n'; 22 | std::cout << n3 << " * " << n4 << ": " << n3 * n4 << '\n'; 23 | std::cout << n3 << " / " << n4 << ": " << n3 / n4 << '\n'; 24 | //] 25 | 26 | //[fmod There is no % for floating point types 27 | std::cout << "fmod(" << n3 << ", " << n4 << "): " << fmod(n3, n4) << '\n'; 28 | // This won't work: std::cout << n3 << " % " << n4 << ": " << n3 % n4 << '\n'; 29 | //] 30 | 31 | //[assign Attribution operator 32 | n1 += n2; // n1 = n1 + n2; 33 | std::cout << "n1 after += is " << n1 << '\n'; 34 | n1 -= n2; 35 | std::cout << "n1 after -= is " << n1 << '\n'; 36 | n1 *= n2; 37 | std::cout << "n1 after *= is " << n1 << '\n'; 38 | n1 /= n2; 39 | std::cout << "n1 after /= is " << n1 << '\n'; 40 | n1 %= n2; 41 | std::cout << "n1 after %= is " << n1 << '\n'; 42 | //] 43 | 44 | //[postfix Postfixed increment/decrement 45 | n1++; // or n1 += 1; // or n1 = n1 + 1; 46 | std::cout << "n1 after ++ is " << n1 << '\n'; 47 | n1--; 48 | std::cout << "n1 after -- is " << n1 << '\n'; 49 | //] 50 | 51 | //[prefix Prefixed increment 52 | // same as n1 += 1; // or n1 = n1 + 1; 53 | ++n1; 54 | std::cout << "n1 after ++ is " << n1 << '\n'; 55 | //] 56 | 57 | //[predecrement Prefixed decrement 58 | // same as n1 -= 1; // or n1 = n1 - 1; 59 | --n1; 60 | std::cout << "n1 after -- is " << n1 << '\n'; 61 | //] 62 | 63 | //[postexpr Postfixed inside an expression: use and increment 64 | std::cout << "n1: " << n1++ << '\n'; 65 | //] 66 | 67 | //[preexpr Prefixed inside an expression: increment and use 68 | std::cout << "n1: " << ++n1 << '\n'; 69 | //] 70 | 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /snippets/datetime/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(clock clock.cpp) 2 | 3 | #[datetime Find datetime library 4 | find_package(Date QUIET) 5 | if (NOT Date_FOUND) 6 | # Find Threads library 7 | find_package(Threads) 8 | 9 | # Find Curl (to download timezone database) 10 | find_package(CURL QUIET) 11 | if (NOT CURL_FOUND) 12 | set(USE_SYSTEM_TZ_DB ON CACHE BOOL "Build tz library" FORCE) 13 | else () 14 | set(USE_SYSTEM_TZ_DB OFF CACHE BOOL "Build tz library" FORCE) 15 | endif () 16 | message("USE_SYSTEM_TZ_DB=${USE_SYSTEM_TZ_DB}") 17 | set(BUILD_TZ_LIB ON CACHE BOOL "Build tz library" FORCE) 18 | 19 | # Fetch date library 20 | FetchContent_Declare(date GIT_REPOSITORY https://github.com/HowardHinnant/date.git GIT_TAG v3.0.1) 21 | FetchContent_MakeAvailable(date) 22 | endif () 23 | 24 | # Link library 25 | add_executable(datetime datetime.cpp) 26 | target_link_libraries(datetime date::date date::date-tz) 27 | #] -------------------------------------------------------------------------------- /snippets/files/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(files files.cpp) 2 | 3 | #[find_filesystem Find package 4 | # Use CMake script to identify if Filesystem library is available 5 | # This will look for the headers or 6 | # See CMake Functions 7 | find_package(Filesystem) 8 | #] 9 | 10 | #[find_boost_filesystem Find boost.filesystem if C++17 is not available 11 | # See https://cmake.org/cmake/help/latest/module/FindBoost.html 12 | if (NOT Filesystem_FOUND) 13 | find_package(Boost COMPONENTS filesystem) 14 | endif() 15 | #] 16 | 17 | #[link_filesystem Use C++17 filesystem or Boost.Filesystem 18 | add_executable(filesystem_manage filesystem.cpp) 19 | if (Filesystem_FOUND) 20 | target_link_libraries(filesystem_manage PRIVATE std::filesystem) 21 | target_compile_definitions(filesystem_manage PRIVATE -DCXX_FILESYSTEM_HEADER=<${CXX_FILESYSTEM_HEADER}>) 22 | target_compile_definitions(filesystem_manage PRIVATE -DCXX_FILESYSTEM_NAMESPACE=${CXX_FILESYSTEM_NAMESPACE}) 23 | elseif(Boost_FOUND) 24 | target_link_libraries(filesystem_manage PRIVATE Boost::filesystem) 25 | target_compile_definitions(filesystem_manage PRIVATE -DCXX_FILESYSTEM_HEADER=) 26 | target_compile_definitions(filesystem_manage PRIVATE -DCXX_FILESYSTEM_NAMESPACE=boost::filesystem) 27 | endif() 28 | #] -------------------------------------------------------------------------------- /snippets/files/files.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | int main() { 12 | //[vector_number Create a vector of numbers 13 | std::vector numbers; 14 | constexpr size_t n = 15; 15 | numbers.resize(n); 16 | for (size_t i = 0; i < n; ++i) { 17 | numbers[i] = i * 1000 + 1; 18 | } 19 | //] 20 | 21 | //[save Save numbers in text file 22 | std::ofstream fout("numbers.txt"); 23 | for (int number : numbers) { 24 | fout << number << " "; 25 | } 26 | fout.close(); 27 | //] 28 | 29 | //[load Load numbers from text file 30 | std::vector m_numbers; 31 | std::ifstream fin("numbers.txt"); 32 | do { 33 | int x; 34 | fin >> x; 35 | if (fin) { 36 | m_numbers.emplace_back(x); 37 | } 38 | } while (fin); 39 | fin.close(); 40 | //] 41 | 42 | //[print Print numbers from file 43 | for (const auto &number : numbers) { 44 | std::cout << number << " "; 45 | } 46 | std::cout << '\n'; 47 | for (const auto &number : m_numbers) { 48 | std::cout << number << " "; 49 | } 50 | std::cout << '\n'; 51 | //] 52 | 53 | //[save_binary Save numbers in binary file 54 | fout.open("numbers.bin", std::ios::binary); 55 | for (int &number : numbers) { 56 | char *pointer_to_number = (char *)&number; 57 | size_t bytes_per_number = sizeof(number); 58 | fout.write(pointer_to_number, bytes_per_number); 59 | } 60 | fout.close(); 61 | //] 62 | 63 | //[load_binary Load numbers from binary file 64 | m_numbers.clear(); 65 | fin.open("numbers.bin", std::ios::binary); 66 | for (size_t i = 0; i < numbers.size(); ++i) { 67 | int x; 68 | char *pointer_to_number = (char *)&x; 69 | size_t bytes_per_number = sizeof(x); 70 | fin.read(pointer_to_number, bytes_per_number); 71 | m_numbers.emplace_back(x); 72 | } 73 | fin.close(); 74 | //] 75 | 76 | //[print Print numbers from binary file 77 | for_each(numbers.begin(), numbers.end(), 78 | [](auto x) { std::cout << x << " "; }); 79 | std::cout << '\n'; 80 | for_each(m_numbers.begin(), m_numbers.end(), 81 | [](auto x) { std::cout << x << " "; }); 82 | std::cout << '\n'; 83 | //] 84 | 85 | //[filesize Compare file sizes 86 | std::cout << "File size (text): " 87 | << std::filesystem::file_size("numbers.txt") << " bytes\n"; 88 | std::cout << "File size (binary): " 89 | << std::filesystem::file_size("numbers.bin") << " bytes\n"; 90 | //] 91 | 92 | return 0; 93 | } -------------------------------------------------------------------------------- /snippets/functions/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(functions functions.cpp) 2 | 3 | add_executable(lambda lambda.cpp) -------------------------------------------------------------------------------- /snippets/gui/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(qt) 2 | 3 | add_subdirectory(webview) 4 | 5 | add_subdirectory(opengl) 6 | 7 | add_subdirectory(imgui) 8 | 9 | add_subdirectory(tray) -------------------------------------------------------------------------------- /snippets/gui/imgui/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #[find_opengl Find OpenGL 2 | find_package(OpenGL) 3 | #] 4 | if (NOT OPENGL_FOUND OR NOT EXPECTED_COMPILER) 5 | return() 6 | endif () 7 | 8 | if (CMAKE_SYSTEM_NAME STREQUAL Linux) 9 | find_package(X11 REQUIRED) 10 | if (NOT X11_Xi_FOUND) 11 | message(FATAL_ERROR "X11 Xi library is required") 12 | endif () 13 | endif () 14 | 15 | if (NOT TARGET glad AND EXPECTED_COMPILER) 16 | #[fetch_glad Fetch GLAD 17 | FetchContent_Declare(glad GIT_REPOSITORY https://github.com/Dav1dde/glad.git GIT_TAG df8e9e16110b305479a875399cee13daa0ccadd9) 18 | FetchContent_MakeAvailable(glad) 19 | #] 20 | endif () 21 | 22 | if (NOT TARGET glfw AND EXPECTED_COMPILER) 23 | #[fetch_glfw Fetch GLFW 24 | set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE) 25 | set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) 26 | set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE) 27 | set(GLFW_INSTALL OFF CACHE BOOL "" FORCE) 28 | FetchContent_Declare(glfw GIT_REPOSITORY https://github.com/glfw/glfw.git GIT_TAG 3.3.2) 29 | FetchContent_MakeAvailable(glfw) 30 | #] 31 | if (MSVC) 32 | # target_compile_options(glfw PRIVATE /Wno-pedantic) 33 | else () 34 | target_compile_options(glfw PRIVATE -Wno-pedantic -Wno-missing-field-initializers -Wno-unused-parameter) 35 | endif () 36 | endif () 37 | 38 | set(GLFW_INSTALL OFF CACHE BOOL "" FORCE) 39 | 40 | #[fetch_imgui Fetch ImGUI 41 | FetchContent_Declare( 42 | imgui 43 | GIT_REPOSITORY https://github.com/ocornut/imgui.git 44 | GIT_TAG v1.77 45 | ) 46 | FetchContent_GetProperties(imgui) 47 | if (NOT imgui_POPULATED) 48 | FetchContent_Populate(imgui) 49 | set(IMGUI_INCLUDE_DIR ${imgui_SOURCE_DIR}/) 50 | file(GLOB IMGUI_SOURCES ${imgui_SOURCE_DIR}/*.cpp) 51 | file(GLOB IMGUI_HEADERS ${imgui_SOURCE_DIR}/*.h) 52 | add_library(imgui STATIC ${IMGUI_SOURCES} ${IMGUI_SOURCES} ${imgui_SOURCE_DIR}/examples/imgui_impl_glfw.cpp ${imgui_SOURCE_DIR}/examples/imgui_impl_opengl3.cpp) 53 | add_definitions(-DIMGUI_IMPL_OPENGL_LOADER_GLAD) 54 | #] 55 | #[link_imgui Link ImGUI 56 | target_include_directories(imgui PUBLIC ${IMGUI_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR} ${GLFW_INCLUDE_DIR} ${GLAD_INCLUDE_DIR}) 57 | target_link_libraries(imgui ${OPENGL_LIBRARIES} glfw glad) 58 | endif () 59 | #] 60 | 61 | if (EXPECTED_COMPILER) 62 | add_executable(imgui_hello imgui_hello.cpp) 63 | target_link_libraries(imgui_hello PUBLIC imgui) 64 | endif () -------------------------------------------------------------------------------- /snippets/gui/opengl/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(glfw) 2 | add_subdirectory(sdl) -------------------------------------------------------------------------------- /snippets/gui/opengl/glfw/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #[find_opengl Find OpenGL 2 | find_package(OpenGL) 3 | #] 4 | if (NOT OPENGL_FOUND OR NOT EXPECTED_COMPILER) 5 | return() 6 | endif () 7 | 8 | if (NOT TARGET glad AND EXPECTED_COMPILER) 9 | #[fetch_glad Fetch GLAD 10 | FetchContent_Declare(glad GIT_REPOSITORY https://github.com/Dav1dde/glad.git GIT_TAG df8e9e16110b305479a875399cee13daa0ccadd9) 11 | FetchContent_MakeAvailable(glad) 12 | #] 13 | endif () 14 | 15 | if (NOT TARGET glfw AND EXPECTED_COMPILER) 16 | #[fetch_glfw Fetch GLFW 17 | set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE) 18 | set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) 19 | set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE) 20 | set(GLFW_INSTALL OFF CACHE BOOL "" FORCE) 21 | FetchContent_Declare(glfw GIT_REPOSITORY https://github.com/glfw/glfw.git GIT_TAG 3.3.2) 22 | FetchContent_MakeAvailable(glfw) 23 | #] 24 | if (MSVC) 25 | # target_compile_options(glfw PUBLIC /Wno-pedantic) 26 | else () 27 | target_compile_options(glfw PRIVATE -Wno-pedantic -Wno-missing-field-initializers -Wno-unused-parameter) 28 | endif () 29 | endif () 30 | 31 | if (EXPECTED_COMPILER) 32 | #[link_glfw Link GLFW 33 | add_executable(opengl_hello opengl_hello.cpp) 34 | target_link_libraries(opengl_hello PUBLIC glad glfw) 35 | #] 36 | endif () -------------------------------------------------------------------------------- /snippets/gui/opengl/sdl/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if (NOT EXPECTED_COMPILER) 2 | return() 3 | endif () 4 | 5 | #[find_sdl Find SDL 6 | find_package(SDL2 QUIET) 7 | #] 8 | if (NOT SDL2_FOUND) 9 | return() 10 | endif () 11 | 12 | #[find_glad Find GLAD 13 | if (SDL2_FOUND) 14 | if (NOT TARGET glad AND EXPECTED_COMPILER) 15 | FetchContent_Declare(glad GIT_REPOSITORY https://github.com/Dav1dde/glad.git GIT_TAG df8e9e16110b305479a875399cee13daa0ccadd9) 16 | FetchContent_MakeAvailable(glad) 17 | endif () 18 | #] 19 | 20 | #[add_executable Link SDL 21 | if (SDL2_FOUND AND EXPECTED_COMPILER) 22 | add_executable(sdl_hello sdl_hello.cpp) 23 | target_link_libraries(sdl_hello PUBLIC ${SDL2_LIBRARIES} glad) 24 | target_include_directories(sdl_hello PRIVATE ${SDL2_INCLUDE_DIRS}) 25 | endif () 26 | endif () 27 | #] -------------------------------------------------------------------------------- /snippets/gui/qt/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Try to add Qt path to CMAKE_PREFIX_PATH 2 | add_qt_to_cmake_paths() 3 | 4 | # If we still don't have a CMAKE_PREFIX_PATH 5 | #[throw Show message if Qt5Widgets_DIR is not set 6 | if (NOT CMAKE_PREFIX_PATH AND NOT Qt5Widgets_DIR) 7 | message("CMAKE_PREFIX_PATH is not defined, you may need to set it " 8 | "(-DCMAKE_PREFIX_PATH=\"path/to/Qt/lib/cmake\" or -DCMAKE_PREFIX_PATH=/usr/include/{host}/qt{version}/ on Ubuntu)") 9 | 10 | message("CMAKE_PREFIX_PATH is not defined." 11 | "find_package(Qt5) is probably not going to work. " 12 | " Set the CMAKE_PREFIX_PATH environment variable to the install prefix of Qt 5" 13 | " - Set it in the command line as -DCMAKE_PREFIX_PATH=\"path/to/Qt5/lib/cmake\"" 14 | " - Or set it in your build script with set(CMAKE_PREFIX_PATH path/to/Qt5/lib/cmake)") 15 | endif () 16 | #] 17 | 18 | #[find Find Qt 19 | find_package(Qt5 COMPONENTS Widgets QUIET) 20 | #] 21 | if (NOT Qt5_FOUND) 22 | return() 23 | endif () 24 | 25 | #[enable_moc Enable MOC 26 | set(CMAKE_AUTOMOC ON) 27 | set(CMAKE_AUTORCC ON) 28 | set(CMAKE_AUTOUIC ON) 29 | #] 30 | 31 | #[link_qt Link Qt 32 | add_executable(qt_helloworld qt_hello.cpp) 33 | target_link_libraries(qt_helloworld Qt5::Widgets) 34 | #] 35 | 36 | #[disable_moc Disable MOC 37 | set(CMAKE_AUTOMOC OFF) 38 | set(CMAKE_AUTORCC OFF) 39 | set(CMAKE_AUTOUIC OFF) 40 | #] -------------------------------------------------------------------------------- /snippets/gui/qt/qt_hello.cpp: -------------------------------------------------------------------------------- 1 | //[headers Headers 2 | #include 3 | #include 4 | //] 5 | #include 6 | 7 | int main(int argc, char **argv) { 8 | //[QApplication Create Qt Application 9 | QApplication app(argc, argv); 10 | //] 11 | 12 | //[windows Create window 13 | QWidget window; 14 | window.setFixedSize(100, 80); 15 | //] 16 | 17 | //[button Create button and attach to window 18 | auto *buttonInfo = new QPushButton("Info", &window); 19 | buttonInfo->setGeometry(10, 10, 80, 30); 20 | //] 21 | 22 | //[button_cb Set button callback 23 | QApplication::connect(buttonInfo, &QPushButton::clicked, 24 | [] { std::cout << "Info" << std::endl; }); 25 | //] 26 | 27 | //[button_quit Create quit button 28 | auto *buttonQuit = new QPushButton("Quit", &window); 29 | buttonQuit->setGeometry(10, 40, 80, 30); 30 | //] 31 | 32 | //[button_quit_cb Set quit button callback 33 | QApplication::connect(buttonQuit, &QPushButton::clicked, 34 | [] { QApplication::quit(); }); 35 | //] 36 | 37 | //[run Run application 38 | window.show(); 39 | return app.exec(); 40 | //] 41 | } -------------------------------------------------------------------------------- /snippets/gui/tray/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This hasn't been tested on all OSs 2 | if (NOT APPLE OR NOT EXPECTED_COMPILER) 3 | return() 4 | endif () 5 | 6 | 7 | # Library: https://github.com/zserge/tray 8 | # Patch: https://github.com/wormyrocks/tray 9 | # - GUIs with system tray_ icons are great for deamons 10 | # - This is a C99 library that seems to be abandoned 11 | # - wormyrocks/tray includes a patch fixing some issues 12 | # - So far, there is no good C++ library for the same task 13 | # - The library is quite simple though 14 | # - This can serve as inspiration for a C++ implementation 15 | #[fetch_tray Fetch tray library 16 | FetchContent_Declare( 17 | tray 18 | GIT_REPOSITORY https://github.com/wormyrocks/tray.git 19 | GIT_TAG 3e4a1447bff413e6907c5e43ac8d65e36866fdfd 20 | ) 21 | FetchContent_GetProperties(tray) 22 | #] 23 | #[tray_target Create tray target 24 | if (NOT tray_POPULATED) 25 | FetchContent_Populate(tray) 26 | add_library(tray INTERFACE) 27 | target_sources(tray INTERFACE ${tray_SOURCE_DIR}/tray.h) 28 | target_include_directories(tray INTERFACE ${tray_SOURCE_DIR}) 29 | if (WIN32) 30 | target_compile_definitions(tray INTERFACE TRAY_WINAPI) 31 | elseif (APPLE) 32 | target_compile_definitions(tray INTERFACE TRAY_APPKIT) 33 | target_link_libraries(tray INTERFACE "-framework Cocoa") 34 | # Some warnings the library doesn't deal with 35 | target_compile_options(tray INTERFACE -Wno-unused-parameter) 36 | target_compile_options(tray INTERFACE -Wno-unused-variable) 37 | target_compile_options(tray INTERFACE -Wno-writable-strings) 38 | target_compile_options(tray INTERFACE -Wno-misleading-indentation) 39 | elseif (UNIX) 40 | target_compile_definitions(tray INTERFACE TRAY_APPINDICATOR) 41 | target_link_libraries(tray INTERFACE "$(shell pkg-config --cflags appindicator3-0.1 --libs appindicator3-0.1)") 42 | # Some warnings the library doesn't deal with 43 | target_compile_options(tray INTERFACE -Wno-unused-parameter) 44 | target_compile_options(tray INTERFACE -Wno-unused-variable) 45 | target_compile_options(tray INTERFACE -Wno-writable-strings) 46 | target_compile_options(tray INTERFACE -Wno-misleading-indentation) 47 | endif () 48 | endif () 49 | #] 50 | 51 | #[link Link tray library 52 | add_executable(tray_helloworld tray_hello.cpp) 53 | target_link_libraries(tray_helloworld tray) 54 | #] 55 | 56 | #[icons Copy tray icons 57 | if (WIN32) 58 | file(COPY ${tray_SOURCE_DIR}/icon.ico DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) 59 | elseif (APPLE) 60 | file(COPY ${tray_SOURCE_DIR}/icon.png DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) 61 | endif () 62 | #] -------------------------------------------------------------------------------- /snippets/gui/webview/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This hasn't been tested on all OSs 2 | if (NOT APPLE OR NOT EXPECTED_COMPILER) 3 | return() 4 | endif () 5 | 6 | # Library: https://github.com/zserge/tray 7 | # - Webviews are great for GUIs to work cross-platform 8 | # - They are also great for mobile GUIs 9 | # - So far, there is no good pure C++ library for the same task 10 | # - The C++ interface in this repository is still changing often 11 | # - The library is quite simple though 12 | # - This can serve as inspiration for a C++ implementation 13 | # - There's no CMake build script for this library yet 14 | # - There's a CMake build script in the master branch but 15 | # still does not work for some platforms 16 | #[fetch_webview Fetch webview 17 | FetchContent_Declare( 18 | webview 19 | GIT_REPOSITORY https://github.com/webview/webview.git 20 | GIT_TAG 50e4bcc420abdc7be96a54b7c79934a000b76901 21 | ) 22 | FetchContent_GetProperties(webview) 23 | #] 24 | 25 | #[webview_target Create webview target 26 | if (NOT webview_POPULATED) 27 | # Library does not have a CMake build script 28 | # We have to do it ourselves 29 | FetchContent_Populate(webview) 30 | add_library(webview INTERFACE) 31 | target_sources(webview INTERFACE ${webview_SOURCE_DIR}/webview.h) 32 | target_include_directories(webview INTERFACE ${webview_SOURCE_DIR}) 33 | 34 | # Set compile options 35 | # See: https://github.com/webview/webview/blob/master/script/build.sh 36 | if (WIN32) 37 | target_compile_definitions(webview INTERFACE WEBVIEW_EDGE) 38 | # See: https://github.com/webview/webview/blob/master/script/build.bat 39 | target_link_libraries(webview INTERFACE "-mwindows -L./dll/x64 -lwebview -lWebView2Loader") 40 | # target_compile_options(...) ? 41 | elseif (APPLE) 42 | target_compile_definitions(webview INTERFACE WEBVIEW_COCOA) 43 | target_compile_definitions(webview INTERFACE "GUI_SOURCE_DIR=\"${CMAKE_CURRENT_SOURCE_DIR}\"") 44 | target_compile_options(webview INTERFACE -Wno-all -Wno-extra -Wno-pedantic -Wno-delete-non-abstract-non-virtual-dtor) 45 | target_link_libraries(webview INTERFACE "-framework WebKit") 46 | elseif (UNIX) 47 | target_compile_definitions(webview INTERFACE WEBVIEW_GTK) 48 | target_compile_options(webview INTERFACE -Wall -Wextra -Wpedantic) 49 | target_link_libraries(webview INTERFACE "$(pkg-config --cflags --libs gtk+-3.0 webkit2gtk-4.0)") 50 | endif () 51 | endif () 52 | #] 53 | 54 | #[link Link webview 55 | add_executable(webview_hello webview_hello.cpp) 56 | target_link_libraries(webview_hello PUBLIC webview) 57 | #] -------------------------------------------------------------------------------- /snippets/gui/webview/webview_hello.cpp: -------------------------------------------------------------------------------- 1 | //[headers Headers 2 | #include 3 | //] 4 | 5 | #include 6 | 7 | #ifdef _WIN32 8 | int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 9 | LPSTR lpCmdLine, int nCmdShow) 10 | #else 11 | int main() 12 | #endif 13 | { 14 | //[create Create a webview 15 | webview::webview w(true, nullptr); 16 | w.set_title("Example"); 17 | w.set_size(480, 320, WEBVIEW_HINT_NONE); 18 | w.set_size(180, 120, WEBVIEW_HINT_MIN); 19 | //] 20 | 21 | //[bind_fn Bind javascript function receiving a string 22 | w.bind("noop", [](std::string s) -> std::string { 23 | std::cout << s << std::endl; 24 | return s; 25 | }); 26 | //] 27 | 28 | //[bind_fn_ints Bind javascript function receiving two ints 29 | w.bind("add", [](std::string s) -> std::string { 30 | auto a = std::stoi(webview::json_parse(s, "", 0)); 31 | auto b = std::stoi(webview::json_parse(s, "", 1)); 32 | return std::to_string(a + b); 33 | }); 34 | //] 35 | 36 | //[render Render webview 37 | w.navigate(R"(data:text/html, 38 | 39 | 40 | hello 41 | 52 | 53 | )"); 54 | //] 55 | 56 | //[run Run application 57 | w.run(); 58 | //] 59 | 60 | return 0; 61 | } -------------------------------------------------------------------------------- /snippets/heterogeneous_types/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Heterogeneous data structures 2 | add_executable(tuples tuples.cpp) 3 | 4 | add_executable(variant variant.cpp) 5 | 6 | add_executable(any any.cpp) 7 | 8 | add_executable(optional optional.cpp) 9 | -------------------------------------------------------------------------------- /snippets/heterogeneous_types/any.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() { 7 | std::cout << std::boolalpha; 8 | 9 | //[any `std::any` is a container for single values of any type 10 | // Be careful when using it 11 | std::any a = 1; 12 | //] 13 | 14 | //[accessing_int Accessing values (int) 15 | std::cout << a.type().name() << ": " << std::any_cast(a) << '\n'; 16 | //] 17 | 18 | //[accessing_double Accessing values (double) 19 | a = 3.14; 20 | std::cout << a.type().name() << ": " << std::any_cast(a) << '\n'; 21 | //] 22 | 23 | //[accessing_bool Accessing values (bool) 24 | a = true; 25 | std::cout << a.type().name() << ": " << std::any_cast(a) << '\n'; 26 | //] 27 | 28 | //[accessing_string Accessing values (string) 29 | a = std::string("Any string"); 30 | std::cout << a.type().name() << ": " << std::any_cast(a) << '\n'; 31 | //] 32 | 33 | //[attempt Attempting to access values 34 | try { 35 | std::any v = 1; 36 | std::cout << std::any_cast(v) << '\n'; 37 | } catch (std::bad_any_cast &e) { 38 | std::cout << e.what() << '\n'; 39 | } 40 | //] 41 | 42 | //[check_value Checking if variable is empty 43 | std::any s2 = 1; 44 | if (!s2.has_value()) { 45 | const std::type_info &ti = s2.type(); 46 | std::cout << ti.name() << '\n'; 47 | } 48 | //] 49 | 50 | //[access_pointer Access pointer to value 51 | std::any a3 = 1; 52 | int *i = std::any_cast(&a3); 53 | std::cout << *i << '\n'; 54 | //] 55 | 56 | return 0; 57 | } -------------------------------------------------------------------------------- /snippets/heterogeneous_types/optional.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | //[opt_func Function that returns a value only if it's even 9 | std::optional get_even_random_number() { 10 | int i = std::rand(); 11 | if (i % 2 == 0) { 12 | return i; 13 | } else { 14 | return std::nullopt; 15 | } 16 | } 17 | //] 18 | 19 | //[opt_func_2 Function that always returns a non-empty optional value 20 | std::optional get_even_random_number2() { 21 | int i = std::rand(); 22 | return std::make_optional(int(i % 2 == 0)); 23 | } 24 | //] 25 | 26 | int main() { 27 | auto entropy_source = static_cast(std::time(nullptr)); 28 | std::srand(entropy_source); 29 | 30 | std::cout << "Optional variables:" << std::endl; 31 | { 32 | //[callfunc1 Call function that returns optional value 33 | std::optional i = get_even_random_number(); 34 | if (i) { 35 | std::cout << std::sqrt(static_cast(*i)) << '\n'; 36 | } else { 37 | std::cout << "No value was returned" << '\n'; 38 | } 39 | //] 40 | 41 | //[callfunc2 Call function that returns non-empty optional value 42 | i = get_even_random_number2(); 43 | double d = i.value_or(0); 44 | std::cout << std::sqrt(d) << '\n'; 45 | std::cout << i.value_or(0) << std::endl; 46 | //] 47 | } 48 | return 0; 49 | } -------------------------------------------------------------------------------- /snippets/heterogeneous_types/variant.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | //[decl_union Declare an C union 7 | union my_union { 8 | double a; 9 | char b; 10 | int c; 11 | }; 12 | //] 13 | 14 | //[use_union Using unions 15 | // - It only works with fundamental data type 16 | // - It doesn't have convenience functions 17 | my_union u = {3.14}; 18 | u = {'A'}; 19 | u = {15}; 20 | //] 21 | 22 | //[size_union Union size 23 | // A union is as large as the largest type in the union 24 | std::cout << "sizeof(double): " << sizeof(double) << '\n'; 25 | std::cout << "sizeof(char): " << sizeof(char) << '\n'; 26 | std::cout << "sizeof(int): " << sizeof(int) << '\n'; 27 | std::cout << "sizeof(my_union): " << sizeof(my_union) << '\n'; 28 | //] 29 | 30 | //[decl_variant Declaring a variant type 31 | std::variant v; 32 | //] 33 | 34 | //[set_value Setting variant values 35 | v = 3.14; // becomes double 36 | v = 'A'; // becomes char 37 | v = "Some longer text"; // becomes std::string 38 | //] 39 | 40 | //[variant_size Variant size 41 | // A variant is larger than the largest type in the variant 42 | // This happens because variants need a flag to indicate the current type 43 | std::cout << "sizeof(double): " << sizeof(double) << '\n'; 44 | std::cout << "sizeof(char): " << sizeof(char) << '\n'; 45 | std::cout << "sizeof(string): " << sizeof(std::string) << '\n'; 46 | std::cout << "sizeof(variant): " 47 | << sizeof(std::variant) << '\n'; 48 | //] 49 | 50 | //[access Accessing values 51 | v = 3.14; 52 | std::cout << get(v) << '\n'; 53 | v = 'A'; 54 | std::cout << get(v) << '\n'; 55 | v = "Some longer text"; 56 | std::cout << get(v) << '\n'; 57 | //] 58 | 59 | //[visit Visiting variant 60 | // Applying function to whatever value type it holds 61 | std::visit([](auto x) { std::cout << x << '\n'; }, v); 62 | //] 63 | 64 | //[index Checking current alternative index 65 | switch (v.index()) { 66 | case 0: 67 | std::cout << "This is a double\n"; 68 | break; 69 | case 1: 70 | std::cout << "This is a char\n"; 71 | break; 72 | case 2: 73 | std::cout << "This is a string\n"; 74 | break; 75 | } 76 | //] 77 | 78 | //[check_type Checking current alternative type 79 | if (std::holds_alternative(v)) { 80 | std::cout << "This is a double\n"; 81 | } else if (std::holds_alternative(v)) { 82 | std::cout << "This is a char\n"; 83 | } else if (std::holds_alternative(v)) { 84 | std::cout << "This is a string\n"; 85 | } 86 | //] 87 | 88 | return 0; 89 | } 90 | -------------------------------------------------------------------------------- /snippets/input_output/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #[hello_world CMakeLists.txt 2 | add_executable(hello_world hello_world.cpp) 3 | #] 4 | 5 | add_executable(cin cin.cpp) 6 | 7 | add_executable(printing output.cpp) 8 | 9 | add_executable(iomanip iomanip.cpp) 10 | 11 | #[fmt Find and link fmt library 12 | find_package(fmt QUIET) 13 | if (NOT fmt_FOUND) 14 | FetchContent_Declare( 15 | fmt 16 | GIT_REPOSITORY https://github.com/fmtlib/fmt 17 | GIT_TAG 8.1.1 18 | ) 19 | FetchContent_MakeAvailable(fmt) 20 | endif() 21 | add_executable(format format.cpp) 22 | target_link_libraries(format fmt::fmt) 23 | #] 24 | -------------------------------------------------------------------------------- /snippets/input_output/cin.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | //[headers Headers 3 | #include 4 | //] 5 | 6 | int main() { 7 | 8 | 9 | //[input User input 10 | int age; 11 | std::cout << "How old are you? "; 12 | std::cin >> age; 13 | //] 14 | 15 | //[input_error User input (Handling error) 16 | std::cout << "How old are you again? "; 17 | if (!(std::cin >> age)) { 18 | std::cout << "There is an error in your input\n"; 19 | return 1; 20 | } 21 | //] 22 | 23 | //[consume Consuming input 24 | if (age >= 18) { 25 | std::cout << "Welcome!\n"; 26 | } else { 27 | std::cout << "Sorry.\n"; 28 | return 1; 29 | } 30 | //] 31 | 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /snippets/input_output/format.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | //[headers Headers 8 | #include // time formatters 9 | #include // color formatters 10 | #include // main header 11 | #include // ostream formatters 12 | #include // range formatters 13 | //] 14 | 15 | int main() { 16 | //[print Simple print 17 | fmt::print("Hello, world!\n"); 18 | //] 19 | 20 | //[to_string Format to string 21 | std::cout << fmt::format("The answer is {}.\n", 42); 22 | //] 23 | 24 | //[ordered Format with order 25 | std::cout << fmt::format("I'd rather be {1} than {0}.\n", "right", "happy"); 26 | //] 27 | 28 | //[chrono Chrono literals 29 | using namespace std::literals::chrono_literals; 30 | fmt::print("Default format: {} {}\n", 42s, 100ms); 31 | //] 32 | 33 | //[custom_chrono strftime-like format 34 | fmt::print("strftime-like format: {:%H:%M:%S}\n", 3h + 15min + 30s); 35 | //] 36 | 37 | //[ranges Format ranges 38 | std::vector v = {1, 2, 3}; 39 | fmt::print("{}\n", v); 40 | //] 41 | 42 | //[tuple Format tuple 43 | std::tuple t2{'a', 1, 2.0f}; 44 | fmt::print("{}", t2); 45 | //] 46 | 47 | //[color Color support 48 | fmt::print(fg(fmt::color::crimson) | fmt::emphasis::bold, "Hello, {}!\n", 49 | "world"); 50 | auto style = fg(fmt::color::floral_white) | bg(fmt::color::slate_gray) | 51 | fmt::emphasis::underline; 52 | fmt::print(style, "Hello, {}!\n", "мир"); 53 | //] 54 | 55 | //[utf8 UTF-8 56 | print(fg(fmt::color::steel_blue) | fmt::emphasis::italic, "Hello, {}!\n", "世界"); 57 | //] 58 | 59 | //[memory Format to memory 60 | std::vector out; 61 | fmt::format_to(std::back_inserter(out), "For a moment, {} happened.", "nothing"); 62 | fmt::print("{}", out.data()); 63 | //] 64 | } 65 | -------------------------------------------------------------------------------- /snippets/input_output/hello_world.cpp: -------------------------------------------------------------------------------- 1 | //[hello Your first C++ program 2 | #include 3 | 4 | int main() { 5 | std::cout << "Hello world" << std::endl; 6 | return 0; 7 | } 8 | //] -------------------------------------------------------------------------------- /snippets/input_output/iomanip.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | 6 | 7 | double f = 3.14159; 8 | std::cout << "std::setprecision(2): " << std::setprecision(2) << f << '\n'; 9 | std::cout << "std::setprecision(5): " << std::setprecision(5) << f << '\n'; 10 | std::cout << "std::setprecision(9): " << std::setprecision(9) << f << '\n'; 11 | std::cout << std::fixed; 12 | std::cout << "std::setprecision(5): " << std::setprecision(5) << f << '\n'; 13 | std::cout << "std::setprecision(9): " << std::setprecision(9) << f << '\n'; 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /snippets/input_output/output.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | 5 | 6 | int age; 7 | std::cout << "How old are you? "; 8 | std::cin >> age; 9 | if (age < 18) { 10 | //[printf printf 11 | printf("Sorry."); 12 | //] 13 | //[cout std::cout 14 | std::cout << "Sorry." << '\n'; 15 | //] 16 | //[cout_flush Flushing std::cout 17 | std::cout << "Sorry." << std::endl; 18 | //] 19 | } else { 20 | //[printf_param printf with parameters 21 | printf("Welcome! You are %d years old.", age); 22 | //] 23 | //[cout_param std::cout with parameters 24 | std::cout << "Welcome! You are " << age << " years old." << '\n'; 25 | //] 26 | //[cout_param_flush Flushing std::cout with parameters 27 | std::cout << "Welcome! You are " << age << " years old." << std::endl; 28 | //] 29 | // See the format example for another way 30 | // std::cout << std::format(...); 31 | } 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /snippets/networking/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ####################################################### 2 | ### External Libraries ### 3 | ####################################################### 4 | FetchContent_Declare(asio GIT_REPOSITORY https://github.com/chriskohlhoff/asio.git GIT_TAG asio-1-18-1) 5 | FetchContent_GetProperties(asio) 6 | if (NOT asio_POPULATED) 7 | FetchContent_Populate(asio) 8 | add_library(asio INTERFACE) 9 | target_include_directories(asio INTERFACE ${asio_SOURCE_DIR}/asio/include) 10 | target_compile_definitions(asio INTERFACE ASIO_STANDALONE ASIO_NO_DEPRECATED) 11 | target_link_libraries(asio INTERFACE Threads::Threads) 12 | endif () 13 | 14 | ####################################################### 15 | ### Networking ### 16 | ####################################################### 17 | #[network CMakeLists.txt 18 | add_executable(network network.cpp) 19 | target_link_libraries(network asio) 20 | #] 21 | 22 | #[network_async CMakeLists.txt 23 | add_executable(network_async network_async.cpp) 24 | target_link_libraries(network_async asio) 25 | #] 26 | 27 | add_subdirectory(server) 28 | -------------------------------------------------------------------------------- /snippets/networking/network.cpp: -------------------------------------------------------------------------------- 1 | #include "asio.hpp" 2 | #include 3 | #include 4 | #include 5 | 6 | // Create the string to be sent back to the client 7 | std::string make_daytime_string() { 8 | time_t now = time(nullptr); 9 | std::string r = ctime(&now); 10 | std::cout << "Time requested: " << r; 11 | return r; 12 | } 13 | 14 | int main() { 15 | try { 16 | //[io_context Create io_context executor 17 | // Object for network input and output 18 | // - All networking programs at least one io_context 19 | // - I/O execution context represents your program's link to the 20 | // operating system's I/O services 21 | asio::io_context io_context; 22 | //] 23 | 24 | //[acceptor Create acceptor 25 | // The acceptor listens for connections 26 | // - Create the simplest server possible 27 | asio::ip::tcp::endpoint ep(asio::ip::tcp::v4(), 8080); 28 | asio::ip::tcp::acceptor acceptor(io_context, ep); 29 | //] 30 | 31 | //[socket Create connection socket 32 | // For loop listening to connections from client 33 | // - It will handle one connection at a time 34 | // - See the async example for more than one connection at a time 35 | while (true) { 36 | // Connection socket 37 | // - Represents the connection to the client 38 | asio::ip::tcp::socket socket(io_context); 39 | //] 40 | 41 | //[accept Wait for connection from client 42 | // - Wait for a connection 43 | // - Use socket to represent the new connection 44 | // - Open http://localhost:8080 in your browser 45 | acceptor.accept(socket); 46 | //] 47 | 48 | // Create message to be returned 49 | // - The message is the current time 50 | std::string message = make_daytime_string(); 51 | 52 | //[write Write response to client 53 | // - Transfer this information to the client with the socket 54 | std::error_code error; 55 | asio::write(socket, asio::buffer(message), error); 56 | //] 57 | 58 | //[error Check for errors 59 | if (error) { 60 | std::cout << "Error " << error.value() << ": " 61 | << error.message() << std::endl; 62 | } 63 | } // while (true) 64 | //] 65 | } catch (std::exception &e) { 66 | // Handle any possible exceptions 67 | std::cerr << e.what() << '\n'; 68 | } 69 | 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /snippets/networking/server/.gitignore: -------------------------------------------------------------------------------- 1 | .deps 2 | .dirstamp 3 | *.o 4 | *.obj 5 | *.exe 6 | *_server 7 | *_client 8 | *.ilk 9 | *.manifest 10 | *.pdb 11 | *.tds 12 | -------------------------------------------------------------------------------- /snippets/networking/server/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This is just an example of how an HTTP server could be implemented with asio 2 | # For proper HTTP servers, it's more recommendable to use a library for that 3 | #[server http_server 4 | add_executable(http_server 5 | connection.cpp 6 | connection.hpp 7 | connection_manager.cpp 8 | connection_manager.hpp 9 | header.hpp 10 | main.cpp 11 | mime_types.cpp 12 | mime_types.hpp 13 | reply.cpp 14 | reply.hpp 15 | request.hpp 16 | request_handler.cpp 17 | request_handler.hpp 18 | request_parser.cpp 19 | request_parser.hpp 20 | server.cpp 21 | server.hpp) 22 | target_link_libraries(http_server asio) 23 | #] 24 | -------------------------------------------------------------------------------- /snippets/networking/server/connection.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // connection.hpp 3 | // ~~~~~~~~~~~~~~ 4 | // 5 | // Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6 | // 7 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 8 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | 11 | #ifndef HTTP_CONNECTION_HPP 12 | #define HTTP_CONNECTION_HPP 13 | 14 | #include "reply.hpp" 15 | #include "request.hpp" 16 | #include "request_handler.hpp" 17 | #include "request_parser.hpp" 18 | #include 19 | #include 20 | #include 21 | 22 | namespace http::server { 23 | 24 | class connection_manager; 25 | 26 | //[def_connection Define class for a single connection from a client. 27 | class connection : public std::enable_shared_from_this { 28 | public: 29 | connection(const connection &) = delete; 30 | connection &operator=(const connection &) = delete; 31 | 32 | // Construct a connection with the given socket. 33 | explicit connection(asio::ip::tcp::socket socket, 34 | connection_manager &manager, 35 | request_handler &handler); 36 | 37 | // Start the first asynchronous operation for the connection. 38 | void start(); 39 | 40 | // Stop all asynchronous operations associated with the connection. 41 | void stop(); 42 | 43 | private: 44 | // Perform an asynchronous read operation. 45 | void schedule_read(); 46 | 47 | // Perform an asynchronous write operation. 48 | void schedule_write(); 49 | 50 | // Socket for the connection. 51 | asio::ip::tcp::socket socket_; 52 | 53 | // The manager for this connection. 54 | connection_manager &connection_manager_; 55 | 56 | // The handler used to process the incoming request. 57 | request_handler &request_handler_; 58 | 59 | // Buffer for incoming data. 60 | std::array buffer_; 61 | 62 | // The incoming request. 63 | request request_; 64 | 65 | // The parser for the incoming request. 66 | request_parser request_parser_; 67 | 68 | // The reply to be sent back to the client. 69 | reply reply_; 70 | }; 71 | //] 72 | 73 | typedef std::shared_ptr connection_ptr; 74 | 75 | } // namespace http::server 76 | 77 | #endif // HTTP_CONNECTION_HPP 78 | -------------------------------------------------------------------------------- /snippets/networking/server/connection_manager.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // connection_manager.cpp 3 | // ~~~~~~~~~~~~~~~~~~~~~~ 4 | // 5 | // Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6 | // 7 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 8 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | 11 | #include "connection_manager.hpp" 12 | 13 | namespace http::server { 14 | 15 | //[connection_manager_connection_manager Default construct 16 | connection_manager::connection_manager() = default; 17 | //] 18 | 19 | //[connection_manager_start Start a connection 20 | void connection_manager::start(connection_ptr c) { 21 | connections_.insert(c); 22 | c->start(); 23 | } 24 | //] 25 | 26 | //[connection_manager_stop Stop a connection 27 | void connection_manager::stop(connection_ptr c) { 28 | connections_.erase(c); 29 | c->stop(); 30 | } 31 | //] 32 | 33 | //[connection_manager_stop_all Stop all connections 34 | void connection_manager::stop_all() { 35 | for (auto c : connections_) { 36 | c->stop(); 37 | } 38 | connections_.clear(); 39 | } 40 | //] 41 | 42 | } // namespace http::server 43 | -------------------------------------------------------------------------------- /snippets/networking/server/connection_manager.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // connection_manager.hpp 3 | // ~~~~~~~~~~~~~~~~~~~~~~ 4 | // 5 | // Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6 | // 7 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 8 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | 11 | #ifndef HTTP_CONNECTION_MANAGER_HPP 12 | #define HTTP_CONNECTION_MANAGER_HPP 13 | 14 | #include "connection.hpp" 15 | #include 16 | 17 | namespace http::server { 18 | 19 | //[def_connection_manager Declare connection manager 20 | // Manages open connections so that they may be cleanly stopped when 21 | // the server needs to shut down. 22 | class connection_manager { 23 | public: 24 | connection_manager(const connection_manager &) = delete; 25 | connection_manager &operator=(const connection_manager &) = delete; 26 | 27 | // Construct a connection manager. 28 | connection_manager(); 29 | 30 | // Add the specified connection to the manager and start it. 31 | void start(connection_ptr c); 32 | 33 | // Stop the specified connection. 34 | void stop(connection_ptr c); 35 | 36 | // Stop all connections. 37 | void stop_all(); 38 | 39 | private: 40 | // The managed connections. 41 | std::set connections_; 42 | }; 43 | //] 44 | 45 | } // namespace http::server 46 | 47 | #endif // HTTP_CONNECTION_MANAGER_HPP 48 | -------------------------------------------------------------------------------- /snippets/networking/server/header.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // header.hpp 3 | // ~~~~~~~~~~ 4 | // 5 | // Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6 | // 7 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 8 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | 11 | #ifndef HTTP_HEADER_HPP 12 | #define HTTP_HEADER_HPP 13 | 14 | #include 15 | 16 | namespace http::server { 17 | //[header Struct for request headers 18 | struct header { 19 | std::string name; 20 | std::string value; 21 | }; 22 | //] 23 | } // namespace http::server 24 | 25 | #endif // HTTP_HEADER_HPP 26 | -------------------------------------------------------------------------------- /snippets/networking/server/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // main.cpp 3 | // ~~~~~~~~ 4 | // 5 | // Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6 | // 7 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 8 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | 11 | #include "server.hpp" 12 | #include 13 | #include 14 | 15 | //[cli_check Check command line arguments. 16 | int main(int argc, char *argv[]) { 17 | try { 18 | if (argc != 4) { 19 | std::cout << "Usage: http_server
\n"; 20 | std::cout << " For IPv4, try: "; 21 | std::cout << " receiver 0.0.0.0 80 .\n"; 22 | std::cout << " For IPv6, try: "; 23 | std::cout << " receiver 0::0 80 .\n"; 24 | } 25 | //] 26 | 27 | //[init Initialise the server 28 | std::string address = argc > 1 ? argv[1] : "0.0.0.0"; 29 | std::string port = argc > 2 ? argv[2] : "80"; 30 | std::string doc_root = argc > 3 ? argv[3] : "."; 31 | std::cout << "Server address: http://" << address << ":" << port 32 | << '\n'; 33 | http::server::server s(address, port, doc_root); 34 | //] 35 | 36 | //[run Run the server until stopped. 37 | s.run(); 38 | //] 39 | //[catch Catch server exceptions 40 | } catch (std::exception &e) { 41 | std::cerr << "exception: " << e.what() << "\n"; 42 | } 43 | //] 44 | 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /snippets/networking/server/mime_types.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // mime_types.cpp 3 | // ~~~~~~~~~~~~~~ 4 | // 5 | // Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6 | // 7 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 8 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | 11 | #include "mime_types.hpp" 12 | 13 | namespace http::server::mime_types { 14 | 15 | //[mappings Map MIME types 16 | constexpr struct mapping { 17 | const char *extension; 18 | const char *mime_type; 19 | } mappings[] = {{"gif", "image/gif"}, 20 | {"htm", "text/html"}, 21 | {"html", "text/html"}, 22 | {"jpg", "image/jpeg"}, 23 | {"png", "image/png"}}; 24 | //] 25 | 26 | //[extension_to_type Convert file extension to type 27 | std::string extension_to_type(const std::string &extension) { 28 | for (mapping m : mappings) { 29 | if (m.extension == extension) { 30 | return m.mime_type; 31 | } 32 | } 33 | 34 | return "text/plain"; 35 | } 36 | //] 37 | 38 | } // namespace http::server::mime_types 39 | -------------------------------------------------------------------------------- /snippets/networking/server/mime_types.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // mime_types.hpp 3 | // ~~~~~~~~~~~~~~ 4 | // 5 | // Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6 | // 7 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 8 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | 11 | #ifndef HTTP_MIME_TYPES_HPP 12 | #define HTTP_MIME_TYPES_HPP 13 | 14 | #include 15 | 16 | namespace http::server::mime_types { 17 | 18 | //[extension_to_type Convert a file extension into a MIME type. 19 | std::string extension_to_type(const std::string &extension); 20 | //] 21 | 22 | } // namespace http::server::mime_types 23 | 24 | #endif // HTTP_MIME_TYPES_HPP 25 | -------------------------------------------------------------------------------- /snippets/networking/server/reply.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // reply.hpp 3 | // ~~~~~~~~~ 4 | // 5 | // Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6 | // 7 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 8 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | 11 | #ifndef HTTP_REPLY_HPP 12 | #define HTTP_REPLY_HPP 13 | 14 | #include "header.hpp" 15 | #include 16 | #include 17 | #include 18 | 19 | namespace http::server { 20 | 21 | //[reply A reply to be sent to a client. 22 | struct reply { 23 | // The status of the reply. 24 | enum status_type { 25 | ok = 200, 26 | created = 201, 27 | accepted = 202, 28 | no_content = 204, 29 | multiple_choices = 300, 30 | moved_permanently = 301, 31 | moved_temporarily = 302, 32 | not_modified = 304, 33 | bad_request = 400, 34 | unauthorized = 401, 35 | forbidden = 403, 36 | not_found = 404, 37 | internal_server_error = 500, 38 | not_implemented = 501, 39 | bad_gateway = 502, 40 | service_unavailable = 503 41 | } status; 42 | 43 | // The headers to be included in the reply. 44 | std::vector
headers; 45 | 46 | // The content to be sent in the reply. 47 | std::string content; 48 | 49 | // Convert the reply into a vector of buffers. The buffers do not 50 | // own the underlying memory blocks, therefore the reply object 51 | // must remain valid and not be changed until the write operation 52 | // has completed. 53 | std::vector to_buffers(); 54 | 55 | // Get a stock reply. 56 | static reply stock_reply(status_type status); 57 | }; 58 | //] 59 | 60 | } // namespace http::server 61 | 62 | #endif // HTTP_REPLY_HPP 63 | -------------------------------------------------------------------------------- /snippets/networking/server/request.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // request.hpp 3 | // ~~~~~~~~~~~ 4 | // 5 | // Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6 | // 7 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 8 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | 11 | #ifndef HTTP_REQUEST_HPP 12 | #define HTTP_REQUEST_HPP 13 | 14 | #include "header.hpp" 15 | #include 16 | #include 17 | 18 | namespace http::server { 19 | //[request A request received from a client. 20 | struct request { 21 | std::string method; 22 | std::string uri; 23 | int http_version_major; 24 | int http_version_minor; 25 | std::vector
headers; 26 | }; 27 | //] 28 | } // namespace http::server 29 | 30 | #endif // HTTP_REQUEST_HPP 31 | -------------------------------------------------------------------------------- /snippets/networking/server/request_handler.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // request_handler.hpp 3 | // ~~~~~~~~~~~~~~~~~~~ 4 | // 5 | // Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6 | // 7 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 8 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | 11 | #ifndef HTTP_REQUEST_HANDLER_HPP 12 | #define HTTP_REQUEST_HANDLER_HPP 13 | 14 | #include 15 | 16 | namespace http::server { 17 | 18 | struct reply; 19 | struct request; 20 | 21 | //[request_handler The common handler for all incoming requests. 22 | class request_handler { 23 | public: 24 | request_handler(const request_handler &) = delete; 25 | request_handler &operator=(const request_handler &) = delete; 26 | 27 | // Construct with a directory containing files to be served. 28 | explicit request_handler(const std::string &doc_root); 29 | 30 | // Handle a request and produce a reply. 31 | void handle_request(const request &req, reply &rep); 32 | 33 | private: 34 | // The directory containing the files to be served. 35 | std::string doc_root_; 36 | 37 | // Perform URL-decoding on a string. Returns false if the encoding 38 | // was invalid. 39 | static bool url_decode(const std::string &in, std::string &out); 40 | }; 41 | //] 42 | 43 | } // namespace http::server 44 | 45 | #endif // HTTP_REQUEST_HANDLER_HPP 46 | -------------------------------------------------------------------------------- /snippets/networking/server/server.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // server.hpp 3 | // ~~~~~~~~~~ 4 | // 5 | // Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6 | // 7 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 8 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | 11 | #ifndef HTTP_SERVER_HPP 12 | #define HTTP_SERVER_HPP 13 | 14 | #include "connection.hpp" 15 | #include "connection_manager.hpp" 16 | #include "request_handler.hpp" 17 | #include 18 | #include 19 | 20 | namespace http::server { 21 | 22 | //[server_define Define top-level class for the HTTP server. 23 | class server { 24 | public: 25 | server(const server &) = delete; 26 | server &operator=(const server &) = delete; 27 | 28 | // Construct the server to listen on the specified TCP address and 29 | // port, and serve up files from the given directory. 30 | explicit server(const std::string &address, const std::string &port, 31 | const std::string &doc_root); 32 | 33 | // Run the server's io_context loop. 34 | void run(); 35 | 36 | private: 37 | // Perform an asynchronous accept operation. 38 | void schedule_accept(); 39 | 40 | // Wait for a request to stop the server. 41 | void schedule_await_stop(); 42 | 43 | // The io_context used to perform asynchronous operations. 44 | asio::io_context io_context_; 45 | 46 | // Executor for the io context 47 | asio::thread_pool pool_; 48 | 49 | // The signal_set is used to register for process termination 50 | // notifications. 51 | asio::signal_set signals_; 52 | 53 | // Acceptor used to listen for incoming connections. 54 | asio::ip::tcp::acceptor acceptor_; 55 | 56 | // The connection manager which owns all live connections. 57 | connection_manager connection_manager_; 58 | 59 | // The handler for all incoming requests. 60 | request_handler request_handler_; 61 | 62 | // Helper class to setup signals 63 | void setup_signals(); 64 | 65 | // Helper class to setup acceptor 66 | void setup_acceptor(const std::string &address, 67 | const std::string &port); 68 | }; 69 | //] 70 | 71 | } // namespace http::server 72 | 73 | #endif // HTTP_SERVER_HPP 74 | -------------------------------------------------------------------------------- /snippets/paradigms/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_executable(polymorphism polymorphism.cpp) 3 | 4 | add_executable(shared_from_this shared_from_this.cpp) 5 | 6 | add_executable(CRTP CRTP.cpp) 7 | -------------------------------------------------------------------------------- /snippets/paradigms/CRTP.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | //[shape Declare shape class with derived type as template parameter 4 | template class shape { 5 | public: 6 | virtual derived clone() { return static_cast(*this); }; 7 | }; 8 | //] 9 | 10 | //[square Inherits from base and base has derived as a template parameter 11 | class square : public shape { 12 | public: 13 | square() = default; 14 | explicit square(const shape &){}; 15 | // CRTP: Clone can return a square even though it's derived from shape 16 | square clone() override { return *this; } 17 | }; 18 | //] 19 | 20 | int main() { 21 | //[use_fn Use a template dependant function 22 | square a; 23 | square b = a.clone(); 24 | //] 25 | 26 | //[print Print addresses 27 | std::cout << "The square has been cloned as a real square" << '\n'; 28 | std::cout << "&a: " << &a << '\n'; 29 | std::cout << "&b: " << &b << '\n'; 30 | //] 31 | 32 | return 0; 33 | } -------------------------------------------------------------------------------- /snippets/paradigms/shared_from_this.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() { 7 | //[hello_printer A shared class that say hello 8 | class hello_printer : public std::enable_shared_from_this { 9 | public: 10 | // Main class function 11 | void say_hello() { std::cout << "Hello, World!" << '\n'; } 12 | //] 13 | 14 | //[factory A factory function to create instances of hello_printer 15 | static std::shared_ptr create() { 16 | return std::shared_ptr(new hello_printer()); 17 | } 18 | 19 | private: 20 | // New objects need to be created with the factory 21 | hello_printer() = default; 22 | }; 23 | //] 24 | 25 | //[create Create a hello printer 26 | auto y = hello_printer::create(); 27 | y->say_hello(); 28 | std::cout << "y.get() = " << y.get() << '\n'; 29 | std::cout << "&y = " << &y << '\n'; 30 | //] 31 | 32 | //[share Share the hello printer 33 | // y2 will also point to the same object as y 34 | std::shared_ptr y2 = y->shared_from_this(); 35 | y2->say_hello(); 36 | std::cout << "y2.get() = " << y2.get() << '\n'; 37 | std::cout << "&y2 = " << &y2 << '\n'; 38 | //] 39 | 40 | //[create_z Create an independent hello printer 41 | auto z = hello_printer::create(); 42 | z->say_hello(); 43 | std::cout << "z.get() = " << z.get() << '\n'; 44 | std::cout << "&z = " << &z << '\n'; 45 | //] 46 | 47 | return 0; 48 | } -------------------------------------------------------------------------------- /snippets/parallel/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # https://stackoverflow.com/questions/66881657/ubuntu-18-gcc-9-failed-to-link-tbb-library-for-execution-policy-in-standard-lib 2 | #[policies CMakeLists.txt 3 | find_package(Threads) 4 | find_package(Execution) 5 | find_library(TBB_LIBRARY NAMES tbb) 6 | if (Execution_FOUND AND TBB_LIBRARY) 7 | add_executable(policies policies.cpp) 8 | target_link_libraries(policies PUBLIC std::execution Threads::Threads ${TBB_LIBRARIES}) 9 | endif () 10 | #] 11 | 12 | #[threads CMakeLists.txt 13 | find_package(Threads) 14 | add_executable(multithreading multithreading.cpp) 15 | target_link_libraries(multithreading PUBLIC Threads::Threads) 16 | #] 17 | 18 | #[find_asio Find ASIO 19 | find_package(Asio 1.21.0 QUIET) 20 | if (NOT Asio_FOUND) 21 | FetchContent_Declare(asio GIT_REPOSITORY https://github.com/chriskohlhoff/asio.git GIT_TAG asio-1-21-0) 22 | FetchContent_GetProperties(asio) 23 | if (NOT asio_POPULATED) 24 | FetchContent_Populate(asio) 25 | add_library(asio INTERFACE) 26 | target_include_directories(asio INTERFACE ${asio_SOURCE_DIR}/asio/include) 27 | target_compile_definitions(asio INTERFACE ASIO_STANDALONE ASIO_NO_DEPRECATED) 28 | target_link_libraries(asio INTERFACE Threads::Threads) 29 | endif () 30 | endif() 31 | #] 32 | 33 | # The executor libraries in ASIO do not have lots of convenience functions 34 | # but they are a good reference for the executor proposal 35 | #[executors CMakeLists.txt 36 | add_executable(executors executors.cpp) 37 | target_link_libraries(executors asio) 38 | #] 39 | 40 | #[timers CMakeLists.txt 41 | add_executable(timers timers.cpp) 42 | target_link_libraries(timers asio) 43 | #] 44 | 45 | #[signals CMakeLists.txt 46 | add_executable(signals signals.cpp) 47 | target_link_libraries(signals asio) 48 | #] 49 | 50 | # Async++ has good convenience functions/algorithms for parallel computing 51 | # But it's about to be completely replaced by the traditional executors in C++23 52 | # Replace this library as soon as we have an alternative based on executors 53 | # Async++ 54 | # The build script has a few problems 55 | # - stdlib++ whenever the platform is APPLE. The user might not be using stdlib++ 56 | # - it doesn't seem to be working on more recent MSVC compilers 57 | # - it doesn't seem to be working on more recent Clang compilers 58 | if (GCC) 59 | #[asyncplusplus CMakeLists.txt 60 | FetchContent_Declare(asyncplusplus GIT_REPOSITORY https://github.com/Amanieu/asyncplusplus.git GIT_TAG v1.1) 61 | FetchContent_MakeAvailable(asyncplusplus) 62 | add_executable(async_pools async_pools.cpp) 63 | target_link_libraries(async_pools PUBLIC Async++) 64 | target_compile_features(async_pools PUBLIC cxx_std_17) 65 | #] 66 | endif () 67 | -------------------------------------------------------------------------------- /snippets/parallel/async_pools.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | //[launch Launch tasks 6 | auto task1 = async::spawn( 7 | [] { std::cout << "Task 1 executes asynchronously" << '\n'; }); 8 | 9 | auto task2 = async::spawn([]() -> int { 10 | std::cout << "Task 2 executes in parallel with task 1" << '\n'; 11 | return 42; 12 | }); 13 | //] 14 | 15 | //[then Task continuation 16 | auto task3 = task2.then([](int value) -> int { 17 | std::cout << "Task 3 executes after task 2, which returned " << value 18 | << '\n'; 19 | return value * 3; 20 | }); 21 | //] 22 | 23 | //[conj Task conjunctions 24 | auto task4 = async::when_all(task1, task3); 25 | auto task5 = 26 | task4.then([](std::tuple, async::task> results) { 27 | std::cout << "Task 5 executes after tasks 1 and 3. Task 3 returned " 28 | << std::get<1>(results).get() << '\n'; 29 | }); 30 | //] 31 | 32 | //[get Get task results 33 | task5.get(); 34 | std::cout << "Task 5 has completed" << '\n'; 35 | //] 36 | 37 | //[par_invoke Parallel invoke 38 | async::parallel_invoke( 39 | [] { std::cout << "This is executed in parallel..." << '\n'; }, 40 | [] { std::cout << "with this" << '\n'; }); 41 | //] 42 | 43 | //[par_for Parallel for 44 | async::parallel_for(async::irange(0, 5), [](int x) { std::cout << x; }); 45 | std::cout << '\n'; 46 | //] 47 | 48 | //[par_reduce Parallel reduce 49 | int r = async::parallel_reduce({1, 2, 3, 4}, 0, 50 | [](int x, int y) { return x + y; }); 51 | std::cout << "The sum of {1, 2, 3, 4} is " << r << '\n'; 52 | //] 53 | } 54 | -------------------------------------------------------------------------------- /snippets/parallel/policies.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | //[seq Execution may not be parallelized 6 | std::vector x{5, 7, 6, 4, 8, 2}; 7 | std::sort(std::execution::seq, x.begin(), x.end()); 8 | std::copy(x.begin(), x.end(), std::ostream_iterator{std::cout, " "}); 9 | std::cout << '\n'; 10 | //] 11 | 12 | //[par Execution may be parallelized 13 | std::vector y{5, 7, 6, 4, 8, 2}; 14 | std::sort(std::execution::par, y.begin(), y.end()); 15 | std::copy(y.begin(), y.end(), std::ostream_iterator{std::cout, " "}); 16 | std::cout << '\n'; 17 | //] 18 | 19 | //[par_unseq Execution may be parallelized, vectorized, or migrated across threads 20 | std::vector z{5, 7, 6, 4, 8, 2}; 21 | std::sort(std::execution::par_unseq, z.begin(), z.end()); 22 | std::copy(z.begin(), z.end(), std::ostream_iterator{std::cout, " "}); 23 | std::cout << '\n'; 24 | //] 25 | 26 | //[unseq Execution may be vectorized 27 | std::vector w{5, 7, 6, 4, 8, 2}; 28 | std::sort(std::execution::unseq, w.begin(), w.end()); 29 | std::copy(w.begin(), w.end(), std::ostream_iterator{std::cout, " "}); 30 | std::cout << '\n'; 31 | //] 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /snippets/parallel/signals.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | //[io_context Create io_context executor 7 | asio::io_context io_context; 8 | //] 9 | 10 | //[signal_set Create signal_set responding to SIGINT and SIGTERM 11 | asio::signal_set signals(io_context, SIGINT, SIGTERM); 12 | //] 13 | 14 | //[signal_cb Set the signal set callback 15 | // The signals will set stop_timer to true 16 | std::atomic request_stop_timer = false; 17 | signals.async_wait([&](const asio::error_code &ec, int signal_number) { 18 | if (!ec) { 19 | std::cout << "Signal number " << signal_number << std::endl; 20 | std::cout << "Gracefully stopping the timer and exiting" 21 | << std::endl; 22 | request_stop_timer.store(true); 23 | } else { 24 | std::cout << "Error " << ec.value() << " - " << ec.message() 25 | << " - Signal number - " << signal_number << std::endl; 26 | } 27 | }); 28 | //] 29 | 30 | //[timer Create a timer that keeps counting until we have a signal 31 | asio::steady_timer t(io_context, asio::chrono::seconds(1)); 32 | //] 33 | 34 | //[timer_cb Set timer callback 35 | int count = 0; 36 | std::function timer_callback; 37 | timer_callback = [&](asio::error_code ec) { 38 | if (!ec) { 39 | if (count < 30 && !request_stop_timer.load()) { 40 | // Increase counter 41 | std::cout << count << std::endl; 42 | ++count; 43 | // Set the timer again 44 | t.expires_at(t.expiry() + std::chrono::seconds(1)); 45 | t.async_wait(timer_callback); 46 | } else { 47 | std::cout << "Reached " << count << std::endl; 48 | } 49 | } else { 50 | std::cout << "Timer Error" << std::endl; 51 | } 52 | }; 53 | //] 54 | 55 | //[timer_wait Push timer waiting task to io_context 56 | t.async_wait(timer_callback); 57 | //] 58 | 59 | //[dequeue Execute tasks from io_context 60 | asio::thread_pool pool; 61 | for (size_t i = 0; i < std::thread::hardware_concurrency(); ++i) { 62 | asio::post(pool, [&io_context] { io_context.run(); }); 63 | } 64 | //] 65 | } 66 | -------------------------------------------------------------------------------- /snippets/parallel/timers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | //[io_context Create io_context executor 7 | asio::io_context io_context; 8 | //] 9 | 10 | // Sync timer 11 | std::cout << "Setting sync timer" << '\n'; 12 | //[sync_timer Setting a synchronous timer 13 | asio::steady_timer t(io_context, std::chrono::seconds(3)); 14 | t.wait(); 15 | std::cout << "Sync Timer expired" << '\n'; 16 | //] 17 | 18 | // Async Steady timer 19 | 20 | //[sync_steady_timer Create a steady timer 21 | asio::steady_timer t1(io_context, std::chrono::seconds(3)); 22 | //] 23 | std::cout << "Setting timers" << '\n'; 24 | 25 | //[async_steady_timer_callback Setting steady timer asynchronous callback 26 | t1.async_wait([](std::error_code ec) { 27 | if (!ec) { 28 | std::cout << "Timer 1 expired" << '\n'; 29 | } else { 30 | std::cout << "Timer 1 error" << '\n'; 31 | } 32 | }); 33 | //] 34 | 35 | // Async System timer 36 | //[system_timer Creating a system timer 37 | asio::system_timer t2(io_context, std::chrono::seconds(3)); 38 | //] 39 | 40 | //[system_timer_call Setting asynchronous steady timer callback 41 | t2.async_wait([](std::error_code ec) { 42 | if (!ec) { 43 | std::cout << "Timer 2 expired" << '\n'; 44 | } else { 45 | std::cout << "Timer 2 error" << '\n'; 46 | } 47 | }); 48 | //] 49 | 50 | // Async High-resolution timer 51 | //[high_resolution_timer Creating a high-resolution timer 52 | asio::high_resolution_timer t3(io_context, std::chrono::seconds(3)); 53 | //] 54 | 55 | //[high_res_timer_call Setting asynchronous high-resolution timer callback 56 | t3.async_wait([](std::error_code ec) { 57 | if (!ec) { 58 | std::cout << "Timer 3 expired" << '\n'; 59 | } else { 60 | std::cout << "Timer 3 error" << '\n'; 61 | } 62 | }); 63 | //] 64 | 65 | //[dequeue Dequeue tasks from io_context executor 66 | asio::thread_pool pool; 67 | for (size_t i = 0; i < std::thread::hardware_concurrency(); ++i) { 68 | asio::post(pool, [&io_context] { io_context.run(); }); 69 | } 70 | //] 71 | } 72 | -------------------------------------------------------------------------------- /snippets/pointers/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(address_operator address_operator.cpp) 2 | 3 | add_executable(raw_pointers raw_pointers.cpp) 4 | 5 | add_executable(references references.cpp) 6 | 7 | add_executable(smart_pointers smart_pointers.cpp) 8 | -------------------------------------------------------------------------------- /snippets/pointers/address_operator.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | using std::cout; 6 | 7 | //[print Print variable and its address 8 | int a = 10; 9 | cout << "a: " << a << '\n'; 10 | cout << "&a (hex): " << &a << '\n'; 11 | cout << "&a: (dec) " << reinterpret_cast(&a) << '\n'; 12 | //] 13 | 14 | //[print_2 Create another stack variable 15 | int b = 10; 16 | cout << "b: " << b << '\n'; 17 | cout << "&b (hex): " << &b << '\n'; 18 | cout << "&b: (dec) " << reinterpret_cast(&b) << '\n'; 19 | //] 20 | 21 | //[print_heap Create a value in the heap 22 | auto c = std::make_unique(10); 23 | cout << "*c: " << *c << '\n'; 24 | cout << "c (hex): " << c << '\n'; // address should be distant from a and b 25 | cout << "c: (dec) " << reinterpret_cast(c.get()) << '\n'; 26 | //] 27 | 28 | //[stack_dist Distance between two stack variables 29 | cout << "Distance &b - &a = " << &b - &a << " ints\n"; 30 | cout << "Distance &b - &a = " << reinterpret_cast(&b) - reinterpret_cast(&a) << " bytes\n"; 31 | //] 32 | 33 | //[heap_dist Distance between stack and heap variables 34 | cout << "Distance c.get() - &a = " << c.get() - &a << " ints\n"; 35 | cout << "Distance c.get() - &a = " << reinterpret_cast(c.get()) - reinterpret_cast(&a) << " bytes\n"; 36 | //] 37 | 38 | return 0; 39 | } -------------------------------------------------------------------------------- /snippets/pointers/raw_pointers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | int main() { 9 | //[alloc Pointer to an int on the heap 10 | int *x = new int(5); 11 | //] 12 | 13 | //[print Print pointer address 14 | std::cout << "x: " << x << '\n'; 15 | //] 16 | 17 | //[print_value Print pointed value if any 18 | if (x) { 19 | std::cout << "*x: " << *x << '\n'; 20 | } else { 21 | std::cout << "*x: empty" << '\n'; 22 | } 23 | //] 24 | 25 | //[delete Delete value pointed 26 | // - Forgetting to delete causes memory leaks 27 | // - Forgetting to update to nullptr might lead to segmentation faults 28 | // - Use smart pointers to delete the data automatically 29 | delete x; 30 | x = nullptr; 31 | //] 32 | 33 | //[arrays_raw Raw dynamic arrays 34 | // - This is what existed before vectors 35 | // - Point to a sequence of values 36 | // - Always use vectors instead of this 37 | // - If you need to access the raw data, use vector::data() 38 | int *x2 = new int[10]; 39 | for (int i2 = 0; i2 < 10; ++i2) { 40 | x2[i2] = 10 + i2 * 10; 41 | } 42 | //] 43 | 44 | //[print_dyn Print addresses 45 | std::cout << "x2: " << x2 << '\n'; 46 | std::cout << "&x2[0]: " << &x2[0] << '\n'; 47 | std::cout << "x2[0]: " << x2[0] << '\n'; 48 | //] 49 | 50 | //[print_first Points to the first number in the sequence 51 | std::cout << "*x2: " << *x2 << '\n'; 52 | std::cout << "x2[3]: " << x2[3] << '\n'; 53 | std::cout << "*(x2+3): " << *(x2 + 3) << '\n'; 54 | //] 55 | 56 | //[deallocate Deallocate sequence 57 | // - Slightly different command: more danger 58 | delete[] x2; 59 | x2 = nullptr; 60 | //] 61 | 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /snippets/pointers/references.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | //[stack References to stack value 7 | int n = 1; 8 | int &r1 = n; 9 | int &r2 = r1; 10 | int &r3 = n; 11 | //] 12 | 13 | //[print References as aliases 14 | std::cout << "n: " << n << '\n'; 15 | std::cout << "r1: " << r1 << '\n'; 16 | std::cout << "r2: " << r2 << '\n'; 17 | std::cout << "r3: " << r3 << '\n'; 18 | //] 19 | 20 | //[ref_array Reference to array 21 | int ar[3]; 22 | int(&ra)[3] = ar; 23 | //] 24 | 25 | //[print_array Reference as array alias 26 | std::cout << "ar: " << ar << '\n'; 27 | std::cout << "ra: " << ra << '\n'; 28 | //] 29 | 30 | //[ptr_reference Reference to pointer 31 | int *p = new int(3); 32 | int *&ppr = p; 33 | //] 34 | 35 | //[print_array Reference as pointer alias 36 | std::cout << "p: " << p << '\n'; 37 | std::cout << "ppr: " << ppr << '\n'; 38 | //] 39 | 40 | //[ref_ptr_value Reference to value pointed by p 41 | int &prr = *p; 42 | std::cout << "prr: " << prr << '\n'; 43 | //] 44 | 45 | //[delete_ptr Deleting pointer is not the responsibility of the reference 46 | delete p; 47 | // ppr and prr are now dangling references 48 | //] 49 | 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /snippets/pointers/smart_pointers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | //[unique Unique pointer with no pointed value 6 | // Only one unique pointer can point to an address 7 | std::unique_ptr c; 8 | if (c) { 9 | std::cout << "*c : " << *c << '\n'; 10 | } else { 11 | std::cout << "c is empty" << '\n'; 12 | } 13 | //] 14 | 15 | //[change Changing value of unique pointer 16 | // Previous value is deleted if needed 17 | c = std::make_unique(2); 18 | if (c) { 19 | std::cout << "*c : " << *c << '\n'; 20 | } else { 21 | std::cout << "c is empty" << '\n'; 22 | } 23 | //] 24 | 25 | //[unique_init Initialize unique pointer with value 26 | auto c2 = std::make_unique(3); 27 | //] 28 | 29 | //[swap Swap unique pointers 30 | // Swapping values is valid 31 | c.swap(c2); 32 | // c = c2; <- but copying doesn't work 33 | //] 34 | 35 | //[move_unique Moving values is valid 36 | c = std::move(c2); 37 | if (c) { 38 | std::cout << "New *c : " << *c << '\n'; 39 | } else { 40 | std::cout << "c is empty" << '\n'; 41 | } 42 | //] 43 | 44 | if (c2) { 45 | std::cout << "New *c2 : " << *c << '\n'; 46 | } else { 47 | std::cout << "c2 is empty" << '\n'; 48 | } 49 | 50 | //[shared_ptr Create shared pointer 51 | auto sp = std::make_shared(2); 52 | if (sp) { 53 | std::cout << "New *sp : " << *sp << '\n'; 54 | } else { 55 | std::cout << "sp is empty" << '\n'; 56 | } 57 | //] 58 | 59 | //[share_ptr Share pointed value 60 | std::shared_ptr sp2 = sp; 61 | *sp2 = 3; 62 | if (sp) { 63 | std::cout << "New *sp : " << *sp << '\n'; // 3 64 | } else { 65 | std::cout << "sp is empty" << '\n'; 66 | } 67 | if (sp2) { 68 | std::cout << "New *sp2 : " << *sp << '\n'; // 3 69 | } else { 70 | std::cout << "sp2 is empty" << '\n'; 71 | } 72 | 73 | //[count Count number of shared pointers 74 | // How many pointers are pointing to this number? 75 | std::cout << "There are " << sp.use_count() << " pointers to " << sp.get() 76 | << '\n'; 77 | //] 78 | 79 | return 0; 80 | } -------------------------------------------------------------------------------- /snippets/random/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(random random.cpp) 2 | 3 | # PCG is failing on windows: pcg_uint128.hpp(74,1) - Unable to determine target endianness 4 | # It's not that complicated to find a workaround and set this macro manually 5 | if (NOT WIN32) 6 | #[pcg Find PCG 7 | find_package(pcg-cpp QUIET) 8 | if (NOT pcg-cpp_FOUND) 9 | FetchContent_Declare(pcg-cpp GIT_REPOSITORY https://github.com/imneme/pcg-cpp.git GIT_TAG v0.98.1) 10 | FetchContent_GetProperties(pcg-cpp) 11 | if (NOT pcg-cpp_POPULATED) 12 | FetchContent_Populate(pcg-cpp) 13 | # Create header-only library with pcg-cpp include files 14 | add_library(pcg-cpp INTERFACE) 15 | target_include_directories(pcg-cpp INTERFACE ${pcg-cpp_SOURCE_DIR}/include) 16 | endif () 17 | endif() 18 | add_executable(pcg pcg.cpp) 19 | target_link_libraries(pcg pcg-cpp) 20 | #] 21 | endif() -------------------------------------------------------------------------------- /snippets/random/pcg.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | //[init Initialize generator with two fixed seeds 7 | pcg32 rng(42u, 54u); 8 | //] 9 | 10 | //[init_seed Seed generator with external entropy 11 | rng.seed(pcg_extras::seed_seq_from()); 12 | //] 13 | 14 | //[random Random numbers 15 | std::cout << "Random number: " << rng() << '\n'; 16 | //] 17 | std::cout << "Random number: " << rng() << '\n'; 18 | std::cout << "Random number: " << rng() << '\n'; 19 | 20 | //[flip Flip coins 21 | std::cout << "Flip coin: " << rng(2) << '\n'; 22 | //] 23 | std::cout << "Flip coin: " << rng(2) << '\n'; 24 | std::cout << "Flip coin: " << rng(2) << '\n'; 25 | 26 | //[dice Roll dice 27 | std::cout << "Roll dice: " << rng(6) << '\n'; 28 | //] 29 | std::cout << "Roll dice: " << rng(6) << '\n'; 30 | std::cout << "Roll dice: " << rng(6) << '\n'; 31 | 32 | //[state Print generator state 33 | std::cout << "Generator state: " << rng << '\n'; 34 | std::cout << "Result size: " << sizeof(pcg32::result_type) * 8 << "bits" << '\n'; 35 | std::cout << "Period: 2^" << pcg32::period_pow2() << '\n'; 36 | //] 37 | 38 | //[dist Use with C++ distributions 39 | std::uniform_real_distribution distribution(1.0, 10.0); 40 | std::cout << distribution(rng) << '\n'; 41 | //] 42 | 43 | return 0; 44 | } -------------------------------------------------------------------------------- /snippets/templates/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(template_functions template_functions.cpp) 2 | add_executable(template_alias template_alias.cpp) 3 | 4 | find_package(Concepts) 5 | if (Concepts_FOUND) 6 | #[concepts Find concepts 7 | add_executable(concepts concepts.cpp) 8 | target_compile_features(concepts PRIVATE cxx_std_20) 9 | #] 10 | else () 11 | message("Your compiler does not support *concepts* yet") 12 | endif () 13 | 14 | add_executable(sfinae sfinae.cpp) 15 | 16 | add_executable(metaprogramming metaprogramming.cpp) 17 | -------------------------------------------------------------------------------- /snippets/templates/metaprogramming.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | //[factorial Factorial value computed as constant class value 7 | template struct factorial { 8 | enum { value = n * factorial::value }; 9 | }; 10 | 11 | template <> struct factorial<0> { 12 | enum { value = 1 }; 13 | }; 14 | //] 15 | 16 | void call_meta() { 17 | //[call_factorial Accessing factorial value calculated at compile-time 18 | std::cout << "factorial<7>::value : " << factorial<7>::value << '\n'; 19 | //] 20 | } 21 | 22 | //[constexpr Computing at compile time with constexpr 23 | constexpr int factorial2(int n) { return n <= 1 ? 1 : (n * factorial2(n - 1)); } 24 | //] 25 | 26 | void call_constexpr() { 27 | //[call_factorial Accessing factorial value calculated at compile-time 28 | std::cout << "factorial2(7) : " << factorial2(7) << '\n'; 29 | //] 30 | } 31 | 32 | //[meta_count Count number of elements 33 | struct MyClass { 34 | template static int count() { return 0; } 35 | 36 | template static int count() { 37 | return 1 + count(); 38 | } 39 | }; 40 | //] 41 | 42 | void call_count() { 43 | //[call_count Access number of elements 44 | std::cout << "MyClass::count<'f','o','o'>(): " 45 | << MyClass::count<'f', 'o', 'o'>() << '\n'; // 3 46 | //] 47 | } 48 | 49 | int main() { 50 | call_meta(); 51 | call_constexpr(); 52 | call_count(); 53 | return 0; 54 | } -------------------------------------------------------------------------------- /snippets/templates/template_alias.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | //[alias Template alias for two-dimensional arrays 6 | template 7 | using matrix = std::array, N_ROWS>; 8 | //] 9 | 10 | int main() { 11 | //[use_alias Using a template alias 12 | matrix m; 13 | double i = 5.6; 14 | for (auto &row : m) { 15 | for (auto &xij : row) { 16 | xij = i++; 17 | } 18 | } 19 | //] 20 | 21 | //[use_matrix Iterating the matrix 22 | for (auto &row : m) { 23 | for (auto &xij : row) { 24 | std::cout << "xij: " << xij << '\n'; 25 | } 26 | } 27 | //] 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /snippets/templates/template_functions.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | //[max_int Function with int parameters 4 | int max(int n1, int n2) { return (n1 > n2) ? n1 : n2; } 5 | //] 6 | 7 | //[max_T Function for any type T 8 | template T max(T n1, T n2) { return (n1 > n2) ? n1 : n2; } 9 | //] 10 | 11 | //[max_t1_t2 Function for any types T1 and T2 12 | template T2 max(T1 n1, T2 n2) { 13 | return (n1 > n2) ? n1 : n2; 14 | } 15 | //] 16 | 17 | void call_max() { 18 | //[call_max Calling template function for any data type 19 | std::cout << "max: " << max(3, 9) << '\n'; 20 | std::cout << "max: " << max(3.5, 9.3) << '\n'; 21 | std::cout << "max: " << max(3, 9.3) << '\n'; 22 | //] 23 | } 24 | 25 | //[max_erased Type erased max function 26 | // The "old" way: max operating on nullified pointers 27 | void *max(void *n1, void *n2, bool (*comp)(void *, void *)) { 28 | // `comp` is responsible to internally convert `void*` to the appropriate 29 | // data type and perform the comparison. 30 | return (comp(n1, n2)) ? n1 : n2; 31 | } 32 | //] 33 | 34 | //[comp_erased Type erased comparison function 35 | // The "old" way: an extra function operating on the nullified pointers 36 | bool comp(void *a, void *b) { return (*(int *)a < *(int *)b); } 37 | //] 38 | 39 | void call_max_erased() { 40 | //[call_max_erased Calling function with type erased parameters 41 | // In old C++ and C, we need nullify pointers to create generic functions. 42 | // It's easy to see why this is inconvenient. 43 | int a = 3; 44 | int b = 9; 45 | void *m = max(&a, &b, &comp); 46 | std::cout << "m: " << *(int *)m << '\n'; 47 | //] 48 | } 49 | 50 | //[class Template class 51 | template struct pair { 52 | T1 first; 53 | T2 second; 54 | }; 55 | //] 56 | 57 | int main() { 58 | call_max(); 59 | call_max_erased(); 60 | 61 | //[instance_class Instances of templated objects 62 | pair p{3, 3.3}; 63 | std::cout << "p.first: " << p.first << '\n'; 64 | std::cout << "p.second: " << p.second << '\n'; 65 | //] 66 | 67 | 68 | 69 | return 0; 70 | } -------------------------------------------------------------------------------- /snippets/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ####################################################### 2 | ### Utilities for testing ### 3 | ####################################################### 4 | # Print source location 5 | add_executable(source_location source_location.cpp) 6 | target_compile_features(source_location PRIVATE cxx_std_20) 7 | 8 | # Unit tests in C++20 only 9 | # Still failing on MSVC: 10 | # - ut.hpp(9,1): a declaration can be exported only from a module interface unit; and 11 | # - 'log': ambiguous symbol 12 | if (NOT WIN32) 13 | # boost.ut 14 | #[fetch_boostut Fetch boost.ut 15 | FetchContent_Declare(boost.ut GIT_REPOSITORY https://github.com/boost-ext/ut GIT_TAG v1.1.8) 16 | FetchContent_MakeAvailable(boost.ut) 17 | #] 18 | #[link_boostut Link boost.ut 19 | add_executable(unit_tests unit_tests_ut.cpp) 20 | target_link_libraries(unit_tests PRIVATE boost.ut) 21 | #] 22 | if (NOT MSVC) 23 | target_compile_options(unit_tests PRIVATE -Wno-comma) 24 | endif() 25 | endif() 26 | 27 | # Unit tests 28 | #[find_catch2 Find Catch2 29 | find_package(Catch2 CONFIG) 30 | if (Catch2_FOUND) 31 | include(${Catch2_DIR}/Catch.cmake) 32 | else () 33 | FetchContent_Declare(Catch2 URL https://github.com/catchorg/Catch2/archive/refs/tags/v2.13.6.zip) 34 | FetchContent_GetProperties(Catch2) 35 | if (NOT Catch2_POPULATED) 36 | FetchContent_Populate(Catch2) 37 | set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) 38 | set(CATCH_USE_VALGRIND OFF) # "Perform SelfTests with Valgrind" 39 | set(CATCH_BUILD_TESTING OFF) # "Build SelfTest project" 40 | set(CATCH_BUILD_EXAMPLES OFF) # "Build documentation examples" 41 | set(CATCH_BUILD_EXTRA_TESTS OFF) # "Build extra tests" 42 | set(CATCH_BUILD_STATIC_LIBRARY OFF) # "Builds static library from the main implementation. EXPERIMENTAL" 43 | set(CATCH_ENABLE_COVERAGE OFF) # "Generate coverage for codecov.io" 44 | set(CATCH_ENABLE_WERROR OFF) # "Enable all warnings as errors" 45 | set(CATCH_INSTALL_DOCS OFF) # "Install documentation alongside library" 46 | set(CATCH_INSTALL_HELPERS ON) # "Install contrib alongside library" 47 | add_subdirectory(${catch2_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/catch2) 48 | include(${catch2_SOURCE_DIR}/contrib/Catch.cmake) 49 | endif () 50 | endif () 51 | #] 52 | #[link_catch2 Link Catch2 53 | add_executable(unit_tests_catch unit_tests_catch.cpp) 54 | target_link_libraries(unit_tests_catch PRIVATE Catch2::Catch2) 55 | #] 56 | 57 | # Plots 58 | if (EXPECTED_COMPILER) 59 | #[find_matplot Find Matplot++ 60 | find_package(Matplot++ QUIET) 61 | #] 62 | #[link_matplot Link Matplot++ 63 | if (Matplot++_FOUND) 64 | add_executable(plots plots.cpp) 65 | target_link_libraries(plots PRIVATE Matplot++::matplot) 66 | endif () 67 | #] 68 | endif () -------------------------------------------------------------------------------- /snippets/tests/plots.cpp: -------------------------------------------------------------------------------- 1 | //[headers Headers 2 | #include 3 | //] 4 | 5 | int main() { 6 | //[line_plot Line plot 7 | matplot::plot(std::vector{1, 2, 3, 4, 5, 6}); 8 | matplot::show(); 9 | //] 10 | return 0; 11 | } -------------------------------------------------------------------------------- /snippets/tests/source_location.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #if defined(__has_include) && __has_include("") 5 | //[headers Headers 6 | #include 7 | //] 8 | #else 9 | #include "source_location.h" 10 | #endif 11 | 12 | //[function Function that requires source location 13 | void print_msg_with_line( 14 | std::string_view message, 15 | const std::source_location &location = std::source_location::current()) { 16 | std::cout << "info: " << location.file_name() << ':' << location.line() 17 | << ' ' << message << '\n'; 18 | } 19 | //] 20 | 21 | int main() { 22 | //[call Call function with source location 23 | print_msg_with_line("Hello world!"); 24 | //] 25 | return 0; 26 | } -------------------------------------------------------------------------------- /snippets/tests/source_location.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Alan Freitas on 17/11/20. 3 | // 4 | 5 | #ifndef MODERNCPP_SOURCE_LOCATION_H 6 | #define MODERNCPP_SOURCE_LOCATION_H 7 | 8 | namespace std { 9 | class source_location { 10 | public: 11 | [[nodiscard]] static constexpr auto current( 12 | #if defined(__has_builtin) && __has_builtin(__builtin_FILE) && __has_builtin(__builtin_LINE) 13 | const char* file = __builtin_FILE(), int line = __builtin_LINE() 14 | #else 15 | const char *file = "unknown", int line = {} 16 | #endif 17 | ) noexcept { 18 | source_location sl{}; 19 | sl.file_ = file; 20 | sl.line_ = line; 21 | return sl; 22 | } 23 | 24 | [[nodiscard]] constexpr auto file_name() const noexcept { return file_; } 25 | 26 | [[nodiscard]] constexpr auto line() const noexcept { return line_; } 27 | 28 | private: 29 | const char *file_{"unknown"}; 30 | int line_{}; 31 | }; 32 | } 33 | 34 | 35 | #endif // MODERNCPP_SOURCE_LOCATION_H 36 | -------------------------------------------------------------------------------- /snippets/tests/unit_tests_catch.cpp: -------------------------------------------------------------------------------- 1 | //[headers Headers 2 | #define CATCH_CONFIG_MAIN 3 | #include 4 | //] 5 | 6 | static int Factorial(int number) { 7 | return number <= 1 ? number : Factorial(number - 1) * number; // fail 8 | // return number <= 1 ? 1 : Factorial( number - 1 ) * number; // pass 9 | } 10 | 11 | //[test_case Create test case 12 | TEST_CASE("Factorial of 0 is 1 (fail)", "[single-file]") { 13 | REQUIRE(Factorial(0) == 1); 14 | } 15 | //] 16 | 17 | //[test_case_2 Create test case 18 | TEST_CASE("Factorials of 1 and higher are computed (pass)", "[single-file]") { 19 | REQUIRE(Factorial(1) == 1); 20 | REQUIRE(Factorial(2) == 2); 21 | REQUIRE(Factorial(3) == 6); 22 | REQUIRE(Factorial(10) == 3628800); 23 | } 24 | //] -------------------------------------------------------------------------------- /snippets/utilities/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(regex regex.cpp) --------------------------------------------------------------------------------