├── .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