├── .clang-format ├── .clang-tidy ├── .gitignore ├── 01-220905 ├── 01-org │ ├── 01-rules.md │ └── 02-materials.md ├── 02-standards │ ├── 01-zoo.md │ └── c-vs-cpp.svg ├── 03-basic │ ├── 01-hello-world.cpp │ ├── 02-no-main-return.cpp │ ├── 03-a-plus-b.cpp │ ├── 04-compilation-error.cpp │ ├── 05-uninitialized-vars.cpp │ ├── 06-global-vars-scopes.cpp │ ├── 07-using-namespace.cpp │ └── links.md ├── TODO.md └── progress.md ├── 02-220912 ├── 00-old.md ├── 01-arithmetics │ ├── 01-int.cpp │ ├── 02-int-overflow-ub.cpp │ ├── 03-unsigned.cpp │ ├── 04-long-long.cpp │ ├── 05-literals.cpp │ ├── 06-conversions.cpp │ ├── 07-auto.cpp │ ├── 10-other-ints.cpp │ ├── 11-bool.cpp │ ├── 20-assignment.cpp │ ├── 21-increment.cpp │ ├── 22-division.cpp │ ├── 23-bitwise.cpp │ └── 24-bitwise-optimizations.cpp ├── 02-branching │ ├── 01-if.cpp │ ├── 02-logical.cpp │ ├── 03-for.cpp │ ├── 04-while.cpp │ └── 05-comma-operator.cpp ├── 03-array │ ├── 01-array.cpp │ ├── 02-array-overflow.cpp │ ├── 03-array-underflow.cpp │ └── 04-array-for-unsigned-error.cpp ├── TODO.md └── progress.md ├── 03-220919 ├── 01-array │ ├── 05-vector-resize.cpp │ ├── 06-for-ref.cpp │ ├── 07-vector-2d.cpp │ ├── 10-vector-operators.cpp │ ├── 11-vector-assert.cpp │ ├── 12-vector-missing.md │ ├── 13-vector-bool.cpp │ └── 14-vector-c-array.cpp ├── 02-strings │ ├── 01-char.cpp │ ├── 02-char-vector-wtf.cpp │ ├── 03-char-signed.cpp │ ├── 10-string.cpp │ ├── 11-stringstream.cpp │ ├── 12-to-string.cpp │ ├── 13-cin-vs-getline.cpp │ ├── 14-encodings.01.in │ ├── 14-encodings.02.in │ ├── 14-encodings.03.in │ ├── 14-encodings.04.in │ └── 14-encodings.cpp ├── 03-eof │ ├── 01-while-eof.cpp │ ├── 01-while-eof.in │ ├── 02-while-char-eof.cpp │ ├── 02-while-char-eof.txt │ ├── 03-while-success.cpp │ ├── 03-while-success.in │ └── TODO.md ├── 04-functions │ ├── 01-simple.cpp │ ├── 02-no-return.cpp │ ├── 03-return-void.cpp │ ├── 04-copy-slow.cpp │ ├── 05-const-ref-fast.cpp │ ├── 10-ref.cpp │ └── 11-return-by-value.cpp ├── TODO.md └── progress.md ├── 04-220926 ├── 00-old │ ├── 01-maybe-unused.cpp │ └── 02-nodiscard.cpp ├── 01-struct │ ├── 01-struct.cpp │ ├── 02-aggregates.cpp │ ├── 03-const.cpp │ ├── 04-const-break.cpp │ ├── 10-member-default-initialization.cpp │ ├── 11-constructors-bad-style.cpp │ ├── 12-member-initialization-list.cpp │ ├── 13-no-default-ctor.cpp │ ├── 20-public.cpp │ ├── 21-private.cpp │ ├── 30-friend.cpp │ └── 31-struct-class.cpp ├── 02-conversions │ ├── 01-implicit-conversion.cpp │ ├── 02-explicit-bad.cpp │ ├── 03-explicit-bad-fix.cpp │ ├── 10-conversion-operator.cpp │ ├── 11-conversion-explicit.cpp │ ├── 12-mix.cpp │ └── 13-mix-fixed.cpp ├── 03-operators │ ├── 01-comparison-bad.cpp │ ├── 02-comparison-friend.cpp │ ├── 03-assignment.cpp │ ├── 04-increment.cpp │ ├── 05-via.cpp │ ├── 06-output.cpp │ └── 07-input.cpp ├── TODO.md └── progress.md ├── 05-221003 ├── 01-declare-define │ ├── 01-identifiers.cpp │ ├── 02-declare-define-recursive.cpp │ ├── 03-inside-classes.cpp │ ├── 04-incomplete-type.cpp │ ├── 05-outside-classes.cpp │ ├── 06-recursive.cpp │ ├── 10-vexing-parse-default.cpp │ └── 11-vexing-parse-args.cpp ├── 02-namespaces │ ├── 01-basic.cpp │ ├── 02-name-resolution.cpp │ ├── 03-nested.cpp │ ├── 04-adl.cpp │ └── 05-using-namespace.cpp ├── 03-naive-include │ ├── README.md │ ├── bigint.inc.cpp │ └── main.cpp ├── 04-basic-linking │ ├── .gitignore │ ├── 01-build.sh │ ├── 02-build.sh │ ├── README.md │ ├── linking-folder │ │ └── README.md │ ├── main.cpp │ └── print_hello.cpp ├── 05-return-value-ub │ ├── README.md │ ├── get.cpp │ └── main.cpp ├── 06-odr │ ├── README.md │ ├── foo.cpp │ └── main.cpp ├── 07-odr-violation-var │ ├── README.md │ └── main.cpp ├── 08-no-odr-violation │ ├── foo.cpp │ └── main.cpp ├── 10-struct-outside │ ├── foo.cpp │ └── main.cpp ├── 11-struct-inside │ ├── foo.cpp │ └── main.cpp ├── 12-struct-ub │ ├── foo.cpp │ └── main.cpp ├── 13-struct-incomplete │ ├── TODO.md │ ├── foo.cpp │ └── main.cpp ├── 20-include │ ├── foo.cpp │ ├── foo.hpp │ └── main.cpp ├── 21-include-dependencies │ ├── foo.cpp │ ├── foo.hpp │ └── main.cpp ├── 22-include-guards │ ├── cli_view.cpp │ ├── cli_view.hpp │ ├── field.cpp │ ├── field.hpp │ └── main.cpp └── progress.md ├── 06-221010 ├── 00-include-bad │ ├── get.cpp │ ├── get.hpp │ └── main.cpp ├── 01-include-cycle │ ├── bar.hpp │ ├── foo.cpp │ ├── foo.hpp │ └── main.cpp ├── 02-forward-include │ ├── bar.hpp │ ├── bar_fwd.hpp │ ├── foo.cpp │ ├── foo.hpp │ ├── foo_fwd.hpp │ ├── main.cpp │ └── todo.md ├── 03-iosfwd │ ├── foo.cpp │ ├── foo.hpp │ ├── foo_check.cpp │ └── foo_check.hpp ├── 10-static-initialization-order-fiasco │ ├── README.md │ ├── bar.cpp │ ├── foo.cpp │ ├── foo.hpp │ └── main.cpp ├── 11-static-initialization-order-fiasco-iostream │ ├── foo.cpp │ ├── foo.hpp │ └── main.cpp ├── 12-construct-on-first-use │ ├── bar.cpp │ ├── foo.cpp │ ├── foo.hpp │ └── main.cpp ├── 20-unnamed-namespace │ ├── main.cpp │ ├── other.cpp │ └── other.hpp └── todo.md ├── 07-221017 ├── 01-extra │ ├── 01-floating.cpp │ ├── 02-floating-ops.cpp │ ├── 03-floating-bad.cpp │ ├── 04-long-long-vs-double.cpp │ ├── 10-order-of-eval.cpp │ ├── 11-interleaving.cpp │ ├── 12-vector-ub-before-cpp17.cpp │ └── 13-short-circuit.cpp ├── 02-containers │ ├── 01-set.cpp │ ├── 02-iterators.cpp │ ├── 03-structured-binding.cpp │ ├── 04-map.cpp │ ├── 05-map-indexing.cpp │ └── 06-random-vs-bidirectional.cpp └── 03-algorithms │ ├── 01-sort.cpp │ ├── 02-capture.cpp │ ├── 03-lower-bound.cpp │ ├── 04-upper-bound.cpp │ ├── 05-lower-bound-map.cpp │ ├── 10-remove-if.cpp │ ├── 11-erase.cpp │ └── 12-erase-good.cpp ├── 08-221107 ├── 01-old │ ├── 01-inner-class.cpp │ └── 02-static-vs-friend.cpp ├── 02-raw-pointers │ ├── 00-todo.md │ ├── 01-pointers.cpp │ └── 02-this-is-a-pointer.cpp ├── 03-unique-ptr │ ├── 01-dynamic-storage.cpp │ ├── 02-basic.cpp │ ├── 03-copy.cpp │ ├── 04-move.cpp │ ├── 05-move-in-ctor.cpp │ ├── 06-raw-and-unique.cpp │ └── 07-move-containers.cpp ├── 04-basic-inheritance │ ├── 00-warning.md │ ├── 01-basic.cpp │ ├── 02-compatible.cpp │ ├── 03-ctors.cpp │ ├── 04-no-polymorph.cpp │ ├── 05-virtual.cpp │ ├── 06-pure-virtual.cpp │ ├── 07-vector-a.cpp │ ├── 08-vector-b.cpp │ ├── 09-vector-c.cpp │ └── TODO.md ├── TODO.md └── progress.md ├── 09-221114 ├── 01-lifetime │ ├── 01-special-ops.cpp │ ├── 02-automatic.cpp │ ├── 03-dynamic-syntax.cpp │ ├── 04-vector.cpp │ ├── 05-automatic-dangling.cpp │ ├── 06-invalidation.cpp │ ├── 10-static.cpp │ ├── 11-static-func-ok.cpp │ ├── 12-static-func-oops.cpp │ ├── 13-static-class.cpp │ └── 30-address.cpp ├── 02-temporary-lifetime │ ├── 01-temporary.cpp │ ├── 02-dangling.cpp │ ├── 03-const-extension.cpp │ ├── 04-id.cpp │ └── 05-min.cpp ├── 03-derived-cast │ ├── 01-casts.cpp │ ├── 02-bad-c-cast.cpp │ └── 03-list.cpp ├── 04-rtti │ ├── 01-typeid-basic.cpp │ ├── 02-typeid-operations.cpp │ ├── 03-dynamic-cast.cpp │ └── 04-dynamic-cast-ref.cpp └── progress.md ├── 10-221121 ├── 01-move-objects │ ├── 01-swap-vectors.cpp │ ├── 02-swap-structs.cpp │ ├── 03-move-to-field.cpp │ └── 04-moved-from-state.cpp ├── 02-old │ ├── 01-friend-make-unique-bad.cpp │ ├── 02-final-struct.cpp │ └── 03-final-methods.cpp ├── 03-external-library │ ├── 01-boost-header-only.cpp │ ├── 02-boost-link-filesystem.cpp │ ├── 03-sfml.cpp │ ├── 04-nana.cpp │ ├── 05-hello-world-needs-dll.cpp │ └── README.md ├── 04-cmake │ ├── CMakeLists.txt │ ├── include │ │ └── foo.hpp │ └── src │ │ ├── foo.cpp │ │ └── main.cpp ├── 05-cmake-external-library │ ├── CMakeLists.txt │ ├── include │ │ └── foo.hpp │ └── src │ │ ├── foo.cpp │ │ └── main.cpp ├── 06-shared-library │ ├── CMakeLists.txt │ ├── abstract_plugin.hpp │ ├── main.cpp │ ├── plan.md │ ├── plugin_multiply.cpp │ └── plugin_sum.cpp ├── TODO.md └── progress.md ├── 11-221128 ├── 01-old │ └── 01-virtual-dtor │ │ ├── 08-vector-b.cpp │ │ ├── 08-vector-b2.cpp │ │ ├── 09-vector-c.cpp │ │ ├── 09-vector-c2.cpp │ │ ├── README.md │ │ └── TODO.md ├── 02-threads │ ├── 01-basic-thread │ │ ├── 01-simple.cpp │ │ ├── 02-args.cpp │ │ ├── 03-detached.cpp │ │ └── 04-computation.cpp │ ├── 02-race │ │ ├── 01-writeln-single.cpp │ │ ├── 02-writeln-race.cpp │ │ ├── 03-writeln-mutex-good.cpp │ │ ├── 04-writeln-mutex-bad.cpp │ │ ├── 05-writeln-mutex-lock-bad.cpp │ │ ├── 06-writeln-mutex-lock-good.cpp │ │ └── mutex.md │ ├── 03-data-race │ │ ├── 01-counter.cpp │ │ ├── 02-even-counter.cpp │ │ ├── 03-even-counter-snapshot.cpp │ │ ├── 04-two-threads.cpp │ │ ├── 05-two-threads-mutex-bad.cpp │ │ ├── 06-two-threads-mutex-good.cpp │ │ ├── 07-two-threads-atomic-bad.cpp │ │ ├── 08-two-threads-atomic-also-bad.cpp │ │ ├── 09-two-threads-atomic-very-bad.cpp │ │ └── README.md │ ├── 04-model │ │ ├── .gitignore │ │ ├── 01-optimizer.cpp │ │ ├── 02-reordering.cpp │ │ ├── 03-volatile-bad.cpp │ │ ├── 04-happens-before.md │ │ ├── 04-happens-before.tex │ │ └── README.md │ ├── 05-producer-consumer │ │ ├── 01-promise-future.cpp │ │ └── 02-queues.md │ ├── TODO.md │ ├── links.md │ └── progress.md └── todo.md ├── 12-221205 ├── 01-c-arrays │ ├── 01-basic.cpp │ ├── 02-vla.cpp │ ├── 03-init.cpp │ ├── 04-basic-arithmetics.cpp │ ├── 05-arithmetics-borders.cpp │ ├── 10-as-field.cpp │ ├── 11-heap.cpp │ ├── 12-vector-as-arr.cpp │ └── 13-pass-as-arg.cpp ├── 02-c-str │ ├── 01-c-str.cpp │ ├── 02-compare.cpp │ ├── 03-len.cpp │ ├── 04-out-of-bounds.cpp │ ├── 10-allocator-bad.cpp │ ├── 11-static-buf-read-word.cpp │ ├── 12-gets-bad.cpp │ ├── 13-fgets-safe.cpp │ ├── 20-string-dangling.cpp │ └── optimization.h ├── 03-c-library │ ├── 01-description.md │ ├── 02-opaque-pointers.cpp │ ├── 03-void-star.cpp │ └── 04-const-cast.cpp └── todo.md ├── 13-221212 ├── 01-functions │ ├── 01-overloads.cpp │ ├── 02-overload-null.cpp │ ├── 03-std-lcm.cpp │ ├── 04-unnamed-arg.cpp │ ├── 05-tags.cpp │ ├── 06-default.cpp │ └── 07-default-overload.cpp ├── 02-function-objects │ ├── 01-compare.cpp │ ├── 02-compare-capture.cpp │ ├── 03-set.cpp │ ├── 04-set-capture.cpp │ ├── 05-set-fptr.cpp │ ├── 06-std-function.cpp │ ├── 07-stl-copies.cpp │ └── 08-ref-wrapper.cpp ├── 03-lambdas │ ├── 00-lambda-example.cpp │ ├── 01-lambda-captures.cpp │ ├── 02-distinct-types.cpp │ └── 03-no-recursion.cpp ├── 04-typedef-using.cpp ├── 05-inheritance-extra │ ├── 10-virtual-in-ctors.cpp │ └── 11-pure-virtual-ctors.cpp ├── 10-patterns │ └── 01-circle-ellipse.cpp ├── next.md └── progress.md ├── 13x-221218 ├── 01-structured-binding │ └── 01-structured-binding.cpp ├── 02-slicing │ ├── 01-slicing.cpp │ └── 02-prevent-slicing.cpp ├── 03-copying │ ├── a.cpp │ └── b.py ├── 04-const-ref-mutated │ └── a.cpp ├── 05-const-qualifier │ └── a.cpp ├── 06-cast-copies │ └── a.cpp ├── 07-eof-bad │ ├── a.txt │ ├── bad.cpp │ └── link.txt ├── 08-order-of-fields │ └── a.cpp ├── 09-complex-comparison │ ├── a.cpp │ └── a.py └── 10-friend │ ├── a.cpp │ ├── b.cpp │ └── c.cpp ├── 13y-221225 ├── 01-copy-direct-init │ ├── 01-copy-initialization.cpp │ ├── 02-direct-initialization.cpp │ └── 03-conversions.cpp ├── 02-static │ └── question.cpp ├── 03-auto-return-deduction │ ├── 01.cpp │ ├── 02.cpp │ ├── 03.cpp │ └── README.md ├── 04-return-braces │ └── main.cpp └── 05.md ├── 14-220123 ├── 01-move-semantics │ ├── 01-value-category.cpp │ ├── 02-refs.cpp │ └── 03-specials.cpp ├── 02-templates │ ├── 01-old.cpp │ ├── 02-class-template.cpp │ ├── 03-instantiation.cpp │ ├── 04-shortcut.cpp │ ├── 10-function-template.cpp │ ├── 11-argument-deduction.cpp │ ├── 12-function-instantiation.cpp │ └── 20-static-dynamic-polymorphism.cpp ├── 03-functors │ ├── 01-calling.cpp │ ├── 02-calling-stateful.cpp │ └── 03-storing.cpp └── 04-misc │ ├── 01-operator-deref.cpp │ └── 02-operator-arrow.cpp ├── 15-230130 ├── 00-questions │ ├── 01-incomplete-type.cpp │ └── 02-deleter-functor.cpp ├── 01-preprocessor-basic │ ├── 01-preprocessor-not-related-to-cpp.txt │ ├── 02-trigraphs-newlines.cpp │ ├── 03-literals-int-str-concat.cpp │ ├── 10-ifdef-define.cpp │ ├── 11-ifdef-compiler.cpp │ ├── 12-ignore-warning.cpp │ ├── 20-macros-expanded-naively.cpp │ ├── 21-macro-ub.cpp │ └── included-text.txt ├── 02-macro-functions │ ├── 01-macro-func-bad.cpp │ ├── 02-macro-func-good.cpp │ ├── 03-function-like-statement-bad.cpp │ ├── 04-function-like-statement-bad.cpp │ ├── 05-function-like-statement-good.cpp │ ├── 10-assert.cpp │ ├── 11-concat-tokens.cpp │ └── 12-concat-tokens-more.cpp ├── 03-extra-macro │ ├── 01-variadic-macro.cpp │ ├── 02-no-recursion.cpp │ ├── 03-macro-high-order-enum.cpp │ ├── 04-code-block.cpp │ ├── 05-logging.cpp │ └── 06-extra.md └── TODO.md ├── 16-230206 ├── 01-ideology │ └── README.md ├── 02-error-techniques │ ├── 01-object-state-flag.cpp │ ├── 02-global-errno.cpp │ ├── 03-retval.cpp │ ├── 04-either.rs │ ├── 05-either-syntax-sugar.rs │ ├── 10-no-handling.cpp │ ├── 11-handle-in-place.cpp │ ├── 12-propagate.cpp │ ├── numbers-01-simple.in │ └── numbers-02-immediate-eof.in ├── 03-basic-exceptions │ ├── .idea │ │ ├── .gitignore │ │ ├── .name │ │ ├── 03-basic-exceptions.iml │ │ ├── misc.xml │ │ ├── modules.xml │ │ └── vcs.xml │ ├── 01-basic.cpp │ ├── 02-destructors.cpp │ ├── 03-multiple-catch.cpp │ ├── 04-catch-inheritance.cpp │ ├── 05-complex-try-block.cpp │ ├── 06-uncaught.cpp │ ├── 20-std-exceptions.cpp │ ├── 21-inherit.cpp │ ├── 30-final-notes.md │ ├── CMakeLists.txt │ └── cmake-build-debug │ │ ├── .cmake │ │ └── api │ │ │ └── v1 │ │ │ ├── query │ │ │ ├── cache-v2 │ │ │ ├── cmakeFiles-v1 │ │ │ ├── codemodel-v2 │ │ │ └── toolchains-v1 │ │ │ └── reply │ │ │ ├── cache-v2-bf2cedbce2857656583b.json │ │ │ ├── cmakeFiles-v1-9e715c91031bb01cf401.json │ │ │ ├── codemodel-v2-d20377ba1e18ce169705.json │ │ │ ├── directory-.-Debug-d0094a50bb2071803777.json │ │ │ ├── index-2023-02-06T09-25-25-0721.json │ │ │ ├── target-02-destructors-Debug-2752088d5503e67a9179.json │ │ │ ├── target-05-complex-try-block-Debug-ce1bfb0a979b4e05ca32.json │ │ │ └── toolchains-v1-94e2df65455c4944eba3.json │ │ ├── .ninja_deps │ │ ├── .ninja_log │ │ ├── Testing │ │ └── Temporary │ │ │ └── LastTest.log │ │ └── build.ninja ├── TODO.md └── todo │ ├── 10-exception-safety.cpp │ └── 11-no-exception-safety.cpp ├── 17-230213 ├── 00-extra-classes │ ├── 01-inheritance-visibility.cpp │ ├── 02-inheritance-class.cpp │ ├── 03-inheritance-private-noncopyable.cpp │ ├── 10-slicing.cpp │ ├── 11-prevent-slicing.cpp │ └── 20-delegating-ctor.cpp ├── 01-weird-exceptions │ ├── 01-rethrow.cpp │ └── 02-rethrow-slicing.cpp └── 02-intermediate-exceptions │ ├── 01-not-exception.cpp │ ├── 02-guarantees.cpp │ ├── 10-noexcept.cpp │ ├── 11-noexcept-catch-inside.cpp │ ├── 12-dtor-noexcept.cpp │ ├── 13-noexcept-concerns.md │ ├── 14-move-noexcept.cpp │ ├── 20-raii.cpp │ ├── 21-catch-ctor-and.cpp │ ├── 22-catch-ctor-only.cpp │ ├── 30-between-tu.a.cpp │ ├── 30-between-tu.b.cpp │ ├── 30-between-tu.c.cpp │ ├── 40-speed-no-throw.cpp │ ├── 41-speed-throw.cpp │ └── 42-notes.md ├── 18-230220 ├── 00-old │ └── 01-exception-ptr.cpp ├── 01-exceptions-everywhere │ ├── 01-ctor.cpp │ ├── 02-array.cpp │ ├── 03-members.cpp │ ├── 04-member-init-list.cpp │ ├── 05-member-ctor.cpp │ ├── 06-base-fails.cpp │ ├── 07-derived-fails.cpp │ ├── 08-delegeted-inside.cpp │ ├── 09-delegated-outside.cpp │ ├── 10-args.cpp │ ├── 11-interleaving.cpp │ ├── 12-return.cpp │ ├── 13-return-assignment.cpp │ ├── 14-stack-pop.cpp │ ├── 15-stack-pop-fix.cpp │ ├── 20-function-try-block-ctor.cpp │ ├── 21-function-try-block-dtor.cpp │ ├── 22-function-try-block-func.cpp │ └── 30-default-assignment-basic-violation.cpp └── 02-threads │ └── 01-producer-consumer │ ├── 01-promise-future.cpp │ ├── 02-queues.md │ └── 10-condvar.cpp ├── 19-230227 ├── 01-threads │ ├── 01-producer-consumer │ │ ├── 02-producer-consumer.cpp │ │ ├── 10-condvar.cpp │ │ ├── 11-condvar-bad-fix.cpp │ │ ├── 12-condvar-bad-fix-bad-fix.cpp │ │ ├── 13-condvar-fixed.cpp │ │ ├── 20-async-bad.cpp │ │ ├── NOTES.md │ │ └── TODO.md │ └── 04-mutable │ │ ├── 01-mutable.cpp │ │ └── 02-mutable-for-cache.cpp └── 02-network │ ├── 01-theory.md │ ├── 02-server.cpp │ ├── 03-client.cpp │ ├── 10-read-lines-bad.cpp │ ├── 11-send-lines-not-helping.cpp │ ├── 20-exceptions-gcc-bug.cpp │ └── README.md ├── 20-230306 ├── 02-network │ ├── 30-nat.md │ ├── 31-sync-vs-async.md │ └── 32-boost-vs-qt.md ├── 03-threads │ ├── 01-mutual-deadlock │ │ ├── 01-mutual.cpp │ │ └── 02-kludge-solution.cpp │ ├── 02-api-design │ │ ├── 01-non-atomic.cpp │ │ ├── 02-deadlock.cpp │ │ ├── 03-two-mutexes-bad.cpp │ │ ├── 04-atomic-api.cpp │ │ ├── 20-leaking-from-lock.cpp │ │ ├── 21-balance-toc-tou.cpp │ │ ├── 22-toctou-wild.md │ │ └── 23-balance-fix.cpp │ └── 03-thread-misc │ │ ├── 01-shared-ptr-safety.cpp │ │ ├── 02-thread-local.cpp │ │ └── 10-general-knowledge.md ├── 04-old │ └── 01-calling-stateful-method.cpp └── 05-multiple-tus │ ├── 20-function-template-multiple-tu-bad │ ├── foo.cpp │ ├── main.cpp │ ├── print.cpp │ └── print.hpp │ ├── 21-function-template-multiple-tu │ ├── foo.cpp │ ├── main.cpp │ └── print.hpp │ └── 22-class-template-multiple-tu │ ├── foo.cpp │ ├── main.cpp │ └── my_templ.hpp ├── 21-230313 ├── 05-multiple-tus │ ├── 01-extern-var-siof │ │ ├── a.cpp │ │ └── main.cpp │ ├── 02-const-var-no-linkage │ │ ├── a.cpp │ │ └── main.cpp │ ├── 10-inline │ │ ├── foo.cpp │ │ ├── main.cpp │ │ ├── print.cpp │ │ └── print.h │ ├── 11-inline-var-almost-no-siof │ │ ├── a.cpp │ │ └── main.cpp │ ├── 12-static-member-redefinition │ │ ├── a.cpp │ │ └── main.cpp │ ├── 13-static-member-inline │ │ ├── a.cpp │ │ └── main.cpp │ └── 14-global-consts-multiple-tu │ │ ├── a.cpp │ │ ├── a.h │ │ └── main.cpp ├── 10-align-padding │ ├── 01-alignment.cpp │ ├── 02-padding.cpp │ ├── 03-padding-arrays.cpp │ ├── 04-padding-order.cpp │ ├── 05-padding-inheritance.cpp │ └── TODO.md ├── 11-for-optional │ ├── 01-ref-qualifiers.cpp │ ├── 02-ref-qualifiers-own.cpp │ ├── 10-placement-new.cpp │ ├── 11-placement-new-meeeeh.cpp │ └── TODO.md └── 12-vtable │ ├── 10-naive-polymorph.cpp │ ├── 11-fptrs.cpp │ ├── 12-vtable.cpp │ └── 13-vtable-inheritance.cpp ├── 22-230320 ├── 01-binary-formats │ ├── 01-basics.md │ ├── 02-strings.cp1251.txt │ ├── 02-strings.cp866.txt │ ├── 02-strings.koi8r.txt │ ├── 02-strings.md │ ├── 02-strings.utf8.txt │ ├── 03-real-world.md │ └── 04-newline.md ├── 02-aliasing │ ├── 01-reinterpret-cast.cpp │ ├── 02-aliasing.cpp │ ├── 03-aliasing-opt.cpp │ ├── 04-write.cpp │ ├── 05-write-bad.cpp │ ├── 06-note.txt │ ├── 07-copy.cpp │ └── extra-reading.md ├── 03-trivially-copyable │ ├── .gitignore │ ├── 01-write.cpp │ ├── 02-read.cpp │ ├── 10-padding.cpp │ ├── 11-padding-read.cpp │ ├── 12-swap-unaligned │ ├── 12-swap-unaligned.cpp │ ├── 13-pack-vector-bad.cpp │ └── 20-standard-layout-pod.cpp └── 04-trivially-copyable-strings │ ├── .gitignore │ ├── 01-c-str-arr-pod.cpp │ ├── 01b-c-str-arr-pod-read.cpp │ ├── 02-c-str-ptr-bad-pod.cpp │ └── 03-string-bad-pod.cpp ├── 23-230411 ├── 01-for-raii │ ├── 01-copy-assignment-bad.cpp │ ├── 02-copy-assignment-basic.cpp │ ├── 03-copy-assignment-strong.cpp │ ├── 10-copy-swap-idiom.cpp │ ├── 11-copy-swap-short.cpp │ └── 12-general-strong-safety.cpp ├── 02-for-vector │ ├── 01-placement-new-in-array.cpp │ ├── 02-new-delete-bad.cpp │ ├── 03-allocator.cpp │ ├── 04-allocator-no-state.cpp │ ├── 10-push-back-aliasing.cpp │ ├── 20-push-back-not-optimal.cpp │ ├── 21-push-back-better.cpp │ ├── 22-push-back-optimal.cpp │ └── 30-const-cast-accessor.cpp ├── 03-vector-is-impossible │ ├── 01-arithmetics.cpp │ └── 02-launder.cpp └── 10-template-friends │ ├── 01-class.cpp │ ├── 02-class-full-spec.cpp │ └── 10-non-templ-func.cpp ├── 24-230413 ├── 00-old │ ├── 01-switch.cpp │ ├── 02-switch-init.cpp │ ├── 03-switch-init.c │ └── 10-array.cpp ├── 01-multidim-arrays │ ├── 01-c-multidim-array.cpp │ └── 02-array-of-arrays.cpp ├── 02-double-pointers │ ├── 01-array-of-strs.cpp │ ├── 02-out-str.cpp │ ├── 02-out-str.in │ ├── 10-derived-cast.cpp │ ├── 11-const-positions.cpp │ └── 12-const-ptr-casts.cpp └── 03-printf-scanf │ ├── 01-formats.c │ ├── 01.in │ ├── 02-snprintf.c │ ├── 03-scanf_s.c │ ├── 03.in │ └── 04-sscanf.c ├── 25-230420 ├── 01-c-generics │ ├── 01-void-ptr.cpp │ ├── 02-void-ptr-print-str.cpp │ ├── 03-void-ptr-extensions.cpp │ ├── 10-fptrs.cpp │ ├── 11-fptrs-templated.cpp │ ├── 12-fptrs-overload.cpp │ ├── 13-fptrs-incompatible.cpp │ ├── 14-fptrs-default-args.cpp │ ├── 20-for-each-int.cpp │ ├── 21-for-each-generic.cpp │ ├── 22-for-each-generic-gcc.cpp │ ├── 23-for-each-generic-context.cpp │ └── TODO.md └── 02-c-differences │ ├── 00-warning.md │ ├── 01-basic.c │ ├── 02-function-args.c │ ├── 03-implicit-function-declaration.c │ ├── 03b-implicit-var.c │ ├── 04-kr-defs.c │ ├── 05-designator-list.c │ ├── 06-memcpy-memmove-restrict.c │ ├── 07-extensions.md │ ├── 10-missing.md │ ├── 20-static-function-var-1.c │ ├── 20-static-function-var-2.c │ ├── 21-struct-typedef.c │ ├── 22-malloc.c │ ├── 22b-malloc-implicit.c │ ├── 23-realloc.c │ ├── 24-incompatibility.c │ ├── 24-incompatibility.cpp │ └── TODO.md ├── 26-230427 ├── 02-goto │ ├── 01-goto-bad.c │ ├── 02-goto-fwd.c │ ├── 02-goto-fwd.cpp │ ├── 03-goto-good-loop-break.cpp │ ├── 04-goto-good-cleanup.c │ ├── data-no-n.in │ ├── data-not-enough.in │ └── data-ok.in ├── 03-unions │ ├── 01-union.c │ ├── 02-union-embedded.c │ ├── 03-anonymous-union.c │ └── 04-anonymous-struct.cpp ├── 04-c-cpp-extern │ ├── 01-extern-c-linking │ │ ├── a.c │ │ ├── b.cpp │ │ ├── build-bad.sh │ │ └── build.sh │ ├── 02-header │ │ ├── a.c │ │ ├── a.h │ │ ├── b.cpp │ │ ├── b.h │ │ ├── build-bad.sh │ │ ├── build.sh │ │ └── xxx.h │ └── 03-header-incompatibility │ │ └── a.h ├── 05-c-resource-management │ ├── 01-libcurl-simple.c │ ├── 02-libcurl-url2file.c │ ├── 10-json.c │ └── 11-json.c └── 06-extra.md ├── 27-230511 ├── 01-inheritance-tricks │ ├── 01-virtual.cpp │ └── 02-crtp.cpp ├── 02-multiple-inheritance │ ├── 01-multiple-inheritance.cpp │ ├── 02-usage-multiple-interfaces.cpp │ ├── 03-crtp-boost-operators.cpp │ ├── 10-side-cast.cpp │ ├── 11-most-derived.cpp │ ├── 12-override-independent.cpp │ ├── 20-diamond-problem.cpp │ ├── 21-virtual-inheritance.cpp │ ├── 22-virtual-inheritance-naive.cpp │ ├── 23-virtual-inheritance-impl.cpp │ ├── 30-iostream.cpp │ └── 31-virtual-interfaces.cpp └── 03-virtual-multiple-inheritance-details │ ├── 01-no-static-downcast.cpp │ ├── 02-dynamic-downcast.cpp │ ├── 03-most-accessible-path.cpp │ ├── 04-delegate-to-sister.cpp │ ├── 10-no-unique-final-overrider.cpp │ ├── 11-unique-final-overrider-in-derived.cpp │ ├── 12-unique-final-overrider-in-bases.cpp │ ├── 13-most-derived.cpp │ └── 20-mixed.cpp ├── 28-230518 ├── 01-template-friends │ ├── 00-link.md │ ├── 10-non-templ-func.cpp │ ├── 11-non-templ-inline.cpp │ ├── 12-non-templ-redef.cpp │ ├── 12-templ-func.cpp │ ├── 13-templ-func-redef.cpp │ ├── 14-templ-func-inline.cpp │ ├── 15-templ-func-spec.cpp │ └── TODO.md ├── 02-template-details │ ├── 01-typename-ambiguity.cpp │ ├── 02-template-member-call-ambiguity.cpp │ ├── 03-dependent-types-deduction.cpp │ ├── 10-conversion-deduction-fail.cpp │ ├── 11-double-angle-bracket.cpp │ ├── 20-class-alises.cpp │ ├── 21-consts.cpp │ ├── 21b-variables.cpp │ ├── 22-definition.cpp │ ├── 30-default-args.cpp │ ├── 31-default-args-deps.cpp │ ├── 32-template-as-template-arg.cpp │ └── TODO.md ├── 03-function-template-details │ ├── 01-const-deduction.cpp │ ├── 02-partial-deduction.cpp │ ├── 03-template-members.cpp │ ├── 04-ctad.cpp │ ├── 05-deduction-fails.cpp │ └── TODO.md └── TODO.md ├── 29-230525 ├── 01-constexpr │ ├── 01-const-vs-constexpr.cpp │ ├── 02-constexpr-struct.cpp │ ├── 03-parse-literal.cpp │ └── 04-ub.cpp ├── 02-specialization │ ├── 01-class.cpp │ ├── 02-vector-bool-bad.cpp │ ├── 03-meta.cpp │ ├── 04-spec-odr-violation │ │ ├── README.md │ │ ├── foo.cpp │ │ ├── main.cpp │ │ ├── print.h │ │ └── print_ext.h │ ├── 10-partial.cpp │ ├── 11-partial-values.cpp │ ├── 12-partial-fail.cpp │ ├── 13-partial-less-types.cpp │ ├── 14-partial-more-types.cpp │ ├── 20-function.cpp │ ├── 21-function-overload.cpp │ ├── 22-function-partial.cpp │ └── 23-swap.cpp ├── 03-meta-conventions │ ├── 00-notes.md │ ├── 01-type-traits.cpp │ ├── 01b-char-traits.cpp │ ├── 02-type-traits-short.cpp │ ├── 03-standard-helpers.cpp │ └── 10-typed-values.cpp ├── 04-variadic │ └── 01-function-variadic-template │ │ ├── 01-basic.cpp │ │ ├── 02-pattern.cpp │ │ ├── 03-argument-deduction.cpp │ │ ├── 04-pack-expansion.cpp │ │ ├── 10-fold-expression.cpp │ │ └── 11-iterate.cpp └── TODO.md ├── 30-230601 ├── 00-misc │ ├── 01-template-lambda.cpp │ ├── 02-tuple.cpp │ ├── 03-tuple-refs.cpp │ └── 04-type-display.cpp ├── 04-variadic │ ├── 01-function-variadic-template │ │ ├── 12-recursive.cpp │ │ ├── 20-value-packs.cpp │ │ ├── 21-auto-value-packs.cpp │ │ └── 30-index-sequence.cpp │ └── 02-class-variadic-template │ │ ├── 01-basic.cpp │ │ ├── 02-class-pack-expansion.cpp │ │ ├── 03-specializations.cpp │ │ ├── 04-tuple-recursive-fields.cpp │ │ └── 05-recursive-compute.cpp ├── 05-perfect-forwarding │ ├── 01-log-naive.cpp │ ├── 02-log-almost.cpp │ ├── 03-log-perfect.cpp │ ├── 04-not-forwarding-reference.cpp │ ├── 05-api-design.md │ ├── 06-perfect-forward-callee.cpp │ ├── 10-decltype.cpp │ ├── 11-decltype-auto.cpp │ ├── 12-perfect-return.cpp │ └── 13-lambdas.cpp └── 06-sfinae-fast │ ├── 01-sfinae-origins.cpp │ ├── 20-need-restricted-templates-task.cpp │ ├── 21-need-restricted-templates-concepts.cpp │ └── 22-need-restricted-templates-sol.cpp ├── 31-230608 ├── 01-sfinae │ ├── 02-sfinae-type-alias.cpp │ ├── 03-sfinae-type-inside-struct.cpp │ ├── 04-sfinae-template-variable.cpp │ ├── 05-sfinae-no-template-variable.cpp │ ├── 10-prologue.txt │ ├── 23-need-restricted-templates.cpp │ ├── 24-retval-comma.cpp │ ├── 30-enable-if-task.cpp │ ├── 31-enable-if-concepts.cpp │ ├── 32-enable-if-sol.cpp │ ├── 40-template-dummy-type.cpp │ ├── 41-template-multiple-overloads.cpp │ ├── 42-template-dummy-value.cpp │ ├── 43-void-t.cpp │ ├── 50-sfinae-in-class-template.cpp │ ├── 51-destructors.cpp │ ├── 52-sfinae-for-not-overloads.cpp │ ├── 60-need-mass-specialization-task.cpp │ ├── 61-need-mass-specialiazation-concepts.cpp │ └── 62-need-mass-specialiazation-sol.cpp ├── 02-cond-noexcept │ ├── 01-if-noexcept.cpp │ ├── 02-cond-noexcept.cpp │ ├── 10-noexcept-operator.cpp │ ├── 11-noexcept-noexcept.cpp │ ├── 12-declval.cpp │ ├── 13-cond-explicit.cpp │ └── TODO.md ├── 03-return-auto │ ├── 01-deduced.cpp │ ├── 02-lambda.cpp │ ├── 03-trailing.cpp │ ├── 04-in-declaration.a.cpp │ └── 04-in-declaration.b.cpp ├── 04-complex-overloads │ ├── 01-simple.cpp │ ├── 02-explicit-templ.cpp │ ├── 03-messy.cpp │ ├── 04-specialization-a.cpp │ ├── 05-specialization-b.cpp │ └── 06-specialization-c.cpp └── 05-blog.txt ├── LICENSE ├── common ├── README.md ├── TODO.md ├── checkver │ ├── .gitignore │ ├── 01-ubuntu-g++-libstdc++.txt │ ├── 02-ubuntu-clang++-libstdc++.txt │ ├── 03-ubuntu-clang++-libc++.txt │ ├── 04-ubuntu-icc-libstdc++.txt │ ├── 10-windows-vs2022.txt │ ├── 20-macos-appleclang.txt │ ├── README.md │ ├── checkver.cpp │ ├── has-cpp17.cpp │ └── has-cpp17.expected.txt ├── macos.md ├── materials.md ├── software.md ├── ubuntu.md └── windows.md ├── next ├── 02-threads │ └── 05-producer-consumer │ │ ├── 02-condvar.cpp │ │ ├── 03-condvar-bad-fix.cpp │ │ ├── 04-condvar-fixed.cpp │ │ ├── 10-async-bad.cpp │ │ ├── NOTES.md │ │ └── TODO.md ├── 13-221212 │ └── xx-patterns │ │ ├── 02-strategy.cpp │ │ ├── 02x-notes.txt │ │ ├── 03-factory.cpp │ │ ├── 10-no-visitor.cpp │ │ └── 11-visitor.cpp ├── TODO.md ├── x5-meta-conventions-variadic │ ├── 10-type-list.cpp │ ├── 11-type-list-generic.cpp │ └── 12-function-traits.cpp └── xx-functions-global-vars.cpp ├── questions-a ├── README.md └── quick │ ├── 01-undefined-reference │ ├── problem │ │ ├── main.cpp │ │ ├── triple.cpp │ │ └── triple.hpp │ └── solution │ │ ├── main.cpp │ │ ├── triple.cpp │ │ └── triple.hpp │ ├── 02-compile-them-all │ ├── problem │ │ ├── 01.txt │ │ ├── 02.txt │ │ ├── 03.txt │ │ ├── 04.txt │ │ └── 05.txt │ └── solution │ │ ├── a.cpp │ │ ├── a.hpp │ │ ├── b.cpp │ │ ├── b.hpp │ │ └── main.cpp │ ├── 03-inheritance │ ├── problem.cpp │ └── solution.cpp │ ├── 04-struct │ ├── problem.md │ └── solution.cpp │ ├── 05-multithreading │ ├── problem.cpp │ └── solution.cpp │ ├── 06-ub-iterators │ ├── problem.cpp │ └── solution.cpp │ ├── 07-ub-erase │ ├── problem.cpp │ └── solution.cpp │ ├── 08-functions │ └── problem.cpp │ └── README.md └── questions-b └── README.md /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: Chromium 2 | IndentWidth: 4 3 | AccessModifierOffset: -4 4 | PointerAlignment: Right 5 | IncludeBlocks: Merge 6 | AllowShortBlocksOnASingleLine: false 7 | AllowShortFunctionsOnASingleLine: false 8 | AllowShortIfStatementsOnASingleLine: false 9 | AllowShortLoopsOnASingleLine: false 10 | 11 | # Only from clang-format 14.0.0 12 | AlignAfterOpenBracket: BlockIndent 13 | QualifierAlignment: Left 14 | SeparateDefinitionBlocks: Always 15 | EmptyLineAfterAccessModifier: Never 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pdf 2 | 3 | CMakeCache.txt 4 | CMakeFiles/ 5 | Makefile 6 | cmake_install.cmake 7 | *.sln 8 | *.vcxproj 9 | *.vcxproj.filters 10 | 11 | # Prerequisites 12 | *.d 13 | 14 | # Compiled Object files 15 | *.slo 16 | *.lo 17 | *.o 18 | *.obj 19 | 20 | # Precompiled Headers 21 | *.gch 22 | *.pch 23 | 24 | # Compiled Dynamic libraries 25 | *.so 26 | *.dylib 27 | *.dll 28 | 29 | # Fortran module files 30 | *.mod 31 | *.smod 32 | 33 | # Compiled Static libraries 34 | *.lai 35 | *.la 36 | *.a 37 | *.lib 38 | 39 | # Executables 40 | *.exe 41 | *.out 42 | *.app 43 | -------------------------------------------------------------------------------- /01-220905/03-basic/01-hello-world.cpp: -------------------------------------------------------------------------------- 1 | #include // Akin to `import` in Python/Java, details later 2 | 3 | // Top-level: no code, only functions/global variables/#include/etc 4 | 5 | int main() { // entry point, the `main` function 6 | std::cout << "Hello World\n"; // printing to the "standard output" of the program 7 | // only double quotes, escaping with \ works 8 | return 0; // any application has an "exit code", 0 is "success" by convention, 9 | // everything else is typically "runtime error" 10 | } 11 | -------------------------------------------------------------------------------- /01-220905/03-basic/02-no-main-return.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | std::cout << "Hello World\n"; 5 | // In `main` (and `main` only) `return 0` is automatically appended. 6 | // Hooray! Hello World in 4 lines. Maybe in 2. 7 | } 8 | -------------------------------------------------------------------------------- /01-220905/03-basic/03-a-plus-b.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | /* variable declaration: type of a variable is always fixed 5 | type is a pair of (possible values, possible operations) */ 6 | int a /* comment here */, b; 7 | a = 5; // ok 8 | std::cin >> a >> b; 9 | std::cout << a + b << std::endl; // like "\n", but flushes buffer, much slower 10 | 11 | // Alternative 12 | int s = a + b; // declare variable right before it's needed please! 13 | std::cout << s << std::endl; 14 | } 15 | -------------------------------------------------------------------------------- /01-220905/03-basic/04-compilation-error.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | int a, b; 5 | std::cin >> a >> b; 6 | a = "hello"; // compilation error: cannot assign string (`const char*` because legacy) to an `int` variable 7 | std::cout << a + b << std::endl; 8 | } 9 | -------------------------------------------------------------------------------- /01-220905/03-basic/05-uninitialized-vars.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | { 5 | int wtf = 123; 6 | std::cout << wtf << "\n"; 7 | } 8 | { 9 | int x; 10 | x = x * 0; // reading from uninitialized variable is UB (undefined behavior): https://notes.algoprog.ru/cpp/additional.html#undefined-behavior 11 | std::cout << x << "\n"; // but it behaves ok with my compiler in this program 12 | // Note: if not multiplied by `0`, it's constant on my Windows and something random on my Linux. 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /01-220905/03-basic/07-using-namespace.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // To the compiler: when unable to find X, check for std::X as well. 4 | // Typically each library has its own "namespace", `std` is for the standard C++ library. 5 | // Bad style: lots of stuff in `std`, and more gets added with each standard. 6 | using namespace std; 7 | 8 | int main() { 9 | int a, b; 10 | // Helps in olympiads: less to type, do not care about other compilers or newer standards. 11 | cin >> a >> b; 12 | cout << a << b; 13 | } 14 | -------------------------------------------------------------------------------- /01-220905/03-basic/links.md: -------------------------------------------------------------------------------- 1 | https://notes.algoprog.ru/cpp/syntax.html -------------------------------------------------------------------------------- /01-220905/TODO.md: -------------------------------------------------------------------------------- 1 | Talk about standards and compilers should not take 45-60 minutes, probably? 2 | Add info about upsolving (see letter from the beginning of 2022/12). 3 | -------------------------------------------------------------------------------- /01-220905/progress.md: -------------------------------------------------------------------------------- 1 | ПАДИИ-1: до 03-basic/12-conversions включительно 2 | ПМИ: до 03-basic/07-using-namespace включительно 3 | ПАДИИ-2: до 03-basic/05-uninitialized-vars включительно 4 | 5 | На болтологию лучше время ограничить 6 | -------------------------------------------------------------------------------- /02-220912/00-old.md: -------------------------------------------------------------------------------- 1 | Materials available in `common/` 2 | You've got an email from me this night 3 | -------------------------------------------------------------------------------- /02-220912/01-arithmetics/02-int-overflow-ub.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | int i = 1; 5 | while (true) { 6 | i = i * 3; // UB is typically caught by -fsanitize=undefined, execution 7 | // continues 8 | std::cout << i << "\n"; 9 | if (i < 0) { // Typically optimized out by the compiler. 10 | std::cout << "Overflow detected\n"; 11 | return 0; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /02-220912/01-arithmetics/10-other-ints.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | std::cout << "short: " << sizeof(short) << "\n"; // Typically 2 bytes 6 | std::cout << "unsigned short: " << sizeof(unsigned short) << "\n"; 7 | std::cout << "long: " << sizeof(long) 8 | << "\n"; // Typically 4 or 8 bytes (see msys2 vs Linux) 9 | std::cout << "std::size_t: " << sizeof(std::size_t) 10 | << "\n"; // Typically 4 or 8 bytes 11 | 12 | std::size_t x = 13 | -1; // std::size_t is unsigned, used for sizes of arrays/variables... 14 | std::cout << x << "\n"; 15 | } 16 | -------------------------------------------------------------------------------- /02-220912/01-arithmetics/20-assignment.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | int x = 0, y = 0; 5 | x = y = 20; 6 | std::cout << x << " " << y << "\n"; 7 | 8 | std::cout << (x = 15) << "\n"; // 15, but what for? 9 | std::cout << x << "\n"; // 15 10 | 11 | if (x = 5) { // modern compiler should emit warning 12 | std::cout << "x = " << x << "\n"; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /02-220912/02-branching/05-comma-operator.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | // comma operators evaluates left, then right, returns right: 5 | // https://en.cppreference.com/w/cpp/language/operator_other used to show 6 | // off: 7 | int a = 0, b = 0, c = 0; 8 | std::cout << (a = 1, b = 2, c = 3) << "\n"; // 3 9 | std::cout << a << " " << b << " " << c << "\n"; 10 | 11 | // sometimes more useful: 12 | for (int i = 0, j = 10 /* usual variable declaration */; i <= j; 13 | i++, j-- /* comma operator */) { 14 | std::cout << i << " " << j << "\n"; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /02-220912/03-array/03-array-underflow.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | std::vector v{1, 2, 3}; 6 | std::cout << v[-1] << "\n"; // UB, not v[2], unlike Python 7 | } 8 | -------------------------------------------------------------------------------- /02-220912/TODO.md: -------------------------------------------------------------------------------- 1 | Less details about arithmetics, division, bitwise operations? 2 | It is not necessary in C++ course during the first labs, and we still have notes.algoprog.ru 3 | 4 | -------------------------------------------------------------------------------- /02-220912/progress.md: -------------------------------------------------------------------------------- 1 | ПМИ: целиком 2 | ПАДИИ-2: до 01-arithmetics включительно 3 | ПАДИИ-1: до 02-branching включительно 4 | -------------------------------------------------------------------------------- /03-220919/01-array/11-vector-assert.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | std::vector v{1, 2, 3}; 7 | assert(v == std::vector{1, 2, 3}); // Compilation error because assert is a naive macro 8 | assert((v == std::vector{1, 2, 3})); // OK 9 | assert(v == (std::vector{1, 2, 3})); // OK 10 | std::cout << "OK\n"; 11 | } 12 | -------------------------------------------------------------------------------- /03-220919/01-array/12-vector-missing.md: -------------------------------------------------------------------------------- 1 | Unlike Python: 2 | 3 | * No slices `a[1:10:2]` 4 | * Arrays are homogenous: all elements have the same type, known in advance 5 | -------------------------------------------------------------------------------- /03-220919/01-array/13-vector-bool.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | // Extra reading: https://isocpp.org/blog/2012/11/on-vectorbool 6 | std::vector v{false, true, false}; 7 | std::cout << v[0] << v[1] << v[2] << "\n"; // 010 8 | 9 | for ([[maybe_unused]] bool x : v) { // copy as expected 10 | x = true; 11 | } 12 | std::cout << v[0] << v[1] << v[2] << "\n"; // 010 13 | 14 | for (auto x : v) { // copy? 15 | x = true; 16 | } 17 | std::cout << v[0] << v[1] << v[2] << "\n"; // 111 ?! 18 | } 19 | -------------------------------------------------------------------------------- /03-220919/01-array/14-vector-c-array.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | int n; 5 | std::cin >> n; 6 | 7 | int v1[3], v2[3]; // uninitialized memory 8 | // no push_back, pop_back, resize 9 | v2 = v1; // compilation error 10 | 11 | [[maybe_unused]] int v3[n]; // non-standard extension: variable-length-array (VLA) 12 | 13 | // Do not use! 14 | } 15 | -------------------------------------------------------------------------------- /03-220919/02-strings/02-char-vector-wtf.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | std::vector vec1('a', 'b'); // vec2(97, 98); 6 | std::cout << vec1.size() << ' ' << vec1[0] << '\n'; 7 | 8 | std::vector vec2{'a', 'b'}; 9 | std::cout << vec2.size() << ' ' << vec2[0] << '\n'; // 2 elements: 97, 98. 10 | } 11 | -------------------------------------------------------------------------------- /03-220919/02-strings/11-stringstream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | { 6 | std::stringstream s; 7 | int x = 456; 8 | s << 123 << ' ' << x; 9 | 10 | std::string str = s.str(); 11 | std::cout << str.size() << ">" << str << "<\n"; 12 | 13 | int y, z; 14 | s >> y >> z; 15 | std::cout << "y=" << y << ", z=" << z << "\n"; 16 | } 17 | { 18 | std::stringstream s(" -10 -20 "); 19 | int y, z; 20 | s >> y >> z; 21 | std::cout << "y=" << y << ", z=" << z << "\n"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /03-220919/02-strings/12-to-string.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | std::string s = std::to_string(10); 6 | // std::string s2 = static_cast(10); // compilation error 7 | std::cout << s.size() << ' ' << s << "\n"; 8 | 9 | int x = std::stoi("123"); // string-to-int, stoll 10 | std::cout << x << "\n"; 11 | 12 | std::string s3 = static_cast(0); // UB, because C++ and legacy 13 | std::cout << s3 << '\n'; 14 | 15 | std::cout << "oops\n"; 16 | } 17 | -------------------------------------------------------------------------------- /03-220919/02-strings/13-cin-vs-getline.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | std::string s1; 5 | std::cin >> s1; // skip whitespaces, read non-whitespaces 6 | std::cout << ">" << s1 << "<\n"; 7 | 8 | std::string s2; 9 | std::getline(std::cin, s2); // read until end of line 10 | std::cout << ">" << s2 << "<\n"; 11 | } 12 | -------------------------------------------------------------------------------- /03-220919/02-strings/14-encodings.01.in: -------------------------------------------------------------------------------- 1 | привет 2 | -------------------------------------------------------------------------------- /03-220919/02-strings/14-encodings.02.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hse-spb-2022-cpp/lectures/fb4f0527a3e94fb3d4d6562c5443aa55a50ecb39/03-220919/02-strings/14-encodings.02.in -------------------------------------------------------------------------------- /03-220919/02-strings/14-encodings.03.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hse-spb-2022-cpp/lectures/fb4f0527a3e94fb3d4d6562c5443aa55a50ecb39/03-220919/02-strings/14-encodings.03.in -------------------------------------------------------------------------------- /03-220919/02-strings/14-encodings.04.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hse-spb-2022-cpp/lectures/fb4f0527a3e94fb3d4d6562c5443aa55a50ecb39/03-220919/02-strings/14-encodings.04.in -------------------------------------------------------------------------------- /03-220919/02-strings/14-encodings.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | while (true) { 5 | int c = std::cin.get(); 6 | if (c == std::char_traits::eof()) { // theoretically can be not -1 7 | break; 8 | } 9 | std::cout << c << '\n'; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /03-220919/03-eof/01-while-eof.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | while (!std::cin.eof()) { // Never do that: only checks whether EOF is already known. 5 | int x; 6 | std::cin >> x; // Reads until the number is ended, not further. 7 | std::cout << x << "\n"; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /03-220919/03-eof/01-while-eof.in: -------------------------------------------------------------------------------- 1 | 1 2 3 2 | -------------------------------------------------------------------------------- /03-220919/03-eof/02-while-char-eof.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | while (true) { 5 | char c = std::cin.get(); 6 | if (c == std::char_traits::eof()) { // Some `char`'s values may coincide with `eof()` 7 | break; 8 | } 9 | std::cout << c << '\n'; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /03-220919/03-eof/02-while-char-eof.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hse-spb-2022-cpp/lectures/fb4f0527a3e94fb3d4d6562c5443aa55a50ecb39/03-220919/03-eof/02-while-char-eof.txt -------------------------------------------------------------------------------- /03-220919/03-eof/03-while-success.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | while (true) { 5 | int x; 6 | if (!(std::cin >> x)) { 7 | break; 8 | } 9 | std::cout << x << "\n"; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /03-220919/03-eof/03-while-success.in: -------------------------------------------------------------------------------- 1 | 1 2 3 2 | -------------------------------------------------------------------------------- /03-220919/03-eof/TODO.md: -------------------------------------------------------------------------------- 1 | More 02 somewhere else, it does not belong between 01 and 03 2 | 3 | -------------------------------------------------------------------------------- /03-220919/04-functions/01-simple.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int sum(int a, int b) { // each parameter is a copy of an arguments; pass-by-value 4 | a += b; // does not modifies arguments 5 | std::cout << "new a=" << a << "\n"; 6 | return a; 7 | } 8 | 9 | int main() { 10 | int x = 5; 11 | std::cout << sum(x, 20) << '\n'; // 25 12 | std::cout << x << '\n'; // 5 13 | std::cout << sum(10, 20) << '\n'; // would be hard to modify 10 14 | } 15 | -------------------------------------------------------------------------------- /03-220919/04-functions/02-no-return.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int sum(int a, int b) { 4 | a += b; 5 | if (a == 25) { 6 | return 10; 7 | } 8 | } 9 | 10 | int main() { 11 | int x = 5; 12 | std::cout << "Started\n"; 13 | sum(x, 20); // ok 14 | std::cout << "Middle\n"; 15 | sum(x, 21); // UB, caught by UBSan 16 | std::cout << "OK\n"; 17 | } 18 | -------------------------------------------------------------------------------- /03-220919/04-functions/03-return-void.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void print(int a) { 4 | std::cout << a << '\n'; 5 | if (a == 5) { 6 | return; 7 | } 8 | std::cout << "a is not 5\n"; 9 | return; // optional 10 | } 11 | 12 | int main() { 13 | print(5); 14 | print(6); 15 | } 16 | -------------------------------------------------------------------------------- /03-220919/04-functions/04-copy-slow.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int sz(std::string s) { // pass-by-value 6 | return static_cast(s.size()); 7 | } 8 | 9 | int main() { 10 | const int LEN = 1'000'000; 11 | 12 | std::string s(LEN, 'x'); 13 | std::cout << s.size() << '\n'; 14 | 15 | for (int i = 0; i < 1'000'000; i++) { 16 | assert(s.size() == LEN); 17 | } 18 | std::cout << "OK 1/2\n"; 19 | 20 | for (int i = 0; i < 1'000'000; i++) { 21 | assert(sz(s) == LEN); 22 | } 23 | std::cout << "OK 2/2\n"; 24 | } 25 | -------------------------------------------------------------------------------- /03-220919/04-functions/11-return-by-value.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | std::string BIG(1'000'000, 'x'); 5 | 6 | std::string create_string() { 7 | return BIG; // return copies; O(n) 8 | } 9 | 10 | int main() { 11 | for (int i = 0; i < 1'000'000; i++) { 12 | create_string(); 13 | } 14 | std::cout << "OK\n"; 15 | } 16 | -------------------------------------------------------------------------------- /03-220919/TODO.md: -------------------------------------------------------------------------------- 1 | Add `[[no_unused]]` and `[[maybe_unused]]` from the next lecture? 2 | After `04-functions` add `??-typedef-using.cpp` for type aliases 3 | `vector-bool`: link to https://alenacpp.blogspot.com/2005/06/vector.html , example with `bool&` 4 | -------------------------------------------------------------------------------- /03-220919/progress.md: -------------------------------------------------------------------------------- 1 | ПМИ: полностью (но `11-return-by-value.cpp` неудачно и без escaping у строк) 2 | ПАДИИ-1: без 11-return-by-value.cpp 3 | ПАДИИ-2: кроме 02-strings/11+ и 04-functions 4 | -------------------------------------------------------------------------------- /04-220926/00-old/01-maybe-unused.cpp: -------------------------------------------------------------------------------- 1 | int main() { 2 | /*[[maybe_unused]]*/ int a = 10, b = 20; 3 | a++; 4 | // (b++) = 10; 5 | } 6 | -------------------------------------------------------------------------------- /04-220926/01-struct/10-member-default-initialization.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct ratio { 4 | int num = 0; // C++11: member default initialization 5 | int denom = 1; 6 | }; 7 | 8 | int main() { 9 | ratio r; 10 | std::cout << r.num << "\n"; 11 | std::cout << r.denom << "\n"; 12 | std::cout << ratio{}.num << "\n"; 13 | 14 | ratio r2{3, 4}; 15 | std::cout << r2.num << " " << r2.denom << "\n"; 16 | } 17 | -------------------------------------------------------------------------------- /04-220926/01-struct/13-no-default-ctor.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct ratio { 4 | int num = 0; 5 | int denom = 1; 6 | // no default constructor is autogenerated 7 | ratio(int value) : num(value) {} 8 | }; 9 | 10 | int main() { 11 | ratio r; 12 | } 13 | -------------------------------------------------------------------------------- /04-220926/01-struct/20-public.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct ratio { 4 | // Invariant: denom != 0 5 | int num; 6 | int denom; 7 | 8 | ratio() : num(0), denom(1) {} 9 | ratio(int value) : num(value), denom(1) {} 10 | ratio(int num_, int denom_) : num(num_), denom(denom_) { 11 | assert(denom != 0); 12 | } 13 | double to_double() const { 14 | return num * 1.0 / denom; 15 | } 16 | }; 17 | 18 | int main() { 19 | ratio r; 20 | // API design principle: it should be impossible to 21 | // "break" the class even if you want! 22 | // Violated: 23 | r.denom = 0; 24 | } 25 | -------------------------------------------------------------------------------- /04-220926/01-struct/30-friend.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct Foo { 4 | private: 5 | int field = 10; 6 | 7 | public: 8 | void increment() { 9 | field++; 10 | } 11 | 12 | private: // private, public, does not matter, visible to all 13 | friend bool eq(const Foo &a, const Foo &b) { 14 | return a.field == b.field; 15 | } 16 | }; 17 | 18 | int main() { 19 | Foo f1, f2; 20 | // f1.field = 5; 21 | f1.increment(); 22 | std::cout << eq(f1, f2) << "\n"; // 0 23 | f2.increment(); 24 | std::cout << eq(f1, f2) << "\n"; // 1 25 | } 26 | -------------------------------------------------------------------------------- /04-220926/01-struct/31-struct-class.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct Foo { // public: 4 | int x = 10; 5 | }; 6 | 7 | class Bar { // private: 8 | // public: 9 | int x = 10; 10 | }; 11 | 12 | // Different teams have different conventions. 13 | 14 | int main() { 15 | Foo f; 16 | Bar b; 17 | std::cout << f.x << "\n"; 18 | std::cout << b.x << "\n"; 19 | } 20 | -------------------------------------------------------------------------------- /04-220926/02-conversions/02-explicit-bad.cpp: -------------------------------------------------------------------------------- 1 | struct my_vector { 2 | my_vector() {} 3 | my_vector(int) {} 4 | }; 5 | 6 | void print_vector([[maybe_unused]] const my_vector &vec) { 7 | } 8 | 9 | int main() { 10 | [[maybe_unused]] my_vector v1(10); 11 | [[maybe_unused]] my_vector v2 = 10; // copy initialization, should not work 12 | print_vector(10); // copy initialization, should not work 13 | } 14 | -------------------------------------------------------------------------------- /04-220926/02-conversions/10-conversion-operator.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct ratio { 4 | int num; 5 | int denom; 6 | 7 | operator double() const { 8 | std::cout << "operator double()\n"; 9 | return num * 1.0 / denom; 10 | } 11 | }; 12 | 13 | int main() { 14 | ratio r{3, 4}; 15 | std::cout << r.num << "\n"; 16 | double x = r; // implicit conversion 17 | double x1 = r.operator double(); 18 | double x2 = static_cast(r); // explicit conversion 19 | std::cout << x << "\n"; 20 | std::cout << r << "\n"; // implicit conversion to double 21 | } 22 | -------------------------------------------------------------------------------- /04-220926/02-conversions/11-conversion-explicit.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct ratio { 4 | int num; 5 | int denom; 6 | 7 | explicit operator double() { 8 | std::cout << "operator double()\n"; 9 | return num * 1.0 / denom; 10 | } 11 | }; 12 | 13 | int main() { 14 | ratio r{3, 4}; 15 | std::cout << r.num << "\n"; 16 | // double x0 = r; // compilation error 17 | double x = static_cast(r); 18 | double x2(r); 19 | double x3 = double(r); 20 | std::cout << x << "\n"; 21 | std::cout << static_cast(r) << "\n"; 22 | } 23 | -------------------------------------------------------------------------------- /04-220926/02-conversions/12-mix.cpp: -------------------------------------------------------------------------------- 1 | // Does not compile because of 'reasons' 2 | struct Foo { 3 | operator Bar() { // Compiler does not know about `Bar` yet 4 | return Bar{}; 5 | } 6 | }; 7 | 8 | struct Bar { 9 | Bar() {} 10 | Bar(Foo /*arg*/) {} 11 | }; 12 | 13 | int main() { 14 | Foo f; 15 | Bar b = f; // ambiguous 16 | } 17 | -------------------------------------------------------------------------------- /04-220926/02-conversions/13-mix-fixed.cpp: -------------------------------------------------------------------------------- 1 | // Does not compile because of 'reasons' 2 | struct Bar; 3 | 4 | struct Foo { 5 | operator Bar(); 6 | }; 7 | 8 | struct Bar { 9 | Bar() {} 10 | Bar(Foo /*arg*/) {} 11 | }; 12 | 13 | Foo::operator Bar() { 14 | return Bar{}; 15 | } 16 | 17 | int main() { 18 | Foo f; 19 | Bar b = f; // ambiguous 20 | } 21 | -------------------------------------------------------------------------------- /04-220926/TODO.md: -------------------------------------------------------------------------------- 1 | too short? like 20+45=65 minutes. Maybe restore 01-functions here. 2 | Does 01-struct/11-constructors-bad-style.cpp really need a note on operations order? 3 | 03-operators/01-comparison-bad is too fast of a change. Maybe add few intermediate steps? Even when repeated, still takes about 60-70 minutes. 4 | -------------------------------------------------------------------------------- /04-220926/progress.md: -------------------------------------------------------------------------------- 1 | ПМИ: целиком 2 | ПАДИИ-1: целиком 3 | ПАДИИ-2: до 03-operators/02-comparison-friend (были технические проблемы) 4 | -------------------------------------------------------------------------------- /05-221003/01-declare-define/01-identifiers.cpp: -------------------------------------------------------------------------------- 1 | // https://stackoverflow.com/a/228797/767632 2 | // https://codeforces.com/blog/entry/17747 3 | 4 | // int true = 10; // No keywords 5 | // int 10fff = 20; // Not start with a digit 6 | 7 | int _; // UB 8 | int _z; // UB 9 | int z_; // ok 10 | int x__a = 30; // UB 11 | int _Xx; // UB 12 | 13 | struct foo_t { // '_t', not UB, but reserved by POSIX. 14 | }; 15 | 16 | int main() { 17 | int _, _x; // OK, but no. 18 | int x__b = 30; // UB 19 | int _Xy; // UB 20 | } 21 | -------------------------------------------------------------------------------- /05-221003/01-declare-define/02-declare-define-recursive.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void bar(int n); // declaration, объявление 4 | 5 | void foo(int n) { // definition, определение 6 | std::cout << "foo " << n << "\n"; 7 | bar(n - 1); 8 | } 9 | 10 | void bar(int n) { // definition, определение 11 | std::cout << "bar " << n << "\n"; 12 | if (n == 0) { 13 | return; 14 | } 15 | foo(n - 1); 16 | } 17 | 18 | int main() { 19 | bar(10); 20 | } 21 | -------------------------------------------------------------------------------- /05-221003/01-declare-define/03-inside-classes.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct Foo { 4 | void foo() { 5 | bar(); 6 | } 7 | 8 | void bar() { 9 | foo(); 10 | } 11 | }; 12 | 13 | int main() { 14 | } 15 | -------------------------------------------------------------------------------- /05-221003/01-declare-define/04-incomplete-type.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // https://en.cppreference.com/w/cpp/language/type 5 | struct Bar; // forward declaration 6 | 7 | struct Foo { 8 | // Bar b; // compilation error: incomplete type 9 | std::vector bs; 10 | 11 | void doit() { 12 | bs.push_back(Bar()); 13 | bs.resize(10); 14 | Bar b2; 15 | b2.bar_do(); 16 | } 17 | friend void foo_friend() { 18 | Bar b3; 19 | } 20 | }; 21 | 22 | struct Bar { 23 | Foo f; 24 | }; 25 | 26 | int main() { 27 | } 28 | -------------------------------------------------------------------------------- /05-221003/01-declare-define/06-recursive.cpp: -------------------------------------------------------------------------------- 1 | struct Bar; // incomplete type 2 | 3 | struct Foo { 4 | operator Bar(); 5 | }; 6 | 7 | struct Bar { 8 | Bar() {} 9 | Bar(Foo /*arg*/) {} 10 | }; 11 | 12 | Foo::operator Bar() { 13 | return Bar{}; 14 | } 15 | 16 | int main() { 17 | Foo f; 18 | Bar b = f; // ambiguous 19 | } 20 | -------------------------------------------------------------------------------- /05-221003/01-declare-define/10-vexing-parse-default.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // The most vexing parse 5 | struct Foo { 6 | int x{}; // ok: default initialization, i.e. 0 7 | int y(); // the most vexing parse: function????? 8 | }; 9 | 10 | int main() { 11 | Foo f; 12 | f.x = 10; 13 | f.y = 10; 14 | 15 | std::vector v1{}; 16 | std::vector v2(10); 17 | std::vector v3(); 18 | std::vector v4; 19 | 20 | std::cout << v1.size() << "\n"; 21 | std::cout << v2.size() << "\n"; 22 | std::cout << v3.size() << "\n"; 23 | } 24 | -------------------------------------------------------------------------------- /05-221003/01-declare-define/11-vexing-parse-args.cpp: -------------------------------------------------------------------------------- 1 | struct Bar { 2 | explicit Bar() {} 3 | }; 4 | struct Foo { 5 | explicit Foo(Bar) {} 6 | }; 7 | 8 | struct Botva { 9 | Foo f(Bar()); // oops, function 10 | // TODO 11 | 12 | void foo() { 13 | f = f; 14 | } 15 | }; 16 | 17 | int main() { 18 | Foo f(Bar()); // the most vexing parse: Foo f(Bar (*arg) ()) 19 | // Foo f{Bar()}; 20 | // Foo f(Bar{}); 21 | // Foo f{Bar{}}; 22 | // Foo f((Bar())); // C++03 and before 23 | // Foo f( (Bar()) ); // C++03 and before 24 | f = f; 25 | } 26 | 27 | // Foo f( (int x) ) {} 28 | -------------------------------------------------------------------------------- /05-221003/02-namespaces/05-using-namespace.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int x = 10; 4 | 5 | namespace ns { 6 | int x = 20; 7 | void foo() { 8 | std::cout << "foo()\n"; 9 | } 10 | } 11 | 12 | int main() { 13 | std::cout << x << " " << ::x << " " << ns::x << "\n"; 14 | // foo(); 15 | { 16 | std::cout << x << " " << ::x << " " << ns::x << "\n"; 17 | // foo(); 18 | using namespace ns; 19 | std::cout << /*x << " " <<*/ ::x << " " << ns::x << "\n"; // x is ambiguous 20 | foo(); 21 | } 22 | std::cout << x << " " << ::x << " " << ns::x << "\n"; 23 | // foo(); 24 | } 25 | -------------------------------------------------------------------------------- /05-221003/03-naive-include/README.md: -------------------------------------------------------------------------------- 1 | Надо каждый раз перечитывать все исходные файлы. 2 | -------------------------------------------------------------------------------- /05-221003/03-naive-include/bigint.inc.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct bigint { 4 | private: 5 | std::vector digits; 6 | 7 | public: 8 | bigint() {} 9 | bigint(int x) : digits{x} { 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /05-221003/03-naive-include/main.cpp: -------------------------------------------------------------------------------- 1 | #include "bigint.inc.cpp" 2 | 3 | int main() { 4 | bigint x; 5 | bigint y = 123; 6 | } 7 | -------------------------------------------------------------------------------- /05-221003/04-basic-linking/.gitignore: -------------------------------------------------------------------------------- 1 | !/Makefile 2 | -------------------------------------------------------------------------------- /05-221003/04-basic-linking/01-build.sh: -------------------------------------------------------------------------------- 1 | #/bin/bash 2 | g++ main.cpp print_hello.cpp -o main-01 3 | -------------------------------------------------------------------------------- /05-221003/04-basic-linking/02-build.sh: -------------------------------------------------------------------------------- 1 | #/bin/bash 2 | g++ -c main.cpp -O2 -DDEBUG -std=c++17 3 | g++ -c print_hello.cpp -O2 -DDEBUG -std=c++17 4 | g++ main.o print_hello.o -O2 -std=c++17 -o main-02 5 | -------------------------------------------------------------------------------- /05-221003/04-basic-linking/README.md: -------------------------------------------------------------------------------- 1 | Зачем: 2 | 3 | * Не такие длинные файлы. 4 | * Компиляция параллелится. 5 | * Перекомпиляция ускоряется: меньше файлов перечитывать. 6 | * Можно собрать несколько программ из разных кусочков и переиспользовать результаты компиляции. 7 | * Например, отдельно код, отдельно тесты к коду. 8 | 9 | Дальше можно делать статические библиотеки (набор `.o`, собранный вместе) и динамические. 10 | Статические вкомпилированы в исполянемый файл, динамические подгружаются ОС в процессе выполнения 11 | (и тогда их можно иметь общие между разными программами). 12 | 13 | TODO: gcc vs g++ 14 | -------------------------------------------------------------------------------- /05-221003/04-basic-linking/linking-folder/README.md: -------------------------------------------------------------------------------- 1 | 1. Compile `main.cpp` at `../` and copy `../main.o` to `main.o`. 2 | 2. Compile `print_hello.cpp` at `../` and copy `../print_hello.o` to `print_hello_1.o`. 3 | 3. Change `print_hello.cpp`, recompile it and copy the resulting object file to `print_hello_2.o`. 4 | 4. Link `main.o` with `print_hello_1.o` and run, see result 1. 5 | 5. Link `main.o` with `print_hello_2.o` and run, see result 2. 6 | -------------------------------------------------------------------------------- /05-221003/04-basic-linking/main.cpp: -------------------------------------------------------------------------------- 1 | // Translation unit 1. 2 | 3 | // No : we do not use it in main() at all. 4 | void print_hello_please(); 5 | 6 | int main() { 7 | print_hello_please(); 8 | } 9 | -------------------------------------------------------------------------------- /05-221003/04-basic-linking/print_hello.cpp: -------------------------------------------------------------------------------- 1 | // Translation unit 2. 2 | 3 | #include 4 | 5 | void print_hello_please() { 6 | std::cout << "Hello World-2!\n"; 7 | } 8 | -------------------------------------------------------------------------------- /05-221003/05-return-value-ub/README.md: -------------------------------------------------------------------------------- 1 | API (Application Programming Interface) 2 | void foo(); 3 | foo(); 4 | 5 | Gets converted by the compiler to: 6 | 7 | ABI (Application Binary Interface) 8 | '_Z3foov' --> 9 | (name mangling) 10 | 11 | But return value type is not mangled. 12 | 13 | Different compilers/flags => different ABIs => UB. 14 | ABIs are incompatible and not checked. 15 | E.g.: size of `std::size_t`, `int*`, `int`, fields inside `std::vector`'s implementation... 16 | `long` vs `int` 17 | -------------------------------------------------------------------------------- /05-221003/05-return-value-ub/get.cpp: -------------------------------------------------------------------------------- 1 | float get() { 2 | return 1'234'567'890; 3 | } 4 | -------------------------------------------------------------------------------- /05-221003/05-return-value-ub/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | double get(); // UB: return type differs from get.cpp 4 | 5 | // IFNDR: Ill Formed, No Diagnostic Required 6 | 7 | int main() { 8 | std::cout << get() << "\n"; 9 | } 10 | -------------------------------------------------------------------------------- /05-221003/06-odr/README.md: -------------------------------------------------------------------------------- 1 | ODR (One Definition Rule) 2 | 3 | IFNDR (Ill-Formed, No Diagnostic Required) 4 | -------------------------------------------------------------------------------- /05-221003/06-odr/foo.cpp: -------------------------------------------------------------------------------- 1 | void foo() { 2 | } 3 | -------------------------------------------------------------------------------- /05-221003/06-odr/main.cpp: -------------------------------------------------------------------------------- 1 | void foo(); // Irreleavent. 2 | 3 | void foo() { 4 | } 5 | 6 | int main() { 7 | foo(); 8 | } 9 | -------------------------------------------------------------------------------- /05-221003/07-odr-violation-var/README.md: -------------------------------------------------------------------------------- 1 | https://codeforces.com/blog/entry/95574 2 | 3 | Compile with `-static` 4 | Consequence: please use namespaces! 5 | -------------------------------------------------------------------------------- /05-221003/07-odr-violation-var/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int write; // how to solve: namespaces 4 | 5 | int main() { 6 | std::ios_base::sync_with_stdio(false); 7 | std::cout << 10; 8 | } 9 | -------------------------------------------------------------------------------- /05-221003/08-no-odr-violation/foo.cpp: -------------------------------------------------------------------------------- 1 | void foo(int) { 2 | // foo(); 3 | } 4 | -------------------------------------------------------------------------------- /05-221003/08-no-odr-violation/main.cpp: -------------------------------------------------------------------------------- 1 | // These are two independent overloads. 2 | void foo(int); 3 | void foo() { 4 | } 5 | 6 | int main() { 7 | foo(); 8 | foo(10); 9 | } 10 | -------------------------------------------------------------------------------- /05-221003/10-struct-outside/foo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct Foo { 5 | int a = 10; 6 | std::vector v; 7 | 8 | void method(); 9 | void method_unused(); 10 | }; 11 | 12 | Foo get_foo() { 13 | return Foo{}; 14 | } 15 | 16 | void Foo::method() { 17 | std::cout << "method() called " << a << "\n"; 18 | } 19 | 20 | void Foo::method_unused() { 21 | std::cout << "method_unused() called " << a << "\n"; 22 | } 23 | -------------------------------------------------------------------------------- /05-221003/10-struct-outside/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // Should have definition. Method are supposedly defined outside of the struct. 5 | struct Foo { 6 | int a = 10; // Should be exactly 10, IFNDR otherwise. 7 | std::vector v; 8 | 9 | void method(); 10 | void method_unused(); 11 | }; 12 | 13 | Foo get_foo(); 14 | 15 | int main() { 16 | get_foo().method(); 17 | 18 | Foo f = get_foo(); 19 | f.method(); 20 | 21 | Foo f2; 22 | f2.method(); 23 | } 24 | -------------------------------------------------------------------------------- /05-221003/11-struct-inside/foo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct Foo { 5 | int a = 10; 6 | std::vector v; 7 | 8 | void method() { // Definition inside struct: not ODR-violation, if the same everywhere. 9 | std::cout << "method() called " << a << "\n"; 10 | } 11 | }; 12 | 13 | Foo get_foo() { 14 | return Foo{}; 15 | } 16 | -------------------------------------------------------------------------------- /05-221003/11-struct-inside/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // Should have definition. Method are supposedly defined outside of the struct. 5 | struct Foo { 6 | int a = 10; 7 | std::vector v; 8 | 9 | void method() { 10 | std::cout << "method() called " << a << "\n"; 11 | } 12 | }; 13 | 14 | Foo get_foo(); 15 | 16 | int main() { 17 | get_foo().method(); 18 | 19 | Foo f = get_foo(); 20 | f.method(); 21 | } 22 | -------------------------------------------------------------------------------- /05-221003/12-struct-ub/foo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct Foo { 5 | int a = 10; 6 | std::vector v; 7 | 8 | void method(); 9 | }; 10 | 11 | Foo get_foo() { 12 | return Foo{}; 13 | } 14 | 15 | void Foo::method() { 16 | std::cout << "method() called " << a << "\n"; 17 | } 18 | -------------------------------------------------------------------------------- /05-221003/13-struct-incomplete/TODO.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hse-spb-2022-cpp/lectures/fb4f0527a3e94fb3d4d6562c5443aa55a50ecb39/05-221003/13-struct-incomplete/TODO.md -------------------------------------------------------------------------------- /05-221003/13-struct-incomplete/foo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct Foo { 5 | int a = 10; 6 | std::vector v; 7 | 8 | void method(); 9 | }; 10 | 11 | Foo& get_foo() { 12 | static Foo f; 13 | return f; 14 | } 15 | 16 | void call_method(Foo &f) { 17 | f.method(); 18 | } 19 | 20 | void Foo::method() { 21 | std::cout << "method() called " << a << "\n"; 22 | } 23 | -------------------------------------------------------------------------------- /05-221003/13-struct-incomplete/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct Foo; 4 | 5 | // Incomplete type is enough for references/pointers passing. 6 | // Sometimes even STL containers support incomplete types, check cppreference. 7 | Foo& get_foo(); 8 | void call_method(Foo &f); 9 | 10 | int main() { 11 | call_method(get_foo()); 12 | Foo &f = get_foo(); 13 | // f.method(); // Need complete type: is there even a `method`? 14 | call_method(f); 15 | 16 | // Foo g = get_foo(); // Need complete type: have to allocate a place for `Foo`. 17 | } 18 | -------------------------------------------------------------------------------- /05-221003/20-include/foo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "foo.hpp" 4 | 5 | Foo get_foo() { 6 | return Foo{}; 7 | } 8 | 9 | void Foo::method() { 10 | std::cout << "method() called " << a << "\n"; 11 | } 12 | 13 | void Foo::method_unused() { 14 | std::cout << "method_unused() called " << a << "\n"; 15 | } 16 | -------------------------------------------------------------------------------- /05-221003/20-include/foo.hpp: -------------------------------------------------------------------------------- 1 | struct Foo { 2 | int a = 10; 3 | std::vector v; 4 | 5 | void method(); 6 | void method_unused(); 7 | }; 8 | 9 | Foo get_foo(); 10 | -------------------------------------------------------------------------------- /05-221003/20-include/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "foo.hpp" 4 | 5 | int main() { 6 | get_foo().method(); 7 | 8 | Foo f = get_foo(); 9 | f.method(); 10 | 11 | Foo f2; 12 | f2.method(); 13 | } 14 | -------------------------------------------------------------------------------- /05-221003/21-include-dependencies/foo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "foo.hpp" 3 | 4 | Foo get_foo() { 5 | return Foo{}; 6 | } 7 | 8 | void Foo::method() { 9 | std::cout << "method() called " << a << "\n"; 10 | } 11 | 12 | void Foo::method_unused() { 13 | std::cout << "method_unused() called " << a << "\n"; 14 | } 15 | -------------------------------------------------------------------------------- /05-221003/21-include-dependencies/foo.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct Foo { 4 | int a = 10; 5 | std::vector v; 6 | 7 | void method(); 8 | void method_unused(); 9 | }; 10 | 11 | Foo get_foo(); 12 | -------------------------------------------------------------------------------- /05-221003/21-include-dependencies/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "foo.hpp" 3 | 4 | int main() { 5 | get_foo().method(); 6 | 7 | Foo f = get_foo(); 8 | f.method(); 9 | 10 | Foo f2; 11 | f2.method(); 12 | } 13 | -------------------------------------------------------------------------------- /05-221003/22-include-guards/cli_view.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "field.hpp" 3 | #include "cli_view.hpp" 4 | 5 | namespace cli_view { 6 | void show_field(const field::Field &f) { 7 | std::cout << f.width << "x" << f.height << "\n"; 8 | } 9 | } // namespace cli_view 10 | -------------------------------------------------------------------------------- /05-221003/22-include-guards/cli_view.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CLI_VIEW_H_ 2 | #define CLI_VIEW_H_ 3 | 4 | #include "field.hpp" 5 | 6 | namespace cli_view { 7 | void show_field(const field::Field &f); 8 | } // namespace cli_view 9 | 10 | #endif // CLI_VIEW_H_ 11 | -------------------------------------------------------------------------------- /05-221003/22-include-guards/field.cpp: -------------------------------------------------------------------------------- 1 | #include "field.hpp" 2 | 3 | namespace field { 4 | int Field::area() const { 5 | return width * height; 6 | } 7 | 8 | Field create_field(int width, int height) { 9 | return {width, height}; 10 | } 11 | } // namespace field 12 | -------------------------------------------------------------------------------- /05-221003/22-include-guards/field.hpp: -------------------------------------------------------------------------------- 1 | // Alternative: '#pragma once', not in standard, but all major compilers support it. 2 | #ifndef FIELD_HPP_ // Include guards 3 | #define FIELD_HPP_ 4 | 5 | namespace field { 6 | struct Field { 7 | int width, height; 8 | 9 | int area() const; 10 | }; 11 | 12 | Field create_field(int width, int height); 13 | } // namespace field 14 | 15 | #endif // FIELD_HPP_ 16 | -------------------------------------------------------------------------------- /05-221003/22-include-guards/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | // Order _should not_ matter and includes _should_ be independent! 3 | // That's why `cli_view.h` includes `field.h` 4 | #include "field.hpp" 5 | #include "cli_view.hpp" 6 | 7 | int main() { 8 | field::Field f = field::create_field(3, 4); 9 | cli_view::show_field(f); 10 | } 11 | -------------------------------------------------------------------------------- /05-221003/progress.md: -------------------------------------------------------------------------------- 1 | ПМИ: кроме 02-namespaces/05-using-namespace, 08-no-odr-violation, 1*-struct, 21-include-dependencies, 22-include-guards 2 | ПАДИИ-1: кроме 02-namespaces 3 | ПАДИИ-2: кроме 02-namespaces, 12-struct-ub, 13-struct-incomplete 4 | -------------------------------------------------------------------------------- /06-221010/00-include-bad/get.cpp: -------------------------------------------------------------------------------- 1 | #include "get.hpp" 2 | 3 | float get() { 4 | return 1'234'567'890; 5 | } 6 | -------------------------------------------------------------------------------- /06-221010/00-include-bad/get.hpp: -------------------------------------------------------------------------------- 1 | #ifndef GET_HPP_ 2 | #define GET_HPP_ 3 | 4 | double get(); 5 | 6 | #endif // GET_HPP_ 7 | -------------------------------------------------------------------------------- /06-221010/00-include-bad/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "get.hpp" 3 | 4 | int main() { 5 | std::cout << get() << "\n"; 6 | } 7 | -------------------------------------------------------------------------------- /06-221010/01-include-cycle/bar.hpp: -------------------------------------------------------------------------------- 1 | #ifndef BAR_H_ 2 | #define BAR_H_ 3 | 4 | #include "foo.hpp" 5 | 6 | struct Bar { 7 | Foo f; 8 | }; 9 | 10 | #endif // BAR_H_ 11 | -------------------------------------------------------------------------------- /06-221010/01-include-cycle/foo.cpp: -------------------------------------------------------------------------------- 1 | #include "foo.hpp" 2 | #include "bar.hpp" 3 | 4 | void Foo::doit() { 5 | bs.push_back(Bar()); 6 | bs.resize(10); 7 | Bar b2; 8 | // b2.bar_do(); 9 | } 10 | 11 | void foo_friend() { 12 | Bar b3; 13 | } 14 | -------------------------------------------------------------------------------- /06-221010/01-include-cycle/foo.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FOO_H_ 2 | #define FOO_H_ 3 | 4 | #include 5 | //#include "bar.hpp" 6 | struct Bar; 7 | 8 | struct Foo { 9 | std::vector bs; 10 | 11 | void doit(); 12 | friend void foo_friend(); 13 | }; 14 | 15 | #endif // FOO_H_ 16 | -------------------------------------------------------------------------------- /06-221010/01-include-cycle/main.cpp: -------------------------------------------------------------------------------- 1 | #include "foo.hpp" 2 | #include "bar.hpp" 3 | 4 | int main() { 5 | Foo f; 6 | Bar b; 7 | } 8 | -------------------------------------------------------------------------------- /06-221010/02-forward-include/bar.hpp: -------------------------------------------------------------------------------- 1 | #ifndef BAR_HPP_ 2 | #define BAR_HPP_ 3 | 4 | #include "bar_fwd.hpp" 5 | #include "foo.hpp" 6 | 7 | struct Bar { 8 | Foo f; 9 | }; 10 | 11 | #endif // BAR_HPP_ 12 | -------------------------------------------------------------------------------- /06-221010/02-forward-include/bar_fwd.hpp: -------------------------------------------------------------------------------- 1 | #ifndef BAR_FWD_HPP_ 2 | #define BAR_FWD_HPP_ 3 | 4 | struct Bar; 5 | 6 | #endif // BAR_FWD_HPP_ 7 | -------------------------------------------------------------------------------- /06-221010/02-forward-include/foo.cpp: -------------------------------------------------------------------------------- 1 | #include "foo.hpp" 2 | #include "bar.hpp" 3 | 4 | void Foo::doit() { 5 | bs.push_back(Bar()); 6 | bs.resize(10); 7 | Bar b2; 8 | // b2.bar_do(); 9 | } 10 | 11 | void foo_friend() { 12 | Bar b3; 13 | } 14 | -------------------------------------------------------------------------------- /06-221010/02-forward-include/foo.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FOO_HPP_ 2 | #define FOO_HPP_ 3 | 4 | #include "foo_fwd.hpp" 5 | 6 | #include 7 | // #include "bar.hpp" 8 | #include "bar_fwd.hpp" 9 | 10 | struct Foo { 11 | std::vector bs; 12 | 13 | void doit(); 14 | friend void foo_friend(); 15 | }; 16 | 17 | #endif // FOO_HPP_ 18 | -------------------------------------------------------------------------------- /06-221010/02-forward-include/foo_fwd.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FOO_FWD_HPP_ 2 | #define FOO_FWD_HPP_ 3 | 4 | struct Foo; 5 | 6 | #endif // FOO_FWD_HPP_ 7 | -------------------------------------------------------------------------------- /06-221010/02-forward-include/main.cpp: -------------------------------------------------------------------------------- 1 | #include "foo.hpp" 2 | #include "bar.hpp" 3 | 4 | int main() { 5 | Foo f; 6 | Bar b; 7 | } 8 | -------------------------------------------------------------------------------- /06-221010/02-forward-include/todo.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hse-spb-2022-cpp/lectures/fb4f0527a3e94fb3d4d6562c5443aa55a50ecb39/06-221010/02-forward-include/todo.md -------------------------------------------------------------------------------- /06-221010/03-iosfwd/foo.cpp: -------------------------------------------------------------------------------- 1 | #include "foo.h" 2 | #include 3 | 4 | std::ostream& operator<<(std::ostream &os, const Foo&) { 5 | return os << "hello world"; 6 | } 7 | -------------------------------------------------------------------------------- /06-221010/03-iosfwd/foo.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FOO_H_ 2 | #define FOO_H_ 3 | 4 | #include // smaller than , only forward declarations 5 | 6 | struct Foo {}; 7 | 8 | std::ostream& operator<<(std::ostream&, const Foo&); 9 | 10 | #endif // FOO_H_ 11 | -------------------------------------------------------------------------------- /06-221010/03-iosfwd/foo_check.cpp: -------------------------------------------------------------------------------- 1 | #include "foo_check.hpp" 2 | 3 | void foo_check(const Foo &) { 4 | } 5 | -------------------------------------------------------------------------------- /06-221010/03-iosfwd/foo_check.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FOO_CHECK_HPP_ 2 | #define FOO_CHECK_HPP_ 3 | 4 | #include "foo.hpp" 5 | 6 | void foo_check(const Foo &); 7 | 8 | #endif // FOO_CHECK_HPP_ -------------------------------------------------------------------------------- /06-221010/10-static-initialization-order-fiasco/README.md: -------------------------------------------------------------------------------- 1 | https://isocpp.org/wiki/faq/ctors#static-init-order 2 | https://github.com/Nekrolm/ubbook/blob/master/runtime/static_initialization_order_fiasco.md 3 | -------------------------------------------------------------------------------- /06-221010/10-static-initialization-order-fiasco/bar.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "foo.hpp" 3 | 4 | int b0 = get_foo().x; 5 | 6 | struct Bar { 7 | Bar(int x) { 8 | std::cout << "b0=" << b0 << "\n"; 9 | std::cout << "Bar(" << x << ", foo.x=" << get_foo().x << ")\n"; 10 | } 11 | }; 12 | 13 | Bar b1(10 + b0); 14 | Bar b2(20 + b0); 15 | -------------------------------------------------------------------------------- /06-221010/10-static-initialization-order-fiasco/foo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "foo.hpp" 3 | 4 | Foo::Foo() { 5 | std::cout << "Foo()\n"; 6 | } 7 | 8 | Foo f; 9 | 10 | Foo &get_foo() { 11 | return f; 12 | } 13 | -------------------------------------------------------------------------------- /06-221010/10-static-initialization-order-fiasco/foo.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FOO_HPP_ 2 | #define FOO_HPP_ 3 | 4 | struct Foo { 5 | int x = 10; 6 | Foo(); 7 | }; 8 | 9 | Foo &get_foo(); 10 | 11 | #endif // FOO_HPP_ 12 | -------------------------------------------------------------------------------- /06-221010/10-static-initialization-order-fiasco/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "foo.hpp" 3 | 4 | int main() { 5 | std::cout << "main sees: " << get_foo().x << "\n"; 6 | } 7 | -------------------------------------------------------------------------------- /06-221010/11-static-initialization-order-fiasco-iostream/foo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void print_hello() { 4 | std::ios_base::Init init; 5 | std::cout << "Hello World\n"; 6 | } 7 | -------------------------------------------------------------------------------- /06-221010/11-static-initialization-order-fiasco-iostream/foo.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FOO_HPP_ 2 | #define FOO_HPP_ 3 | 4 | void print_hello(); 5 | 6 | #endif // FOO_HPP_ 7 | -------------------------------------------------------------------------------- /06-221010/11-static-initialization-order-fiasco-iostream/main.cpp: -------------------------------------------------------------------------------- 1 | #include "foo.hpp" 2 | 3 | struct Bar { 4 | Bar() { 5 | print_hello(); 6 | } 7 | }; 8 | 9 | Bar b; 10 | 11 | int main() {} 12 | -------------------------------------------------------------------------------- /06-221010/12-construct-on-first-use/bar.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "foo.hpp" 3 | 4 | int b0 = get_foo().x; 5 | 6 | struct Bar { 7 | Bar(int x) { 8 | std::cout << "b0=" << b0 << "\n"; 9 | std::cout << "Bar(" << x << ", foo.x=" << get_foo().x << ")\n"; 10 | } 11 | }; 12 | 13 | Bar b1(10 + b0); 14 | Bar b2(20 + b0); 15 | -------------------------------------------------------------------------------- /06-221010/12-construct-on-first-use/foo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "foo.hpp" 3 | 4 | Foo::Foo() { 5 | std::cout << "Foo()\n"; 6 | } 7 | 8 | Foo &get_foo() { // construct-on-first-use 9 | static Foo f; // like global variable, but initialized at first execution of this line 10 | return f; 11 | } 12 | -------------------------------------------------------------------------------- /06-221010/12-construct-on-first-use/foo.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FOO_HPP_ 2 | #define FOO_HPP_ 3 | 4 | struct Foo { 5 | int x = 10; 6 | Foo(); 7 | }; 8 | 9 | Foo &get_foo(); 10 | 11 | #endif // FOO_HPP_ 12 | -------------------------------------------------------------------------------- /06-221010/12-construct-on-first-use/main.cpp: -------------------------------------------------------------------------------- 1 | int main() {} 2 | -------------------------------------------------------------------------------- /06-221010/20-unnamed-namespace/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "other.hpp" 3 | 4 | void foo() { 5 | std::cout << "main foo\n"; 6 | } 7 | 8 | int main() { 9 | foo(); 10 | do_other(); 11 | } 12 | -------------------------------------------------------------------------------- /06-221010/20-unnamed-namespace/other.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "other.hpp" 3 | 4 | // "unnamed namespace" 5 | namespace { 6 | // internal linkage 7 | void foo() { 8 | std::cout << "other foo\n"; 9 | } 10 | } // namespace 11 | 12 | // default: external linkage 13 | void do_other() { 14 | foo(); 15 | } 16 | -------------------------------------------------------------------------------- /06-221010/20-unnamed-namespace/other.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OTHER_HPP_ 2 | #define OTHER_HPP_ 3 | 4 | void do_other(); 5 | 6 | #endif // OTHER_HPP_ -------------------------------------------------------------------------------- /06-221010/todo.md: -------------------------------------------------------------------------------- 1 | 13b-211215\04-linkage.cpp 2 | 13b-211215\05-static-deinitialization-order.cpp 3 | swap 11 and 12 4 | -------------------------------------------------------------------------------- /07-221017/01-extra/04-long-long-vs-double.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | long long x = 123'456'789'123'456'789; 5 | std::cout << x << "\n"; 6 | std::cout << std::fixed << static_cast(x) << "\n"; 7 | 8 | double a = 1e100; 9 | double b = 1e100 + 1; 10 | std::cout << (a == b) << "\n"; 11 | std::cout << (a == a + 1) << "\n"; 12 | } 13 | -------------------------------------------------------------------------------- /07-221017/01-extra/11-interleaving.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | bool a = false, b = false; 4 | 5 | int f(bool, int x) { 6 | std::cout << "f(" << a << b << ", " << x << ")\n"; 7 | return true; 8 | } 9 | 10 | int main() { 11 | // GCC: f(10, 1), f(11, 2) 12 | // MSVC: f(11, 2), f(11, 1) 13 | std::cout << f(a = true, 1) + f(b = true, 2) << "\n"; 14 | } 15 | -------------------------------------------------------------------------------- /07-221017/01-extra/12-vector-ub-before-cpp17.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | std::vector vec; 5 | 6 | int foo() { 7 | vec.push_back(20); 8 | return 123; 9 | } 10 | 11 | int main() { 12 | vec.push_back(10); 13 | vec[0] = foo(); // Safe since C++17: = computes rights first, left second. 14 | 15 | std::cout << vec.size() << "\n"; 16 | std::cout << vec[0] << " " << vec[1] << "\n"; 17 | } 18 | -------------------------------------------------------------------------------- /07-221017/03-algorithms/05-lower-bound-map.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | const int N = 1'000'000; 7 | 8 | int main() { 9 | std::set s; 10 | for (int i = 0; i < N; i++) { 11 | s.insert(i); 12 | } 13 | for (int step = 0; step < N; step++) { 14 | // assert(*std::lower_bound(s.begin(), s.end(), 10) == 10); // O(n) for std::set :( 15 | assert(*s.lower_bound(10) == 10); // O(log) 16 | } 17 | std::cout << "OK\n"; 18 | } 19 | -------------------------------------------------------------------------------- /07-221017/03-algorithms/10-remove-if.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | std::vector v{10, 11, 12, 13, 14, 15, 16, 17, 18}; 7 | 8 | auto new_end = std::remove_if(v.begin(), v.end(), [](int x) { 9 | return x % 3 == 0; 10 | }); 11 | std::cout << new_end - v.begin() << "\n"; 12 | 13 | for (int x : v) { 14 | std::cout << " " << x; 15 | } 16 | std::cout << "\n"; 17 | } 18 | -------------------------------------------------------------------------------- /07-221017/03-algorithms/11-erase.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | std::set s{3, 1, 2, 4, 2};//, 100, 101, 102, 103, 104, 105, 106, 107}; 6 | for (int x : s) { 7 | if (x % 2 == 0) { 8 | s.erase(x); 9 | // UB при переходе к следующему элементу 10 | } 11 | } 12 | std::cout << s.size() << "\n"; 13 | } 14 | -------------------------------------------------------------------------------- /08-221107/01-old/01-inner-class.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct Foo { 5 | private: 6 | int x = 0; 7 | 8 | void foo() { 9 | x++; 10 | } 11 | 12 | public: 13 | struct Bar { // has access to all privates of Foo 14 | int y = 0; 15 | void foo() { 16 | // x++; 17 | Foo f; 18 | f.x++; 19 | f.foo(); 20 | y++; 21 | } 22 | }; 23 | 24 | private: 25 | struct Baz {}; 26 | }; 27 | 28 | int main() { 29 | std::map::iterator it; 30 | Foo::Bar b; 31 | b.foo(); 32 | 33 | Foo::Baz z; 34 | } 35 | -------------------------------------------------------------------------------- /08-221107/02-raw-pointers/00-todo.md: -------------------------------------------------------------------------------- 1 | objects are immovable! 2 | values kinda are 3 | -------------------------------------------------------------------------------- /08-221107/02-raw-pointers/02-this-is-a-pointer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct Foo { 4 | int x = 20; 5 | 6 | void foo() { 7 | Foo *f = this; 8 | std::cout << x << "\n"; 9 | std::cout << f->x << "\n"; 10 | std::cout << this->x << "\n"; 11 | std::cout << (*this).x << "\n"; 12 | } 13 | }; 14 | 15 | int main() { 16 | Foo{}.foo(); 17 | 18 | Foo f; 19 | f.foo(); // this == &f 20 | } 21 | -------------------------------------------------------------------------------- /08-221107/03-unique-ptr/06-raw-and-unique.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | struct Foo { 7 | std::vector v; 8 | 9 | Foo() : v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} {} 10 | }; 11 | 12 | Foo *bad() { 13 | std::unique_ptr f = std::make_unique(); 14 | Foo *ptr = f.get(); 15 | assert(ptr->v[3] == 4); 16 | return ptr; 17 | } 18 | 19 | int main() { 20 | Foo *f = bad(); 21 | *f; // UB, because unique_ptr `delete`d the object 22 | std::cout << f->v[3] << "\n"; 23 | } 24 | -------------------------------------------------------------------------------- /08-221107/03-unique-ptr/07-move-containers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | std::string s = "hi"; 6 | std::string s2 = std::move(s); 7 | // `s` is not guaranteed to be empty 8 | std::cout << "|" << s << "| |" << s2 << "|\n"; 9 | } 10 | -------------------------------------------------------------------------------- /08-221107/04-basic-inheritance/TODO.md: -------------------------------------------------------------------------------- 1 | 02-compatible: what for? Mention `std::ostream&` 2 | 03-ctors: out of place if we're rushing towards `vector>` 3 | make all examples the same: Base/Int/String 4 | TODO: virtual dtor, between 08 and 09, see 221128 5 | 6 | -------------------------------------------------------------------------------- /08-221107/TODO.md: -------------------------------------------------------------------------------- 1 | Рассказ получается вывернут наизнанку: цель в итоге в `vector>`, 2 | но наследование возникает только в самом конце и непонятно, что и зачем. 3 | Особенно непонятно, зачем `unique_ptr`, когда есть просто `Foo`. 4 | 5 | -------------------------------------------------------------------------------- /08-221107/progress.md: -------------------------------------------------------------------------------- 1 | ПМИ: до 04-basic-inheritance/06-pure-virtual включительно 2 | ПАДИИ-2: кроме 01-old и 03-unique-ptr/07-move-containers 3 | ПАДИИ-1: кроме 01-old и 03-unique-ptr/07-move-containers, смазались 04-basic-inheritance/07-vector-a и дальше 4 | -------------------------------------------------------------------------------- /09-221114/01-lifetime/04-vector.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | std::vector v{10, 20}; 6 | std::cout << sizeof(v) << "\n"; 7 | 8 | /*struct vector { 9 | int *buffer; 10 | size_t len; 11 | size_t capacity; 12 | };*/ 13 | 14 | std::cout << &v << " " << &v[0] << " " << &v[1] << "\n"; 15 | v.resize(100); 16 | std::cout << &v << " " << &v[0] << " " << &v[1] << "\n"; 17 | } 18 | -------------------------------------------------------------------------------- /09-221114/01-lifetime/05-automatic-dangling.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | std::vector& foo() { 5 | std::vector vec{1, 2, 3}; 6 | return vec; 7 | } 8 | 9 | int main() { 10 | std::vector &vec1 = foo(); // Not UB 11 | std::cout << vec1.size() << "\n"; // UB 12 | 13 | std::vector vec2 = foo(); // UB, because copy constructor 14 | std::cout << vec2.size() << "\n"; // UB 15 | } 16 | -------------------------------------------------------------------------------- /09-221114/01-lifetime/11-static-func-ok.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int counter() { 4 | static int calls = 10; 5 | return ++calls; 6 | } 7 | 8 | int main() { 9 | assert(counter() == 11); 10 | assert(counter() == 12); 11 | assert(counter() == 13); 12 | assert(counter() == 14); 13 | } 14 | -------------------------------------------------------------------------------- /09-221114/02-temporary-lifetime/01-temporary.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct Foo { 4 | int value; 5 | Foo(int value_) : value(value_) { 6 | std::cout << "Foo(" << value << ") " << this << "\n"; 7 | } 8 | ~Foo() { 9 | std::cout << "~Foo(" << value << ") " << this << "\n"; 10 | } 11 | }; 12 | 13 | Foo calc() { 14 | Foo x = Foo(20).value + Foo(30).value; 15 | return x; 16 | } 17 | 18 | int main() { 19 | Foo f(10); 20 | std::cout << "f created\n"; 21 | Foo g = calc().value + Foo(40).value + Foo(50).value; 22 | std::cout << "g created\n"; 23 | } 24 | -------------------------------------------------------------------------------- /09-221114/02-temporary-lifetime/02-dangling.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | std::vector &vec = std::vector{1, 2, 3}; 5 | } 6 | -------------------------------------------------------------------------------- /09-221114/02-temporary-lifetime/03-const-extension.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void println(const std::vector &) { 5 | } 6 | 7 | int main() { 8 | // https://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/ 9 | const std::vector &vec = std::vector{1, 2, 3}; 10 | std::cout << vec.size() << "\n"; 11 | 12 | println(std::vector{1, 2, 3}); 13 | } 14 | -------------------------------------------------------------------------------- /09-221114/02-temporary-lifetime/04-id.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int id_val(int x) { 4 | return x; 5 | } 6 | 7 | const int &id_ref(const int &x) { 8 | return x; 9 | } 10 | 11 | int main() { 12 | // Rvalue lifetime disaster, Arno Schoedl. 13 | { 14 | const int &x = id_val(10); 15 | std::cout << x << "\n"; 16 | } 17 | { 18 | const int &x = id_ref(10); 19 | std::cout << x << "\n"; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /09-221114/02-temporary-lifetime/05-min.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | const auto &val = std::min(3, 4); 6 | std::cout << val << "\n"; 7 | 8 | const auto &[min1, max1] = std::minmax(3, 4); 9 | std::cout << min1 << " " << max1 << "\n"; 10 | 11 | // pair 12 | auto [min2, max2] = std::minmax(3, 4); 13 | std::cout << min2 << " " << max2 << "\n"; 14 | } 15 | -------------------------------------------------------------------------------- /09-221114/progress.md: -------------------------------------------------------------------------------- 1 | ПМИ: всё 2 | ПАДИИ-2: `01-lifetime/0*` (без static/dynamic), `03-derived-cast`, `04-rtti/01`; 3 | на следующей лекции разобрали всё кроме `02-temporary-lifetime` 4 | ПАДИИ-1: всё 5 | -------------------------------------------------------------------------------- /10-221121/01-move-objects/01-swap-vectors.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | std::vector v1(100000), v2; 7 | for (int i = 0; i < 100000; i++) { 8 | using std::swap; 9 | swap(v1, v2); 10 | } 11 | std::cout << v1.size() << "\n"; 12 | } 13 | -------------------------------------------------------------------------------- /10-221121/02-old/01-friend-make-unique-bad.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // https://abseil.io/tips/134 4 | 5 | struct Foo { 6 | static std::unique_ptr make() { 7 | return std::make_unique(); // bad 8 | // return std::unique_ptr(new Foo()); // good 9 | } 10 | 11 | private: 12 | Foo() {} 13 | 14 | // Technically possible, but won't help becase std::make_unique may construct indirectly 15 | // friend std::unique_ptr std::make_unique(); 16 | }; 17 | 18 | int main() { 19 | // auto p1 = std::make_unique(); // hence, this is bad 20 | auto p2 = Foo::make(); // this is good 21 | } 22 | -------------------------------------------------------------------------------- /10-221121/03-external-library/01-boost-header-only.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | std::cout << boost::core::demangle(typeid(std::vector).name()); 7 | } 8 | -------------------------------------------------------------------------------- /10-221121/03-external-library/02-boost-link-filesystem.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace fs = boost::filesystem; 5 | 6 | int main() { 7 | std::cout << "Current directory is: " << fs::current_path() << "\n"; 8 | std::cout << "Content is:\n"; 9 | for (const auto &f : fs::directory_iterator(fs::current_path())) { 10 | std::cout << f.path().filename() << "\n"; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /10-221121/03-external-library/03-sfml.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | sf::RenderWindow window(sf::VideoMode(200, 200), "SFML works!"); 6 | sf::CircleShape shape(100.f); 7 | shape.setFillColor(sf::Color::Green); 8 | 9 | while (window.isOpen()) 10 | { 11 | sf::Event event; 12 | while (window.pollEvent(event)) 13 | { 14 | if (event.type == sf::Event::Closed) 15 | window.close(); 16 | } 17 | 18 | window.clear(); 19 | window.draw(shape); 20 | window.display(); 21 | } 22 | 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /10-221121/03-external-library/05-hello-world-needs-dll.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | int main() { 3 | std::cout << "Hello World\n"; 4 | } 5 | -------------------------------------------------------------------------------- /10-221121/04-cmake/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.22) 2 | 3 | project(lectures-cmake CXX) 4 | 5 | set(CMAKE_CXX_STANDARD 17) 6 | set(CMAKE_CXX_STANDARD_REQUIRED True) 7 | 8 | include_directories(include) # Should be before add_executable 9 | add_executable(main src/main.cpp src/foo.cpp) 10 | -------------------------------------------------------------------------------- /10-221121/04-cmake/include/foo.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FOO_HPP_ 2 | #define FOO_HPP_ 3 | 4 | void foo(); 5 | 6 | #endif // FOO_HPP_ 7 | -------------------------------------------------------------------------------- /10-221121/04-cmake/src/foo.cpp: -------------------------------------------------------------------------------- 1 | #include "foo.hpp" 2 | #include 3 | 4 | void foo() { 5 | std::cout << "Hello World\n"; 6 | } 7 | -------------------------------------------------------------------------------- /10-221121/04-cmake/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "foo.hpp" 2 | 3 | int main() { 4 | foo(); 5 | } 6 | -------------------------------------------------------------------------------- /10-221121/05-cmake-external-library/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.22) 2 | 3 | project(lectures-cmake CXX) 4 | 5 | set(CMAKE_CXX_STANDARD 17) 6 | set(CMAKE_CXX_STANDARD_REQUIRED True) 7 | 8 | find_package(Boost 1.74 REQUIRED filesystem) 9 | include_directories(${Boost_INCLUDE_DIRS}) # -I 10 | link_directories(${Boost_LIBRARY_DIRS}) # -L 11 | 12 | include_directories(include) # Should be before add_executable 13 | add_executable(main src/main.cpp src/foo.cpp) 14 | target_link_libraries(main ${Boost_LIBRARIES}) # -l 15 | -------------------------------------------------------------------------------- /10-221121/05-cmake-external-library/include/foo.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FOO_HPP_ 2 | #define FOO_HPP_ 3 | 4 | void foo(); 5 | 6 | #endif // FOO_HPP_ 7 | -------------------------------------------------------------------------------- /10-221121/05-cmake-external-library/src/foo.cpp: -------------------------------------------------------------------------------- 1 | #include "foo.hpp" 2 | #include 3 | #include 4 | 5 | namespace fs = boost::filesystem; 6 | 7 | void foo() { 8 | std::cout << "Hello World\n"; 9 | std::cout << "Current directory is: " << fs::current_path() << "\n"; 10 | } 11 | -------------------------------------------------------------------------------- /10-221121/05-cmake-external-library/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "foo.hpp" 2 | 3 | int main() { 4 | foo(); 5 | } 6 | -------------------------------------------------------------------------------- /10-221121/06-shared-library/abstract_plugin.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ABSTRACT_PLUGIN_HPP_ 2 | #define ABSTRACT_PLUGIN_HPP_ 3 | 4 | #include 5 | #include 6 | 7 | namespace plugins_demo { 8 | class BOOST_SYMBOL_VISIBLE abstract_plugin { 9 | public: 10 | virtual const std::string &name() const = 0; 11 | virtual float calculate(float x, float y) = 0; 12 | virtual ~abstract_plugin() = default; 13 | }; 14 | } // namespace plugins_demo 15 | 16 | #endif // ABSTRACT_PLUGIN_HPP_ 17 | -------------------------------------------------------------------------------- /10-221121/TODO.md: -------------------------------------------------------------------------------- 1 | This lecture is about 1:10-1:15 2 | 06-shared-library: mention macOS and Linux DLL extensions. Mention Linux non-linking of shared objects. 3 | 4 | -------------------------------------------------------------------------------- /10-221121/progress.md: -------------------------------------------------------------------------------- 1 | ПМИ: всё (кроме `03-external-library\05-hello-world-needs-dll.cpp`, демонстрации `.dll` и CMake+Boost.DLL) 2 | ПАДИИ-2: кроме `01` и `02`, не рассказал про Awesome C++ и CMake+Boost.DLL 3 | ПАДИИ-1: всё 4 | -------------------------------------------------------------------------------- /11-221128/01-old/01-virtual-dtor/README.md: -------------------------------------------------------------------------------- 1 | Typical inheritance for polymorphism: 2 | 3 | 1. There is a single base class with pure virtual functions. 4 | 2. It has a virtual destructor. 5 | 3. Everything is stored via smart pointers. 6 | Otherwise you know the exact type and don't need virtual functions/inheritance: 7 | ``` 8 | Derived d; 9 | d.some_base_method(); // No need for virtual functions, non-virtual call. 10 | ``` 11 | -------------------------------------------------------------------------------- /11-221128/01-old/01-virtual-dtor/TODO.md: -------------------------------------------------------------------------------- 1 | Merge into 08-221107 2 | -------------------------------------------------------------------------------- /11-221128/02-threads/01-basic-thread/01-simple.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | int data = 1234; 7 | std::thread t([&]() { 8 | std::this_thread::sleep_for(std::chrono::milliseconds(500)); 9 | std::cout << "Hello from thread! data=" << data << "\n"; 10 | data += 10; 11 | }); 12 | std::cout << "Waiting for it...\n"; 13 | t.join(); // Подождать поток t, освобождает ресурсы потока. 14 | std::cout << "data is " << data << "\n"; 15 | // Вызывается ~thread(), к этому моменту обязательно сделать join(). 16 | } 17 | -------------------------------------------------------------------------------- /11-221128/02-threads/01-basic-thread/02-args.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void worker(int a, int &b) { 5 | std::cout << "Thread: " << a << " " << &b << "\n"; 6 | } 7 | 8 | int main() { 9 | int a = 10, b = 20; 10 | std::thread(worker, a, std::ref(b)).join(); 11 | } 12 | -------------------------------------------------------------------------------- /11-221128/02-threads/02-race/01-writeln-single.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void writeln(const std::string &s) { 6 | for (std::size_t i = 0; i < s.size(); i++) { 7 | std::cout << s[i]; 8 | } 9 | std::cout << '\n'; 10 | } 11 | 12 | int main() { 13 | for (;;) { 14 | writeln("Hello from the main thread"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /11-221128/02-threads/02-race/02-writeln-race.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void writeln(const std::string &s) { 7 | for (std::size_t i = 0; i < s.size(); i++) { 8 | std::cout << s[i]; 9 | } 10 | std::cout << '\n'; 11 | // std::cout << s << "\n"; 12 | } 13 | 14 | int main() { 15 | std::thread t([]() { 16 | for (;;) { 17 | writeln("Hello from the second thread"); 18 | } 19 | }); 20 | for (;;) { 21 | writeln("Hello from the main thread"); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /11-221128/02-threads/02-race/04-writeln-mutex-bad.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | void writeln(const std::string &s) { 8 | std::mutex m; 9 | m.lock(); 10 | for (std::size_t i = 0; i < s.size(); i++) { 11 | std::cout << s[i]; 12 | } 13 | std::cout << '\n'; 14 | m.unlock(); 15 | } 16 | 17 | int main() { 18 | std::thread t([]() { 19 | for (;;) { 20 | writeln("Hello from the second thread"); 21 | } 22 | }); 23 | for (;;) { 24 | writeln("Hello from the main thread"); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /11-221128/02-threads/02-race/05-writeln-mutex-lock-bad.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | std::mutex m; 8 | void writeln(const std::string &s) { 9 | std::unique_lock{m}; 10 | for (std::size_t i = 0; i < s.size(); i++) { 11 | std::cout << s[i]; 12 | } 13 | std::cout << '\n'; 14 | } 15 | 16 | int main() { 17 | std::thread t([]() { 18 | for (;;) { 19 | writeln("Hello from the second thread"); 20 | } 21 | }); 22 | for (;;) { 23 | writeln("Hello from the main thread"); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /11-221128/02-threads/02-race/06-writeln-mutex-lock-good.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | std::mutex m; 8 | void writeln(const std::string &s) { 9 | std::unique_lock l{m}; 10 | for (std::size_t i = 0; i < s.size(); i++) { 11 | std::cout << s[i]; 12 | } 13 | std::cout << '\n'; 14 | } 15 | 16 | int main() { 17 | std::thread t([]() { 18 | for (;;) { 19 | writeln("Hello from the second thread"); 20 | } 21 | }); 22 | for (;;) { 23 | writeln("Hello from the main thread"); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /11-221128/02-threads/03-data-race/01-counter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #pragma GCC optimize ("O0") 5 | 6 | const int N = 500'000'000; 7 | const int M = 1000; 8 | 9 | int main() { 10 | int data = 0; 11 | auto worker = [&]() { 12 | for (int i = 0; i < N; i++) { 13 | data++; 14 | } 15 | }; 16 | std::thread t(worker); 17 | for (int i = 0; i < M; i++) { 18 | std::cout << "data is " << data << " (in progress)\n"; 19 | } 20 | t.join(); 21 | std::cout << "data is " << data << "\n"; 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /11-221128/02-threads/03-data-race/README.md: -------------------------------------------------------------------------------- 1 | Data race is UB, even with `sleep`. 2 | 3 | Do not use atomic, it's very hard if there is more than one variable (i.e. almost always) 4 | 5 | std::cout is bytewise thread-safe: https://eel.is/c++draft/input.output#iostream.objects.overview-7 6 | -------------------------------------------------------------------------------- /11-221128/02-threads/04-model/.gitignore: -------------------------------------------------------------------------------- 1 | /*.aux 2 | /*.log 3 | /*.pdf 4 | -------------------------------------------------------------------------------- /11-221128/02-threads/04-model/03-volatile-bad.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #pragma GCC optimize("-O2") 6 | 7 | int main() { 8 | volatile int data = 0; 9 | volatile bool finished = false; 10 | 11 | std::thread t([&]() { 12 | std::this_thread::sleep_for(std::chrono::milliseconds(100)); 13 | // Hmm: compiler cannot reorder two writes below. But CPU still can! 14 | data = 123; 15 | finished = true; 16 | }); 17 | 18 | while (!finished) {} 19 | // Hmm? 20 | std::cout << data << "\n"; 21 | 22 | t.join(); 23 | } 24 | -------------------------------------------------------------------------------- /11-221128/02-threads/04-model/README.md: -------------------------------------------------------------------------------- 1 | Появилось только в 1978 году, первые две страницы: https://lamport.azurewebsites.net/pubs/time-clocks.pdf 2 | -------------------------------------------------------------------------------- /11-221128/02-threads/05-producer-consumer/02-queues.md: -------------------------------------------------------------------------------- 1 | There are some. 2 | Not covered today. 3 | Please use your team's/project's framework. 4 | For AMIS: we will cover this first deal in the new term. 5 | 6 | -------------------------------------------------------------------------------- /11-221128/02-threads/TODO.md: -------------------------------------------------------------------------------- 1 | Too long. `04-model` is already around 1:15. 2 | Update READMEs and happens-before, include pictures with `data++` race 3 | -------------------------------------------------------------------------------- /11-221128/02-threads/links.md: -------------------------------------------------------------------------------- 1 | https://abseil.io/docs/cpp/guides/synchronization 2 | -------------------------------------------------------------------------------- /11-221128/02-threads/progress.md: -------------------------------------------------------------------------------- 1 | ПАДИИ-2: кроме `01-basic-thread/04-computation`, `03-data-race/09-two-threads-atomic-very-bad` 2 | ПМИ: кроме `05-producer-consumer` 3 | ПАДИИ-1: кроме `05-producer-consumer` 4 | -------------------------------------------------------------------------------- /11-221128/todo.md: -------------------------------------------------------------------------------- 1 | 02-threads: maybe start from example with faster computation right away? 2 | -------------------------------------------------------------------------------- /12-221205/02-c-str/04-out-of-bounds.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | char a = 'x'; 5 | char *a_str_bad = &a; 6 | char b[2] = "hi"; 7 | 8 | std::cout << a_str_bad << "\n"; // ub: out of bounds 9 | std::cout << b << "\n"; // ub: out of bounds 10 | } -------------------------------------------------------------------------------- /12-221205/02-c-str/10-allocator-bad.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | const char *strcat_alloc(const char *a, const char *b) { // It's not like std::strcat, the latter does not allocate memory at all. 4 | char *res = new char[std::strlen(a) + std::strlen(b) + 1]; 5 | 6 | int res_len = 0; 7 | for (int i = 0; a[i]; i++) 8 | res[res_len++] = a[i]; 9 | for (int i = 0; b[i]; i++) 10 | res[res_len++] = b[i]; 11 | res[res_len] = '\0'; 12 | return res; 13 | } 14 | 15 | int main() { 16 | const char *x = "xyz"; 17 | const char *y = strcat_alloc("xy", "z") + 1; 18 | // ...... 19 | delete[] (y - 1); 20 | } 21 | -------------------------------------------------------------------------------- /12-221205/02-c-str/11-static-buf-read-word.cpp: -------------------------------------------------------------------------------- 1 | #include "optimization.h" 2 | 3 | int main() { 4 | const int MAX_LEN = 10; 5 | char buf[MAX_LEN + 1]; 6 | bool is_password_correct = false; 7 | readWord(buf); // Careful: do not overflow the buffer 8 | // UB otherwise, see https://en.wikipedia.org/wiki/Buffer_overflow 9 | // Solution: do not use 'readWord', use 'fgets' instead of 'gets' 10 | // Also see https://ulearn.me/Course/Hackerdom 11 | } 12 | -------------------------------------------------------------------------------- /12-221205/02-c-str/12-gets-bad.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | const int MAX_LEN = 10; 6 | char buf[MAX_LEN + 1]; 7 | gets(buf); // DANGEROUS 8 | std::cout << "buf=|" << buf << "|\n"; 9 | // Top-1 vulnerability: https://ulearn.me/course/hackerdom/Perepolnenie_steka_3bda1c2c-c2a1-4fb0-9146-fccc47daf93b 10 | } 11 | -------------------------------------------------------------------------------- /12-221205/02-c-str/13-fgets-safe.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | printf("> "); 5 | 6 | char command[10]; 7 | // Мы за безопасный gets! 8 | fgets(command, sizeof command, stdin); // Always null-terminated string, truncated. 9 | 10 | // C++'s std::string never truncates, but may exhaust whole memory. 11 | 12 | printf("command is |%s|\n", command); 13 | } 14 | -------------------------------------------------------------------------------- /12-221205/02-c-str/20-string-dangling.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | const char *s_ptr; 5 | { 6 | // Small string optimization 7 | // std::string s = "hello"; 8 | std::string s = "hello 1234567890654345678986434567898643456789097654"; 9 | 10 | s_ptr = s.c_str(); 11 | // s_ptr = &s[0]; 12 | std::cout << s_ptr << " (1)\n"; 13 | } 14 | std::cout << s_ptr << " (2)\n"; 15 | { 16 | char x[] = "botva1234565436543654654387658746"; 17 | std::cout << x << "\n"; 18 | } 19 | std::cout << s_ptr << " (3)\n"; 20 | } 21 | -------------------------------------------------------------------------------- /12-221205/03-c-library/02-opaque-pointers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | // "opaque" pointer 6 | FILE *f = fopen("02-opaque-pointers.c", "r"); // "constructor", resources are allocated by the library. 7 | 8 | // Never try to access `FILE`'s fields directly. 9 | char buf[20]; 10 | fscanf(f, "%20s", buf); // "method" 11 | printf("buf=|%s|\n", buf); 12 | 13 | fclose(f); // "destructor" 14 | } 15 | -------------------------------------------------------------------------------- /12-221205/03-c-library/03-void-star.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // "Library" 4 | void *user_data; 5 | 6 | //todo: like setopt 7 | void set_data(void *data) { 8 | user_data = data; 9 | } 10 | 11 | void *get_data() { 12 | return user_data; 13 | } 14 | 15 | // Somewhat like std::any 16 | 17 | // Application 18 | int main() { 19 | int data[]{1, 2, 3, 4}; 20 | 21 | set_data(data); // implicit: int[4] --> int* --> void* 22 | int *data_ptr = static_cast(get_data()); 23 | assert(data_ptr[2] == 3); 24 | } 25 | -------------------------------------------------------------------------------- /12-221205/03-c-library/04-const-cast.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int len(char *s) { 5 | int l = 0; 6 | while (s[l] != '\0') { 7 | l++; 8 | } 9 | return l; 10 | } 11 | 12 | void update(char *s) { 13 | s[0] = 'h'; 14 | } 15 | 16 | int main() { 17 | const char *s = "hello"; 18 | // assert(len(s) == 5); // compilation error 19 | assert(len(const_cast(s)) == 5); // ok 20 | 21 | update(const_cast(s)); // ub 22 | } 23 | -------------------------------------------------------------------------------- /12-221205/todo.md: -------------------------------------------------------------------------------- 1 | 03-c-str: get rid of duplicated examples (esp. duplicated with the first reading of c-str) 2 | 04-c-resource-management: Add example of sqlite-like interface (does not return pointer, instead returns an error code) 3 | 4 | Do not use json-c, as it is complicated stuff which includes `shared_ptr` semantics? Something `unique_ptr`-like with `clone` is better. 5 | Maybe libcurl? Or some hashing? Both provide examples of creating an 'instance of a library' and very low-level stuff, which may be counterintuitive. 6 | 01-c-arrays: what pointers are comparable with == or >= (different) 7 | -------------------------------------------------------------------------------- /13-221212/01-functions/02-overload-null.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct node {}; 5 | 6 | void foo(int) { 7 | std::cout << "foo(int)\n"; 8 | } 9 | 10 | void foo(node*) { 11 | std::cout << "foo(node*)\n"; 12 | } 13 | 14 | int main() { 15 | [[maybe_unused]] node *x = 0; 16 | foo(0); 17 | foo(NULL); 18 | foo(nullptr); // C++11 19 | } 20 | -------------------------------------------------------------------------------- /13-221212/01-functions/04-unnamed-arg.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // [[]] is an 'attribute', since C++17 4 | void foo([[maybe_unused]] int x) { 5 | std::cout << "foo(int)\n"; 6 | } 7 | 8 | void foo(int x, int) { 9 | std::cout << "foo(int x, int) x=" << x << "\n"; 10 | } 11 | 12 | void foo(int x, int, int z) { 13 | std::cout << "foo(int x, int, int z) x=" << x << ", z=" << z << "\n"; 14 | } 15 | 16 | int main() { 17 | foo(10); 18 | foo(10, 20); 19 | foo(10, 20, 30); 20 | } 21 | -------------------------------------------------------------------------------- /13-221212/01-functions/06-default.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // K _last_ parameters can be defaulted. 5 | void foo(int x, int y = 10, int z = 20) { 6 | std::cout << "x = " << x << "\n"; 7 | std::cout << "y = " << y << "\n"; 8 | std::cout << "z = " << z << "\n"; 9 | } 10 | 11 | void bar(std::vector vec = {1, 2, 3}) { 12 | vec.push_back(100); 13 | std::cout << "vec.size() = " << vec.size() << "\n"; 14 | } 15 | 16 | int main() { 17 | foo(1); 18 | foo(2, 3); 19 | // foo(2, z=3); // Python-only, not C++ 20 | foo(4, 5, 6); 21 | 22 | bar(); 23 | bar(); 24 | bar(); 25 | } 26 | -------------------------------------------------------------------------------- /13-221212/01-functions/07-default-overload.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void foo(int, int = 10) { 4 | std::cout << "1\n"; 5 | } 6 | 7 | void foo(double) { 8 | std::cout << "2\n"; 9 | } 10 | 11 | int main() { 12 | foo(10, 20); 13 | foo(30); 14 | foo(30.0); 15 | } 16 | -------------------------------------------------------------------------------- /13-221212/02-function-objects/02-compare-capture.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | struct CloserTo { 7 | int center; 8 | 9 | bool operator()(int a, int b) const { 10 | return std::abs(a - center) < std::abs(b - center); 11 | } 12 | }; 13 | 14 | int main() { 15 | std::vector v{1, 2, 3, 4, 5, 6, 7, 8}; 16 | sort(v.begin(), v.end(), CloserTo{3}); 17 | for (int x : v) { 18 | std::cout << x << "\n"; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /13-221212/02-function-objects/03-set.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | struct Greater { 7 | bool operator()(int a, int b) const { 8 | return a > b; 9 | } 10 | }; 11 | 12 | int main() { 13 | std::set v{1, 2, 3, 4, 5, 6, 7, 8}; // Creates Greater() with default ctor. 14 | for (int x : v) { 15 | std::cout << x << "\n"; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /13-221212/02-function-objects/05-set-fptr.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | bool compare_gt(int a, int b) { 7 | return a > b; 8 | } 9 | 10 | int main() { 11 | std::set v({1, 2, 3, 4, 5, 6, 7, 8}, compare_gt /* &compare_gt */); 12 | for (int x : v) { 13 | std::cout << x << "\n"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /13-221212/03-lambdas/02-distinct-types.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | auto l1 = [](int a, int b) { return a > b; }; 5 | auto l2 = [](int a, int b) { return a > b; }; 6 | std::set s1(l1); 7 | // std::set s2(l2); 8 | } 9 | -------------------------------------------------------------------------------- /13-221212/04-typedef-using.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | typedef std::vector vi; 7 | using pii = std::pair; 8 | // Please do not #define: it does not respect namespaces/private/public 9 | // https://stackoverflow.com/a/1666375/767632 10 | 11 | int main() { 12 | vi v1(10); 13 | std::vector &v2 = v1; 14 | std::cout << typeid(v1).name() << "\n"; 15 | std::cout << typeid(v2).name() << "\n"; 16 | 17 | pii p1(10, 20); 18 | [[maybe_unused]] std::pair &p2 = p1; 19 | } 20 | -------------------------------------------------------------------------------- /13-221212/05-inheritance-extra/11-pure-virtual-ctors.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct Base { 4 | int value = 123; 5 | 6 | virtual void printTo() = 0; 7 | 8 | Base() { 9 | printTo(); 10 | } 11 | }; 12 | 13 | /*void Base::printTo() { // BUT WHY 14 | std::cout << "Not so pure, eh?\n"; 15 | }*/ 16 | 17 | struct Derived : Base { 18 | void printTo() override { 19 | } 20 | }; 21 | 22 | int main() { 23 | // Base b; // class is still abstract. 24 | Derived d; 25 | } 26 | -------------------------------------------------------------------------------- /13-221212/next.md: -------------------------------------------------------------------------------- 1 | 07-201105 2 | friend struct -------------------------------------------------------------------------------- /13-221212/progress.md: -------------------------------------------------------------------------------- 1 | ПМИ: без `05-inheritance-extra/2*`, из `10-patterns` только `01-circle-ellipse` 2 | ПАДИИ-1: то же самое 3 | ПАДИИ-2: то же самое 4 | -------------------------------------------------------------------------------- /13x-221218/03-copying/a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct B { 5 | std::vector vec{10, 20, 30}; 6 | }; 7 | 8 | struct A { 9 | std::vector bs = std::vector(5); 10 | }; 11 | 12 | int main() { 13 | A x; 14 | A y = x; 15 | std::cout << x.bs[0].vec[1] << "\n"; 16 | std::cout << y.bs[0].vec[1] << "\n"; 17 | x.bs[0].vec[1]++; 18 | std::cout << x.bs[0].vec[1] << "\n"; 19 | std::cout << y.bs[0].vec[1] << "\n"; 20 | } 21 | -------------------------------------------------------------------------------- /13x-221218/03-copying/b.py: -------------------------------------------------------------------------------- 1 | class B: 2 | def __init__(self): 3 | self.vec = [10, 20, 30] 4 | 5 | class A: 6 | def __init__(self): 7 | self.bs = [B(), B(), B(), B(), B()] 8 | 9 | x = A() 10 | y = x 11 | print(x.bs[0].vec[1]) 12 | print(y.bs[0].vec[1]) 13 | x.bs[0].vec[1] += 1 14 | print(x.bs[0].vec[1]) 15 | print(y.bs[0].vec[1]) 16 | -------------------------------------------------------------------------------- /13x-221218/04-const-ref-mutated/a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int a = 10; 4 | 5 | void foo(const int &x) { 6 | std::cout << x << "\n"; 7 | a++; 8 | std::cout << x << "\n"; 9 | } 10 | 11 | int main() { 12 | foo(a); 13 | } 14 | -------------------------------------------------------------------------------- /13x-221218/05-const-qualifier/a.cpp: -------------------------------------------------------------------------------- 1 | struct Foo { 2 | int x = 10; 3 | 4 | // void foo(const Foo *this, int &y, int z) { 5 | void foo(int &y, int z) const { 6 | // x++; // prohibited by const qualifier 7 | y++; 8 | z++; 9 | } 10 | }; 11 | 12 | int main() { 13 | Foo f; 14 | int y = 40, z = 50; 15 | f.foo(y, z); 16 | std::cout << y << " " << z << "\n"; 17 | } 18 | -------------------------------------------------------------------------------- /13x-221218/06-cast-copies/a.cpp: -------------------------------------------------------------------------------- 1 | int main() { 2 | double x = 1.5; 3 | int y = static_cast(x); 4 | int &z = static_cast(x); // CE 5 | } 6 | -------------------------------------------------------------------------------- /13x-221218/07-eof-bad/a.txt: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | 3 4 | -------------------------------------------------------------------------------- /13x-221218/07-eof-bad/bad.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | while (!std::cin.eof()) { 5 | int x; 6 | std::cin >> x; 7 | std::cout << x << "\n"; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /13x-221218/07-eof-bad/link.txt: -------------------------------------------------------------------------------- 1 | https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-i-e-while-stream-eof-cons 2 | https://notes.algoprog.ru/ru/cpp/syntax.html#id12 3 | -------------------------------------------------------------------------------- /13x-221218/08-order-of-fields/a.cpp: -------------------------------------------------------------------------------- 1 | struct Base { 2 | int x; 3 | int y; 4 | 5 | Base() : y(10), x(y) {} // UB, -Wreorder 6 | }; 7 | -------------------------------------------------------------------------------- /13x-221218/09-complex-comparison/a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | std::string x = "a", y = "a", z = "z"; 6 | if (x == y == z) { 7 | std::cout << "wtf\n"; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /13x-221218/09-complex-comparison/a.py: -------------------------------------------------------------------------------- 1 | x = "a" 2 | y = "a" 3 | z = "a" 4 | print(x == y == z) 5 | print(x == y and y == z) 6 | print(x < y > z) 7 | -------------------------------------------------------------------------------- /13x-221218/10-friend/a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct Foo { 4 | private: 5 | int x = 10; 6 | 7 | friend void print(const Foo &f) { 8 | std::cout << f.x << "\n"; 9 | } 10 | }; 11 | // void print(const Foo &f); 12 | 13 | int main() { 14 | Foo f; 15 | print(f); 16 | } 17 | -------------------------------------------------------------------------------- /13x-221218/10-friend/b.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct Foo { 4 | private: 5 | int x = 10; 6 | 7 | friend void print(const Foo &f); 8 | }; 9 | 10 | void print(const Foo &f) { 11 | std::cout << f.x << "\n"; 12 | } 13 | 14 | int main() { 15 | Foo f; 16 | print(f); 17 | } 18 | -------------------------------------------------------------------------------- /13x-221218/10-friend/c.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct Foo; 4 | 5 | namespace printers { 6 | void print(const Foo &f); 7 | } 8 | 9 | struct Foo { 10 | private: 11 | int x = 10; 12 | 13 | friend void printers::print(const Foo &f); 14 | }; 15 | 16 | namespace printers { 17 | void print(const Foo &f) { 18 | std::cout << f.x << "\n"; 19 | } 20 | } 21 | 22 | int main() { 23 | Foo f; 24 | printers::print(f); 25 | } 26 | -------------------------------------------------------------------------------- /13y-221225/01-copy-direct-init/01-copy-initialization.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct Foo { 4 | Foo(int x) {} 5 | explicit Foo(std::string s) {} 6 | }; 7 | 8 | void do_something(Foo g) { 9 | } 10 | 11 | Foo create_something() { 12 | Foo h(5); 13 | return h; // copy initialization 3/3 14 | } 15 | 16 | int main() { 17 | Foo f(10); 18 | Foo g = f; // copy initialization 1/3 19 | do_something(g); // copy initialization 2/3 20 | } 21 | -------------------------------------------------------------------------------- /13y-221225/01-copy-direct-init/02-direct-initialization.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct Foo { 4 | Foo(int x) {} 5 | explicit Foo(std::string s) {} 6 | }; 7 | 8 | int main() { 9 | Foo f(10); // direct initialization 10 | f = Foo(10); // direct initialization + operator= 11 | f = Foo{10}; // direct initialization + operator= 12 | f = Foo{"hello"}; // direct initialization + operator= 13 | Foo g("hello"); // direct initialization 14 | } 15 | -------------------------------------------------------------------------------- /13y-221225/01-copy-direct-init/03-conversions.cpp: -------------------------------------------------------------------------------- 1 | int main() { 2 | Foo f; 3 | f = 5; 4 | } 5 | -------------------------------------------------------------------------------- /13y-221225/02-static/question.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | std::vector v; 4 | 5 | int main() { 6 | // v = std::vector(); // ? 7 | std::cout << v.size() << "\n"; 8 | } 9 | -------------------------------------------------------------------------------- /13y-221225/03-auto-return-deduction/01.cpp: -------------------------------------------------------------------------------- 1 | auto ce() { 2 | return 1; 3 | return 2LL; 4 | } 5 | 6 | auto ok() -> long long { 7 | // long long ok() { 8 | return 1; 9 | return 2LL; 10 | } 11 | 12 | int main() { 13 | } 14 | -------------------------------------------------------------------------------- /13y-221225/03-auto-return-deduction/02.cpp: -------------------------------------------------------------------------------- 1 | auto foo(); 2 | 3 | auto bar() { 4 | return foo(); 5 | } 6 | 7 | auto foo() { 8 | return bar(); 9 | } 10 | 11 | int main() {} 12 | -------------------------------------------------------------------------------- /13y-221225/03-auto-return-deduction/03.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | auto foo(bool x) { 5 | return x ? 0.0f : 0LL; // meh :( 6 | } 7 | 8 | int main() { 9 | std::cout << boost::core::demangle(typeid(foo(false)).name()) << "\n"; 10 | } 11 | -------------------------------------------------------------------------------- /13y-221225/03-auto-return-deduction/README.md: -------------------------------------------------------------------------------- 1 | Not for exam! 2 | -------------------------------------------------------------------------------- /13y-221225/04-return-braces/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | std::vector foo() { 4 | return {1, 2, 3}; // implicit 5 | // return 1; // implicit 6 | return std::vector{1, 2, 3}; // explicit 7 | return std::vector(10); // explicit 8 | return static_cast>(10); // explicit 9 | } 10 | 11 | int main() { 12 | } 13 | -------------------------------------------------------------------------------- /13y-221225/05.md: -------------------------------------------------------------------------------- 1 | https://bugs.llvm.org/show_bug.cgi?id=49599 and https://news.ycombinator.com/item?id=26498233 2 | -------------------------------------------------------------------------------- /14-220123/02-templates/01-old.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define DECLARE_OPTION(T) \ 4 | struct Optional ## T { \ 5 | private: \ 6 | T value; \ 7 | bool exists; \ 8 | public: \ 9 | }; 10 | 11 | DECLARE_OPTION(int) 12 | DECLARE_OPTION(std::string) 13 | 14 | struct OptionalString { 15 | private: 16 | std::string value; 17 | bool exists; 18 | public: 19 | 20 | }; 21 | 22 | int main() { 23 | } 24 | -------------------------------------------------------------------------------- /14-220123/02-templates/10-function-template.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // function template 5 | template 6 | void swap(T &a, T &b) { 7 | T tmp = std::move(a); 8 | a = std::move(b); 9 | b = std::move(tmp); 10 | } 11 | 12 | int main() { 13 | int x = 1, y = 2; 14 | swap(x, y); 15 | 16 | [[maybe_unused]] short z = 3; 17 | swap(x, z); // compilation error: cannot bind int& to short 18 | } 19 | -------------------------------------------------------------------------------- /14-220123/03-functors/02-calling-stateful.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | template 5 | void apply(F operation) { 6 | std::cout << "Calling with 10\n"; 7 | operation(10); 8 | } 9 | 10 | struct Print { 11 | int printed = 0; 12 | 13 | void operator()(int x) { 14 | std::cout << x << "\n"; 15 | printed++; 16 | } 17 | }; 18 | 19 | int main() { 20 | Print p; 21 | std::cout << "printed=" << p.printed << "\n"; 22 | apply(p); 23 | // apply(std::ref(p)); 24 | std::cout << "printed=" << p.printed << "\n"; 25 | } 26 | -------------------------------------------------------------------------------- /14-220123/03-functors/03-storing.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | struct Caller { 5 | F operation; 6 | T value; 7 | 8 | void operator()() { 9 | operation(value); 10 | } 11 | }; 12 | 13 | struct Printer { 14 | void operator()(int a) const { 15 | std::cout << a << "\n"; 16 | } 17 | }; 18 | 19 | int main() { 20 | Caller c{Printer{}, 10}; 21 | c(); 22 | c(); 23 | } 24 | -------------------------------------------------------------------------------- /14-220123/04-misc/01-operator-deref.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct int_wrapper { 4 | int data = 10; 5 | int &operator*() { 6 | return data; 7 | } 8 | }; 9 | 10 | int main() { 11 | int_wrapper x; 12 | std::cout << *x << "\n"; 13 | ++*x; 14 | std::cout << *x << "\n"; 15 | } 16 | -------------------------------------------------------------------------------- /14-220123/04-misc/02-operator-arrow.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct point { 4 | int x = 0, y = 0; 5 | }; 6 | 7 | struct point_wrapper { 8 | point p; 9 | point &operator*() { 10 | return p; 11 | } 12 | 13 | point *operator->() { 14 | return &p; 15 | } 16 | }; 17 | 18 | int main() { 19 | point_wrapper p; 20 | std::cout << (*p).x << "\n"; 21 | std::cout << (*p).y << "\n"; 22 | std::cout << p->x << "\n"; // (p.operator->())->x 23 | } 24 | -------------------------------------------------------------------------------- /15-230130/00-questions/01-incomplete-type.cpp: -------------------------------------------------------------------------------- 1 | See `05-221003\01-declare-define\04-incomplete-type.cpp ` 2 | 3 | struct Bar; 4 | std::unique_ptr x; // should work, but not necessarily destruct 5 | -------------------------------------------------------------------------------- /15-230130/01-preprocessor-basic/01-preprocessor-not-related-to-cpp.txt: -------------------------------------------------------------------------------- 1 | Run `g++ -xc++ -E 01-preprocessor-not-related-to-cpp.txt` 2 | 3 | This file is not a valid C++ code. However, the preprocessor still works: 4 | Phases 1-6: https://en.cppreference.com/w/cpp/language/translation_phases 5 | 6 | #include "included-text.txt" 7 | #include "included-text.txt" 8 | -------------------------------------------------------------------------------- /15-230130/01-preprocessor-basic/02-trigraphs-newlines.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | int main() { 4 | std::vector v(10); 5 | v??(0??) = 10; // v[0] = 10; 6 | std::cout << v[0] << "\n"; 7 | 8 | // You can ignore newline characters anywhere (including in a comment, phase 2) by \ 9 | This line is a comment as well! \ 10 | And this too! 11 | 12 | std::cout << "1\n"; 13 | // Does the following line compiles??/ 14 | std::cout << "2\n"; 15 | std::cout << "3\n"; 16 | } 17 | -------------------------------------------------------------------------------- /15-230130/01-preprocessor-basic/03-literals-int-str-concat.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | [[maybe_unused]] int x = 0x12; 6 | 7 | int y = 1\ 8 | 234; 9 | std::cout << y << "\n"; 10 | 11 | std::string s1 = "hello" "wor\ 12 | ld"; 13 | [[maybe_unused]] std::string s2 = "he\n\t\xFF" R"foo(Hello World)foo"; 14 | std::cout << s1 << "\n"; 15 | } 16 | -------------------------------------------------------------------------------- /15-230130/01-preprocessor-basic/11-ifdef-compiler.cpp: -------------------------------------------------------------------------------- 1 | // See `common/checkver/checkver.cpp` 2 | -------------------------------------------------------------------------------- /15-230130/01-preprocessor-basic/12-ignore-warning.cpp: -------------------------------------------------------------------------------- 1 | int main() { 2 | #ifdef __GNUC__ // Everything is very compiler-specific, see doctest.h for an example 3 | // `#pragma` is a compiler command, not preprocessor 4 | #pragma GCC diagnostic push // save current warnings state to a stack 5 | #pragma GCC diagnostic ignored "-Wunused-variable" 6 | #endif 7 | /* [[maybe_unused]] */ int x = 10; 8 | #ifdef __GNUC__ 9 | #pragma GCC diagnostic pop // restore warnings state 10 | #endif 11 | } 12 | -------------------------------------------------------------------------------- /15-230130/01-preprocessor-basic/20-macros-expanded-naively.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define THREE 1 + 2 4 | #define ZERO 1 - 1 5 | 6 | int main() { 7 | std::cout << THREE * 3 << "\n"; 8 | // However, `#if` computes integers 9 | #if THREE == 3 10 | std::cout << "Three indeed\n"; 11 | #else 12 | std::cout << "Not three\n"; 13 | #endif 14 | 15 | #if ZERO 16 | std::cout << "Zero is the truth\n"; 17 | #else 18 | std::cout << "Zero is the lie\n"; 19 | #endif 20 | } 21 | -------------------------------------------------------------------------------- /15-230130/01-preprocessor-basic/21-macro-ub.cpp: -------------------------------------------------------------------------------- 1 | // #define private public // UB 2 | // #include 3 | 4 | // #define true false // UB 5 | 6 | // #define int long long // UB 7 | 8 | // Define of any keyword is UB 9 | 10 | // https://github.com/menahishayan/rickroll.h // Probably not UB, but macros are weird. Condolenses to IDEs. 11 | 12 | #define __FOO__ // UB, double underscore 13 | #define _Abotva // UB, starts with underscore 14 | -------------------------------------------------------------------------------- /15-230130/01-preprocessor-basic/included-text.txt: -------------------------------------------------------------------------------- 1 | This is an included file! 2 | With multiple lines! 3 | -------------------------------------------------------------------------------- /15-230130/02-macro-functions/01-macro-func-bad.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define max(a, b) a < b ? a : b 4 | #define mul(a, b) a * b 5 | 6 | int foo() { 7 | std::cout << "foo() evaluated\n"; 8 | return 10; 9 | } 10 | 11 | int main() { 12 | std::cout << max(2, 1) << "\n"; // No brackets => ((std::cout << 2) < 1) ? 2 : 1 << "\n"; 13 | std::cout << mul(2 + 1, 2) << "\n"; // No brackets => 2 + 1 * 2 14 | 15 | int x = 10; 16 | std::cout << max(x++, 12) << "\n"; // Macro => double change of 'x' => UB. 17 | std::cout << max(foo(), 12) << "\n"; // Macro => double evaluation of foo(). 18 | } 19 | -------------------------------------------------------------------------------- /15-230130/02-macro-functions/02-macro-func-good.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define max(a, b) ((a) < (b) ? (a) : (b)) 4 | #define mul(a, b) ((a) * (b)) 5 | 6 | int foo() { 7 | std::cout << "foo() evaluated\n"; 8 | return 10; 9 | } 10 | 11 | int main() { 12 | std::cout << max(2, 1) << "\n"; // No brackets => ((std::cout << 2) < 1) ? 2 : 1 << "\n"; 13 | std::cout << mul(2 + 1, 2) << "\n"; // No brackets => 2 + 1 * 2 14 | 15 | int x = 10; 16 | std::cout << max(x++, 12) << "\n"; // Macro => double change of 'x' => UB. 17 | std::cout << max(foo(), 12) << "\n"; // Macro => double evaluation of foo(). 18 | } 19 | -------------------------------------------------------------------------------- /15-230130/02-macro-functions/03-function-like-statement-bad.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define print_twice(x) std::cout << x; std::cout << x; 4 | 5 | int main() { 6 | print_twice(500); 7 | if (2 * 2 == 5) 8 | print_twice(123); 9 | } 10 | -------------------------------------------------------------------------------- /15-230130/02-macro-functions/04-function-like-statement-bad.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define print_twice(x) { std::cout << x; std::cout << x; } 4 | 5 | int main() { 6 | if (2 * 2 == 4) 7 | print_twice(55); 8 | else 9 | print_twice(123); 10 | } 11 | -------------------------------------------------------------------------------- /15-230130/02-macro-functions/05-function-like-statement-good.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // https://stackoverflow.com/questions/923822/whats-the-use-of-do-while0-when-we-define-a-macro 4 | #define print_twice(x) do { std::cout << x; std::cout << x; } while (0) 5 | 6 | int main() { 7 | if (2 * 2 == 5) 8 | print_twice(55); 9 | else 10 | print_twice(123); 11 | 12 | // Cannot be fixed. 13 | print_twice(10), print_twice(20); 14 | } 15 | -------------------------------------------------------------------------------- /15-230130/02-macro-functions/10-assert.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void my_assert_1(bool expr) { 5 | if (!expr) { 6 | std::cout << "Assertion failed: ???????\n"; 7 | }; 8 | } 9 | 10 | #define my_assert_2(expr) \ 11 | do { \ 12 | if (!(expr)) { \ 13 | std::cout << "Assertion failed: " #expr " at " __FILE__ ":" << __LINE__ << "\n"; \ 14 | } \ 15 | } while(0) 16 | 17 | int main() { 18 | my_assert_1(2 * 2 == 5); 19 | my_assert_2(2 * 2 == 5); 20 | assert(2 * 2 == 5); 21 | } 22 | -------------------------------------------------------------------------------- /15-230130/02-macro-functions/11-concat-tokens.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define FOO(a, b) st##a##b 4 | #define NEW_VAR(id) int x##id 5 | 6 | int main() { 7 | FOO(d::c, out) << "Hello World\n"; 8 | NEW_VAR(123) = 10; 9 | std::cout << x123 << "\n"; 10 | } 11 | -------------------------------------------------------------------------------- /15-230130/03-extra-macro/01-variadic-macro.cpp: -------------------------------------------------------------------------------- 1 | // Compile with `g++ -E` to see preprocessed output. 2 | 3 | // variadic macro 4 | #define foo(a, b, ...) bar(b, a, __VA_ARGS__) 5 | 6 | int main() { 7 | foo(1, 2, 3, 4); 8 | foo(1, 2, 3); 9 | 10 | // Oopses: 11 | foo({1, 2, 3, 4}); 12 | foo(({1, 2, 3, 4}), 5, 6); 13 | foo(1, 2); // Can be fixed with C++20's __VA_OPT__ or GCC's extension of ##. 14 | foo(std::map(), std::map()); 15 | foo((std::map()), (std::map())); 16 | 17 | // TODO: Compilation error 18 | foo((std::map())); 19 | } 20 | -------------------------------------------------------------------------------- /15-230130/03-extra-macro/02-no-recursion.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define FOO(x) if (x > 0) { std::cout << x; FOO(x - 1) } 4 | 5 | // Extra reading: Boost::PP (preprocessor). 6 | 7 | int main() { 8 | FOO(5); 9 | } 10 | -------------------------------------------------------------------------------- /15-230130/03-extra-macro/03-macro-high-order-enum.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | enum E { Option1, Option2, Option3 }; 4 | #define LIST_E(f) f(Option1) f(Option2) f(Option3) 5 | 6 | int main() { 7 | E e = Option2; 8 | switch (e) { 9 | case Option1: std::cout << "Option1\n"; break; 10 | case Option2: std::cout << "Option2\n"; break; 11 | case Option3: std::cout << "Option3\n"; break; 12 | } 13 | 14 | switch (e) { 15 | #define PRINT_OPTION(e) case e: std::cout << #e "\n"; break; 16 | LIST_E(PRINT_OPTION) 17 | #undef PRINT_OPTION // undefine, remove macro 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /15-230130/03-extra-macro/04-code-block.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef DEBUG 4 | #define debug_only 5 | #else 6 | #define debug_only if (false) 7 | #endif 8 | 9 | int main() { 10 | std::cout << "1\n"; 11 | debug_only { 12 | std::cout << "2\n"; 13 | std::cout << "3\n"; 14 | } 15 | std::cout << "4\n"; 16 | } 17 | -------------------------------------------------------------------------------- /15-230130/03-extra-macro/05-logging.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int foo() { 4 | std::cout << "Works a lot!\n"; 5 | return 10; 6 | } 7 | 8 | bool logging_enabled = true; 9 | 10 | #define LOG !logging_enabled ? std::cout : std::cout 11 | 12 | int main() { 13 | if (logging_enabled) { 14 | std::cout << foo() << "\n"; 15 | } 16 | LOG << foo() << "\n"; 17 | } 18 | // TODO: show why not func 19 | -------------------------------------------------------------------------------- /15-230130/03-extra-macro/06-extra.md: -------------------------------------------------------------------------------- 1 | http://jhnet.co.uk/articles/cpp_magic 2 | -------------------------------------------------------------------------------- /15-230130/TODO.md: -------------------------------------------------------------------------------- 1 | Add digraphs 2 | Talk about usefulness of macros _before_ its drawbacks 3 | Fix order of 03-extra-macro 4 | Better examples, not artificial 5 | -------------------------------------------------------------------------------- /16-230206/02-error-techniques/05-either-syntax-sugar.rs: -------------------------------------------------------------------------------- 1 | // https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html 2 | use std::fs::File; 3 | use std::io::Error; 4 | use std::io::Read; 5 | 6 | fn main() -> Result<(), Error> { 7 | let mut f = File::open("hello.txt")?; // '?' is a shortcut for "if failure, return Err()". 8 | let mut s = String::new(); 9 | f.read_to_string(&mut s)?; 10 | println!("File read: {:?}", s); 11 | Ok(()) 12 | } 13 | -------------------------------------------------------------------------------- /16-230206/02-error-techniques/10-no-handling.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | std::vector read_vector(const std::string &filename) { 9 | std::ifstream f(filename); 10 | assert(f); // Why no handling? 11 | int n; 12 | f >> n; 13 | assert(f); 14 | std::vector vec(n); 15 | for (int &v : vec) { 16 | f >> v; 17 | assert(f); 18 | } 19 | return vec; 20 | } 21 | -------------------------------------------------------------------------------- /16-230206/02-error-techniques/numbers-01-simple.in: -------------------------------------------------------------------------------- 1 | 2 3 2 | 4 5 3 | -------------------------------------------------------------------------------- /16-230206/02-error-techniques/numbers-02-immediate-eof.in: -------------------------------------------------------------------------------- 1 | 2 3 2 | 4 5 -------------------------------------------------------------------------------- /16-230206/03-basic-exceptions/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /16-230206/03-basic-exceptions/.idea/.name: -------------------------------------------------------------------------------- 1 | 03_basic_exceptions -------------------------------------------------------------------------------- /16-230206/03-basic-exceptions/.idea/03-basic-exceptions.iml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /16-230206/03-basic-exceptions/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /16-230206/03-basic-exceptions/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /16-230206/03-basic-exceptions/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /16-230206/03-basic-exceptions/03-multiple-catch.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct err1 {}; 5 | struct err2 {}; 6 | 7 | int main() { 8 | try { 9 | // throw err1(); 10 | // throw err2(); 11 | std::vector vec(-1); 12 | } catch (const err1 &) { 13 | std::cout << "1\n"; 14 | } catch (const err2 &) { 15 | std::cout << "2\n"; 16 | } catch (...) { // Exceptions only. Not UB, not assertions! 17 | std::cout << "3\n"; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /16-230206/03-basic-exceptions/30-final-notes.md: -------------------------------------------------------------------------------- 1 | Do not blindly use exceptions. Think about error handling first. Use exceptions only when it's easier than error codes. 2 | Especially do not use exceptions with programming errors. 3 | You can always easily go from error codes to exceptions, vice-versa is harder. 4 | Exceptions should be part of a contract. 5 | -------------------------------------------------------------------------------- /16-230206/03-basic-exceptions/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.24) 2 | project(03_basic_exceptions) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | 6 | add_executable(02-destructors 02-destructors.cpp) 7 | add_executable(05-complex-try-block 05-complex-try-block.cpp) 8 | -------------------------------------------------------------------------------- /16-230206/03-basic-exceptions/cmake-build-debug/.cmake/api/v1/query/cache-v2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hse-spb-2022-cpp/lectures/fb4f0527a3e94fb3d4d6562c5443aa55a50ecb39/16-230206/03-basic-exceptions/cmake-build-debug/.cmake/api/v1/query/cache-v2 -------------------------------------------------------------------------------- /16-230206/03-basic-exceptions/cmake-build-debug/.cmake/api/v1/query/cmakeFiles-v1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hse-spb-2022-cpp/lectures/fb4f0527a3e94fb3d4d6562c5443aa55a50ecb39/16-230206/03-basic-exceptions/cmake-build-debug/.cmake/api/v1/query/cmakeFiles-v1 -------------------------------------------------------------------------------- /16-230206/03-basic-exceptions/cmake-build-debug/.cmake/api/v1/query/codemodel-v2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hse-spb-2022-cpp/lectures/fb4f0527a3e94fb3d4d6562c5443aa55a50ecb39/16-230206/03-basic-exceptions/cmake-build-debug/.cmake/api/v1/query/codemodel-v2 -------------------------------------------------------------------------------- /16-230206/03-basic-exceptions/cmake-build-debug/.cmake/api/v1/query/toolchains-v1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hse-spb-2022-cpp/lectures/fb4f0527a3e94fb3d4d6562c5443aa55a50ecb39/16-230206/03-basic-exceptions/cmake-build-debug/.cmake/api/v1/query/toolchains-v1 -------------------------------------------------------------------------------- /16-230206/03-basic-exceptions/cmake-build-debug/.cmake/api/v1/reply/directory-.-Debug-d0094a50bb2071803777.json: -------------------------------------------------------------------------------- 1 | { 2 | "backtraceGraph" : 3 | { 4 | "commands" : [], 5 | "files" : [], 6 | "nodes" : [] 7 | }, 8 | "installers" : [], 9 | "paths" : 10 | { 11 | "build" : ".", 12 | "source" : "." 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /16-230206/03-basic-exceptions/cmake-build-debug/.ninja_deps: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hse-spb-2022-cpp/lectures/fb4f0527a3e94fb3d4d6562c5443aa55a50ecb39/16-230206/03-basic-exceptions/cmake-build-debug/.ninja_deps -------------------------------------------------------------------------------- /16-230206/03-basic-exceptions/cmake-build-debug/Testing/Temporary/LastTest.log: -------------------------------------------------------------------------------- 1 | Start testing: Feb 06 11:28 GTB Standard Time 2 | ---------------------------------------------------------- 3 | End testing: Feb 06 11:28 GTB Standard Time 4 | -------------------------------------------------------------------------------- /16-230206/TODO.md: -------------------------------------------------------------------------------- 1 | // throw; // rethrow current exception 2 | // no 'finally' block! -------------------------------------------------------------------------------- /16-230206/todo/11-no-exception-safety.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct Data { 5 | std::vector a, b; 6 | }; 7 | 8 | int main() { 9 | Data x, y; 10 | // ..... 11 | x = y; // x.a = x.b; y.a = y.b; 12 | // Oops: not exception safe 13 | } 14 | -------------------------------------------------------------------------------- /17-230213/00-extra-classes/02-inheritance-class.cpp: -------------------------------------------------------------------------------- 1 | class Base { 2 | public: 3 | void foo() { 4 | } 5 | }; 6 | 7 | class Derived : /* private */ Base {}; // Not OK? 8 | // class Derived : public Base {}; // OK 9 | // struct Derived : /* public */ Base {}; // OK 10 | 11 | int main() { 12 | Derived d; 13 | d.foo(); 14 | } 15 | -------------------------------------------------------------------------------- /17-230213/00-extra-classes/03-inheritance-private-noncopyable.cpp: -------------------------------------------------------------------------------- 1 | struct noncopyable { // boost::noncopyable 2 | noncopyable() = default; 3 | noncopyable(const noncopyable &) = delete; 4 | noncopyable(noncopyable &&) = delete; 5 | noncopyable &operator=(const noncopyable &) = delete; 6 | noncopyable &operator=(noncopyable &&) = delete; 7 | }; 8 | 9 | struct Foo : private noncopyable {}; 10 | struct Bar : private noncopyable {}; 11 | struct Baz : private noncopyable {}; 12 | 13 | int main() { 14 | Foo f; 15 | // noncopyable &n = f; // WTF, 'private' prevents that. 16 | 17 | // Foo f2 = f; 18 | } 19 | -------------------------------------------------------------------------------- /17-230213/00-extra-classes/20-delegating-ctor.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct bigint { 4 | bigint(const std::string &s) { 5 | // TODO: ... 6 | std::cout << "constructing from string " << s << "\n"; 7 | } 8 | bigint(int x) : bigint(std::to_string(x)) { // Delegating constructor 9 | // bigint(std::to_string(x)); // bad attempt :( 10 | std::cout << "constructing from int " << x << "\n"; 11 | } 12 | bigint() : bigint(0) {} 13 | }; 14 | 15 | int main() { 16 | bigint x(123); 17 | } 18 | -------------------------------------------------------------------------------- /17-230213/01-weird-exceptions/02-rethrow-slicing.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void foo() { 6 | try { 7 | throw std::runtime_error("Hello World"); 8 | } catch (std::exception &a) { 9 | // throw a; // oops, slicing 10 | throw; // no slicing 11 | } 12 | } 13 | 14 | int main() { 15 | try { 16 | foo(); 17 | } catch (std::exception &e) { 18 | std::cout << "caught in main(): " << e.what() << "\n"; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /17-230213/02-intermediate-exceptions/01-not-exception.cpp: -------------------------------------------------------------------------------- 1 | int main() { 2 | int x = 2 * 2'000'000'000; // UB 3 | int y = 2 / 0; // UB 4 | assert(false); // assertion failed, может быть удалён. 5 | 6 | std::vector vec(10); // Может быть std::bad_alloc, если памяти не хватило. 7 | vec[10] = 5; // UB 8 | vec.at(10) = 5; // std::out_of_bounds : std::exception, гарантируется. 9 | } 10 | -------------------------------------------------------------------------------- /17-230213/02-intermediate-exceptions/10-noexcept.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void check_n(int n) { 4 | if (n < 0) { 5 | throw 0; 6 | } 7 | } 8 | 9 | void foo() noexcept { // If exception: std::terminate(), no dtor calls 10 | std::cout << "foo() start\n"; 11 | int n; 12 | std::cin >> n; 13 | check_n(n); 14 | std::cout << "foo() end\n"; 15 | } 16 | 17 | int main() { 18 | try { 19 | foo(); 20 | } catch (...) { 21 | std::cout << "Caught\n"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /17-230213/02-intermediate-exceptions/11-noexcept-catch-inside.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void check_n(int n) { 4 | if (n < 0) { 5 | throw 0; 6 | } 7 | } 8 | 9 | void foo() noexcept { // If exception: std::terminate(), no dtor calls 10 | std::cout << "foo() start\n"; 11 | int n; 12 | std::cin >> n; 13 | try { 14 | check_n(n); 15 | } catch (...) { 16 | std::cout << "Caught inside\n"; 17 | } 18 | std::cout << "foo() end\n"; 19 | } 20 | 21 | int main() { 22 | try { 23 | foo(); 24 | } catch (...) { 25 | std::cout << "Caught\n"; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /17-230213/02-intermediate-exceptions/21-catch-ctor-and.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void may_throw(std::vector &) { 5 | // maybe throw exception 6 | } 7 | 8 | int main() { 9 | try { 10 | // try { 11 | std::vector v(100'000'000'000); 12 | // } catch 13 | v[99'999'999'999] = 123; 14 | may_throw(v); 15 | } catch (std::bad_alloc &) { 16 | std::cout << "caught bad_alloc inside v ctor or from may_throw\n"; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /17-230213/02-intermediate-exceptions/22-catch-ctor-only.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void may_throw(std::vector &) { 5 | // maybe throw exception 6 | } 7 | 8 | int main() { 9 | try { 10 | std::vector v(100'000'000'000); 11 | try { 12 | v[99'999'999'999] = 123; 13 | may_throw(v); 14 | } catch (...) { 15 | std::cout << "caught exception not inside v ctor\n"; 16 | } 17 | } catch (std::bad_alloc &) { 18 | std::cout << "caught bad_alloc inside v ctor\n"; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /17-230213/02-intermediate-exceptions/30-between-tu.a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void foo(); 5 | 6 | int main() { 7 | try { 8 | foo(); 9 | } catch (std::exception &e) { 10 | std::cout << "Exception: " << e.what() << "\n"; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /17-230213/02-intermediate-exceptions/30-between-tu.b.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void bar(int i); 4 | 5 | void foo() { 6 | for (int i = 0; i < 5; i++) { 7 | std::cout << "i=" << i << "\n"; 8 | bar(i); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /17-230213/02-intermediate-exceptions/30-between-tu.c.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct my_error : std::exception { 4 | const char *what() const noexcept override { 5 | return "my_error"; 6 | } 7 | }; 8 | 9 | void bar(int i) { 10 | if (i == 3) { 11 | throw my_error(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /17-230213/02-intermediate-exceptions/42-notes.md: -------------------------------------------------------------------------------- 1 | Some projects disabled exceptions altogether due to: 2 | 3 | 1. Little to no support in a compiler 4 | 2. Slow happy path 5 | 3. Hard-to-maintain code 6 | 7 | Example: Google. 8 | Enabling exceptions back is hard due to the lack of exception safety. They did not. 9 | 10 | Stereotype about hardware engineers: `-fno-exceptions` 11 | -------------------------------------------------------------------------------- /18-230220/01-exceptions-everywhere/14-stack-pop.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | struct stack { 5 | std::vector data; 6 | 7 | T pop() { 8 | T result = std::move(data.back()); 9 | data.pop_back(); 10 | return result; 11 | } 12 | }; 13 | 14 | int main() { 15 | stack s; 16 | s.data = std::vector{1, 2, 3, 4, 5}; 17 | 18 | int x = 10; 19 | x = s.pop(); // If exception is thrown by `operator=`, `s` cannot restore stack state. 20 | // Looks like strong guarantee violation. 21 | } 22 | -------------------------------------------------------------------------------- /18-230220/01-exceptions-everywhere/15-stack-pop-fix.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | struct stack { 5 | std::vector data; 6 | 7 | void pop_into(T &result) { 8 | result = std::move(data.back()); 9 | data.pop_back(); 10 | } 11 | }; 12 | 13 | int main() { 14 | stack s; 15 | s.data = std::vector{1, 2, 3, 4, 5}; 16 | 17 | int x = 10; 18 | s.pop_into(x); // All exceptions are handled by `pop` itself. 19 | } 20 | -------------------------------------------------------------------------------- /18-230220/02-threads/01-producer-consumer/02-queues.md: -------------------------------------------------------------------------------- 1 | There are some blocking queues: single-producer-single-consumer (SPSC), multi-producer multi-consumer (MPMC). 2 | Not covered today. 3 | Please use your team's/project's framework. 4 | E.g. in Facebook's Folly. 5 | -------------------------------------------------------------------------------- /19-230227/01-threads/01-producer-consumer/TODO.md: -------------------------------------------------------------------------------- 1 | notify() is better be under mutex: 2 | https://sourceware.org/git/?p=valgrind.git;a=blob;f=helgrind/hg_main.c;h=490fc38fefc7fd6e241ab8c592edb428933c90f4;hb=HEAD#l2421 3 | https://en.cppreference.com/w/cpp/thread/condition_variable/notify_one#Notes 4 | https://cplusplus.github.io/LWG/issue3343 5 | https://github.com/isocpp/CppCoreGuidelines/issues/1272 6 | https://github.com/isocpp/CppCoreGuidelines/issues/554#issuecomment-425687510 7 | -------------------------------------------------------------------------------- /19-230227/01-threads/04-mutable/01-mutable.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct atomic_int { 4 | int get() const { 5 | std::unique_lock l(m); 6 | return value; 7 | } 8 | 9 | void set(int new_value) { 10 | std::unique_lock l(m); 11 | value = new_value; 12 | } 13 | 14 | private: 15 | mutable std::mutex m; // Can be changed even in const-qualified methods. 16 | int value; 17 | }; 18 | 19 | int main() { 20 | } 21 | -------------------------------------------------------------------------------- /19-230227/01-threads/04-mutable/02-mutable-for-cache.cpp: -------------------------------------------------------------------------------- 1 | struct matrix { 2 | int determinant() const { 3 | } 4 | 5 | private: 6 | int n; 7 | std::vector data; 8 | mutable std::optional last_determinant; 9 | }; 10 | -------------------------------------------------------------------------------- /19-230227/02-network/README.md: -------------------------------------------------------------------------------- 1 | Complicated Boost examples: blocking TCP server/client from https://www.boost.org/doc/libs/1_78_0/doc/html/boost_asio/examples/cpp11_examples.html 2 | -------------------------------------------------------------------------------- /20-230306/02-network/32-boost-vs-qt.md: -------------------------------------------------------------------------------- 1 | For a project: use less libraries than more. 2 | If you use Qt, it already has almost anything you need, including sockets. 3 | Principles are the same, I don't recommend trying to set up both Boost and Qt. You can, though. 4 | -------------------------------------------------------------------------------- /20-230306/03-threads/02-api-design/22-toctou-wild.md: -------------------------------------------------------------------------------- 1 | https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use 2 | https://rules.sonarsource.com/c/RSPEC-5847 3 | https://habr.com/ru/post/683846/ 4 | -------------------------------------------------------------------------------- /20-230306/04-old/01-calling-stateful-method.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct Applier { 5 | int value; 6 | 7 | // We only know how to write it inside the class, no ODR violations here surprisingly. 8 | template 9 | void apply(F operation) { 10 | std::cout << "Calling with " << value << "\n"; 11 | operation(value); 12 | } 13 | }; 14 | 15 | struct Print { 16 | void operator()(int x) { 17 | std::cout << x << "\n"; 18 | } 19 | }; 20 | 21 | int main() { 22 | Applier a{10}; 23 | Print p; 24 | a.apply(p); 25 | } 26 | -------------------------------------------------------------------------------- /20-230306/05-multiple-tus/20-function-template-multiple-tu-bad/foo.cpp: -------------------------------------------------------------------------------- 1 | #include "print.hpp" 2 | #include 3 | 4 | namespace { 5 | struct my_secret_type {}; 6 | std::ostream &operator<<(std::ostream &os, const my_secret_type &) { 7 | return os << "secret"; 8 | } 9 | } 10 | 11 | void foo() { 12 | print(2); 13 | print(2.3); 14 | print(my_secret_type()); 15 | } 16 | -------------------------------------------------------------------------------- /20-230306/05-multiple-tus/20-function-template-multiple-tu-bad/main.cpp: -------------------------------------------------------------------------------- 1 | #include "print.hpp" 2 | 3 | void foo(); 4 | 5 | int main() { 6 | print(1); 7 | print(1.23); 8 | foo(); 9 | } 10 | -------------------------------------------------------------------------------- /20-230306/05-multiple-tus/20-function-template-multiple-tu-bad/print.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "print.hpp" 3 | 4 | template void print(const T &value) { 5 | std::cout << value << "\n"; 6 | } 7 | -------------------------------------------------------------------------------- /20-230306/05-multiple-tus/20-function-template-multiple-tu-bad/print.hpp: -------------------------------------------------------------------------------- 1 | #ifndef PRINT_HPP_ 2 | #define PRINT_HPP_ 3 | 4 | template void print(const T &value); 5 | 6 | #endif // PRINT_HPP_ 7 | -------------------------------------------------------------------------------- /20-230306/05-multiple-tus/21-function-template-multiple-tu/foo.cpp: -------------------------------------------------------------------------------- 1 | #include "print.hpp" 2 | #include 3 | 4 | namespace { 5 | struct my_secret_type {}; 6 | std::ostream &operator<<(std::ostream &os, const my_secret_type &) { 7 | return os << "secret"; 8 | } 9 | } 10 | 11 | void foo() { 12 | print(2); 13 | print(2.3); 14 | print(my_secret_type()); 15 | } 16 | -------------------------------------------------------------------------------- /20-230306/05-multiple-tus/21-function-template-multiple-tu/main.cpp: -------------------------------------------------------------------------------- 1 | #include "print.hpp" 2 | 3 | void foo(); 4 | 5 | int main() { 6 | print(1); 7 | print(1.23); 8 | foo(); 9 | } 10 | -------------------------------------------------------------------------------- /20-230306/05-multiple-tus/22-class-template-multiple-tu/foo.cpp: -------------------------------------------------------------------------------- 1 | #include "my_templ.hpp" 2 | 3 | void foo() { 4 | my_template{}.foo(); 5 | my_template{}.bar(); 6 | } 7 | -------------------------------------------------------------------------------- /20-230306/05-multiple-tus/22-class-template-multiple-tu/main.cpp: -------------------------------------------------------------------------------- 1 | #include "my_templ.hpp" 2 | 3 | void foo(); 4 | 5 | int main() { 6 | my_template{}.foo(); 7 | my_template{}.bar(); 8 | foo(); 9 | } 10 | -------------------------------------------------------------------------------- /21-230313/05-multiple-tus/01-extern-var-siof/a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | extern int var_main; // can be written in a header 5 | 6 | int var1 = 10; 7 | std::string var2 = "hello" + std::to_string(var_main); 8 | 9 | namespace { // multiple definition otherwise 10 | int var2_len = var2.size(); 11 | } 12 | 13 | void foo() { 14 | std::cout << "From foo()\n"; 15 | std::cout << var1 << " " << &var1 << "\n"; 16 | std::cout << var2 << " " << &var2 << "\n"; 17 | std::cout << var2_len << " " << &var2_len << "\n"; 18 | } 19 | -------------------------------------------------------------------------------- /21-230313/05-multiple-tus/02-const-var-no-linkage/a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | const int var1 = 10; 5 | const std::string var2 = "hello" + std::to_string(var1); 6 | 7 | void foo() { 8 | std::cout << "From foo()\n"; 9 | std::cout << var1 << " " << &var1 << "\n"; 10 | std::cout << var2 << " " << &var2 << "\n"; 11 | } 12 | -------------------------------------------------------------------------------- /21-230313/05-multiple-tus/02-const-var-no-linkage/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | const int var1 = 10; // const => unnamed namespace 5 | const std::string var2 = "hello" + std::to_string(var1); 6 | 7 | void foo(); 8 | 9 | int main() { 10 | std::cout << "From main()\n"; 11 | std::cout << var1 << " " << &var1 << "\n"; 12 | std::cout << var2 << " " << &var2 << "\n"; 13 | foo(); 14 | } 15 | -------------------------------------------------------------------------------- /21-230313/05-multiple-tus/10-inline/foo.cpp: -------------------------------------------------------------------------------- 1 | #include "print.h" 2 | 3 | void foo() { 4 | print(20); 5 | } 6 | -------------------------------------------------------------------------------- /21-230313/05-multiple-tus/10-inline/main.cpp: -------------------------------------------------------------------------------- 1 | #include "print.h" 2 | 3 | void foo(); 4 | 5 | int main() { 6 | foo(); 7 | print(10); 8 | 9 | Printer p = {239}; 10 | p.print(); 11 | p.foo(); 12 | } 13 | -------------------------------------------------------------------------------- /21-230313/05-multiple-tus/10-inline/print.cpp: -------------------------------------------------------------------------------- 1 | #include "print.h" 2 | #include 3 | 4 | void Printer::foo() { 5 | std::cout << "Printer::foo()\n"; 6 | } 7 | -------------------------------------------------------------------------------- /21-230313/05-multiple-tus/11-inline-var-almost-no-siof/a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | inline int counter = 123; 5 | inline constexpr int var2 = ++counter; 6 | inline constexpr int var1 = ++counter; 7 | 8 | void foo() { 9 | std::cout << "From foo()\n"; 10 | std::cout << var1 << " " << &var1 << "\n"; 11 | std::cout << var2 << " " << &var2 << "\n"; 12 | } 13 | -------------------------------------------------------------------------------- /21-230313/05-multiple-tus/11-inline-var-almost-no-siof/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | inline int counter = 123; // Since C++17 4 | // Behavior changes when commented out 5 | inline constexpr int var1 = ++counter; 6 | inline constexpr int var2 = ++counter; 7 | 8 | struct Foo { 9 | static inline int value = 10; 10 | }; 11 | 12 | void foo(); 13 | 14 | int main() { 15 | std::cout << "From main()\n"; 16 | std::cout << var1 << " " << &var1 << "\n"; 17 | std::cout << var2 << " " << &var2 << "\n"; 18 | std::cout << Foo::value << " " << &Foo::value << "\n"; 19 | foo(); 20 | } 21 | -------------------------------------------------------------------------------- /21-230313/05-multiple-tus/12-static-member-redefinition/a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct Foo { 5 | static int value; 6 | }; 7 | //int Foo::value = 10; 8 | 9 | void foo() { 10 | std::cout << "From foo()\n"; 11 | std::cout << Foo::value << " " << &Foo::value << "\n"; 12 | } 13 | -------------------------------------------------------------------------------- /21-230313/05-multiple-tus/12-static-member-redefinition/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct Foo { 4 | static int value; 5 | }; 6 | int Foo::value = 10; 7 | 8 | void foo(); 9 | 10 | int main() { 11 | std::cout << "From main()\n"; 12 | std::cout << Foo::value << " " << &Foo::value << "\n"; 13 | foo(); 14 | } 15 | -------------------------------------------------------------------------------- /21-230313/05-multiple-tus/13-static-member-inline/a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct Foo { 5 | static inline int value = 10; 6 | }; 7 | 8 | void foo() { 9 | std::cout << "From foo()\n"; 10 | std::cout << Foo::value << " " << &Foo::value << "\n"; 11 | } 12 | -------------------------------------------------------------------------------- /21-230313/05-multiple-tus/13-static-member-inline/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct Foo { 4 | static inline int value = 10; 5 | }; 6 | 7 | void foo(); 8 | 9 | int main() { 10 | std::cout << "From main()\n"; 11 | std::cout << Foo::value << " " << &Foo::value << "\n"; 12 | foo(); 13 | } 14 | -------------------------------------------------------------------------------- /21-230313/05-multiple-tus/14-global-consts-multiple-tu/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "a.h" 3 | 4 | int main() { 5 | std::cout << "From main()\n"; 6 | std::cout << str1 << " " << &str1 << "\n"; 7 | std::cout << str2 << " " << &str2 << "\n"; 8 | std::cout << str3 << " " << &str3 << "\n"; 9 | std::cout << str4 << " " << &str4 << "\n"; 10 | std::cout << Foo::str1 << " " << &Foo::str1 << "\n"; 11 | std::cout << Foo::str2 << " " << &Foo::str2 << "\n"; 12 | std::cout << Foo::str3 << " " << &Foo::str3 << "\n"; 13 | std::cout << Foo::str4 << " " << &Foo::str4 << "\n"; 14 | 15 | foo(); 16 | } 17 | -------------------------------------------------------------------------------- /21-230313/10-align-padding/01-alignment.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | long long x = 10; 6 | std::cout << x << "\n"; 7 | std::cout << sizeof(x) << " " << alignof(x) << "\n"; 8 | assert(sizeof(x) % alignof(x) == 0); 9 | std::cout << &x << "\n"; 10 | } 11 | -------------------------------------------------------------------------------- /21-230313/10-align-padding/05-padding-inheritance.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct Bar { 4 | int i = 0; 5 | char c = 0; 6 | char c2 = 0; 7 | // padding 8 | }; 9 | 10 | struct BarDerived : Bar { 11 | char c3 = 0; 12 | int i2 = 0; 13 | }; 14 | 15 | int main() { 16 | std::cout << sizeof(Bar) << "\n"; 17 | std::cout << sizeof(BarDerived) << "\n"; 18 | } 19 | -------------------------------------------------------------------------------- /21-230313/10-align-padding/TODO.md: -------------------------------------------------------------------------------- 1 | demonstrate incorrect alignment with ubsanitizer or qemu or bad performance 2 | 3 | -------------------------------------------------------------------------------- /21-230313/11-for-optional/TODO.md: -------------------------------------------------------------------------------- 1 | optional &operator=(optional other) 2 | vs 3 | optional &operator=(const optional &other) 4 | optional &operator=(optional &&other) 5 | -------------------------------------------------------------------------------- /22-230320/01-binary-formats/02-strings.cp1251.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hse-spb-2022-cpp/lectures/fb4f0527a3e94fb3d4d6562c5443aa55a50ecb39/22-230320/01-binary-formats/02-strings.cp1251.txt -------------------------------------------------------------------------------- /22-230320/01-binary-formats/02-strings.cp866.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hse-spb-2022-cpp/lectures/fb4f0527a3e94fb3d4d6562c5443aa55a50ecb39/22-230320/01-binary-formats/02-strings.cp866.txt -------------------------------------------------------------------------------- /22-230320/01-binary-formats/02-strings.koi8r.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hse-spb-2022-cpp/lectures/fb4f0527a3e94fb3d4d6562c5443aa55a50ecb39/22-230320/01-binary-formats/02-strings.koi8r.txt -------------------------------------------------------------------------------- /22-230320/01-binary-formats/02-strings.utf8.txt: -------------------------------------------------------------------------------- 1 | Вопрос? 2 | Vopros? 3 | -------------------------------------------------------------------------------- /22-230320/01-binary-formats/03-real-world.md: -------------------------------------------------------------------------------- 1 | https://www.youtube.com/watch?v=Z8SHvJnGUCM 2 | https://stackoverflow.com/questions/6163683/cycles-in-family-tree-software 3 | https://github.com/kdeldycke/awesome-falsehood 4 | -------------------------------------------------------------------------------- /22-230320/01-binary-formats/04-newline.md: -------------------------------------------------------------------------------- 1 | `\n` in C++ - number 10. 2 | 3 | Windows: newline: number 13 ('\r'), number 10 ('\n'). 4 | Carriage return + new line, like in typewriter 5 | Linux, modern macOS: number 10. 6 | Old macOS: number 13. 7 | 8 | C++, Python...: 9 | File in "text mode": replace 13 with: 13 or 13+10 or 10. 10 | File in "binary mode": write 13 as-is 11 | 12 | Why: 13 | https://xkcd.com/927/ 14 | https://xkcd.ru/927/ 15 | -------------------------------------------------------------------------------- /22-230320/02-aliasing/01-reinterpret-cast.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | int x = 123456; 6 | char *xc = reinterpret_cast(&x); 7 | // Becomes the following: 8 | // char *xc = static_cast(static_cast(&x)); 9 | for (std::size_t i = 0; i < sizeof(x); i++) { 10 | std::cout << static_cast(xc[i]) << "\n"; 11 | } 12 | // 64 -30 1 0 13 | // 64 226 1 0 14 | // 64 + 256*(226 + 256*(1 + 256*0)) 15 | } 16 | -------------------------------------------------------------------------------- /22-230320/02-aliasing/04-write.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | int x = 123456; 6 | char *xc = reinterpret_cast(&x); 7 | static_assert(sizeof(int) == 4); 8 | 9 | xc[0] = 10; 10 | xc[1] = 11; 11 | xc[2] = 12; 12 | xc[3] = 13; 13 | std::cout << std::hex << x << "\n"; 14 | } 15 | -------------------------------------------------------------------------------- /22-230320/02-aliasing/05-write-bad.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | char xc[] = {10, 11, 12, 13}; 6 | static_assert(sizeof(int) == 4); 7 | 8 | int *xptr = reinterpret_cast(xc); 9 | std::cout << std::hex << *xptr /* UB */ << "\n"; 10 | // T1 == int, T2 == char[]. Нельзя. 11 | } 12 | -------------------------------------------------------------------------------- /22-230320/02-aliasing/06-note.txt: -------------------------------------------------------------------------------- 1 | Strict aliasing rule часто нарушают. 2 | Много кода требует себе `-fno-strict-aliasing`. 3 | -------------------------------------------------------------------------------- /22-230320/02-aliasing/07-copy.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | float x = 1.0; 5 | int y; 6 | 7 | static_assert(sizeof(x) == sizeof(y)); 8 | // Аналог std::memcpy. Не UB. 9 | // Начиная с C++20 есть bit_cast<>. 10 | for (int i = 0; i < 4; i++) { 11 | reinterpret_cast(&y)[i] = reinterpret_cast(&x)[i]; 12 | } 13 | 14 | std::cout << std::hex << y << "\n"; 15 | } 16 | -------------------------------------------------------------------------------- /22-230320/02-aliasing/extra-reading.md: -------------------------------------------------------------------------------- 1 | Type punning 2 | https://habr.com/ru/company/otus/blog/442554/ 3 | https://habr.com/ru/company/otus/blog/443602/ 4 | -------------------------------------------------------------------------------- /22-230320/03-trivially-copyable/.gitignore: -------------------------------------------------------------------------------- 1 | /*.bin 2 | -------------------------------------------------------------------------------- /22-230320/03-trivially-copyable/02-read.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | struct MyTriviallyCopyable { 6 | int x; 7 | char y; 8 | // Compiler may add padding: 3 bytes so 'z' is 4-bytes aligned. 9 | float z; 10 | }; 11 | 12 | static_assert(std::is_trivially_copyable_v); 13 | 14 | int main() { 15 | MyTriviallyCopyable p; 16 | std::ifstream f("01.bin", std::ios_base::in | std::ios_base::binary); 17 | // Not UB. 18 | f.read(reinterpret_cast(&p), sizeof(p)); 19 | std::cout << p.x << " " << static_cast(p.y) << " " << p.z << "\n"; 20 | } 21 | -------------------------------------------------------------------------------- /22-230320/03-trivially-copyable/11-padding-read.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #pragma pack(push, 1) 5 | struct MyPod { 6 | int x = 100; 7 | char y = 200; 8 | float z = 300; 9 | }; 10 | #pragma pack(pop) 11 | 12 | int main() { 13 | MyPod p; 14 | std::ifstream f("10.bin", std::ios_base::out | std::ios_base::binary); 15 | // Not UB. 16 | f.read(reinterpret_cast(&p), sizeof(p)); 17 | std::cout << p.x << " " << static_cast(p.y) << " " << p.z << "\n"; 18 | } 19 | -------------------------------------------------------------------------------- /22-230320/03-trivially-copyable/12-swap-unaligned: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hse-spb-2022-cpp/lectures/fb4f0527a3e94fb3d4d6562c5443aa55a50ecb39/22-230320/03-trivially-copyable/12-swap-unaligned -------------------------------------------------------------------------------- /22-230320/03-trivially-copyable/13-pack-vector-bad.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #pragma pack(push, 1) 5 | struct Foo { 6 | char x; 7 | std::vector v; 8 | }; 9 | #pragma pack(pop) 10 | 11 | int main() { 12 | Foo f; 13 | std::cout << alignof(f) << "\n"; 14 | std::cout << alignof(std::vector) << "\n"; 15 | std::cout << static_cast(&f.v) << "\n"; 16 | } 17 | -------------------------------------------------------------------------------- /22-230320/04-trivially-copyable-strings/.gitignore: -------------------------------------------------------------------------------- 1 | /*.bin 2 | -------------------------------------------------------------------------------- /22-230320/04-trivially-copyable-strings/01-c-str-arr-pod.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | struct Person { 6 | char first_name[31]{}; 7 | char last_name[31]{}; 8 | }; 9 | 10 | int main() { 11 | Person p; 12 | std::strcpy(p.first_name, "Konstantin"); 13 | std::strcpy(p.first_name, "Ivan"); 14 | std::strcpy(p.last_name, "Ivanov"); 15 | 16 | { 17 | std::ofstream f("01.bin", std::ios::binary); 18 | f.write(reinterpret_cast(&p), sizeof p); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /22-230320/04-trivially-copyable-strings/01b-c-str-arr-pod-read.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | struct Person { 6 | char first_name[31]{}; 7 | char last_name[31]{}; 8 | }; 9 | 10 | int main() { 11 | Person p; 12 | { 13 | std::ifstream f("01.bin", std::ios::binary); 14 | f.read(reinterpret_cast(&p), sizeof p); 15 | } 16 | std::cout << p.first_name << "\n"; 17 | std::cout << p.last_name << "\n"; 18 | } 19 | -------------------------------------------------------------------------------- /22-230320/04-trivially-copyable-strings/02-c-str-ptr-bad-pod.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | struct Person { 6 | const char *first_name; 7 | const char *last_name; 8 | }; 9 | 10 | int main() { 11 | Person p; 12 | p.first_name = "Ivan"; 13 | p.last_name = "Ivanov"; 14 | 15 | { 16 | std::ofstream f("02.bin", std::ios::binary); 17 | f.write(reinterpret_cast(&p), sizeof p); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /22-230320/04-trivially-copyable-strings/03-string-bad-pod.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | struct Person { 6 | std::string first_name; 7 | std::string last_name; 8 | }; 9 | 10 | int main() { 11 | Person p; 12 | p.first_name = "Ivan1234123412341234123412341234123412341234123412341234xxx"; 13 | p.last_name = "Ivanov"; 14 | 15 | { 16 | std::ofstream f("03.bin", std::ios::binary); 17 | f.write(reinterpret_cast(&p), sizeof p); // Not UB, but UB on read. 18 | // std::string is not trivially copyable. 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /23-230411/10-template-friends/01-class.cpp: -------------------------------------------------------------------------------- 1 | // template 2 | // struct Bar; 3 | 4 | template 5 | struct Foo { 6 | private: 7 | int x = 0; 8 | 9 | // All Bar<> are friends of us. 10 | template 11 | friend struct Bar; 12 | }; 13 | 14 | template 15 | struct Bar { 16 | void bar() { 17 | Foo f; 18 | f.x = 10; 19 | 20 | Foo g; 21 | g.x = 10; 22 | } 23 | }; 24 | 25 | int main() { 26 | Bar().bar(); 27 | } 28 | -------------------------------------------------------------------------------- /24-230413/02-double-pointers/01-array-of-strs.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | //void foo(const char *strs[]) { 4 | void foo(const char **strs) { 5 | std::cout << strs[0] << " " << strs[1] << "\n"; 6 | } 7 | 8 | int main(int argc, char *argv[]) { 9 | const char *strs[] = { 10 | "Hello from ", 11 | "World" 12 | }; 13 | foo(strs); 14 | 15 | for (int i = 0; i < argc; i++) { 16 | std::cout << argv[i] << "\n"; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /24-230413/02-double-pointers/02-out-str.in: -------------------------------------------------------------------------------- 1 | 123456789abcdefghi 2 | 3 | -------------------------------------------------------------------------------- /24-230413/03-printf-scanf/01.in: -------------------------------------------------------------------------------- 1 | hi wor- meow-meow 4 5 2 | 123.45 3 | 99999999125.43 4 | -------------------------------------------------------------------------------- /24-230413/03-printf-scanf/03.in: -------------------------------------------------------------------------------- 1 | hi 2 | heyy 123 3 | hoy 4 | -------------------------------------------------------------------------------- /25-230420/01-c-generics/02-void-ptr-print-str.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | int i = 123; 5 | char a = 'X'; 6 | 7 | std::cout << i << "\n"; // 123 8 | std::cout << &i << "\n"; // address of 'i' 9 | 10 | std::cout << a << "\n"; // X 11 | // std::cout << &a << "\n"; // UB, because `char*` is interpreted as ASCIIZ string 12 | std::cout << static_cast(&a) << "\n"; // ok, address of 'a' 13 | } 14 | -------------------------------------------------------------------------------- /25-230420/01-c-generics/03-void-ptr-extensions.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void func() {} 4 | 5 | int main() { 6 | int buf[10]; 7 | void *ptr = buf; 8 | void *ptr2 = ptr + 5; // GCC extension! Only a warning in GCC, error in Clang. 9 | assert(ptr2 == static_cast(ptr) + 5); 10 | } 11 | -------------------------------------------------------------------------------- /25-230420/01-c-generics/14-fptrs-default-args.cpp: -------------------------------------------------------------------------------- 1 | void foo(int = 10) {} 2 | 3 | int main() { 4 | void (*f1)(int) = foo; 5 | 6 | // No support for default arguments at all: 7 | 8 | // void (*f2)() = foo; 9 | // void (*f3)(int = 10) = foo; 10 | } 11 | -------------------------------------------------------------------------------- /25-230420/01-c-generics/20-for-each-int.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void for_each(int *begin, int *end, void (*f)(int)) { 4 | while (begin != end) 5 | f(*begin++); 6 | } 7 | 8 | void print_int(int x) { 9 | std::cout << x << "\n"; 10 | } 11 | 12 | int main(void) { 13 | int arr[10]{}; 14 | arr[3] = 100; 15 | arr[5] = 200; 16 | for_each(arr, arr + 10, print_int); 17 | } 18 | -------------------------------------------------------------------------------- /25-230420/01-c-generics/22-for-each-generic-gcc.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void for_each(void *begin, void *end, std::size_t elem_size, void (*f)(const void*)) { 5 | for (; begin != end; begin += elem_size) { 6 | f(begin); // Can only pass element by pointer 7 | } 8 | } 9 | 10 | void print_int(const int *x) { 11 | std::cout << *x << "\n"; 12 | } 13 | 14 | int main(void) { 15 | int arr[10]{}; 16 | arr[3] = 100; 17 | arr[5] = 200; 18 | for_each(arr, arr + 10, sizeof(arr[0]), 19 | print_int // Needs -fpermissive and pile of luck 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /25-230420/01-c-generics/TODO.md: -------------------------------------------------------------------------------- 1 | talk about lack of templates and what is the need for void* and fptr 2 | 3 | swap 0x and 1x, mix with 2x: first function pointers to describe lack of templates, then void* for captures 4 | 5 | interleave with 12-221205? 6 | -------------------------------------------------------------------------------- /25-230420/02-c-differences/00-warning.md: -------------------------------------------------------------------------------- 1 | * I have no idea about exact UB or rules :( 2 | * You can look it up at 3 | * https://en.cppreference.com/w/c/string/byte/memcpy 4 | * https://en.cppreference.com/w/cpp/string/byte/memcpy 5 | * Also see https://isocpp.org/wiki/faq/c 6 | -------------------------------------------------------------------------------- /25-230420/02-c-differences/02-function-args.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void foo(char* a) { 4 | printf("%s\n", a); 5 | } 6 | 7 | void bar() { // Any arguments! 8 | } 9 | 10 | void baz(void) { // No arguments 11 | } 12 | 13 | int main(void) { 14 | foo("hello"); 15 | // foo("hello", "world"); // compilation error 16 | bar(1, 2, 3, "wow"); 17 | baz(); 18 | // baz(1, 2, 3); // compilation error 19 | } 20 | -------------------------------------------------------------------------------- /25-230420/02-c-differences/03-implicit-function-declaration.c: -------------------------------------------------------------------------------- 1 | // #include 2 | /* 3 | 4 | f(1, 2, 3, 4, "foo") --> int f(); 5 | void *malloc() vs int malloc(). 6 | gcc thinks it's ok in C11 still 7 | */ 8 | 9 | int main(void) { 10 | printf("2 + 2 = %d\n", 4); // Works: implicitly adds `int printf();` 11 | // botva(1, 2); // Error in C99, link error in C89 (or GCC with C99+) 12 | } 13 | -------------------------------------------------------------------------------- /25-230420/02-c-differences/03b-implicit-var.c: -------------------------------------------------------------------------------- 1 | /* int */ x = 10; 2 | /* int */ main() { printf("Hello World %d\n", x); } 3 | -------------------------------------------------------------------------------- /25-230420/02-c-differences/04-kr-defs.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* K&R (old-style) function definitions are allowed (deleted in C23). Use never. */ 4 | void foo(a, b) 5 | int a; char b; 6 | { 7 | printf("a=%d, b=%c\n", a, b); 8 | } 9 | 10 | void bar(int a, char b) { 11 | printf("a=%d, b=%c\n", a, b); 12 | } 13 | 14 | int main() { 15 | foo(123, 'x'); 16 | bar(456, 'y'); 17 | } 18 | -------------------------------------------------------------------------------- /25-230420/02-c-differences/05-designator-list.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct point { 4 | int x, y, z; 5 | }; 6 | 7 | #define INIT_ARR [0] = 55, [1] = 56 8 | 9 | int main(void) { 10 | // zero everything except `x` and `y` 11 | struct point p = {.z = 10, .y = 20}; 12 | printf("p=%d %d %d\n", p.x, p.y, p.z); 13 | 14 | // https://docs.python.org/3/extending/newtypes_tutorial.html#defining-new-types 15 | int arr[10] = {INIT_ARR, [3] = 5, [5] = 10}; 16 | for (int i = 0; i < 10; i++) { 17 | printf("arr[%d]=%d\n", i, arr[i]); 18 | } 19 | // int arr2[10] = {1, 2, 3}; 20 | } 21 | -------------------------------------------------------------------------------- /25-230420/02-c-differences/07-extensions.md: -------------------------------------------------------------------------------- 1 | Lots of compiler-specific stuff: 2 | 3 | https://gcc.gnu.org/onlinedocs/gcc-11.2.0/gcc/#toc-Extensions-to-the-C-Language-Family 4 | 5 | * Nested functions in C 6 | * `__attribute__((constructor))` 7 | -------------------------------------------------------------------------------- /25-230420/02-c-differences/20-static-function-var-1.c: -------------------------------------------------------------------------------- 1 | void foo(void); 2 | void bar(void); 3 | 4 | extern int x; 5 | extern int y; 6 | 7 | int main(void) { 8 | foo(); 9 | bar(); 10 | x = 0; 11 | y = 0; 12 | } 13 | -------------------------------------------------------------------------------- /25-230420/02-c-differences/20-static-function-var-2.c: -------------------------------------------------------------------------------- 1 | // Instead of unnamed namespace 2 | static void foo(void) { // internal linkage 3 | } 4 | 5 | void bar(void) { 6 | } 7 | 8 | static int x; // internal linkage 9 | int y; 10 | -------------------------------------------------------------------------------- /25-230420/02-c-differences/22b-malloc-implicit.c: -------------------------------------------------------------------------------- 1 | int main(void) { 2 | int *a = malloc(sizeof(int)); // TODO 3 | a[0] = 10; 4 | printf("%d\n", a[0]); 5 | free(a); 6 | } 7 | -------------------------------------------------------------------------------- /25-230420/02-c-differences/24-incompatibility.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(void) { 5 | // 1. 6 | int *a = malloc(5 * sizeof(int)); // new int[5]; 7 | // int *a = (int*)malloc(5 * sizeof(int)); // very bad style: TODO 8 | free(a); // delete[] a 9 | 10 | // 2. 11 | // 'A' is int in C, char in C++. 12 | printf("%d %d %d\n", (int)sizeof('A'), (int)sizeof((char)'A'), (int)sizeof(char)); 13 | } 14 | -------------------------------------------------------------------------------- /25-230420/02-c-differences/24-incompatibility.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(void) { 5 | // 1. 6 | // int *a = malloc(5 * sizeof(int)); // new int[5]; 7 | int *a = static_cast(malloc(5 * sizeof(int))); // new int[5]; 8 | free(a); // delete[] a 9 | 10 | // 2. 11 | // 'A' is int in C, char in C++. 12 | printf("%d %d\n", (int)sizeof('A'), (int)sizeof(char)); 13 | } 14 | -------------------------------------------------------------------------------- /25-230420/02-c-differences/TODO.md: -------------------------------------------------------------------------------- 1 | Split even better: 2 | 3 | 1. Things you really need 4 | 2. Things you may find useful 5 | 3. (???) Things similar to C++, but different 6 | 4. Historical quirks 7 | -------------------------------------------------------------------------------- /26-230427/02-goto/02-goto-fwd.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) { 4 | int n = 10; 5 | if (n >= 5) 6 | goto big_n; 7 | int c = 100; // Ok in C, "crosses initialization" in C++. 8 | printf("n is small\n"); 9 | n += 100; 10 | big_n: 11 | printf("n is big: %d; c=%d\n", n, c); 12 | } 13 | -------------------------------------------------------------------------------- /26-230427/02-goto/02-goto-fwd.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) { 4 | int n = 10; 5 | if (n >= 5) 6 | goto big_n; 7 | int c = 100; // Ok in C, "crosses initialization" in C++. 8 | printf("n is small\n"); 9 | n += 100; 10 | big_n: 11 | printf("n is big: %d; c=%d\n", n, c); 12 | } 13 | -------------------------------------------------------------------------------- /26-230427/02-goto/data-no-n.in: -------------------------------------------------------------------------------- 1 | xxx 2 | -------------------------------------------------------------------------------- /26-230427/02-goto/data-not-enough.in: -------------------------------------------------------------------------------- 1 | 10 5 5 5 2 | 3 | -------------------------------------------------------------------------------- /26-230427/02-goto/data-ok.in: -------------------------------------------------------------------------------- 1 | 3 2 | 1 2 3 3 | -------------------------------------------------------------------------------- /26-230427/04-c-cpp-extern/01-extern-c-linking/a.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int my_main(void); 4 | 5 | int foo(void) { 6 | int arr[] = { [3] = 123 }; // Use C-specific syntax to ensure we're writing C. 7 | return arr[3]; 8 | } 9 | 10 | int main(void) { 11 | printf("hello\n"); 12 | return my_main(); 13 | } 14 | -------------------------------------------------------------------------------- /26-230427/04-c-cpp-extern/01-extern-c-linking/build-bad.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | gcc a.c b.cpp # gcc does not link with C++ standard library 3 | g++ a.c b.cpp # g++ considers all files to be C++ regardless of extension 4 | -------------------------------------------------------------------------------- /26-230427/04-c-cpp-extern/01-extern-c-linking/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | gcc a.c -c # gcc or `-x c`, otherwise will assume c++ regardless of extension 3 | gcc b.cpp -c # gcc or g++ both work(?) 4 | g++ a.o b.o -o a # g++! Should include C++ standard library: https://stackoverflow.com/a/172592/767632 5 | #gcc a.o b.o -lstdc++ -o a 6 | -------------------------------------------------------------------------------- /26-230427/04-c-cpp-extern/02-header/a.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "a.h" 3 | #include "b.h" 4 | 5 | int foo(void) { 6 | int arr[] = { [3] = 123 }; // Use C-specific syntax to ensure we're writing C. 7 | return arr[3]; 8 | } 9 | 10 | int main(void) { 11 | printf("hello\n"); 12 | return my_main(); 13 | // return my_main(1, 2, 3); // Should not compile! 14 | } 15 | -------------------------------------------------------------------------------- /26-230427/04-c-cpp-extern/02-header/a.h: -------------------------------------------------------------------------------- 1 | #ifndef A_H_ 2 | #define A_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | int foo(void); 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | 14 | #endif // A_H_ 15 | -------------------------------------------------------------------------------- /26-230427/04-c-cpp-extern/02-header/b.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "a.h" 5 | #include "b.h" 6 | 7 | int foo(int x) { // OK 8 | return x + 1; 9 | } 10 | 11 | struct Foo { 12 | Foo() { 13 | std::printf("Foo\n"); 14 | } 15 | ~Foo() { 16 | std::printf("~Foo\n"); 17 | } 18 | } f; 19 | 20 | int my_main() { 21 | std::vector v; 22 | std::cout << foo() << "\n"; 23 | std::cout << foo(100) << "\n"; 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /26-230427/04-c-cpp-extern/02-header/b.h: -------------------------------------------------------------------------------- 1 | #ifndef B_H_ 2 | #define B_H_ 3 | 4 | // .h instead of .hpp because compatible with C. My personal tradition. 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | int my_main(void); // Remember to say "no arguments" in C! It's compatible with C++ 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif // B_H_ 17 | -------------------------------------------------------------------------------- /26-230427/04-c-cpp-extern/02-header/build-bad.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | gcc a.c b.cpp # gcc does not link with C++ standard library 3 | g++ a.c b.cpp # g++ considers all files to be C++ regardless of extension 4 | -------------------------------------------------------------------------------- /26-230427/04-c-cpp-extern/02-header/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | gcc a.c -c # gcc or `-x c`, otherwise will assume c++ regardless of extension 3 | gcc b.cpp -c # gcc or g++ both work(?) 4 | g++ a.o b.o -o a # g++! Should include C++ standard library: https://stackoverflow.com/a/172592/767632 5 | #gcc a.o b.o -lstdc++ -o a 6 | -------------------------------------------------------------------------------- /26-230427/04-c-cpp-extern/02-header/xxx.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | 5 | #define N 100 // instead of const int N = 100; 6 | 7 | int foo(void); // Remember to say "no arguments" in C! It's compatible with C++ 8 | int my_main(); // Bad style. 9 | 10 | // There are other incompatibilities: e.g. default arguments, macros instead of consts, you name it... 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | -------------------------------------------------------------------------------- /26-230427/04-c-cpp-extern/03-header-incompatibility/a.h: -------------------------------------------------------------------------------- 1 | const int N = 100; // C++ only 2 | #define N 100 // C++ and C 3 | 4 | struct Point { 5 | int x, y; 6 | }; 7 | struct TwoPoints { 8 | Point a, b; // C++ only 9 | struct Point a, b; // C++ and C 10 | }; 11 | 12 | int foo(int x = 100); // C++ only 13 | int foo(int x); // C++ and C, no default arguments. At all. 14 | -------------------------------------------------------------------------------- /26-230427/05-c-resource-management/10-json.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | const char *s = "{\"field\":\"value\",\"arr\":[1,2,3.5]}"; 7 | 8 | struct json_object *obj = json_tokener_parse(s); 9 | // ~ shared_ptr 10 | assert(obj); 11 | 12 | // for (auto [k, v] : obj) 13 | json_object_object_foreach(obj, k, v) { 14 | printf("%s --> %s\n", k, json_object_to_json_string_ext(v, JSON_C_TO_STRING_PRETTY)); 15 | } 16 | 17 | json_object_put(obj); // ~ destructor 18 | } 19 | -------------------------------------------------------------------------------- /26-230427/06-extra.md: -------------------------------------------------------------------------------- 1 | Linkers: 2 | 3 | ld - GNU 4 | lld - LLVM linker, may be faster: https://lld.llvm.org/ 5 | gold - another GNU, may be faster: https://en.wikipedia.org/wiki/Gold_(linker) 6 | mold - parallel, https://github.com/rui314/mold 7 | sold - commercial version of mold, https://github.com/bluewhalesystems/sold 8 | 9 | -------------------------------------------------------------------------------- /27-230511/03-virtual-multiple-inheritance-details/03-most-accessible-path.cpp: -------------------------------------------------------------------------------- 1 | struct Base { 2 | int data; 3 | }; 4 | 5 | struct X : private virtual Base { 6 | }; 7 | 8 | struct Y : public virtual Base { 9 | }; 10 | 11 | struct X1 : X { 12 | void foo() { 13 | // data = 10; // access through X, private 14 | } 15 | }; 16 | 17 | struct Derived : X, Y { 18 | void foo() { 19 | data = 10; // access is public through Y 20 | Y::data = 20; // accessible as well, not surprising 21 | X::data = 30; // accessible as well, wow 22 | } 23 | }; 24 | 25 | int main() { 26 | } 27 | -------------------------------------------------------------------------------- /28-230518/01-template-friends/00-link.md: -------------------------------------------------------------------------------- 1 | See 23-230411/10-template-friends/0* 2 | -------------------------------------------------------------------------------- /28-230518/01-template-friends/TODO.md: -------------------------------------------------------------------------------- 1 | There are four combinations: 2 | 3 | 1. Is the friend function a template or not? 4 | 2. Do we generate a new friend function for each class instantiation or not? 5 | 6 | Add those to files, renumber. 7 | -------------------------------------------------------------------------------- /28-230518/02-template-details/01-typename-ambiguity.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct foo { 3 | int y = 1; 4 | void bar() { 5 | /*typename*/ T::x *y; 6 | /*typename*/ T::x * y; 7 | } 8 | }; 9 | 10 | struct with_int { static inline int x = 5; }; 11 | foo f_int; 12 | 13 | struct with_type { using x = char; }; 14 | foo f_type; 15 | 16 | int main() { 17 | f_int.bar(); 18 | f_type.bar(); // Does not compile, needs 'typename' before 'T::x' 19 | } 20 | -------------------------------------------------------------------------------- /28-230518/02-template-details/02-template-member-call-ambiguity.cpp: -------------------------------------------------------------------------------- 1 | struct with_templ_member { 2 | template 3 | static int foo() { return 10; }; 4 | }; 5 | 6 | template 7 | struct Foo { 8 | void call_foo() { 9 | // T::foo(); 10 | // T::foo < int >(); // compilation error: expected primary-expression before 'int' 11 | // i.e.. "cannot compare foo with int" 12 | T::template foo(); // needs 'template' 13 | } 14 | }; 15 | 16 | int main() { 17 | Foo().call_foo(); 18 | } 19 | -------------------------------------------------------------------------------- /28-230518/02-template-details/10-conversion-deduction-fail.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | template 5 | void print_two(const T &a, const T &b) { 6 | std::cout << a << " " << b << std::endl; 7 | } 8 | 9 | int main() { 10 | print_two(std::string("hello"), "world"); 11 | // print_two<>(std::string("hello"), "world"); // compilation error: conflicting types 12 | 13 | print_two<>("hello", "world"); // ok, both are char[6] 14 | print_two<>("hello111", "world"); // not ok: char[9], char[6]. But it's ok if 'T' instead of 'const &' because 'char*'. 15 | } 16 | -------------------------------------------------------------------------------- /28-230518/02-template-details/11-double-angle-bracket.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | std::vector> x; // Invalid prior to C++11 because of >> token. 5 | } 6 | -------------------------------------------------------------------------------- /28-230518/02-template-details/20-class-alises.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using vi1 = std::vector; 5 | typedef std::vector vi2; // Like variable declaration, prepended 'typedef'. 6 | 7 | // v = std::vector; 8 | template 9 | using v = std::vector; 10 | // `using` only, not with `typedef` 11 | 12 | template 13 | using vp = std::vector>; 14 | 15 | int main() { 16 | v v; 17 | vp v2; 18 | } 19 | -------------------------------------------------------------------------------- /28-230518/02-template-details/21b-variables.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // Since C++17 5 | template 6 | T var{}; 7 | 8 | int main() { 9 | var = 10; // `var` is a name 10 | var = "hello"; 11 | 12 | std::cout << var << "\n"; 13 | std::cout << var << "\n"; 14 | } 15 | -------------------------------------------------------------------------------- /28-230518/02-template-details/TODO.md: -------------------------------------------------------------------------------- 1 | Regroup: 2 | 10 --> ../03-function-template-details 3 | `1*/2*` groups together to "interesting syntax"? or not? `11-double-angle-bracket` is out of place 4 | -------------------------------------------------------------------------------- /28-230518/03-function-template-details/TODO.md: -------------------------------------------------------------------------------- 1 | 05-deduction-fails: split into two: ambiguous base + conversions 2 | -------------------------------------------------------------------------------- /28-230518/TODO.md: -------------------------------------------------------------------------------- 1 | Approx. 1:25 in current state 2 | 3 | 01-template-friends: some parts were delivered earlier, add them back. 4 | Maybe reduce 03, everything is covered? 5 | -------------------------------------------------------------------------------- /29-230525/01-constexpr/04-ub.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | // Since C++20: vector is constexpr 5 | static_assert([]() { 6 | std::vector v; 7 | v.push_back(10); 8 | v.push_back(20); 9 | v.push_back(30); 10 | v.pop_back(); 11 | // Compiler _should_ catch UB 12 | 13 | // v.pop_back(); 14 | // v.pop_back(); 15 | // v.pop_back(); 16 | return v.size(); 17 | }() == 2); 18 | } 19 | -------------------------------------------------------------------------------- /29-230525/02-specialization/04-spec-odr-violation/README.md: -------------------------------------------------------------------------------- 1 | Specializations should be the same in all translation units! 2 | ODR otherwise, like here. 3 | 4 | If you add `inline` to function definitions, it becomes silent 5 | https://stackoverflow.com/questions/45120323/why-c-linker-is-silent-about-odr-violation 6 | 7 | Moral: do not specialialize in different headers/translation units. 8 | -------------------------------------------------------------------------------- /29-230525/02-specialization/04-spec-odr-violation/foo.cpp: -------------------------------------------------------------------------------- 1 | #include "print.h" 2 | #include 3 | 4 | // ODR and linkage error if commented: two instances of print. 5 | // ODR and linkage error if uncommented: two instances of print. 6 | #if 1 7 | template<> 8 | void print(const int &value) { 9 | std::cout << "foo " << value << "\n"; 10 | } 11 | #endif 12 | 13 | void foo() { 14 | print(2); 15 | print(2.3); 16 | } -------------------------------------------------------------------------------- /29-230525/02-specialization/04-spec-odr-violation/main.cpp: -------------------------------------------------------------------------------- 1 | #include "print_ext.h" 2 | #include 3 | 4 | void foo(); 5 | 6 | int main() { 7 | print(1); 8 | print(1.23); 9 | foo(); 10 | } 11 | -------------------------------------------------------------------------------- /29-230525/02-specialization/04-spec-odr-violation/print.h: -------------------------------------------------------------------------------- 1 | #ifndef PRINT_H_ 2 | #define PRINT_H_ 3 | 4 | #include 5 | 6 | template 7 | void print(const T &value) { 8 | std::cout << value << "\n"; 9 | } 10 | 11 | #endif // PRINT_H_ 12 | -------------------------------------------------------------------------------- /29-230525/02-specialization/04-spec-odr-violation/print_ext.h: -------------------------------------------------------------------------------- 1 | #ifndef PRINT_EXT_H_ 2 | #define PRINT_EXT_H_ 3 | 4 | #include "print.h" 5 | 6 | template<> 7 | void print(const int &value) { 8 | std::cout << "mwahaha " << value << "\n"; 9 | } 10 | 11 | #endif // PRINT_EXT_H_ 12 | -------------------------------------------------------------------------------- /29-230525/02-specialization/10-partial.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | struct is_reference { 5 | static inline const bool value = false; 6 | }; 7 | 8 | template 9 | struct is_reference { // (const U)& as well. 10 | static inline const bool value = true; 11 | }; 12 | 13 | template 14 | static const bool is_reference_v = is_reference::value; 15 | 16 | int main() { 17 | std::cout << is_reference_v << "\n"; 18 | std::cout << is_reference_v << "\n"; 19 | std::cout << is_reference_v << "\n"; 20 | } 21 | -------------------------------------------------------------------------------- /29-230525/02-specialization/11-partial-values.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | template 5 | struct conditional { 6 | using type = T; 7 | }; 8 | 9 | template 10 | struct conditional { 11 | using type = F; 12 | }; 13 | 14 | int main() { 15 | conditional<2 * 2 == 4, int, double>::type x = 10.5; 16 | conditional<2 * 2 == 5, int, double>::type y = 10.5; 17 | std::cout << x << "\n"; 18 | std::cout << y << "\n"; 19 | } 20 | -------------------------------------------------------------------------------- /29-230525/02-specialization/12-partial-fail.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | template 5 | struct foo { 6 | }; 7 | 8 | template 9 | struct foo<2 * I> { // Compilation error: cannot solve "real" equations 10 | static inline const bool value = I; 11 | }; 12 | 13 | int main() { 14 | std::cout << foo<10>::value << "\n"; 15 | } 16 | -------------------------------------------------------------------------------- /29-230525/02-specialization/13-partial-less-types.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | struct is_same { 5 | static inline const bool value = false; 6 | }; 7 | 8 | template 9 | struct is_same { 10 | static inline const bool value = true; 11 | }; 12 | 13 | template 14 | static const bool is_same_v = is_same::value; 15 | 16 | int main() { 17 | std::cout << is_same_v << "\n"; 18 | std::cout << is_same_v << "\n"; 19 | std::cout << is_same_v << "\n"; 20 | std::cout << is_same_v << "\n"; 21 | } 22 | -------------------------------------------------------------------------------- /29-230525/03-meta-conventions/00-notes.md: -------------------------------------------------------------------------------- 1 | Template meteprogramming was more "discovered" than "designed for". 2 | Hence the ugly syntax and quirks. 3 | -------------------------------------------------------------------------------- /29-230525/TODO.md: -------------------------------------------------------------------------------- 1 | Sliced with 30-230601 2 | -------------------------------------------------------------------------------- /30-230601/00-misc/01-template-lambda.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | // Since C++14 5 | auto print1 = [](auto x, auto y) { // Independent implicit template parameter for each argument. 6 | std::cout << x << " " << y << "\n"; 7 | }; 8 | print1(10, 20.0); 9 | print1(10, "hello"); 10 | 11 | // Since C++20: https://stackoverflow.com/a/54126333/767632 12 | auto print2 = [](const T &x, const T &y) { 13 | std::cout << x << " " << y << "\n"; 14 | }; 15 | print2(10, 20); 16 | // print2(10, 20.0); 17 | } 18 | -------------------------------------------------------------------------------- /30-230601/00-misc/04-type-display.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template struct TD; // "Type Display" in a compilation error 4 | 5 | int main() { 6 | TD(); 7 | TD(); 8 | 9 | std::string s; 10 | TD(); 11 | 12 | auto f = [](auto x) { 13 | TD(); 14 | }; 15 | f(10); 16 | f(10.5); 17 | } 18 | -------------------------------------------------------------------------------- /30-230601/04-variadic/01-function-variadic-template/20-value-packs.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // Template parameter pack, but of values instead of types. 4 | template 5 | constexpr std::pair sum() { 6 | return {(Ns + ...), sizeof...(Ns)}; 7 | } 8 | static_assert(sum<1, 2, 3, 4>() == std::pair(10, 4)); 9 | 10 | int main() {} 11 | -------------------------------------------------------------------------------- /30-230601/04-variadic/02-class-variadic-template/02-class-pack-expansion.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct Foo { 4 | Foo(int) {} 5 | void func(int) { std::cout << "1\n"; } 6 | }; 7 | 8 | struct Bar { 9 | Bar(int); 10 | void func(char) { std::cout << "2\n"; } 11 | }; 12 | 13 | template 14 | struct Hybrid : Ts... { // Hybrid : Foo, Bar 15 | Hybrid() : Ts(10)... {} 16 | // Hybrid() : Foo(10), Bar(10) {} 17 | using Ts::func...; // Since C++17 (TODO), not exam 18 | }; 19 | 20 | int main() { 21 | Hybrid h; 22 | // .... 23 | h.func(10); // (1) 24 | h.func('x'); // (2) 25 | } 26 | -------------------------------------------------------------------------------- /30-230601/05-perfect-forwarding/04-not-forwarding-reference.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct my_vector { 3 | void push_back_1(T &&) { // not forwarding reference: `T` is already fixed. Just rvalue reference. 4 | } 5 | 6 | template 7 | void push_back_2(U &&) { // forwarding reference: `U` is deduced when calling 8 | } 9 | }; 10 | 11 | template 12 | void foo(my_vector &&) { // not forwarding reference: argument is always rvalue, `T` cannot affect this 13 | // TODO: example for SFINAE 14 | } 15 | -------------------------------------------------------------------------------- /30-230601/05-perfect-forwarding/06-perfect-forward-callee.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct Foo { 4 | void operator()() & { 5 | std::cout << "lvalue\n"; 6 | } 7 | void operator()() && { 8 | std::cout << "rvalue\n"; 9 | } 10 | }; 11 | 12 | template 13 | void call(Fn &&fn) { 14 | std::forward(fn)(); // Rarely done in STL: it assumes functors are trivial. Should actually be done. 15 | } 16 | 17 | int main() { 18 | Foo f; 19 | f(); // lvalue 20 | Foo()(); // rvalue 21 | call(f); // lvalue 22 | call(Foo()); // should call operator() && 23 | } 24 | -------------------------------------------------------------------------------- /30-230601/05-perfect-forwarding/11-decltype-auto.cpp: -------------------------------------------------------------------------------- 1 | int x; 2 | 3 | auto foo() { // int 4 | return x; 5 | } 6 | 7 | auto &foo_ref() { // int& 8 | return x; 9 | } 10 | 11 | auto foo_ref_caller_bad() { // int 12 | return foo_ref(); 13 | } 14 | 15 | decltype(auto) foo_ref_caller_bad() { // int& 16 | return foo_ref(); 17 | } 18 | 19 | decltype(auto) bar() { // int 20 | return x; 21 | } 22 | 23 | decltype(auto) baz() { // int& 24 | return (x); 25 | } 26 | 27 | int main() { 28 | } 29 | -------------------------------------------------------------------------------- /31-230608/01-sfinae/02-sfinae-type-alias.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct BotvaHolder { 4 | using botva = int; 5 | }; 6 | 7 | template using GetBotva = typename T::botva; 8 | 9 | template 10 | void foo(T, GetBotva) { // GetBotva is an alias, substitution failure happens 'here'. 11 | std::cout << "1\n"; 12 | } 13 | 14 | template 15 | void foo(T, std::nullptr_t) { 16 | std::cout << "2\n"; 17 | } 18 | 19 | int main() { 20 | foo(BotvaHolder(), 10); // 1 21 | foo(BotvaHolder(), nullptr); // 2 22 | foo(10, nullptr); // 2 23 | // foo(10, 10); // CE 24 | } 25 | -------------------------------------------------------------------------------- /31-230608/01-sfinae/05-sfinae-no-template-variable.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct BotvaHolder { 4 | static constexpr int botva = 10; 5 | }; 6 | 7 | template struct Foo {}; 8 | 9 | template 10 | void foo(T, Foo) { // SFINAE is enabled 11 | std::cout << "1\n"; 12 | } 13 | 14 | template 15 | void foo(T, std::nullptr_t) { 16 | std::cout << "2\n"; 17 | } 18 | 19 | int main() { 20 | foo(BotvaHolder(), Foo<10>{}); // 1 21 | foo(BotvaHolder(), nullptr); // 2 22 | foo(10, nullptr); // 2 23 | // foo(10, Foo{}); // CE 24 | // foo(BotvaHolder(), Foo<11>{}); // CE 25 | } 26 | -------------------------------------------------------------------------------- /31-230608/01-sfinae/51-destructors.cpp: -------------------------------------------------------------------------------- 1 | // Destructors cannot be SFINAEd out. C++20: concepts to the rescue! 2 | // Having a destructor makes the difference between TriviallyDestructible types and others. 3 | 4 | ~Foo() noexcept(?????) { // No SFINAE even within noexcept: https://stackoverflow.com/a/33667546/767632 5 | } 6 | -------------------------------------------------------------------------------- /31-230608/02-cond-noexcept/13-cond-explicit.cpp: -------------------------------------------------------------------------------- 1 | // Since C++20: conditional `explicit` is available as well 2 | // Example: pair() is implicit iff both T() and U() are implicit 3 | 4 | // TODO 5 | template 6 | struct pair { 7 | explicit(.....) pair() {} 8 | } 9 | -------------------------------------------------------------------------------- /31-230608/02-cond-noexcept/TODO.md: -------------------------------------------------------------------------------- 1 | declval: talk before declval in sfinae 2 | -------------------------------------------------------------------------------- /31-230608/03-return-auto/04-in-declaration.a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | auto foo(); 4 | auto bar(); 5 | 6 | auto foo() { 7 | return 10; 8 | } 9 | 10 | int main() { 11 | std::cout << foo() << "\n"; 12 | // std::cout << bar() << "\n"; // compilation error: `auto` is not deduced, it's in another TU. 13 | } 14 | -------------------------------------------------------------------------------- /31-230608/03-return-auto/04-in-declaration.b.cpp: -------------------------------------------------------------------------------- 1 | auto bar(); 2 | 3 | auto bar() { 4 | return 10; 5 | } 6 | -------------------------------------------------------------------------------- /31-230608/05-blog.txt: -------------------------------------------------------------------------------- 1 | https://www.modernescpp.com/index.php/der-einstieg-in-modernes-c 2 | https://alenacpp.blogspot.com/ 3 | https://www.cppstories.com/ 4 | -------------------------------------------------------------------------------- /common/README.md: -------------------------------------------------------------------------------- 1 | * [Софт](software.md) 2 | * [Материалы](materials.md) 3 | -------------------------------------------------------------------------------- /common/TODO.md: -------------------------------------------------------------------------------- 1 | macOS: сначала установить homebrew инструменты 2 | macOS: перепроверить добавление в `PATH`, не рекомендовать gcc/clang 3 | macOS: проверить интеграцию файловой системы с виртуалками 4 | Все ОС: проверить необходимость включения виртуализации 5 | Все ОС: разделить инструкцию на две: а) фиксированный набор софта, который нужно поставить на чистую систему; б) альтернативы: что на что можно заменить, как, что можно добавить. 6 | Все ОС: возможно, предложить установку Docker, если с ним работает CLion 7 | -------------------------------------------------------------------------------- /common/checkver/.gitignore: -------------------------------------------------------------------------------- 1 | /checkver 2 | -------------------------------------------------------------------------------- /common/checkver/01-ubuntu-g++-libstdc++.txt: -------------------------------------------------------------------------------- 1 | C++ 201703 2 | 64-bit 3 | Detecting compiler... GNU C 12.0.1 4 | Detecting standard library... GNU libstdc++: 20220319 5 | -------------------------------------------------------------------------------- /common/checkver/02-ubuntu-clang++-libstdc++.txt: -------------------------------------------------------------------------------- 1 | C++ 201703 2 | 64-bit 3 | Detecting compiler... LLVM/Apple clang 14.0.0 4 | Detecting standard library... GNU libstdc++: 20220319 5 | -------------------------------------------------------------------------------- /common/checkver/03-ubuntu-clang++-libc++.txt: -------------------------------------------------------------------------------- 1 | C++ 201703 2 | 64-bit 3 | Detecting compiler... LLVM/Apple clang 14.0.0 4 | Detecting standard library... LLVM/Apple libc++: 14000 5 | -------------------------------------------------------------------------------- /common/checkver/04-ubuntu-icc-libstdc++.txt: -------------------------------------------------------------------------------- 1 | C++ 201703 2 | 64-bit 3 | Detecting compiler... Intel C++ Compiler Classic: 2021 Intel(R) C++ g++ 11.2 mode 4 | Detecting standard library... GNU libstdc++: 20220324 5 | -------------------------------------------------------------------------------- /common/checkver/10-windows-vs2022.txt: -------------------------------------------------------------------------------- 1 | C++ 199711 2 | 64-bit 3 | Detecting compiler... Microsoft Visual C++ 1933 4 | Detecting standard library... Microsoft STL: 143 at 202205 5 | -------------------------------------------------------------------------------- /common/checkver/20-macos-appleclang.txt: -------------------------------------------------------------------------------- 1 | C++ 201703 2 | 64-bit 3 | Detecting compiler... LLVM/Apple clang 13.1.6 (clang-1316.0.21.2.5) 4 | Detecting standard library... LLVM/Apple libc++: 13000 5 | -------------------------------------------------------------------------------- /common/checkver/has-cpp17.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | std::cout << "Hello World!\n"; 6 | std::vector vec{1, 2, 3, 4}; // Requires C++17. 7 | std::cout << "1 == " << vec[0] << "\n"; 8 | } 9 | -------------------------------------------------------------------------------- /common/checkver/has-cpp17.expected.txt: -------------------------------------------------------------------------------- 1 | Hello World! 2 | 1 == 1 3 | -------------------------------------------------------------------------------- /next/02-threads/05-producer-consumer/TODO.md: -------------------------------------------------------------------------------- 1 | notify() is better be under mutex: 2 | https://sourceware.org/git/?p=valgrind.git;a=blob;f=helgrind/hg_main.c;h=490fc38fefc7fd6e241ab8c592edb428933c90f4;hb=HEAD#l2421 3 | https://en.cppreference.com/w/cpp/thread/condition_variable/notify_one#Notes 4 | https://cplusplus.github.io/LWG/issue3343 5 | https://github.com/isocpp/CppCoreGuidelines/issues/1272 6 | https://github.com/isocpp/CppCoreGuidelines/issues/554#issuecomment-425687510 7 | -------------------------------------------------------------------------------- /next/13-221212/xx-patterns/02x-notes.txt: -------------------------------------------------------------------------------- 1 | Book "Design Patterns" from "Gang of Four"/GoF/"Банда четырёх" (Gamma et al): https://ru.wikipedia.org/wiki/Design_Patterns 2 | 3 | Please don't do like that: https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpriseEdition 4 | -------------------------------------------------------------------------------- /next/TODO.md: -------------------------------------------------------------------------------- 1 | float/double 2 | cout precision 3 | short circuit 4 | while init statement 5 | if init statement 6 | C-style arrays 7 | C-style strings + readWord/writeWord 8 | -------------------------------------------------------------------------------- /next/x5-meta-conventions-variadic/12-function-traits.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | template struct type_list; 5 | 6 | // We can "parse" types, like in boots::function_trai 7 | template struct function_traits {}; 8 | template 9 | struct function_traits { 10 | static constexpr std::size_t arity = sizeof...(Args); 11 | using return_type = Ret; 12 | using args = type_list; 13 | }; 14 | 15 | static_assert(std::is_void_v< 16 | function_traits::return_type 17 | >); 18 | 19 | int main() {} 20 | -------------------------------------------------------------------------------- /next/xx-functions-global-vars.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int a = 10, b = 20; 4 | 5 | void print_a() { // returns `void` (has no values), i.e. returns nothing 6 | std::cout << a << "\n"; 7 | } 8 | 9 | void print(int x) { // takes a single parameter: `x` 10 | std::cout << x << "\n"; 11 | } 12 | 13 | int sum(int a, int b) { // returns `int`, takes two parameters: `a` and `b`, just like local variables 14 | return a + b; // should always return, otherwise UB 15 | } 16 | 17 | int main() { 18 | print_a(); // 10 19 | print(5); // 5 20 | print(a + b); // 30 21 | print(sum(a, b)); // 30 22 | } 23 | -------------------------------------------------------------------------------- /questions-a/quick/01-undefined-reference/problem/main.cpp: -------------------------------------------------------------------------------- 1 | #include "triple.hpp" 2 | 3 | int main() { 4 | const Triple t{1, 2, 3}; 5 | t.print(); 6 | assert(t.sum() == 1 + 2 + 3); 7 | } 8 | -------------------------------------------------------------------------------- /questions-a/quick/01-undefined-reference/problem/triple.cpp: -------------------------------------------------------------------------------- 1 | #include "triple.hpp" 2 | 3 | void print() { 4 | std::cout << a << " " << b << " " << c << "\n"; 5 | } 6 | -------------------------------------------------------------------------------- /questions-a/quick/01-undefined-reference/problem/triple.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TRIPLE_HPP_ 2 | #define TRIPLE_HPP_ 3 | 4 | struct Triple { 5 | int a, b, c; 6 | 7 | int sum(); 8 | void print(); 9 | }; 10 | 11 | #endif // TRIPLE_HPP_ 12 | -------------------------------------------------------------------------------- /questions-a/quick/01-undefined-reference/solution/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "triple.hpp" 3 | 4 | int main() { 5 | const Triple t{1, 2, 3}; 6 | t.print(); 7 | assert(t.sum() == 1 + 2 + 3); 8 | } 9 | -------------------------------------------------------------------------------- /questions-a/quick/01-undefined-reference/solution/triple.cpp: -------------------------------------------------------------------------------- 1 | #include "triple.hpp" 2 | #include 3 | 4 | void Triple::print() const { 5 | std::cout << a << " " << b << " " << c << "\n"; 6 | } 7 | -------------------------------------------------------------------------------- /questions-a/quick/01-undefined-reference/solution/triple.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TRIPLE_HPP_ 2 | #define TRIPLE_HPP_ 3 | 4 | struct Triple { 5 | int a, b, c; 6 | 7 | int sum() const { 8 | return a + b + c; 9 | } 10 | void print() const; 11 | }; 12 | 13 | #endif // TRIPLE_HPP_ 14 | -------------------------------------------------------------------------------- /questions-a/quick/02-compile-them-all/problem/01.txt: -------------------------------------------------------------------------------- 1 | #include "b.hpp" 2 | 3 | namespace { 4 | int xx = 123; 5 | }; 6 | 7 | Bar::Bar() : x(xx) { 8 | } 9 | -------------------------------------------------------------------------------- /questions-a/quick/02-compile-them-all/problem/02.txt: -------------------------------------------------------------------------------- 1 | #ifndef A_HPP_ 2 | #define A_HPP_ 3 | 4 | #include "b.hpp" 5 | 6 | struct Foo { 7 | Bar b; 8 | int get(); 9 | }; 10 | 11 | #endif // A_HPP_ 12 | -------------------------------------------------------------------------------- /questions-a/quick/02-compile-them-all/problem/03.txt: -------------------------------------------------------------------------------- 1 | #include "a.hpp" 2 | #include 3 | 4 | int main() { 5 | Foo f; 6 | std::cout << f.get() << "\n"; 7 | } 8 | -------------------------------------------------------------------------------- /questions-a/quick/02-compile-them-all/problem/04.txt: -------------------------------------------------------------------------------- 1 | #include "a.hpp" 2 | 3 | namespace { 4 | int x = 500; 5 | } 6 | 7 | int Foo::get() { 8 | return b.x + x; 9 | } 10 | -------------------------------------------------------------------------------- /questions-a/quick/02-compile-them-all/problem/05.txt: -------------------------------------------------------------------------------- 1 | #ifndef B_HPP_ 2 | #define B_HPP_ 3 | 4 | struct Bar { 5 | int x; 6 | 7 | Bar(); 8 | }; 9 | 10 | #endif // B_HPP_ 11 | -------------------------------------------------------------------------------- /questions-a/quick/02-compile-them-all/solution/a.cpp: -------------------------------------------------------------------------------- 1 | #include "a.hpp" 2 | 3 | namespace { 4 | int x = 500; 5 | } 6 | 7 | int Foo::get() { 8 | return b.x + x; 9 | } 10 | -------------------------------------------------------------------------------- /questions-a/quick/02-compile-them-all/solution/a.hpp: -------------------------------------------------------------------------------- 1 | #ifndef A_HPP_ 2 | #define A_HPP_ 3 | 4 | #include "b.hpp" 5 | 6 | struct Foo { 7 | Bar b; 8 | int get(); 9 | }; 10 | 11 | #endif // A_HPP_ 12 | -------------------------------------------------------------------------------- /questions-a/quick/02-compile-them-all/solution/b.cpp: -------------------------------------------------------------------------------- 1 | #include "b.hpp" 2 | 3 | namespace { 4 | int xx = 123; 5 | }; 6 | 7 | Bar::Bar() : x(xx) { 8 | } 9 | -------------------------------------------------------------------------------- /questions-a/quick/02-compile-them-all/solution/b.hpp: -------------------------------------------------------------------------------- 1 | #ifndef B_HPP_ 2 | #define B_HPP_ 3 | 4 | struct Bar { 5 | int x; 6 | 7 | Bar(); 8 | }; 9 | 10 | #endif // B_HPP_ 11 | -------------------------------------------------------------------------------- /questions-a/quick/02-compile-them-all/solution/main.cpp: -------------------------------------------------------------------------------- 1 | #include "a.hpp" 2 | #include 3 | 4 | int main() { 5 | Foo f; 6 | std::cout << f.get() << "\n"; 7 | } 8 | -------------------------------------------------------------------------------- /questions-a/quick/04-struct/problem.md: -------------------------------------------------------------------------------- 1 | Реализуйте структуру `Person` с трёмя полями: имя, фамилия, программа обучения. 2 | Программа обучения - `enum class` с двумя значениями: `AMIS` и `ADAAI`. 3 | У структуры должен быть конструктор от трёх значений - исходные значения полей. 4 | -------------------------------------------------------------------------------- /questions-a/quick/04-struct/solution.cpp: -------------------------------------------------------------------------------- 1 | enum class Major { AMIS, ADAAI }; 2 | 3 | struct Person { 4 | std::string first_name, last_name; 5 | Major major; 6 | 7 | Person(std::string first_name_, std::string last_name_, Major major_) 8 | : first_name(std::move(first_name_)) 9 | , last_name(std::move(last_name_)) 10 | , major(std::move(major_)) {} 11 | }; 12 | -------------------------------------------------------------------------------- /questions-a/quick/05-multithreading/problem.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | std::deque q; 7 | 8 | std::thread t1([&]() { 9 | for (int i = 0; i < 1'000'000; i++) { 10 | q.push_back(i); 11 | } 12 | }); 13 | std::thread t2([&]() { 14 | while (!q.empty()) { 15 | std::cout << q.front() << "\n"; 16 | q.pop_front(); 17 | } 18 | }); 19 | t1.join(); 20 | t2.join(); 21 | } 22 | -------------------------------------------------------------------------------- /questions-a/quick/06-ub-iterators/problem.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | std::map m{ 6 | {1, 1000}, 7 | {2, 1000}, 8 | {3, 1000}, 9 | }; 10 | auto it = m.find(2); 11 | 12 | int x; 13 | std::cin >> x; 14 | m.erase(x); 15 | 16 | it->second++; 17 | std::cout << m[2] << "\n"; // 1001 or 1 18 | } 19 | -------------------------------------------------------------------------------- /questions-a/quick/06-ub-iterators/solution.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | std::map m{ 6 | {1, 1000}, 7 | {2, 1000}, 8 | {3, 1000}, 9 | }; 10 | 11 | int x; 12 | std::cin >> x; 13 | m.erase(x); 14 | 15 | m[2]++; 16 | std::cout << m[2] << "\n"; // 1001 or 1 17 | } 18 | -------------------------------------------------------------------------------- /questions-a/quick/07-ub-erase/problem.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | std::map m{ 6 | {1, 100}, 7 | {2, 101}, 8 | {3, 102}, 9 | }; 10 | for (auto [key, value] : m) { 11 | if (key % 2 == 0) { 12 | m.erase(key); 13 | } 14 | } 15 | std::cout << m.size() << "\n"; 16 | } 17 | -------------------------------------------------------------------------------- /questions-a/quick/07-ub-erase/solution.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | std::map m{ 6 | {1, 100}, 7 | {2, 101}, 8 | {3, 102}, 9 | }; 10 | for (auto it = m.begin(); it != m.end();) { 11 | if (it->first % 2 == 0) { 12 | it = m.erase(it); 13 | } else { 14 | ++it; 15 | } 16 | } 17 | std::cout << m.size() << "\n"; 18 | } 19 | -------------------------------------------------------------------------------- /questions-a/quick/08-functions/problem.cpp: -------------------------------------------------------------------------------- 1 | long long mul(int a, int b) { 2 | return a * b; 3 | } 4 | 5 | void sum(int a, int b) { 6 | a + b; 7 | } 8 | 9 | void assign(int &a, int &b) { 10 | a = b; 11 | } 12 | -------------------------------------------------------------------------------- /questions-a/quick/README.md: -------------------------------------------------------------------------------- 1 | * Оффлайн, на ноутбуках 2 | * Билетов нет, выдаются упражнения в репозиторий `labs-blabla`. 3 | * В начале включаете запись экрана + камеры в OBS 4 | * 1 час, `K` упражнений (в том числе индивидуальные), нужно выполнить ~80% 5 | * Решение упражнения: текст или ответы да/нет (гуглоформа). 6 | * Гуглить можно, общаться нельзя. 7 | * Будет кто-то в аудитории, кому можно задавать вопросы. Или мне онлайн. 8 | * В конце: останавливаете запись, считаете хэш (`sha256sum`), отправляете форму. 9 | Вечером: загружаете запись на диск. 10 | --------------------------------------------------------------------------------