├── .github └── workflows │ └── c-cpp.yml ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── c ├── .gitignore ├── 11.c ├── 99.c ├── Makefile ├── README.md ├── ansi.c ├── libc.c ├── tr.c └── tricks.c ├── cpp ├── .clang-format ├── .gitignore ├── .vscode │ ├── settings.json │ └── tasks.json ├── 03.cpp ├── 11.cpp ├── 14.cpp ├── 17.cpp ├── 20.cpp ├── CMakeLists.txt ├── Doxyfile ├── Makefile ├── README.md ├── core_guidelines.cc ├── features.cpp ├── patterns.cpp ├── patterns.dot └── visitor.html ├── doxygen-awesome.css ├── js ├── 10.js ├── 6.js ├── 7.js ├── 8.js ├── 9.js ├── Makefile ├── README.md ├── test-node.js └── test.html ├── python ├── 2.3.py ├── 2.4.py ├── 2.5.py ├── 2.6.py ├── 2.7.py ├── 3.0.py ├── 3.1.py ├── 3.2.py ├── 3.3.py ├── 3.4.py ├── 3.5.py ├── 3.6.py ├── 3.7.py ├── 3.8.py ├── 3.9.py ├── Makefile ├── README.md ├── passed.py └── pythonX-install.sh ├── rust ├── .gitignore ├── .vscode │ └── tasks.json ├── Cargo.toml ├── Makefile └── src │ ├── .gitignore │ ├── Makefile │ └── main.rs └── sprof ├── .gitignore ├── Makefile ├── libdemo.c ├── prog.c └── runme.sh /.github/workflows/c-cpp.yml: -------------------------------------------------------------------------------- 1 | name: C/C++ CI 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | pull_request: 7 | branches: [ "main" ] 8 | 9 | jobs: 10 | 11 | build: 12 | 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v3 17 | - name: configure 18 | run: sudo apt-get update; sudo apt-get install -y musl-tools 19 | - name: make 20 | run: pwd;ls;make 21 | - name: make check 22 | run: make check 23 | - name: make distcheck 24 | run: make distcheck || true 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | $(MAKE) -C cpp 3 | $(MAKE) -C c 4 | $(MAKE) -C js 5 | 6 | check: 7 | $(MAKE) $@ -C cpp 8 | $(MAKE) $@ -C c 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Minimal working examples by release 2 | 3 | This project is collection of 4 | [minimal, complete, and verifiable examples](https://stackoverflow.com/help/mcve) 5 | of several languages ordered by release or version number. 6 | 7 | * [Python](python/README.md) 8 | * [ECMAScript / JavaScript](js/README.md) 9 | * [C++](cpp/README.md) 10 | * [C](c/README.md) 11 | 12 | ## Features 13 | * Minimal and practical self descriptive as possible source code. 14 | (Please read references for explanations) 15 | * Complete and ready to copy-paste into an your application. 16 | * Runnable in-place. (No need to copy paste snippets from documentation 17 | into an interpreter) 18 | * Verifiable. Internal tests provides reliability and durability. You can easily add 19 | new features and run tests to assure code validity. 20 | 21 | Files of the project are compact source code with examples of new features. 22 | You can compile and run examples to prove correctness and validation. 23 | 24 | Contributions are welcome! 25 | -------------------------------------------------------------------------------- /c/.gitignore: -------------------------------------------------------------------------------- 1 | tr 2 | libc 3 | ansi 4 | 99 5 | -------------------------------------------------------------------------------- /c/11.c: -------------------------------------------------------------------------------- 1 | _Static_assert(__STDC_VERSION__ > 201100, ""); 2 | 3 | /** 4 | @file 5 | @brief C11 6 | 7 | [C11 @ wikipedia](https://en.wikipedia.org/wiki/C11_(C_standard_revision)) 8 | 9 | [C11 gcc status](https://gcc.gnu.org/wiki/C11Status) 10 | 11 | */ 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #if !__STDC_NO_THREADS__ 19 | #include 20 | 21 | /** 22 | 23 | https://en.cppreference.com/w/c/thread 24 | 25 | https://www.gnu.org/software/libc/manual/html_node/ISO-C-Threads.html 26 | */ 27 | 28 | int run(void *arg) 29 | { 30 | *(int *)arg = 1; 31 | } 32 | 33 | int thrd_passed; 34 | 35 | _Static_assert(thrd_success == 0, ""); 36 | 37 | void thrd_test() 38 | { 39 | thrd_t thread; 40 | int res; 41 | int passed = 0; 42 | res = thrd_create(&thread, run, &passed); 43 | assert(!res); 44 | assert(res == thrd_success); 45 | 46 | thrd_join(thread, NULL); 47 | assert(passed); 48 | } 49 | 50 | #else 51 | 52 | #pragma message "thrd_test skipped" 53 | void thrd_test() 54 | { 55 | } 56 | 57 | #endif 58 | 59 | #define cbrt(x) _Generic((x), long double: cbrtl, \ 60 | default: cbrt, \ 61 | float: cbrtf)(x) 62 | 63 | int main() 64 | { 65 | assert(__STDC_VERSION__ > 201100); 66 | atomic_int acnt; 67 | ++acnt; // is thread safe 68 | assert(cbrt(1.1 * 1.1 * 1.1) == 1.1); 69 | assert(cbrt(8) == 2); 70 | thrd_test(); 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /c/99.c: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | @brief C99 4 | 5 | [C99 @ wikipedia](https://en.wikipedia.org/wiki/C99) 6 | 7 | [C99 gcc status](https://gcc.gnu.org/c99status.html) 8 | */ 9 | 10 | #include 11 | 12 | // C++ comment 13 | 14 | int main() 15 | { 16 | assert(__STDC_VERSION__ > 199900); 17 | struct xy { int x, y; }; 18 | struct nest { struct xy nested; }; 19 | 20 | struct nest n = { .nested.x = 0 }; 21 | struct xy out_of_order = { .y = 1, .x = 2 }; 22 | struct xy mixed = { .x = 1, 2 }; 23 | int array[3] = { [1] = 5 }; 24 | 25 | { } 26 | int declaration_after_statement; 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /c/Makefile: -------------------------------------------------------------------------------- 1 | all: tr ansi 99 libc 11 tricks 2 | 3 | CFLAGS+=-Wpedantic 4 | CFLAGS+=-Wextra -Wno-missing-field-initializers 5 | 6 | tr: CFLAGS+=-std=c89 -Wtraditional 7 | ansi: CFLAGS+=-ansi 8 | 99: CFLAGS+=-std=c99 9 | 11: CFLAGS+=-std=c11 10 | 11: CC=musl-gcc 11 | tricks: CFLAGS+=-g -Og -fsanitize=leak -fno-omit-frame-pointer -Wno-format 12 | 13 | check: all 14 | ./tr 15 | ./ansi 16 | ./99 17 | ./libc 18 | ./11 19 | ./tricks 20 | @echo $@ finished 21 | -------------------------------------------------------------------------------- /c/README.md: -------------------------------------------------------------------------------- 1 | # C features examples by standard version 2 | * [C11, ISO 9899:2011](11.c) 3 | * [libc example](libc.c) 4 | * [C99, ISO 9899:1999](99.c) 5 | * [ANSI C / C89, ISO 9899:199409](ansi.c) 6 | * [Legacy "Traditional"](tr.c) 7 | 8 | References 9 | * [Language Standards Supported by GCC](https://gcc.gnu.org/onlinedocs/gcc/Standards.html) 10 | * [Incompatibilities of GCC](https://gcc.gnu.org/onlinedocs/gcc/Incompatibilities.html) 11 | -------------------------------------------------------------------------------- /c/ansi.c: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | @brief ANSI C 4 | 5 | [ANSI C @ wikipedia](https://en.wikipedia.org/wiki/ANSI_C) 6 | 7 | http://ee.hawaii.edu/~tep/EE160/Book/chapapx/node7.html 8 | 9 | https://developerinsider.co/difference-between-c-and-ansi-c/ 10 | 11 | */ 12 | 13 | #include 14 | 15 | function_returns_int() 16 | { 17 | return 0; 18 | } 19 | 20 | void proc() 21 | { 22 | } 23 | 24 | int main() 25 | { 26 | { 27 | struct xy { int x, y; }; 28 | struct line { struct xy a, b; }; 29 | struct line c = {1, }; /* instead memset */ 30 | assert(c.a.x); 31 | assert(!c.b.y); 32 | } 33 | { 34 | char s[10] = {'a', }; 35 | assert(!s[9]); 36 | } 37 | { 38 | signed char negative = -127; 39 | assert(negative < 0); 40 | } 41 | { 42 | long double ld; 43 | assert(sizeof ld == 16); 44 | } 45 | { 46 | const c = 1; 47 | assert(c); 48 | } 49 | { 50 | enum { e0, e1 } e; 51 | e = e1; 52 | assert(!e0); 53 | assert(e); 54 | } 55 | assert(!function_returns_int()); 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /c/libc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int cmp(const void *p1, const void *p2) 7 | { 8 | return *(int *)p1 - *(int *)p2; 9 | } 10 | 11 | void sort_libc() 12 | { 13 | int list[] = {3, 1, 2}; 14 | 15 | qsort(list, 3, sizeof list[0], cmp); 16 | assert(list[0] == 1); 17 | assert(list[2] == 3); 18 | } 19 | 20 | int main() 21 | { 22 | sort_libc(); 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /c/tr.c: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | @brief "Traditional" C, before books of K&R 4 | 5 | https://gcc.gnu.org/onlinedocs/cpp/Traditional-warnings.html 6 | 7 | See also: 8 | * [K&R_C](https://en.wikipedia.org/wiki/K%26R_C) 9 | 10 | */ 11 | 12 | #include 13 | 14 | int max(); 15 | 16 | max(a, b) 17 | int a, b; 18 | { 19 | return a > b ? a : b; 20 | } 21 | 22 | int main() 23 | { 24 | long int li; 25 | unsigned u = -1; 26 | struct { int x, y; } s; 27 | 28 | memset(&s, 0, sizeof s); 29 | u -= 1; 30 | (void) u; 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /c/tricks.c: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | @brief C tricks 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define STRINGIFY_(arg) #arg 13 | #define STRINGIFY(arg) STRINGIFY_(arg) 14 | 15 | struct open_array { 16 | int len; 17 | int str[]; 18 | }; 19 | 20 | void integer_tricks() 21 | { 22 | // convert to boolean or bit 23 | static_assert(!! 0 == 0); 24 | static_assert((!! 123) == 1); 25 | 26 | // logical not 27 | static_assert((!!! 0) == 1); 28 | static_assert(!!! 123 == 0); 29 | 30 | // implicit "if else" with side effect 31 | static_assert(!((0 && 0) || 0)); 32 | static_assert((0 && 0) || 1); 33 | static_assert(!(0 && 1 || 0)); 34 | static_assert(0 && 1 || 1); 35 | static_assert(!(1 && 0 || 0)); 36 | static_assert(1 && 0 || 1); 37 | static_assert(1 && 1 || 1/0); 38 | } 39 | 40 | void swaps() 41 | { 42 | int a = 1, b = 2; 43 | 44 | a ^= b, b ^= a, a ^= b; 45 | assert(a == 2 && b == 1); 46 | 47 | a = a + b - (b = a); 48 | assert(a == 1 && b == 2); 49 | 50 | a ^= b ^= a ^= b; 51 | assert(a == 2 && b == 1); 52 | } 53 | 54 | struct itos_ { 55 | char str[12]; /* more than length of INT_MAX */ 56 | }; 57 | 58 | /** 59 | https://en.cppreference.com/w/c/language/lifetime 60 | */ 61 | 62 | static inline struct itos_ itos(int i) 63 | { 64 | struct itos_ s; 65 | (void)snprintf(s.str, sizeof(s.str), "%d", i); 66 | return s; 67 | } 68 | 69 | int main() 70 | { 71 | assert(0 == strcmp(STRINGIFY(123), "123")); 72 | 73 | integer_tricks(); 74 | swaps(); 75 | 76 | // inline automatic pointer to integer 77 | assert(*(int[]){1} == 1); 78 | setsockopt(0, 0, 0, (int[]){1}, sizeof(int)); 79 | 80 | int a, b; 81 | 82 | // https://en.cppreference.com/w/c/language/operator_other 83 | // https://en.wikipedia.org/wiki/Comma_operator 84 | 85 | // Avoiding compound statement 86 | if (1) 87 | a = 1, b = 2, assert(1); 88 | assert(a == 1 && b == 2); 89 | 90 | // void function can be part of comma operator 91 | b = (0, assert(1), 2, 3); 92 | 93 | assert(b == 3); 94 | 95 | // Avoiding use of strlen 96 | int i; 97 | char s[] = "abc"; 98 | for (i = 0; s[i]; i++); 99 | assert(i == 3); 100 | 101 | assert(0 == strcmp("1234", itos(1234).str)); 102 | //memory leak: assert(0 > strcmp(itos(123).str, itos(456).str)); 103 | 104 | char *dynamic = NULL; 105 | int num = sscanf("discarded dynamic 1", "%*s %ms %d", &dynamic, &i); 106 | assert(num == 2); 107 | assert(i == 1); 108 | assert(dynamic); 109 | assert(! strcmp(dynamic, "dynamic")); 110 | // no need to call free(dynamic); 111 | 112 | assert((i = 2) == 2); // assign and use 113 | 114 | int x = 3; 115 | while( x --> 0 ); // 2 1 0 116 | } 117 | 118 | /** 119 | @file 120 | 121 | References: 122 | 123 | https://www.techbeamers.com/top-c-programming-tips-and-tricks-for-you/ 124 | 125 | https://stackoverflow.com/questions/599365/what-is-your-favorite-c-programming-trick?answertab=votes#tab-top 126 | 127 | */ 128 | -------------------------------------------------------------------------------- /cpp/.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: WebKit 2 | -------------------------------------------------------------------------------- /cpp/.gitignore: -------------------------------------------------------------------------------- 1 | 11 2 | 14 3 | 17 4 | 98 5 | CMakeCache.txt 6 | CMakeFiles 7 | cmake_install.cmake 8 | html 9 | -------------------------------------------------------------------------------- /cpp/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "makefile.extensionOutputFolder": "./.vscode", 3 | "C_Cpp.default.configurationProvider": "ms-vscode.makefile-tools" 4 | } -------------------------------------------------------------------------------- /cpp/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "shell", 6 | "label": "Build", 7 | "command": "make", 8 | "detail": "Build C++ examples with default make", 9 | "problemMatcher": { 10 | "owner": "cpp", 11 | "fileLocation": [ 12 | "relative", 13 | "${workspaceFolder}" 14 | ], 15 | "pattern": 16 | { 17 | "regexp": "^\\w+: ([^[]*):(\\d+):\\s+(.*)$", 18 | "file": 1, 19 | "line": 2, 20 | "message": 3 21 | } 22 | }, 23 | "group": { 24 | "kind": "build", 25 | "isDefault": true 26 | } 27 | }, 28 | { 29 | "type": "shell", 30 | "label": "Clean", 31 | "command": "make", 32 | "args": [ "clean" ], 33 | "group": "build" 34 | }, 35 | { 36 | "type": "shell", 37 | "label": "Test coverage", 38 | "detail": "Find untested code with gcov", 39 | "command": "make coverage", 40 | "group": "build", 41 | "problemMatcher": { 42 | "owner": "cpp", 43 | "fileLocation": [ 44 | "relative", 45 | "${workspaceFolder}" 46 | ], 47 | "pattern": { 48 | "regexp": "^(.*):(\\d+):\\s+(.*)$", 49 | "file": 1, 50 | "line": 2, 51 | "message": 3 52 | } 53 | } 54 | } 55 | ] 56 | } 57 | -------------------------------------------------------------------------------- /cpp/03.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | @brief C++03 / C++98 4 | 5 | @defgroup CPP03 C++03 examples 6 | @brief C++03 / C++98 7 | 8 | https://en.wikipedia.org/wiki/C++03 9 | 10 | @{ 11 | */ 12 | 13 | #include 14 | 15 | using namespace std; 16 | 17 | /** 18 | @defgroup lang03 Language 19 | @{ 20 | 21 | */ 22 | 23 | void init_03() 24 | { 25 | 26 | // https://en.cppreference.com/w/cpp/language/copy_initialization 27 | int x3 = { 3 }; 28 | double x4 = { 3.0 }; 29 | 30 | struct point { 31 | int x, y; 32 | }; 33 | 34 | point p1 = { 1, 2 }; 35 | (void)p1.x; 36 | (void)p1.y; 37 | 38 | #if gcc_extension 39 | // designated initializers 40 | // https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html 41 | __extension__ point gpp_ext = { .x = 1 }; // C99-like gcc extension 42 | __extension__ point gcc_ext = { x : 1 }; // C-like gcc extension 43 | #endif 44 | 45 | // Mutable 46 | struct struct_with_mutable { 47 | struct_with_mutable() {}; 48 | mutable int m; 49 | } const const_struct_with_mutable; 50 | const_struct_with_mutable.m = 2; 51 | assert(const_struct_with_mutable.m == 2); 52 | int y = 0; 53 | int& reference = y; 54 | reference = 1; 55 | assert(y == 1); 56 | } 57 | 58 | /** 59 | [set](https://en.cppreference.com/w/cpp/container/set) 60 | 61 | [map](https://en.cppreference.com/w/cpp/container/map) 62 | 63 | [multimap](https://en.cppreference.com/w/cpp/container/multimap) 64 | */ 65 | 66 | void associative_containers_03() 67 | { 68 | set s; 69 | s.insert(1); 70 | s.insert(2); 71 | assert(*s.find(1) == 1); 72 | assert(s.find(3) == s.end()); 73 | 74 | map m; 75 | m['a'] = 1; 76 | m.insert(make_pair('b', 2)); 77 | ++m['a']; 78 | assert(m['a'] == 2); 79 | 80 | multimap mm; 81 | mm.insert(make_pair('c', 1)); 82 | mm.insert(make_pair('b', 2)); 83 | mm.insert(make_pair('a', 3)); 84 | mm.insert(make_pair('a', 4)); 85 | multimap::iterator i = mm.find('a'); 86 | assert(i->second == 3); 87 | i++; 88 | assert(i->second == 4); 89 | i++; 90 | assert(i->first == 'b'); 91 | assert(i->second == 2); 92 | } 93 | 94 | template 95 | void test_generic_container(C& c) 96 | { 97 | assert(c.empty()); 98 | assert(c.max_size() > 1000); 99 | c.push_back(0); 100 | assert(c.front() == 0); 101 | assert(c.back() == 0); 102 | assert(c.size() == 1); 103 | c.push_back(1); 104 | c.push_back(2); 105 | c.push_back(3); 106 | assert(c.size() == 4); 107 | for (typename C::iterator i = c.begin(); i != c.end();) { 108 | if (*i == 1) { 109 | i = c.erase(i); 110 | continue; 111 | } 112 | if (*i == 2) { 113 | c.erase(i++); 114 | continue; 115 | } 116 | ++i; 117 | } 118 | assert(c.size() == 2); 119 | assert(c.front() == 0); 120 | assert(c.back() == 3); 121 | c.assign(4, 1); 122 | assert(c.size() == 4); 123 | c.clear(); 124 | } 125 | 126 | template 127 | void test_vector_container(V& v) 128 | { 129 | string err; 130 | try { 131 | v.at(666) = 0; 132 | } catch (out_of_range const& exc) { 133 | err = exc.what(); 134 | } 135 | assert(err.length()); 136 | assert(v[0] == 1); 137 | v.resize(4); 138 | 139 | int arr[] = { 1, 2, 3 }; 140 | v.insert(v.begin(), arr, arr + 3); 141 | assert(v[1] == 2); 142 | } 143 | 144 | /// [container](https://en.cppreference.com/w/cpp/container) 145 | 146 | void container_03() 147 | { 148 | list l; 149 | test_generic_container(l); 150 | 151 | vector v; 152 | test_generic_container(v); 153 | test_vector_container(v); 154 | 155 | v.reserve(10); 156 | assert(v.capacity() == 10); 157 | 158 | deque d; 159 | test_generic_container(d); 160 | test_vector_container(d); 161 | 162 | stack s; 163 | s.push(1); 164 | assert(s.top() == 1); 165 | s.push(2); 166 | assert(s.top() == 2); 167 | s.pop(); 168 | assert(s.top() == 1); 169 | s.pop(); 170 | assert(s.empty()); 171 | 172 | queue q; 173 | q.push(1); 174 | q.push(2); 175 | assert(q.front() == 1); 176 | assert(q.back() == 2); 177 | q.pop(); 178 | assert(q.front() == 2); 179 | q.pop(); 180 | assert(q.empty()); 181 | 182 | priority_queue pq; 183 | pq.push(2); 184 | pq.push(3); 185 | pq.push(1); 186 | assert(pq.top() == 3); 187 | 188 | associative_containers_03(); 189 | } 190 | 191 | /** 192 | @fn void sort_03() 193 | http://www.cplusplus.com/reference/algorithm/sort/?kw=sort 194 | 195 | Compare with @ref lambda::sort_11 and @ref sort_libc 196 | */ 197 | 198 | /// @private 199 | bool func(int i, int j) { return i < j; } 200 | 201 | /// @private 202 | struct _ { 203 | bool operator()(int i, int j) { return i < j; } 204 | } functor; 205 | 206 | void sort_03() 207 | { 208 | int a[] = { 5, 7, 4, 2, 8, 6, 1, 9, 0, 3 }; 209 | list list(a, a + sizeof a / sizeof a[0]); 210 | list.sort(); 211 | 212 | vector v(a, a + sizeof a / sizeof a[0]); 213 | 214 | // using default comparison (operator <): 215 | sort(v.begin(), v.begin() + 4); 216 | 217 | // using function as comp 218 | sort(v.begin() + 4, v.end(), func); 219 | 220 | // sort using a standard library compare function object 221 | sort(v.begin(), v.end(), greater()); 222 | 223 | // using object as comp 224 | sort(v.begin(), v.end(), functor); 225 | 226 | int prev = -1; 227 | for (vector::iterator i = v.begin(); i != v.end(); ++i) { 228 | assert(*i >= prev); 229 | prev = *i; 230 | } 231 | } 232 | 233 | /// [algorithm](https://en.cppreference.com/w/cpp/algorithm) 234 | 235 | void algo_03() 236 | { 237 | int a[] = { 1, 2, 3 }; 238 | vector v(a, a + sizeof a / sizeof a[0]); 239 | vector r(sizeof a / sizeof a[0]); 240 | reverse_copy(v.begin(), v.end(), r.begin()); 241 | assert(r[0] > r[1]); 242 | 243 | sort_03(); 244 | } 245 | 246 | /// [reference](https://en.cppreference.com/w/cpp/language/reference) 247 | int& a_ref(int& a) { return a; } 248 | 249 | struct Common { 250 | int n; 251 | Common(int x) 252 | : n(x) 253 | { 254 | } 255 | }; 256 | 257 | /// [ref](https://en.cppreference.com/w/cpp/language/virtual) 258 | struct Virtual_A : virtual Common { 259 | Virtual_A() 260 | : Common(1) 261 | { 262 | } 263 | }; 264 | struct Virtual_B : virtual Common { 265 | Virtual_B() 266 | : Common(2) 267 | { 268 | } 269 | }; 270 | struct Diamond : Virtual_A, Virtual_B { 271 | Diamond() 272 | : Common(3) 273 | , Virtual_A() 274 | , Virtual_B() 275 | { 276 | } 277 | }; 278 | 279 | void types_03() 280 | { 281 | int a = 0; 282 | assert(typeid(int) == typeid(a)); 283 | assert(typeid(int).name() == string("i")); 284 | 285 | a_ref(a) = 2; 286 | assert(a == 2); 287 | 288 | Diamond d; 289 | assert(d.Virtual_A::n == 3); 290 | assert(d.Virtual_B::n == 3); 291 | } 292 | 293 | /// @} 294 | 295 | int main(void) 296 | { 297 | assert(__cplusplus == 199711); 298 | 299 | init_03(); 300 | container_03(); 301 | algo_03(); 302 | types_03(); 303 | assert(min(1, 2) == 1); 304 | assert(max(1, 2) == 2); 305 | pair p(1, 'a'); 306 | assert(p.first == 1); 307 | assert(p.second == 'a'); 308 | p = make_pair('b', 2); 309 | assert(p.first == 'b'); 310 | } 311 | 312 | /// @} 313 | -------------------------------------------------------------------------------- /cpp/11.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | @brief C++11 4 | @defgroup CPP11 C++11 examples 5 | 6 | https://en.wikipedia.org/wiki/C++11 7 | 8 | https://github.com/AnthonyCalandra/modern-cpp-features/blob/master/CPP11.md 9 | 10 | @{ 11 | 12 | */ 13 | 14 | static_assert(__cplusplus == 201103, ""); 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | #if __has_include() 21 | #include 22 | #endif 23 | 24 | using namespace std; 25 | 26 | /** 27 | @defgroup lang11 Language 28 | @{ 29 | 30 | */ 31 | 32 | void types_11() 33 | { 34 | static_assert(__cpp_decltype, ""); 35 | 36 | int a; 37 | // https://en.cppreference.com/w/cpp/header/type_traits 38 | decltype(a) b; // https://en.cppreference.com/w/cpp/language/decltype 39 | 40 | assert((is_same::value)); 41 | assert((!is_same::value)); 42 | assert((is_same::value)); 43 | assert((is_same::value)); 44 | 45 | assert(is_integral::value); 46 | assert(is_integral::value); 47 | assert(!is_integral::value); 48 | assert(is_pointer::value); 49 | assert(sizeof(long long) >= 8); 50 | 51 | enum class Number { zero, 52 | tree = 3, 53 | four }; 54 | Number n = Number::zero; 55 | assert(static_cast(n) == 0); 56 | assert(is_enum()); 57 | } 58 | 59 | /// [unique_ptr](https://en.cppreference.com/w/cpp/memory/unique_ptr) 60 | 61 | void unique_pounter() 62 | { 63 | int d = 0; 64 | unique_ptr u1; 65 | assert(!u1); 66 | u1.reset(&d); 67 | assert(u1); 68 | *u1 = 1; 69 | assert(d == 1); 70 | 71 | unique_ptr u2; 72 | // u2 = u1; - prohibited 73 | 74 | int* p1 = u1.get(); 75 | u2 = move(u1); // [move](https://en.cppreference.com/w/cpp/utility/move) 76 | assert(u2.get() == p1); 77 | assert(u2); 78 | assert(!u1); 79 | assert(u2.get() == &d); 80 | // must release because d is local 81 | u2.release(); 82 | u2.reset(new int(10)); 83 | assert(*u2 == 10); 84 | 85 | u2.reset(); // deletes int(10) 86 | assert(u2 == nullptr); // [nullptr](https://en.cppreference.com/w/cpp/language/nullptr) 87 | 88 | assert(!u2); 89 | } 90 | 91 | /// [shared_ptr](https://en.cppreference.com/w/cpp/memory/shared_ptr) 92 | 93 | void shared_pointer() 94 | { 95 | shared_ptr s1; 96 | assert(!s1); 97 | assert(!s1.use_count()); 98 | 99 | auto s2 = make_shared(1); 100 | assert(s2.use_count() == 1); 101 | 102 | s1 = s2; 103 | assert(s1.use_count() == 2); 104 | 105 | *s1 = 2; 106 | assert(*s1 == *s1.get()); 107 | assert(*s2 == 2); 108 | 109 | s2 = nullptr; // like s2.reset(); 110 | assert(s1.use_count() == 1); 111 | assert(!s2.use_count()); 112 | } 113 | 114 | /// [weak_ptr](https://en.cppreference.com/w/cpp/memory/weak_ptr) 115 | 116 | void weak_pointer() 117 | { 118 | weak_ptr wp; 119 | 120 | assert(!wp.lock()); 121 | assert(!wp.use_count()); 122 | auto sp = make_shared(1); 123 | wp = sp; 124 | assert(*wp.lock() == 1); 125 | } 126 | 127 | /** 128 | [new](https://en.cppreference.com/w/cpp/memory/new/operator_new), 129 | 130 | [delete](https://en.cppreference.com/w/cpp/memory/new/operator_delete) 131 | */ 132 | 133 | void dynamic_memory_11() 134 | { 135 | auto a = new int[3] { 1, 2, 3 }; 136 | assert(a[2] == 3); 137 | delete a; 138 | 139 | auto as = new string[3] { "1", "2", "3" }; 140 | assert(as[2] == "3"); 141 | delete[] as; // calls destructors for all members 142 | 143 | unique_pounter(); 144 | 145 | shared_pointer(); 146 | 147 | weak_pointer(); 148 | } 149 | 150 | /// func_type - overloaded functions 151 | /// [remove_reference](https://en.cppreference.com/w/cpp/types/remove_reference) 152 | 153 | char func_type(const int& x) 154 | { 155 | assert(is_const::type>::value); 156 | assert(is_lvalue_reference::value); 157 | return 'C'; 158 | } 159 | 160 | char func_type(int& x) 161 | { 162 | assert(is_lvalue_reference::value); 163 | return 'L'; 164 | } 165 | 166 | char func_type(int&& x) 167 | { 168 | assert(is_rvalue_reference::value); 169 | return 'R'; 170 | } 171 | 172 | /// [Forwarding reference](https://en.cppreference.com/w/cpp/language/reference#Forwarding_references) 173 | 174 | template 175 | char func_type_template(T&& x) // x is a forwarding reference 176 | { 177 | // x is not R-value here 178 | assert(func_type(x) != 'R'); 179 | 180 | // x can be forwarded as R or L value 181 | // https://en.cppreference.com/w/cpp/utility/forward 182 | return func_type(forward(x)); // like func_type((T)(x)); 183 | } 184 | 185 | /** 186 | [References](https://en.wikipedia.org/wiki/Reference_(C++)) 187 | 188 | [is_reference](https://en.cppreference.com/w/cpp/types/is_reference), 189 | [ref](https://en.cppreference.com/w/cpp/utility/functional/ref), 190 | [reference_wrapper](https://en.cppreference.com/w/cpp/utility/functional/reference_wrapper) 191 | */ 192 | 193 | void references_11() 194 | { 195 | // https://en.cppreference.com/w/cpp/language/reference 196 | assert(is_reference::value); 197 | 198 | // L-value: 199 | assert(is_lvalue_reference::value); 200 | 201 | // R-value 202 | assert(is_rvalue_reference::value); 203 | 204 | const int c = 1; 205 | int i = 2; 206 | 207 | assert(func_type(3) == 'R'); 208 | assert(func_type(c) == 'C'); 209 | assert(func_type(move(i)) == 'R'); 210 | 211 | assert(func_type_template(c) == 'C'); 212 | assert(func_type_template(i) == 'L'); 213 | assert(func_type_template(3) == 'R'); 214 | reference_wrapper rw = i; 215 | rw.get() = 3; 216 | assert(i == 3); 217 | auto cr = cref(i); 218 | assert(cr == 3); 219 | } 220 | 221 | /** 222 | [direct_initialization](https://en.cppreference.com/w/cpp/language/direct_initialization) 223 | 224 | [zero_initialization](https://en.cppreference.com/w/cpp/language/zero_initialization) 225 | 226 | [list_initialization](https://en.cppreference.com/w/cpp/language/list_initialization) 227 | 228 | [initializer_list](https://en.cppreference.com/w/cpp/utility/initializer_list) 229 | 230 | [Member_initialization](https://en.cppreference.com/w/cpp/language/data_members#Member_initialization) 231 | 232 | [aggregate_initialization](https://en.cppreference.com/w/cpp/language/aggregate_initialization) 233 | 234 | [reference_initialization](https://en.cppreference.com/w/cpp/language/reference_initialization) 235 | 236 | */ 237 | 238 | void init_11() 239 | { 240 | struct C { 241 | int a, b, c; 242 | }; 243 | auto o2 = C { 1, 2, 3 }; 244 | C o3 { 1, 2, 3 }; 245 | (void)o3; 246 | 247 | auto uses_il = [](initializer_list il) { 248 | assert(*il.begin() == 3); 249 | assert(il.size() == 4); 250 | }; 251 | uses_il({ 3, 2, 1, 0 }); 252 | 253 | auto z1 = C(); 254 | C z2 = {}; 255 | auto z3 = C {}; 256 | 257 | assert(!z1.a); 258 | assert(!z2.a); 259 | assert(!z3.a); 260 | array a { 1, 2 }; 261 | } 262 | 263 | /** 264 | Trailing return type 265 | 266 | https://en.cppreference.com/w/cpp/language/function 267 | 268 | https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_73/rzarg/trailing_return.htm 269 | 270 | */ 271 | 272 | /// https://en.cppreference.com/w/cpp/language/auto 273 | auto auto_int = 1; 274 | 275 | // int before(int a) { return a; } 276 | auto trailing_return_type(int a) -> int 277 | { 278 | return a; 279 | } 280 | 281 | /// [copy_elision](https://en.cppreference.com/w/cpp/language/copy_elision) 282 | 283 | void copy_elision_demo() 284 | { 285 | struct Obj2 { 286 | Obj2* orig = this; 287 | int ballast[4]; 288 | }; 289 | auto&& o2 = []() { return Obj2(); }(); 290 | assert(&o2 == o2.orig); 291 | } 292 | 293 | void func_11() 294 | { 295 | class functor { 296 | int y = 1; 297 | 298 | public: 299 | int operator()(int a) const 300 | { 301 | return a + y; 302 | } 303 | }; 304 | functor ft; 305 | assert(ft(1) == 2); 306 | 307 | // https://en.cppreference.com/w/cpp/utility/functional/function 308 | function ft2 = ft; 309 | assert(ft(2) == 3); 310 | return; 311 | 312 | // https://en.cppreference.com/w/cpp/utility/functional/bind 313 | auto binded = bind(ft2, 3); 314 | assert(binded() == 5); 315 | 316 | copy_elision_demo(); 317 | } 318 | 319 | static_assert(__cpp_constexpr, ""); 320 | 321 | /// https://en.cppreference.com/w/cpp/language/constexpr 322 | 323 | constexpr int constexpr_factorial(int n) 324 | { 325 | return n <= 1 ? 1 : (n * constexpr_factorial(n - 1)); 326 | } 327 | 328 | /// https://en.cppreference.com/w/cpp/language/parameter_pack 329 | 330 | template 331 | T constexpr adder(T v) 332 | { 333 | return v; 334 | } 335 | 336 | template 337 | T constexpr adder(T first, Args... args) 338 | { 339 | return first + adder(args...); 340 | } 341 | 342 | static_assert(adder(1, 2, 3) == 6, ""); 343 | static_assert(adder(1, 2, 3) == 6, ""); 344 | 345 | struct Base11 { 346 | virtual void method1(); 347 | virtual void method2(); 348 | }; 349 | 350 | struct Derived11 : Base11 { 351 | void method1() override; ///< [override](https://en.cppreference.com/w/cpp/language/override) 352 | void method2() final; ///< [final](https://en.cppreference.com/w/cpp/language/final) 353 | }; 354 | 355 | void language_11() 356 | { 357 | types_11(); 358 | references_11(); 359 | init_11(); 360 | auto r = trailing_return_type(1); 361 | (void) r; 362 | dynamic_memory_11(); 363 | func_11(); 364 | } 365 | 366 | /// @} lang11 367 | 368 | /** 369 | @defgroup lambda11 Lambda 370 | https://en.cppreference.com/w/cpp/language/lambda 371 | https://www.geeksforgeeks.org/lambda-expression-in-c/ 372 | @{ 373 | */ 374 | 375 | static void lambda_basics(void) 376 | { 377 | auto annotated_named_lambda_expression = // optional name 378 | [] // capture clause 379 | () // optional list of arguments 380 | {}; // body 381 | 382 | // Primitive named lambdas are just like closure functions: 383 | // https://en.wikipedia.org/wiki/Closure_(computer_programming) 384 | 385 | // declaration like a function: 386 | // void closure() { }; 387 | auto closure = [] {}; 388 | 389 | closure(); 390 | 391 | // with arguments 392 | auto pass = [](int a) { return a; }; 393 | assert(pass(5) == 5); 394 | 395 | // lambda captures external value 396 | int c = 1; 397 | auto get_i = [=]() { return c; }; 398 | assert(get_i() == 1); 399 | 400 | // lambda captures external variable by reference 401 | // with omitted arguments and return type 402 | auto inc_get = [&] { return ++c; }; 403 | assert(inc_get() == 2); 404 | assert(inc_get() == 3); 405 | 406 | // annotated expanded empty inline lambda call: 407 | [] // capture 408 | () // optional list of arguments 409 | -> void // optional return value 410 | {} // body 411 | (); // call with arguments 412 | 413 | // annotated expanded sample inline lambda call: 414 | c = // result 415 | [c] // capture 416 | (int a) // an argument 417 | -> int // return value 418 | { return c + a; } // body 419 | (1); // call with argument 420 | assert(c == 4); 421 | 422 | // inline lambda which is called in place 423 | // https://en.wikipedia.org/wiki/Anonymous_function 424 | 425 | // assert((1 + 1) == 2); 426 | assert([](int a) { return a + 1; }(1) == 2); 427 | 428 | // Actually calling lambda inline is useless 429 | // and is provided only for demonstration. 430 | } 431 | 432 | /// @cond 433 | static int glob; 434 | /// @endcond 435 | 436 | static void lambda_capture(void) 437 | { 438 | // read only 439 | int i = 2; 440 | assert([=] { return i; }() == 2); 441 | 442 | // read and write access 443 | [&](int a) { i = a; }(3); 444 | assert(i == 3); 445 | 446 | // explicit r/o and r/w 447 | int j; 448 | [i, &j]() { j = i; }(); 449 | assert(j == i); 450 | 451 | // r/o by default 452 | i++; 453 | [=, &j]() { j = i; }(); 454 | assert(j == i); 455 | 456 | // r/w by default 457 | i++; 458 | [&, i]() { j = i; }(); 459 | assert(j == i); 460 | 461 | // can access globals anyway 462 | auto inc_global = []() { return ++glob; }; 463 | assert(inc_global() == 1); 464 | assert(inc_global() == 2); 465 | } 466 | 467 | /// [utility](https://en.cppreference.com/w/cpp/utility) 468 | 469 | void utils_11() 470 | { 471 | pair bounds = minmax({3, 2, 1}); 472 | assert(bounds.first == 1); 473 | assert(bounds.second == 3); 474 | int min, max; 475 | tie(min, max) = bounds; 476 | assert(min == 1); 477 | int n = 1; 478 | auto t = make_tuple(0, "one", 3.14, ref(n), n); 479 | n = 2; 480 | //cerr << func_type(get<2>(t)) << '\n'; 481 | assert(is_arithmetic::value); 482 | //assert(is_arithmetic(t))>::value); 483 | assert(get<3>(t) == 2); 484 | assert(get<4>(t) == 1); 485 | } 486 | 487 | /// [container](https://en.cppreference.com/w/cpp/container) 488 | 489 | template 490 | void test_list_container(L& l) 491 | { 492 | l.push_front(0); 493 | assert(l.front() == 0); 494 | l.emplace_front(1); 495 | assert(l.front() == 1); 496 | l.pop_front(); 497 | L l2; 498 | swap(l, l2); 499 | l.swap(l2); 500 | } 501 | 502 | void container_11() 503 | { 504 | // [list_initialization](https://en.cppreference.com/w/cpp/language/list_initialization) 505 | vector v = { 1, 2, 3 }; 506 | assert(v.data()[2] == 3); 507 | 508 | v.shrink_to_fit(); 509 | 510 | v.emplace(v.cbegin(), 0); 511 | assert(v.front() == 0); 512 | 513 | v.emplace_back(4); 514 | assert(v.back() == 4); 515 | 516 | array a1, a2; 517 | swap(a1, a2); 518 | 519 | /// [forward_list](https://en.cppreference.com/w/cpp/container/forward_list) 520 | forward_list fl; 521 | test_list_container(fl); 522 | fl.insert_after(fl.cbegin(), 3); 523 | assert(*(next(fl.begin())) == 3); 524 | fl.erase_after(fl.cbefore_begin()); // like fl.pop_front(); 525 | assert(fl.front() == 3); 526 | fl.pop_front(); 527 | 528 | list l; 529 | test_list_container(l); 530 | l.emplace_back(0); 531 | l.emplace(l.begin(), 2); 532 | assert(l.front() == 2); 533 | l.sort(); 534 | 535 | deque d; 536 | test_list_container(d); 537 | d.emplace_back(0); 538 | 539 | stack s, s2; 540 | s.emplace(1); 541 | s.swap(s2); 542 | } 543 | 544 | /// [algorithm](https://en.cppreference.com/w/cpp/algorithm) 545 | 546 | void algo_11() 547 | { 548 | vector v = { 1, 2, 3 }; 549 | assert(find(begin(v), end(v), 0) == end(v)); 550 | assert(find(begin(v), end(v), 1) != end(v)); 551 | 552 | // https://en.cppreference.com/w/cpp/container/vector/erase 553 | // https://en.cppreference.com/w/cpp/algorithm/remove 554 | v.erase(remove_if(v.begin(), v.end(), [](unsigned char x) { return x == 2; }), v.end()); 555 | assert(v.size() == 2); 556 | 557 | vector r(v.size()); 558 | reverse_copy(begin(v), end(v), r.begin()); 559 | assert(r[0] > r[1]); 560 | 561 | // https://en.cppreference.com/w/cpp/string/basic_string/erase 562 | string s = "1 2 3"; 563 | s.erase(remove_if(s.begin(), s.end(), [](unsigned char x) { return isspace(x); }), s.end()); 564 | assert(s == "123"); 565 | } 566 | 567 | /// Compare with @ref sort_03 568 | 569 | struct comp { 570 | template 571 | bool operator()(const T& l, const T& r) const 572 | { 573 | return l.second < r.second; 574 | } 575 | }; 576 | 577 | void sort_11() 578 | { 579 | /// [array](https://en.cppreference.com/w/cpp/container/array) 580 | 581 | array s { 5, 7, 4, 2, 8, 6, 1, 9, 0, 3 }; 582 | sort(s.begin(), s.end(), 583 | // sort using a lambda expression 584 | [](int a, int b) { return a > b; }); 585 | 586 | // https://stackoverflow.com/questions/18045208/override-mapcompare-with-lambda-function-directly 587 | auto reverse = map> { 588 | [](const string& a, const string& b) { return a > b; } 589 | } 590 | = { 591 | { "a", 2 }, 592 | { "b", 1 }, 593 | { "c", 0 }, 594 | }; 595 | assert(reverse.begin()->first == "c"); 596 | assert(reverse.begin()->second == 0); 597 | 598 | // https://www.techiedelight.com/sort-map-values-cpp/ 599 | typedef pair pair; 600 | vector vec = { 601 | { "a", 2 }, 602 | { "b", 1 }, 603 | { "c", 0 }, 604 | }; 605 | sort(vec.begin(), vec.end(), 606 | [](const pair& l, const pair& r) { return l.second < r.second; }); 607 | assert(vec.begin()->first == "c"); 608 | 609 | set, comp> t = { 610 | { "a", 2 }, 611 | { "b", 1 }, 612 | { "c", 0 }, 613 | }; 614 | assert(t.begin()->first == "c"); 615 | } 616 | 617 | /// @} 618 | 619 | /** 620 | @defgroup lambda11_complex More complex Lambdas 621 | @{ 622 | */ 623 | 624 | /// @cond 625 | 626 | /// [function](https://en.cppreference.com/w/cpp/utility/functional/function) 627 | 628 | // int use_lambda(int a; int (func*)(int)) 629 | static int use_lambda(int a, function f) 630 | { 631 | // lambda argument is like pointer to functions 632 | return f(a); 633 | } 634 | 635 | static function g_f; 636 | 637 | static void set_lambda(function&& f) 638 | { 639 | g_f = f; 640 | } 641 | 642 | static int call_lambda(int a) 643 | { 644 | return g_f(a); 645 | } 646 | 647 | /// @endcond 648 | 649 | static void lambda_complex(void) 650 | { 651 | auto increment = [](int a) -> int { return a + 1; }; 652 | assert(increment(5) == 6); 653 | 654 | // named lambda as argument 655 | assert(use_lambda(2, increment) == 3); 656 | set_lambda(increment); 657 | assert(call_lambda(3) == 4); 658 | 659 | // inline lambda as argument 660 | assert(use_lambda(1, [](int a) { return a + 1; }) == 2); 661 | 662 | int x = 0; 663 | [x]() mutable { assert(++x); }(); 664 | assert(x == 0); 665 | } 666 | 667 | /// @} lambda11_complex 668 | 669 | /** 670 | @defgroup threads11 Threads 671 | [threads](https://en.cppreference.com/w/cpp/thread) 672 | @{ 673 | */ 674 | 675 | /// @cond 676 | 677 | // just function with delay for demonstration 678 | int lento(int a = 0) 679 | { 680 | this_thread::yield(); 681 | this_thread::sleep_for(chrono::milliseconds(50)); 682 | return a; 683 | } 684 | /// @endcond 685 | 686 | /** 687 | [condition_variable](https://en.cppreference.com/w/cpp/thread/condition_variable) 688 | [notify_one](https://en.cppreference.com/w/cpp/thread/condition_variable/notify_one) 689 | */ 690 | 691 | void condition_variable_11() 692 | { 693 | mutex m; 694 | int stage = 0; 695 | condition_variable cv; 696 | thread th( 697 | [&m, &stage, &cv] { 698 | unique_lock lk(m); 699 | cv.wait(lk, [&stage] { return stage == 1; }); 700 | stage = 2; 701 | lk.unlock(); 702 | cv.notify_one(); 703 | }); 704 | // locking block 705 | { 706 | unique_lock lk(m); 707 | // https://en.cppreference.com/w/cpp/thread/condition_variable/wait_for 708 | assert(cv.wait_for(lk, chrono::milliseconds(0)) == cv_status::timeout); 709 | assert(!cv.wait_for(lk, chrono::milliseconds(0),[]{return false;})); 710 | } 711 | { 712 | unique_lock lk(m); 713 | stage = 1; 714 | } 715 | cv.notify_one(); 716 | unique_lock lk(m); 717 | cv.wait(lk, [&stage] { return stage == 2; }); 718 | th.join(); 719 | } 720 | 721 | void threads_11() 722 | { 723 | this_thread::yield(); 724 | assert(hash()(this_thread::get_id())); 725 | this_thread::sleep_for(chrono::nanoseconds(1)); 726 | promise p; 727 | future f = p.get_future(); 728 | int v = 0; 729 | thread t([&p, &v] { 730 | lento(); 731 | p.set_value(2); 732 | v = 3; 733 | }); 734 | assert(v == 0); 735 | assert(f.get() == 2); 736 | lento(); 737 | assert(v == 3); 738 | thread t2; 739 | t2.swap(t); 740 | assert(!t.joinable()); 741 | assert(t2.joinable()); 742 | t2.join(); 743 | try { 744 | t2.join(); 745 | t2.detach(); 746 | } catch (const system_error& e) { 747 | assert(e.code().value() == 22); 748 | } 749 | assert(!t2.joinable()); 750 | 751 | // detach demo 752 | { 753 | thread t3([&p, &v] { 754 | v = 4; 755 | }); 756 | t3.detach(); 757 | std::thread { []() { assert(1); } }.detach(); 758 | } 759 | lento(); 760 | assert(v == 4); 761 | 762 | condition_variable_11(); 763 | } 764 | 765 | void mutex_11() 766 | { 767 | int unguarded = 0, guarded = 0; 768 | mutex m; 769 | 770 | thread t1([&unguarded, &guarded, &m] { 771 | unguarded = lento(unguarded) + 1; 772 | 773 | lock_guard guard(m); 774 | guarded = lento(guarded) + 1; 775 | }); 776 | thread t2([&unguarded, &guarded, &m] { 777 | unguarded = lento(unguarded) + 1; 778 | 779 | lock_guard guard(m); 780 | guarded = lento(guarded) + 1; 781 | }); 782 | 783 | assert(unguarded == 0); 784 | assert(guarded == 0); 785 | t1.join(); 786 | t2.join(); 787 | assert(unguarded == 1); 788 | assert(guarded == 2); 789 | } 790 | /// @} threads11 791 | 792 | /** 793 | @{ 794 | 795 | TODO: 796 | function get_a = a; 797 | 798 | https://en.cppreference.com/w/cpp/language/attributes 799 | 800 | https://en.cppreference.com/w/cpp/language/string_literal 801 | 802 | https://en.cppreference.com/w/cpp/language/character_literal 803 | 804 | https://en.cppreference.com/w/cpp/language/user_literal 805 | 806 | https://en.cppreference.com/w/cpp/language/initializer_list 807 | 808 | https://en.cppreference.com/w/cpp/utility/declval 809 | 810 | https://en.cppreference.com/w/cpp/language/range-for 811 | 812 | https://en.cppreference.com/w/cpp/types/is_move_constructible 813 | 814 | https://en.cppreference.com/w/cpp/types/is_constructible 815 | 816 | @} 817 | */ 818 | 819 | void sig(int) 820 | { 821 | abort(); 822 | } 823 | 824 | int main(void) 825 | { 826 | signal(SIGALRM, sig); 827 | alarm(1); 828 | language_11(); 829 | lambda_basics(); 830 | lambda_capture(); 831 | lambda_complex(); 832 | utils_11(); 833 | container_11(); 834 | algo_11(); 835 | sort_11(); 836 | static_assert(constexpr_factorial(4), ""); 837 | 838 | threads_11(); 839 | mutex_11(); 840 | 841 | return 0; 842 | } 843 | 844 | /// @} 845 | -------------------------------------------------------------------------------- /cpp/14.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | @brief C++14 4 | @defgroup CPP14 C++14 examples 5 | 6 | https://en.wikipedia.org/wiki/C++14 7 | 8 | https://isocpp.org/wiki/faq/cpp14-language 9 | 10 | https://github.com/AnthonyCalandra/modern-cpp-features/blob/master/CPP14.md 11 | 12 | @{ 13 | */ 14 | 15 | static_assert(__cplusplus == 201402, ""); 16 | 17 | #include 18 | 19 | using namespace std; 20 | 21 | /** 22 | @defgroup ded14 Deduction 23 | @{ 24 | */ 25 | 26 | #define static_assert(a) static_assert(a, "") 27 | static_assert(__cpp_return_type_deduction); 28 | 29 | auto implicit_int_return_type() 30 | { 31 | return 1; 32 | } 33 | 34 | // template T before_deduced_return_type(int a) { return a; } 35 | auto deduced_return_type(int a) 36 | { 37 | return a; 38 | } 39 | 40 | // template T& before_deduced_return_type_template(T& a) { return a; } 41 | template 42 | auto& deduced_return_type_template(T& t) 43 | { 44 | return t; 45 | } 46 | 47 | // Returns a reference to a deduced type. 48 | auto deduced_return_type_lambda = [](auto& x) -> auto& 49 | { 50 | return deduced_return_type_template(x); 51 | }; 52 | 53 | void return_type_deduction_demo() 54 | { 55 | implicit_int_return_type(); 56 | auto x = deduced_return_type(1); 57 | int& y = deduced_return_type_lambda(x); // reference to `x` 58 | assert(&y == &x); 59 | assert(y == 1); 60 | } 61 | 62 | /// @} 63 | /** 64 | @defgroup other14 Other 65 | @{ 66 | TODO: 67 | 68 | https://en.cppreference.com/w/cpp/container/map/find 69 | 70 | https://en.cppreference.com/w/cpp/language/constexpr 71 | 72 | https://en.cppreference.com/w/cpp/language/integer_literal 73 | 74 | https://en.cppreference.com/w/cpp/language/function // decltype(auto) 75 | 76 | https://en.cppreference.com/w/cpp/language/aggregate_initialization 77 | 78 | https://en.cppreference.com/w/cpp/thread/shared_timed_mutex 79 | 80 | https://en.cppreference.com/w/cpp/thread/shared_lock 81 | 82 | https://en.cppreference.com/w/cpp/utility/integer_sequence 83 | 84 | https://en.cppreference.com/w/cpp/utility/exchange 85 | 86 | https://en.cppreference.com/w/cpp/utility/forward 87 | 88 | https://en.cppreference.com/w/cpp/io/manip/quoted 89 | 90 | // [[deprecated]] 91 | */ 92 | 93 | /// Binary literals, digit separators 94 | 95 | /// Template variables 96 | /// https://en.cppreference.com/w/cpp/language/variable_template 97 | 98 | static_assert(__cpp_variable_templates); 99 | 100 | /// Numeric pi 101 | template 102 | T pi = T(3.141592653589793238462643383); 103 | 104 | // String pi 105 | // Usual specialization rules apply: 106 | template <> 107 | const char* pi = "pi"; 108 | 109 | static void demo() 110 | { 111 | assert(pi == 3); 112 | assert(string(pi) == "pi"); 113 | 114 | auto binary_literal = 0b0100'1100'0110; 115 | 116 | auto integer_literal = 1'000'000; 117 | 118 | auto floating_point_literal = 0.000'015'3; 119 | 120 | /// Standard user-defined literals 121 | 122 | auto str = "hello world"s; // auto deduces string 123 | auto dur = 60s; // auto deduces chrono::seconds 124 | } 125 | 126 | void types_14() 127 | { 128 | static_assert(is_null_pointer::value); 129 | static_assert(is_null_pointer::value); 130 | static_assert(__cpp_decltype); 131 | static_assert(is_integral()); 132 | 133 | // Tuple addressing via type 134 | tuple tuple_by_type("foo", "bar", 7); 135 | 136 | int i = get(tuple_by_type); 137 | assert(i == 7); 138 | 139 | int j = get<2>(tuple_by_type); 140 | assert(j == 7); 141 | 142 | // https://en.cppreference.com/w/cpp/language/auto 143 | int a = 0; 144 | static_assert(__cpp_decltype_auto); 145 | decltype(auto) a_copy = a; 146 | assert(&a_copy != &a); 147 | decltype(auto) a_ref = (a); 148 | assert(&a_ref == &a); 149 | 150 | // https://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique 151 | // auto u = unique_ptr(new int(1)); 152 | auto u = make_unique(1); 153 | assert(u); 154 | assert(*u == 1); 155 | auto ua = make_unique(3); 156 | } 157 | 158 | /// @} 159 | /** 160 | @defgroup lambda14 Lambda 161 | https://en.cppreference.com/w/cpp/language/lambda 162 | @{ 163 | */ 164 | static void lambda_14() 165 | { 166 | // Generic lambdas 167 | // auto before_generic_lambda = [](int x) { return x; }; 168 | static_assert(__cpp_generic_lambdas); 169 | auto generic_lambda = [](auto x) { return x; }; 170 | 171 | auto universal_size = [](const auto& m) { return m.size(); }; 172 | 173 | static_assert(__cpp_init_captures); 174 | auto capture_initializers = [value = 1] { return value; }; 175 | 176 | assert(capture_initializers() == 1); 177 | 178 | auto mutable_lambda = [value = 1]() mutable { return ++value; }; 179 | 180 | assert(mutable_lambda() == 2); 181 | assert(mutable_lambda() == 3); 182 | 183 | // capture initialization can change context 184 | int c = 0; 185 | auto change_c = [value = ++c] {}; 186 | assert(c == 1); 187 | 188 | unique_ptr ptr(new int(10)); 189 | auto capture_by_move = [value = move(ptr)] { return *value; }; 190 | } 191 | 192 | /// Compare with @ref lambda::sort_11 193 | 194 | void sort_14() 195 | { 196 | array s = { 5, 7, 4, 2, 8, 6, 1, 9, 0, 3 }; 197 | sort(s.begin(), s.end(), 198 | // sort using a generic lambda expression 199 | [](auto a, auto b) // C++14 allows auto 200 | { return a > b; }); 201 | 202 | // https://stackoverflow.com/questions/18045208/override-mapcompare-with-lambda-function-directly 203 | auto reverse = map> { 204 | [](const auto& a, const auto& b) { return a > b; } 205 | } 206 | = { 207 | { "a", 2 }, 208 | { "b", 1 }, 209 | { "c", 0 }, 210 | }; 211 | assert(reverse.begin()->first == "c"); 212 | assert(reverse.begin()->second == 0); 213 | } 214 | 215 | /// @} 216 | 217 | int main(void) 218 | { 219 | return_type_deduction_demo(); 220 | demo(); 221 | sort_14(); 222 | types_14(); 223 | lambda_14(); 224 | } 225 | /// @} 226 | -------------------------------------------------------------------------------- /cpp/17.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | @brief C++17 4 | @defgroup CPP17 C++17 examples 5 | 6 | https://en.wikipedia.org/wiki/C++17 7 | 8 | https://github.com/AnthonyCalandra/modern-cpp-features/blob/master/CPP17.md 9 | 10 | https://en.cppreference.com/w/cpp/language/history/17 11 | 12 | @{ 13 | */ 14 | 15 | static_assert(__cplusplus == 201703); 16 | 17 | #include 18 | 19 | using namespace std; 20 | 21 | /** 22 | @defgroup templ17 Template 23 | 24 | https://en.cppreference.com/w/cpp/language/templates 25 | 26 | @{ 27 | */ 28 | 29 | /** 30 | @defgroup template_argument_deduction Template argument deduction 31 | 32 | [template_argument_deduction](https://en.cppreference.com/w/cpp/language/template_argument_deduction) 33 | 34 | [class_template_argument_deduction](https://en.cppreference.com/w/cpp/language/class_template_argument_deduction) 35 | 36 | @{ 37 | */ 38 | 39 | /// @brief pair p(1, 2.3); 40 | constexpr pair deducted_pair(1, 2.3); 41 | static_assert(deducted_pair.second == 2.3); 42 | 43 | /// @brief auto t = make_tuple(4, 3, 2.5); 44 | constexpr tuple deducted_tuple(4, 2, 2.5); 45 | static_assert(get<2>(deducted_tuple) == 2.5); 46 | 47 | /// @brief template with type float by default 48 | template 49 | struct template_struct { 50 | T val; 51 | template_struct() 52 | : val() 53 | { 54 | } 55 | template_struct(T val) 56 | : val(val) 57 | { 58 | } 59 | }; 60 | 61 | /// @brief deducted \ 62 | template_struct template_arg_deduction { 1 }; 63 | 64 | #if __cpp_deduction_guides > 201611 65 | 66 | /// @brief deducted \ 67 | template_struct template_default_arg_deduction; 68 | 69 | #endif 70 | 71 | vector int_vector = { 1, 2, 3, 4 }; 72 | 73 | /// [deduction_guides](https://en.cppreference.com/w/cpp/container/deque/deduction_guides) 74 | 75 | /// @brief deduced deque\ 76 | deque deduction_guide1_queue(int_vector.begin(), int_vector.end()); 77 | 78 | /// @brief deduced deque\ :: iterator\> 79 | deque deduction_guide2_queue { int_vector.cbegin(), int_vector.cend() }; 80 | 81 | /// [deduction_guides](https://en.cppreference.com/w/cpp/container/array/deduction_guides) 82 | array deduction_guide_array { 1, 2, 3, 4 }; 83 | 84 | /// [deduction_guides](https://en.cppreference.com/w/cpp/container/vector/deduction_guides) 85 | /// @brief deduced vector\ 86 | vector deduction_guide1_vector(int_vector.begin(), int_vector.end()); 87 | /// @brief deduced vector\ :: iterator\> 88 | vector deduction_guide2_vector { int_vector.begin(), int_vector.end() }; 89 | 90 | /** 91 | @} template_argument_deduction 92 | */ 93 | 94 | void deduction_guides_17() 95 | { 96 | assert(deduction_guide1_queue[0] == 1); 97 | assert(*deduction_guide2_queue[0] == 1); 98 | assert(deduction_guide1_vector[0] == 1); 99 | assert(*deduction_guide2_vector[0] == 1); 100 | } 101 | 102 | /** 103 | @defgroup template_parameters Template parameters 104 | 105 | [template_parameters](https://en.cppreference.com/w/cpp/language/template_parameters) 106 | 107 | @{ 108 | */ 109 | 110 | template 111 | struct B { /* ... */ 112 | }; 113 | 114 | B<5> b1; // OK: non-type template parameter type is int 115 | 116 | B<'a'> b2; 117 | 118 | // Error: 119 | // B<2.5> b3; 120 | 121 | tuple foo_tuple() 122 | { 123 | // return make_tuple(1, -1); 124 | return { 1, -1 }; 125 | } 126 | 127 | template 128 | struct my_integer_sequence { 129 | }; 130 | 131 | /// @brief auto seq = integer_sequence(); 132 | auto seq = my_integer_sequence<0, 1, 2>(); 133 | 134 | /** 135 | 136 | @} template_parameters 137 | @} templ17 138 | 139 | @defgroup lambda17 Lambda 140 | 141 | @{ 142 | */ 143 | 144 | /** 145 | @defgroup constexpr_lambda Constexpr lambda 146 | 147 | [lambda](https://en.cppreference.com/w/cpp/language/lambda) 148 | 149 | [lambda-expressions-constexpr](https://docs.microsoft.com/en-us/cpp/cpp/lambda-expressions-constexpr) 150 | 151 | @{ 152 | */ 153 | 154 | // explicit constexpr 155 | auto identity = [](int n) constexpr { return n; }; 156 | static_assert(identity(1) == 1); 157 | 158 | // lambda with auto argument actually is a template 159 | 160 | // implicit auto constexpr: 161 | 162 | auto can_be_constexpr1 = [](auto a) { return a; }; 163 | auto can_be_constexpr2 = [](int (*fp)(int), auto a) { return fp(a); }; 164 | 165 | static_assert(can_be_constexpr2(can_be_constexpr1, 3) == 3); 166 | 167 | // error: non-constant condition for static assertion 168 | // static int i=0; 169 | // static_assert(can_be_constexpr2(can_be_constexpr1, i) == 0); 170 | 171 | auto non_const = [](auto a) { 172 | static int s; 173 | return a; 174 | }; 175 | 176 | // error: no specialization can be constexpr because of s 177 | // static_assert(can_be_constexpr(non_const, 3)==3); 178 | 179 | constexpr int const_inc(int n) 180 | { 181 | return [n] { return n + 1; }(); 182 | } 183 | 184 | constexpr int (*inc)(int) = const_inc; 185 | static_assert(const_inc(1) == 2); 186 | 187 | /** 188 | @} constexpr_lambda 189 | 190 | @defgroup lcbv Lambda capture this by value 191 | 192 | [Lambda 193 | capture](https://en.cppreference.com/w/cpp/language/lambda#Lambda_capture) 194 | 195 | @{ 196 | */ 197 | 198 | void capture_this_by_value() 199 | { 200 | struct capture_value_o { 201 | int value { 1 }; 202 | auto get_value_copy() 203 | { 204 | return [*this] { return value; }; 205 | } 206 | }; 207 | 208 | capture_value_o mo; 209 | auto val = mo.get_value_copy(); 210 | mo.value = 2; 211 | assert(val() == 1); 212 | } 213 | 214 | void lambda_17() 215 | { 216 | assert(can_be_constexpr1(2) == 2); 217 | int i = 3; 218 | assert(can_be_constexpr2(can_be_constexpr1, 3) == 3); 219 | non_const(1); 220 | capture_this_by_value(); 221 | } 222 | 223 | /** 224 | @} lcbv 225 | 226 | @} lambda17 227 | 228 | @defgroup threads17 Threads 229 | [threads](https://en.cppreference.com/w/cpp/thread) 230 | @{ 231 | */ 232 | 233 | /** 234 | [shared_lock](https://en.cppreference.com/w/cpp/thread/shared_lock) 235 | 236 | [shared_mutex](https://en.cppreference.com/w/cpp/thread/shared_mutex) 237 | 238 | [scoped_lock](https://en.cppreference.com/w/cpp/thread/scoped_lock) 239 | */ 240 | 241 | void threads_17() 242 | { 243 | shared_mutex m; 244 | shared_lock lock(m); 245 | 246 | mutex mt[2]; 247 | thread t2; 248 | { 249 | scoped_lock l1(mt[0], mt[1]); 250 | t2 = thread([&mt] { scoped_lock l2(mt[0], mt[1]); }); 251 | } 252 | t2.join(); 253 | } 254 | 255 | /// @} threads17 256 | 257 | /** 258 | @defgroup lang17 Language 259 | @brief [language](https://en.cppreference.com/w/cpp/language) 260 | @{ 261 | */ 262 | 263 | void references_17() 264 | { 265 | static_assert(is_reference_v); 266 | 267 | // L-value: 268 | static_assert(is_lvalue_reference_v); 269 | 270 | // R-value 271 | static_assert(is_rvalue_reference_v); 272 | } 273 | 274 | /** 275 | @defgroup folding Folding 276 | @brief [fold](https://en.cppreference.com/w/cpp/language/fold) 277 | @{ 278 | */ 279 | 280 | template 281 | constexpr bool folding_and(Args... args) 282 | { 283 | return (true && ... && args); 284 | } 285 | 286 | template 287 | constexpr auto folding_sum(Args... args) 288 | { 289 | return (... + args); 290 | } 291 | 292 | void folding_demo() 293 | { 294 | static_assert(!folding_and(true, false, true)); 295 | static_assert(folding_sum(1.0, 2.0f, 3) == 6.0); 296 | } 297 | 298 | /** 299 | @} folding 300 | @defgroup nn Qualified nested namespace 301 | @brief [namespace](https://en.cppreference.com/w/cpp/language/namespace) 302 | 303 | http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4026.html 304 | 305 | @{ 306 | */ 307 | 308 | /// Before: namespace outer_namespace { namespace nested_namespace { } } 309 | 310 | namespace outer_namespace::qualified_nested_namespace { 311 | int in_qualified_nested_namespace; 312 | } 313 | 314 | /** 315 | @} nn 316 | @defgroup sb Structured bindings 317 | 318 | [structured 319 | binding](https://en.cppreference.com/w/cpp/language/structured_binding) 320 | @{ 321 | */ 322 | 323 | static_assert(__cpp_structured_bindings); 324 | 325 | void structured_bindings() 326 | { 327 | 328 | int a[2] = { 1, 2 }; 329 | 330 | auto [a0, a1] = a; 331 | // a0_ref = &a; a0_ref = &a; 332 | auto& [a0_ref, a1_ref] = a; 333 | 334 | float x {}; 335 | char y {}; 336 | int z {}; 337 | 338 | unordered_map mapping { 339 | { "a", 1 }, 340 | { "b", 2 }, 341 | { "c", 3 }, 342 | }; 343 | 344 | for (const auto& [key, value] : mapping) { 345 | // Do something with key and value 346 | } 347 | // tuple tpl(x,move(y),z); 348 | // const auto& [a,b,c] = tpl; 349 | // https://en.cppreference.com/w/cpp/language/structured_binding 350 | auto [min, max] = minmax({ 3, 2, 1 }); 351 | assert(min == 1); 352 | assert(max == 3); 353 | } 354 | 355 | /// @} sb 356 | /** 357 | Variable declaration in conditionals 358 | 359 | Specs: 360 | [if](https://en.cppreference.com/w/cpp/language/if), 361 | [switch](https://en.cppreference.com/w/cpp/language/switch) 362 | 363 | */ 364 | 365 | void conditional_with_init() 366 | { 367 | if (auto a = true) { 368 | }; 369 | 370 | switch (int a = 10) { 371 | } 372 | } 373 | 374 | /** 375 | @defgroup attr New attributes 376 | @brief 377 | [fallthrough](https://en.cppreference.com/w/cpp/language/attributes/fallthrough), 378 | [nodiscard](https://en.cppreference.com/w/cpp/language/attributes/nodiscard), 379 | [maybe_unused](https://en.cppreference.com/w/cpp/language/attributes/maybe_unused) 380 | 381 | @{ 382 | */ 383 | 384 | // Will warn if return of foo() is ignored 385 | [[nodiscard]] int foo() { return 1; } 386 | void test_attr() 387 | { 388 | int a { 1 }; 389 | switch (a) { 390 | // Indicates that falling through on case 1 is intentional 391 | case 1: 392 | [[fallthrough]]; 393 | case 2: 394 | // Indicates that b might be unused, such as on production builds 395 | [[maybe_unused]] int b = foo(); 396 | assert(b > 0); 397 | break; 398 | } 399 | } 400 | 401 | /// @} 402 | 403 | /** 404 | @brief 405 | [if](https://en.cppreference.com/w/cpp/language/if) 406 | */ 407 | 408 | constexpr int const_if() 409 | { 410 | if constexpr (true) 411 | return 1; 412 | } 413 | 414 | static_assert(const_if()); 415 | 416 | /** 417 | Character literal 418 | @brief 419 | [character_literal](https://en.cppreference.com/w/cpp/language/character_literal) 420 | */ 421 | 422 | static char char_u8 = u8'x'; 423 | 424 | /** 425 | Direct list initialization of 426 | [enum](https://en.cppreference.com/w/cpp/language/enum)s 427 | 428 | [floating_literal](https://en.cppreference.com/w/cpp/language/floating_literal) 429 | 430 | [invoke](https://en.cppreference.com/w/cpp/utility/functional/invoke) 431 | */ 432 | 433 | void types_17() 434 | { 435 | enum byte_e : unsigned char { 436 | }; 437 | static byte_e b { 123 }; 438 | 439 | floating_literal: 440 | static_assert(is_integral_v); 441 | static_assert(__cpp_hex_float); 442 | double hex_double = 0x1.2p3; 443 | assert(hex_double == 9.0); 444 | 445 | static_assert(is_invocable::value); 446 | static_assert(is_invocable::value); 447 | static_assert(is_invocable_r::value); 448 | static_assert(is_invocable_r::value); 449 | static_assert(negation_v>); 450 | 451 | auto inc = [](int a) -> int { return a + 1; }; 452 | static_assert(is_invocable_r::value); 453 | static_assert(__cpp_lib_invoke); 454 | assert(invoke(inc, 2) == 3); 455 | } 456 | 457 | /// [language](https://en.cppreference.com/w/cpp/language) 458 | 459 | void lang_17() 460 | { 461 | references_17(); 462 | folding_demo(); 463 | structured_bindings(); 464 | conditional_with_init(); 465 | test_attr(); 466 | types_17(); 467 | 468 | /// https://en.cppreference.com/w/cpp/language/range-for 469 | map mymap; 470 | for (auto&& [first, second] : mymap) { 471 | // use first and second 472 | } 473 | } 474 | 475 | /** 476 | @} lang17 477 | 478 | @defgroup lib17 Library 479 | 480 | @{ 481 | */ 482 | 483 | void map_demo() 484 | { 485 | /// @brief https://en.cppreference.com/w/cpp/container/map/extract 486 | map m { { 1, "mango" }, { 2, "papaya" }, { 3, "guava" } }; 487 | auto nh = m.extract(2); 488 | nh.key() = 4; 489 | /// @brief https://en.cppreference.com/w/cpp/container/map/insert 490 | m.insert(move(nh)); 491 | // m == {{1, "mango"}, {3, "guava"}, {4, "papaya"}} 492 | 493 | /// @brief https://en.cppreference.com/w/cpp/container/map/merge 494 | set src { 1, 3, 5 }; 495 | set dst { 2, 4, 5 }; 496 | dst.merge(src); 497 | assert(size(dst) == 5); 498 | } 499 | 500 | /** 501 | [variant](https://en.cppreference.com/w/cpp/utility/variant) 502 | 503 | [visit](https://en.cppreference.com/w/cpp/utility/variant/visit) 504 | */ 505 | 506 | void variant_demo() 507 | { 508 | variant v, w; 509 | v = 12; // v contains int 510 | int i = get(v); 511 | w = get(v); 512 | w = get<0>(v); // same effect as the previous line 513 | w = v; // same effect as the previous line 514 | 515 | // get(v); // error: no double in [int, float] 516 | // get<3>(v); // error: valid index values are 0 and 1 517 | 518 | try { 519 | get(w); // w contains int, not float: will throw 520 | } catch (const bad_variant_access&) { 521 | } 522 | 523 | using namespace literals; 524 | 525 | variant x("abc"); 526 | 527 | // converting constructors work when unambiguous 528 | x = "def"; // converting assignment also works when unambiguous 529 | 530 | variant y("abc"); 531 | 532 | // casts to void const * when passed a char const * 533 | assert(holds_alternative(y)); 534 | y = "xyz"s; 535 | assert(holds_alternative(y)); 536 | 537 | auto inc = [](int a) -> int { return a + 1; }; 538 | assert(visit(inc, (variant)1) == 2); 539 | } 540 | 541 | void optional_demo() 542 | { 543 | optional i = make_optional(1); 544 | assert(i.has_value()); 545 | assert(i.value() == 1); 546 | i = nullopt; 547 | assert(i.value_or(2) == 2); 548 | } 549 | 550 | void clamp_demo() 551 | { 552 | static_assert(__cpp_lib_clamp); 553 | /// clamp(x, low, high) == x < low ? low : x > high ? high : x; 554 | assert(clamp(0, 1, 3) == 1); 555 | assert(clamp(2, 1, 3) == 2); 556 | assert(clamp(4, 1, 3) == 3); 557 | } 558 | 559 | void dynamic_memory_17() 560 | { 561 | int d[2] = { 10, 11 }; 562 | unique_ptr u1(d); 563 | assert(u1.get()[0] == 10); // C++11 564 | assert(u1[1] == 11); 565 | assert((bool)u1); 566 | u1.release(); 567 | const shared_ptr s1 { 0 }; 568 | // cout << s1.element_type.name() << endl; 569 | // cout << typeid(s1.weak_type).name() << endl; 570 | assert(typeid(reinterpret_pointer_cast>(s1)).name() 571 | == string("St10shared_ptrIS_IiEE")); 572 | vector s = { 5, 7, 4, 2, 8, 6, 1, 9, 0, 3 }; 573 | 574 | // https://en.cppreference.com/w/cpp/numeric/valarray/deduction_guides 575 | int a[] = { 1, 2, 3 }; 576 | valarray va(a, 3); // uses explicit deduction guide 577 | static_assert(is_integral_v::type>); 578 | } 579 | 580 | void string_view_demo() 581 | { 582 | static_assert(__cpp_lib_string_view); 583 | string s = "abcd"; 584 | string_view v = s; 585 | assert(v.data() == s.c_str()); 586 | assert(v.substr(1, 2).data() >= s.c_str()); 587 | assert(v.substr(1, 2).data() <= s.c_str() + s.length()); 588 | } 589 | 590 | /// @} lib17 591 | 592 | /** 593 | @defgroup other17 Other 594 | @{ 595 | 596 | */ 597 | 598 | /// [inline](https://en.cppreference.com/w/cpp/language/inline) 599 | 600 | inline int inline_var; 601 | 602 | /** 603 | @} other17 604 | */ 605 | 606 | int main() 607 | { 608 | deduction_guides_17(); 609 | lang_17(); 610 | lambda_17(); 611 | threads_17(); 612 | map_demo(); 613 | variant_demo(); 614 | optional_demo(); 615 | clamp_demo(); 616 | dynamic_memory_17(); 617 | string_view_demo(); 618 | } 619 | 620 | /** 621 | @} CPP17 622 | */ 623 | -------------------------------------------------------------------------------- /cpp/20.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | @brief C++20 4 | @defgroup CPP20 C++20 examples 5 | 6 | [C++20](https://en.wikipedia.org/wiki/C++20) 7 | 8 | [Modern Cpp20 features](https://github.com/AnthonyCalandra/modern-cpp-features/blob/master/CPP20.md) 9 | 10 | https://en.cppreference.com/w/cpp/20 11 | 12 | @{ 13 | */ 14 | 15 | static_assert(__cplusplus >= 201707); 16 | 17 | #include 18 | 19 | using namespace std; 20 | 21 | /** 22 | @defgroup lang20 Language 23 | [language](https://en.cppreference.com/w/cpp/language) 24 | @{ 25 | */ 26 | 27 | #if __cpp_lib_three_way_comparison 28 | static_assert(1 <=> 2 < 0); 29 | static_assert(2 <=> 1 > 0); 30 | static_assert(1 <=> 1 == 0); 31 | #else 32 | #pragma message("undefined __cpp_lib_three_way_comparison") 33 | #endif 34 | 35 | #if __cpp_char8_t 36 | /// [char8_t](https://en.cppreference.com/w/cpp/keyword/char8_t) 37 | char8_t char8; 38 | #endif 39 | 40 | /// [to_array](https://en.cppreference.com/w/cpp/container/array/to_array) 41 | 42 | auto to_array_demo = to_array("foo"); 43 | static_assert(to_array_demo.size() == 4); 44 | 45 | void init_20() 46 | { 47 | struct point { 48 | int x, y; 49 | }; 50 | struct line { 51 | point a, b; 52 | }; 53 | 54 | // [aggregate_initialization](https://en.cppreference.com/w/cpp/language/aggregate_initialization) 55 | 56 | #if __cplusplus > 201707 57 | point p1 = { .x = 1 }; 58 | assert(p1.x == 1); 59 | assert(!p1.y); 60 | 61 | point p2 { {}, 2 }; 62 | assert(p2.y == 2); 63 | assert(!p2.x); 64 | #endif 65 | #if __cpp_aggregate_paren_init >= 201902 66 | int a[](0, 1, 2); 67 | assert(a[2] == 2); 68 | line l2 = { 1, 2 }; 69 | assert(l2.a.x == 1); 70 | assert(l2.a.y == 2); 71 | #endif 72 | line l1 = {}; 73 | assert(!l1.a.x); 74 | line l3 = { 1, 2, 3, 4 }; // missing-braces 75 | assert(l3.b.x == 3); 76 | assert(l3.b.y == 4); 77 | } 78 | 79 | void types_20() 80 | { 81 | #if __cpp_lib_bit_cast 82 | assert(typeid(bit_cast(0)).name() == string { "d" }); 83 | #endif 84 | } 85 | 86 | void dynamic_memory_20() 87 | { 88 | #if !__GNUG__ 89 | /// Shared array 90 | /// [make_shared](https://en.cppreference.com/w/cpp/memory/shared_ptr/make_shared) 91 | auto a = make_shared(); 92 | static_assert(is_same_v); 93 | 94 | /// [contains](https://en.cppreference.com/w/cpp/container/map/contains) 95 | map m = { { 2, 3 } }; 96 | #if __cplusplus > 201707 && __GNUG__ > 8 97 | assert(m.contains(2)); 98 | #endif 99 | #if __cpp_lib_erase_if 100 | /// [erase_if](https://en.cppreference.com/w/cpp/container/map/erase_if) 101 | vector v = { 11, 12, 13 }; 102 | assert(erase_if(v, [](int a) { return a >= 13; }) == 1); 103 | assert(v.size() == 2); 104 | #endif 105 | #endif 106 | } 107 | 108 | namespace lambda { 109 | 110 | #if __cpp_template_template_args && __GNUG__ > 8 111 | /// [Lambda capture of parameter pack](https://en.cppreference.com/w/cpp/language/lambda#Lambda_capture) 112 | template 113 | auto make_lambda_with_parameter_pack_capture(Args&&... args) 114 | { 115 | return [... args = forward(args)] { 116 | return (... + args); 117 | }; 118 | } 119 | #endif 120 | 121 | void lambda_20() 122 | { 123 | #if __cplusplus >= 201709 124 | // generic lambda, operator() is a template with two parameters 125 | auto glambda = [](T a, auto&& b) { return a < b; }; 126 | assert(glambda(1, 2)); 127 | // generic lambda, operator() is a template with one parameter pack 128 | auto f = [](Ts&&... ts) { 129 | return 1; 130 | }; 131 | assert(f(1, 2, 3)); 132 | 133 | struct point { 134 | int x, y; 135 | }; 136 | auto point_lambda = [](T && var) {}; 137 | point_lambda({ 1, 2 }); 138 | 139 | #if __cpp_template_template_args && __GNUG__ > 8 140 | assert(make_lambda_with_parameter_pack_capture(1, 2, 3)() == 6); 141 | #endif 142 | #endif 143 | } 144 | 145 | } 146 | using namespace lambda; 147 | 148 | /// @} lang20 149 | 150 | /** 151 | @defgroup templ20 Templates 152 | 153 | [templates](https://en.cppreference.com/w/cpp/language/templates) 154 | 155 | @{ 156 | */ 157 | 158 | /** 159 | 160 | @defgroup conc20 Concepts 161 | 162 | https://en.wikipedia.org/wiki/Concepts_(C++) 163 | [constraints](https://en.cppreference.com/w/cpp/language/constraints) 164 | [concepts](https://en.cppreference.com/w/cpp/header/concepts) 165 | 166 | @{ 167 | */ 168 | 169 | /** 170 | @defgroup req20 'Requires' clause and expression 171 | @{ 172 | */ 173 | 174 | // Using [requires](https://en.cppreference.com/w/cpp/keyword/requires) 175 | 176 | template 177 | requires is_integral_v T constexpr requires_demo(T a) { return a + 1; } 178 | 179 | static_assert(requires_demo(1) == 2); 180 | 181 | /** 182 | requires-clause can be after function declaration and supports template overloading 183 | */ 184 | 185 | template 186 | auto constexpr requires_demo(T&& a) requires is_same_v { return 2; } 187 | static_assert(requires_demo(0.1) == 2); 188 | 189 | // Annotated example of complex requirement 190 | template 191 | requires // requires-clause 192 | is_signed_v ||(is_unsigned_v && !is_void_v) // constraint expression 193 | void complex_requirement_demo() 194 | { 195 | } 196 | 197 | /// Annotated example of requires-expression 198 | 199 | template 200 | requires // requires-clause 201 | requires() // requires-expression 202 | { 203 | true; 204 | } // unevaluated requirements sequence 205 | void requires_expression_demo() { } 206 | 207 | template 208 | requires requires(T a) { a / 0; } 209 | auto constexpr what(T a) { return 1; } 210 | static_assert(what(1) == 1); 211 | 212 | template 213 | requires requires(T a) { a[0]; } 214 | auto constexpr what(T a) { return 2; } 215 | static_assert(what("2") == 2); 216 | 217 | /** 218 | @} 219 | 220 | @defgroup conc_def_20 Concept definitions 221 | @{ 222 | */ 223 | 224 | /// trivial concepts as assignment 225 | template 226 | concept truism = true; 227 | 228 | #if !__cpp_lib_concepts 229 | 230 | /// short concept definition from a constraint directly 231 | template 232 | concept integral = is_integral_v; 233 | 234 | #endif 235 | 236 | /** 237 | defining concept with requires-expression 238 | */ 239 | 240 | template 241 | concept integral_req_ct = requires(T a) 242 | { 243 | is_integral_v; 244 | }; 245 | 246 | template 247 | constexpr T _inc2(T a) { return a + 1; } 248 | 249 | static_assert(_inc2(1) == 2); 250 | 251 | /** 252 | [Compound_Requirements](https://en.cppreference.com/w/cpp/language/constraints#Compound_Requirements) 253 | [convertible_to](https://en.cppreference.com/w/cpp/concepts/convertible_to) 254 | */ 255 | 256 | template 257 | concept compound_requirements = requires(T x) 258 | { 259 | { 260 | x + 1 261 | } -> convertible_to; 262 | { 263 | x * 2 264 | } -> same_as; 265 | }; 266 | 267 | /** 268 | 269 | @} conc_def_20 270 | 271 | @} conc20 272 | 273 | @} templ20 274 | 275 | @defgroup cor20 Coroutines 276 | @{ 277 | 278 | [coroutine](https://en.cppreference.com/w/cpp/coroutine) 279 | 280 | [coroutines](https://en.cppreference.com/w/cpp/language/coroutines) 281 | 282 | */ 283 | 284 | #if __cpp_impl_coroutine 285 | auto switch_to_new_thread(jthread& out) 286 | { 287 | struct awaitable { 288 | jthread* p_out; 289 | bool await_ready() { return false; } 290 | void await_suspend(coroutine_handle<> h) 291 | { 292 | jthread& out = *p_out; 293 | if (out.joinable()) 294 | throw runtime_error("Output jthread parameter not empty"); 295 | out = jthread([h] { h.resume(); }); 296 | } 297 | void await_resume() { } 298 | }; 299 | return awaitable { &out }; 300 | } 301 | 302 | struct task { 303 | struct promise_type { 304 | struct task get_return_object() { return {}; } 305 | suspend_never initial_suspend() { return {}; } 306 | suspend_never final_suspend() noexcept { return {}; } 307 | void return_void() { } 308 | void unhandled_exception() { } 309 | }; 310 | }; 311 | 312 | struct task resuming_on_new_thread(jthread& out) 313 | { 314 | auto starting_tid = this_thread::get_id(); 315 | // suspends coroutine 316 | co_await switch_to_new_thread(out); ///< [co_await](https://en.cppreference.com/w/cpp/keyword/co_await) 317 | // awaiter is destroyed here 318 | assert(this_thread::get_id() != starting_tid); 319 | } 320 | 321 | void coroutine_demo() 322 | { 323 | jthread out; 324 | resuming_on_new_thread(out); 325 | } 326 | 327 | #else 328 | void coroutine_demo() 329 | { 330 | } 331 | #pragma message("undefined __cpp_impl_coroutine") 332 | #endif 333 | 334 | /** 335 | @} cor20 336 | 337 | @defgroup other20 Other 338 | @{ 339 | 340 | TODO: 341 | 342 | [range-for](https://en.cppreference.com/w/cpp/language/range-for) 343 | [common_reference](https://en.cppreference.com/w/cpp/types/common_reference) 344 | 345 | */ 346 | 347 | #if __cpp_lib_ranges 348 | 349 | #include 350 | 351 | /// [ranges](https://en.cppreference.com/w/cpp/ranges) 352 | /// [range algorithms](https://en.cppreference.com/w/cpp/algorithm/ranges) 353 | /// [sort](https://en.cppreference.com/w/cpp/algorithm/ranges/sort) 354 | /// [distance](https://en.cppreference.com/w/cpp/iterator/ranges/distance) 355 | 356 | void sort_20() 357 | { 358 | vector v = { 5, 7, 4, 2, 8, 6, 1, 9, 1, 3 }; 359 | ranges::sort(v); 360 | assert(v.front() <= v.back()); 361 | assert(ranges::distance(v)); 362 | assert(!ranges::distance(v.begin(), v.begin())); 363 | } 364 | 365 | void ranges_20() 366 | { 367 | list data { 0, 1, 2, 3 }; 368 | /// [reverse_view](https://en.cppreference.com/w/cpp/ranges/reverse_view) 369 | #if !__clang_major__ 370 | auto r = data | views::reverse; 371 | // r is kind of transform_view 372 | vector result(r.begin(), r.end()); 373 | ranges::reverse_view rv { data }; 374 | assert(vector(rv.begin(), rv.end()) == result); 375 | assert((result == vector { 3, 2, 1, 0 })); 376 | #endif 377 | auto [min, max] = ranges::minmax(data); 378 | assert(min == 0); 379 | assert(max == 3); 380 | auto a = ranges::minmax(list { 3, 2, 1, 0 }); 381 | assert(a.min == 0); 382 | assert(a.max == 3); 383 | assert(!in_range(-1)); 384 | 385 | vector rev(ssize(data)); 386 | ranges::reverse_copy(data, begin(rev)); 387 | assert(rev[0] > rev[1]); 388 | } 389 | 390 | #else 391 | #pragma message("undefined __cpp_lib_ranges") 392 | #endif 393 | 394 | #include 395 | 396 | /// [source_location](https://en.cppreference.com/w/cpp/utility/source_location) 397 | 398 | void location_20() 399 | { 400 | auto l = experimental::source_location::current(); 401 | basic_stringstream buff; 402 | buff << l.file_name() << ":" << l.line() << ":" << l.column() << l.function_name(); 403 | assert(buff.str().length()); 404 | } 405 | 406 | /** 407 | [functional](https://en.cppreference.com/w/cpp/header/functional) 408 | [bind_front](https://en.cppreference.com/w/cpp/utility/functional/bind_front) 409 | */ 410 | 411 | void functional_20() 412 | { 413 | auto constexpr plus_one = std::bind_front(std::plus(), 1); 414 | static_assert(plus_one(2) == 3); 415 | } 416 | 417 | /// @} other20 418 | 419 | int main() 420 | { 421 | init_20(); 422 | types_20(); 423 | dynamic_memory_20(); 424 | lambda_20(); 425 | #if __cpp_lib_jthread 426 | jthread t([] {}); 427 | #endif 428 | coroutine_demo(); 429 | sort_20(); 430 | ranges_20(); 431 | location_20(); 432 | functional_20(); 433 | } 434 | /// @} 435 | 436 | /** 437 | @defgroup CPP C++ examples by version 438 | @brief from recent to oldest 439 | @{ 440 | @addtogroup CPP20 441 | @addtogroup CPP17 442 | @addtogroup CPP14 443 | @addtogroup CPP11 444 | @addtogroup CPP03 445 | @} 446 | */ 447 | -------------------------------------------------------------------------------- /cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | set(CMAKE_BUILD_TYPE Debug) 3 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic -Wno-unused") 4 | set(CMAKE_CXX_STANDARD_REQUIRED True) 5 | execute_process(COMMAND clang++ ${CXX_FLAGS} -std=gnu++2a ${CMAKE_SOURCE_DIR}/20.cpp -o 20) 6 | project(17) 7 | add_executable(17 17.cpp) 8 | set_property(TARGET 17 PROPERTY CXX_STANDARD 17) 9 | project(14) 10 | add_executable(14 14.cpp) 11 | set_property(TARGET 14 PROPERTY CXX_STANDARD 14) 12 | project(11) 13 | add_executable(11 11.cpp) 14 | set_property(TARGET 11 PROPERTY CXX_STANDARD 11) 15 | target_link_libraries(11 pthread) 16 | project(03) 17 | add_executable(03 03.cpp) 18 | set_property(TARGET 03 PROPERTY CXX_STANDARD 98) 19 | -------------------------------------------------------------------------------- /cpp/Doxyfile: -------------------------------------------------------------------------------- 1 | PROJECT_NAME = "C++ features by examples" 2 | INPUT = patterns.cpp 20.cpp 17.cpp 14.cpp 11.cpp 03.cpp 3 | EXTRACT_ALL = YES 4 | EXTRACT_STATIC = YES 5 | RECURSIVE = YES 6 | EXCLUDE = html CMakeFiles README.md lib tracer.hpp 7 | GENERATE_TREEVIEW = YES 8 | GENERATE_LATEX = NO 9 | HAVE_DOT = YES 10 | DOT_FONTSIZE = 15 11 | CALL_GRAPH = YES 12 | CALLER_GRAPH = YES 13 | DOT_IMAGE_FORMAT = svg 14 | #INTERACTIVE_SVG = YES 15 | DOT_TRANSPARENT = yes 16 | DOT_MULTI_TARGETS = yes 17 | DOT_CLEANUP = NO 18 | DOT_FONTNAME = Ubuntu 19 | #CASE_SENSE_NAMES = YES 20 | SOURCE_BROWSER = YES 21 | INLINE_SOURCES = YES 22 | QUIET = YES 23 | ENABLE_PREPROCESSING = YES 24 | EXCLUDE_SYMBOLS = assert requires double _* 25 | -------------------------------------------------------------------------------- /cpp/Makefile: -------------------------------------------------------------------------------- 1 | default: build 2 | ${MAKE} check 3 | 4 | e=20 17 14 11 03 5 | e+=patterns 6 | t=features.csv 7 | 8 | build: $e $t 9 | 10 | clean: 11 | rm -f $e $t || true 12 | rm -f *.gcov *.gcda *.gcno || true 13 | 14 | CXXFLAGS+=-Wall -Wno-unused 15 | CXXFLAGS+=-Wextra -Wno-missing-field-initializers 16 | CXXFLAGS+=-Wpedantic 17 | CXXFLAGS+=-Dgcc_extension 18 | CXXFLAGS+=-include features.cpp 19 | CXXFLAGS+=-g -fsanitize=leak 20 | LDLIBS+=-pthread 21 | CXXFLAGS+=--coverage 22 | 23 | ifneq (, $(shell which g++-10)) 24 | 20: CXX=g++-10 25 | 20: CXXFLAGS+=-fcoroutines -fconcepts -fgnu-tm 26 | 20: CXXFLAGS+=-fconcepts -fgnu-tm 27 | else 28 | 20: CXX=clang++-10 29 | 20: CXXFLAGS+=-Wno-missing-braces -Wno-unused-parameter 30 | endif 31 | 32 | 20: CXXFLAGS+=-std=c++2a 33 | 34 | 17 patterns: CXXFLAGS+=-std=c++17 35 | 14: CXXFLAGS+=-std=c++14 36 | 11: CXXFLAGS+=-std=c++11 37 | 03: CXXFLAGS+=-std=c++03 38 | 39 | check: build 40 | rm *.gcda || true 41 | for a in $e; do ./$$a || exit; done 42 | 43 | features.csv: 44 | #./03 && ./11 && ./14 && ./17 && ./20 45 | bash -c "export features=1; join --nocheck-order <(join <(join <(join <(./03) <(./11)) <(./14)) <(./17)) <(./20)" \ 46 | > $@ 47 | 48 | coverage: build 49 | ${MAKE} check &> /dev/null 50 | for a in $e; do gcov ./$$a 2> /dev/null || exit; done 51 | grep -H '##' *cpp.gcov | sed 's/\.gcov: \+#\+: \+\([0-9]\+\):/:\1: untested:/' 52 | -------------------------------------------------------------------------------- /cpp/README.md: -------------------------------------------------------------------------------- 1 | # C++ features examples 2 | 3 | * Minimal working features examples of 4 | * [Design and OOP patterns](patterns.cpp) 5 | * [C++20](20.cpp) 6 | * [C++17](17.cpp) 7 | * [C++14](14.cpp) 8 | * [C++11](11.cpp) 9 | * [C++98](03.cpp) 10 | * [Coroutines](https://github.com/makelinux/examples/search?q=cor20) 11 | * [Concepts](https://github.com/makelinux/examples/search?q=conc20) 12 | * Lambda expressions 13 | * Templates 14 | * [Reveals features support by compiler](features.cpp) 15 | * A lot of [Doxygen inline and online documentation](https://makelinux.github.io/docs/examples/cpp/) 16 | -------------------------------------------------------------------------------- /cpp/core_guidelines.cc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/makelinux/examples/180f8b693145b2feaf3bfd7e3b90ab9d061fbba9/cpp/core_guidelines.cc -------------------------------------------------------------------------------- /cpp/features.cpp: -------------------------------------------------------------------------------- 1 | // Check and dump C++ feature test defines 2 | // 3 | // See https://en.cppreference.com/w/cpp/feature_test 4 | 5 | #include 6 | 7 | /* 8 | 9 | Updating from /usr/include/: 10 | 11 | comm -13 <(grep check features.cpp | grep -o '__cpp_\w*' |sort -u) \ 12 | <(grep --binary-files=without-match -ro '__cpp_\w*' -h . /usr/include/ | sort -u) \ 13 | | awk '{ print "check(" $1 ");";}' 14 | 15 | Updating from web: 16 | 17 | comm -13 <(grep check features.cpp | grep -o '__cpp_\w*' | sort -u) \ 18 | <(wget -q -O- 'https://en.cppreference.com/mwiki/index.php?title=cpp/feature_test&action=raw' | \ 19 | sed 's/_}}{{c|/_/' | grep -o '__cpp\w*' | sort -u) | \ 20 | awk '{ print "check(" $1 ");";}' 21 | 22 | comm -13 <(grep check features.cpp | grep -o '__cpp_\w*' | sort -u) \ 23 | <(wget -q -O- https://raw.githubusercontent.com/BRevzin/sd6/master/macros.yaml | \ 24 | awk '/name: __cpp/ { print $3 }' | sort -u) | \ 25 | awk '{ print "check(" $1 ");";}' 26 | 27 | Tip: append result of snippets above to this file. 28 | 29 | Builing table: 30 | export features=1 31 | join <(join <(join <(join <(./03) <(./11)) <(./14)) <(./17)) <(./20) > a.csv 32 | 33 | */ 34 | 35 | #include 36 | 37 | using namespace std; 38 | 39 | // Run checks as global constructors automatically 40 | // without manual operations 41 | 42 | #define concat2(a, b) a##b 43 | 44 | #define concat(a, b) concat2(a, b) 45 | 46 | #define u(a) concat(a, __LINE__) 47 | 48 | #define check2(x, y) \ 49 | do { \ 50 | cout << x; \ 51 | if (string(x) != #y) \ 52 | cout << " " << #y; \ 53 | else \ 54 | cout << " ------"; \ 55 | cout << endl; \ 56 | } while (0) 57 | 58 | #define check(x) \ 59 | static class c##x { \ 60 | public: \ 61 | c##x() \ 62 | { \ 63 | if (std::getenv("features")) \ 64 | check2(#x, x); \ 65 | } \ 66 | } c##x // global instantiation 67 | 68 | // Just append new check at the end of the file 69 | 70 | check(__GNUC__); 71 | check(__GNUC_MINOR__); 72 | check(__GNUC_PATCHLEVEL__); 73 | check(__GNUG__); 74 | check(__clang__); 75 | check(__clang_major__); 76 | check(__clang_minor__); 77 | check(__clang_patchlevel__); 78 | check(__cplusplus); 79 | check(__cpp_exceptions); 80 | check(__cpp_rtti); 81 | check(__cpp_static_assert); 82 | check(__cpp_delegating_constructors); 83 | check(__cpp_rvalue_references); 84 | check(__cpp_alias_templates); 85 | check(__cpp_variadic_templates); 86 | check(__cpp_unicode_characters); 87 | check(__cpp_constexpr); 88 | check(__cpp_decltype); 89 | check(__cpp_raw_strings); 90 | check(__cpp_ref_qualifiers); 91 | check(__cpp_unicode_literals); 92 | check(__cpp_initializer_lists); 93 | check(__cpp_threadsafe_static_init); 94 | check(__cpp_attributes); 95 | check(__cpp_nsdmi); 96 | check(__cpp_user_defined_literals); 97 | check(__cpp_lambdas); 98 | check(__cpp_range_based_for); 99 | check(__cpp_lib_result_of_sfinae); 100 | check(__cpp_binary_literals); 101 | check(__cpp_lib_is_null_pointer); 102 | check(__cpp_lib_allocator_is_always_equal); 103 | check(__cpp_lib_allocator_traits_is_always_equal); 104 | check(__cpp_lib_incomplete_container_elements); 105 | check(__cpp_inheriting_constructors); 106 | check(__cpp_hex_float); 107 | 108 | // C++14 109 | 110 | check(__cpp_aggregate_nsdmi); 111 | check(__cpp_decltype_auto); 112 | check(__cpp_generic_lambdas); 113 | check(__cpp_init_captures); 114 | check(__cpp_lib_exchange_function); 115 | check(__cpp_lib_integer_sequence); 116 | check(__cpp_lib_integral_constant_callable); 117 | check(__cpp_lib_robust_nonmodifying_seq_ops); 118 | check(__cpp_lib_string_udls); 119 | check(__cpp_lib_transformation_trait_aliases); 120 | check(__cpp_lib_tuples_by_type); 121 | check(__cpp_return_type_deduction); 122 | check(__cpp_variable_templates); 123 | check(__cpp_sized_deallocation); 124 | check(__cpp_lib_is_final); 125 | check(__cpp_lib_make_reverse_iterator); 126 | check(__cpp_lib_tuple_element_t); 127 | check(__cpp_lib_transparent_operators); 128 | 129 | // C++17 130 | 131 | check(__cpp_enumerator_attributes); 132 | check(__cpp_lib_invoke); 133 | check(__cpp_lib_nonmember_container_access); 134 | check(__cpp_lib_uncaught_exceptions); 135 | check(__cpp_lib_unordered_map_insertion); 136 | check(__cpp_lib_unordered_map_try_emplace); 137 | check(__cpp_lib_void_t); 138 | check(__cpp_namespace_attributes); 139 | check(__cpp_nontype_template_args); 140 | check(__cpp_lib_bool_constant); 141 | check(__cpp_lib_as_const); 142 | check(__cpp_lib_logical_traits); 143 | check(__cpp_lib_type_trait_variable_templates); 144 | check(__cpp_noexcept_function_type); 145 | check(__cpp_aggregate_bases); 146 | check(__cpp_capture_star_this); 147 | check(__cpp_fold_expressions); 148 | check(__cpp_lib_addressof_constexpr); 149 | check(__cpp_lib_apply); 150 | check(__cpp_lib_array_constexpr); 151 | check(__cpp_lib_boyer_moore_searcher); 152 | check(__cpp_lib_clamp); 153 | check(__cpp_lib_is_swappable); 154 | check(__cpp_lib_not_fn); 155 | check(__cpp_lib_sample); 156 | check(__cpp_lib_string_view); 157 | check(__cpp_aligned_new); 158 | check(__cpp_guaranteed_copy_elision); 159 | check(__cpp_if_constexpr); 160 | check(__cpp_inline_variables); 161 | check(__cpp_lib_has_unique_object_representations); 162 | check(__cpp_lib_launder); 163 | check(__cpp_lib_make_from_tuple); 164 | check(__cpp_lib_node_extract); 165 | check(__cpp_lib_optional); 166 | check(__cpp_lib_raw_memory_algorithms); 167 | check(__cpp_nontype_template_parameter_auto); 168 | check(__cpp_structured_bindings); 169 | check(__cpp_lib_constexpr_char_traits); 170 | check(__cpp_template_template_args); 171 | check(__cpp_variadic_using); 172 | check(__cpp_deduction_guides); 173 | check(__cpp_lib_is_aggregate); 174 | check(__cpp_lib_is_invocable); 175 | 176 | // C++20 gcc-9 177 | 178 | check(__cpp_transactional_memory); 179 | check(__cpp_concepts); 180 | check(__cpp_conditional_explicit); 181 | check(__cpp_impl_destroying_delete); 182 | check(__cpp_lib_destroying_delete); 183 | check(__cpp_nontype_template_parameter_class); 184 | check(__cpp_char8_t); 185 | check(__cpp_lib_char8_t); 186 | check(__cpp_lib_is_constant_evaluated); 187 | check(__cpp_lib_erase_if); 188 | check(__cpp_lib_bounded_array_traits); 189 | check(__cpp_lib_bind_front); 190 | 191 | // Not yet implemented 192 | 193 | check(__cpp_aggregate_paren_init); 194 | check(__cpp_consteval); 195 | check(__cpp_constexpr_in_decltype); 196 | check(__cpp_constinit); 197 | check(__cpp_coroutines); 198 | check(__cpp_impl_three_way_comparison); 199 | check(__cpp_lib_any); 200 | check(__cpp_lib_assume_aligned); 201 | check(__cpp_lib_atomic_flag_test); 202 | check(__cpp_lib_atomic_float); 203 | check(__cpp_lib_atomic_is_always_lock_free); 204 | check(__cpp_lib_atomic_lock_free_type_aliases); 205 | check(__cpp_lib_atomic_ref); 206 | check(__cpp_lib_atomic_shared_ptr); 207 | check(__cpp_lib_atomic_value_initialization); 208 | check(__cpp_lib_atomic_wait); 209 | check(__cpp_lib_barrier); 210 | check(__cpp_lib_bit_cast); 211 | check(__cpp_lib_bitops); 212 | check(__cpp_lib_byte); 213 | check(__cpp_lib_chrono); 214 | check(__cpp_lib_chrono_udls); 215 | check(__cpp_lib_complex_udls); 216 | check(__cpp_lib_concepts); 217 | check(__cpp_lib_constexpr); 218 | check(__cpp_lib_constexpr_algorithms); 219 | check(__cpp_lib_constexpr_complex); 220 | check(__cpp_lib_constexpr_dynamic_alloc); 221 | check(__cpp_lib_constexpr_functional); 222 | check(__cpp_lib_constexpr_iterator); 223 | check(__cpp_lib_constexpr_memory); 224 | check(__cpp_lib_constexpr_numeric); 225 | check(__cpp_lib_constexpr_string); 226 | check(__cpp_lib_constexpr_string_view); 227 | check(__cpp_lib_constexpr_swap_algorithms); 228 | check(__cpp_lib_constexpr_tuple); 229 | check(__cpp_lib_constexpr_utility); 230 | check(__cpp_lib_constexpr_vector); 231 | check(__cpp_lib_enable_shared_from_this); 232 | check(__cpp_lib_endian); 233 | check(__cpp_lib_execution); 234 | check(__cpp_lib_experimental_any); 235 | check(__cpp_lib_experimental_boyer_moore_searching); 236 | check(__cpp_lib_experimental_detect); 237 | check(__cpp_lib_experimental_erase_if); 238 | check(__cpp_lib_experimental_filesystem); 239 | check(__cpp_lib_experimental_gcd_lcm); 240 | check(__cpp_lib_experimental_logical_traits); 241 | check(__cpp_lib_experimental_make_array); 242 | check(__cpp_lib_experimental_memory_resources); 243 | check(__cpp_lib_experimental_net); 244 | check(__cpp_lib_experimental_net_extensible); 245 | check(__cpp_lib_experimental_not_fn); 246 | check(__cpp_lib_experimental_observer_ptr); 247 | check(__cpp_lib_experimental_optional); 248 | check(__cpp_lib_experimental_ostream_joiner); 249 | check(__cpp_lib_experimental_randint); 250 | check(__cpp_lib_experimental_sample); 251 | check(__cpp_lib_experimental_source_location); 252 | check(__cpp_lib_experimental_string_view); 253 | check(__cpp_lib_experimental_tuple); 254 | check(__cpp_lib_experimental_type_trait_variable_templates); 255 | check(__cpp_lib_filesystem); 256 | check(__cpp_lib_format); 257 | check(__cpp_lib_gcd); 258 | check(__cpp_lib_gcd_lcm); 259 | check(__cpp_lib_generic_associative_lookup); 260 | check(__cpp_lib_generic_unordered_lookup); 261 | check(__cpp_lib_hardware_interference_size); 262 | check(__cpp_lib_hypot); 263 | check(__cpp_lib_int_pow2); 264 | check(__cpp_lib_interpolate); 265 | check(__cpp_lib_is_layout_compatible); 266 | check(__cpp_lib_is_pointer_interconvertible); 267 | check(__cpp_lib_jthread); 268 | check(__cpp_lib_latch); 269 | check(__cpp_lib_lcm); 270 | check(__cpp_lib_list_remove_return_type); 271 | check(__cpp_lib_make_unique); 272 | check(__cpp_lib_map_insertion); 273 | check(__cpp_lib_map_try_emplace); 274 | check(__cpp_lib_math_constants); 275 | check(__cpp_lib_math_special_functions); 276 | check(__cpp_lib_memory_resource); 277 | check(__cpp_lib_nothrow_convertible); 278 | check(__cpp_lib_null_iterators); 279 | check(__cpp_lib_parallel_algorithm); 280 | check(__cpp_lib_polymorphic_allocator); 281 | check(__cpp_lib_quoted_string_io); 282 | check(__cpp_lib_ranges); 283 | check(__cpp_lib_remove_cvref); 284 | check(__cpp_lib_scoped_lock); 285 | check(__cpp_lib_semaphore); 286 | check(__cpp_lib_shared_mutex); 287 | check(__cpp_lib_shared_ptr_arrays); 288 | check(__cpp_lib_shared_ptr_weak_type); 289 | check(__cpp_lib_shared_timed_mutex); 290 | check(__cpp_lib_shift); 291 | check(__cpp_lib_smart_ptr_default_init); 292 | check(__cpp_lib_source_location); 293 | check(__cpp_lib_span); 294 | check(__cpp_lib_ssize); 295 | check(__cpp_lib_starts_ends_with); 296 | check(__cpp_lib_syncbuf); 297 | check(__cpp_lib_three_way_comparison); 298 | check(__cpp_lib_to_address); 299 | check(__cpp_lib_to_array); 300 | check(__cpp_lib_to_chars); 301 | check(__cpp_lib_type_identity); 302 | check(__cpp_lib_unwrap_ref); 303 | check(__cpp_lib_variant); 304 | check(__cpp_constexpr_dynamic_alloc); 305 | check(__cpp_designated_initializers); 306 | check(__cpp_lib_generic_unordered_hash_lookup); 307 | check(__cpp_modules); 308 | check(__cpp_using_enum); 309 | 310 | check(__cpp_impl_coroutine); 311 | check(__cpp_lib_coroutine); 312 | check(__cpp_lib_integer_comparison_functions); 313 | check(__cpp_lib_is_nothrow_convertible); 314 | 315 | check(__cpp_cxx23_stub); 316 | check(__cpp_lib_cxx23_stub); 317 | check(__cpp_lib_smart_ptr_for_overwrite); 318 | 319 | check(__cpp_lib_is_scoped_enum); 320 | check(__cpp_lib_stacktrace); 321 | check(__cpp_lib_stdatomic_h); 322 | check(__cpp_lib_string_contains); 323 | check(__cpp_size_t_suffix); 324 | -------------------------------------------------------------------------------- /cpp/patterns.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | /** 6 | @file 7 | @brief skeleton C++ examples of OOP and Design patterns 8 | 9 | © 2021 Constantine Shulyupin 10 | 11 | Patterns help to conform to [SOLID principles](https://en.wikipedia.org/wiki/SOLID): 12 | - [Single-responsibility](https://en.wikipedia.org/wiki/Single-responsibility_principle) 13 | - high [cohesion](https://en.wikipedia.org/wiki/Cohesion_(computer_science)) 14 | - [Open-closed](https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle) 15 | - open for extension 16 | - but closed for modification 17 | - [Liskov substitution](https://en.wikipedia.org/wiki/Liskov_substitution_principle) 18 | - [composition over inheritance](https://en.wikipedia.org/wiki/Composition_over_inheritance) 19 | - [Interface segregation](https://en.wikipedia.org/wiki/Interface_segregation_principle) 20 | - use many specific interfaces 21 | - [Dependency inversion](https://en.wikipedia.org/wiki/Dependency_inversion_principle) 22 | - don't depend on implementations 23 | - depend on interfaces 24 | - [Loose coupling](https://en.wikipedia.org/wiki/Loose_coupling) 25 | 26 | 27 | Coding style: 28 | Using struct because is it like class with default public members and methods. 29 | Less is more. Skeleton code with minimal optional code and duplications. 30 | Each word "Sample" in an inventer assumes multiple instances like Sample1, Sample2 ... SampleN 31 | 32 | Contents 33 | - @ref OOP 34 | - @ref DP 35 | 36 | */ 37 | 38 | /** 39 | @defgroup OOP C++ OOP patterns 40 | @brief some examples in C++ 41 | 42 | Four Pillars of 43 | [Object-oriented_programming](https://en.wikipedia.org/wiki/Object-oriented_programming): 44 | - [Abstraction](https://en.wikipedia.org/wiki/Abstraction_(computer_science)) 45 | - [Encapsulation](https://en.wikipedia.org/wiki/Encapsulation_(computer_programming)) 46 | - [Inheritance](https://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)) 47 | - [Polymorphism](https://en.wikipedia.org/wiki/Polymorphism_(computer_science)) 48 | 49 | [object-oriented-programming-in-cpp](https://www.geeksforgeeks.org/object-oriented-programming-in-cpp) 50 | 51 | [class](https://en.cppreference.com/w/cpp/language/class) 52 | 53 | [derived_class](https://en.cppreference.com/w/cpp/language/derived_class) 54 | 55 | [abstract_class](https://en.cppreference.com/w/cpp/language/abstract_class) 56 | 57 | [shared_lock](https://en.cppreference.com/w/cpp/thread/shared_lock) 58 | 59 | Three independent interfaces 60 | Setter_interface, Getter_interface and Change_interface demonstrate 61 | [Interface segregation](https://en.wikipedia.org/wiki/Interface_segregation_principle) 62 | 63 | [Use multiple inheritance to represent multiple distinct interfaces](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#c135-use-multiple-inheritance-to-represent-multiple-distinct-interfaces) 64 | 65 | @{ 66 | */ 67 | 68 | struct Module { }; 69 | 70 | /// [Object composition](https://en.wikipedia.org/wiki/Object_composition) 71 | struct Composition { 72 | Module m1, m2; 73 | }; 74 | 75 | /** [Aggregation](https://en.wikipedia.org/wiki/Object_composition#Aggregation) 76 | by reference 77 | */ 78 | struct Reference { 79 | Module &m1, &m2; 80 | Reference() = default; 81 | }; 82 | 83 | /** [Pointer](https://en.wikipedia.org/wiki/Pointer_(computer_programming)#C_and_C++) 84 | is also can be used for aggregation 85 | */ 86 | struct Pointer { 87 | Module* ptr; 88 | shared_ptr sm; 89 | unique_ptr um; 90 | }; 91 | 92 | /// [Associations](https://en.wikipedia.org/wiki/Association_(object-oriented_programming)) 93 | void associations_demo() 94 | { 95 | Module m1, m2; 96 | Reference r { m1, m2 }; 97 | 98 | Pointer p { &m1 }; 99 | // References can't be changed or zeroed like pointers during runtime. 100 | p.ptr = nullptr; 101 | } 102 | 103 | /// @brief is a sample of setter abstract interface for Synchronized_encapsulated_value 104 | template 105 | struct Setter_interface { 106 | virtual void set(ValueType i) = 0; 107 | virtual ~Setter_interface() noexcept = default; 108 | }; 109 | 110 | template 111 | struct Getter_interface 112 | /// @brief is a sample of getter abstract interface for Synchronized_encapsulated_value 113 | { 114 | virtual ValueType get() const = 0; 115 | virtual ~Getter_interface() noexcept = default; 116 | }; 117 | 118 | template 119 | struct Change_interface 120 | /// @brief is a sample of changer abstract interface for Synchronized_encapsulated_value 121 | { 122 | virtual void change(ValueType c) = 0; 123 | virtual ~Change_interface() noexcept = default; 124 | }; 125 | 126 | template 127 | class Synchronized_encapsulated_value 128 | /** 129 | @brief [encapsulating](https://en.wikipedia.org/wiki/Encapsulation_(computer_programming)) 130 | class with only public accessor and [mutator](https://en.wikipedia.org/wiki/Mutator_method) intrfaces 131 | 132 | Classes by default are private. This class doesn't contain public members. 133 | 134 | Uses [Readers–writer_lock](https://en.wikipedia.org/wiki/Readers–writer_lock). 135 | 136 | See also: 137 | - [Boost synchronized values](https://www.boost.org/doc/libs/release/doc/html/thread/sds.html#thread.sds.synchronized_valuesxxx) 138 | - [boost/thread/synchronized_value.hpp](https://github.com/boostorg/thread/blob/HEAD/include/boost/thread/synchronized_value.hpp) 139 | */ 140 | : public Setter_interface, 141 | public Getter_interface, 142 | public Change_interface { 143 | void set(ValueType i) override 144 | { 145 | scoped_lock writer_lock(mtx); 146 | value = i; 147 | } 148 | 149 | ValueType get() const override 150 | { 151 | shared_lock reader_lock(mtx); /// [reader writer locks](https://www.modernescpp.com/index.php/reader-writer-locks) 152 | return value; 153 | } 154 | 155 | void change(ValueType c) override 156 | { 157 | scoped_lock writer_lock(mtx); 158 | value += c; 159 | } 160 | 161 | mutable shared_mutex mtx; ///< [shared_mutex](https://en.cppreference.com/w/cpp/thread/shared_mutex) 162 | ValueType value; 163 | }; 164 | 165 | void synchronized_encapsulated_value() 166 | /** 167 | Lambda expression 'client' demonstrates [Dependency inversion](https://en.wikipedia.org/wiki/Dependency_inversion_principle) - 168 | it doesn't depends from implementation Synchronized_encapsulated_value but depends only from interfaces. 169 | */ 170 | 171 | { 172 | auto client = [](Setter_interface& s, Getter_interface& g) { 173 | s.set(1); 174 | assert(g.get() == 1); 175 | }; 176 | Synchronized_encapsulated_value v; 177 | Setter_interface& s = v; 178 | Getter_interface& g = v; 179 | client(s, g); 180 | 181 | auto client2 = [](Setter_interface& s, Getter_interface& g) { 182 | s.set("abc"); 183 | assert(g.get() == "abc"); 184 | }; 185 | Synchronized_encapsulated_value v2; 186 | Setter_interface& s2(v2); 187 | Getter_interface& g2(v2); 188 | Change_interface& c2(v2); 189 | client2(s2, g2); 190 | c2.change("de"); 191 | assert(g2.get() == "abcde"); 192 | } 193 | 194 | void oop_demo() 195 | { 196 | associations_demo(); 197 | synchronized_encapsulated_value(); 198 | } 199 | 200 | /// @} 201 | 202 | /** 203 | @defgroup DP Design patterns skeleton examples 204 | @brief [Software design patterns](https://en.wikipedia.org/wiki/Software_design_pattern) 205 | 206 | https://refactoring.guru/design-patterns 207 | 208 | [C++ Programming: Code patterns design](https://en.wikibooks.org/wiki/C++_Programming/Code/Design_Patterns) 209 | 210 | Disclaimer: 211 | 212 | Example code below for simplicity doesn't utilize synchronization, 213 | privatization and other administrative functions. 214 | 215 | Don't forget to add locking, synchronization, encapsulation, privatization, 216 | protection manually where it is required when using examples below. 217 | 218 | @{ 219 | */ 220 | 221 | struct Interface 222 | /// @brief is a common pure virtual interface 223 | { 224 | virtual int method() = 0; 225 | virtual ~Interface() noexcept = default; 226 | }; 227 | 228 | /** 229 | @defgroup CP Creational 230 | @brief [Creational patterns](https://en.wikipedia.org/wiki/Creational_pattern) 231 | 232 | https://refactoring.guru/design-patterns/creational-patterns 233 | 234 | @{ 235 | */ 236 | 237 | /** 238 | The singleton will be automatically safely instantiated on the first call. 239 | 240 | Define constructor body after the define */ 241 | 242 | #define SINGLETON(Singleton) \ 243 | public: \ 244 | /* Meyers Singleton realization */ \ 245 | static Singleton& instance() \ 246 | { \ 247 | static Singleton me; \ 248 | return me; \ 249 | } \ 250 | Singleton(const Singleton&) = delete; \ 251 | Singleton& operator=(const Singleton&) = delete; \ 252 | Singleton(Singleton&&) = delete; \ 253 | Singleton& operator=(Singleton&&) = delete; \ 254 | \ 255 | private: \ 256 | Singleton() 257 | 258 | struct Singleton_demo { 259 | SINGLETON(Singleton_demo) {}; 260 | }; 261 | 262 | struct Factory_method_demo { 263 | virtual unique_ptr factory_method() = 0; 264 | 265 | int client() 266 | { 267 | auto p(factory_method()); 268 | return p->method(); 269 | }; 270 | }; 271 | 272 | struct Sample_product 273 | : Interface { 274 | int data; 275 | int method() override { return data; } 276 | Sample_product(int d = 0) 277 | : data(d) 278 | { 279 | } 280 | }; 281 | 282 | struct Sample_factory_method_demo 283 | : Factory_method_demo { 284 | unique_ptr factory_method() override 285 | { 286 | return make_unique(123); 287 | } 288 | }; 289 | 290 | struct Abstract_factory { 291 | virtual unique_ptr create() = 0; 292 | }; 293 | 294 | struct Sample_factory 295 | : Abstract_factory { 296 | virtual unique_ptr create() 297 | { 298 | return make_unique(); 299 | } 300 | }; 301 | 302 | struct Prototype 303 | /// @brief is the factory of himself 304 | : Abstract_factory, 305 | Interface { 306 | 307 | int method() override { return 1; } 308 | unique_ptr create() override 309 | { 310 | auto clone = new Prototype(*this); 311 | return unique_ptr(clone); 312 | } 313 | }; 314 | 315 | struct Builder { 316 | int data = 0; 317 | Builder& add(int i) 318 | { 319 | data += i; 320 | return *this; 321 | } 322 | 323 | Builder& operator<<(int i) { return add(i); } 324 | 325 | Interface& create() 326 | { 327 | return *new Sample_product(data); 328 | } 329 | }; 330 | 331 | void creational_patterns_demo() 332 | { 333 | Singleton_demo& singe = Singleton_demo::instance(); 334 | 335 | unique_ptr factory(new Sample_factory()); 336 | 337 | auto product = factory->create(); 338 | 339 | Prototype p1; 340 | auto p2 = p1.create(); 341 | 342 | Sample_factory_method_demo C; 343 | assert(C.client() == 123); 344 | 345 | Interface& p = (Builder().add(1).add(2) << 3 << 4).create(); 346 | assert(p.method() == 10); 347 | // stringstream looks like string builder 348 | delete &p; 349 | } 350 | 351 | /// @} CP 352 | 353 | /** 354 | @defgroup SP Structural 355 | @brief [Structural patterns](https://en.wikipedia.org/wiki/Structural_pattern) 356 | 357 | https://refactoring.guru/design-patterns/structural-patterns 358 | 359 | @{ 360 | */ 361 | 362 | struct Standalone 363 | /** @brief is wrapped by Bridge. AKA adaptee of Adapter 364 | 365 | It could be a legacy interface playing adaptee role in Adapter pattern 366 | */ 367 | { 368 | float standalone_method() const 369 | { 370 | return 1.01; 371 | } 372 | }; 373 | 374 | struct Bridge 375 | /// @brief is a wrapper using different from Standalone interface. AKA Adapter 376 | : public Interface { 377 | Bridge(Standalone& s) 378 | : standalone(s) 379 | { 380 | } 381 | int method() override 382 | { 383 | return this->standalone.standalone_method(); 384 | } 385 | 386 | private: 387 | Standalone& standalone; 388 | }; 389 | 390 | struct Proxy 391 | /// @brief is a opaque wrapper with same as wrapped object Interface 392 | : public Interface { 393 | Proxy(Interface& o) 394 | : subject(o) 395 | { 396 | } 397 | int method() override 398 | { 399 | return this->subject.method(); 400 | } 401 | 402 | private: 403 | Interface& subject; 404 | }; 405 | 406 | struct Decorator 407 | /// @brief is a partial wrapper of an object with same as wrapped object Interface 408 | : public Interface { 409 | Decorator(Interface& o) 410 | : subject(o) 411 | { 412 | } 413 | int method() override 414 | { 415 | return 100 + this->subject.method(); 416 | } 417 | Interface& subject; // decorated object is public 418 | }; 419 | 420 | struct Composite 421 | : public Interface { 422 | int method() override 423 | { 424 | for (Interface& i : children) 425 | i.method(); 426 | return 0; 427 | } 428 | forward_list> children; 429 | }; 430 | 431 | void structural_patterns_demo() 432 | { 433 | Standalone sa; 434 | Bridge br(sa); 435 | br.method(); 436 | Proxy p(br); 437 | Decorator dec(br); 438 | dec.method(); 439 | dec.subject.method(); 440 | p.method(); 441 | Composite comp; 442 | comp.children.push_front(p); 443 | comp.method(); 444 | } 445 | 446 | /// @} SP 447 | 448 | /** 449 | @defgroup BP Behavioral 450 | @brief [Behavioral patterns](https://en.wikipedia.org/wiki/Behavioral_pattern) 451 | 452 | https://refactoring.guru/design-patterns/behavioral-patterns 453 | 454 | @{ 455 | */ 456 | 457 | /** 458 | Credit: [observer](https://cpppatterns.com/patterns/observer.html) 459 | */ 460 | 461 | struct Subject; 462 | 463 | struct Observer 464 | /// @brief is virtual observer of a Subject 465 | { 466 | /// @brief without arguments 467 | virtual void notify() {}; 468 | /// @brief with the only Subject argument 469 | virtual void update(Subject& subject) {}; 470 | virtual ~Observer() noexcept = default; 471 | }; 472 | 473 | struct Subject 474 | /// @brief of Observer 475 | { 476 | void notify_observers() 477 | { 478 | for (Observer& o : observers) { 479 | o.notify(); 480 | o.update(*this); 481 | } 482 | } 483 | forward_list> observers; 484 | }; 485 | 486 | void observer_demo() 487 | { 488 | Observer o; 489 | Subject s; 490 | s.observers.push_front(o); 491 | s.notify_observers(); 492 | } 493 | 494 | /** 495 | @defgroup PS Publish–subscribe pattern 496 | @brief [Publish–subscribe pattern](https://en.wikipedia.org/wiki/Publish–subscribe_pattern) 497 | 498 | @{ 499 | */ 500 | 501 | struct Message { }; 502 | 503 | struct Subscriber { 504 | void message(Message& m) {}; 505 | }; 506 | 507 | struct Publisher { 508 | map>> topic_subscribers; 509 | 510 | void publish(const string& topic, Message& m) 511 | { 512 | for (Subscriber& s : topic_subscribers[topic]) 513 | s.message(m); 514 | } 515 | }; 516 | 517 | void publisher_subscriber_demo() 518 | { 519 | Subscriber sub; 520 | Publisher pub; 521 | pub.topic_subscribers["sample_topic"].push_front(sub); 522 | Message m; 523 | pub.publish("sample_topic", m); 524 | } 525 | 526 | /// @} PS 527 | 528 | /** 529 | [Mediator_pattern](https://en.wikipedia.org/wiki/Mediator_pattern) 530 | 531 | https://refactoring.guru/design-patterns/mediator 532 | */ 533 | 534 | struct Mediator; 535 | 536 | struct Member { 537 | Mediator* mediator; 538 | void send(Message&); 539 | void receive(Message&) { } 540 | }; 541 | 542 | struct Mediator { 543 | void register_member(Member& m) 544 | { 545 | m.mediator = this; 546 | members.push_front(m); 547 | } 548 | void dispatch(Message& msg) 549 | { 550 | for (Member& m : members) 551 | m.receive(msg); 552 | } 553 | forward_list> members; 554 | }; 555 | 556 | void Member::send(Message& m) 557 | { 558 | mediator->dispatch(m); 559 | } 560 | 561 | void mediator_demo() 562 | { 563 | Member m1, m2; 564 | Mediator md; 565 | md.register_member(m1); 566 | md.register_member(m2); 567 | Message msg; 568 | m1.send(msg); 569 | } 570 | 571 | struct Command 572 | /** @brief encapsulates arguments. AKA Intent, operation. 573 | 574 | [Command pattern](https://en.wikipedia.org/wiki/Command_pattern) 575 | 576 | https://refactoring.guru/design-patterns/command/cpp/example 577 | */ 578 | { 579 | virtual int execute() { return -1; }; 580 | }; 581 | 582 | /** 583 | @defgroup visitor Visitor 584 | @brief [Visitor pattern](https://en.wikipedia.org/wiki/Visitor_pattern) 585 | 586 | https://refactoring.guru/design-patterns/visitor/cpp/example 587 | @{ 588 | */ 589 | 590 | struct Abstract_visitor; 591 | 592 | struct Component 593 | /// @brief accepts a pure virtual Abstract_visitor 594 | { 595 | virtual string component_accept(Abstract_visitor&) const = 0; 596 | virtual ~Component() = default; 597 | }; 598 | 599 | string client_visit(const forward_list>& components, 600 | const forward_list>& visitors) 601 | /// @brief knows only virtual visitor and component 602 | { 603 | string res; 604 | for (auto&& v : visitors) 605 | for (auto&& c : components) { 606 | assert(typeid(c) != typeid(Component)); 607 | res += string(__func__) + " > " + c->component_accept(*v.get()); 608 | } 609 | return res; 610 | } 611 | 612 | struct Sample_component; 613 | struct Abstract_visitor 614 | /// @brief is a pure virtual visitor of Sample_component and other specific components 615 | { 616 | /// overloaded function for each component subtype 617 | virtual string visit(const Sample_component&) const = 0; 618 | virtual ~Abstract_visitor() noexcept = default; 619 | }; 620 | 621 | struct Sample_component 622 | : public Component 623 | /** @brief one of many components 624 | is independent from Sample_visitor and implementations of function visit. 625 | */ 626 | { 627 | string component_accept(Abstract_visitor& visitor) const override 628 | { 629 | assert(typeid(*this) == typeid(Sample_component)); 630 | assert(typeid(visitor) != typeid(Abstract_visitor)); 631 | return string(__func__) + " > " + visitor.visit(*this); 632 | } 633 | /// @brief is not virtual 634 | string sample_component_method() const 635 | { 636 | return __func__; 637 | } 638 | }; 639 | 640 | /** 641 | Call hierarchy: 642 | 643 | visitor_demo 644 | client_visit 645 | component_accept 646 | visit 647 | sample_component_method 648 | */ 649 | 650 | void visitor_demo() 651 | { 652 | /// @brief is one of many specific visitors with custom method visit 653 | /// Per each of the possible pairs of Sample_visitor and Sample_component 654 | struct Sample_visitor 655 | : public Abstract_visitor { 656 | /// overloaded function for each component 657 | string visit(const Sample_component& sc) const override 658 | { 659 | assert(typeid(*this) == typeid(Sample_visitor)); 660 | assert(typeid(sc) == typeid(Sample_component)); 661 | return string(__func__) + " > " + sc.sample_component_method(); 662 | } 663 | }; 664 | 665 | forward_list> components; 666 | components.emplace_front(new Sample_component); 667 | 668 | forward_list> visitors; 669 | visitors.emplace_front(new Sample_visitor); 670 | 671 | assert(client_visit(components, visitors) == "client_visit > component_accept > visit > sample_component_method"); 672 | 673 | // flat code of expanded client_visit: 674 | for (auto&& v : visitors) { 675 | if (auto sv = dynamic_cast(v.get())) 676 | for (auto&& c : components) { 677 | if (auto sc = dynamic_cast(c.get())) 678 | // inside component_accept: 679 | sv->visit(*sc); 680 | else { 681 | }; 682 | } 683 | else { 684 | /* And so on for each pair of visitor and component. 685 | Total number of pairs is multiplication of 686 | number components and number of visitors. 687 | */ 688 | }; 689 | } 690 | } 691 | 692 | // std::visit demo: 693 | 694 | static stringstream output; 695 | 696 | struct Visitor_op { 697 | void operator()(int arg) { output << "int "; }; 698 | void operator()(long arg) { output << "long "; }; 699 | void operator()(double arg) { output << "double "; }; 700 | void operator()(string arg) { output << "string "; }; 701 | }; 702 | 703 | void visitor_std_demo() 704 | /// Demonstration of standard template [visit](https://en.cppreference.com/w/cpp/utility/variant/visit) 705 | { 706 | // trivial visit call 707 | visit([](auto&& arg) {}, variant { 1 }); 708 | 709 | // practical visit usage 710 | using Components = variant; 711 | vector comps = { 10, 15l, 1.5, "hello" }; 712 | Visitor_op visitors; 713 | 714 | for (auto& c : comps) 715 | visit(visitors, c); 716 | 717 | assert(output.str() == "int long double string "); 718 | } 719 | 720 | /// @} visitor 721 | 722 | struct Handler 723 | /// @brief is a virtual command handler of Chain_of_responsibility 724 | { 725 | /// Specific handler can process a command and return non-negative 726 | virtual int handle(Command& cmnd) { return cmnd.execute(); }; 727 | virtual ~Handler() noexcept = default; 728 | }; 729 | 730 | struct Chain_of_responsibility 731 | : Handler 732 | /** @brief list based implementation without recursion 733 | 734 | [Chain-of-responsibility pattern](https://en.wikipedia.org/wiki/Chain-of-responsibility_pattern) 735 | 736 | https://refactoring.guru/design-patterns/chain-of-responsibility 737 | 738 | */ 739 | { 740 | void register_handler(Handler&& h, bool front = false) 741 | { 742 | if (front) 743 | handlers.push_front(h); 744 | else 745 | handlers.push_back(h); 746 | } 747 | int handle(Command& cmnd) override 748 | { 749 | int rc = -1; 750 | for (Handler& h : handlers) 751 | if ((rc = h.handle(cmnd)) >= 0) 752 | return rc; 753 | return rc; 754 | } 755 | 756 | private: 757 | list> handlers; 758 | }; 759 | 760 | void behavioral_patterns_demo() 761 | { 762 | observer_demo(); 763 | 764 | publisher_subscriber_demo(); 765 | 766 | mediator_demo(); 767 | 768 | Chain_of_responsibility chain; 769 | chain.register_handler(Handler()); 770 | 771 | Command cmnd; 772 | chain.handle(cmnd); 773 | 774 | visitor_demo(); 775 | 776 | visitor_std_demo(); 777 | } 778 | 779 | /// @} BP 780 | 781 | /** 782 | @defgroup AP Architectural 783 | @brief [Architectural patterns](https://en.wikipedia.org/wiki/Architectural_pattern) 784 | 785 | @{ 786 | */ 787 | 788 | struct Model 789 | : Subject 790 | /// @brief is part of MVC with View and Controller 791 | { 792 | void register_observer(Observer& o) 793 | { 794 | observers.push_front(o); 795 | } 796 | 797 | int command(Command& cmnd) 798 | { 799 | int rc = cmnd.execute(); 800 | notify_observers(); 801 | return rc; 802 | } 803 | 804 | int command(Command&& cmnd) 805 | { 806 | int rc = cmnd.execute(); 807 | notify_observers(); 808 | return rc; 809 | } 810 | }; 811 | 812 | struct View 813 | /// @brief is concrete Observer 814 | : public Observer { 815 | View(Model& m) 816 | : model(m) {}; 817 | 818 | void notify() override 819 | { 820 | // check model 821 | (void)model; 822 | } 823 | 824 | Model& model; 825 | }; 826 | 827 | struct Controller 828 | /** @brief is part of MVC with Model and View 829 | 830 | */ 831 | { 832 | Model& mod; // can be many models 833 | Controller(Model& s) 834 | : mod(s) {}; 835 | 836 | int command(Command& cmnd) 837 | { 838 | return mod.command(cmnd); 839 | } 840 | 841 | int command(Command&& cmnd) 842 | { 843 | return mod.command(cmnd); 844 | } 845 | }; 846 | 847 | void architectural_patterns_demo() 848 | { 849 | Model mod; 850 | View view(mod); 851 | mod.register_observer(view); 852 | mod.notify_observers(); 853 | Controller ctrl(mod); 854 | ctrl.command(Command()); 855 | Command cmnd; 856 | ctrl.command(cmnd); 857 | } 858 | 859 | /// @} AP 860 | 861 | /** 862 | @defgroup CC Concurrency 863 | @brief [Concurrency patterns](https://en.wikipedia.org/wiki/Concurrency_pattern) 864 | 865 | @{ 866 | */ 867 | 868 | template > 869 | class Synchronized_queue 870 | /** 871 | See also 872 | - [Boost synchronized queues](https://www.boost.org/doc/libs/release/doc/html/thread/sds.html#thread.sds.synchronized_queues) 873 | - [boost/thread/concurrent_queues/sync_queue.hpp](https://github.com/boostorg/thread/blob/HEAD/include/boost/thread/concurrent_queues/sync_queue.hpp) 874 | - [boost/thread/concurrent_queues/detail/sync_queue_base.hpp](https://github.com/boostorg/thread/blob/HEAD/include/boost/thread/concurrent_queues/detail/sync_queue_base.hpp) 875 | - [Messaging pattern](https://en.wikipedia.org/wiki/Messaging_pattern) 876 | 877 | Warning: unbounded synchronized queues can cause [OOM](https://en.wikipedia.org/wiki/Out_of_memory) 878 | */ 879 | : Container { 880 | mutex mtx; 881 | bool stoped = false; 882 | 883 | public: 884 | condition_variable cv; 885 | void push(T&& v) 886 | { 887 | lock_guard { mtx }, Container::push(v); 888 | cv.notify_one(); 889 | }; 890 | 891 | T& pull() 892 | { 893 | unique_lock lk(mtx); 894 | cv.wait(lk, [&] { return !this->empty() || stoped; }); 895 | if (stoped) 896 | throw "stopped"; 897 | T& ret = Container::front(); 898 | this->pop(); 899 | return ret; 900 | }; 901 | 902 | void stop() 903 | { 904 | stoped = true; 905 | cv.notify_all(); 906 | } 907 | }; 908 | 909 | struct Active_object 910 | /** @brief [Active object](https://en.wikipedia.org/wiki/Active_object) 911 | 912 | [Revisiting the Active Object Pattern - with C++11 Closures](https://www.codeproject.com/Articles/991641/Revisiting-the-Active-Object-Pattern-with-Cplusplu) 913 | 914 | */ 915 | : Interface { 916 | typedef function Command; 917 | Interface& subject; 918 | Active_object(Interface& s) 919 | : subject(s) 920 | { 921 | th = thread([this] { 922 | try { 923 | while (true) 924 | cmd_q.pull()(); // call Command 925 | } catch (...) { 926 | } 927 | }); 928 | } 929 | 930 | ~Active_object() noexcept 931 | { 932 | cmd_q.stop(); 933 | th.join(); 934 | } 935 | 936 | int method() override 937 | { 938 | promise p; 939 | future f = p.get_future(); 940 | cmd_q.push([&p, this] { p.set_value(subject.method()); }); 941 | auto status = f.wait_for(1s); 942 | if (status != future_status::ready) 943 | throw status; 944 | return f.get(); 945 | } 946 | 947 | protected: 948 | Synchronized_queue cmd_q; // BTW, Circular buffer is more durable because it doesn't cause OOM 949 | thread th; 950 | }; 951 | 952 | void concurrency_patterns_demo() 953 | { 954 | Sample_product sp(3); 955 | Active_object ao(sp); 956 | assert(ao.method() == 3); 957 | } 958 | 959 | /// @} CC 960 | 961 | int main() 962 | { 963 | oop_demo(); 964 | creational_patterns_demo(); 965 | structural_patterns_demo(); 966 | behavioral_patterns_demo(); 967 | architectural_patterns_demo(); 968 | concurrency_patterns_demo(); 969 | } 970 | 971 | /// @} 972 | 973 | /** 974 | @mainpage 975 | 976 | @ref OOP 977 | 978 | @ref DP 979 | 980 | @ref CPP 981 | 982 | [Sources](https://github.com/makelinux/examples/tree/main/cpp) 983 | */ 984 | -------------------------------------------------------------------------------- /cpp/patterns.dot: -------------------------------------------------------------------------------- 1 | digraph G { 2 | rankdir="BT" 3 | node [shape=plaintext]; 4 | edge [fontsize=10 _fontcolor=darkgray] 5 | // Inheritance 6 | edge [label=inh arrowhead=onormal]; 7 | 8 | // Implementation 9 | edge [label=imp weight=1000 arrowhead=onormal style=dashed]; 10 | Product -> Interface; 11 | Factory [label=Factory>] 12 | Sample_factory -> Factory; 13 | Proxy [label=<Proxy>] 14 | { Subject Proxy } -> Proxy_interface 15 | Decorator [label=<Decorator>] 16 | Subject_of_Decorator [label=Subject] 17 | { Decorator Subject_of_Decorator} -> Decorator_interface 18 | Proxy_interface [label="Interface"] 19 | Decorator_interface [label="Interface"] 20 | Factory_of_prototype [label=Factory] 21 | Interface_of_prototype [label=Interface] 22 | Prototype -> { Factory_of_prototype Interface_of_prototype} 23 | Prototype [label=<Prototype>] 24 | Bridge_interface [label=Interface] 25 | Bridge [label=<Bridge or Adapter>] 26 | Bridge -> Bridge_interface 27 | Observer [label=<Observer>] 28 | View [label=<View>] 29 | Model [label=<Model>] 30 | Controller [label=<Controller>] 31 | View -> Observer 32 | 33 | Visitor [label=<Abstract Visitor>] 34 | //Component [rank=min] 35 | Sample_visitor -> Visitor 36 | Sample_component -> Component 37 | 38 | // Aggregation 39 | edge [label=agg weight=1 arrowtail=odiamond dir=back style=""] 40 | 41 | edge [label=creates dir="" arrowhead=odiamond] 42 | Product -> Sample_factory 43 | Prototype -> Prototype 44 | 45 | // Dependencies 46 | edge [label=uses weight=1 arrowhead=vee style=dashed dir="" ] 47 | 48 | Component -> Visitor [label=accepts weight=0] 49 | Sample_component -> Visitor [label=usage dir=both _weight=0 arrowtail=vee constraint=false] 50 | rank = same { Sample_component Visitor } 51 | //{Sample_visitor Sample_component } -> Client_of_Visitor [style=invis] 52 | edge [label=uses weight=1 dir=back arrowtail=vee ] 53 | Client_of_Decorator [label=Client] 54 | Subject_of_Decorator -> Decorator -> Client_of_Decorator 55 | Decorator_interface -> Client_of_Decorator 56 | Subject_of_Decorator -> Client_of_Decorator [color=green] 57 | Client_of_Visitor [label=Client] 58 | Component -> Client_of_Visitor 59 | Visitor -> Client_of_Visitor 60 | 61 | Subject -> Proxy 62 | Client_of_Proxy [label=Client] 63 | Proxy -> Client_of_Proxy 64 | Proxy_interface -> Client_of_Proxy 65 | Model -> Controller [label=manipulates] 66 | Interface -> Factory 67 | Interface_of_prototype -> Factory_of_prototype 68 | Standalone -> Bridge 69 | Observer -> Model [label=updates] 70 | Sample_component -> Sample_visitor [label=<visits
and does a work
> constraint=false] 71 | edge [color=lightgray fontcolor=lightgray xweight=0 constraint=false] 72 | Sample_visitor -> Sample_component [label="independent" constraint=false] 73 | Subject -> Client_of_Proxy [label="no access"] 74 | Standalone -> Bridge_interface [label="incompatible" constraint=false] 75 | } 76 | -------------------------------------------------------------------------------- /cpp/visitor.html: -------------------------------------------------------------------------------- 1 | 19 | 20 |
21 |
22 |
23 |
24 | 25 | Double dispatch 26 | matrix of virtual functions "visit" of 27 | Visitor pattern 28 | for example of tree components and tree visitors 29 |
30 |
31 |
32 | 33 | 34 | 36 | 38 | 41 | 43 | 46 | 48 | 51 | 52 | 53 | 56 | 58 | 61 | 63 | 66 | 68 | 71 | 72 | 73 | 76 | 78 | 81 | 83 | 86 | 87 | 91 | 92 | 93 | 96 | 98 | 101 | 103 | 106 | 108 | 111 | 112 | 113 | 115 | 117 | 120 | 122 | 125 | 127 | 130 | 131 |
35 | 37 | 39 | struct Visitor_1 : public Visitor { 40 | 42 | 44 | struct Visitor_2 : public Visitor { 45 | 47 | 49 | struct Visitor_3 : public Visitor { 50 |
54 | Component_1 55 | 57 | 59 | string visit(const Component_1& c); 60 | 62 | 64 | string visit(const Component_1& c); 65 | 67 | 69 | string visit(const Component_1& c); 70 |
74 | Component_2 75 | 77 | 79 | string visit(const Component_2& c); 80 | 82 | 84 | string visit(const Component_2& c); 85 | 88 | 89 | string visit(const Component_2& c); 90 |
94 | Component_3 95 | 97 | 99 | string visit(const Component_3& c); 100 | 102 | 104 | string visit(const Component_3& c); 105 | 107 | 109 | string visit(const Component_3& c); 110 |
114 | 116 | 118 | }; 119 | 121 | 123 | }; 124 | 126 | 128 | }; 129 |
132 | -------------------------------------------------------------------------------- /js/10.js: -------------------------------------------------------------------------------- 1 | // ES10 - ECMAScript 2019 examples 2 | 3 | assert_eq([ 0, [ 1 ] ].flat(), [0, 1]) 4 | 5 | assert_eq([ 0, [ 1, [ 2 ] ] ].flat(), [ 0, 1, [ 2 ] ]) 6 | 7 | assert_eq([ 0, [ 1, [ 2 ] ] ].flat(Infinity), [ 0, 1, 2 ]) 8 | 9 | assert_eq([ 0, 2 ].flatMap(x => [x, x + 1]), [ 0, 1, 2, 3 ]) 10 | 11 | assert_eq(" a ".trimStart().trimEnd(), "a") 12 | 13 | try { } catch /* Optional Catch Binding */ { } 14 | 15 | assert_eq(Object.fromEntries([['1', 2], ['3', 4]]), { '1': 2, '3': 4 }) 16 | 17 | assert_eq((function () { }).toString(), 'function () { }') 18 | 19 | assert_eq(String(Symbol(1)), 'Symbol(1)') 20 | 21 | assert_eq(Symbol(1).description, '1') 22 | 23 | assert_eq(JSON.stringify('\uD800'), '"\\ud800"') 24 | 25 | /* 26 | References 27 | https://alligator.io/js/es2019/ 28 | https://blog.logrocket.com/5-es2019-features-you-can-use-today/ 29 | https://firstclassjs.com/ecmascript-2019es2019-new-features-with-examples/ 30 | https://medium.com/@selvaganesh93/javascript-whats-new-in-ecmascript-2019-es2019-es10-35210c6e7f4b 31 | */ 32 | 33 | -------------------------------------------------------------------------------- /js/6.js: -------------------------------------------------------------------------------- 1 | // ES6 2 | // https://github.com/lukehoban/es6features 3 | // https://www.smashingmagazine.com/2015/10/es6-whats-new-next-version-javascript/ 4 | // https://www.w3schools.com/js/js_es6.asp 5 | // https://davidwalsh.name/es6-features 6 | // https://davidwalsh.name/es6-features-ii 7 | 8 | // TODO 9 | -------------------------------------------------------------------------------- /js/7.js: -------------------------------------------------------------------------------- 1 | // ES7 - ECMAScript 2016 examples 2 | // https://www.freecodecamp.org/news/ecmascript-2016-es7-features-86903c5cab70/ 3 | 4 | assert_eq(4 ** 5, Math.pow(4, 5)) 5 | assert_eq([0, 1].includes(1), true) 6 | assert_eq([NaN].includes(NaN), true) 7 | -------------------------------------------------------------------------------- /js/8.js: -------------------------------------------------------------------------------- 1 | // ES8 - ECMAScript 2017 examples 2 | // https://2ality.com/2016/02/ecmascript-2017.html 3 | // https://flaviocopes.com/es2017/ 4 | // https://medium.com/@Rashaunwarner/new-es8-features-f3d8b7b4fc8c 5 | 6 | // https://2ality.com/2015/11/stage3-object-entries.html 7 | var map={'a':1, 'b':2} 8 | assert_eq(Object.values(map), [1, 2]) 9 | assert_eq(Object.entries(map), [['a', 1], ['b', 2]]) 10 | 11 | // https://2ality.com/2015/11/string-padding.html 12 | assert_eq('1'.padStart(3,0), '001') 13 | assert_eq('loading'.padEnd(10, '. '), 'loading. .') 14 | assert_eq(Object.getOwnPropertyDescriptors({a: 1}).a.writable, true) 15 | 16 | 17 | function promise_func() { 18 | return new Promise((resolve, reject) => { 19 | setTimeout(() => { 20 | resolve('hello'); 21 | }, 10); 22 | }); 23 | } 24 | 25 | async function async_func() { 26 | const text = await promise_func(); 27 | console.log(text); 28 | } 29 | 30 | async_func(); 31 | 32 | // TODO: SharedArrayBuffer, Atomics Object.prototype 33 | // https://2ality.com/2017/01/shared-array-buffer.html 34 | -------------------------------------------------------------------------------- /js/9.js: -------------------------------------------------------------------------------- 1 | // ES9 - ECMAScript 2018 examples 2 | 3 | [a, ...rest1] = [1, 2, 3]; 4 | 5 | assert_eq(rest1, [2, 3]) 6 | 7 | let {b, ...rest2} = { b: 1, c:2, d:3}; 8 | assert_eq(rest2, { c: 2, d: 3}); 9 | 10 | assert_eq([1, 2, ...[3, 4]], [1, 2, 3, 4]); 11 | 12 | // https://github.com/tc39/proposal-async-iteration 13 | var buff = '0' 14 | async function process(array) { 15 | for await (let i of array) { 16 | buff += String(i) 17 | throw 'e' 18 | } 19 | } 20 | 21 | process([1, 2]) 22 | .catch(a => {buff += a}) 23 | .finally(() => {buff += 'f'; 24 | assert_eq(buff, '01ef')}); 25 | 26 | /* Node.js only: 27 | assert_eq(/(?.)/.exec('1').groups.name, '1') 28 | */ 29 | 30 | // https://medium.com/@bramus/javascript-whats-new-in-ecmascript-2018-es2018-17ede97f36d5 31 | // https://github.com/tc39/proposal-object-rest-spread 32 | -------------------------------------------------------------------------------- /js/Makefile: -------------------------------------------------------------------------------- 1 | test: 2 | ./test-node.js 3 | -------------------------------------------------------------------------------- /js/README.md: -------------------------------------------------------------------------------- 1 | # ECMAScript / JavaScript features examples by version 2 | 3 | * [ES7](7.js) 4 | * [ES8](8.js) 5 | * [ES9](9.js) 6 | * [ES10](10.js) 7 | 8 | References 9 | * https://en.wikipedia.org/wiki/ECMAScript#ES2015 10 | * https://medium.com/@madasamy/javascript-brief-history-and-ecmascript-es6-es7-es8-features-673973394df4 11 | * https://www.freecodecamp.org/news/here-are-examples-of-everything-new-in-ecmascript-2016-2017-and-2018-d52fa3b5a70e/ 12 | -------------------------------------------------------------------------------- /js/test-node.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var passed = 0, failed = 0; 4 | 5 | assert = require('assert'); 6 | function assert_eq(a, b) 7 | { 8 | //console.log(a); 9 | //assert.deepStrictEqual(a, b) 10 | if ((aj = JSON.stringify(a)) != (bj = JSON.stringify(b))) { 11 | console.log("error: ", aj , "!=", bj) 12 | failed++; 13 | } else { 14 | passed++; 15 | } 16 | } 17 | 18 | function passed() 19 | { 20 | console.log(4); 21 | console.log(__filename.slice(__dirname.length + 1)); 22 | } 23 | 24 | var fs = require('fs') 25 | 26 | function run_test(r) 27 | { 28 | 29 | eval(fs.readFileSync('./' + r + '.js').toString()); 30 | console.log(r + ".js, passed: ", passed, ", failed: ", failed); 31 | passed = 0, failed = 0; 32 | } 33 | 34 | run_test(7); 35 | run_test(8); 36 | run_test(9); 37 | run_test(10); 38 | -------------------------------------------------------------------------------- /js/test.html: -------------------------------------------------------------------------------- 1 | 2 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /python/2.3.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2.3 2 | # -*- coding: UTF-8 -*- 3 | 4 | from passed import passed 5 | 6 | 7 | try: 8 | raise "Ex" 9 | except: 10 | pass 11 | 12 | 13 | # https://docs.python.org/3.10/whatsnew/2.0.html 14 | 15 | 16 | comprehension = [c for c in 'ab' if c > 'a'] 17 | assert 'a' not in comprehension 18 | assert 'b' in comprehension 19 | 20 | # https://docs.python.org/3.10/whatsnew/2.1.html 21 | 22 | 23 | def function(): 24 | def closure(): 25 | pass 26 | closure() 27 | 28 | 29 | # https://docs.python.org/3.10/whatsnew/2.2.html 30 | 31 | 32 | class C(object): 33 | def __init__(self): 34 | pass 35 | 36 | 37 | assert C.__name__ == 'C' 38 | 39 | 40 | # https://docs.python.org/3.10/whatsnew/2.0.html 41 | 42 | 43 | comprehension = [c for c in 'ab' if c > 'a'] 44 | assert 'a' not in comprehension 45 | assert 'b' in comprehension 46 | 47 | 48 | # https://docs.python.org/3.10/whatsnew/2.1.html 49 | 50 | 51 | def function(): 52 | def closure(): 53 | pass 54 | closure() 55 | 56 | 57 | # https://docs.python.org/3.10/whatsnew/2.2.html 58 | 59 | 60 | class C(object): 61 | def __init__(self): 62 | pass 63 | 64 | 65 | assert C.__name__ == 'C' 66 | 67 | 68 | 69 | import logging 70 | import csv 71 | 72 | 73 | # before 2.4 74 | 75 | comprehension = [c for c in 'ab' if c > 'a'] 76 | assert 'a' not in comprehension 77 | assert 'b' in comprehension 78 | 79 | '%(page)i: %(title)s' % {'page': 2, 'title': 'The Best of Times'} 80 | 81 | # https://docs.python.org/3.10/whatsnew/2.3.html 82 | 83 | 84 | def sipmple_generator(N): 85 | for i in range(N): 86 | yield i 87 | 88 | 89 | gen = sipmple_generator(3) 90 | assert gen.next() == 0 91 | assert gen.next() == 1 92 | assert gen.next() == 2 93 | 94 | assert list(enumerate(['a', 'b', 'c'])) == [(0, 'a'), (1, 'b'), (2, 'c')] 95 | 96 | assert bool(1) is True 97 | assert bool([]) is False 98 | assert range(5)[::2] == [0, 2, 4] 99 | 100 | passed() 101 | -------------------------------------------------------------------------------- /python/2.4.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2.4 2 | 3 | import subprocess 4 | import string 5 | from passed import passed 6 | 7 | # https://docs.python.org/3.10/whatsnew/2.4.html#pep-218-built-in-set-objects 8 | 9 | assert 1 in set([1, 2]) 10 | 11 | a_str = set('ab') 12 | assert 'b' in a_str 13 | a_str.add('c') 14 | assert 'c' in a_str 15 | a_str.update('d') 16 | assert 'd' in a_str 17 | a_str.remove('a') 18 | assert 'a' not in a_str 19 | 20 | 21 | # https://docs.python.org/3.10/whatsnew/2.4.html#pep-289-generator-expressions 22 | 23 | generator_expression = (c for c in 'ef' if c > 'e') 24 | 25 | for c in generator_expression: 26 | a_str.add(c) 27 | 28 | assert 'e' not in a_str 29 | assert 'f' in a_str 30 | 31 | 32 | # https://docs.python.org/3.10/whatsnew/2.4.html#pep-292-simpler-string-substitutions 33 | 34 | a_str = string.Template('var=$var') 35 | assert a_str.substitute({'var': 1}) == 'var=1' 36 | 37 | 38 | # https://docs.python.org/3.10/whatsnew/2.4.html#pep-318-decorators-for-functions-and-methods 39 | 40 | def decoration(func): 41 | def wrapper(arg): 42 | return 'decorated' + func(arg) 43 | wrapper.attr = 'decorated' 44 | return wrapper 45 | 46 | 47 | @decoration 48 | def decorated(arg): 49 | return arg 50 | 51 | 52 | assert decorated.attr 53 | assert decorated('1') == 'decorated1' 54 | 55 | # https://docs.python.org/3.10/whatsnew/2.4.html#pep-322-reverse-iteration 56 | 57 | assert list(reversed(xrange(1, 4))) == [3, 2, 1] 58 | 59 | # https://docs.python.org/3.10/whatsnew/2.4.html#pep-324-new-subprocess-module 60 | 61 | 62 | passed() 63 | -------------------------------------------------------------------------------- /python/2.5.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2.5 2 | 3 | # https://docs.python.org/3.10/whatsnew/2.5.html 4 | 5 | from passed import passed 6 | 7 | assert (1 if False else 2) == 2 8 | 9 | try: 10 | pass 11 | except TypeError: 12 | pass 13 | except AttributeError: 14 | pass 15 | else: 16 | pass 17 | finally: 18 | pass 19 | 20 | 21 | passed() 22 | -------------------------------------------------------------------------------- /python/2.6.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2.6 2 | 3 | # https://docs.python.org/3.10/whatsnew/2.6.html 4 | 5 | from threading import Lock 6 | from passed import passed 7 | 8 | lock = Lock() 9 | with lock: 10 | pass 11 | 12 | passed() 13 | -------------------------------------------------------------------------------- /python/2.7.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2.7 2 | 3 | from collections import OrderedDict 4 | import logging 5 | import logging.config 6 | import importlib 7 | # import argparse 8 | from passed import passed 9 | 10 | # https://docs.python.org/3.10/whatsnew/2.7.html 11 | 12 | assert {1, 2} == set([1, 2]) 13 | assert {x: x * x for x in range(3)} == {0: 0, 1: 1, 2: 4} 14 | 15 | # https://docs.python.org/3.10/whatsnew/2.7.html#pep-372-adding-an-ordered-dictionary-to-collections 16 | 17 | a_dict = OrderedDict([('a', 1), ('b', 2), ('c', 3)]) 18 | a_dict['b'] = 4 19 | 20 | assert a_dict == OrderedDict([('a', 1), ('b', 4), ('c', 3)]) 21 | 22 | assert a_dict.popitem(last=False) == ('a', 1) 23 | 24 | 25 | passed() 26 | -------------------------------------------------------------------------------- /python/3.0.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.1 2 | 3 | import io 4 | from passed import passed 5 | 6 | # https://docs.python.org/3.10/whatsnew/3.0.html 7 | 8 | assert 3 / 2 == 1.5 9 | assert isinstance(range(3), range) 10 | 11 | 12 | buff = io.StringIO() 13 | 14 | # https://docs.python.org/3.10/whatsnew/3.0.html#print-is-a-function 15 | 16 | print(1, 2, 3, sep=", ", end="!", file=buff) 17 | 18 | assert buff.getvalue() == "1, 2, 3!" 19 | 20 | 21 | class Meta(type): 22 | pass 23 | 24 | 25 | class Foo(metaclass=Meta): 26 | pass 27 | 28 | 29 | passed() 30 | -------------------------------------------------------------------------------- /python/3.1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.1 2 | 3 | # https://docs.python.org/3.10/whatsnew/3.1.html 4 | 5 | from decimal import Decimal 6 | from passed import passed 7 | 8 | assert format(1000, ',d') == '1,000' 9 | 10 | assert format(Decimal('1.23'), '.3f') == '1.230' 11 | 12 | passed() 13 | -------------------------------------------------------------------------------- /python/3.2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.2 2 | 3 | # https://docs.python.org/3.10/whatsnew/3.2.html 4 | 5 | import argparse 6 | from passed import passed 7 | 8 | # TODO 9 | 10 | passed() 11 | -------------------------------------------------------------------------------- /python/3.3.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.3 2 | 3 | # https://docs.python.org/3.10/whatsnew/3.3.html 4 | 5 | import faulthandler 6 | import ipaddress 7 | import lzma 8 | import unittest.mock 9 | import venv 10 | from passed import passed 11 | 12 | # TODO 13 | 14 | passed() 15 | -------------------------------------------------------------------------------- /python/3.4.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.4 2 | 3 | # https://docs.python.org/3/whatsnew/3.4.html 4 | 5 | import enum 6 | import pathlib 7 | import selectors 8 | import statistics 9 | import tracemalloc 10 | from passed import passed 11 | 12 | passed() 13 | -------------------------------------------------------------------------------- /python/3.5.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.5 2 | 3 | import asyncio 4 | from passed import passed 5 | 6 | # https://docs.python.org/3/whatsnew/3.5.html 7 | 8 | from typing import Callable, List, NewType 9 | 10 | 11 | def function_with_type_annotation(a: str) -> str: 12 | return a 13 | 14 | 15 | # But the Python runtime does not enforce function. 16 | assert function_with_type_annotation(1.2) == 1.2 17 | 18 | Vector_type_alias = List[float] 19 | 20 | 21 | def scale(scalar: float, vector: Vector_type_alias) -> Vector_type_alias: 22 | return [scalar * num for num in vector] 23 | 24 | 25 | assert scale(2, [1.1, 3.3]) == [2.2, 6.6] 26 | 27 | UserId = NewType('UserId', int) 28 | some_id = UserId(1) 29 | 30 | 31 | def valid(id: UserId) -> bool: 32 | return True 33 | 34 | 35 | def feeder(get_next_item: Callable[[], str]) -> None: 36 | pass 37 | 38 | 39 | def async_query(on_success: Callable[[int], None], 40 | on_error: Callable[[int, Exception], None]) -> None: 41 | pass 42 | 43 | 44 | # https://docs.python.org/3.5/whatsnew/3.5.html#pep-492-coroutines-with-async-and-await-syntax 45 | 46 | 47 | async def coroutine(): 48 | return 1 49 | 50 | loop = asyncio.get_event_loop() 51 | try: 52 | r = loop.run_until_complete(coroutine()) 53 | finally: 54 | loop.close() 55 | 56 | assert r == 1 57 | 58 | passed() 59 | -------------------------------------------------------------------------------- /python/3.6.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.6 2 | 3 | # https://docs.python.org/3.6/whatsnew/3.6.html 4 | 5 | # https://docs.python.org/3.6/whatsnew/3.6.html#pep-498-formatted-string-literals 6 | 7 | import asyncio 8 | from passed import passed 9 | 10 | an_int = 1 11 | assert f'{an_int}' == '1' 12 | assert f'an_int={an_int:02}' == 'an_int=01' 13 | assert f"{an_int:#0x}" == "0x1" # using integer format specifier 14 | 15 | a_real = 1.23 16 | assert f'{a_real}' == '1.23' 17 | assert f'a_real={a_real:1.2}' == 'a_real=1.2' 18 | 19 | a_str = 'a' 20 | assert f'{a_str}' == 'a' 21 | assert f'{a_str!r}' == "'a'" 22 | 23 | # https://docs.python.org/3.6/whatsnew/3.6.html#pep-526-syntax-for-variable-annotations 24 | 25 | a_str: str 26 | an_int: int 27 | 28 | 29 | async def main(): 30 | print('hello') 31 | await asyncio.sleep(1) 32 | print('world') 33 | 34 | # asyncio.run(main()) 35 | 36 | passed() 37 | -------------------------------------------------------------------------------- /python/3.7.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.7 2 | 3 | # https://docs.python.org/3/whatsnew/3.7.html 4 | # https://realpython.com/python37-new-features/ 5 | 6 | import asyncio 7 | import sys 8 | from contextvars import ContextVar 9 | import dataclasses 10 | import importlib.resources 11 | from passed import passed 12 | 13 | var: ContextVar[int] = ContextVar('var', default=1) 14 | assert var.get() == 1 15 | 16 | var.set(2) 17 | assert var.get() == 2 18 | 19 | buf = '' 20 | 21 | 22 | async def corutine(): 23 | global buf 24 | buf += '3' 25 | 26 | 27 | async def test_task(): 28 | global buf 29 | buf += '1' 30 | # Before: 31 | # task = asyncio.ensure_future(corutine()) 32 | task = asyncio.create_task(corutine()) 33 | buf += '2' 34 | await task 35 | buf += '4' 36 | 37 | asyncio.run(test_task()) 38 | assert buf == '1234' 39 | 40 | breakpoint_passed = False 41 | 42 | sys.breakpointhook = lambda: globals().update(breakpoint_passed=True) 43 | breakpoint() 44 | 45 | assert breakpoint_passed 46 | 47 | passed() 48 | -------------------------------------------------------------------------------- /python/3.8.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.8 2 | 3 | from passed import passed 4 | 5 | # https://www.geeksforgeeks.org/awesome-new-features-in-python-3-8/ 6 | # 7 | # https://docs.python.org/3/whatsnew/3.8.html 8 | 9 | 10 | # https://docs.python.org/3/whatsnew/3.8.html#positional-only-parameters 11 | 12 | # Arguments before / are considered as positional arguments only 13 | 14 | def pos_only_arg_demo(pos_only_arg, /): 15 | return pos_only_arg 16 | 17 | 18 | try: 19 | res = pos_only_arg_demo(pos_only_arg='Fail') 20 | except TypeError: 21 | res = pos_only_arg_demo('Passed') 22 | assert res == 'Passed' 23 | 24 | # Assignment Expression 25 | # https://docs.python.org/3/whatsnew/3.8.html#assignment-expressions 26 | 27 | assert (an_int := 2) > 1 28 | 29 | # https://docs.python.org/3/whatsnew/3.8.html#f-strings-support-for-self-documenting-expressions-and-debugging 30 | 31 | an_int = 1 32 | 33 | assert f'{an_int=}' == 'an_int=1' 34 | 35 | # The usual f-string format specifiers allow more control over how the result 36 | # of the expression is displayed: 37 | 38 | assert f'{an_int=:.3f}' == 'an_int=1.000' 39 | 40 | assert f'{an_int+an_int=}' == 'an_int+an_int=2' 41 | 42 | # get_coro get_name set_name 43 | 44 | passed() 45 | -------------------------------------------------------------------------------- /python/3.9.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.9 2 | 3 | from passed import passed 4 | 5 | # https://docs.python.org/3.9/whatsnew/3.9.html 6 | 7 | # https://docs.python.org/3.9/whatsnew/3.9.html#dictionary-merge-update-operators 8 | 9 | dict_1 = {'a': 0, 'b': 2} 10 | dict_2 = {'a': 1, 'c': 3} 11 | 12 | # Merging dictionaries 13 | 14 | assert dict_1 | dict_2 == {'a': 1, 'b': 2, 'c': 3} 15 | 16 | dict_1 |= dict_2 17 | 18 | # Updating a dictionary 19 | 20 | assert dict_1 | dict_2 == {'a': 1, 'b': 2, 'c': 3} 21 | assert dict_1 == {'a': 1, 'b': 2, 'c': 3} 22 | 23 | 24 | # In type annotations you can now use built-in collection types such as list 25 | # and dict as generic types instead of importing the corresponding 26 | # capitalized types. 27 | # https://docs.python.org/3.9/whatsnew/3.9.html#pep-585-builtin-generic-types 28 | 29 | 30 | def is_list(a_list: list[int]) -> bool: 31 | return isinstance(a_list, list) 32 | 33 | 34 | assert is_list([1, 2, 3]) 35 | 36 | assert 'ab'.removeprefix('a') == 'b' 37 | assert 'ab'.removesuffix('b') == 'a' 38 | 39 | passed() 40 | -------------------------------------------------------------------------------- /python/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | ./2.1.py 3 | ./2.2.py 4 | ./2.3.py 5 | ./2.4.py 6 | ./2.5.py 7 | ./2.6.py 8 | ./2.7.py 9 | ./3.0.py 10 | ./3.1.py 11 | ./3.2.py 12 | ./3.3.py 13 | ./3.4.py 14 | ./3.5.py 15 | ./3.6.py 16 | ./3.7.py 17 | ./3.8.py 18 | ./3.9.py 19 | -------------------------------------------------------------------------------- /python/README.md: -------------------------------------------------------------------------------- 1 | # Python features examples by releases 2 | 3 | ## [2.0 - 2.3](2.3.py), [2.4](2.4.py), [2.5](2.5.py), [2.6](2.6.py), [2.7](2.7.py) 4 | ## [3.0](3.0.py), [3.1](3.1.py), [3.2](3.2.py), [3.3](3.3.py), [3.4](3.4.py), [3.5](3.5.py), [3.6](3.6.py), [3.7](3.7.py), [3.8](3.8.py), [3.9](3.9.py) 5 | 6 | ## Features 7 | * Minimal and practical self descriptive as possible source code. 8 | (Please read references for explanations) 9 | * Complete and ready to copy-paste into an your application. 10 | * Runnable in-place. (No need to copy paste snippets from documentation 11 | into an interpreter) 12 | * Verifiable. Internal tests provides reliability and durability. You can easily add 13 | new features and run tests to assure code validity. 14 | 15 | ## Usage 16 | * Read sources 17 | * 'assert' statements in the sources show expected results 18 | * Run 'make' or any example manually for validation and unit testing 19 | * Improvements and new features are welcome 20 | 21 | ## References 22 | * [What’s New in Python](https://docs.python.org/3.10/whatsnew/index.html) 23 | * [Minimal working example](https://en.wikipedia.org/wiki/Minimal_working_example) 24 | * [Minimal, Complete, and Verifiable Example](https://stackoverflow.com/help/mcve) 25 | -------------------------------------------------------------------------------- /python/passed.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | 4 | def passed(): 5 | try: 6 | print("passed %s with %s.%s" % (sys.argv[0], sys.version_info.major, 7 | sys.version_info.minor)) 8 | except AttributeError: 9 | print("passed %s with %s.%s" % (sys.argv[0], sys.version_info[0], 10 | sys.version_info[1])) 11 | -------------------------------------------------------------------------------- /python/pythonX-install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # https://launchpad.net/~deadsnakes/+archive/ubuntu/ppa 4 | 5 | grep --quiet '^deb.*deadsnakes/ppa' --recursive /etc/apt/sources.list.d/ || sudo add-apt-repository ppa:deadsnakes/ppa 6 | sudo apt-get -q update 7 | 8 | for v in 2.{3..7} 3.{1..10}; do 9 | which python$v || sudo apt-get --yes install python$v 10 | done 11 | 12 | -------------------------------------------------------------------------------- /rust/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | Cargo.lock 3 | -------------------------------------------------------------------------------- /rust/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "type": "cargo", 8 | "command": "build", 9 | "problemMatcher": [ 10 | "$rustc" 11 | ], 12 | "group": { 13 | "kind": "build", 14 | "isDefault": true 15 | }, 16 | "label": "rust: cargo build" 17 | }, 18 | { 19 | "type": "cargo", 20 | "command": "test", 21 | "problemMatcher": [ 22 | "$rustc" 23 | ], 24 | "group": { 25 | "kind": "test", 26 | "isDefault": false 27 | }, 28 | "label": "rust: cargo test" 29 | } 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust_examples" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | -------------------------------------------------------------------------------- /rust/Makefile: -------------------------------------------------------------------------------- 1 | all: build 2 | $(MAKE) check 3 | 4 | build: 5 | cargo build 6 | 7 | clean: 8 | cargo clean 9 | 10 | check: 11 | cargo test 12 | 13 | doc: 14 | cargo doc 15 | xdg-open target/doc/rust_basics/index.html 16 | -------------------------------------------------------------------------------- /rust/src/.gitignore: -------------------------------------------------------------------------------- 1 | main 2 | -------------------------------------------------------------------------------- /rust/src/Makefile: -------------------------------------------------------------------------------- 1 | all: main 2 | ./main 3 | 4 | main: 5 | 6 | check: 7 | ./main 8 | 9 | SUFFIXES = .rs 10 | 11 | %: %.rs 12 | rustc $< 13 | -------------------------------------------------------------------------------- /rust/src/main.rs: -------------------------------------------------------------------------------- 1 | // system packages: rust-all rust-src 2 | 3 | fn main() { 4 | // to stdout: 5 | print!("output"); 6 | println!(" + new line"); 7 | // to stderr: 8 | eprint!("error"); 9 | eprintln!(" + new line"); 10 | 11 | assert_eq!(func(1), 2); 12 | 13 | fn func(arg: i32) -> i32 { 14 | // immutable: arg += 1; 15 | arg + 1 // the last value is return value 16 | } 17 | } 18 | 19 | #[test] 20 | fn constants() { 21 | let logical: bool; 22 | logical = true; 23 | assert!(logical); 24 | 25 | let int: i32 = 100; 26 | assert_eq!(int, 100); 27 | } 28 | 29 | #[test] 30 | fn mutable_test() { 31 | assert_eq!(format!("{}", 0xf), "15"); 32 | 33 | let mut variable = 1; // mutable means variable 34 | 35 | variable += 1; 36 | assert_eq!(variable, 2); 37 | } 38 | 39 | #[test] 40 | fn casting_test() { 41 | let decimal = 65.4321_f32; 42 | let integer = decimal as u8; 43 | let character = integer as char; 44 | assert_eq!(character, 'A'); 45 | } 46 | 47 | #[test] 48 | fn types_test() { 49 | let elem = 5; // i32 by default 50 | let mut vec = Vec::new(); // generic vector declaration 51 | vec.push(elem); 52 | 53 | // formatting debug representation 54 | assert_eq!(format!("{:?}", vec), "[5]"); 55 | 56 | #[allow(dead_code)] 57 | type NanoSecond = u64; // type alias 58 | 59 | let my_str; 60 | my_str = "1"; // like char* in C 61 | assert_eq!(my_str, "1"); 62 | 63 | let mut my_string = String::from(my_str); 64 | assert_eq!(my_string, "1"); 65 | 66 | my_string = my_str.into(); 67 | my_string += "2"; 68 | assert_eq!(my_string, "12"); 69 | 70 | let s2 = my_string.clone(); 71 | assert_eq!(s2, "12"); 72 | assert_eq!(my_string, "12"); 73 | 74 | my_string = "aaa".to_string(); 75 | assert!(!my_string.is_empty()); 76 | } 77 | 78 | #[test] 79 | fn parsing_test() { 80 | // inferred type 81 | let parsed1: i32 = "5".parse().unwrap(); 82 | // explicit type 83 | let parsed2 = "5".parse::().unwrap(); 84 | assert_eq!(parsed1, parsed2); 85 | } 86 | 87 | #[test] 88 | fn controls_test() { 89 | if 1 > 0 { 90 | } else { 91 | }; 92 | // blocks are expressions, the last expression without ';' is a return value 93 | let mut res = { 94 | let a = 1; 95 | a // without ';' 96 | }; 97 | assert_eq!(res, 1); 98 | assert_eq!({}, ()); // like void return value in C 99 | 100 | res = if 1 > 0 { 2 } else { 3 }; 101 | assert_eq!(res, 2); 102 | 103 | // like switch in C 104 | match true { 105 | // like case in C 106 | true => assert!(true), 107 | _ => assert!(false), 108 | }; 109 | } 110 | 111 | #[test] 112 | fn loops() { 113 | // match as expression 114 | let m = match 1 { 115 | 0 => 0, 116 | _ => 1, // default match 117 | }; 118 | assert_eq!(m, 1); 119 | 120 | loop { 121 | break; 122 | } 123 | 124 | while false { 125 | continue; 126 | } 127 | 128 | for n in 0..10 { 129 | assert!(n < 10); 130 | } 131 | 132 | for n in 1..=10 { 133 | assert!(n <= 10); 134 | } 135 | } 136 | 137 | #[test] 138 | fn references() { 139 | let reference1 = &4; 140 | let ref reference2 = 4; 141 | // dereferencing 142 | assert_eq!(*reference1, 4); 143 | assert_eq!(*reference2, 4); 144 | let &val = reference1; 145 | assert_eq!(val, 4); 146 | 147 | let s1: &str = "abc"; // like char* 148 | let ref s2 = *"abc"; // like char* 149 | assert_eq!(s1, s2); 150 | } 151 | 152 | #[test] 153 | fn data_structures() { 154 | // classic struct 155 | 156 | #[allow(dead_code)] 157 | #[derive(Debug)] // required for `format!("{:?}", p)` 158 | struct Person { 159 | name: String, 160 | age: u8, 161 | } 162 | 163 | let p = Person { 164 | name: "Peter".to_string(), 165 | age: 27, 166 | }; 167 | assert_eq!(format!("{:?}", p), "Person { name: \"Peter\", age: 27 }"); 168 | } 169 | 170 | #[test] 171 | fn tuples() { 172 | // A tuple struct 173 | 174 | #[derive(Debug)] 175 | struct Pair(i32, f32); 176 | let pair = Pair(1, 0.1); 177 | assert_eq!(format!("{:?}", pair), "Pair(1, 0.1)"); 178 | // destruction (decomposition) 179 | assert_eq!(pair.0, 1); 180 | assert_eq!(pair.1, 0.1); 181 | let Pair(integer, decimal) = pair; 182 | assert_eq!(integer, 1); 183 | assert_eq!(decimal, 0.1); 184 | static GLOBAL: i32 = 1; // statics need to be uppercase 185 | assert_eq!(GLOBAL, 1); 186 | 187 | // generics are like template in C++ 188 | 189 | struct SampleGeneric(T); // generic tuple 190 | let _char = SampleGeneric('a'); 191 | assert_eq!(_char.0, 'a'); 192 | } 193 | 194 | #[test] 195 | fn traits() { 196 | // a trait is like an interface, can contain methods 197 | trait Zero { 198 | const ZERO: Self; 199 | fn is_zero(&self) -> bool; 200 | } 201 | 202 | // implementations must implement their interface 203 | impl Zero for i32 { 204 | const ZERO: Self = 0; 205 | 206 | fn is_zero(&self) -> bool { 207 | *self == Self::ZERO 208 | } 209 | } 210 | 211 | assert_eq!(i32::ZERO, 0); 212 | assert!(i32::ZERO.is_zero()); 213 | assert!(!4.is_zero()); 214 | } 215 | 216 | #[test] 217 | fn destructor_test() { 218 | static mut DROPPED: bool = false; 219 | struct Droppper; 220 | impl Drop for Droppper { 221 | // destructor 222 | fn drop(&mut self) { 223 | unsafe { 224 | // because `static mut` is unsafe 225 | DROPPED = true; // must be static (global) 226 | } 227 | } 228 | } 229 | { 230 | let _x = Droppper; 231 | } 232 | unsafe { assert!(DROPPED) }; 233 | } 234 | 235 | #[test] 236 | fn options() { 237 | let x: Option = Some(2); 238 | assert_eq!(x.is_some(), true); 239 | 240 | let x: Option = None; 241 | assert_eq!(x.is_some(), false); 242 | } 243 | 244 | #[test] 245 | fn raw_pointers() { 246 | let mut var: i32 = 3; 247 | let ptr: *mut i32 = &mut var; 248 | unsafe { 249 | if !ptr.is_null() { 250 | assert_eq!(*ptr, 3); 251 | } 252 | } 253 | } 254 | 255 | #[test] 256 | fn scope() { 257 | //static S:String = String::from("a"); 258 | let mut a = String::from("a"); 259 | fn delete(_arg: String) { 260 | // argument is moved end deleted by destructor 261 | } 262 | delete(a.clone()); 263 | assert_eq!(a, "a"); 264 | if false { 265 | delete(a); // the value is moved here even it is assert_eq!(a, "a");under the "if false" 266 | } 267 | // value of a is undefined here 268 | //assert_eq!(a, "a"); // error: value borrowed here after move 269 | a = "1".to_string(); // reusing a 270 | let c = a; 271 | // value of a is undefined here 272 | assert_eq!(c, "1"); 273 | a = c; 274 | // c is unusable because it is immutable 275 | //c = a; // error: cannot assign twice to immutable variable 276 | assert_eq!(a, "1"); 277 | } 278 | 279 | #[test] 280 | fn mutable_function_argument() { 281 | let mut a = String::from("a"); 282 | fn append(arg: &mut String, s: &str) { 283 | arg.push_str(s); 284 | } 285 | append(&mut a, "b"); 286 | append(&mut a, "c"); 287 | assert_eq!(a, "abc"); 288 | let b = a; 289 | // a is undefined 290 | let c = b + "d"; // content of b is moved here 291 | // b is unusable here 292 | assert_eq!(c, "abcd"); 293 | a = c; // reusing a, because it is mutable 294 | assert_eq!(a, "abcd"); 295 | } 296 | 297 | #[test] 298 | fn macro_test() { 299 | macro_rules! sample_macro { 300 | // `()` indicates that the macro takes no argument. 301 | () => { 302 | 0 303 | }; 304 | ($a:expr) => { 305 | $a 306 | }; 307 | ($a:expr, $b:expr) => { 308 | $a + $b 309 | }; 310 | } 311 | assert_eq!(sample_macro!(), 0); 312 | assert_eq!(sample_macro!(1), 1); 313 | assert_eq!(sample_macro!(1, 2), 3); 314 | } 315 | 316 | #[test] 317 | fn closue() { 318 | // Closures are like lambda expressions in C++ 319 | 320 | // Closures can capture external objects (constants, variables) 321 | let one = 1; 322 | 323 | // Closure which is bound to reference (name) 324 | let closure_annotated = |arg: i32| -> i32 { arg + one }; 325 | assert_eq!(closure_annotated(1), 2); 326 | 327 | // Annotation and block are optional 328 | let closure_inferred = |arg| arg + one; 329 | assert_eq!(closure_inferred(1), 2); 330 | 331 | // anonymous closure 332 | assert_eq!((|arg| arg + one)(1), 2); 333 | 334 | let mut var = 1; 335 | assert_eq!( 336 | (|arg| { 337 | var += arg; 338 | var 339 | })(1), 340 | 2 341 | ); 342 | } 343 | 344 | #[test] 345 | #[ignore] 346 | fn failing_test() { 347 | assert!(false) 348 | } 349 | -------------------------------------------------------------------------------- /sprof/.gitignore: -------------------------------------------------------------------------------- 1 | libdemo.so* 2 | prog 3 | -------------------------------------------------------------------------------- /sprof/Makefile: -------------------------------------------------------------------------------- 1 | all: libdemo.so.1.0.1 prog 2 | 3 | CFLAGS+=-g 4 | libdemo.so.1.0.1: libdemo.c 5 | 6 | libdemo.so.1.0.1: 7 | cc -g -fPIC -shared -Wl,-soname,libdemo.so.1 -o $@ $^ 8 | ln -sf libdemo.so.1.0.1 libdemo.so.1 9 | ln -sf libdemo.so.1 libdemo.so 10 | 11 | CFAGS=-g 12 | prog: LDLIBS=-L. -ldemo 13 | 14 | -------------------------------------------------------------------------------- /sprof/libdemo.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void task_1(int lim) 4 | { 5 | for (int j = 0; j < lim; j++) 6 | getppid(); 7 | } 8 | 9 | void x1(void) 10 | { 11 | for (int j = 0; j < 100; j++) 12 | task_1(200000); 13 | } 14 | 15 | void task_2(int lim) 16 | { 17 | for (int j = 0; j < lim; j++) 18 | getppid(); 19 | } 20 | 21 | void x2(void) 22 | { 23 | for (int j = 0; j < 1000; j++) 24 | task_2(10000); 25 | } 26 | -------------------------------------------------------------------------------- /sprof/prog.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void x1(void); 4 | void x2(void); 5 | 6 | int main() 7 | { 8 | x1(); 9 | x2(); 10 | exit(EXIT_SUCCESS); 11 | } 12 | -------------------------------------------------------------------------------- /sprof/runme.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | make 4 | export LD_PROFILE=libdemo.so.1 5 | export LD_PROFILE_OUTPUT=. 6 | profile=$LD_PROFILE_OUTPUT/libdemo.so.1.profile 7 | rm -f $profile 8 | LD_LIBRARY_PATH=. ./prog 9 | ls prof_data 10 | sprof -V | head 1 11 | sprof -p libdemo.so.1 $profile 12 | sprof -c libdemo.so.1 $profile 13 | --------------------------------------------------------------------------------