├── .github └── workflows │ └── workflow.yml ├── CMakeLists.txt ├── LICENSE ├── README.md ├── allocators ├── CMakeLists.txt ├── attempt1.cc ├── attempt2.cc ├── diffallocs.cc ├── freelist.cc ├── freelist.hpp ├── logging.cc ├── logging.hpp ├── pmrexample.cc ├── pmrtestres.cc ├── pmrtestres.hpp ├── scopedalloc.cc ├── shortalloc.cc ├── shortalloc.hpp ├── slist.cc └── slist.hpp ├── atomics ├── CMakeLists.txt ├── atomic_counter_demo.cc ├── atomic_counter_demo.plot ├── atomic_twice_demo.cc ├── atomic_twice_demo.plot ├── chasing_demo.cc ├── chasing_test.cc ├── custom_mutex_demo.cc ├── custom_mutex_demo.plot ├── inc_corr.cc ├── inc_naive.cc ├── lockfree_basic_bench.cc ├── lockfree_bench.cc ├── lockfree_comparison.plot ├── lockfree_queue.cc ├── lockfree_queue_demo.cc ├── lockfree_queue_improved_demo.cc ├── lockfree_queue_wrong.cc ├── sptr_atomic.cc ├── sptr_mutex.cc ├── sptr_race.cc ├── stack_reclaim_direct.cc ├── stack_reclaim_problem.cc ├── stack_reclaim_sptr.cc └── stack_reclaim_sptr_wrong.cc ├── classtemplates ├── CMakeLists.txt ├── backward.cc ├── danger1.cc ├── danger2.cc ├── dedguide.cc ├── dedsimple.cc ├── forint.cc ├── member-func-spec.cc ├── member-func.cc ├── partial-func.cc ├── partial-primer.cc └── point-of-decl.cc ├── concepts ├── CMakeLists.txt ├── compound.cc ├── contain.cc ├── difference-complex-simple.cc ├── distance-mystery.cc ├── distance-too-simple.cc ├── distance-working.cc ├── eq-complexreq.cc ├── eq-constexprif.cc ├── eq-enableif.cc ├── eq-require.cc ├── eq.cc ├── explicitreq.cc ├── impossible.cc ├── minelt.cc ├── partial.cc └── strange.cc ├── concurrency ├── CMakeLists.txt ├── dcl.cc ├── dcl_once.cc ├── deadlock.cc ├── dining_lock.cc ├── dining_naive.cc ├── focus_demo.cc ├── locations_ok.cc ├── locations_ub.cc ├── lock_guard.cc ├── mutex_solution.cc ├── notify_all.cc ├── notify_one.cc ├── posix_solution.cc ├── race_demo.cc ├── race_demo_volatile.cc ├── shared_lock_bench.cc ├── spawned_id.cc ├── sutter_case.cc ├── thread_create.cc └── volatile.cc ├── constexpr ├── CMakeLists.txt ├── binparser.cc ├── cce.cc ├── cecollatz.cc ├── cenew.cc ├── cepred-expr.cc ├── ceval-cinit.cc ├── cexpr-local.cc ├── complex-op.cc ├── complex.cc ├── ctconst.cc ├── ctfield.cc ├── ctmap.cc ├── ctstrcpy.cc ├── cycle.cc ├── heavy.cc ├── ifcedetails.cc ├── mplike.cc ├── numlimits-fixed.cc ├── numlimits.cc ├── trits-op.cc ├── trits.cc ├── ubsan-dependent.cc ├── ubsan.cc ├── virtce-ok.cc └── virtce.cc ├── coroutines ├── CMakeLists.txt ├── cancellable.cc ├── fsm.cc ├── futures.cc ├── natseq.cc ├── natseq_range.cc ├── natseq_zip.cc ├── optional.cc ├── resumable.cc ├── subscribers.cc ├── subscribers_mt.cc ├── subscribers_mt_demo.cc ├── subscribers_mt_req.cc └── subscribers_natlst.cc ├── functempls ├── CMakeLists.txt ├── class-typename.cc ├── crocodile.cc ├── deduce-default.cc ├── deduce-generalized.cc ├── deduce-nttp.cc ├── deduce-partial.cc ├── deduce-qual.cc ├── deduce-spec.cc ├── generate-then-delete.cc ├── ics-tail.cc ├── instantiations-demo │ ├── 01-naive │ │ ├── Makefile │ │ ├── main.cc │ │ ├── max.hpp │ │ ├── maxuser1.cc │ │ └── maxuser2.cc │ ├── 02-block │ │ ├── Makefile │ │ ├── main.cc │ │ ├── max.hpp │ │ ├── maxuser1.cc │ │ └── maxuser2.cc │ └── 03-force │ │ ├── Makefile │ │ ├── main.cc │ │ ├── max.cc │ │ ├── max.hpp │ │ ├── maxuser1.cc │ │ └── maxuser2.cc ├── name-hiding.cc ├── name-res-examples.cc ├── non-type-params.cc ├── non-type-spec.cc ├── nth-power-clean.cc ├── nth-power-concept.cc ├── nth-power-concrete.cc ├── nth-power-naive.cc ├── nth-power-traits.cc ├── templ-inst-spec.cc ├── templ-templ.cc └── whats-call.cc ├── inference ├── CMakeLists.txt ├── bindfail.cc ├── jcase_broken_deftype.cc ├── jcase_broken_fwd.cc ├── jcase_deftype.cc ├── jcase_forward.cc ├── jcase_negative.cc ├── jcase_positive.cc ├── jcase_single.cc ├── leftbind.cc ├── nrvo.cc ├── refovr.cc └── rightbind.cc ├── lambdas ├── CMakeLists.txt ├── callables.cc ├── decltyped.cc ├── explicit.cc ├── fwd_capture.cc ├── fwd_capture_astuple.cc ├── fwd_capture_problem.cc ├── generic_fail_demo.cc ├── implcast.cc ├── invoke.cc ├── more_transparent.cc ├── projection.cc ├── propagated.cc ├── renaming.cc ├── transparent.cc ├── tricky_capture_demo.cc └── vapack.cc ├── modules ├── discarded.cc ├── extended │ ├── first_extended.cppm │ ├── first_extended.pcm │ ├── first_module.cppm │ ├── first_module.pcm │ ├── main.cc │ └── runme.sh ├── fullspec-1.cc ├── fullspec-2.cc ├── fullspec.hpp ├── global-fragment │ ├── global.cppm │ ├── global.hpp │ ├── global.pcm │ ├── main.cc │ └── runme.sh ├── hello-afx.cc ├── hello-modules │ ├── hello.cppm │ ├── main.cc │ └── runme.sh ├── hello.cc ├── imports │ ├── imported.cppm │ ├── main.cc │ └── runme.sh ├── odruse.cc ├── pcl-introduce-modules │ ├── Makefile │ ├── Node.cpp │ ├── Node.cppm │ ├── Symtab.cppm │ ├── compiler.y │ ├── driver.cpp │ ├── parser.hpp │ ├── scanner.l │ └── tests │ │ └── fib │ │ ├── file.in │ │ ├── file.out │ │ └── file.pcl ├── pcl-modular │ ├── Makefile │ ├── Node.cpp │ ├── Node.cppm │ ├── Symtab.cppm │ ├── compiler.y │ ├── driver.cpp │ ├── parser.cppm │ ├── scanner.l │ ├── tests │ │ └── fib │ │ │ ├── file.in │ │ │ ├── file.out │ │ │ └── file.pcl │ └── yyret.h ├── pcl-naive │ ├── INode.hpp │ ├── Makefile │ ├── Node.cpp │ ├── Node.hpp │ ├── Symtab.hpp │ ├── compiler.y │ ├── driver.cpp │ ├── parser.hpp │ ├── scanner.l │ └── tests │ │ └── fib │ │ ├── file.in │ │ ├── file.out │ │ └── file.pcl ├── simplest │ ├── first_module.cppm │ ├── first_module.pcm │ ├── main.cc │ └── runme.sh ├── stdafx.h ├── templ-twophase │ ├── main.cc │ ├── runme.sh │ └── twophase.cppm └── visibility │ ├── main.cc │ ├── reachable.cppm │ ├── runme.sh │ └── unreachable.cppm ├── parallel ├── CMakeLists.txt ├── algo_bench.cc ├── algo_bench.plot ├── lambdas_async.cc ├── my_reduce.cc ├── my_reduce_async.cc ├── my_reduce_pkg.cc ├── paralg.cc ├── reduce_bench.cc └── reduce_bench.plot ├── parasl └── parasl.txt ├── queues ├── CMakeLists.txt ├── auto_return_generic.cc ├── auto_return_wrong.cc ├── basic_return.cc ├── classic_queue.cc ├── classic_queue_bench.cc ├── classic_queue_demo.cc ├── classic_queue_wrong-01.cc ├── classic_queue_wrong-02.cc ├── classic_queue_wrong-03.cc ├── classic_queue_wrong-04.cc ├── classic_stack.cc ├── classic_stack_demo.cc ├── classic_stack_wrong_demo.cc ├── futures.cc ├── latch.cc ├── marshalling.cc ├── packaged.cc ├── shared.cc └── unbounded_queue_demo.cc ├── ranges ├── CMakeLists.txt ├── brokenfilter.cc ├── buggy-concat.cc ├── common.cc ├── constfilter.cc ├── counted.cc ├── danglemessage.cc ├── dangling.cc ├── endvalue.cc ├── errmsg.cc ├── fibiter.cc ├── nondangleview.cc ├── nonsfinaeissue.cc ├── notlazy.cc ├── proj.cc ├── pullmodel.cc ├── sentinel.cc ├── sfinaeissue.cc ├── simplecomb.cc ├── strangeissue.cc ├── subsort.cc ├── takemore.cc ├── teaser.cc ├── tostr_adaptor.cc ├── tostr_view.cc ├── transformed.cc ├── trimbetter.cc ├── trimnaive.cc ├── typed.cc ├── unreachable.cc └── working-concat.cc ├── runtimepoly ├── CMakeLists.txt ├── crtp_mixins.cc ├── crtpcost_demo.cc ├── discouraging_function.cc ├── dynamic_casts.cc ├── dyncast_cost_demo.cc ├── init_seq.cc ├── romb_novirt.cc ├── romb_throw.cc ├── sean_parents.cc ├── virtcost_demo.cc ├── virtinh_cost_demo.cc ├── virtintf.cc ├── virtintf_crtp.cc ├── virtual_clone_base.cc ├── virtual_clone_mixin.cc └── visible_base.cc ├── sfinae ├── CMakeLists.txt ├── detected.cc ├── discrim-custom.cc ├── enableif-ints.cc ├── enableif-naive.cc ├── enableif-ptrs.cc ├── fireonce-naive.cc ├── fireonce-trampoline.cc ├── fusion-adapt.cc ├── hasfoobar-naive.cc ├── hasfoobar.cc ├── lazyness.cc ├── logic-broken.cc ├── logic-fixed.cc ├── mpltags.cc ├── sfinae-negate.cc ├── st.cc └── void-discrim.cc ├── smartptrs ├── CMakeLists.txt ├── movable.cc ├── moveret_demo.cc ├── prvalue.cc ├── sankels.cc └── sankels_complete.cc ├── strings ├── CMakeLists.txt ├── conversions.cc ├── cstrs.cc ├── fmt.cc ├── hello.cc └── tokenizer.cc ├── utils ├── memuse.hpp ├── opts.hpp └── timer.hpp └── variadics ├── CMakeLists.txt ├── addable.cc ├── addable2.cc ├── commas.cc ├── conj.cc ├── cstyle.cc ├── cxxstyle_another_ok.cc ├── cxxstyle_ok.cc ├── cxxstyle_wrong.cc ├── exoticfold.cc ├── expansion.cc ├── expansion_initlist.cc ├── expansion_proxy.cc ├── expansion_wrong.cc ├── ineff.cc ├── mixins.cc ├── moreeff.cc ├── realeff.cc ├── reqpack.cc ├── sumall.cc ├── twopacks.cc └── voidpack.cc /.github/workflows/workflow.yml: -------------------------------------------------------------------------------- 1 | name: C++ masters course pre-commit and post-push 2 | on: 3 | push: 4 | branches: 5 | - master 6 | pull_request: 7 | branches: 8 | - master 9 | jobs: 10 | main: 11 | runs-on: ubuntu-latest 12 | defaults: 13 | run: 14 | shell: bash 15 | steps: 16 | - name: Install google test and boost, also install g++-12 (for atomic shared pointers) 17 | run: sudo apt-get install libgtest-dev googletest googletest-tools google-mock libboost-dev g++-12 18 | - name: Checkout repository 19 | uses: actions/checkout@v3 20 | - name: CMake release config 21 | run: cmake -S . -B build -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_BUILD_TYPE=Release 22 | - name: CMake release build 23 | run: cmake --build build 24 | - name: CMake release test 25 | run: env CTEST_OUTPUT_ON_FAILURE=1 cmake --build build --target test 26 | - name: CMake debug config 27 | run: cmake -S . -B debug -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_BUILD_TYPE=Release 28 | - name: CMake debug build 29 | run: cmake --build debug 30 | - name: CMake debug test 31 | run: env CTEST_OUTPUT_ON_FAILURE=1 cmake --build debug --target test 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cpp-masters 2 | 3 | C++ masters course revisited. Repo mostly contains examples, shaped as unit tests. 4 | 5 | ## Building and testing repo 6 | 7 | You will need at least g++-12 because some examples are using atomic 8 | 9 | Full prerequisite list 10 | 11 | ``` 12 | sudo apt-get install libgtest-dev googletest googletest-tools google-mock libboost-dev g++-12 ninja-build 13 | ``` 14 | 15 | Release build 16 | 17 | ``` 18 | cmake -G Ninja -B build -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_BUILD_TYPE=Release . 19 | cmake --build build 20 | env CTEST_OUTPUT_ON_FAILURE=1 cmake --build build --target test 21 | ``` 22 | 23 | Debug build 24 | 25 | ``` 26 | cmake -G Ninja -B debug -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_BUILD_TYPE=Debug . 27 | cmake --build debug 28 | env CTEST_OUTPUT_ON_FAILURE=1 cmake --build debug --target test 29 | ``` 30 | 31 | -------------------------------------------------------------------------------- /allocators/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # 3 | # Source code for MIPT masters course on C++ 4 | # Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | # Licensed after GNU GPL v3 6 | # 7 | #------------------------------------------------------------------------------ 8 | # 9 | # Build system for examples (allocators lecture) 10 | # 11 | # Order of examples in SRCS variable corresponds to the order in the lecture. 12 | # Examples commented out are broken (often -- intentionally). 13 | # 14 | # Try: cmake -DCMAKE_CXX_COMPILER=clang++-15 .. 15 | # 16 | #------------------------------------------------------------------------------ 17 | 18 | set(SRCS 19 | attempt1.cc 20 | attempt2.cc 21 | logging.cc 22 | freelist.cc 23 | shortalloc.cc 24 | diffallocs.cc 25 | # scopedalloc.cc -- problematic case, interesting CT error 26 | pmrexample.cc 27 | pmrtestres.cc 28 | slist.cc 29 | ) 30 | 31 | add_gtest(allocs) 32 | -------------------------------------------------------------------------------- /allocators/freelist.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Freelist allocator example tests 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "freelist.hpp" 20 | #include "gtest/gtest.h" 21 | 22 | TEST(allocs, freelist) { 23 | std::vector> v; 24 | for (int i = 0; i < 16; ++i) 25 | v.push_back(i); 26 | printf("---\n"); 27 | std::list> l(v.begin(), v.end()); 28 | printf("---\n"); 29 | l.remove(2); 30 | l.remove(6); 31 | l.insert(l.begin(), -1); 32 | l.insert(l.begin(), -3); 33 | l.insert(l.begin(), -5); 34 | printf("---\n"); 35 | } -------------------------------------------------------------------------------- /allocators/logging.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // C++98 allocs: finished logging alloc tests 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "logging.hpp" 20 | #include "gtest/gtest.h" 21 | 22 | TEST(allocs, logging) { 23 | std::vector> v; 24 | 25 | for (int i = 0; i < 16; ++i) 26 | v.push_back(i); 27 | printf("---\n"); 28 | std::vector> v2 = v; 29 | v2.push_back(16); 30 | EXPECT_EQ(v2[16], 16); 31 | 32 | // problems: 33 | 34 | // 1. Assign (what to do with allocator on assign?) 35 | #if defined(PROBLEM1) 36 | v = v2; 37 | #endif 38 | 39 | // 2. Rebind (how to create allocator for the list node from T?) 40 | #if defined(PROBLEM2) 41 | std::list> l(v.begin(), v.end()); 42 | #endif 43 | } -------------------------------------------------------------------------------- /allocators/pmrexample.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Example usage of PMR 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "gtest/gtest.h" 19 | 20 | #include "memuse.hpp" 21 | 22 | TEST(allocs, pmr) { 23 | auto initial = memuse(); 24 | constexpr size_t sz = 1000 * sizeof(double); 25 | alignas(double) char buffer[sz]; 26 | std::pmr::monotonic_buffer_resource alloc(buffer, sz); 27 | double start = 0.0; 28 | std::pmr::vector v1(&alloc); 29 | std::generate_n(std::back_inserter(v1), 10, 30 | [start]() mutable { return (start += 1.25); }); 31 | EXPECT_EQ(memuse(), initial); 32 | 33 | for (int i = 0; i < v1.size(); ++i) 34 | EXPECT_EQ(v1[i], (i + 1) * 1.25); 35 | } -------------------------------------------------------------------------------- /allocators/pmrtestres.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Simple PMR test resource tests 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "pmrtestres.hpp" 21 | #include "gtest/gtest.h" 22 | 23 | static auto mtgen() { 24 | static std::random_device rd; 25 | static std::mt19937 g(rd()); 26 | return g; 27 | } 28 | 29 | TEST(allocs, memres) { 30 | test_resource talloc; 31 | 32 | // allocate smth to leak 33 | (void)talloc.allocate(10, 4); 34 | 35 | double start = 0.0; 36 | std::pmr::vector v1(&talloc); 37 | std::generate_n(back_inserter(v1), 100, 38 | [start]() mutable { return (start += 1.25); }); 39 | 40 | std::pmr::vector v2(&talloc); 41 | v2.assign(v1.rbegin(), v1.rend()); 42 | 43 | EXPECT_EQ(v1[42], 53.75); 44 | EXPECT_EQ(v2[42], 72.5); 45 | } 46 | -------------------------------------------------------------------------------- /allocators/slist.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Simple PMR allocator-aware container example 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "memuse.hpp" 21 | #include "slist.hpp" 22 | #include "gtest/gtest.h" 23 | 24 | TEST(allocs, slist) { 25 | auto initial = memuse(); 26 | constexpr size_t sz = 1000 * sizeof(int); 27 | alignas(int) char buffer[sz]; 28 | 29 | std::pmr::monotonic_buffer_resource res(buffer, sz); 30 | 31 | slist s(&res); 32 | s.push_back(10); 33 | s.push_back(20); 34 | s.push_front(30); 35 | s.push_front(40); 36 | 37 | slist s1(s, s.get_allocator()); 38 | slist s2(std::move(s1)); 39 | 40 | for (auto x : s2) 41 | printf("%d\n", x); 42 | 43 | EXPECT_EQ(initial, memuse()); 44 | } 45 | -------------------------------------------------------------------------------- /atomics/atomic_counter_demo.plot: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # 3 | # Gnuplot script for atomic vs mutex counter experiment 4 | # 5 | # collect data with gemm.rb 6 | # ./build/atomics/atomic_counter_demo > mutex_cnt.dat 7 | # ./build/atomics/atomic_counter_demo -atomic=1 > atomic_cnt.dat 8 | # 9 | # run plotter with 10 | # > gnuplot -persist -c ./atomics/atomic_counter_demo.plot 11 | # 12 | #------------------------------------------------------------------------------ 13 | # 14 | # This file is licensed after LGPL v3 15 | # Look at: https://www.gnu.org/licenses/lgpl-3.0.en.html for details 16 | # 17 | #------------------------------------------------------------------------------ 18 | 19 | set term png 20 | set grid 21 | set key left top 22 | set xlabel "number of threads" 23 | set ylabel "time (milliseconds)" 24 | 25 | # atomic vs mutex counter 26 | set output "atomic_counter_demo.png" 27 | plot 'mutex_cnt.dat' with linespoints title 'Counter protected by mutex',\ 28 | 'atomic_cnt.dat' with linespoints t 'Atomic counter' 29 | -------------------------------------------------------------------------------- /atomics/atomic_twice_demo.plot: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # 3 | # Gnuplot script for atomic vs mutex counter experiment 4 | # 5 | # collect data with gemm.rb 6 | # ./build/atomics/atomic_twice_demo > mutex_cnt.dat 7 | # ./build/atomics/atomic_twice_demo -atomic=1 > atomic_cnt.dat 8 | # 9 | # run plotter with 10 | # > gnuplot -persist -c ./atomics/atomic_twice_demo.plot 11 | # 12 | #------------------------------------------------------------------------------ 13 | # 14 | # This file is licensed after LGPL v3 15 | # Look at: https://www.gnu.org/licenses/lgpl-3.0.en.html for details 16 | # 17 | #------------------------------------------------------------------------------ 18 | 19 | set term png 20 | set grid 21 | set key left top 22 | set xlabel "number of threads" 23 | set ylabel "time (milliseconds)" 24 | 25 | # atomic vs mutex counter 26 | set output "atomic_twice_demo.png" 27 | plot 'mutex_cnt.dat' with linespoints title 'Counter protected by mutex',\ 28 | 'atomic_cnt.dat' with linespoints t 'Atomic counter' 29 | -------------------------------------------------------------------------------- /atomics/chasing_demo.cc: -------------------------------------------------------------------------------- 1 | // g++-11 -O2 --std=c++20 atomics/chasing_demo.cc -pthread 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | volatile long long a = 0, b = 0; 8 | std::atomic wrongcount = 0; 9 | long long MAXCOUNT = 1ll << 20; 10 | 11 | // a is always > b 12 | void chase() { 13 | for (;;) { 14 | a = a + 1; 15 | b = b + 1; 16 | if (a > MAXCOUNT) 17 | break; 18 | } 19 | } 20 | 21 | // check that a > b 22 | void check() { 23 | for (;;) { 24 | long long bval = b; 25 | long long aval = a; 26 | if (aval < bval) { 27 | wrongcount += 1; 28 | break; 29 | } 30 | if (aval > MAXCOUNT) 31 | break; 32 | } 33 | } 34 | 35 | int main() { 36 | std::thread t1{chase}; 37 | std::thread t2{check}; 38 | t1.join(); 39 | t2.join(); 40 | auto w = wrongcount.load(); 41 | if (w != 0) 42 | std::cout << "Wrong " << w << "times\n"; 43 | return w; 44 | } 45 | -------------------------------------------------------------------------------- /atomics/chasing_test.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "gtest/gtest.h" 7 | 8 | volatile long long a = 0, b = 0; 9 | std::atomic wrongcount = 0; 10 | long long MAXCOUNT = 1ll << 10; 11 | 12 | // a is always > b 13 | void chase() { 14 | for (;;) { 15 | a += 1; 16 | b += 1; 17 | if (a > MAXCOUNT) 18 | break; 19 | } 20 | } 21 | 22 | // check that a > b 23 | void check() { 24 | for (;;) { 25 | long long bval = b; 26 | long long aval = a; 27 | if (aval < bval) { 28 | wrongcount += 1; 29 | break; 30 | } 31 | if (aval > MAXCOUNT) 32 | break; 33 | } 34 | } 35 | 36 | TEST(atomics, chase) { 37 | std::thread t1{chase}; 38 | std::thread t2{check}; 39 | t1.join(); 40 | t2.join(); 41 | EXPECT_EQ(wrongcount, 0); 42 | } 43 | -------------------------------------------------------------------------------- /atomics/inc_corr.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "gtest/gtest.h" 7 | 8 | namespace { 9 | 10 | constexpr int NTHREAD = 8; 11 | constexpr int NITER = 1000; 12 | 13 | struct Counters { 14 | int A = 0, B = 0; 15 | }; 16 | 17 | std::atomic ACnt; 18 | 19 | void increment(std::atomic &Cnt) { 20 | Counters Cnl = ACnt.load(), Cnn; 21 | do { 22 | if (Cnl.A >= NTHREAD * NITER) 23 | break; 24 | Cnn = {Cnl.A + 1, Cnl.B + 1}; 25 | } while (!ACnt.compare_exchange_weak(Cnl, Cnn)); 26 | } 27 | 28 | void threadfunc() { 29 | for (int i = 0; i < NITER; ++i) { 30 | increment(ACnt); 31 | } 32 | } 33 | 34 | } // namespace 35 | 36 | TEST(atomics, inc_corr) { 37 | std::vector Threads(NTHREAD); 38 | for (auto &&t : Threads) 39 | t = std::thread(threadfunc); 40 | for (auto &&t : Threads) 41 | t.join(); 42 | Counters Val = ACnt.load(); 43 | EXPECT_EQ(Val.A, NTHREAD * NITER); 44 | EXPECT_EQ(Val.B, NTHREAD * NITER); 45 | } -------------------------------------------------------------------------------- /atomics/inc_naive.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "gtest/gtest.h" 7 | 8 | namespace { 9 | 10 | constexpr int NTHREAD = 8; 11 | constexpr int NITER = 1000; 12 | 13 | struct Counters { 14 | int A = 0, B = 0; 15 | }; 16 | 17 | std::atomic ACnt; 18 | 19 | void increment(std::atomic &Cnt) { 20 | Counters Val = Cnt.load(); 21 | Val.A += 1; 22 | Val.B += 1; 23 | Cnt.store(Val); 24 | } 25 | 26 | void threadfunc() { 27 | for (int i = 0; i < NITER; ++i) { 28 | increment(ACnt); 29 | } 30 | } 31 | 32 | } // namespace 33 | 34 | TEST(atomics, inc_naive) { 35 | std::vector Threads(NTHREAD); 36 | for (auto &&t : Threads) 37 | t = std::thread(threadfunc); 38 | for (auto &&t : Threads) 39 | t.join(); 40 | Counters Val = ACnt.load(); 41 | EXPECT_EQ(Val.A, NTHREAD * NITER); 42 | EXPECT_EQ(Val.B, NTHREAD * NITER); 43 | } -------------------------------------------------------------------------------- /classtemplates/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # 3 | # Source code for MIPT masters course on C++ 4 | # Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | # Licensed after GNU GPL v3 6 | # 7 | #------------------------------------------------------------------------------ 8 | # 9 | # Build system for examples (class templates lecture) 10 | # 11 | # Order of examples in SRCS variable corresponds to the order in the lecture. 12 | # Examples commented out are broken (often -- intentionally). 13 | # 14 | #------------------------------------------------------------------------------ 15 | 16 | set(SRCS 17 | point-of-decl.cc 18 | # danger-1.cc -- requires separate build 19 | # danger-2.cc -- requires separate build 20 | partial-primer.cc 21 | backward.cc 22 | partial-func.cc 23 | member-func.cc 24 | member-func-spec.cc 25 | forint.cc 26 | dedguide.cc 27 | dedsimple.cc 28 | ) 29 | 30 | add_gtest(classtempls) -------------------------------------------------------------------------------- /classtemplates/backward.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Partial specialization other way 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | #include 15 | 16 | template struct vector {}; 17 | 18 | template struct X { int primary = 1; }; 19 | 20 | template struct X> { int partial = 2; }; 21 | 22 | TEST(classtempls, backward) { 23 | X a; 24 | X> b; 25 | EXPECT_EQ(a.primary, 1); 26 | EXPECT_EQ(b.partial, 2); 27 | } -------------------------------------------------------------------------------- /classtemplates/danger1.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Danger example: see also danger2 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include 14 | 15 | template struct D { 16 | enum { max = 10 }; 17 | }; 18 | 19 | // here we requested instance of D 20 | char buffer[D::max]; 21 | 22 | extern void clear(char *buf); 23 | 24 | int main() { 25 | std::cout << "Requesting to clean " << D::max << std::endl; 26 | clear(buffer); 27 | } 28 | -------------------------------------------------------------------------------- /classtemplates/danger2.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Danger example: see also danger1 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include 14 | 15 | template struct D; 16 | 17 | // we explicitly specialized D 18 | // but it was instanced in another TU 19 | // this is clearly IFNDR 20 | template <> struct D { 21 | enum { max = 100 }; 22 | }; 23 | 24 | void clear(char *buf) { 25 | std::cout << "cleaning up " << D::max << std::endl; 26 | for (int k = 0; k < D::max; ++k) 27 | buf[k] = 0; 28 | } 29 | -------------------------------------------------------------------------------- /classtemplates/dedguide.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Deduction guide for iterator pair 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | #include 15 | 16 | template struct container { 17 | int n = 0; 18 | container(T t) : n(1) {} 19 | template container(Iter beg, Iter end) : n(2) {} 20 | }; 21 | 22 | template 23 | using value_t = typename std::iterator_traits::value_type; 24 | 25 | template container(Iter b, Iter e) -> container>; 26 | 27 | TEST(classtempls, dedguide) { 28 | container c(7); // OK 29 | std::vector v = {1, 2, 3}; // OK (same reasons) 30 | auto d = container(v.begin(), v.end()); // OK: deduces T=double 31 | EXPECT_EQ(c.n, 1); 32 | EXPECT_EQ(d.n, 2); 33 | } -------------------------------------------------------------------------------- /classtemplates/dedsimple.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Deduction guide without ctor 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | #include 15 | 16 | template struct NamedValue { 17 | T value; 18 | std::string name; 19 | }; 20 | 21 | NamedValue(const char *, const char *)->NamedValue; 22 | 23 | TEST(classtempls, dedsimple) { 24 | NamedValue n{"hello", "world"}; // OK 25 | EXPECT_EQ(n.name, "world"); 26 | } -------------------------------------------------------------------------------- /classtemplates/forint.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Overload for int 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | #include 15 | 16 | template struct Type2Type { using OriginalType = T; }; 17 | 18 | template struct A { 19 | int func() { return internal_func(Type2Type()); } 20 | 21 | private: 22 | template int internal_func(V) { return 1; } 23 | int internal_func(Type2Type) { return 2; } 24 | }; 25 | 26 | TEST(classtempls, forint) { 27 | A a; 28 | A b; 29 | EXPECT_EQ(a.func(), 2); 30 | EXPECT_EQ(b.func(), 1); 31 | } -------------------------------------------------------------------------------- /classtemplates/member-func.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Member template function and twice-template 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | #include 15 | 16 | struct Data { 17 | template T read() const { return {}; } 18 | }; 19 | 20 | template class DataReader { 21 | const T &source_; 22 | 23 | public: 24 | DataReader(const T &source) : source_(source) {} 25 | template R read(); 26 | }; 27 | 28 | template template R DataReader::read() { 29 | R res = source_.template read(); 30 | return res; 31 | } 32 | 33 | TEST(classtempls, memfunc) { 34 | Data d; 35 | DataReader reader(d); 36 | auto myval = reader.read(); 37 | EXPECT_EQ(myval, 0); 38 | } -------------------------------------------------------------------------------- /classtemplates/partial-func.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Sutter trick: emulating partial function specialization 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | #include 15 | 16 | template struct FImpl { 17 | static int f(T t) { return 0; } 18 | }; 19 | 20 | template struct FImpl { 21 | static int f(T *t) { return 1; } 22 | }; 23 | 24 | template int f(T t) { return FImpl::f(t); } 25 | 26 | TEST(classtempls, partialfunc) { 27 | int x; 28 | int *px; 29 | double y; 30 | double *py; 31 | 32 | EXPECT_EQ(f(x), 0); 33 | EXPECT_EQ(f(px), 1); 34 | EXPECT_EQ(f(y), 0); 35 | EXPECT_EQ(f(py), 1); 36 | } -------------------------------------------------------------------------------- /classtemplates/partial-primer.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Partial specialization basic example 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | #include 15 | 16 | template struct Foo { int primary = 0; }; 17 | 18 | template struct Foo { int partial = 1; }; 19 | 20 | template struct Foo { int partial = 2; }; 21 | 22 | template struct Foo { int partial = 3; }; 23 | 24 | TEST(classtempls, primer) { 25 | Foo mif; 26 | EXPECT_EQ(mif.primary, 0); 27 | Foo mff; 28 | EXPECT_EQ(mff.partial, 1); 29 | Foo mfi; 30 | EXPECT_EQ(mfi.partial, 2); 31 | Foo mp; 32 | EXPECT_EQ(mp.partial, 3); 33 | } -------------------------------------------------------------------------------- /classtemplates/point-of-decl.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // illustration of point of declaration 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | #include 15 | 16 | TEST(classtempls, pod) { 17 | int x = 2; 18 | { 19 | int x[x]; 20 | EXPECT_EQ(sizeof(x), 2 * sizeof(int)); // passed 21 | } 22 | 23 | int y = 2; 24 | { 25 | int y = y; 26 | // EXPECT_EQ(y, 2); // failed 27 | } 28 | } -------------------------------------------------------------------------------- /concepts/compound.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Compound concepts 10 | // 11 | //----------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | #include 15 | 16 | namespace { 17 | 18 | struct S { 19 | int data_ = 0; 20 | using inner = int; 21 | S &operator++() noexcept { 22 | ++data_; 23 | return *this; 24 | } 25 | }; 26 | 27 | int operator+(S s, int x) { return x + s.data_; } 28 | 29 | template int foo(T x) requires requires(T a) { 30 | // clang-format off 31 | { a + 1 } -> std::convertible_to; 32 | // clang-format on 33 | requires noexcept(++a); 34 | requires sizeof(T) == 4; 35 | } 36 | { return ++x + 1; } 37 | 38 | } // namespace 39 | 40 | TEST(concepts, compound) { 41 | S s; 42 | auto x = foo(s); 43 | EXPECT_EQ(x, 2); 44 | } 45 | -------------------------------------------------------------------------------- /concepts/contain.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Unrestricted contains: ugly compilation bug 10 | // 11 | //----------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | #include 15 | 16 | namespace { 17 | 18 | template 19 | bool contains(R const &range, T const &value) { 20 | for (auto const &x : range) 21 | if (x == value) 22 | return true; 23 | return false; 24 | } 25 | 26 | } // namespace 27 | 28 | TEST(concepts, contain) { 29 | std::vector v{"0", "1", "2"}; 30 | bool is_in = contains(v, 1); 31 | EXPECT_EQ(is_in, false); 32 | } -------------------------------------------------------------------------------- /concepts/difference-complex-simple.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Difference between compile-time evaluation of predicate and syntactic check 10 | // 11 | //----------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | 15 | namespace { 16 | 17 | #ifdef BUG 18 | template constexpr int somepred() { return 14; } 19 | #else 20 | template constexpr int somepred() { return 42; } 21 | #endif 22 | 23 | template 24 | requires(somepred() == 42) bool foo(T &&lhs, T &&rhs) { return lhs < rhs; } 25 | 26 | template 27 | requires requires(T t) { somepred() == 42; } 28 | bool bar(T &&lhs, T &&rhs) { return lhs < rhs; } 29 | 30 | } // namespace 31 | 32 | TEST(concepts, difference) { 33 | bool a, b; 34 | a = bar(1, 2); 35 | b = foo(1, 2); 36 | EXPECT_EQ(a, true); 37 | EXPECT_EQ(b, true); 38 | } -------------------------------------------------------------------------------- /concepts/eq-complexreq.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // check_eq constrained with requires expression 10 | // 11 | //----------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | #include 15 | 16 | namespace { 17 | 18 | template 19 | requires requires(T t, U u) { t == u; } 20 | bool check_eq(T &&lhs, U &&rhs) { return (lhs == rhs); } 21 | 22 | } // namespace 23 | 24 | TEST(concepts, reqreq) { 25 | bool a, b, c; 26 | a = check_eq(1, 2); 27 | EXPECT_EQ(a, false); 28 | b = check_eq(std::string{"1"}, std::string{"2"}); 29 | EXPECT_EQ(b, false); 30 | c = check_eq(std::string{"1"}, 1); 31 | EXPECT_EQ(c, false); 32 | } -------------------------------------------------------------------------------- /concepts/eq.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Equality comparable SFINAE trait 10 | // 11 | //----------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | #include 15 | 16 | namespace { 17 | 18 | template 19 | struct is_equality_comparable : std::false_type {}; 20 | template 21 | struct is_equality_comparable< 22 | T, U, std::void_t() == std::declval())>> 23 | : std::true_type {}; 24 | 25 | } // namespace 26 | 27 | TEST(concepts, eq) { 28 | constexpr bool string_int = is_equality_comparable::value; 29 | constexpr bool long_char = is_equality_comparable::value; 30 | EXPECT_EQ(string_int, false); 31 | EXPECT_EQ(long_char, true); 32 | } -------------------------------------------------------------------------------- /concepts/impossible.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // We can't do different cool things 10 | // 11 | //----------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | #include 15 | 16 | namespace { 17 | 18 | // no recursive definitions 19 | 20 | template 21 | concept AllTrueRec = b &&((sizeof...(bs) == 0) ? true : AllTrueRec); 22 | 23 | template 24 | requires AllTrueRec 25 | int foo() { return 1; } 26 | 27 | // no associated constraints to concepts 28 | 29 | template 30 | concept Inner = requires { 31 | typename T::inner; 32 | }; 33 | 34 | template 35 | requires Inner 36 | concept Outer = requires { typename T::outer; }; 37 | 38 | } // namespace 39 | 40 | TEST(concepts, whatcanido) { 41 | auto x = foo(); // corr 42 | EXPECT_EQ(x, 1); 43 | } -------------------------------------------------------------------------------- /concepts/strange.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Lazy evaluation 10 | // 11 | //----------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | #include 15 | 16 | namespace { 17 | 18 | // clang-format off 19 | template 20 | concept Strange = (sizeof(T) == 4) || 21 | (requires() { { T::value } -> std::convertible_to; } && 22 | (T::value == true)); 23 | // clang-format on 24 | 25 | template 26 | requires Strange 27 | int f(T t) { return 42; } 28 | 29 | } // namespace 30 | 31 | TEST(concepts, strange) { 32 | int x = f(1); 33 | EXPECT_EQ(x, 42); 34 | } 35 | -------------------------------------------------------------------------------- /concurrency/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # 3 | # Source code for MIPT masters course on C++ 4 | # Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | # Licensed after GNU GPL v3 6 | # 7 | #------------------------------------------------------------------------------ 8 | # 9 | # Build system for examples (concurrency lecture) 10 | # 11 | # Order of examples in SRCS variable corresponds to the order in the lecture. 12 | # Examples commented out are broken (often -- intentionally). 13 | # 14 | # Try: cmake -DCMAKE_CXX_COMPILER=clang++-15 .. 15 | # 16 | #------------------------------------------------------------------------------ 17 | 18 | set(SRCS 19 | thread_create.cc 20 | spawned_id.cc 21 | # race_demo.cc -- we have UB 22 | # race_demo_volatile.cc -- we have UB 23 | volatile.cc 24 | # posix_solution.cc -- we have UB 25 | # locations_ub.cc -- we have UB 26 | locations_ok.cc 27 | mutex_solution.cc 28 | lock_guard.cc 29 | sutter_case.cc 30 | # deadlock.cc 31 | dining_naive.cc 32 | dining_lock.cc 33 | dcl.cc 34 | dcl_once.cc 35 | notify_one.cc 36 | notify_all.cc 37 | # focus_demo.cc -- just demo 38 | # shared_lock_bench.cc -- benchmark 39 | ) 40 | 41 | add_gtest(concurrency) 42 | -------------------------------------------------------------------------------- /concurrency/locations_ok.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // concept of location: unclear OK case 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include 14 | #include 15 | 16 | #include "gtest/gtest.h" 17 | 18 | namespace { 19 | 20 | void __attribute__((noinline)) use(int c) { asm(""); } 21 | 22 | char x[2] = {0, 0}, i = 0, j = 0; 23 | 24 | void readerf() { 25 | while (i++ < 'g') { 26 | x[0] += 0x1; 27 | use(x[0]); 28 | } 29 | } 30 | 31 | void writerf() { 32 | while (j++ < 'g') { 33 | x[1] += 0x1; 34 | use(x[1]); 35 | } 36 | } 37 | 38 | } // namespace 39 | 40 | TEST(threads, locations_ok) { 41 | std::thread t1{readerf}, t2{writerf}; 42 | t1.join(); 43 | t2.join(); 44 | EXPECT_EQ(x[0], 'g'); 45 | EXPECT_EQ(x[1], 'g'); 46 | } 47 | -------------------------------------------------------------------------------- /concurrency/locations_ub.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // concept of location: unclear UB case 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include 14 | #include 15 | 16 | #include "gtest/gtest.h" 17 | 18 | namespace { 19 | 20 | unsigned x = 0, i = 0, j = 0; 21 | 22 | void __attribute__((noinline)) use(int c) { asm(""); } 23 | 24 | void readerf() { 25 | while (i++ < 'g') { 26 | x += 0x1; 27 | use(x); 28 | } 29 | } 30 | 31 | void writerf() { 32 | while (j++ < 'g') { 33 | x += 0x10000; 34 | use(x); 35 | } 36 | } 37 | 38 | } // namespace 39 | 40 | TEST(threads, locations_ub) { 41 | std::thread t1{readerf}, t2{writerf}; 42 | t1.join(); 43 | t2.join(); 44 | EXPECT_EQ(x & 0xFF, 'g'); 45 | EXPECT_EQ((x >> 16) & 0xFF, 'g'); 46 | } 47 | -------------------------------------------------------------------------------- /concurrency/lock_guard.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // example of lock_guard 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include "gtest/gtest.h" 18 | 19 | namespace { 20 | 21 | volatile int x = 0; 22 | std::mutex mforx; 23 | 24 | void __attribute__((noinline)) use(int c) { asm(""); } 25 | 26 | void race() { 27 | // going up 28 | for (int i = 0; i < 1000000; ++i) { 29 | std::lock_guard lk{mforx}; 30 | x = x + 1; 31 | use(x); 32 | } 33 | 34 | // going down 35 | for (int i = 0; i < 1000000; ++i) { 36 | std::lock_guard lk{mforx}; 37 | x = x - 1; 38 | use(x); 39 | } 40 | } 41 | 42 | } // namespace 43 | 44 | TEST(threads, lock_guard) { 45 | std::thread t1{race}; 46 | std::thread t2{race}; 47 | t1.join(); 48 | t2.join(); 49 | EXPECT_EQ(x, 0); 50 | } 51 | -------------------------------------------------------------------------------- /concurrency/mutex_solution.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // solution for race with mutex 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include "gtest/gtest.h" 18 | 19 | namespace { 20 | 21 | int x = 0; 22 | std::mutex mforx; 23 | 24 | void __attribute__((noinline)) use(int c) { asm(""); } 25 | 26 | void race() { 27 | // going up 28 | for (int i = 0; i < 1000000; ++i) { 29 | mforx.lock(); 30 | x += 1; 31 | use(x); 32 | mforx.unlock(); 33 | } 34 | 35 | // going down 36 | for (int i = 0; i < 1000000; ++i) { 37 | mforx.lock(); 38 | x -= 1; 39 | use(x); 40 | mforx.unlock(); 41 | } 42 | } 43 | 44 | } // namespace 45 | 46 | TEST(threads, mutex_solution) { 47 | std::thread t1{race}; 48 | std::thread t2{race}; 49 | t1.join(); 50 | t2.join(); 51 | EXPECT_EQ(x, 0); 52 | } 53 | -------------------------------------------------------------------------------- /concurrency/race_demo.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Race demo 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include 14 | #include 15 | 16 | namespace { 17 | 18 | int x = 0; 19 | 20 | void __attribute__((noinline)) use(int c) { asm(""); } 21 | 22 | void race() { 23 | // going up 24 | for (int i = 0; i < 1000000; ++i) { 25 | x += 1; 26 | use(x); 27 | } 28 | 29 | // going down 30 | for (int i = 0; i < 1000000; ++i) { 31 | x -= 1; 32 | use(x); 33 | } 34 | } 35 | 36 | } // namespace 37 | 38 | int main() { 39 | std::thread t1{race}; 40 | std::thread t2{race}; 41 | t1.join(); 42 | t2.join(); 43 | std::cout << x << std::endl; 44 | } 45 | -------------------------------------------------------------------------------- /concurrency/race_demo_volatile.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Race demo -- attempt to use volatile 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include 14 | #include 15 | 16 | namespace { 17 | 18 | volatile int x = 0; 19 | 20 | void __attribute__((noinline)) use(int c) { asm(""); } 21 | 22 | void race() { 23 | // going up 24 | for (int i = 0; i < 1000000; ++i) { 25 | x += 1; 26 | use(x); 27 | } 28 | 29 | // going down 30 | for (int i = 0; i < 1000000; ++i) { 31 | x -= 1; 32 | use(x); 33 | } 34 | } 35 | 36 | } // namespace 37 | 38 | int main() { 39 | std::thread t1{race}; 40 | std::thread t2{race}; 41 | t1.join(); 42 | t2.join(); 43 | std::cout << x << std::endl; 44 | } 45 | -------------------------------------------------------------------------------- /concurrency/spawned_id.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Spawned thread id 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include 14 | #include 15 | 16 | int main() { 17 | std::thread t([]() { 18 | std::cout << "Spawned id: " << std::this_thread::get_id() << std::endl; 19 | }); 20 | std::cout << "Parent id: " << std::this_thread::get_id() << std::endl; 21 | t.join(); 22 | } 23 | -------------------------------------------------------------------------------- /concurrency/thread_create.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Simplest thread creation 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include 14 | #include 15 | 16 | #include "gtest/gtest.h" 17 | 18 | TEST(threads, thread_create) { 19 | int j = 0; 20 | std::thread t([&j] { j += 1; }); 21 | t.join(); 22 | EXPECT_EQ(j, 1); 23 | } 24 | -------------------------------------------------------------------------------- /concurrency/volatile.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // volatile examples 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include "gtest/gtest.h" 18 | 19 | namespace { 20 | 21 | int foo(int *p) { return *p; } 22 | int bar(const int *p) { return *p; } 23 | int buz(volatile int *p) { return *p; } 24 | 25 | } // namespace 26 | 27 | TEST(threads, volatile_test) { 28 | int i = 1; 29 | const int ci = 2; 30 | volatile int vi = 3; 31 | EXPECT_EQ(foo(&i), 1); 32 | // foo(&ci); 33 | // foo(&vi); 34 | EXPECT_EQ(bar(&i), 1); 35 | EXPECT_EQ(bar(&ci), 2); 36 | // bar(&vi); 37 | EXPECT_EQ(buz(&i), 1); 38 | // buz(&ci); 39 | EXPECT_EQ(buz(&vi), 3); 40 | } 41 | -------------------------------------------------------------------------------- /constexpr/binparser.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // CE binary number parser 10 | // 11 | //----------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | 15 | namespace { 16 | 17 | template 18 | constexpr unsigned long long binparser(unsigned long long accum, char c, 19 | Ts... cs) { 20 | unsigned digit = (c == '1') ? 1 : (c == '0') ? 0 : throw "out of range"; 21 | if constexpr (sizeof...(Ts) != 0) 22 | return binparser(accum * 2 + digit, cs...); 23 | return accum * 2 + digit; 24 | } 25 | 26 | template constexpr unsigned long long operator"" _binary() { 27 | return binparser(0ull, Chars...); 28 | } 29 | 30 | } // namespace 31 | 32 | TEST(cexpr, binparser) { 33 | constexpr unsigned long long c = 1010101010101_binary; 34 | EXPECT_EQ(c, 5461); 35 | } -------------------------------------------------------------------------------- /constexpr/cce.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // constexpr core constant expression tricky case 10 | // 11 | //----------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | 15 | struct S { 16 | int n_; 17 | S(int n) : n_(n) {} // non-constexpr ctor! 18 | constexpr int get() { return 42; } 19 | }; 20 | 21 | TEST(cexpr, cce) { 22 | S s{2}; 23 | constexpr int k = s.get(); 24 | EXPECT_EQ(k, 42); 25 | } -------------------------------------------------------------------------------- /constexpr/cecollatz.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // CE Collatz numbers 10 | // 11 | //----------------------------------------------------------------------------- 12 | 13 | #include 14 | 15 | constexpr long long maxcollatz(int n) { 16 | long long cmax = 0, xmax = 0; 17 | for (int x = 2; x < n; ++x) { 18 | long long y = x; 19 | long long c = 0; 20 | while (y > 1) { 21 | c += 1; 22 | if ((y % 2) == 0) 23 | y = y / 2; 24 | else 25 | y = 3 * y + 1; 26 | } 27 | if (c > cmax) { 28 | cmax = c; 29 | xmax = x; 30 | } 31 | } 32 | return xmax; 33 | } 34 | 35 | #ifndef MAXC 36 | #define MAXC 100 37 | #endif 38 | 39 | int main() { 40 | constexpr long long CT = maxcollatz(MAXC); 41 | std::cout << "CT: " << CT << std::endl; 42 | std::cout << "RT: " << maxcollatz(MAXC) << std::endl; 43 | } 44 | -------------------------------------------------------------------------------- /constexpr/cenew.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // constexpr new example 10 | // 11 | //----------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | #include 15 | #include 16 | 17 | namespace { 18 | 19 | constexpr int test() { 20 | int *p = new int(2); 21 | int k = *p; 22 | delete p; 23 | return k; 24 | } 25 | 26 | constexpr int testv() { 27 | std::vector v = {1, 2, 3}; 28 | return v[1]; 29 | } 30 | 31 | constexpr int tests() { 32 | std::string s = "Hello"; 33 | return s[1]; 34 | } 35 | 36 | } // namespace 37 | 38 | TEST(cexpr, opnew) { 39 | constexpr int x = test(); 40 | EXPECT_EQ(x, 2); 41 | 42 | constexpr int y = testv(); 43 | EXPECT_EQ(y, 2); 44 | 45 | constexpr int z = tests(); 46 | EXPECT_EQ(z, 'e'); 47 | } -------------------------------------------------------------------------------- /constexpr/cepred-expr.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // core constant expression detailed 10 | // 11 | //----------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | #include 15 | 16 | consteval bool negate(bool x) { return !x; } 17 | 18 | template constexpr int f(Predicate pred) { 19 | if constexpr (pred(true)) 20 | return 1; 21 | return 0; 22 | } 23 | 24 | TEST(cexpr, pred) { 25 | constexpr int x = f(negate); 26 | EXPECT_EQ(x, false); 27 | } -------------------------------------------------------------------------------- /constexpr/ceval-cinit.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Consteval and constinit big example 10 | // 11 | //----------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | 15 | namespace { 16 | 17 | // compile time only 18 | consteval int ctsqr(int n) { return n * n; } 19 | 20 | // OK, global constinit 21 | constinit int g = ctsqr(100); 22 | 23 | } // namespace 24 | 25 | TEST(cexpr, cevinit) { 26 | constexpr int c = ctsqr(100); 27 | 28 | #ifdef BAD 29 | // FAIL: cannot assign constexpr (i.e. const) variable 30 | c += 1; 31 | #endif 32 | 33 | #ifdef BAD 34 | // FAIL: function consteval, x not CT known 35 | int x = 100; 36 | int y = ctsqr(x); 37 | #endif 38 | 39 | #ifdef BAD 40 | // FAIL: constinit can not be local 41 | constinit int d = ctsqr(100); 42 | #endif 43 | 44 | // OK to do this in runtime 45 | g += 1; 46 | 47 | EXPECT_EQ(g, 10001); 48 | } -------------------------------------------------------------------------------- /constexpr/cexpr-local.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Constexpr local variable fallacy case 10 | // 11 | //----------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | #include 15 | 16 | namespace { 17 | 18 | template consteval auto ilist_sz(std::initializer_list init) { 19 | #if defined(BAD) 20 | constexpr auto init_sz = init.size(); 21 | #else 22 | auto init_sz = init.size(); 23 | #endif 24 | return init_sz; 25 | } 26 | 27 | } // namespace 28 | 29 | TEST(cexpr, cexprlocal) { 30 | constexpr auto n = ilist_sz({1, 2, 3}); 31 | EXPECT_EQ(n, 3); 32 | } -------------------------------------------------------------------------------- /constexpr/complex.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Complex numbers example 10 | // 11 | //----------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | 15 | namespace { 16 | 17 | class Complex { 18 | double re, im; 19 | 20 | public: 21 | constexpr Complex(double r, double i) : re(r), im(i) {} 22 | constexpr double real() const { return re; } 23 | constexpr double imag() const { return im; } 24 | constexpr Complex &operator+=(Complex rhs) { 25 | re += rhs.re; 26 | im += rhs.im; 27 | return *this; 28 | } 29 | }; 30 | 31 | constexpr Complex operator+(Complex lhs, Complex rhs) { 32 | lhs += rhs; 33 | return lhs; 34 | } 35 | 36 | } // namespace 37 | 38 | TEST(cexpr, complex) { 39 | constexpr Complex c(0.0, 1.0); 40 | constexpr Complex d(1.0, 2.0); 41 | constexpr Complex e = c + d; 42 | EXPECT_EQ(c.real(), 0.0); 43 | EXPECT_EQ(e.imag(), 3.0); 44 | } -------------------------------------------------------------------------------- /constexpr/ctconst.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Floating compile time constness 10 | // 11 | //----------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | 15 | struct S1 { 16 | static const int sz = 256; 17 | }; 18 | const int page_sz1 = 4 * S1::sz; 19 | int arr1[page_sz1]; // ok, CT constant 20 | 21 | struct S2 { 22 | static const int sz; 23 | }; 24 | const int page_sz2 = 4 * S2::sz; 25 | const int S2::sz = 256; 26 | int arr2[page_sz2]; // error: not CT constant -------------------------------------------------------------------------------- /constexpr/ctfield.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Attempt of constexpr field in structure 10 | // 11 | //----------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | 15 | namespace { 16 | 17 | struct S { 18 | constexpr int n = 42; 19 | }; 20 | 21 | } // namespace 22 | 23 | TEST(cexpr, ctfield) { 24 | S s; 25 | EXPECT_EQ(s.n, 42); 26 | } -------------------------------------------------------------------------------- /constexpr/cycle.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Cycle elements 10 | // 11 | //----------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | #include 15 | 16 | namespace { 17 | 18 | template 19 | constexpr std::array cycle_elems(std::array a) { 20 | std::array result{}; 21 | for (T i = 0; i < N * Size; ++i) 22 | result[i] = a[i % Size]; 23 | return result; 24 | } 25 | 26 | } // namespace 27 | 28 | TEST(cexpr, array) { 29 | constexpr std::array arr = {0, 4, 2, 1, 3}; 30 | constexpr auto cycled = cycle_elems<3>(arr); 31 | EXPECT_EQ(cycled[1], 4); 32 | EXPECT_EQ(cycled[1], cycled[6]); 33 | EXPECT_EQ(cycled[7], 2); 34 | EXPECT_EQ(cycled[7], cycled[12]); 35 | } -------------------------------------------------------------------------------- /constexpr/heavy.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Const on result not always great 10 | // 11 | //----------------------------------------------------------------------------- 12 | 13 | struct Heavy { 14 | Heavy() {} 15 | Heavy(Heavy &&) {} 16 | Heavy(const Heavy &) = delete; 17 | }; 18 | 19 | const Heavy foo() { 20 | Heavy x; 21 | return x; 22 | } 23 | 24 | Heavy bar() { 25 | Heavy x; 26 | return x; 27 | } 28 | 29 | void buz() { 30 | Heavy y = foo(); 31 | Heavy z = bar(); 32 | } -------------------------------------------------------------------------------- /constexpr/ifcedetails.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // if constexpr usage: note only instantiations are affected 10 | // 11 | //----------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | #include 15 | 16 | // template case: constexpr works 17 | 18 | template void bar(T value) { 19 | if constexpr (std::is_pointer_v) 20 | std::cout << "Ptr to " << *value << std::endl; // Error 21 | else 22 | std::cout << "Ref to " << value << std::endl; 23 | } 24 | 25 | template void bar(int); // instantiate here! 26 | template void bar(int *); // instantiate here! 27 | 28 | // non-template case: constexpr fails 29 | 30 | void foo() { 31 | auto value = 100; // deduce int 32 | if constexpr (std::is_pointer_v) 33 | std::cout << "Ptr to " << *value << std::endl; // Error 34 | else 35 | std::cout << "Ref to " << value << std::endl; 36 | } -------------------------------------------------------------------------------- /constexpr/numlimits-fixed.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // numerical limits example fixed 10 | // 11 | //----------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | #include 15 | #include 16 | 17 | namespace { 18 | 19 | template struct my_numeric_limits; 20 | template <> struct my_numeric_limits { 21 | static constexpr size_t max() { return CHAR_MAX; } 22 | }; 23 | 24 | int arr[my_numeric_limits::max()]; // OK 25 | 26 | } // namespace 27 | 28 | TEST(cexpr, ctarr) { 29 | auto n = sizeof(arr); 30 | EXPECT_EQ(n, CHAR_MAX * sizeof(int)); 31 | } -------------------------------------------------------------------------------- /constexpr/numlimits.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // simplest numerical limits example (not working) 10 | // 11 | //----------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | #include 15 | #include 16 | 17 | template struct my_numeric_limits; 18 | template <> struct my_numeric_limits { 19 | static const size_t max() { return CHAR_MAX; } 20 | }; 21 | 22 | int arr[my_numeric_limits::max()]; // FAIL -------------------------------------------------------------------------------- /constexpr/trits.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // constexpr trits 10 | // 11 | //----------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | 15 | namespace { 16 | 17 | template constexpr T ct_trit(const char *t) { 18 | T x = 0; 19 | size_t b = 0; 20 | for (size_t i = 0; t[i] != '\0'; ++i) { 21 | switch (t[i]) { 22 | case '\'': 23 | break; 24 | case '0': 25 | x = (x * 3); 26 | ++b; 27 | break; 28 | case '1': 29 | x = (x * 3) + 1; 30 | ++b; 31 | break; 32 | case 'j': 33 | x = (x * 3) - 1; 34 | ++b; 35 | break; 36 | default: 37 | throw "Only '0', '1', and ',' may be used"; 38 | } 39 | } 40 | return x; 41 | } 42 | 43 | } // namespace 44 | 45 | TEST(cexpr, trits) { 46 | EXPECT_EQ(ct_trit("10j"), 8); 47 | EXPECT_EQ(ct_trit("j01"), -8); 48 | } -------------------------------------------------------------------------------- /constexpr/ubsan-dependent.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Even more interesting UB case demo: 10 | // try with std equals C++17 and C++20 11 | // 12 | //----------------------------------------------------------------------------- 13 | 14 | #include "gtest/gtest.h" 15 | 16 | constexpr int djb2(char const *str) { 17 | int hash = 5381; 18 | int c = 0; 19 | 20 | while ((c = *str++)) 21 | hash = ((hash << 5) + hash) + c; 22 | 23 | return hash; 24 | } 25 | 26 | TEST(cexpr, moreub) { 27 | constexpr int x = djb2("hello you :)"); 28 | EXPECT_EQ(x, -466252103); 29 | } -------------------------------------------------------------------------------- /constexpr/ubsan.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // UB case demo 10 | // 11 | //----------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | 15 | template 16 | constexpr FwdIt static_find(FwdIt it, FwdIt fin, Value v) { 17 | while ((v != *it) && (it != fin)) 18 | ++it; 19 | return it; 20 | } 21 | 22 | TEST(cexpr, ubcase) { 23 | constexpr int a[] = {1}; 24 | constexpr auto res = static_find(a, a + 1, 4); 25 | EXPECT_EQ(res, a + 2); 26 | } -------------------------------------------------------------------------------- /constexpr/virtce-ok.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // virtual constexpr example: ok 10 | // 11 | //----------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | #include 15 | 16 | struct Base { 17 | constexpr Base() = default; 18 | virtual constexpr int data() const { return 1; } 19 | }; 20 | 21 | struct Derived : Base { 22 | constexpr Derived() = default; 23 | constexpr int data() const override { return 2; } 24 | }; 25 | 26 | constexpr int foo() { 27 | const Base b; 28 | const Derived d; 29 | int sum = 0; 30 | const Base *bases[] = {&b, &d}; 31 | for (auto pb : bases) 32 | sum += pb->data(); 33 | return sum; 34 | } 35 | 36 | TEST(cexpr, virtceok) { 37 | constexpr int data = foo(); // ok 38 | EXPECT_EQ(data, 3); 39 | } -------------------------------------------------------------------------------- /constexpr/virtce.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // virtual constexpr example: fail 10 | // 11 | //----------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | #include 15 | 16 | struct Base { 17 | constexpr Base() = default; 18 | virtual constexpr int data() const { return 1; } 19 | }; 20 | 21 | struct Derived : Base { 22 | constexpr Derived() = default; 23 | constexpr int data() const override { return 2; } 24 | }; 25 | 26 | TEST(cexpr, virtce) { 27 | constexpr Derived d; 28 | constexpr const Base *pb = &d; // error 29 | EXPECT_EQ(pb->data(), 2); 30 | } -------------------------------------------------------------------------------- /coroutines/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # 3 | # Source code for MIPT masters course on C++ 4 | # Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | # Licensed after GNU GPL v3 6 | # 7 | #------------------------------------------------------------------------------ 8 | # 9 | # Build system for examples (coroutines lecture) 10 | # 11 | # Order of examples in SRCS variable corresponds to the order in the lecture. 12 | # Examples commented out are broken (often -- intentionally). 13 | # 14 | #------------------------------------------------------------------------------ 15 | 16 | set(SRCS 17 | natseq.cc 18 | resumable.cc 19 | natseq_range.cc 20 | natseq_zip.cc 21 | subscribers.cc 22 | cancellable.cc 23 | fsm.cc 24 | optional.cc 25 | # subscribers_mt.cc -- shall fail 26 | subscribers_mt_demo.cc 27 | subscribers_mt_req.cc 28 | subscribers_natlst.cc 29 | futures.cc 30 | ) 31 | 32 | add_gtest(coroutines) 33 | # add_demo(algo_bench) 34 | -------------------------------------------------------------------------------- /functempls/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # 3 | # Source code for MIPT masters course on C++ 4 | # Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | # Licensed after GNU GPL v3 6 | # 7 | #------------------------------------------------------------------------------ 8 | # 9 | # Build system for examples (function templates lecture) 10 | # 11 | # Order of examples in SRCS variable corresponds to the order in the lecture. 12 | # Examples commented out are broken (often -- intentionally). 13 | # 14 | #------------------------------------------------------------------------------ 15 | 16 | set(SRCS 17 | nth-power-concrete.cc 18 | # nth-power-naive.cc -- supposed to fail 19 | nth-power-traits.cc 20 | nth-power-clean.cc 21 | nth-power-concept.cc 22 | class-typename.cc 23 | templ-inst-spec.cc 24 | # generate-then-delete.cc -- supposed to fail 25 | non-type-params.cc 26 | non-type-spec.cc 27 | templ-templ.cc 28 | deduce-qual.cc 29 | deduce-generalized.cc 30 | deduce-partial.cc 31 | deduce-nttp.cc 32 | deduce-spec.cc 33 | whats-call.cc 34 | name-hiding.cc 35 | name-res-examples.cc 36 | ics-tail.cc 37 | crocodile.cc 38 | ) 39 | 40 | add_gtest(functempls) 41 | # add_demo(algo_bench) 42 | -------------------------------------------------------------------------------- /functempls/class-typename.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // class vs typename holywar solved with concepts 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | #include 15 | 16 | namespace { 17 | 18 | #if 0 19 | template int foo(T x) { return x; } 20 | template int foo(T x) { return x + 1; } 21 | #endif 22 | 23 | template int foo(T x) { return x % 2; } 24 | 25 | } // namespace 26 | 27 | TEST(functemplates, class_typename) { 28 | int res = foo(11); 29 | EXPECT_EQ(res, 1); 30 | } 31 | 32 | #if 0 33 | TEST(functemplates, class_typename_err) { 34 | EXPECT_EQ(foo(0.0), 2); 35 | } 36 | #endif -------------------------------------------------------------------------------- /functempls/crocodile.cc: -------------------------------------------------------------------------------- 1 | #include "gtest/gtest.h" 2 | #include 3 | 4 | namespace { 5 | 6 | template int foo(T, U) { return 1; } 7 | 8 | template int foo(T *, U *) { return 2; } 9 | 10 | template <> int foo(int *, int *) { return 3; } 11 | 12 | } // namespace 13 | 14 | TEST(functemplates, crocodile) { 15 | int x; 16 | int res = foo(&x, &x); 17 | EXPECT_EQ(res, 2); 18 | } -------------------------------------------------------------------------------- /functempls/deduce-default.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // template type deduction with default arguments 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include 14 | #include 15 | 16 | #define CT_ERROR 0 17 | 18 | namespace { 19 | template double foo(T x = 1.5) { return x; } 20 | } // namespace 21 | 22 | TEST(functemplates, deduce_default) { 23 | double v0 = foo(2.0); 24 | EXPECT_EQ(v0, 2.0); 25 | double v1 = foo(); 26 | EXPECT_EQ(v1, 1); 27 | double v2 = foo(); 28 | EXPECT_EQ(v2, 1.5); 29 | } -------------------------------------------------------------------------------- /functempls/deduce-generalized.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // template type deduction with complex types 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | namespace { 19 | 20 | #define CT_ERROR 0 21 | 22 | template std::string deduce(T (*p)(T)) { 23 | return boost::typeindex::type_id_with_cvr().pretty_name(); 24 | } 25 | 26 | int bar(int x) { return x; } 27 | 28 | template std::string deduce2(T const (&)[N]) { 29 | return boost::typeindex::type_id_with_cvr().pretty_name() + " " + 30 | std::to_string(N); 31 | } 32 | 33 | } // namespace 34 | 35 | TEST(functemplates, deduce_extended) { 36 | std::string s = deduce(bar); 37 | EXPECT_EQ(s, "int"); 38 | } 39 | 40 | TEST(functemplates, deduce_array) { 41 | std::string s = deduce2({1, 2, 3}); 42 | EXPECT_EQ(s, "int 3"); 43 | } 44 | -------------------------------------------------------------------------------- /functempls/deduce-nttp.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // template type deduction with NTTP 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include 14 | #include 15 | 16 | #define CT_ERROR 0 17 | 18 | namespace { 19 | 20 | template int foo() { return n; } 21 | 22 | } // namespace 23 | 24 | TEST(functemplates, context) { 25 | double v0 = foo<1>(); 26 | EXPECT_EQ(v0, 1); 27 | 28 | // still not supported in CLANG 16 29 | #if 0 30 | double v1 = foo<2.0>(); 31 | EXPECT_EQ(v1, 2); 32 | #endif 33 | } -------------------------------------------------------------------------------- /functempls/deduce-partial.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // template type deduction with partial specification 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | #define CT_ERROR 0 19 | 20 | namespace { 21 | 22 | template DstT implicit_cast(SrcT x) { return x; } 23 | 24 | } // namespace 25 | 26 | TEST(functemplates, deduce_context) { 27 | #if CT_ERROR 28 | double v0 = implicit_cast(-1); // fail! 29 | #endif 30 | double v1 = implicit_cast(-1); // ok 31 | double v2 = implicit_cast(-1); // ok 32 | EXPECT_EQ(v1, -1.0); 33 | EXPECT_EQ(v2, -1.0); 34 | } 35 | -------------------------------------------------------------------------------- /functempls/deduce-spec.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // template specialization type deduction 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | 15 | namespace { 16 | 17 | // for all 18 | template T foo(T x) { return x; } 19 | 20 | // for int 21 | template <> int foo(int x) { return x + 1; } 22 | 23 | } // namespace 24 | 25 | TEST(functemplates, deduce_spec) { 26 | double d = 1.5; 27 | d = foo(d); 28 | EXPECT_EQ(d, 1.5); 29 | int i = 2; 30 | i = foo(i); 31 | EXPECT_EQ(i, 3); 32 | } -------------------------------------------------------------------------------- /functempls/generate-then-delete.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // generate specialization then delete it 10 | // failure is "redefinition" 11 | // 12 | //---------------------------------------------------------------------------- 13 | 14 | #include "gtest/gtest.h" 15 | 16 | template T max(T x, T y) { return x > y ? x : y; } 17 | 18 | template <> int max(int x, int y) { return x > y ? x : y; } 19 | 20 | template <> int max(int x, int y) = delete; 21 | 22 | TEST(max_test_case, testWillPass) { EXPECT_EQ(max(2, 11), 11); } -------------------------------------------------------------------------------- /functempls/ics-tail.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // simple example on ICS tail sequence importance 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | 15 | namespace { 16 | 17 | struct A { 18 | operator int() { return 42; } 19 | operator double() { return 1.0; } 20 | }; 21 | 22 | } // namespace 23 | 24 | TEST(functemplates, icstail) { 25 | int Res = A{}; 26 | EXPECT_EQ(Res, 42); 27 | } -------------------------------------------------------------------------------- /functempls/instantiations-demo/01-naive/Makefile: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # 3 | # Source code for MIPT masters course on C++ 4 | # Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | # Licensed after GNU GPL v3 6 | # 7 | #------------------------------------------------------------------------------ 8 | 9 | result: maxuser1.o maxuser2.o 10 | ar cr libmax.a maxuser1.o maxuser2.o 11 | $(CXX) main.cc -L. -lmax -o $@ 12 | objdump -d -M intel libmax.a > libmax.dis 13 | 14 | maxuser1.o : maxuser1.cc max.hpp 15 | $(CXX) maxuser1.cc -c 16 | objdump -d -M intel maxuser1.o > maxuser1.dis 17 | 18 | maxuser2.o : maxuser2.cc max.hpp 19 | $(CXX) -O1 maxuser2.cc -c 20 | objdump -d -M intel maxuser2.o > maxuser2.dis 21 | 22 | .PHONY: winclean 23 | winclean: 24 | del *.o *.a a.exe result.exe *.dis 25 | 26 | .PHONY: clean 27 | clean: 28 | rm -rf *.o *.a a.out result *.dis 29 | -------------------------------------------------------------------------------- /functempls/instantiations-demo/01-naive/main.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Demo of instantiations, main function 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include 14 | 15 | #include "max.hpp" 16 | 17 | int main() { 18 | int foores = foo(0, 0); 19 | int barres = bar(0, 0); 20 | std::cout << "foo: " << foores << "; bar: " << barres << std::endl; 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /functempls/instantiations-demo/01-naive/max.hpp: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Demo of instantiations, max function 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #pragma once 14 | 15 | template [[gnu::noinline]] T max(T x, T y) { 16 | return (x > y) ? x : y; 17 | } 18 | 19 | extern int foo(int x, int y); 20 | extern int bar(int x, int y); -------------------------------------------------------------------------------- /functempls/instantiations-demo/01-naive/maxuser1.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Demo of instantiations, function foo 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include "max.hpp" 14 | 15 | int foo(int x, int y) { return max(x, y + 1); } -------------------------------------------------------------------------------- /functempls/instantiations-demo/01-naive/maxuser2.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Demo of instantiations, function bar 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include "max.hpp" 14 | 15 | int bar(int x, int y) { return max(x + 1, y); } -------------------------------------------------------------------------------- /functempls/instantiations-demo/02-block/Makefile: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # 3 | # Source code for MIPT masters course on C++ 4 | # Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | # Licensed after GNU GPL v3 6 | # 7 | #------------------------------------------------------------------------------ 8 | 9 | result: maxuser1.o maxuser2.o 10 | ar cr libmax.a maxuser1.o maxuser2.o 11 | $(CXX) main.cc -L. -lmax -o $@ 12 | objdump -d -M intel libmax.a > libmax.dis 13 | 14 | maxuser1.o : maxuser1.cc max.hpp 15 | $(CXX) maxuser1.cc -c 16 | objdump -d -M intel maxuser1.o > maxuser1.dis 17 | 18 | maxuser2.o : maxuser2.cc max.hpp 19 | $(CXX) -O1 maxuser2.cc -c 20 | objdump -d -M intel maxuser2.o > maxuser2.dis 21 | 22 | .PHONY: winclean 23 | winclean: 24 | del *.o *.a a.exe result.exe *.dis 25 | 26 | .PHONY: clean 27 | clean: 28 | rm -rf *.o *.a a.out result *.dis 29 | -------------------------------------------------------------------------------- /functempls/instantiations-demo/02-block/main.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Demo of instantiations, main function 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include 14 | 15 | #include "max.hpp" 16 | 17 | int main() { 18 | int foores = foo(0, 0); 19 | int barres = bar(0, 0); 20 | std::cout << "foo: " << foores << "; bar: " << barres << std::endl; 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /functempls/instantiations-demo/02-block/max.hpp: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Demo of instantiations, max function 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #pragma once 14 | 15 | template [[gnu::noinline]] T max(T x, T y) { 16 | return (x > y) ? x : y; 17 | } 18 | 19 | extern int foo(int x, int y); 20 | extern int bar(int x, int y); -------------------------------------------------------------------------------- /functempls/instantiations-demo/02-block/maxuser1.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Demo of instantiations, function foo 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include "max.hpp" 14 | 15 | int foo(int x, int y) { return max(x, y + 1); } -------------------------------------------------------------------------------- /functempls/instantiations-demo/02-block/maxuser2.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Demo of instantiations, function bar 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include "max.hpp" 14 | 15 | // block instantiation here 16 | extern template int max(int, int); 17 | 18 | int bar(int x, int y) { return max(x + 1, y); } 19 | -------------------------------------------------------------------------------- /functempls/instantiations-demo/03-force/Makefile: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # 3 | # Source code for MIPT masters course on C++ 4 | # Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | # Licensed after GNU GPL v3 6 | # 7 | #------------------------------------------------------------------------------ 8 | 9 | result: maxuser1.o maxuser2.o max.o 10 | ar cr libmax.a maxuser1.o maxuser2.o max.o 11 | $(CXX) main.cc -L. -lmax -o $@ 12 | objdump -d -M intel libmax.a > libmax.dis 13 | 14 | max.o : max.cc max.hpp 15 | $(CXX) -O2 max.cc -c 16 | objdump -d -M intel max.o > max.dis 17 | 18 | maxuser1.o : maxuser1.cc max.hpp 19 | $(CXX) maxuser1.cc -c 20 | objdump -d -M intel maxuser1.o > maxuser1.dis 21 | 22 | maxuser2.o : maxuser2.cc max.hpp 23 | $(CXX) -O1 maxuser2.cc -c 24 | objdump -d -M intel maxuser2.o > maxuser2.dis 25 | 26 | .PHONY: winclean 27 | winclean: 28 | del *.o *.a a.exe result.exe *.dis 29 | 30 | .PHONY: clean 31 | clean: 32 | rm -rf *.o *.a a.out result *.dis 33 | -------------------------------------------------------------------------------- /functempls/instantiations-demo/03-force/main.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Demo of instantiations, main function 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include 14 | 15 | #include "max.hpp" 16 | 17 | int main() { 18 | int foores = foo(0, 0); 19 | int barres = bar(0, 0); 20 | std::cout << "foo: " << foores << "; bar: " << barres << std::endl; 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /functempls/instantiations-demo/03-force/max.cc: -------------------------------------------------------------------------------- 1 | #include "max.hpp" 2 | 3 | // POI just here 4 | template int max(int, int); 5 | -------------------------------------------------------------------------------- /functempls/instantiations-demo/03-force/max.hpp: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Demo of instantiations, max function 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #pragma once 14 | 15 | template [[gnu::noinline]] T max(T x, T y) { 16 | return (x > y) ? x : y; 17 | } 18 | 19 | // block instancing everywhere 20 | extern template int max(int, int); 21 | 22 | extern int foo(int x, int y); 23 | extern int bar(int x, int y); 24 | -------------------------------------------------------------------------------- /functempls/instantiations-demo/03-force/maxuser1.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Demo of instantiations, function foo 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include "max.hpp" 14 | 15 | int foo(int x, int y) { return max(x, y + 1); } -------------------------------------------------------------------------------- /functempls/instantiations-demo/03-force/maxuser2.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Demo of instantiations, function bar 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include "max.hpp" 14 | 15 | int bar(int x, int y) { return max(x + 1, y); } -------------------------------------------------------------------------------- /functempls/name-hiding.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // simple name hiding example 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | 15 | namespace { 16 | 17 | struct B { 18 | int f(int) { return 42; } 19 | }; 20 | 21 | struct D : B { 22 | // introduces name 23 | // using B::f; 24 | 25 | // hides name 26 | int f(const char *) { return 14; } 27 | }; 28 | 29 | } // namespace 30 | 31 | TEST(functemplates, namehiding) { 32 | D d; 33 | int res = d.f(0); 34 | EXPECT_EQ(res, 14); 35 | } 36 | -------------------------------------------------------------------------------- /functempls/non-type-spec.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // Specializing for non type parameters. 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | 15 | namespace { 16 | 17 | struct Pair { 18 | int x = 1, y = 1; 19 | }; 20 | 21 | template int foo() { 22 | return N + *PN + RN + P.x + P.y; 23 | } 24 | 25 | constexpr Pair p; 26 | int x = 1; 27 | int y = 1; 28 | 29 | template <> int foo<1, nullptr, x, p>() { return 10 + x + p.x + p.y; } 30 | 31 | } // namespace 32 | 33 | TEST(functemplates, nttpspec) { 34 | int res = foo<2, &x, y, p>(); 35 | EXPECT_EQ(res, 2 + 1 + 1 + 1 + 1); 36 | 37 | res = foo<1, nullptr, x, p>(); 38 | EXPECT_EQ(res, 10 + 1 + 1 + 1); 39 | } 40 | -------------------------------------------------------------------------------- /functempls/templ-inst-spec.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // template instantiation vs specialization 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | 15 | #define EARLY 0 16 | #define SPECIALIZE 1 17 | 18 | namespace { 19 | 20 | template T max(T x, T y) { return x > y ? x : y; } 21 | 22 | #if (EARLY == 1) 23 | extern template int max(int, int); 24 | #endif 25 | 26 | #if (SPECIALIZE == 1) 27 | template <> int max(int x, int y) { return x > y ? x : y; } 28 | #endif 29 | 30 | #if (EARLY == 0) 31 | extern template int max(int, int); 32 | #endif 33 | 34 | } // namespace 35 | 36 | TEST(functemplates, inst_spec) { EXPECT_EQ(max(2, 11), 11); } -------------------------------------------------------------------------------- /functempls/templ-templ.cc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Source code for MIPT masters course on C++ 4 | // Slides: https://sourceforge.net/projects/cpp-lects-rus 5 | // Licensed after GNU GPL v3 6 | // 7 | //----------------------------------------------------------------------------- 8 | // 9 | // template template parameters 10 | // 11 | //---------------------------------------------------------------------------- 12 | 13 | #include "gtest/gtest.h" 14 | 15 | namespace { 16 | 17 | template