{"id":13631582,"url":"https://github.com/rachitiitr/modern-cpp-tricks","last_synced_at":"2025-04-04T10:07:25.557Z","repository":{"id":42719204,"uuid":"372942411","full_name":"rachitiitr/modern-cpp-tricks","owner":"rachitiitr","description":"Modern CPP Tricks often useful in Coding Interviews and Competitive Programming","archived":false,"fork":false,"pushed_at":"2024-03-16T07:29:56.000Z","size":11,"stargazers_count":705,"open_issues_count":2,"forks_count":62,"subscribers_count":14,"default_branch":"main","last_synced_at":"2025-03-28T09:06:18.838Z","etag":null,"topics":["coding-interviews","competitive-programming","cpp","tips-and-tricks"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rachitiitr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-06-01T19:36:32.000Z","updated_at":"2025-03-27T11:00:29.000Z","dependencies_parsed_at":"2024-08-01T22:39:50.627Z","dependency_job_id":"d721be5a-5914-4215-b60f-cdf5c7807a54","html_url":"https://github.com/rachitiitr/modern-cpp-tricks","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rachitiitr%2Fmodern-cpp-tricks","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rachitiitr%2Fmodern-cpp-tricks/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rachitiitr%2Fmodern-cpp-tricks/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rachitiitr%2Fmodern-cpp-tricks/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rachitiitr","download_url":"https://codeload.github.com/rachitiitr/modern-cpp-tricks/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247157101,"owners_count":20893214,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["coding-interviews","competitive-programming","cpp","tips-and-tricks"],"created_at":"2024-08-01T22:02:30.695Z","updated_at":"2025-04-04T10:07:25.519Z","avatar_url":"https://github.com/rachitiitr.png","language":null,"readme":"## Introduction  \u003c!-- omit in toc --\u003e\nThis is the list of modern CPP tricks often used in Coding Interviews and Competitive Programming.  \nIf you like Rachit's work, you can follow at - \n- Discord - https://bit.ly/discord-rachit\n- Programming YouTube Channel - https://bit.ly/rachityoutube\n\n## Contents: \u003c!-- omit in toc --\u003e\n- [No more nested `min(x, min(y, ...))`](#no-more-nested-minx-miny-)\n- [JavaScript like Destructuring using Structured Binding in C++](#javascript-like-destructuring-using-structured-binding-in-c)\n- [Powerful Logging and Debugging](#powerful-logging-and-debugging)\n  - [How debug macros work?](#how-debug-macros-work)\n  - [The Problem with this macro - its not scalable](#the-problem-with-this-macro---its-not-scalable)\n  - [Solution using a powerful macro](#solution-using-a-powerful-macro)\n- [Generic Reader and Writer for multiple variables and containers](#generic-reader-and-writer-for-multiple-variables-and-containers)\n  - [Usage](#usage)\n- [Decorators in C++ and Multiple Parameters](#decorators-in-c-and-multiple-parameters)\n  - [Live Demo on YouTube](#live-demo-on-youtube)\n  - [Printing as many variables in one line](#printing-as-many-variables-in-one-line)\n  - [Powerful decorator functions in C++](#powerful-decorator-functions-in-c)\n  - [Exploiting decorators by nesting them](#exploiting-decorators-by-nesting-them)\n- [Sets and Maps Tricks](#sets-and-maps-tricks)\n  - [`s.contains` vs `s.find(...) != s.end`](#scontains-vs-sfind--send)\n  - [`multiset.extract` vs `multiset.erase(multiset.find(...))`](#multisetextract-vs-multiseterasemultisetfind)\n\n\n## No more nested `min(x, min(y, ...))`\nUse initializer list and `std::min` and `std::max` to make life easy\n```cpp\nsmall = min(x, min(y, min(z, k))); // the old way\nsmall = min({x, y, z, k}); // life is easy\n```\n\n## JavaScript like Destructuring using Structured Binding in C++\n```cpp\npair\u003cint, int\u003e cur = {1, 2};\nauto [x, y] = cur;\n// x is now 1, y is now 2\n// no need of cur.first and cur.second\n\narray\u003cint, 3\u003e arr = {1, 0, -1};\nauto [a, b, c] = arr;\n// a is now 1, b is now 0, c is now -1\n```\n\n\n----------------\n\n\n## Powerful Logging and Debugging\n\n### How debug macros work?\nStraight to the point, I have often used the `debug` macro which stringifies the variable names and their values.\n\n```cpp\n#define deb(x) cout \u003c\u003c #x \u003c\u003c \" \" \u003c\u003c x \nint ten = 10;\ndeb(ten); // prints \"ten = 10\"\n```\n\nThis is often useful in debugging.\n\n### The Problem with this macro - its not scalable\nHowever, when you have multiple variables to log, you end up with more `deb2` and `deb3` macros.\n\n```cpp\n#define deb(x) cout \u003c\u003c #x \u003c\u003c \" \" \u003c\u003c x \n#define deb2(x) cout \u003c\u003c #x \u003c\u003c \" \" \u003c\u003c x \u003c\u003c \" \"  \u003c\u003c #y \u003c\u003c \" \" \u003c\u003c y \n#define deb3(x, y, z) cout \u003c\u003c #x \u003c\u003c \" \" \u003c\u003c x \u003c\u003c \" \"  \u003c\u003c #y \u003c\u003c \" \" \u003c\u003c y \u003c\u003c \" \"  \u003c\u003c #z \u003c\u003c \" \" \u003c\u003c z \n```\n\nThis is not scalable.\n\n### Solution using a powerful macro\nHere is the solution using variadic macros and fold expressions,\n\n```cpp\n#define deb(...) logger(#__VA_ARGS__, __VA_ARGS__)\ntemplate\u003ctypename ...Args\u003e\nvoid logger(string vars, Args\u0026\u0026... values) {\n    cout \u003c\u003c vars \u003c\u003c \" = \";\n    string delim = \"\";\n    (..., (cout \u003c\u003c delim \u003c\u003c values, delim = \", \"));\n}\n\nint xx = 3, yy = 10, xxyy = 103;\ndeb(xx); // prints \"xx = 3\"\ndeb(xx, yy, xxyy); // prints \"xx, yy, xxyy = 3, 10, 103\"\n```\n\n\n----------------\n\n\n## Generic Reader and Writer for multiple variables and containers\n```cpp\ntemplate \u003ctypename... T\u003e\nvoid read(T \u0026...args) {\n    ((cin \u003e\u003e args), ...);\n}\n\ntemplate \u003ctypename... T\u003e\nvoid write(string delimiter, T \u0026\u0026...args) {\n    ((cout \u003c\u003c args \u003c\u003c delimiter), ...);\n}\n\ntemplate \u003ctypename T\u003e\nvoid readContainer(T \u0026t) {\n    for (auto \u0026e : t) {\n        read(e);\n    }\n}\n\ntemplate \u003ctypename T\u003e\nvoid writeContainer(string delimiter, T \u0026t) {\n    for (const auto \u0026e : t) {\n        write(delimiter, e);\n    }\n    write(\"\\n\");\n}\n```\n### Usage\n```cpp\n// Question: read three space seprated integers and print them in different lines.\n\tint x, y, z;\n\tread(x, y, z);\n\twrite(\"\\n\", x, y, z);\n\t\n// even works with variable data types :)\n\tint n;\n\tstring s;\n\tread(n, s);\n\twrite(\" \", s, \"has length\", n, \"\\n\");\n\t\n// Question: read an array of `N` integers and print it to the output console.\n\tint N;\n\tread(N);\n\tvector\u003cint\u003e arr(N);\n\treadContainer(arr);\n\twriteContainer(\" \", arr); // output: arr[0] arr[1] arr[2] ... arr[N - 1]\n\twriteContainer(\"\\n\", arr);\n\t/**\n\t* output:\n\t* arr[0]\n\t* arr[1]\n\t* arr[2]\n\t* ...\n\t* ...\n\t* ...\n\t* arr[N - 1]\n\t*/\n```\n\n\n----------------\n\n\n## Decorators in C++ and Multiple Parameters\n\n### Live Demo on YouTube\n- Check the online demo on YouTube [here on Rachit's channel](https://www.youtube.com/watch?v=ZhWyNjPGXD4).\n\n\n### Printing as many variables in one line\n```cpp\ntemplate\u003ctypename ...T\u003e\nvoid printer(T\u0026\u0026... args) {\n    ((cout \u003c\u003c args \u003c\u003c \" \"), ...);\n}\n\nint age = 25;\nstring name = \"Rachit\";\nprinter(\"I am\", name, ',', age, \"years old\"); \n// ^ This prints the following\n// I am Rachit, 25 years old\n```\n\n### Powerful decorator functions in C++\n```cpp\ntemplate\u003ctypename F\u003e\nauto debug_func(const F\u0026 func) {\n    return [func](auto \u0026\u0026...args) { // forward reference\n        cout \u003c\u003c \"input = \";\n        printer(args...);\n        auto res = func(forward\u003cdecltype(args)\u003e(args)...);\n        cout \u003c\u003c \"res = \" \u003c\u003c res \u003c\u003c endl;\n        return res;\n    };\n}\n\ndebug_func(pow)(2, 3);\n// ^ this automatically prints\n// input = 2 3 res = 8\n```\n\n### Exploiting decorators by nesting them\nLets define another decorator `beautify` as follows.\n```cpp\ntemplate\u003ctypename F\u003e\nauto beautify(const F\u0026 func) {\n    return [func](auto \u0026\u0026...args) { // forward reference\n        cout \u003c\u003c \"========\" \u003c\u003c endl;\n        func(forward\u003cdecltype(args)\u003e(args)...);\n        cout \u003c\u003c \"========\" \u003c\u003c endl;\n    };\n}\n\nbeautify(debug_func(pow(2, 3)));\n// ^ this now prints\n// ========\n// input = 2 3 res = 8\n// ========\n```\nIts amazing how much you can do by writing such generic decorators and nest them.  \nThink about decorators like `log_time` that calculates the time taken for a given function.\n\n## Sets and Maps Tricks\n\n### `s.contains` vs `s.find(...) != s.end`\n```\nset\u003cint\u003e example{1, 2, 3, 4};\nexample.find(3) != example.end() // true\nexample.contains(3) // true\n```\n\nNote that this works with `map` as well as `set`.\n\n### `multiset.extract` vs `multiset.erase(multiset.find(...))`\n```\nmultiset\u003cint\u003e mset{1, 1, 2, 2, 3, 3};\nmset.erase(1); // {2, 2, 3, 3} deleted all 1s\nmset.erase(mset.find(2)) // {2, 3, 3} need to use erase + find\nmset.extract(3) // {2, 3} simple and clean\n```\n\n* `multiset::extract` helps remove single instance naturally.\n* Note this also works with normal `set` and `map`.\n* It returns a node handle ","funding_links":[],"categories":["Others"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frachitiitr%2Fmodern-cpp-tricks","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frachitiitr%2Fmodern-cpp-tricks","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frachitiitr%2Fmodern-cpp-tricks/lists"}