mirror of
https://github.com/boostorg/optional.git
synced 2025-06-28 05:21:01 +02:00
Compare commits
598 Commits
svn-branch
...
optional-2
Author | SHA1 | Date | |
---|---|---|---|
c1519884ed | |||
19f202b650 | |||
4ce395e14d | |||
1ceb5004da | |||
942caa437b | |||
824552dc5f | |||
c74b5e1e29 | |||
cbc7014edf | |||
6fa214e0a6 | |||
87586cd9b1 | |||
cc54a71150 | |||
8ecf840c33 | |||
c6657cc9bd | |||
ce03067859 | |||
c3b5267506 | |||
5fa59b9a35 | |||
e1a3501a78 | |||
36c33f2e67 | |||
411ead088d | |||
e360de3da5 | |||
346dc03746 | |||
27309c40ad | |||
6ec468aff6 | |||
794e03af30 | |||
3a8556186e | |||
82d08adf11 | |||
4c503758fe | |||
bf10cf91c2 | |||
dfe1915930 | |||
8ffcf0f369 | |||
0473d0a56c | |||
8421c07517 | |||
22657e9c6e | |||
6bd32078b4 | |||
9a2c5ec37b | |||
1f473d2596 | |||
81f4543d81 | |||
7ed6bf5bca | |||
b7a1d666f1 | |||
f8387e371b | |||
b5e9f067a7 | |||
85e50fe919 | |||
3d8f71728c | |||
88428d350d | |||
7a5386eeeb | |||
ca1495b69d | |||
5f12573608 | |||
e962a134f0 | |||
5c34c54b05 | |||
b270cf019b | |||
790d4f729f | |||
8375df7693 | |||
01e80d2b87 | |||
a1dbd3b67d | |||
034dfe2ef5 | |||
ac4611c05b | |||
a8dabe8a42 | |||
fd31196819 | |||
e31cf6f2a8 | |||
c60db27762 | |||
5064a9a28d | |||
fe0384baa6 | |||
76c82e83ae | |||
e59b1bce1d | |||
f95fb5dff2 | |||
7878dec842 | |||
a3abf04548 | |||
9c43ae3612 | |||
def2db7c45 | |||
6266c39b8e | |||
e300c4bc60 | |||
302f39e545 | |||
d4f84a868d | |||
46ad495a60 | |||
246f1663e1 | |||
668c8d924b | |||
653ebefbac | |||
ce500ee436 | |||
b4c8f493c6 | |||
7e395f4520 | |||
630cf7f7b5 | |||
cdc2bd8482 | |||
db472e7ed6 | |||
8ffb7e3f57 | |||
deda20af89 | |||
4b63acfc10 | |||
599c72f23b | |||
a4479bf8cd | |||
ba1846abd3 | |||
168552e021 | |||
581c43f25c | |||
c76b73c48b | |||
e26c2d7489 | |||
969930959c | |||
56156dcc87 | |||
802e73477a | |||
9944804c5c | |||
2121a9fa59 | |||
cc416b8989 | |||
74a684232f | |||
6f85014c00 | |||
29dd9187ec | |||
bcc83a662a | |||
c4291fa461 | |||
de27c0f853 | |||
9c44e402f6 | |||
5ab4701192 | |||
ab7e5275c0 | |||
416c89e165 | |||
c809700d6a | |||
293d1861d7 | |||
3038bdea4b | |||
938806c876 | |||
85ebe0a2ed | |||
ce5834add2 | |||
a514ce627d | |||
ec677383dc | |||
52abe4842e | |||
4ead6d14ff | |||
78d42ff970 | |||
6117d08d79 | |||
916ca23572 | |||
c300a8c517 | |||
4f713acdf8 | |||
1e6f838a90 | |||
51b7053abf | |||
ec96129e9e | |||
8e86559103 | |||
56568445b9 | |||
7dd512a019 | |||
21253ea63a | |||
14d43d2e6e | |||
0b159febf8 | |||
d0ab8004c0 | |||
5a444eb84b | |||
0566bde447 | |||
a70c51eed1 | |||
9c9ff5e376 | |||
708db7fe9a | |||
27971d8b11 | |||
97da91f665 | |||
4a1a9c9cdd | |||
71feb7961b | |||
ead529af54 | |||
45321f321e | |||
18222c8394 | |||
a7f49cbec8 | |||
7e0b8145b5 | |||
2b08711ec6 | |||
88e7d55bbc | |||
9de55e6ffd | |||
409a225afe | |||
db5e156ebc | |||
aeac95857e | |||
d5b7791710 | |||
c486bb724c | |||
19b94c01f3 | |||
404f40bcc1 | |||
9b1f8033eb | |||
e52d7d4a9e | |||
ed9edd54e4 | |||
d2479d6f52 | |||
78d6563bce | |||
d4a4a5b6ad | |||
9581804efa | |||
d07ae78901 | |||
683dbe2412 | |||
010ee00604 | |||
13bc27698e | |||
0481b05d1f | |||
4c863f5bf8 | |||
9ed20cb085 | |||
4fbb7582e1 | |||
29dfc173c6 | |||
f4d1107e86 | |||
324272fc0e | |||
ee575b34c5 | |||
a192204b41 | |||
545fd9a72f | |||
29b2dae630 | |||
2f3cf1ca84 | |||
24d29e5865 | |||
eea107d9b5 | |||
69e239530e | |||
65bb040db8 | |||
fae2791f45 | |||
0f8e356bca | |||
59277bc31f | |||
bebc606a4c | |||
106f9aee5e | |||
350ebab88a | |||
a3916b46a9 | |||
c52280bb78 | |||
155ad5911e | |||
228b20df82 | |||
2854383cf7 | |||
d0b87d2f35 | |||
71d797b9ee | |||
701afd43a4 | |||
d13623884a | |||
7320dd54e8 | |||
51a46f95c6 | |||
35ca7c1ff1 | |||
0169460194 | |||
42445e94aa | |||
250806d029 | |||
51d1bc843d | |||
e47a017009 | |||
5182f7f30f | |||
8f992acb94 | |||
33c7a6aa2b | |||
76ff82d191 | |||
b1e29eb585 | |||
a5aaf4d8d0 | |||
1f6d8bc602 | |||
e230bd83c6 | |||
b832d4c54f | |||
fb54ee1741 | |||
5b6f4be434 | |||
f9fdf42a17 | |||
7541076cf1 | |||
40f7c97292 | |||
06dea2cb9b | |||
cbf3cd05af | |||
6e10173a44 | |||
69bf75ae6d | |||
01ebd2ad7f | |||
42c2377a0d | |||
9d0ddc4709 | |||
a7f33f5d6f | |||
58f7c2f14a | |||
ebef3ed6f7 | |||
9e0726cee1 | |||
2d2c3c3f6f | |||
e95f9fc254 | |||
7e1beb473c | |||
61bf382ffa | |||
4fe57f57fa | |||
c695be11b5 | |||
e9f5641be3 | |||
b709447922 | |||
cd4e44f3dc | |||
975a6aa92d | |||
cb7641dc34 | |||
2124f71299 | |||
1618d5f3bb | |||
17826eae3b | |||
d73b5110dd | |||
b4907c2a51 | |||
fafb3abb64 | |||
7ea2ca6c40 | |||
50fb8738f8 | |||
8d69e99e78 | |||
9bc1cc585c | |||
4e08f0dd41 | |||
4a9d53539c | |||
9af24038bc | |||
92d40c7108 | |||
eb9ea1f72d | |||
a710a23102 | |||
e7b310bcc2 | |||
d556ccedb2 | |||
63454c11aa | |||
54e0bc6f04 | |||
9f8823aebf | |||
0988b4c394 | |||
ade083128f | |||
0035e60b1b | |||
62acbe1690 | |||
3e0051be7e | |||
72b3b23475 | |||
b8da1932f3 | |||
1c31338da3 | |||
99efe72052 | |||
5662f55ccf | |||
f9324a8790 | |||
c3abf83426 | |||
b99c1fdcc2 | |||
088e2e3051 | |||
5d5d1f46ba | |||
08076e3964 | |||
844ca6a0d5 | |||
0755ab7b4e | |||
a421444788 | |||
865d94a8d8 | |||
547e861704 | |||
1fd315016a | |||
0831788c86 | |||
3b4a696305 | |||
442b27c019 | |||
2809bfeb08 | |||
57817d75ef | |||
d3dda39beb | |||
9118518516 | |||
c0084a0451 | |||
3b58b0f4da | |||
1334602a2b | |||
f6e09fbf9c | |||
5ffa3fd2f6 | |||
44d57a1d8b | |||
1671966380 | |||
b38b64cee9 | |||
7ae2db7312 | |||
630fbb7973 | |||
c653372524 | |||
87ef503606 | |||
414728970a | |||
b0602a1161 | |||
143bda7c9f | |||
5878212b04 | |||
94c735af2d | |||
b5b8414c06 | |||
e24ab26874 | |||
200e19fada | |||
4b91299d10 | |||
fcd64b1de6 | |||
2ae5c255fd | |||
0a228e74fe | |||
4b3077dea3 | |||
ede89602f7 | |||
9273fb435f | |||
1dd2c422ca | |||
7396e4051b | |||
7138a16680 | |||
c6abecb89f | |||
b96337a6d7 | |||
3ae18175b5 | |||
9ea065edf1 | |||
74bd6444db | |||
472a94d371 | |||
184816ad4d | |||
ade05cdffa | |||
fb1cf2581e | |||
29975d6192 | |||
78fe81e3ed | |||
24fbacb037 | |||
2eaf223085 | |||
c71e860a06 | |||
7490a62a00 | |||
ffa64ccea2 | |||
80a245c8de | |||
6375fccf27 | |||
0d5061aebe | |||
238dd15ed0 | |||
bc91cac244 | |||
fb1edf51e8 | |||
4939613070 | |||
b0d7786e14 | |||
e7cab0e233 | |||
cf4b2e8b16 | |||
a46b0df3d1 | |||
9f8dd57386 | |||
02ed4eadd8 | |||
593710e961 | |||
4beeba5420 | |||
b43ce289c2 | |||
9b1894a2f3 | |||
4be4646ddd | |||
5ece1f224a | |||
95a073f061 | |||
4e7405a233 | |||
ff90f939ed | |||
8ca74951b0 | |||
339202a8fb | |||
1d7fe0e770 | |||
b991ae74ed | |||
9d3f2fa825 | |||
15d9fcdbd1 | |||
6e40825098 | |||
0a8a798c3a | |||
59266a2630 | |||
e4263abe90 | |||
16023fe934 | |||
f229257f30 | |||
726b227aa9 | |||
cc17103070 | |||
c12beb8991 | |||
2437f9cb4c | |||
eed1b6ea33 | |||
67c7e21b4b | |||
a8a6be013f | |||
35eaec5a52 | |||
9e3a4a9b7b | |||
cf665bc3f7 | |||
f649878d7e | |||
a2268d78b4 | |||
26ab338c83 | |||
0818b0a25c | |||
8bc63106d3 | |||
b5ae4bf78d | |||
4df589686c | |||
1e2aed8276 | |||
0d06d66f5c | |||
f8bbb9fabb | |||
1d3446304b | |||
53e53171c4 | |||
5435021ea4 | |||
661cbe15af | |||
d67ca566bd | |||
bbabb6b990 | |||
4c06d708d6 | |||
35d5e25672 | |||
a913650322 | |||
55dc4c1dde | |||
bda2001935 | |||
eef3bfe079 | |||
b7e8b1b54a | |||
d4a4cdca1d | |||
df01e9e429 | |||
953e7de70b | |||
fea4882f24 | |||
4115c41bf3 | |||
18b8c4bb18 | |||
fb578b02f2 | |||
c7200c4aed | |||
599c75a6d3 | |||
4cbb67e505 | |||
4af83ecf83 | |||
d70114b3dc | |||
a158b85bd6 | |||
9edf2ddac1 | |||
0a2a8957fa | |||
31c9119266 | |||
8fc2901fad | |||
04b9080612 | |||
07bdbc3743 | |||
befd3970d7 | |||
d25b0cfd59 | |||
a4e507077e | |||
fdc98d17ca | |||
a448dc7554 | |||
dec71d338d | |||
402f15e996 | |||
3dd614fd91 | |||
f99618f09b | |||
2e583aaf30 | |||
22baf1dd09 | |||
3984c9f9a1 | |||
75271b73a8 | |||
5e59e10f93 | |||
24438efbf1 | |||
3545f9b050 | |||
e9f5ed41be | |||
1c9775a9d9 | |||
f94846ccc5 | |||
6a790e0c97 | |||
86e759fb89 | |||
897fdad11b | |||
c51f3e810b | |||
d59f47156f | |||
c9f1422560 | |||
01b22a0ff0 | |||
655a9e3035 | |||
3816143646 | |||
0e61751fab | |||
c7cf80e5df | |||
5c69bac12f | |||
a26d11be87 | |||
587ef8e988 | |||
b4738ac07e | |||
09f2c0f60e | |||
a3b478b620 | |||
b7557909a3 | |||
5981d984ed | |||
50d09367ca | |||
40a1ec1ca2 | |||
c5ca90ed58 | |||
fdbac34bfb | |||
6cd1827fe2 | |||
c283c778e6 | |||
339a3c4ab8 | |||
c52654fa52 | |||
e3226caccb | |||
820cf7c815 | |||
1895dbb984 | |||
ed33f2bf2f | |||
51d3f2e761 | |||
60f3efc852 | |||
8d6f6ddf4f | |||
84deab1aba | |||
a43db097ca | |||
b4bb05a771 | |||
3cf0363668 | |||
c9ead30713 | |||
931cf3941b | |||
16657e5e1d | |||
cb09282472 | |||
655eb739fa | |||
e8853f23cd | |||
ff48f2b3a0 | |||
e40c2654d9 | |||
ab0ffa1c01 | |||
a5c2ab2125 | |||
181e56a70a | |||
9bd310086a | |||
f6db3d6bc3 | |||
f921762bf6 | |||
f9c46f9a86 | |||
c1d2381a9b | |||
960631e201 | |||
6ed68269a8 | |||
9275e2b8aa | |||
545f8933bc | |||
e9989b260e | |||
646488e0e2 | |||
ef2d285d47 | |||
64d8062621 | |||
d39627c5b6 | |||
f88c8ae423 | |||
ab01dfff7e | |||
8608ad1497 | |||
c93e5a88c7 | |||
425d141cbf | |||
3d859e5fbe | |||
57c07c7a57 | |||
55f54b5921 | |||
97e314f03a | |||
ed450cbf68 | |||
46f4308166 | |||
bccd75c72f | |||
16f0a0aaaf | |||
93f84f3351 | |||
a63dbe0f14 | |||
066dd6f345 | |||
04c1b67629 | |||
4e628ed4a6 | |||
a81ac6e5aa | |||
8682f2bbaa | |||
fac0a7d65d | |||
fea89e84f3 | |||
30419ed5e0 | |||
2772bfc08d | |||
41a677bdaf | |||
361943e033 | |||
20c9fc8ebe | |||
313d15c56c | |||
fd38be1636 | |||
6b8df2a27d | |||
9f655c6932 | |||
e7d7b014d2 | |||
2af3ec341b | |||
e68e68276c | |||
101bb76c18 | |||
3ebabcb2d8 | |||
63f6e7f45e | |||
43eac5bb12 | |||
74674531c8 | |||
a4572497be | |||
951b49f992 | |||
1afed544db | |||
66c366d18a | |||
5a1938ccf7 | |||
4c11dcc703 | |||
472a68c920 | |||
3e33d4a200 | |||
95c864e119 | |||
eb19cc2729 | |||
5956702c32 | |||
9afdbe65e7 | |||
f6518df0c4 | |||
05a685b035 | |||
3b5b5d82a0 | |||
06ba35cd42 | |||
3499d477dc | |||
a690c8e7a2 | |||
4ba562871e | |||
c8e54ef488 | |||
3ff4258fbb | |||
07ce2fc860 | |||
35040aab6a | |||
bfd5cc0a87 | |||
0fd45d73b1 | |||
3bf8d0f1b4 | |||
789cb2b24f | |||
7287f2bf11 | |||
b6a1946a60 | |||
9bbde2be14 | |||
f258713788 | |||
3dc3f46d66 | |||
be7249b537 | |||
c23c21d9c2 | |||
1b7002f663 | |||
5182283649 | |||
4599ae0bfd | |||
16a8ccbecc | |||
734e5b5283 | |||
9ccefc8349 | |||
a77dff3e11 | |||
9516a779fe | |||
0961a6598a | |||
03248b5fd8 | |||
c7e74ce372 | |||
91bdde095d | |||
0e10374194 | |||
d3f9e112c4 | |||
864adf2e87 | |||
0be943c2f6 | |||
04bec76068 |
36
.drone.star
Normal file
36
.drone.star
Normal file
@ -0,0 +1,36 @@
|
||||
# Use, modification, and distribution are
|
||||
# subject to the Boost Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE.txt)
|
||||
#
|
||||
# Copyright Rene Rivera 2020.
|
||||
|
||||
# For Drone CI we use the Starlark scripting language to reduce duplication.
|
||||
# As the yaml syntax for Drone CI is rather limited.
|
||||
#
|
||||
#
|
||||
globalenv={}
|
||||
linuxglobalimage="cppalliance/droneubuntu1604:1"
|
||||
windowsglobalimage="cppalliance/dronevs2019"
|
||||
|
||||
def main(ctx):
|
||||
return [
|
||||
linux_cxx("TOOLSET=gcc COMPILER=g++ CXXSTD=03,11 Job 0", "g++", packages="", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'TOOLSET': 'gcc', 'COMPILER': 'g++', 'CXXSTD': '03,11', 'DRONE_JOB_UUID': 'b6589fc6ab'}, globalenv=globalenv),
|
||||
linux_cxx("TOOLSET=gcc COMPILER=g++-4.7 CXXSTD=03,11 Job 1", "g++-4.7", packages="g++-4.7", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-4.7', 'CXXSTD': '03,11', 'DRONE_JOB_UUID': '356a192b79'}, globalenv=globalenv),
|
||||
linux_cxx("TOOLSET=gcc COMPILER=g++-4.8 CXXSTD=03,11 Job 2", "g++-4.8", packages="g++-4.8", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-4.8', 'CXXSTD': '03,11', 'DRONE_JOB_UUID': 'da4b9237ba'}, globalenv=globalenv),
|
||||
linux_cxx("TOOLSET=gcc COMPILER=g++-4.9 CXXSTD=03,11 Job 3", "g++-4.9", packages="g++-4.9", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-4.9', 'CXXSTD': '03,11', 'DRONE_JOB_UUID': '77de68daec'}, globalenv=globalenv),
|
||||
linux_cxx("TOOLSET=gcc COMPILER=g++-5 CXXSTD=03,11,14,1z Job 4", "g++-5", packages="g++-5", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-5', 'CXXSTD': '03,11,14,1z', 'DRONE_JOB_UUID': '1b64538924'}, globalenv=globalenv),
|
||||
linux_cxx("TOOLSET=gcc COMPILER=g++-6 CXXSTD=03,11,14,1z Job 5", "g++-6", packages="g++-6", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-6', 'CXXSTD': '03,11,14,1z', 'DRONE_JOB_UUID': 'ac3478d69a'}, globalenv=globalenv),
|
||||
linux_cxx("TOOLSET=gcc COMPILER=g++-7 CXXSTD=03,11,14,17 Job 6", "g++-7", packages="g++-7", buildtype="boost", buildscript="drone", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-7', 'CXXSTD': '03,11,14,17', 'DRONE_JOB_UUID': 'c1dfd96eea'}, globalenv=globalenv),
|
||||
linux_cxx("TOOLSET=clang COMPILER=clang++ CXXSTD=03,11 Job 7", "clang++", packages="", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '03,11', 'DRONE_JOB_UUID': '902ba3cda1'}, globalenv=globalenv),
|
||||
linux_cxx("TOOLSET=clang COMPILER=clang++-3.5 CXXSTD=03, Job 8", "clang++-3.5", packages="clang-3.5 libstdc++-4.9-dev", llvm_os="precise", llvm_ver="3.5", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-3.5', 'CXXSTD': '03,11,14,1z', 'DRONE_JOB_UUID': 'fe5dbbcea5'}, globalenv=globalenv),
|
||||
linux_cxx("TOOLSET=clang COMPILER=clang++-3.6 CXXSTD=03, Job 9", "clang++-3.6", packages="clang-3.6", llvm_os="precise", llvm_ver="3.6", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-3.6', 'CXXSTD': '03,11,14,1z', 'DRONE_JOB_UUID': '0ade7c2cf9'}, globalenv=globalenv),
|
||||
linux_cxx("TOOLSET=clang COMPILER=clang++-3.7 CXXSTD=03, Job 10", "clang++-3.7", packages="clang-3.7", llvm_os="precise", llvm_ver="3.7", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-3.7', 'CXXSTD': '03,11,14,1z', 'DRONE_JOB_UUID': 'b1d5781111'}, globalenv=globalenv),
|
||||
linux_cxx("TOOLSET=clang COMPILER=clang++-3.8 CXXSTD=03, Job 11", "clang++-3.8", packages="clang-3.8 libstdc++-4.9-dev", llvm_os="precise", llvm_ver="3.8", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-3.8', 'CXXSTD': '03,11,14,1z', 'DRONE_JOB_UUID': '17ba079149'}, globalenv=globalenv),
|
||||
linux_cxx("TOOLSET=clang COMPILER=clang++-3.9 CXXSTD=03, Job 12", "clang++-3.9", packages="clang-3.9 libstdc++-4.9-dev", llvm_os="precise", llvm_ver="3.9", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-3.9', 'CXXSTD': '03,11,14,1z', 'DRONE_JOB_UUID': '7b52009b64'}, globalenv=globalenv),
|
||||
linux_cxx("TOOLSET=clang COMPILER=clang++-4.0 CXXSTD=03, Job 13", "clang++-4.0", packages="clang-4.0", llvm_os="trusty", llvm_ver="4.0", buildtype="boost", buildscript="drone", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-4.0', 'CXXSTD': '03,11,14,1z', 'DRONE_JOB_UUID': 'bd307a3ec3'}, globalenv=globalenv),
|
||||
linux_cxx("TOOLSET=clang COMPILER=clang++-5.0 CXXSTD=03, Job 14", "clang++-5.0", packages="clang-5.0", llvm_os="trusty", llvm_ver="5.0", buildtype="boost", buildscript="drone", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-5.0', 'CXXSTD': '03,11,14,1z', 'DRONE_JOB_UUID': 'fa35e19212'}, globalenv=globalenv),
|
||||
osx_cxx("TOOLSET=clang COMPILER=clang++ CXXSTD=03,11,1 Job 15", "clang++", packages="", buildtype="boost", buildscript="drone", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '03,11,14,1z', 'DRONE_JOB_UUID': 'f1abd67035'}, globalenv=globalenv),
|
||||
]
|
||||
|
||||
# from https://github.com/boostorg/boost-ci
|
||||
load("@boost_ci//ci/drone/:functions.star", "linux_cxx","windows_cxx","osx_cxx","freebsd_cxx")
|
37
.drone/drone.sh
Executable file
37
.drone/drone.sh
Executable file
@ -0,0 +1,37 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright 2020 Rene Rivera, Sam Darwin
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE.txt or copy at http://boost.org/LICENSE_1_0.txt)
|
||||
|
||||
set -e
|
||||
export TRAVIS_BUILD_DIR=$(pwd)
|
||||
export DRONE_BUILD_DIR=$(pwd)
|
||||
export TRAVIS_BRANCH=$DRONE_BRANCH
|
||||
export VCS_COMMIT_ID=$DRONE_COMMIT
|
||||
export GIT_COMMIT=$DRONE_COMMIT
|
||||
export REPO_NAME=$DRONE_REPO
|
||||
export PATH=~/.local/bin:/usr/local/bin:$PATH
|
||||
|
||||
if [ "$DRONE_JOB_BUILDTYPE" == "boost" ]; then
|
||||
|
||||
echo '==================================> INSTALL'
|
||||
|
||||
BOOST_BRANCH=develop && [ "$TRAVIS_BRANCH" == "master" ] && BOOST_BRANCH=master || true
|
||||
cd ..
|
||||
git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
|
||||
cd boost-root
|
||||
git submodule update --init tools/build
|
||||
git submodule update --init libs/config
|
||||
git submodule update --init tools/boostdep
|
||||
cp -r $TRAVIS_BUILD_DIR/* libs/optional
|
||||
python tools/boostdep/depinst/depinst.py optional
|
||||
./bootstrap.sh
|
||||
./b2 headers
|
||||
|
||||
echo '==================================> SCRIPT'
|
||||
|
||||
echo "using $TOOLSET : : $COMPILER ;" > ~/user-config.jam
|
||||
./b2 libs/optional/test toolset=$TOOLSET cxxstd=$CXXSTD
|
||||
|
||||
fi
|
613
.github/workflows/ci.yml
vendored
Normal file
613
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,613 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
- feature/**
|
||||
|
||||
env:
|
||||
UBSAN_OPTIONS: print_stacktrace=1
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
jobs:
|
||||
posix:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- toolset: gcc-4.8
|
||||
cxxstd: "03,11"
|
||||
os: ubuntu-latest
|
||||
container: ubuntu:18.04
|
||||
install: g++-4.8-multilib
|
||||
address-model: 32,64
|
||||
- toolset: gcc-5
|
||||
cxxstd: "03,11,14,1z"
|
||||
os: ubuntu-latest
|
||||
container: ubuntu:18.04
|
||||
install: g++-5-multilib
|
||||
address-model: 32,64
|
||||
- toolset: gcc-6
|
||||
cxxstd: "03,11,14,1z"
|
||||
os: ubuntu-latest
|
||||
container: ubuntu:18.04
|
||||
install: g++-6-multilib
|
||||
address-model: 32,64
|
||||
- toolset: gcc-7
|
||||
cxxstd: "03,11,14,17"
|
||||
os: ubuntu-latest
|
||||
container: ubuntu:18.04
|
||||
install: g++-7-multilib
|
||||
address-model: 32,64
|
||||
- toolset: gcc-8
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-20.04
|
||||
install: g++-8-multilib
|
||||
address-model: 32,64
|
||||
- toolset: gcc-9
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-20.04
|
||||
install: g++-9-multilib
|
||||
address-model: 32,64
|
||||
- toolset: gcc-10
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-20.04
|
||||
install: g++-10-multilib
|
||||
address-model: 32,64
|
||||
- toolset: gcc-11
|
||||
cxxstd: "03,11,14,17,20"
|
||||
os: ubuntu-22.04
|
||||
install: g++-11-multilib
|
||||
address-model: 32,64
|
||||
- toolset: gcc-12
|
||||
cxxstd: "03,11,14,17,20,2b"
|
||||
os: ubuntu-22.04
|
||||
install: g++-12-multilib
|
||||
address-model: 32,64
|
||||
- toolset: gcc-13
|
||||
cxxstd: "03,11,14,17,20,2b"
|
||||
os: ubuntu-latest
|
||||
container: ubuntu:23.04
|
||||
install: g++-13-multilib
|
||||
address-model: 32,64
|
||||
- toolset: clang
|
||||
compiler: clang++-3.9
|
||||
cxxstd: "03,11,14"
|
||||
os: ubuntu-latest
|
||||
container: ubuntu:18.04
|
||||
install: clang-3.9
|
||||
- toolset: clang
|
||||
compiler: clang++-4.0
|
||||
cxxstd: "03,11,14"
|
||||
os: ubuntu-latest
|
||||
container: ubuntu:18.04
|
||||
install: clang-4.0
|
||||
- toolset: clang
|
||||
compiler: clang++-5.0
|
||||
cxxstd: "03,11,14,1z"
|
||||
os: ubuntu-latest
|
||||
container: ubuntu:18.04
|
||||
install: clang-5.0
|
||||
- toolset: clang
|
||||
compiler: clang++-6.0
|
||||
cxxstd: "03,11,14,17"
|
||||
os: ubuntu-20.04
|
||||
install: clang-6.0
|
||||
- toolset: clang
|
||||
compiler: clang++-7
|
||||
cxxstd: "03,11,14,17"
|
||||
os: ubuntu-20.04
|
||||
install: clang-7
|
||||
- toolset: clang
|
||||
compiler: clang++-8
|
||||
cxxstd: "03,11,14,17"
|
||||
os: ubuntu-20.04
|
||||
install: clang-8
|
||||
- toolset: clang
|
||||
compiler: clang++-9
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-20.04
|
||||
install: clang-9
|
||||
- toolset: clang
|
||||
compiler: clang++-10
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-20.04
|
||||
- toolset: clang
|
||||
compiler: clang++-11
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-20.04
|
||||
- toolset: clang
|
||||
compiler: clang++-12
|
||||
cxxstd: "03,11,14,17,20"
|
||||
os: ubuntu-20.04
|
||||
- toolset: clang
|
||||
compiler: clang++-13
|
||||
cxxstd: "03,11,14,17,20,2b"
|
||||
container: ubuntu:22.04
|
||||
os: ubuntu-latest
|
||||
install: clang-13
|
||||
- toolset: clang
|
||||
compiler: clang++-14
|
||||
cxxstd: "03,11,14,17,20,2b"
|
||||
container: ubuntu:22.04
|
||||
os: ubuntu-latest
|
||||
install: clang-14
|
||||
- toolset: clang
|
||||
compiler: clang++-15
|
||||
cxxstd: "03,11,14,17,20,2b"
|
||||
container: ubuntu:22.04
|
||||
os: ubuntu-latest
|
||||
install: clang-15
|
||||
- toolset: clang
|
||||
compiler: clang++-16
|
||||
cxxstd: "03,11,14,17,20,2b"
|
||||
container: ubuntu:23.04
|
||||
os: ubuntu-latest
|
||||
install: clang-16
|
||||
- toolset: clang
|
||||
compiler: clang++-17
|
||||
cxxstd: "03,11,14,17,20,2b"
|
||||
container: ubuntu:23.10
|
||||
os: ubuntu-latest
|
||||
install: clang-17
|
||||
- toolset: clang
|
||||
cxxstd: "03,11,14,17,20,2b"
|
||||
os: macos-12
|
||||
- toolset: clang
|
||||
cxxstd: "03,11,14,17,20,2b"
|
||||
os: macos-13
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
container: ${{matrix.container}}
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup container environment
|
||||
if: matrix.container
|
||||
run: |
|
||||
apt-get update
|
||||
apt-get -y install sudo python3 git g++
|
||||
|
||||
- name: Install packages
|
||||
if: matrix.install
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install ${{matrix.install}}
|
||||
|
||||
- name: Setup Boost
|
||||
run: |
|
||||
echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY
|
||||
LIBRARY=${GITHUB_REPOSITORY#*/}
|
||||
echo LIBRARY: $LIBRARY
|
||||
echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV
|
||||
echo GITHUB_BASE_REF: $GITHUB_BASE_REF
|
||||
echo GITHUB_REF: $GITHUB_REF
|
||||
REF=${GITHUB_BASE_REF:-$GITHUB_REF}
|
||||
REF=${REF#refs/heads/}
|
||||
echo REF: $REF
|
||||
BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true
|
||||
echo BOOST_BRANCH: $BOOST_BRANCH
|
||||
cd ..
|
||||
git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
|
||||
cd boost-root
|
||||
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
|
||||
git submodule update --init tools/boostdep
|
||||
python3 tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY
|
||||
./bootstrap.sh
|
||||
./b2 -d0 headers
|
||||
|
||||
- name: Create user-config.jam
|
||||
if: matrix.compiler
|
||||
run: |
|
||||
echo "using ${{matrix.toolset}} : : ${{matrix.compiler}} ;" > ~/user-config.jam
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
cd ../boost-root
|
||||
./b2 -j3 libs/$LIBRARY/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} ${ADDRMD:+address-model=$ADDRMD} variant=debug,release
|
||||
|
||||
windows:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- toolset: msvc-14.0
|
||||
cxxstd: 14,latest
|
||||
addrmd: 32,64
|
||||
os: windows-2019
|
||||
- toolset: msvc-14.2
|
||||
cxxstd: "14,17,20,latest"
|
||||
addrmd: 32,64
|
||||
os: windows-2019
|
||||
- toolset: msvc-14.3
|
||||
cxxstd: "14,17,20,latest"
|
||||
addrmd: 32,64
|
||||
os: windows-2022
|
||||
- toolset: clang-win
|
||||
cxxstd: "14,17,20,latest"
|
||||
addrmd: 32,64
|
||||
os: windows-2022
|
||||
- toolset: gcc
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
addrmd: 64
|
||||
os: windows-2019
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Boost
|
||||
shell: cmd
|
||||
run: |
|
||||
echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY%
|
||||
for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi
|
||||
echo LIBRARY: %LIBRARY%
|
||||
echo LIBRARY=%LIBRARY%>>%GITHUB_ENV%
|
||||
echo GITHUB_BASE_REF: %GITHUB_BASE_REF%
|
||||
echo GITHUB_REF: %GITHUB_REF%
|
||||
if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF%
|
||||
set BOOST_BRANCH=develop
|
||||
for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master
|
||||
echo BOOST_BRANCH: %BOOST_BRANCH%
|
||||
cd ..
|
||||
git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root
|
||||
cd boost-root
|
||||
xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\
|
||||
git submodule update --init tools/boostdep
|
||||
python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY%
|
||||
cmd /c bootstrap
|
||||
b2 -d0 headers
|
||||
|
||||
- name: Run tests
|
||||
shell: cmd
|
||||
run: |
|
||||
cd ../boost-root
|
||||
b2 -j3 libs/%LIBRARY%/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release embed-manifest-via=linker
|
||||
|
||||
posix-cmake-subdir:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
- os: macos-12
|
||||
- os: macos-13
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install packages
|
||||
if: matrix.install
|
||||
run: sudo apt-get -y install ${{matrix.install}}
|
||||
|
||||
- name: Setup Boost
|
||||
run: |
|
||||
echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY
|
||||
LIBRARY=${GITHUB_REPOSITORY#*/}
|
||||
echo LIBRARY: $LIBRARY
|
||||
echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV
|
||||
echo GITHUB_BASE_REF: $GITHUB_BASE_REF
|
||||
echo GITHUB_REF: $GITHUB_REF
|
||||
REF=${GITHUB_BASE_REF:-$GITHUB_REF}
|
||||
REF=${REF#refs/heads/}
|
||||
echo REF: $REF
|
||||
BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true
|
||||
echo BOOST_BRANCH: $BOOST_BRANCH
|
||||
cd ..
|
||||
git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
|
||||
cd boost-root
|
||||
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
|
||||
git submodule update --init tools/boostdep
|
||||
python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY
|
||||
|
||||
- name: Use library with add_subdirectory
|
||||
run: |
|
||||
cd ../boost-root/libs/$LIBRARY/test/cmake_subdir_test
|
||||
mkdir __build__ && cd __build__
|
||||
cmake ..
|
||||
cmake --build .
|
||||
ctest --output-on-failure --no-tests=error
|
||||
|
||||
posix-cmake-install:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
- os: macos-12
|
||||
- os: macos-13
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install packages
|
||||
if: matrix.install
|
||||
run: sudo apt-get -y install ${{matrix.install}}
|
||||
|
||||
- name: Setup Boost
|
||||
run: |
|
||||
echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY
|
||||
LIBRARY=${GITHUB_REPOSITORY#*/}
|
||||
echo LIBRARY: $LIBRARY
|
||||
echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV
|
||||
echo GITHUB_BASE_REF: $GITHUB_BASE_REF
|
||||
echo GITHUB_REF: $GITHUB_REF
|
||||
REF=${GITHUB_BASE_REF:-$GITHUB_REF}
|
||||
REF=${REF#refs/heads/}
|
||||
echo REF: $REF
|
||||
BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true
|
||||
echo BOOST_BRANCH: $BOOST_BRANCH
|
||||
cd ..
|
||||
git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
|
||||
cd boost-root
|
||||
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
|
||||
git submodule update --init tools/boostdep
|
||||
python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
cd ../boost-root
|
||||
mkdir __build__ && cd __build__
|
||||
cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DCMAKE_INSTALL_PREFIX=~/.local ..
|
||||
|
||||
- name: Install
|
||||
run: |
|
||||
cd ../boost-root/__build__
|
||||
cmake --build . --target install
|
||||
|
||||
- name: Use the installed library
|
||||
run: |
|
||||
cd ../boost-root/libs/$LIBRARY/test/cmake_install_test && mkdir __build__ && cd __build__
|
||||
cmake -DCMAKE_INSTALL_PREFIX=~/.local ..
|
||||
cmake --build .
|
||||
ctest --output-on-failure --no-tests=error
|
||||
|
||||
posix-cmake-test:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
- os: macos-12
|
||||
- os: macos-13
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install packages
|
||||
if: matrix.install
|
||||
run: sudo apt-get -y install ${{matrix.install}}
|
||||
|
||||
- name: Setup Boost
|
||||
run: |
|
||||
echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY
|
||||
LIBRARY=${GITHUB_REPOSITORY#*/}
|
||||
echo LIBRARY: $LIBRARY
|
||||
echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV
|
||||
echo GITHUB_BASE_REF: $GITHUB_BASE_REF
|
||||
echo GITHUB_REF: $GITHUB_REF
|
||||
REF=${GITHUB_BASE_REF:-$GITHUB_REF}
|
||||
REF=${REF#refs/heads/}
|
||||
echo REF: $REF
|
||||
BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true
|
||||
echo BOOST_BRANCH: $BOOST_BRANCH
|
||||
cd ..
|
||||
git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
|
||||
cd boost-root
|
||||
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
|
||||
git submodule update --init tools/boostdep
|
||||
python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
cd ../boost-root
|
||||
mkdir __build__ && cd __build__
|
||||
cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DBUILD_TESTING=ON ..
|
||||
|
||||
- name: Build tests
|
||||
run: |
|
||||
cd ../boost-root/__build__
|
||||
cmake --build . --target tests
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
cd ../boost-root/__build__
|
||||
ctest --output-on-failure --no-tests=error
|
||||
|
||||
windows-cmake-subdir:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: windows-2019
|
||||
- os: windows-2022
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Boost
|
||||
shell: cmd
|
||||
run: |
|
||||
echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY%
|
||||
for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi
|
||||
echo LIBRARY: %LIBRARY%
|
||||
echo LIBRARY=%LIBRARY%>>%GITHUB_ENV%
|
||||
echo GITHUB_BASE_REF: %GITHUB_BASE_REF%
|
||||
echo GITHUB_REF: %GITHUB_REF%
|
||||
if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF%
|
||||
set BOOST_BRANCH=develop
|
||||
for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master
|
||||
echo BOOST_BRANCH: %BOOST_BRANCH%
|
||||
cd ..
|
||||
git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root
|
||||
cd boost-root
|
||||
xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\
|
||||
git submodule update --init tools/boostdep
|
||||
python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY%
|
||||
|
||||
- name: Use library with add_subdirectory (Debug)
|
||||
shell: cmd
|
||||
run: |
|
||||
cd ../boost-root/libs/%LIBRARY%/test/cmake_subdir_test
|
||||
mkdir __build__ && cd __build__
|
||||
cmake ..
|
||||
cmake --build . --config Debug
|
||||
ctest --output-on-failure --no-tests=error -C Debug
|
||||
|
||||
- name: Use library with add_subdirectory (Release)
|
||||
shell: cmd
|
||||
run: |
|
||||
cd ../boost-root/libs/%LIBRARY%/test/cmake_subdir_test/__build__
|
||||
cmake --build . --config Release
|
||||
ctest --output-on-failure --no-tests=error -C Release
|
||||
|
||||
windows-cmake-install:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: windows-2019
|
||||
- os: windows-2022
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Boost
|
||||
shell: cmd
|
||||
run: |
|
||||
echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY%
|
||||
for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi
|
||||
echo LIBRARY: %LIBRARY%
|
||||
echo LIBRARY=%LIBRARY%>>%GITHUB_ENV%
|
||||
echo GITHUB_BASE_REF: %GITHUB_BASE_REF%
|
||||
echo GITHUB_REF: %GITHUB_REF%
|
||||
if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF%
|
||||
set BOOST_BRANCH=develop
|
||||
for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master
|
||||
echo BOOST_BRANCH: %BOOST_BRANCH%
|
||||
cd ..
|
||||
git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root
|
||||
cd boost-root
|
||||
xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\
|
||||
git submodule update --init tools/boostdep
|
||||
python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY%
|
||||
|
||||
- name: Configure
|
||||
shell: cmd
|
||||
run: |
|
||||
cd ../boost-root
|
||||
mkdir __build__ && cd __build__
|
||||
cmake -DBOOST_INCLUDE_LIBRARIES=%LIBRARY% -DCMAKE_INSTALL_PREFIX=C:/cmake-prefix ..
|
||||
|
||||
- name: Install (Debug)
|
||||
shell: cmd
|
||||
run: |
|
||||
cd ../boost-root/__build__
|
||||
cmake --build . --target install --config Debug
|
||||
|
||||
- name: Install (Release)
|
||||
shell: cmd
|
||||
run: |
|
||||
cd ../boost-root/__build__
|
||||
cmake --build . --target install --config Release
|
||||
|
||||
- name: Use the installed library (Debug)
|
||||
shell: cmd
|
||||
run: |
|
||||
cd ../boost-root/libs/%LIBRARY%/test/cmake_install_test && mkdir __build__ && cd __build__
|
||||
cmake -DCMAKE_INSTALL_PREFIX=C:/cmake-prefix ..
|
||||
cmake --build . --config Debug
|
||||
ctest --output-on-failure --no-tests=error -C Debug
|
||||
|
||||
- name: Use the installed library (Release)
|
||||
shell: cmd
|
||||
run: |
|
||||
cd ../boost-root/libs/%LIBRARY%/test/cmake_install_test/__build__
|
||||
cmake --build . --config Release
|
||||
ctest --output-on-failure --no-tests=error -C Release
|
||||
|
||||
windows-cmake-test:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: windows-2019
|
||||
- os: windows-2022
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Boost
|
||||
shell: cmd
|
||||
run: |
|
||||
echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY%
|
||||
for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi
|
||||
echo LIBRARY: %LIBRARY%
|
||||
echo LIBRARY=%LIBRARY%>>%GITHUB_ENV%
|
||||
echo GITHUB_BASE_REF: %GITHUB_BASE_REF%
|
||||
echo GITHUB_REF: %GITHUB_REF%
|
||||
if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF%
|
||||
set BOOST_BRANCH=develop
|
||||
for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master
|
||||
echo BOOST_BRANCH: %BOOST_BRANCH%
|
||||
cd ..
|
||||
git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root
|
||||
cd boost-root
|
||||
xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\
|
||||
git submodule update --init tools/boostdep
|
||||
python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY%
|
||||
|
||||
- name: Configure
|
||||
shell: cmd
|
||||
run: |
|
||||
cd ../boost-root
|
||||
mkdir __build__ && cd __build__
|
||||
cmake -DBOOST_INCLUDE_LIBRARIES=%LIBRARY% -DBUILD_TESTING=ON ..
|
||||
|
||||
- name: Build tests (Debug)
|
||||
shell: cmd
|
||||
run: |
|
||||
cd ../boost-root/__build__
|
||||
cmake --build . --target tests --config Debug
|
||||
|
||||
- name: Run tests (Debug)
|
||||
shell: cmd
|
||||
run: |
|
||||
cd ../boost-root/__build__
|
||||
ctest --output-on-failure --no-tests=error -C Debug
|
||||
|
||||
- name: Build tests (Release)
|
||||
shell: cmd
|
||||
run: |
|
||||
cd ../boost-root/__build__
|
||||
cmake --build . --target tests --config Release
|
||||
|
||||
- name: Run tests (Release)
|
||||
shell: cmd
|
||||
run: |
|
||||
cd ../boost-root/__build__
|
||||
ctest --output-on-failure --no-tests=error -C Release
|
201
.travis.yml
Normal file
201
.travis.yml
Normal file
@ -0,0 +1,201 @@
|
||||
# Copyright 2016, 2017 Peter Dimov
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
|
||||
|
||||
language: cpp
|
||||
|
||||
sudo: false
|
||||
|
||||
python: "2.7"
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- develop
|
||||
- /feature\/.*/
|
||||
|
||||
env:
|
||||
matrix:
|
||||
- BOGUS_JOB=true
|
||||
|
||||
matrix:
|
||||
|
||||
exclude:
|
||||
- env: BOGUS_JOB=true
|
||||
|
||||
include:
|
||||
- os: linux
|
||||
compiler: g++
|
||||
env: TOOLSET=gcc COMPILER=g++ CXXSTD=03,11
|
||||
|
||||
- os: linux
|
||||
compiler: g++-4.7
|
||||
env: TOOLSET=gcc COMPILER=g++-4.7 CXXSTD=03,11
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-4.7
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-4.8
|
||||
env: TOOLSET=gcc COMPILER=g++-4.8 CXXSTD=03,11
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-4.8
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- os: linux
|
||||
compiler: g++-4.9
|
||||
env: TOOLSET=gcc COMPILER=g++-4.9 CXXSTD=03,11
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-4.9
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-5
|
||||
env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=03,11,14,1z
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-5
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-6
|
||||
env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=03,11,14,1z
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-6
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
dist: trusty
|
||||
compiler: g++-7
|
||||
env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=03,11,14,17
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-7
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: clang++
|
||||
env: TOOLSET=clang COMPILER=clang++ CXXSTD=03,11
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.5
|
||||
env: TOOLSET=clang COMPILER=clang++-3.5 CXXSTD=03,11,14,1z
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.5
|
||||
- libstdc++-4.9-dev
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.5
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.6
|
||||
env: TOOLSET=clang COMPILER=clang++-3.6 CXXSTD=03,11,14,1z
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.6
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.6
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.7
|
||||
env: TOOLSET=clang COMPILER=clang++-3.7 CXXSTD=03,11,14,1z
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.7
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.7
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.8
|
||||
env: TOOLSET=clang COMPILER=clang++-3.8 CXXSTD=03,11,14,1z
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.8
|
||||
- libstdc++-4.9-dev
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.8
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.9
|
||||
env: TOOLSET=clang COMPILER=clang++-3.9 CXXSTD=03,11,14,1z
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.9
|
||||
- libstdc++-4.9-dev
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.9
|
||||
|
||||
- os: linux
|
||||
dist: trusty
|
||||
compiler: clang++-4.0
|
||||
env: TOOLSET=clang COMPILER=clang++-4.0 CXXSTD=03,11,14,1z
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-4.0
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-4.0
|
||||
|
||||
- os: linux
|
||||
dist: trusty
|
||||
compiler: clang++-5.0
|
||||
env: TOOLSET=clang COMPILER=clang++-5.0 CXXSTD=03,11,14,1z
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-5.0
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-5.0
|
||||
|
||||
- os: osx
|
||||
compiler: clang++
|
||||
env: TOOLSET=clang COMPILER=clang++ CXXSTD=03,11,14,1z
|
||||
|
||||
install:
|
||||
- BOOST_BRANCH=develop && [ "$TRAVIS_BRANCH" == "master" ] && BOOST_BRANCH=master || true
|
||||
- cd ..
|
||||
- git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
|
||||
- cd boost-root
|
||||
- git submodule update --init tools/build
|
||||
- git submodule update --init libs/config
|
||||
- git submodule update --init tools/boostdep
|
||||
- cp -r $TRAVIS_BUILD_DIR/* libs/optional
|
||||
- python tools/boostdep/depinst/depinst.py optional
|
||||
- ./bootstrap.sh
|
||||
- ./b2 headers
|
||||
|
||||
script:
|
||||
- |-
|
||||
echo "using $TOOLSET : : $COMPILER ;" > ~/user-config.jam
|
||||
- ./b2 libs/optional/test toolset=$TOOLSET cxxstd=$CXXSTD
|
||||
|
||||
notifications:
|
||||
email:
|
||||
on_success: always
|
31
CMakeLists.txt
Normal file
31
CMakeLists.txt
Normal file
@ -0,0 +1,31 @@
|
||||
# Generated by `boostdep --cmake optional`
|
||||
# Copyright 2020, 2021 Peter Dimov
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
cmake_minimum_required(VERSION 3.5...3.20)
|
||||
|
||||
project(boost_optional VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX)
|
||||
|
||||
add_library(boost_optional INTERFACE)
|
||||
add_library(Boost::optional ALIAS boost_optional)
|
||||
|
||||
target_include_directories(boost_optional INTERFACE include)
|
||||
|
||||
target_link_libraries(boost_optional
|
||||
INTERFACE
|
||||
Boost::assert
|
||||
Boost::config
|
||||
Boost::core
|
||||
Boost::move
|
||||
Boost::static_assert
|
||||
Boost::throw_exception
|
||||
Boost::type_traits
|
||||
)
|
||||
target_compile_features(boost_optional INTERFACE cxx_std_11)
|
||||
|
||||
if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt")
|
||||
|
||||
add_subdirectory(test)
|
||||
|
||||
endif()
|
15
README.md
Normal file
15
README.md
Normal file
@ -0,0 +1,15 @@
|
||||
optional
|
||||
========
|
||||
|
||||
A library for representing optional (nullable) objects in C++.
|
||||
|
||||
```cpp
|
||||
optional<int> readInt(); // this function may return either an int or a not-an-int
|
||||
|
||||
if (optional<int> oi = readInt()) // did I get a real int
|
||||
cout << "my int is: " << *oi; // use my int
|
||||
else
|
||||
cout << "I have no int";
|
||||
```
|
||||
|
||||
For more information refer to the documentation provided with this library.
|
26
build.jam
Normal file
26
build.jam
Normal file
@ -0,0 +1,26 @@
|
||||
# Copyright René Ferdinand Rivera Morell 2023-2024
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
require-b2 5.2 ;
|
||||
|
||||
constant boost_dependencies :
|
||||
/boost/assert//boost_assert
|
||||
/boost/config//boost_config
|
||||
/boost/core//boost_core
|
||||
/boost/move//boost_move
|
||||
/boost/static_assert//boost_static_assert
|
||||
/boost/throw_exception//boost_throw_exception
|
||||
/boost/type_traits//boost_type_traits ;
|
||||
|
||||
project /boost/optional ;
|
||||
|
||||
explicit
|
||||
[ alias boost_optional : : : : <library>$(boost_dependencies) <include>include ]
|
||||
[ alias all : boost_optional test ]
|
||||
;
|
||||
|
||||
call-if : boost-library optional
|
||||
;
|
||||
|
105
doc/00_optional.qbk
Normal file
105
doc/00_optional.qbk
Normal file
@ -0,0 +1,105 @@
|
||||
[library Boost.Optional
|
||||
[quickbook 1.4]
|
||||
[authors [Cacciola Carballal, Fernando Luis]]
|
||||
[copyright 2003-2007 Fernando Luis Cacciola Carballal]
|
||||
[copyright 2014-2024 Andrzej Krzemieński]
|
||||
[category miscellaneous]
|
||||
[id optional]
|
||||
[dirname optional]
|
||||
[purpose
|
||||
Discriminated-union wrapper for optional values
|
||||
]
|
||||
[source-mode c++]
|
||||
[license
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
[@http://www.boost.org/LICENSE_1_0.txt])
|
||||
]
|
||||
]
|
||||
|
||||
[/ Macros will be used for links so we have a central place to change them ]
|
||||
|
||||
|
||||
[/ Cited Boost resources ]
|
||||
|
||||
[def __BOOST_VARIANT__ [@../../../variant/index.html Boost.Variant]]
|
||||
[def __BOOST_TUPLE__ [@../../../tuple/index.html Boost.Tuple]]
|
||||
[def __BOOST_TRIBOOL__ [@../../../../doc/html/tribool.html boost::tribool]]
|
||||
|
||||
[def __OPTIONAL_POINTEE__ [@../../../utility/OptionalPointee.html `OptionalPointee`]]
|
||||
[def __COPY_CONSTRUCTIBLE__ [@../../../utility/CopyConstructible.html `CopyConstructible`]]
|
||||
[def __MOVE_CONSTRUCTIBLE__ `MoveConstructible`]
|
||||
[def __FUNCTION_EQUAL_POINTEES__ [@../../../utility/OptionalPointee.html#equal `equal_pointees()`]]
|
||||
[def __FUNCTION_LESS_POINTEES__ [@../../../utility/OptionalPointee.html#less `less_pointees()`]]
|
||||
|
||||
[def __IN_PLACE_FACTORY_HPP__ [@../../../../boost/utility/in_place_factory.hpp in_place_factory.hpp]]
|
||||
[def __TYPED_IN_PLACE_FACTORY_HPP__ [@../../../../boost/utility/typed_in_place_factory.hpp typed_in_place_factory.hpp]]
|
||||
|
||||
[/ Other web resources ]
|
||||
|
||||
[def __HASKELL__ [@http://www.haskell.org/ Haskell]]
|
||||
[def __STD_DEFAULT_CONSTRUCTIBLE__ [@https://en.cppreference.com/w/cpp/named_req/DefaultConstructible `DefaultConstructible`]]
|
||||
[def __STD_LESS_THAN_COMPARABLE__ [@https://en.cppreference.com/w/cpp/named_req/LessThanComparable `LessThanComparable`]]
|
||||
[def __STD_EQUALITY_COMPARABLE__ [@https://en.cppreference.com/w/cpp/named_req/EqualityComparable `EqualityComparable`]]
|
||||
[def __SGI_GENERATOR__ [@http://www.rrsd.com/software_development/stl/stl/Generator.html `Generator`]]
|
||||
|
||||
|
||||
[/ Icons ]
|
||||
|
||||
[def __SPACE__ [$images/space.png]]
|
||||
[def __GO_TO__ [$images/R.png]]
|
||||
|
||||
|
||||
[section Introduction]
|
||||
Class template `optional` is a wrapper for representing 'optional' (or 'nullable') objects who may not (yet) contain a valid value. Optional objects offer full value semantics; they are good for passing by value and usage inside STL containers. This is a header-only library.
|
||||
|
||||
[heading Problem]
|
||||
Suppose we want to read a parameter from a config file which represents some integral value, let's call it `"MaxValue"`. It is possible that this parameter is not specified; such situation is no error. It is valid to not specify the parameter and in that case the program is supposed to behave slightly differently. Also, suppose that any possible value of type `int` is a valid value for `"MaxValue"`, so we cannot just use `-1` to represent the absence of the parameter in the config file.
|
||||
|
||||
[heading Solution]
|
||||
|
||||
This is how you solve it with `boost::optional`:
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
boost::optional<int> getConfigParam(std::string name); // return either an int or a `not-an-int`
|
||||
|
||||
int main()
|
||||
{
|
||||
if (boost::optional<int> oi = getConfigParam("MaxValue")) // did I get a real int?
|
||||
runWithMax(*oi); // use my int
|
||||
else
|
||||
runWithNoMax();
|
||||
}
|
||||
|
||||
[endsect]
|
||||
|
||||
[include 01_quick_start.qbk]
|
||||
[section Tutorial]
|
||||
[include 10_motivation.qbk]
|
||||
[include 11_development.qbk]
|
||||
[include 12_when_to_use.qbk]
|
||||
[include 13_relational_operators.qbk]
|
||||
[include 14_monadic_interface.qbk]
|
||||
[include 15_io.qbk]
|
||||
[include 16_optional_references.qbk]
|
||||
[include 17_in_place_factories.qbk]
|
||||
[include 18_gotchas.qbk]
|
||||
[include 19_exception_safety.qbk]
|
||||
[include 1A_type_requirements.qbk]
|
||||
[include 1B_on_performance.qbk]
|
||||
[endsect]
|
||||
[section:reference Reference]
|
||||
[include 21_ref_none.qbk]
|
||||
[include 22_ref_bad_optional_access.qbk]
|
||||
[include 23_ref_optional_io.qbk]
|
||||
[include 24_ref_optional_fwd.qbk]
|
||||
[section Header <boost/optional/optional.hpp>]
|
||||
[include 27_ref_optional_synopsis.qbk]
|
||||
[include 28_ref_optional_semantics.qbk]
|
||||
[endsect]
|
||||
[include 29_ref_optional_convenience.qbk]
|
||||
[endsect]
|
||||
[include 90_dependencies.qbk]
|
||||
[include 91_relnotes.qbk]
|
||||
[include 92_acknowledgments.qbk]
|
160
doc/01_quick_start.qbk
Normal file
160
doc/01_quick_start.qbk
Normal file
@ -0,0 +1,160 @@
|
||||
[/
|
||||
Boost.Optional
|
||||
|
||||
Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
|
||||
Copyright (c) 2014 Andrzej Krzemienski
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
|
||||
[section Quick Start]
|
||||
|
||||
[section Optional return values]
|
||||
|
||||
Let's write and use a converter function that converts a `std::string` to an `int`. It is possible that for a given string (e.g. `"cat"`) there exists no value of type `int` capable of representing the conversion result. We do not consider such situation an error. We expect that the converter can be used only to check if the conversion is possible. A natural signature for this function can be:
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
boost::optional<int> convert(const std::string& text);
|
||||
|
||||
All necessary functionality can be included with one header `<boost/optional.hpp>`. The above function signature means that the function can either return a value of type `int` or a flag indicating that no value of `int` is available. This does not indicate an error. It is like one additional value of `int`. This is how we can use our function:
|
||||
|
||||
const std::string& text = /*... */;
|
||||
boost::optional<int> oi = convert(text); // move-construct
|
||||
if (oi) // contextual conversion to bool
|
||||
int i = *oi; // operator*
|
||||
|
||||
In order to test if `optional` contains a value, we use the contextual conversion to type `bool`. Because of this we can combine the initialization of the optional object and the test into one instruction:
|
||||
|
||||
if (boost::optional<int> oi = convert(text))
|
||||
int i = *oi;
|
||||
|
||||
We extract the contained value with `operator*` (and with `operator->` where it makes sense). An attempt to extract the contained value of an uninitialized optional object is an ['undefined behaviour] (UB). This implementation guards the call with `BOOST_ASSERT`. Therefore you should be sure that the contained value is there before extracting. For instance, the following code is reasonably UB-safe:
|
||||
|
||||
int i = *convert("100");
|
||||
|
||||
This is because we know that string value `"100"` converts to a valid value of `int`. If you do not like this potential UB, you can use an alternative way of extracting the contained value:
|
||||
|
||||
try {
|
||||
int j = convert(text).value();
|
||||
}
|
||||
catch (const boost::bad_optional_access&) {
|
||||
// deal with it
|
||||
}
|
||||
|
||||
This version throws an exception upon an attempt to access a nonexistent contained value. If your way of dealing with the missing value is to use some default, like `0`, there exists a yet another alternative:
|
||||
|
||||
int k = convert(text).value_or(0);
|
||||
|
||||
This uses the `atoi`-like approach to conversions: if `text` does not represent an integral number just return `0`. Finally, you can provide a callback to be called when trying to access the contained value fails:
|
||||
|
||||
int fallback_to_default()
|
||||
{
|
||||
cerr << "could not convert; using -1 instead" << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int l = convert(text).value_or_eval(fallback_to_default);
|
||||
|
||||
This will call the provided callback and return whatever the callback returns. The callback can have side effects: they will only be observed when the optional object does not contain a value.
|
||||
|
||||
Now, let's consider how function `convert` can be implemented.
|
||||
|
||||
boost::optional<int> convert(const std::string& text)
|
||||
{
|
||||
std::stringstream s(text);
|
||||
int i;
|
||||
if ((s >> i) && s.get() == std::char_traits<char>::eof())
|
||||
return i;
|
||||
else
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
Observe the two return statements. `return i` uses the converting constructor that can create `optional<T>` from `T`. Thus constructed optional object is initialized and its value is a copy of `i`. The other return statement uses another converting constructor from a special tag `boost::none`. It is used to indicate that we want to create an uninitialized optional object.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Optional automatic variables]
|
||||
|
||||
We could write function `convert` in a slightly different manner, so that it has a single `return`-statement:
|
||||
|
||||
boost::optional<int> convert(const std::string& text)
|
||||
{
|
||||
boost::optional<int> ans;
|
||||
std::stringstream s(text);
|
||||
int i;
|
||||
if ((s >> i) && s.get() == std::char_traits<char>::eof())
|
||||
ans = i;
|
||||
|
||||
return ans;
|
||||
}
|
||||
|
||||
The default constructor of `optional` creates an uninitialized optional object. Unlike with `int`s you cannot have an `optional<int>` in an indeterminate state. Its state is always well defined. Instruction `ans = i` initializes the optional object. It uses the 'mixed' assignment from `int`. In general, for `optional<T>`, when an assignment from `T` is invoked, it can do two things. If the optional object is not initialized (our case here), it initializes the contained value using `T`'s copy constructor. If the optional object is already initialized, it assigns the new value to it using `T`'s copy assignment.
|
||||
[endsect]
|
||||
|
||||
[section Optional data members]
|
||||
|
||||
Suppose we want to implement a ['lazy load] optimization. This is because we do not want to perform an expensive initialization of our `Resource` until (if at all) it is really used. We can do it this way:
|
||||
|
||||
class Widget
|
||||
{
|
||||
mutable boost::optional<const Resource> resource_;
|
||||
|
||||
public:
|
||||
Widget() {}
|
||||
|
||||
const Resource& getResource() const // not thread-safe
|
||||
{
|
||||
if (resource_ == boost::none)
|
||||
resource_.emplace("resource", "arguments");
|
||||
|
||||
return *resource_;
|
||||
}
|
||||
};
|
||||
|
||||
`optional`'s default constructor creates an uninitialized optional. No call to `Resource`'s default constructor is attempted. `Resource` doesn't have to be __STD_DEFAULT_CONSTRUCTIBLE__. In function `getResource` we first check if `resource_` is initialized. This time we do not use the contextual conversion to `bool`, but a comparison with `boost::none`. These two ways are equivalent. Function `emplace` initializes the optional in-place by perfect-forwarding the arguments to the constructor of `Resource`. No copy- or move-construction is involved here. `Resource` doesn't even have to be `MoveConstructible`.
|
||||
|
||||
[note Function `emplace` is only available on compilers that support rvalue references and variadic templates. If your compiler does not support these features and you still need to avoid any move-constructions, use [link boost_optional.tutorial.in_place_factories In-Place Factories].]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Bypassing unnecessary default construction]
|
||||
|
||||
Suppose we have class `Date`, which does not have a default constructor: there is no good candidate for a default date. We have a function that returns two dates in form of a `boost::tuple`:
|
||||
|
||||
boost::tuple<Date, Date> getPeriod();
|
||||
|
||||
In other place we want to use the result of `getPeriod`, but want the two dates to be named: `begin` and `end`. We want to implement something like 'multiple return values':
|
||||
|
||||
Date begin, end; // Error: no default ctor!
|
||||
boost::tie(begin, end) = getPeriod();
|
||||
|
||||
The second line works already, this is the capability of __BOOST_TUPLE__ library, but the first line won't work. We could set some invented initial dates, but it is confusing and may be an unacceptable cost, given that these values will be overwritten in the next line anyway. This is where `optional` can help:
|
||||
|
||||
boost::optional<Date> begin, end;
|
||||
boost::tie(begin, end) = getPeriod();
|
||||
|
||||
It works because inside `boost::tie` a move-assignment from `T` is invoked on `optional<T>`, which internally calls a move-constructor of `T`.
|
||||
[endsect]
|
||||
|
||||
[section Storage in containers]
|
||||
|
||||
Suppose you want to ask users to choose some number (an `int`). One of the valid responses is to choose nothing, which is represented by an uninitialized `optional<int>`. You want to make a histogram showing how many times each choice was made. You can use an `std::map`:
|
||||
|
||||
std::map<boost::optional<int>, int> choices;
|
||||
|
||||
for (int i = 0; i < LIMIT; ++i) {
|
||||
boost::optional<int> choice = readChoice();
|
||||
++choices[choice];
|
||||
}
|
||||
|
||||
This works because `optional<T>` is __STD_LESS_THAN_COMPARABLE__ whenever `T` is __STD_LESS_THAN_COMPARABLE__.
|
||||
In this case the state of being uninitialized is treated as a yet another value of `T`,
|
||||
which is compared less than any value of `T`.
|
||||
`optional<T>` can also be stored as a key in `std::unordered_map` and `std::unordered_set`
|
||||
as it provides specializations for `std::hash`.
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
80
doc/10_motivation.qbk
Normal file
80
doc/10_motivation.qbk
Normal file
@ -0,0 +1,80 @@
|
||||
[/
|
||||
Boost.Optional
|
||||
|
||||
Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
|
||||
Copyright (c) 2014 Andrzej Krzemienski
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
[section Motivation]
|
||||
|
||||
Consider these functions which should return a value but which might not have
|
||||
a value to return:
|
||||
|
||||
* (A) `double sqrt(double n );`
|
||||
* (B) `char get_async_input();`
|
||||
* (C) `point polygon::get_any_point_effectively_inside();`
|
||||
|
||||
There are different approaches to the issue of not having a value to return.
|
||||
|
||||
A typical approach is to consider the existence of a valid return value as a
|
||||
postcondition, so that if the function cannot compute the value to return, it
|
||||
has either undefined behavior (and can use assert in a debug build) or uses a
|
||||
runtime check and throws an exception if the postcondition is violated. This
|
||||
is a reasonable choice for example, for function (A), because the lack of a
|
||||
proper return value is directly related to an invalid parameter (out of domain
|
||||
argument), so it is appropriate to require the callee to supply only parameters
|
||||
in a valid domain for execution to continue normally.
|
||||
|
||||
However, function (B), because of its asynchronous nature, does not fail just
|
||||
because it can't find a value to return; so it is incorrect to consider such
|
||||
a situation an error and assert or throw an exception. This function must
|
||||
return, and somehow, must tell the callee that it is not returning a meaningful
|
||||
value.
|
||||
|
||||
A similar situation occurs with function (C): it is conceptually an error to
|
||||
ask a ['null-area] polygon to return a point inside itself, but in many
|
||||
applications, it is just impractical for performance reasons to treat this as
|
||||
an error (because detecting that the polygon has no area might be too expensive
|
||||
to be required to be tested previously), and either an arbitrary point
|
||||
(typically at infinity) is returned, or some efficient way to tell the callee
|
||||
that there is no such point is used.
|
||||
|
||||
There are various mechanisms to let functions communicate that the returned
|
||||
value is not valid. One such mechanism, which is quite common since it has
|
||||
zero or negligible overhead, is to use a special value which is reserved to
|
||||
communicate this. Classical examples of such special values are `EOF`,
|
||||
`string::npos`, points at infinity, etc...
|
||||
|
||||
When those values exist, i.e. the return type can hold all meaningful values
|
||||
['plus] the ['signal] value, this mechanism is quite appropriate and well known.
|
||||
Unfortunately, there are cases when such values do not exist. In these cases,
|
||||
the usual alternative is either to use a wider type, such as `int` in place of
|
||||
`char`; or a compound type, such as `std::pair<point,bool>`.
|
||||
|
||||
Returning a `std::pair<T,bool>`, thus attaching a boolean flag to the result
|
||||
which indicates if the result is meaningful, has the advantage that can be
|
||||
turned into a consistent idiom since the first element of the pair can be
|
||||
whatever the function would conceptually return. For example, the last two
|
||||
functions could have the following interface:
|
||||
|
||||
std::pair<char,bool> get_async_input();
|
||||
std::pair<point,bool> polygon::get_any_point_effectively_inside();
|
||||
|
||||
These functions use a consistent interface for dealing with possibly nonexistent
|
||||
results:
|
||||
|
||||
std::pair<point,bool> p = poly.get_any_point_effectively_inside();
|
||||
if ( p.second )
|
||||
flood_fill(p.first);
|
||||
|
||||
However, not only is this quite a burden syntactically, it is also error prone
|
||||
since the user can easily use the function result (first element of the pair)
|
||||
without ever checking if it has a valid value.
|
||||
|
||||
Clearly, we need a better idiom.
|
||||
|
||||
[endsect]
|
251
doc/11_development.qbk
Normal file
251
doc/11_development.qbk
Normal file
@ -0,0 +1,251 @@
|
||||
[/
|
||||
Boost.Optional
|
||||
|
||||
Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
[section Design Overview]
|
||||
|
||||
[section The models]
|
||||
|
||||
In C++, we can ['declare] an object (a variable) of type `T`, and we can give this
|
||||
variable an ['initial value] (through an ['initializer]. (cf. 8.5)).
|
||||
When a declaration includes a non-empty initializer (an initial value is given),
|
||||
it is said that the object has been initialized.
|
||||
If the declaration uses an empty initializer (no initial value is given), and
|
||||
neither default nor value initialization applies, it is said that the object is
|
||||
[*uninitialized]. Its actual value exist but has an ['indeterminate initial value]
|
||||
(cf. 8.5/11).
|
||||
`optional<T>` intends to formalize the notion of initialization (or lack of it)
|
||||
allowing a program to test whether an object has been initialized and stating
|
||||
that access to the value of an uninitialized object is undefined behavior. That
|
||||
is, when a variable is declared as `optional<T>` and no initial value is given,
|
||||
the variable is ['formally] uninitialized. A formally uninitialized optional object
|
||||
has conceptually no value at all and this situation can be tested at runtime. It
|
||||
is formally ['undefined behavior] to try to access the value of an uninitialized
|
||||
optional. An uninitialized optional can be assigned a value, in which case its initialization state changes to initialized. Furthermore, given the formal
|
||||
treatment of initialization states in optional objects, it is even possible to
|
||||
reset an optional to ['uninitialized].
|
||||
|
||||
In C++ there is no formal notion of uninitialized objects, which means that
|
||||
objects always have an initial value even if indeterminate.
|
||||
As discussed on the previous section, this has a drawback because you need
|
||||
additional information to tell if an object has been effectively initialized.
|
||||
One of the typical ways in which this has been historically dealt with is via
|
||||
a special value: `EOF`, `npos`, -1, etc... This is equivalent to adding the
|
||||
special value to the set of possible values of a given type. This super set of
|
||||
`T` plus some ['nil_t]—where `nil_t` is some stateless POD—can be modeled in modern
|
||||
languages as a [*discriminated union] of T and nil_t. Discriminated unions are
|
||||
often called ['variants]. A variant has a ['current type], which in our case is either
|
||||
`T` or `nil_t`.
|
||||
Using the __BOOST_VARIANT__ library, this model can be implemented in terms of `boost::variant<T,nil_t>`.
|
||||
There is precedent for a discriminated union as a model for an optional value:
|
||||
the __HASKELL__ [*Maybe] built-in type constructor. Thus, a discriminated union
|
||||
`T+nil_t` serves as a conceptual foundation.
|
||||
|
||||
A `variant<T,nil_t>` follows naturally from the traditional idiom of extending
|
||||
the range of possible values adding an additional sentinel value with the
|
||||
special meaning of ['Nothing]. However, this additional ['Nothing] value is largely
|
||||
irrelevant for our purpose since our goal is to formalize the notion of
|
||||
uninitialized objects and, while a special extended value can be used to convey
|
||||
that meaning, it is not strictly necessary in order to do so.
|
||||
|
||||
The observation made in the last paragraph about the irrelevant nature of the
|
||||
additional `nil_t` with respect to [_purpose] of `optional<T>` suggests an
|
||||
alternative model: a ['container] that either has a value of `T` or nothing.
|
||||
|
||||
As of this writing I don't know of any precedent for a variable-size
|
||||
fixed-capacity (of 1) stack-based container model for optional values, yet I
|
||||
believe this is the consequence of the lack of practical implementations of
|
||||
such a container rather than an inherent shortcoming of the container model.
|
||||
|
||||
In any event, both the discriminated-union or the single-element container
|
||||
models serve as a conceptual ground for a class representing optional—i.e.
|
||||
possibly uninitialized—objects.
|
||||
For instance, these models show the ['exact] semantics required for a wrapper
|
||||
of optional values:
|
||||
|
||||
Discriminated-union:
|
||||
|
||||
* [*deep-copy] semantics: copies of the variant implies copies of the value.
|
||||
* [*deep-relational] semantics: comparisons between variants matches both
|
||||
current types and values
|
||||
* If the variant's current type is `T`, it is modeling an ['initialized] optional.
|
||||
* If the variant's current type is not `T`, it is modeling an ['uninitialized]
|
||||
optional.
|
||||
* Testing if the variant's current type is `T` models testing if the optional
|
||||
is initialized
|
||||
* Trying to extract a `T` from a variant when its current type is not `T`, models
|
||||
the undefined behavior of trying to access the value of an uninitialized optional
|
||||
|
||||
Single-element container:
|
||||
|
||||
* [*deep-copy] semantics: copies of the container implies copies of the value.
|
||||
* [*deep-relational] semantics: comparisons between containers compare container
|
||||
size and if match, contained value
|
||||
* If the container is not empty (contains an object of type `T`), it is modeling
|
||||
an ['initialized] optional.
|
||||
* If the container is empty, it is modeling an ['uninitialized] optional.
|
||||
* Testing if the container is empty models testing if the optional is
|
||||
initialized
|
||||
* Trying to extract a `T` from an empty container models the undefined behavior
|
||||
of trying to access the value of an uninitialized optional
|
||||
|
||||
[endsect]
|
||||
|
||||
[section The semantics]
|
||||
|
||||
Objects of type `optional<T>` are intended to be used in places where objects of
|
||||
type `T` would but which might be uninitialized. Hence, `optional<T>`'s purpose is
|
||||
to formalize the additional possibly uninitialized state.
|
||||
From the perspective of this role, `optional<T>` can have the same operational
|
||||
semantics of `T` plus the additional semantics corresponding to this special
|
||||
state.
|
||||
As such, `optional<T>` could be thought of as a ['supertype] of `T`. Of course, we
|
||||
can't do that in C++, so we need to compose the desired semantics using a
|
||||
different mechanism.
|
||||
Doing it the other way around, that is, making `optional<T>` a ['subtype] of `T`
|
||||
is not only conceptually wrong but also impractical: it is not allowed to
|
||||
derive from a non-class type, such as a built-in type.
|
||||
|
||||
We can draw from the purpose of `optional<T>` the required basic semantics:
|
||||
|
||||
* [*Default Construction:] To introduce a formally uninitialized wrapped
|
||||
object.
|
||||
* [*Direct Value Construction via copy:] To introduce a formally initialized
|
||||
wrapped object whose value is obtained as a copy of some object.
|
||||
* [*Deep Copy Construction:] To obtain a new yet equivalent wrapped object.
|
||||
* [*Direct Value Assignment (upon initialized):] To assign a value to the
|
||||
wrapped object.
|
||||
* [*Direct Value Assignment (upon uninitialized):] To initialize the wrapped
|
||||
object with a value obtained as a copy of some object.
|
||||
* [*Assignment (upon initialized):] To assign to the wrapped object the value
|
||||
of another wrapped object.
|
||||
* [*Assignment (upon uninitialized):] To initialize the wrapped object with
|
||||
value of another wrapped object.
|
||||
* [*Deep Relational Operations (when supported by the type T):] To compare
|
||||
wrapped object values taking into account the presence of uninitialized states.
|
||||
* [*Value access:] To unwrap the wrapped object.
|
||||
* [*Initialization state query:] To determine if the object is formally
|
||||
initialized or not.
|
||||
* [*Swap:] To exchange wrapped objects. (with whatever exception safety
|
||||
guarantees are provided by `T`'s swap).
|
||||
* [*De-initialization:] To release the wrapped object (if any) and leave the
|
||||
wrapper in the uninitialized state.
|
||||
|
||||
Additional operations are useful, such as converting constructors and
|
||||
converting assignments, in-place construction and assignment, and safe
|
||||
value access via a pointer to the wrapped object or null.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section The Interface]
|
||||
|
||||
Since the purpose of optional is to allow us to use objects with a formal
|
||||
uninitialized additional state, the interface could try to follow the
|
||||
interface of the underlying `T` type as much as possible. In order to choose
|
||||
the proper degree of adoption of the native `T` interface, the following must
|
||||
be noted: Even if all the operations supported by an instance of type `T` are
|
||||
defined for the entire range of values for such a type, an `optional<T>`
|
||||
extends such a set of values with a new value for which most
|
||||
(otherwise valid) operations are not defined in terms of `T`.
|
||||
|
||||
Furthermore, since `optional<T>` itself is merely a `T` wrapper (modeling a `T`
|
||||
supertype), any attempt to define such operations upon uninitialized optionals
|
||||
will be totally artificial w.r.t. `T`.
|
||||
|
||||
This library chooses an interface which follows from `T`'s interface only for
|
||||
those operations which are well defined (w.r.t the type `T`) even if any of the
|
||||
operands are uninitialized. These operations include: construction,
|
||||
copy-construction, assignment, swap and relational operations.
|
||||
|
||||
For the value access operations, which are undefined (w.r.t the type `T`) when
|
||||
the operand is uninitialized, a different interface is chosen (which will be
|
||||
explained next).
|
||||
|
||||
Also, the presence of the possibly uninitialized state requires additional
|
||||
operations not provided by `T` itself which are supported by a special interface.
|
||||
|
||||
[heading Lexically-hinted Value Access in the presence of possibly
|
||||
uninitialized optional objects: The operators * and ->]
|
||||
|
||||
A relevant feature of a pointer is that it can have a [*null pointer value].
|
||||
This is a ['special] value which is used to indicate that the pointer is not
|
||||
referring to any object at all. In other words, null pointer values convey
|
||||
the notion of nonexistent objects.
|
||||
|
||||
This meaning of the null pointer value allowed pointers to became a ['de
|
||||
facto] standard for handling optional objects because all you have to do
|
||||
to refer to a value which you don't really have is to use a null pointer
|
||||
value of the appropriate type. Pointers have been used for decades—from
|
||||
the days of C APIs to modern C++ libraries—to ['refer] to optional (that is,
|
||||
possibly nonexistent) objects; particularly as optional arguments to a
|
||||
function, but also quite often as optional data members.
|
||||
|
||||
The possible presence of a null pointer value makes the operations that
|
||||
access the pointee's value possibly undefined, therefore, expressions which
|
||||
use dereference and access operators, such as: `( *p = 2 )` and `( p->foo() )`,
|
||||
implicitly convey the notion of optionality, and this information is tied to
|
||||
the ['syntax] of the expressions. That is, the presence of operators `*` and `->`
|
||||
tell by themselves —without any additional context— that the expression will
|
||||
be undefined unless the implied pointee actually exist.
|
||||
|
||||
Such a ['de facto] idiom for referring to optional objects can be formalized
|
||||
in the form of a concept: the __OPTIONAL_POINTEE__ concept.
|
||||
This concept captures the syntactic usage of operators `*`, `->` and
|
||||
contextual conversion to `bool` to convey the notion of optionality.
|
||||
|
||||
However, pointers are good to [_refer] to optional objects, but not particularly
|
||||
good to handle the optional objects in all other respects, such as initializing
|
||||
or moving/copying them. The problem resides in the shallow-copy of pointer
|
||||
semantics: if you need to effectively move or copy the object, pointers alone
|
||||
are not enough. The problem is that copies of pointers do not imply copies of
|
||||
pointees. For example, as was discussed in the motivation, pointers alone
|
||||
cannot be used to return optional objects from a function because the object
|
||||
must move outside from the function and into the caller's context.
|
||||
|
||||
A solution to the shallow-copy problem that is often used is to resort to
|
||||
dynamic allocation and use a smart pointer to automatically handle the details
|
||||
of this. For example, if a function is to optionally return an object `X`, it can
|
||||
use `shared_ptr<X>` as the return value. However, this requires dynamic allocation
|
||||
of `X`. If `X` is a built-in or small POD, this technique is very poor in terms of
|
||||
required resources. Optional objects are essentially values so it is very
|
||||
convenient to be able to use automatic storage and deep-copy semantics to
|
||||
manipulate optional values just as we do with ordinary values. Pointers do
|
||||
not have this semantics, so are inappropriate for the initialization and
|
||||
transport of optional values, yet are quite convenient for handling the access
|
||||
to the possible undefined value because of the idiomatic aid present in the
|
||||
__OPTIONAL_POINTEE__ concept incarnated by pointers.
|
||||
|
||||
|
||||
[heading Optional<T> as a model of OptionalPointee]
|
||||
|
||||
For value access operations `optional<>` uses operators `*` and `->` to
|
||||
lexically warn about the possibly uninitialized state appealing to the
|
||||
familiar pointer semantics w.r.t. to null pointers.
|
||||
|
||||
[caution
|
||||
However, it is particularly important to note that `optional<>` objects
|
||||
are not pointers. [_`optional<>` is not, and does not model, a pointer].
|
||||
]
|
||||
|
||||
For instance, `optional<>` does not have shallow-copy so does not alias:
|
||||
two different optionals never refer to the ['same] value unless `T` itself is
|
||||
a reference (but may have ['equivalent] values).
|
||||
The difference between an `optional<T>` and a pointer must be kept in mind,
|
||||
particularly because the semantics of relational operators are different:
|
||||
since `optional<T>` is a value-wrapper, relational operators are deep: they
|
||||
compare optional values; but relational operators for pointers are shallow:
|
||||
they do not compare pointee values.
|
||||
As a result, you might be able to replace `optional<T>` by `T*` on some
|
||||
situations but not always. Specifically, on generic code written for both,
|
||||
you cannot use relational operators directly, and must use the template
|
||||
functions __FUNCTION_EQUAL_POINTEES__ and __FUNCTION_LESS_POINTEES__ instead.
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
37
doc/12_when_to_use.qbk
Normal file
37
doc/12_when_to_use.qbk
Normal file
@ -0,0 +1,37 @@
|
||||
|
||||
[section When to use Optional]
|
||||
|
||||
It is recommended to use `optional<T>` in situations where there is exactly one, clear (to all parties) reason for having no value of type `T`, and where the lack of value is as natural as having any regular value of `T`. One example of such situation is asking the user in some GUI form to optionally specify some limit on an `int` value, but the user is allowed to say 'I want the number not to be constrained by the maximum'.
|
||||
For another example, consider a config parameter specifying how many threads the application should launch. Leaving this parameter unspecified means that the application should decide itself. For yet another example, consider a function returning the index of the smallest element in a `vector`. We need to be prepared for the situation, where the `vector` is empty. Therefore a natural signature for such function would be:
|
||||
|
||||
template <typename T>
|
||||
optional<size_t> find_smallest_elem(const std::vector<T>& vec);
|
||||
|
||||
Here, having received an empty `vec` and having no `size_t` to return is not a ['failure] but a ['normal], albeit irregular, situation.
|
||||
|
||||
Another typical situation is to indicate that we do not have a value yet, but we expect to have it later. This notion can be used in implementing solutions like lazy initialization or a two-phase initialization.
|
||||
|
||||
`optional` can be used to take a non-__STD_DEFAULT_CONSTRUCTIBLE__ type `T` and create a sibling type with a default constructor. This is a way to add a ['null-state] to any type that doesn't have it already.
|
||||
|
||||
Sometimes type `T` already provides a built-in null-state, but it may still be useful to wrap it into `optional`. Consider `std::string`. When you read a piece of text from a GUI form or a DB table, it is hardly ever that the empty string indicates anything else but a missing text. And some data bases do not even distinguish between a null string entry and a non-null string of length 0. Still, it may be practical to use `optional<string>` to indicate in the returned type that we want to treat the empty string in a special dedicated program path:
|
||||
|
||||
if(boost::optional<std::string> name = ask_user_name()) {
|
||||
assert(*name != "");
|
||||
logon_as(*name);
|
||||
}
|
||||
else {
|
||||
skip_logon();
|
||||
}
|
||||
|
||||
In the example above, the assertion indicates that if we choose to use this technique, we must translate the empty string state to an optional object with no contained value (inside function `ask_user_name`).
|
||||
|
||||
[heading Not recommended usages]
|
||||
|
||||
It is not recommended to use `optional` to indicate that we were not able to compute a value because of a ['failure]. It is difficult to define what a failure is, but it usually has one common characteristic: an associated information on the cause of the failure. This can be the type and member data of an exception object, or an error code. It is a bad design to signal a failure and not inform about the cause. If you do not want to use exceptions, and do not like the fact that by returning error codes you cannot return the computed value, you can use [@https://github.com/ptal/Boost.Expected Expected] library. It is sort of __BOOST_VARIANT__ that contains either a computed value or a reason why the computation failed.
|
||||
|
||||
Sometimes the distinction into what is a failure and what is a valid but irregular result is blurry and depends on a particular usage and personal preference. Consider a function that converts a `string` to an `int`. Is it a failure that you cannot convert? It might in some cases, but in other you may call it exactly for the purpose of figuring out if a given `string` is convertible, and you are not even interested in the resulting value. Sometimes when a conversion fails you may not consider it a failure, but you need to know why it cannot be converted; for instance at which character it is determined that the conversion is impossible. In this case returning `optional<T>` will not suffice. Finally, there is a use case where an input string that does not represent an `int` is not a failure condition, but during the conversion we use resources whose acquisition may fail. In that case the natural representation is to both return `optional<int>` and signal failure:
|
||||
|
||||
optional<int> convert1(const string& str); // throws
|
||||
expected<ErrorT, optional<int>> convert2(const string& str); // return either optional or error
|
||||
|
||||
[endsect]
|
37
doc/13_relational_operators.qbk
Normal file
37
doc/13_relational_operators.qbk
Normal file
@ -0,0 +1,37 @@
|
||||
|
||||
[section Relational operators]
|
||||
|
||||
Type `optional<T>` is __STD_EQUALITY_COMPARABLE__ whenever `T` is __STD_EQUALITY_COMPARABLE__. Two optional objects containing a value compare in the same way as their contained values. The uninitialized state of `optional<T>` is treated as a distinct value, equal to itself, and unequal to any value of type `T`:
|
||||
|
||||
boost::optional<int> oN = boost::none;
|
||||
boost::optional<int> o0 = 0;
|
||||
boost::optional<int> o1 = 1;
|
||||
|
||||
assert(oN != o0);
|
||||
assert(o1 != oN);
|
||||
assert(o0 != o1);
|
||||
assert(oN == oN);
|
||||
assert(o0 == o0);
|
||||
|
||||
The converting constructor from `T` as well as from `boost::none` implies the existence and semantics of the mixed comparison between `T` and `optional<T>` as well as between `none_t` and `optional<T>`:
|
||||
|
||||
assert(oN != 0);
|
||||
assert(o1 != boost::none);
|
||||
assert(o0 != 1);
|
||||
assert(oN == boost::none);
|
||||
assert(o0 == 0);
|
||||
|
||||
This mixed comparison has a practical interpretation, which is occasionally useful:
|
||||
|
||||
boost::optional<int> choice = ask_user();
|
||||
if (choice == 2)
|
||||
start_procedure_2();
|
||||
|
||||
In the above example, the meaning of the comparison is 'user chose number 2'. If user chose nothing, he didn't choose number 2.
|
||||
|
||||
In case where `optional<T>` is compared to `none`, it is not required that `T` be __STD_EQUALITY_COMPARABLE__.
|
||||
|
||||
In a similar manner, type `optional<T>` is __STD_LESS_THAN_COMPARABLE__ whenever `T` is __STD_LESS_THAN_COMPARABLE__. The optional object containing no value is compared less than any value of `T`. To illustrate this, if the default ordering of `size_t` is {`0`, `1`, `2`, ...}, the default ordering of `optional<size_t>` is {`boost::none`, `0`, `1`, `2`, ...}. This order does not have a practical interpretation. The goal is to have any semantically correct default ordering in order for `optional<T>` to be usable in ordered associative containers (wherever `T` is usable).
|
||||
|
||||
Mixed relational operators are the only case where the contained value of an optional object can be inspected without the usage of value accessing function (`operator*`, `value`, `value_or`).
|
||||
[endsect]
|
45
doc/14_monadic_interface.qbk
Normal file
45
doc/14_monadic_interface.qbk
Normal file
@ -0,0 +1,45 @@
|
||||
[section Monadic interface]
|
||||
|
||||
The monadic interface of `optional` allows the application of functions
|
||||
to optional values without resorting to the usage of explicit `if`-statements.
|
||||
|
||||
Function `map` takes a function mapping type `T` onto type `U` and maps an `optional<T>`
|
||||
onto an `optional<U>` using the provided function.
|
||||
|
||||
int length(const string& s){ return s.size(); };
|
||||
|
||||
optional<string> null{}, thin{""}, word{"word"};
|
||||
assert (null.map(length) == none);
|
||||
assert (thin.map(length) == 0);
|
||||
assert (word.map(length) == 4);
|
||||
|
||||
Function `flat_map` is similar, but it requires the function to return an
|
||||
`optional<V>` for some type `V`. This `optional<V>` becomes the return type of
|
||||
`flat_map`.
|
||||
|
||||
optional<char> first_char(const string& s) {
|
||||
if (s.empty()) return none;
|
||||
else return s[0];
|
||||
};
|
||||
|
||||
optional<string> null{}, thin{""}, word{"word"};
|
||||
assert (null.flat_map(first_char) == none);
|
||||
assert (thin.flat_map(first_char) == none);
|
||||
assert (word.flat_map(first_char) == 'w');
|
||||
|
||||
These functions can be combined in one expression reflecting a chain of computations:
|
||||
|
||||
auto get_contents(path p) -> optional<string>;
|
||||
auto trim(string) -> string;
|
||||
auto length(string) -> int;
|
||||
|
||||
auto trimmed_size_of(optional<path> p) -> int
|
||||
{
|
||||
return p.flat_map(get_contents)
|
||||
.map(trim)
|
||||
.map(length)
|
||||
.value_or(0);
|
||||
}
|
||||
|
||||
|
||||
[endsect]
|
37
doc/15_io.qbk
Normal file
37
doc/15_io.qbk
Normal file
@ -0,0 +1,37 @@
|
||||
|
||||
[section IO operators]
|
||||
|
||||
It is possible to use `optional<T>` with IO streams, provided that `T` can be used with streams. IOStream operators are defined in a separate header.
|
||||
|
||||
``
|
||||
#include <iostream>
|
||||
#include <boost/optional/optional_io.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
boost::optional<int> o1 = 1, oN = boost::none;
|
||||
std::cout << o1;
|
||||
std::cin >> oN;
|
||||
}
|
||||
``
|
||||
|
||||
The current implementation does not guarantee any particular output. What it guarantees is that if streaming out and then back in `T` gives the same value, then streaming out and then back in `optional<T>` will also give back the same result:
|
||||
|
||||
``
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <boost/optional/optional_io.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
boost::optional<int> o1 = 1, oN = boost::none;
|
||||
boost::optional<int> x1, x2;
|
||||
std::stringstream s;
|
||||
s << o1 << oN;
|
||||
s >> x1 >> x2;
|
||||
assert (o1 == x1);
|
||||
assert (oN == x2);
|
||||
}
|
||||
``
|
||||
|
||||
[endsect]
|
123
doc/16_optional_references.qbk
Normal file
123
doc/16_optional_references.qbk
Normal file
@ -0,0 +1,123 @@
|
||||
|
||||
[section Optional references]
|
||||
|
||||
[section Overview]
|
||||
|
||||
This library allows the template parameter `T` to be of reference type:
|
||||
`T&`, and to some extent, `T const&`.
|
||||
|
||||
However, since references are not real objects some restrictions apply and
|
||||
some operations are not available in this case:
|
||||
|
||||
* Converting constructors
|
||||
* Converting assignment
|
||||
* InPlace construction
|
||||
* InPlace assignment
|
||||
* Value-access via pointer
|
||||
|
||||
Also, even though `optional<T&>` treats it wrapped pseudo-object much as
|
||||
a real value, a true real reference is stored so aliasing will occur:
|
||||
|
||||
* Copies of `optional<T&>` will copy the references but all these references
|
||||
will nonetheless refer to the same object.
|
||||
* Value-access will actually provide access to the referenced object
|
||||
rather than the reference itself.
|
||||
|
||||
[caution On compilers that do not conform to Standard C++ rules of reference binding, some operations on optional references are disabled in order to prevent subtle bugs. For more details see [link boost_optional.dependencies_and_portability.optional_reference_binding Dependencies and Portability section].]
|
||||
|
||||
[heading Rvalue references]
|
||||
|
||||
Rvalue references and lvalue references to const have the ability in C++ to extend the life time of a temporary they bind to. Optional references do not have this capability, therefore to avoid surprising effects it is not possible to initialize an optional references from a temporary. Optional rvalue references are disabled altogether. Also, the initialization and assignment of an optional reference to const from rvalue reference is disabled.
|
||||
|
||||
const int& i = 1; // legal
|
||||
optional<const int&> oi = 1; // illegal
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Rebinding semantics for assignment of optional references]
|
||||
|
||||
If you assign to an ['uninitialized ] `optional<T&>` the effect is to bind (for
|
||||
the first time) to the object. Clearly, there is no other choice.
|
||||
|
||||
int x = 1 ;
|
||||
int& rx = x ;
|
||||
optional<int&> ora ;
|
||||
optional<int&> orb(x) ;
|
||||
ora = orb ; // now 'ora' is bound to 'x' through 'rx'
|
||||
*ora = 2 ; // Changes value of 'x' through 'ora'
|
||||
assert(x==2);
|
||||
|
||||
If you assign to a bare C++ reference, the assignment is forwarded to the
|
||||
referenced object; its value changes but the reference is never rebound.
|
||||
|
||||
int a = 1 ;
|
||||
int& ra = a ;
|
||||
int b = 2 ;
|
||||
int& rb = b ;
|
||||
ra = rb ; // Changes the value of 'a' to 'b'
|
||||
assert(a==b);
|
||||
b = 3 ;
|
||||
assert(ra!=b); // 'ra' is not rebound to 'b'
|
||||
|
||||
Now, if you assign to an ['initialized ] `optional<T&>`, the effect is to
|
||||
[*rebind] to the new object instead of assigning the referee. This is unlike
|
||||
bare C++ references.
|
||||
|
||||
int a = 1 ;
|
||||
int b = 2 ;
|
||||
int& ra = a ;
|
||||
int& rb = b ;
|
||||
optional<int&> ora(ra) ;
|
||||
optional<int&> orb(rb) ;
|
||||
ora = orb ; // 'ora' is rebound to 'b'
|
||||
*ora = 3 ; // Changes value of 'b' (not 'a')
|
||||
assert(a==1);
|
||||
assert(b==3);
|
||||
|
||||
[heading Rationale]
|
||||
|
||||
Rebinding semantics for the assignment of ['initialized ] `optional` references has
|
||||
been chosen to provide [*consistency among initialization states] even at the
|
||||
expense of lack of consistency with the semantics of bare C++ references.
|
||||
It is true that `optional<U>` strives to behave as much as possible as `U`
|
||||
does whenever it is initialized; but in the case when `U` is `T&`, doing so would
|
||||
result in inconsistent behavior w.r.t to the lvalue initialization state.
|
||||
|
||||
Imagine `optional<T&>` forwarding assignment to the referenced object (thus
|
||||
changing the referenced object value but not rebinding), and consider the
|
||||
following code:
|
||||
|
||||
optional<int&> a = get();
|
||||
int x = 1 ;
|
||||
int& rx = x ;
|
||||
optional<int&> b(rx);
|
||||
a = b ;
|
||||
|
||||
What does the assignment do?
|
||||
|
||||
If `a` is ['uninitialized], the answer is clear: it binds to `x` (we now have
|
||||
another reference to `x`).
|
||||
But what if `a` is already ['initialized]? it would change the value of the
|
||||
referenced object (whatever that is); which is inconsistent with the other
|
||||
possible case.
|
||||
|
||||
If `optional<T&>` would assign just like `T&` does, you would never be able to
|
||||
use Optional's assignment without explicitly handling the previous
|
||||
initialization state unless your code is capable of functioning whether
|
||||
after the assignment, `a` aliases the same object as `b` or not.
|
||||
|
||||
That is, you would have to discriminate in order to be consistent.
|
||||
|
||||
If in your code rebinding to another object is not an option, then it is very
|
||||
likely that binding for the first time isn't either. In such case, assignment
|
||||
to an ['uninitialized ] `optional<T&>` shall be prohibited. It is quite possible
|
||||
that in such a scenario it is a precondition that the lvalue must be already
|
||||
initialized. If it isn't, then binding for the first time is OK
|
||||
while rebinding is not which is IMO very unlikely.
|
||||
In such a scenario, you can assign the value itself directly, as in:
|
||||
|
||||
assert(!!opt);
|
||||
*opt=value;
|
||||
|
||||
[endsect]
|
||||
[endsect]
|
139
doc/17_in_place_factories.qbk
Normal file
139
doc/17_in_place_factories.qbk
Normal file
@ -0,0 +1,139 @@
|
||||
|
||||
[section In-Place Factories]
|
||||
|
||||
One of the typical problems with wrappers and containers is that their
|
||||
interfaces usually provide an operation to initialize or assign the
|
||||
contained object as a copy of some other object. This not only requires the
|
||||
underlying type to be __COPY_CONSTRUCTIBLE__, but also requires the existence of
|
||||
a fully constructed object, often temporary, just to follow the copy from:
|
||||
|
||||
struct X
|
||||
{
|
||||
X ( int, std::string ) ;
|
||||
} ;
|
||||
|
||||
class W
|
||||
{
|
||||
X wrapped_ ;
|
||||
|
||||
public:
|
||||
|
||||
W ( X const& x ) : wrapped_(x) {}
|
||||
} ;
|
||||
|
||||
void foo()
|
||||
{
|
||||
// Temporary object created.
|
||||
W ( X(123,"hello") ) ;
|
||||
}
|
||||
|
||||
A solution to this problem is to support direct construction of the
|
||||
contained object right in the container's storage.
|
||||
In this scheme, the user only needs to supply the arguments to the
|
||||
constructor to use in the wrapped object construction.
|
||||
|
||||
class W
|
||||
{
|
||||
X wrapped_ ;
|
||||
|
||||
public:
|
||||
|
||||
W ( X const& x ) : wrapped_(x) {}
|
||||
W ( int a0, std::string a1) : wrapped_(a0,a1) {}
|
||||
} ;
|
||||
|
||||
void foo()
|
||||
{
|
||||
// Wrapped object constructed in-place
|
||||
// No temporary created.
|
||||
W (123,"hello") ;
|
||||
}
|
||||
|
||||
A limitation of this method is that it doesn't scale well to wrapped
|
||||
objects with multiple constructors nor to generic code were the constructor
|
||||
overloads are unknown.
|
||||
|
||||
The solution presented in this library is the family of [*InPlaceFactories]
|
||||
and [*TypedInPlaceFactories].
|
||||
These factories are a family of classes which encapsulate an increasing
|
||||
number of arbitrary constructor parameters and supply a method to construct
|
||||
an object of a given type using those parameters at an address specified by
|
||||
the user via placement new.
|
||||
|
||||
For example, one member of this family looks like:
|
||||
|
||||
template<class T,class A0, class A1>
|
||||
class TypedInPlaceFactory2
|
||||
{
|
||||
A0 m_a0 ; A1 m_a1 ;
|
||||
|
||||
public:
|
||||
|
||||
TypedInPlaceFactory2( A0 const& a0, A1 const& a1 ) : m_a0(a0), m_a1(a1) {}
|
||||
|
||||
void construct ( void* p ) { new (p) T(m_a0,m_a1) ; }
|
||||
} ;
|
||||
|
||||
A wrapper class aware of this can use it as:
|
||||
|
||||
class W
|
||||
{
|
||||
X wrapped_ ;
|
||||
|
||||
public:
|
||||
|
||||
W ( X const& x ) : wrapped_(x) {}
|
||||
W ( TypedInPlaceFactory2 const& fac ) { fac.construct(&wrapped_) ; }
|
||||
} ;
|
||||
|
||||
void foo()
|
||||
{
|
||||
// Wrapped object constructed in-place via a TypedInPlaceFactory.
|
||||
// No temporary created.
|
||||
W ( TypedInPlaceFactory2<X,int,std::string>(123,"hello")) ;
|
||||
}
|
||||
|
||||
The factories are divided in two groups:
|
||||
|
||||
* [_TypedInPlaceFactories]: those which take the target type as a primary
|
||||
template parameter.
|
||||
* [_InPlaceFactories]: those with a template `construct(void*)` member
|
||||
function taking the target type.
|
||||
|
||||
Within each group, all the family members differ only in the number of
|
||||
parameters allowed.
|
||||
|
||||
This library provides an overloaded set of helper template functions to
|
||||
construct these factories without requiring unnecessary template parameters:
|
||||
|
||||
template<class A0,...,class AN>
|
||||
InPlaceFactoryN <A0,...,AN> in_place ( A0 const& a0, ..., AN const& aN) ;
|
||||
|
||||
template<class T,class A0,...,class AN>
|
||||
TypedInPlaceFactoryN <T,A0,...,AN> in_place ( T const& a0, A0 const& a0, ..., AN const& aN) ;
|
||||
|
||||
In-place factories can be used generically by the wrapper and user as follows:
|
||||
|
||||
class W
|
||||
{
|
||||
X wrapped_ ;
|
||||
|
||||
public:
|
||||
|
||||
W ( X const& x ) : wrapped_(x) {}
|
||||
|
||||
template< class InPlaceFactory >
|
||||
W ( InPlaceFactory const& fac ) { fac.template <X>construct(&wrapped_) ; }
|
||||
|
||||
} ;
|
||||
|
||||
void foo()
|
||||
{
|
||||
// Wrapped object constructed in-place via a InPlaceFactory.
|
||||
// No temporary created.
|
||||
W ( in_place(123,"hello") ) ;
|
||||
}
|
||||
|
||||
The factories are implemented in the headers: __IN_PLACE_FACTORY_HPP__ and __TYPED_IN_PLACE_FACTORY_HPP__
|
||||
|
||||
[endsect]
|
111
doc/18_gotchas.qbk
Normal file
111
doc/18_gotchas.qbk
Normal file
@ -0,0 +1,111 @@
|
||||
[section Gotchas]
|
||||
|
||||
[section A note about optional<bool>]
|
||||
|
||||
`optional<bool>` should be used with special caution and consideration.
|
||||
|
||||
First, it is functionally similar to a tristate boolean (false, maybe, true)
|
||||
—such as __BOOST_TRIBOOL__— except that in a tristate boolean, the maybe state
|
||||
[_represents a valid value], unlike the corresponding state of an uninitialized
|
||||
`optional<bool>`.
|
||||
It should be carefully considered if an `optional<bool>` instead of a `tribool`
|
||||
is really needed.
|
||||
|
||||
Second, although `optional<>` provides a contextual conversion to `bool` in C++11,
|
||||
this falls back to an implicit conversion on older compilers. This conversion refers
|
||||
to the initialization state and not to the contained value. Using `optional<bool>`
|
||||
can lead to subtle errors due to the implicit `bool` conversion:
|
||||
|
||||
void foo ( bool v ) ;
|
||||
void bar()
|
||||
{
|
||||
optional<bool> v = try();
|
||||
|
||||
// The following intended to pass the value of 'v' to foo():
|
||||
foo(v);
|
||||
// But instead, the initialization state is passed
|
||||
// due to a typo: it should have been foo(*v).
|
||||
}
|
||||
|
||||
The only implicit conversion is to `bool`, and it is safe in the sense that
|
||||
typical integral promotions don't apply (i.e. if `foo()` takes an `int`
|
||||
instead, it won't compile).
|
||||
|
||||
Third, mixed comparisons with `bool` work differently than similar mixed comparisons between pointers and `bool`, so the results might surprise you:
|
||||
|
||||
optional<bool> oEmpty(none), oTrue(true), oFalse(false);
|
||||
|
||||
if (oEmpty == none); // renders true
|
||||
if (oEmpty == false); // renders false!
|
||||
if (oEmpty == true); // renders false!
|
||||
|
||||
if (oFalse == none); // renders false
|
||||
if (oFalse == false); // renders true!
|
||||
if (oFalse == true); // renders false
|
||||
|
||||
if (oTrue == none); // renders false
|
||||
if (oTrue == false); // renders false
|
||||
if (oTrue == true); // renders true
|
||||
|
||||
In other words, for `optional<>`, the following assertion does not hold:
|
||||
|
||||
assert((opt == false) == (!opt));
|
||||
[endsect]
|
||||
|
||||
[section Moved-from `optional`]
|
||||
|
||||
When an optional object that contains a value is moved from (is a source of move constructor or assignment) it still contains a value and its contained value is left in a moved-from state. This can be illustrated with the following example.
|
||||
|
||||
optional<std::unique_ptr<int>> opi {std::make_unique<int>(1)};
|
||||
optional<std::unique_ptr<int>> opj = std::move(opi);
|
||||
assert (opi);
|
||||
assert (*opi == nullptr);
|
||||
|
||||
Quite a lot of people expect that when an object that contains a value is moved from, its contained value should be destroyed. This is not so, for performance reasons. Current semantics allow the implementation of `boost::optional<T>` to be trivially copyable when `T` is trivial.
|
||||
[endsect]
|
||||
|
||||
[section Mixed relational comparisons]
|
||||
|
||||
Because `T` is convertible to `optional<T>` and because `optional<T>` is __STD_LESS_THAN_COMPARABLE__ when `T` is __STD_LESS_THAN_COMPARABLE__,
|
||||
you can sometimes get an unexpected runtime result where you would rather expect a compiler error:
|
||||
|
||||
optional<double> Flight_plan::weight(); // sometimes no weight can be returned
|
||||
|
||||
bool is_aircraft_too_heavy(Flight_plan const& p)
|
||||
{
|
||||
return p.weight() > p.aircraft().max_weight(); // compiles!
|
||||
} // returns false when the optional contains no value
|
||||
|
||||
[endsect]
|
||||
|
||||
[section False positive with -Wmaybe-uninitialized]
|
||||
|
||||
Sometimes on GCC compilers below version 5.1 you may get an -Wmaybe-uninitialized warning when compiling with option -02 on a perfectly valid `boost::optional` usage. For instance in this program:
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
boost::optional<int> getitem();
|
||||
|
||||
int main(int argc, const char *[])
|
||||
{
|
||||
boost::optional<int> a = getitem();
|
||||
boost::optional<int> b;
|
||||
|
||||
if (argc > 0)
|
||||
b = argc;
|
||||
|
||||
if (a != b)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
This is a bug in the compiler. As a workaround (provided in [@http://stackoverflow.com/questions/21755206/how-to-get-around-gcc-void-b-4-may-be-used-uninitialized-in-this-funct this Stack Overflow question]) use the following way of initializing an optional containing no value:
|
||||
|
||||
boost::optional<int> b = boost::make_optional(false, int());
|
||||
|
||||
This is obviously redundant, but makes the warning disappear.
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
57
doc/19_exception_safety.qbk
Normal file
57
doc/19_exception_safety.qbk
Normal file
@ -0,0 +1,57 @@
|
||||
|
||||
[section Exception Safety Guarantees]
|
||||
|
||||
This library assumes that `T`'s destructor does not throw exceptions. If it does, the behaviour of many operations on `optional<T>` is undefined.
|
||||
|
||||
The following mutating operations never throw exceptions:
|
||||
|
||||
* `optional<T>::operator= ( none_t ) noexcept`
|
||||
* `optional<T>::reset() noexcept`
|
||||
|
||||
In addition, the following constructors and the destructor never throw exceptions:
|
||||
|
||||
* `optional<T>::optional() noexcept`
|
||||
* `optional<T>::optional( none_t ) noexcept`
|
||||
|
||||
|
||||
Regarding the following assignment functions:
|
||||
|
||||
* `optional<T>::operator= ( optional<T> const& )`
|
||||
* `optional<T>::operator= ( T const& )`
|
||||
* `template<class U> optional<T>::operator= ( optional<U> const& )`
|
||||
* `template<class InPlaceFactory> optional<T>::operator= ( InPlaceFactory const& )`
|
||||
* `template<class TypedInPlaceFactory> optional<T>::operator= ( TypedInPlaceFactory const& ) `
|
||||
* `optional<T>::reset( T const& )`
|
||||
|
||||
They forward calls to the corresponding `T`'s constructors or assignments (depending on whether the optional object is initialized or not); so if both `T`'s constructor and the assignment provide strong exception safety guarantee, `optional<T>`'s assignment also provides strong exception safety guarantee; otherwise we only get the basic guarantee. Additionally, if both involved `T`'s constructor and the assignment never throw, `optional<T>`'s assignment also never throws.
|
||||
|
||||
Unless `T`'s constructor or assignment throws, assignments to `optional<T>` do not throw anything else on its own. A throw during assignment never changes the initialization state of any optional object involved:
|
||||
|
||||
|
||||
optional<T> opt1(val1);
|
||||
optional<T> opt2(val2);
|
||||
assert(opt1);
|
||||
assert(opt2);
|
||||
|
||||
try
|
||||
{
|
||||
opt1 = opt2; // throws
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
assert(opt1);
|
||||
assert(opt2);
|
||||
}
|
||||
|
||||
This also applies to move assignments/constructors. However, move operations are made no-throw more often.
|
||||
|
||||
Operation `emplace` provides basic exception safety guarantee. If it throws, the optional object becomes uninitialized regardless of its initial state, and its previous contained value (if any) is destroyed. It doesn't call any assignment or move/copy constructor on `T`.
|
||||
|
||||
[heading Swap]
|
||||
|
||||
Unless `swap` on optional is customized, its primary implementation forwards calls to `T`'s `swap` or move constructor (depending on the initialization state of the optional objects). Thus, if both `T`'s `swap` and move constructor never throw, `swap` on `optional<T>` never throws. similarly, if both `T`'s `swap` and move constructor offer strong guarantee, `swap` on `optional<T>` also offers a strong guarantee.
|
||||
|
||||
In case `swap` on optional is customized, the call to `T`'s move constructor are replaced with the calls to `T`'s default constructor followed by `swap`. (This is more useful on older compilers that do not support move semantics, when one wants to achieve stronger exception safety guarantees.) In this case the exception safety guarantees for `swap` are reliant on the guarantees of `T`'s `swap` and default constructor
|
||||
[endsect]
|
||||
|
||||
|
38
doc/1A_type_requirements.qbk
Normal file
38
doc/1A_type_requirements.qbk
Normal file
@ -0,0 +1,38 @@
|
||||
|
||||
[section Type requirements]
|
||||
|
||||
The very minimum requirement of `optional<T>` is that `T` is a complete type and that it has a publicly accessible destructor. `T` doesn't even need to be constructible. You can use a very minimum interface:
|
||||
|
||||
optional<T> o; // uninitialized
|
||||
assert(o == none); // check if initialized
|
||||
assert(!o); //
|
||||
o.value(); // always throws
|
||||
|
||||
But this is practically useless. In order for `optional<T>` to be able to do anything useful and offer all the spectrum of ways of accessing the contained value, `T` needs to have at least one accessible constructor. In that case you need to initialize the optional object with function `emplace()`, or if your compiler does not support it, resort to [link boost_optional.tutorial.in_place_factories In-Place Factories]:
|
||||
|
||||
optional<T> o;
|
||||
o.emplace("T", "ctor", "params");
|
||||
|
||||
If `T` is __MOVE_CONSTRUCTIBLE__, `optional<T>` is also __MOVE_CONSTRUCTIBLE__ and can be easily initialized from an rvalue of type `T` and be passed by value:
|
||||
|
||||
optional<T> o = make_T();
|
||||
optional<T> p = optional<T>();
|
||||
|
||||
If `T` is __COPY_CONSTRUCTIBLE__, `optional<T>` is also __COPY_CONSTRUCTIBLE__ and can be easily initialized from an lvalue of type `T`:
|
||||
|
||||
T v = make_T();
|
||||
optional<T> o = v;
|
||||
optional<T> p = o;
|
||||
|
||||
If `T` is not `MoveAssignable`, it is still possible to reset the value of `optional<T>` using function `emplace()`:
|
||||
|
||||
optional<const T> o = make_T();
|
||||
o.emplace(make_another_T());
|
||||
|
||||
If `T` is `Moveable` (both __MOVE_CONSTRUCTIBLE__ and `MoveAssignable`) then `optional<T>` is also `Moveable` and additionally can be constructed and assigned from an rvalue of type `T`.
|
||||
|
||||
Similarly, if `T` is `Copyable` (both __COPY_CONSTRUCTIBLE__ and `CopyAssignable`) then `optional<T>` is also `Copyable` and additionally can be constructed and assigned from an lvalue of type `T`.
|
||||
|
||||
`T` ['is not] required to be __STD_DEFAULT_CONSTRUCTIBLE__.
|
||||
|
||||
[endsect]
|
156
doc/1B_on_performance.qbk
Normal file
156
doc/1B_on_performance.qbk
Normal file
@ -0,0 +1,156 @@
|
||||
|
||||
[section Performance considerations]
|
||||
|
||||
Technical details aside, the memory layout of `optional<T>` for a generic `T` is more-less this:
|
||||
|
||||
template <typename T>
|
||||
class optional
|
||||
{
|
||||
bool _initialized;
|
||||
std::aligned_storage_t<sizeof(t), alignof(T)> _storage;
|
||||
};
|
||||
|
||||
Lifetime of the `T` inside `_storage` is manually controlled with placement-`new`s and pseudo-destructor calls. However, for scalar `T`s we use a different way of storage, by simply holding a `T`:
|
||||
|
||||
template <typename T>
|
||||
class optional
|
||||
{
|
||||
bool _initialized;
|
||||
T _storage;
|
||||
};
|
||||
|
||||
We call it a ['direct] storage. This makes `optional<T>` a trivially-copyable type for scalar `T`s. This only works for compilers that support defaulted functions (including defaulted move assignment and constructor). On compilers without defaulted functions we still use the direct storage, but `optional<T>` is no longer recognized as trivially-copyable. Apart from scalar types, we leave the programmer a way of customizing her type, so that it is recognized by `optional` as candidate for optimized storage, by specializing type trait `boost::optional_config::optional_uses_direct_storage_for`:
|
||||
|
||||
struct X // not trivial
|
||||
{
|
||||
X() {}
|
||||
};
|
||||
|
||||
namespace boost { namespace optional_config {
|
||||
|
||||
template <> struct optional_uses_direct_storage_for<X> : boost::true_type {};
|
||||
|
||||
}}
|
||||
|
||||
|
||||
[heading Controlling the size]
|
||||
|
||||
For the purpose of the following analysis, considering memory layouts, we can think of it as:
|
||||
|
||||
template <typename T>
|
||||
class optional
|
||||
{
|
||||
bool _initialized;
|
||||
T _storage;
|
||||
};
|
||||
|
||||
Given type `optional<int>`, and assuming that `sizeof(int) == 4`, we will get `sizeof(optional<int>) == 8`. This is so because of the alignment rules, for our two members we get the following alignment:
|
||||
|
||||
[$images/opt_align1.png]
|
||||
|
||||
This means you can fit twice as many `int`s as `optional<int>`s into the same space of memory. Therefore, if the size of the objects is critical for your application (e.g., because you want to utilize your CPU cache in order to gain performance) and you have determined you are willing to trade the code clarity, it is recommended that you simply go with type `int` and use some 'magic value' to represent ['not-an-int], or use something like [@https://github.com/akrzemi1/markable `markable`] library.
|
||||
|
||||
Even if you cannot spare any value of `int` to represent ['not-an-int] (e.g., because every value is useful, or you do want to signal ['not-an-int] explicitly), at least for `Trivial` types you should consider storing the value and the `bool` flag representing the ['null-state] separately. Consider the following class:
|
||||
|
||||
struct Record
|
||||
{
|
||||
optional<int> _min;
|
||||
optional<int> _max;
|
||||
};
|
||||
|
||||
Its memory layout can be depicted as follows:
|
||||
|
||||
[$images/opt_align2.png]
|
||||
|
||||
This is exactly the same as if we had the following members:
|
||||
|
||||
struct Record
|
||||
{
|
||||
bool _has_min;
|
||||
int _min;
|
||||
bool _has_max;
|
||||
int _max;
|
||||
};
|
||||
|
||||
But when they are stored separately, we at least have an option to reorder them like this:
|
||||
|
||||
struct Record
|
||||
{
|
||||
bool _has_min;
|
||||
bool _has_max;
|
||||
int _min;
|
||||
int _max;
|
||||
};
|
||||
|
||||
Which gives us the following layout (and smaller total size):
|
||||
|
||||
[$images/opt_align3.png]
|
||||
|
||||
Sometimes it requires detailed consideration what data we make optional. In our case above, if we determine that both minimum and maximum value can be provided or not provided together, but one is never provided without the other, we can make only one optional member:
|
||||
|
||||
struct Limits
|
||||
{
|
||||
int _min;
|
||||
int _max;
|
||||
};
|
||||
|
||||
struct Record
|
||||
{
|
||||
optional<Limits> _limits;
|
||||
};
|
||||
|
||||
This would give us the following layout:
|
||||
|
||||
[$images/opt_align4.png]
|
||||
|
||||
[heading Optional function parameters]
|
||||
|
||||
Having function parameters of type `const optional<T>&` may incur certain unexpected run-time cost connected to copy construction of `T`. Consider the following code.
|
||||
|
||||
void fun(const optional<Big>& v)
|
||||
{
|
||||
if (v) doSomethingWith(*v);
|
||||
else doSomethingElse();
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
optional<Big> ov;
|
||||
Big v;
|
||||
fun(none);
|
||||
fun(ov); // no copy
|
||||
fun(v); // copy constructor of Big
|
||||
}
|
||||
|
||||
No copy elision or move semantics can save us from copying type `Big` here. Not that we need any copy, but this is how `optional` works. In order to avoid copying in this case, one could provide second overload of `fun`:
|
||||
|
||||
void fun(const Big& v)
|
||||
{
|
||||
doSomethingWith(v);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
optional<Big> ov;
|
||||
Big v;
|
||||
fun(ov); // no copy
|
||||
fun(v); // no copy: second overload selected
|
||||
}
|
||||
|
||||
Alternatively, you could consider using an optional reference instead:
|
||||
|
||||
void fun(optional<const Big&> v) // note where the reference is
|
||||
{
|
||||
if (v) doSomethingWith(*v);
|
||||
else doSomethingElse();
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
optional<Big> ov;
|
||||
Big v;
|
||||
fun(none);
|
||||
fun(ov); // doesn't compile
|
||||
fun(v); // no copy
|
||||
}
|
||||
[endsect]
|
31
doc/21_ref_none.qbk
Normal file
31
doc/21_ref_none.qbk
Normal file
@ -0,0 +1,31 @@
|
||||
[/
|
||||
Boost.Optional
|
||||
|
||||
Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
|
||||
Copyright (c) 2015 Andrzej Krzemienski
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
[section Header <boost/none.hpp>]
|
||||
|
||||
[section Synopsis]
|
||||
```
|
||||
namespace boost {
|
||||
|
||||
class none_t {/* see below */};
|
||||
|
||||
inline constexpr none_t none (/* see below */);
|
||||
|
||||
} // namespace boost
|
||||
```
|
||||
|
||||
Class `none_t` is meant to serve as a tag for selecting appropriate overloads of from `optional`'s interface. It is an empty, trivially copyable class with disabled default constructor.
|
||||
|
||||
Constant `none` is used to indicate an optional object that does not contain a value in initialization, assignment and relational operations of `optional`.
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
40
doc/22_ref_bad_optional_access.qbk
Normal file
40
doc/22_ref_bad_optional_access.qbk
Normal file
@ -0,0 +1,40 @@
|
||||
[/
|
||||
Boost.Optional
|
||||
|
||||
Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
|
||||
Copyright (c) 2015 Andrzej Krzemienski
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
[section Header <boost/optional/bad_optional_access.hpp>]
|
||||
|
||||
[section Synopsis]
|
||||
```
|
||||
namespace boost {
|
||||
|
||||
class bad_optional_access : public std::logic_error
|
||||
{
|
||||
public:
|
||||
bad_optional_access(); ``[link reference_bad_optional_access_constructor __GO_TO__]``
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
```
|
||||
[endsect]
|
||||
|
||||
[section Detailed semantics]
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_bad_optional_access_constructor]
|
||||
|
||||
`bad_optional_access();`
|
||||
|
||||
* [*Effect:] Constructs an object of class `bad_optional_access`.
|
||||
* [*Postconditions:] `what()` returns an implementation-defined NTBS.
|
||||
|
||||
[endsect]
|
||||
[endsect]
|
79
doc/23_ref_optional_io.qbk
Normal file
79
doc/23_ref_optional_io.qbk
Normal file
@ -0,0 +1,79 @@
|
||||
[/
|
||||
Boost.Optional
|
||||
|
||||
Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
|
||||
Copyright (c) 2015 Andrzej Krzemienski
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
[section:io_header Header <boost/optional/optional_io.hpp>]
|
||||
|
||||
[section:io_synop Synopsis]
|
||||
```
|
||||
#include <istream>
|
||||
#include <ostream>
|
||||
#include <boost/optional/optional.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <class CharType, class CharTrait, class T>
|
||||
std::basic_ostream<CharType, CharTrait>&
|
||||
operator<<(std::basic_ostream<CharType, CharTrait>& out, optional<T> const& v); ``[link reference_operator_ostream __GO_TO__]``
|
||||
|
||||
template <class CharType, class CharTrait>
|
||||
std::basic_ostream<CharType, CharTrait>&
|
||||
operator<<(std::basic_ostream<CharType, CharTrait>& out, none_t const&); ``[link reference_operator_ostream_none __GO_TO__]``
|
||||
|
||||
template<class CharType, class CharTrait, class T>
|
||||
std::basic_istream<CharType, CharTrait>&
|
||||
operator>>(std::basic_istream<CharType, CharTrait>& in, optional<T>& v); ``[link reference_operator_istream __GO_TO__]``
|
||||
|
||||
} // namespace boost
|
||||
```
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:io_semantics Detailed semantics]
|
||||
|
||||
|
||||
[#reference_operator_ostream]
|
||||
|
||||
```
|
||||
template <class CharType, class CharTrait, class T>
|
||||
std::basic_ostream<CharType, CharTrait>&
|
||||
operator<<(std::basic_ostream<CharType, CharTrait>& out, optional<T> const& v);
|
||||
```
|
||||
|
||||
* [*Effect:] Outputs an implementation-defined string. The output contains the information about whether the optional object contains a value or not. If `v` contains a value, the output contains result of calling `out << *v`.
|
||||
* [*Returns:] `out`.
|
||||
|
||||
__SPACE__
|
||||
[#reference_operator_ostream_none]
|
||||
|
||||
```
|
||||
template <class CharType, class CharTrait, class T>
|
||||
std::basic_ostream<CharType, CharTrait>&
|
||||
operator<<(std::basic_ostream<CharType, CharTrait>& out, none_t);
|
||||
```
|
||||
|
||||
* [*Effect:] Outputs an implementation-defined string.
|
||||
* [*Returns:] `out`.
|
||||
|
||||
__SPACE__
|
||||
[#reference_operator_istream]
|
||||
|
||||
```
|
||||
template <class CharType, class CharTrait, class T>
|
||||
std::basic_ostream<CharType, CharTrait>&
|
||||
operator>>(std::basic_istream<CharType, CharTrait>& in, optional<T>& v);
|
||||
```
|
||||
|
||||
* [*Requires:] `T` is __STD_DEFAULT_CONSTRUCTIBLE__ and __MOVE_CONSTRUCTIBLE__.
|
||||
* [*Effect:] Reads the value of optional object from `in`. If the string representation indicates that the optional object should contain a value, `v` contains a value and its contained value is obtained as if by default-constructing an object `o` of type `T` and then calling `in >> o`; otherwise `v` does not contain a value, and the previously contained value (if any) has been destroyed.
|
||||
* [*Returns:] `out`.
|
||||
|
||||
[endsect]
|
||||
[endsect]
|
32
doc/24_ref_optional_fwd.qbk
Normal file
32
doc/24_ref_optional_fwd.qbk
Normal file
@ -0,0 +1,32 @@
|
||||
[/
|
||||
Boost.Optional
|
||||
|
||||
Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
|
||||
Copyright (c) 2015 Andrzej Krzemienski
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
[section Header <boost/optional/optional_fwd.hpp>]
|
||||
|
||||
[section Synopsis]
|
||||
```
|
||||
namespace boost {
|
||||
|
||||
template <class T> class optional ;
|
||||
|
||||
template <class T> void swap ( optional<T>& , optional<T>& );
|
||||
|
||||
template <class T> struct optional_swap_should_use_default_constructor ;
|
||||
|
||||
} // namespace boost
|
||||
```
|
||||
|
||||
This header only contains declarations.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[endsect]
|
303
doc/27_ref_optional_synopsis.qbk
Normal file
303
doc/27_ref_optional_synopsis.qbk
Normal file
@ -0,0 +1,303 @@
|
||||
[/
|
||||
Boost.Optional
|
||||
|
||||
Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
|
||||
[#ref_header_optional_optional_hpp] [section:header_optional_optional Synopsis]
|
||||
|
||||
```// In Header: <`[@boost:/boost/optional/optional.hpp boost/optional/optional.hpp]'''<phrase role="comment">></phrase>'''``
|
||||
|
||||
namespace boost {
|
||||
|
||||
class in_place_init_t { /* see below */ } ; ``[link reference_in_place_init __GO_TO__]``
|
||||
const in_place_init_t in_place_init ( /* see below */ ) ;
|
||||
|
||||
class in_place_init_if_t { /*see below*/ } ; ``[link reference_in_place_init_if __GO_TO__]``
|
||||
const in_place_init_if_t in_place_init_if ( /*see below*/ ) ;
|
||||
|
||||
template <class T>
|
||||
class optional ; ``[link reference_operator_template __GO_TO__]``
|
||||
|
||||
template <class T>
|
||||
class optional<T&> ; ``[link reference_operator_template_spec __GO_TO__]``
|
||||
|
||||
template<class T> inline bool operator == ( optional<T> const& x, optional<T> const& y ) ; ``[link reference_operator_compare_equal_optional_optional __GO_TO__]``
|
||||
|
||||
template<class T> inline bool operator != ( optional<T> const& x, optional<T> const& y ) ; ``[link reference_operator_compare_not_equal_optional_optional __GO_TO__]``
|
||||
|
||||
template<class T> inline bool operator < ( optional<T> const& x, optional<T> const& y ) ; ``[link reference_operator_compare_less_optional_optional __GO_TO__]``
|
||||
|
||||
template<class T> inline bool operator > ( optional<T> const& x, optional<T> const& y ) ; ``[link reference_operator_compare_greater_optional_optional __GO_TO__]``
|
||||
|
||||
template<class T> inline bool operator <= ( optional<T> const& x, optional<T> const& y ) ; ``[link reference_operator_compare_less_or_equal_optional_optional __GO_TO__]``
|
||||
|
||||
template<class T> inline bool operator >= ( optional<T> const& x, optional<T> const& y ) ; ``[link reference_operator_compare_greater_or_equal_optional_optional __GO_TO__]``
|
||||
|
||||
template<class T> inline bool operator == ( optional<T> const& x, none_t ) noexcept ; ``[link reference_operator_compare_equal_optional_none __GO_TO__]``
|
||||
|
||||
template<class T> inline bool operator != ( optional<T> const& x, none_t ) noexcept ; ``[link reference_operator_compare_not_equal_optional_none __GO_TO__]``
|
||||
|
||||
template<class T> inline optional<T> make_optional ( T const& v ) ; ``[link reference_make_optional_value __GO_TO__]``
|
||||
|
||||
template<class T> inline optional<std::decay_t<T>> make_optional ( T && v ) ; ``[link reference_make_optional_rvalue __GO_TO__]``
|
||||
|
||||
template<class T> inline optional<T> make_optional ( bool condition, T const& v ) ; ``[link reference_make_optional_bool_value __GO_TO__]``
|
||||
|
||||
template<class T> inline optional<std::decay_t<T>> make_optional ( bool condition, T && v ) ; ``[link reference_make_optional_bool_rvalue __GO_TO__]``
|
||||
|
||||
template<class T> inline auto get_optional_value_or ( optional<T> const& opt, typename optional<T>::reference_const_type def ) -> typename optional<T>::reference_const_type; ``[link reference_free_get_value_or __GO_TO__]``
|
||||
|
||||
template<class T> inline auto get_optional_value_or ( optional<T> const& opt, typename optional<T>::reference_type def ) -> typename optional<T>::reference_type ; ``[link reference_free_get_value_or __GO_TO__]``
|
||||
|
||||
template<class T> inline T const& get ( optional<T> const& opt ) ; ``[link reference_optional_get __GO_TO__]``
|
||||
|
||||
template<class T> inline T& get ( optional<T> & opt ) ; ``[link reference_optional_get __GO_TO__]``
|
||||
|
||||
template<class T> inline T const* get ( optional<T> const* opt ) ; ``[link reference_optional_get __GO_TO__]``
|
||||
|
||||
template<class T> inline T* get ( optional<T>* opt ) ; ``[link reference_optional_get __GO_TO__]``
|
||||
|
||||
template<class T> inline auto get_pointer ( optional<T> const& opt ) -> ``['see below]``; ``[link reference_free_get_pointer __GO_TO__]``
|
||||
|
||||
template<class T> inline auto get_pointer ( optional<T> & opt ) -> ``['see below]``; ``[link reference_free_get_pointer __GO_TO__]``
|
||||
|
||||
template<class T> inline void swap( optional<T>& x, optional<T>& y ) ; ``[link reference_swap_optional_optional __GO_TO__]``
|
||||
|
||||
template<class T> inline void swap( optional<T&>& x, optional<T&>& y ) ; ``[link reference_swap_optional_reference __GO_TO__]``
|
||||
|
||||
} // namespace boost
|
||||
|
||||
namespace std {
|
||||
|
||||
template <typename T>
|
||||
struct hash<boost::optional<T> > ; ``[link reference_std_hash_spec __GO_TO__]``
|
||||
|
||||
template <typename T>
|
||||
struct hash<boost::optional<T&> > ; ``[link reference_std_hash_spec __GO_TO__]``
|
||||
|
||||
} // namespace std
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[section:header_optional_in_place_init Initialization tags]
|
||||
|
||||
[#reference_in_place_init]
|
||||
[#reference_in_place_init_if]
|
||||
|
||||
namespace boost {
|
||||
|
||||
class in_place_init_t { /* see below */ } ;
|
||||
const in_place_init_t in_place_init ( /* see below */ ) ;
|
||||
|
||||
class in_place_init_if_t { /*see below*/ } ;
|
||||
const in_place_init_if_t in_place_init_if ( /*see below*/ ) ;
|
||||
|
||||
}
|
||||
|
||||
Classes `in_place_init_t` and `in_place_init_if_t` are empty classes. Their purpose is to control overload resolution in the initialization of optional objects.
|
||||
They are empty, trivially copyable classes with disabled default constructor.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:header_optional_optional_values Optional Values]
|
||||
|
||||
[#reference_operator_template]
|
||||
|
||||
template <class T>
|
||||
class optional
|
||||
{
|
||||
public :
|
||||
|
||||
typedef T value_type ;
|
||||
typedef T & reference_type ;
|
||||
typedef T const& reference_const_type ;
|
||||
typedef T && rval_reference_type ;
|
||||
typedef T * pointer_type ;
|
||||
typedef T const* pointer_const_type ;
|
||||
|
||||
optional () noexcept ; ``[link reference_optional_constructor __GO_TO__]``
|
||||
|
||||
optional ( none_t ) noexcept ; ``[link reference_optional_constructor_none_t __GO_TO__]``
|
||||
|
||||
optional ( T const& v ) ; ``[link reference_optional_constructor_value __GO_TO__]``
|
||||
|
||||
optional ( T&& v ) ; ``[link reference_optional_constructor_move_value __GO_TO__]``
|
||||
|
||||
optional ( bool condition, T const& v ) ; ``[link reference_optional_constructor_bool_value __GO_TO__]``
|
||||
|
||||
optional ( optional const& rhs ) ; ``[link reference_optional_constructor_optional __GO_TO__]``
|
||||
|
||||
optional ( optional&& rhs ) noexcept(``['see below]``) ; ``[link reference_optional_move_constructor_optional __GO_TO__]``
|
||||
|
||||
template<class U> explicit optional ( optional<U> const& rhs ) ; ``[link reference_optional_constructor_other_optional __GO_TO__]``
|
||||
|
||||
template<class U> explicit optional ( optional<U>&& rhs ) ; ``[link reference_optional_move_constructor_other_optional __GO_TO__]``
|
||||
|
||||
template<class... Args> explicit optional ( in_place_init_t, Args&&... args ) ; ``[link reference_optional_in_place_init __GO_TO__]``
|
||||
|
||||
template<class... Args> explicit optional ( in_place_init_if_t, bool condition, Args&&... args ) ; ``[link reference_optional_in_place_init_if __GO_TO__]``
|
||||
|
||||
template<class InPlaceFactory> explicit optional ( InPlaceFactory const& f ) ; ``[link reference_optional_constructor_factory __GO_TO__]``
|
||||
|
||||
template<class TypedInPlaceFactory> explicit optional ( TypedInPlaceFactory const& f ) ; ``[link reference_optional_constructor_factory __GO_TO__]``
|
||||
|
||||
optional& operator = ( none_t ) noexcept ; ``[link reference_optional_operator_equal_none_t __GO_TO__]``
|
||||
|
||||
optional& operator = ( T const& v ) ; ``[link reference_optional_operator_equal_value __GO_TO__]``
|
||||
|
||||
optional& operator = ( T&& v ) ; ``[link reference_optional_operator_move_equal_value __GO_TO__]``
|
||||
|
||||
optional& operator = ( optional const& rhs ) ; ``[link reference_optional_operator_equal_optional __GO_TO__]``
|
||||
|
||||
optional& operator = ( optional&& rhs ) noexcept(``['see below]``) ; ``[link reference_optional_operator_move_equal_optional __GO_TO__]``
|
||||
|
||||
template<class U> optional& operator = ( optional<U> const& rhs ) ; ``[link reference_optional_operator_equal_other_optional __GO_TO__]``
|
||||
|
||||
template<class U> optional& operator = ( optional<U>&& rhs ) ; ``[link reference_optional_operator_move_equal_other_optional __GO_TO__]``
|
||||
|
||||
template<class... Args> void emplace ( Args&&... args ) ; ``[link reference_optional_emplace __GO_TO__]``
|
||||
|
||||
template<class InPlaceFactory> optional& operator = ( InPlaceFactory const& f ) ; ``[link reference_optional_operator_equal_factory __GO_TO__]``
|
||||
|
||||
template<class TypedInPlaceFactory> optional& operator = ( TypedInPlaceFactory const& f ) ; ``[link reference_optional_operator_equal_factory __GO_TO__]``
|
||||
|
||||
T const& get() const ; ``[link reference_optional_get __GO_TO__]``
|
||||
T& get() ; ``[link reference_optional_get __GO_TO__]``
|
||||
|
||||
T const* operator ->() const ; ``[link reference_optional_operator_arrow __GO_TO__]``
|
||||
T* operator ->() ; ``[link reference_optional_operator_arrow __GO_TO__]``
|
||||
|
||||
T const& operator *() const& ; ``[link reference_optional_operator_asterisk __GO_TO__]``
|
||||
T& operator *() & ; ``[link reference_optional_operator_asterisk __GO_TO__]``
|
||||
T&& operator *() && ; ``[link reference_optional_operator_asterisk_move __GO_TO__]``
|
||||
|
||||
T const& value() const& ; ``[link reference_optional_value __GO_TO__]``
|
||||
T& value() & ; ``[link reference_optional_value __GO_TO__]``
|
||||
T&& value() && ; ``[link reference_optional_value_move __GO_TO__]``
|
||||
|
||||
template<class U> T value_or( U && v ) const& ; ``[link reference_optional_value_or __GO_TO__]``
|
||||
template<class U> T value_or( U && v ) && ; ``[link reference_optional_value_or_move __GO_TO__]``
|
||||
|
||||
template<class F> T value_or_eval( F f ) const& ; ``[link reference_optional_value_or_call __GO_TO__]``
|
||||
template<class F> T value_or_eval( F f ) && ; ``[link reference_optional_value_or_call_move __GO_TO__]``
|
||||
|
||||
template<class F> auto map( F f ) const& -> ``['see below]``; ``[link reference_optional_map __GO_TO__]``
|
||||
template<class F> auto map( F f ) & -> ``['see below]``; ``[link reference_optional_map __GO_TO__]``
|
||||
template<class F> auto map( F f ) && -> ``['see below]``; ``[link reference_optional_map_move __GO_TO__]``
|
||||
|
||||
template<class F> auto flat_map( F f ) const& -> ``['see below]``; ``[link reference_optional_flat_map __GO_TO__]``
|
||||
template<class F> auto flat_map( F f ) & -> ``['see below]``; ``[link reference_optional_flat_map __GO_TO__]``
|
||||
template<class F> auto flat_map( F f ) && -> ``['see below]``; ``[link reference_optional_flat_map_move __GO_TO__]``
|
||||
|
||||
T const* get_ptr() const ; ``[link reference_optional_get_ptr __GO_TO__]``
|
||||
T* get_ptr() ; ``[link reference_optional_get_ptr __GO_TO__]``
|
||||
|
||||
bool has_value() const noexcept ; ``[link reference_optional_operator_bool __GO_TO__]``
|
||||
|
||||
explicit operator bool() const noexcept ; ``[link reference_optional_operator_bool __GO_TO__]``
|
||||
|
||||
bool operator!() const noexcept ; ``[link reference_optional_operator_not __GO_TO__]``
|
||||
|
||||
void reset() noexcept ; ``[link reference_optional_reset __GO_TO__]``
|
||||
|
||||
// deprecated methods
|
||||
|
||||
// (deprecated)
|
||||
void reset ( T const& ) ; ``[link reference_optional_reset_value __GO_TO__]``
|
||||
|
||||
// (deprecated)
|
||||
bool is_initialized() const ; ``[link reference_optional_is_initialized __GO_TO__]``
|
||||
|
||||
// (deprecated)
|
||||
T const& get_value_or( T const& default ) const ; ``[link reference_optional_get_value_or_value __GO_TO__]``
|
||||
};
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[section:header_optional_optional_refs Optional References]
|
||||
|
||||
[#reference_operator_template_spec]
|
||||
template <class T>
|
||||
class optional<T&> // specialization for lvalue references
|
||||
{
|
||||
public :
|
||||
|
||||
typedef T& value_type;
|
||||
typedef T& reference_type;
|
||||
typedef T& reference_const_type; // no const propagation
|
||||
typedef T& rval_reference_type;
|
||||
typedef T* pointer_type;
|
||||
typedef T* pointer_const_type; // no const propagation
|
||||
|
||||
optional () noexcept ; ``[link reference_optional_ref_default_ctor __GO_TO__]``
|
||||
|
||||
optional ( none_t ) noexcept ; ``[link reference_optional_ref_default_ctor __GO_TO__]``
|
||||
|
||||
template<class R> optional(R&& r) noexcept ; ``[link reference_optional_ref_value_ctor __GO_TO__]``
|
||||
|
||||
template <class R> optional(bool cond, R&& r) noexcept ; ``[link reference_optional_ref_cond_value_ctor __GO_TO__]``
|
||||
|
||||
optional ( optional const& rhs ) noexcept ; ``[link reference_optional_ref_copy_ctor __GO_TO__]``
|
||||
|
||||
template<class U> explicit optional ( optional<U&> const& rhs ) noexcept ; ``[link reference_optional_ref_ctor_from_opt_U __GO_TO__]``
|
||||
|
||||
optional& operator = ( none_t ) noexcept ; ``[link reference_optional_ref_assign_none_t __GO_TO__]``
|
||||
|
||||
optional& operator = ( optional const& rhs ) noexcept; ``[link reference_optional_ref_copy_assign __GO_TO__]``
|
||||
|
||||
template<class U> optional& operator = ( optional<U&> const& rhs ) noexcept ; ``[link reference_optional_ref_assign_optional_U __GO_TO__]``
|
||||
|
||||
template<class R> optional& operator = (R&& r) noexcept ; ``[link reference_optional_ref_assign_R __GO_TO__]``
|
||||
|
||||
template<class R> void emplace ( R&& r ) noexcept ; ``[link reference_optional_ref_emplace_R __GO_TO__]``
|
||||
|
||||
T& get() const ; ``[link reference_optional_ref_get __GO_TO__]``
|
||||
T& operator *() const ; ``[link reference_optional_ref_get __GO_TO__]``
|
||||
|
||||
T* operator ->() const ; ``[link reference_optional_ref_arrow __GO_TO__]``
|
||||
|
||||
T& value() const& ; ``[link reference_optional_ref_value __GO_TO__]``
|
||||
|
||||
template<class R> T& value_or( R && r ) const noexcept ; ``[link reference_optional_ref_value_or __GO_TO__]``
|
||||
|
||||
template<class F> T& value_or_eval( F f ) const ; ``[link reference_optional_ref_value_or_eval __GO_TO__]``
|
||||
|
||||
template<class F> auto map( F f ) const -> ``['see below]``; ``[link reference_optional_ref_map __GO_TO__]``
|
||||
|
||||
template<class F> auto flat_map( F f ) const -> ``['see below]``; ``[link reference_optional_ref_flat_map __GO_TO__]``
|
||||
|
||||
T* get_ptr() const noexcept ; ``[link reference_optional_ref_get_ptr __GO_TO__]``
|
||||
|
||||
bool has_value() const noexcept ; ``[link reference_optional_ref_operator_bool __GO_TO__]``
|
||||
|
||||
explicit operator bool() const noexcept ; ``[link reference_optional_ref_operator_bool __GO_TO__]``
|
||||
|
||||
bool operator!() const noexcept ; ``[link reference_optional_ref_operator_not __GO_TO__]``
|
||||
|
||||
void reset() noexcept ; ``[link reference_optional_ref_reset __GO_TO__]``
|
||||
|
||||
// deprecated methods
|
||||
|
||||
// (deprecated)
|
||||
template<class R> void reset ( R && r ) noexcept ; ``[link reference_optional_ref_reset_value __GO_TO__]``
|
||||
|
||||
// (deprecated)
|
||||
bool is_initialized() const noexcept ; ``[link reference_optional_ref_is_initialized __GO_TO__]``
|
||||
|
||||
// (deprecated)
|
||||
template<class R> T& get_value_or( R && r ) constnoexcept; ``[link reference_optional_ref_get_value_or_value __GO_TO__]``
|
||||
|
||||
private:
|
||||
T* ref; // exposition only
|
||||
};
|
||||
[endsect]
|
1444
doc/28_ref_optional_semantics.qbk
Normal file
1444
doc/28_ref_optional_semantics.qbk
Normal file
File diff suppressed because it is too large
Load Diff
17
doc/29_ref_optional_convenience.qbk
Normal file
17
doc/29_ref_optional_convenience.qbk
Normal file
@ -0,0 +1,17 @@
|
||||
[/
|
||||
Boost.Optional
|
||||
|
||||
Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
|
||||
Copyright (c) 2015 Andrzej Krzemienski
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
[section Header <boost/optional.hpp>]
|
||||
|
||||
This is an alias for header [link boost_optional.reference.header__boost_optional_optional_hpp_.header_optional_optional `<boost/optional/optional.hpp>`].
|
||||
|
||||
|
||||
[endsect]
|
113
doc/90_dependencies.qbk
Normal file
113
doc/90_dependencies.qbk
Normal file
@ -0,0 +1,113 @@
|
||||
[/
|
||||
Boost.Optional
|
||||
|
||||
Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
|
||||
[section Dependencies and Portability]
|
||||
|
||||
[section Dependencies]
|
||||
The implementation uses the following other Boost modules:
|
||||
|
||||
# assert
|
||||
# config
|
||||
# core
|
||||
# move
|
||||
# static_assert
|
||||
# throw_exception
|
||||
# type_traits
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Emplace operations in older compilers][#optional_emplace_workaround]
|
||||
|
||||
Certain constructors and functions in the interface of `optional` perform a 'perfect forwarding' of arguments:
|
||||
|
||||
template<class... Args> optional(in_place_init_t, Args&&... args);
|
||||
template<class... Args> optional(in_place_init_if_t, bool condition, Args&&... args);
|
||||
template<class... Args> void emplace(Args&&... args);
|
||||
|
||||
On compilers that do not support variadic templates, each of these functions is substituted with two overloads, one forwarding a single argument, the other forwarding zero arguments. This forms the following set:
|
||||
|
||||
template<class Arg> optional(in_place_init_t, Arg&& arg);
|
||||
optional(in_place_init_t);
|
||||
|
||||
template<class Arg> optional(in_place_init_if_t, bool condition, Arg&& arg);
|
||||
optional(in_place_init_if_t, bool condition);
|
||||
|
||||
template<class Arg> void emplace(Arg&& arg);
|
||||
void emplace();
|
||||
|
||||
On compilers that do not support rvalue references, each of these functions is substituted with three overloads: taking `const` and non-`const` lvalue reference, and third forwarding zero arguments. This forms the following set:
|
||||
|
||||
template<class Arg> optional(in_place_init_t, const Arg& arg);
|
||||
template<class Arg> optional(in_place_init_t, Arg& arg);
|
||||
optional(in_place_init_t);
|
||||
|
||||
template<class Arg> optional(in_place_init_if_t, bool condition, const Arg& arg);
|
||||
template<class Arg> optional(in_place_init_if_t, bool condition, Arg& arg);
|
||||
optional(in_place_init_if_t, bool condition);
|
||||
|
||||
template<class Arg> void emplace(const Arg& arg);
|
||||
template<class Arg> void emplace(Arg& arg);
|
||||
void emplace();
|
||||
|
||||
This workaround addresses about 40% of all use cases. If this is insufficient, you need to resort to using [link boost_optional.tutorial.in_place_factories In-Place Factories].
|
||||
[endsect]
|
||||
|
||||
[section Optional Reference Binding][#optional_reference_binding]
|
||||
|
||||
A number of compilers incorrectly treat const lvalues of integral type as rvalues, and create an illegal temporary when binding to an lvalue reference to const in some expressions. This could result in creating an optional lvalue reference that is in fact bound to an unexpected temporary rather than to the intended object. In order to prevent hard to find run-time bugs, this library performs compile-time checks to prevent expressions that would otherwise bind an optional reference to an unexpected temporary. As a consequence, on certain compilers certain pieces of functionality in optional references are missing. In order to maintain a portability of your code across different compilers, it is recommended that you only stick to the minimum portable interface of optional references: prefer direct-initialization and copy assignment of optional references to copy-initialization and assignment from `T&`:
|
||||
|
||||
const int i = 0;
|
||||
optional<const int&> or1;
|
||||
optional<const int&> or2 = i; // caution: not portable
|
||||
or1 = i; // caution: not portable
|
||||
|
||||
optional<const int&> or3(i); // portable
|
||||
or1 = optional<const int&>(i); // portable
|
||||
|
||||
Compilers known to have these deficiencies include GCC versions 4.2, 4.3, 4.4, 4.5, 5.1, 5.2; QCC 4.4.2; MSVC versions 8.0, 9.0, 10.0, 11.0, 12.0. In order to check if your compiler correctly implements reference binding use this test program.
|
||||
|
||||
#include <cassert>
|
||||
|
||||
const int global_i = 0;
|
||||
|
||||
struct TestingReferenceBinding
|
||||
{
|
||||
TestingReferenceBinding(const int& ii)
|
||||
{
|
||||
assert(&ii == &global_i);
|
||||
}
|
||||
|
||||
void operator=(const int& ii)
|
||||
{
|
||||
assert(&ii == &global_i);
|
||||
}
|
||||
|
||||
void operator=(int&&) // remove this if your compiler doesn't have rvalue refs
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
const int& iref = global_i;
|
||||
assert(&iref == &global_i);
|
||||
|
||||
TestingReferenceBinding ttt = global_i;
|
||||
ttt = global_i;
|
||||
|
||||
TestingReferenceBinding ttt2 = iref;
|
||||
ttt2 = iref;
|
||||
}
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
152
doc/91_relnotes.qbk
Normal file
152
doc/91_relnotes.qbk
Normal file
@ -0,0 +1,152 @@
|
||||
[/
|
||||
Boost.Optional
|
||||
|
||||
Copyright (c) 2015 - 2023 Andrzej Krzemienski
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
|
||||
[section:relnotes Release Notes]
|
||||
|
||||
[heading Boost Release 1.87]
|
||||
|
||||
* *Breaking change.* Dropped support for C++03. C++11 is now the required minimum.
|
||||
* Dropped dependency on Boost.Utility.
|
||||
* Dropped dependency on Boost.Predef.
|
||||
* A bit faster implementation of some relational operations.
|
||||
|
||||
|
||||
[heading Boost Release 1.85]
|
||||
|
||||
* Fixed the implementation for trivial types. Now it is slower, because it always initializes the `T`, but it avoids undefined behavior when `optional<T>` is copied. This fixes [@https://github.com/boostorg/optional/issues/108 issue #108].
|
||||
* Fixed some `-Wmaybe-uninitialized` warnings in GCC 12. Thanks to Christian Mazakas for the fix.
|
||||
* Dropped dependency on Boost.Detail.
|
||||
|
||||
[heading Boost Release 1.83]
|
||||
|
||||
* Deprecated support for C++03 and earlier, C++11 will be required in release 1.86.
|
||||
|
||||
[heading Boost Release 1.80]
|
||||
|
||||
* [*Breaking change:] Added specializations for `std::hash<boost::optional<T>>`. This fixes [@https://github.com/boostorg/optional/issues/55 issue #55]. You may get compiler errors when your program provides specializations for `std::hash<boost::optional<T>>`. If this happens, define macro `BOOST_OPTIONAL_CONFIG_DO_NOT_SPECIALIZE_STD_HASH` to suppress the specializations of `std::hash` in this library.
|
||||
|
||||
[heading Boost Release 1.79]
|
||||
|
||||
* Fixed [@https://github.com/boostorg/optional/issues/98 issue #98].
|
||||
* Fixed [@https://github.com/boostorg/optional/issues/92 issue #92].
|
||||
* Added support for `BOOST_NO_IOSTREAM`.
|
||||
* Now aligned storage uses `unsigned char` rather than `char` to avoid UB.
|
||||
* Now using cv-unqualified `value_type` with placement `new` to avoid UB.
|
||||
|
||||
[heading Boost Release 1.76]
|
||||
|
||||
* Fixed MSVC warning C4702.
|
||||
|
||||
[heading Boost Release 1.75]
|
||||
|
||||
* `boost::none` is `constexpr`-declared.
|
||||
|
||||
* Fixed [@https://github.com/boostorg/optional/issues/78 issue #78].
|
||||
|
||||
[heading Boost Release 1.73]
|
||||
|
||||
* Fixed [@https://github.com/boostorg/optional/issues/78 issue #78].
|
||||
* `boost::none` is now declared as an inline variable (on compilers that support it): there is only one instance of `boost::none` across all translation units.
|
||||
* Fixed a number of compilation errors in GCC 4.4.7 in `optional<T>` for trivial `T`s. Thanks to Robert Leahy for the fix. For details see [@https://github.com/boostorg/optional/pull/80 pr #78].
|
||||
* Now suppressing warning `-Wweak-vtables`.
|
||||
|
||||
[heading Boost Release 1.69]
|
||||
|
||||
* Remove deprecation mark from `reset()` method (without arguments).
|
||||
* Fixed [@https://github.com/boostorg/optional/issues/59 issue #59].
|
||||
* Fixed bug with initialization of certain wrapper types in clang with -std=c++03. See [@https://github.com/boostorg/optional/pull/64 pr #64].
|
||||
|
||||
[heading Boost Release 1.68]
|
||||
|
||||
* Added member function `has_value()` for compatibility with `std::optional` ([@https://github.com/boostorg/optional/issues/52 issue #52]).
|
||||
* Added member function `map()` for transforming `optional<T>` into `optional<U>` using a function of type `T -> U`.
|
||||
* Added member function `flat_map()` for transforming `optional<T>` into `optional<U>` using a function of type `T -> optional<U>`.
|
||||
|
||||
|
||||
[heading Boost Release 1.67]
|
||||
|
||||
* Fixed [@https://github.com/boostorg/optional/issues/46 issue #46].
|
||||
* Fixed `-Wzero-as-null-pointer-constant` warnings.
|
||||
|
||||
|
||||
[heading Boost Release 1.66]
|
||||
|
||||
* On newer compilers `optional` is now trivially-copyable for scalar `T`s. This uses a different storage (just `T` rather than `aligned_storage`). We require the compiler to support defaulted functions.
|
||||
* Changed the implementation of `operator==` to get rid of the `-Wmaybe-uninitialized` false-positive warning from GCC.
|
||||
|
||||
[heading Boost Release 1.63]
|
||||
* Added two new in-place constructors. They work similarly to `emplace()` functions: they initialize the contained value by perfect-forwarding the obtained arguments. One constructor always initializes the contained value, the other based on a boolean condition.
|
||||
* Syntax `o = {}` now correctly un-initializes optional, just like in `std::optional`.
|
||||
* Fixed [@https://svn.boost.org/trac/boost/ticket/12203 Trac #12203].
|
||||
* Fixed [@https://svn.boost.org/trac/boost/ticket/12563 Trac #12563].
|
||||
|
||||
|
||||
[heading Boost Release 1.62]
|
||||
|
||||
* Fixed [@https://svn.boost.org/trac/boost/ticket/12179 Trac #12179].
|
||||
|
||||
|
||||
[heading Boost Release 1.61]
|
||||
|
||||
* Now `boost::optional` is specialized for reference parameters. This addresses a couple of issues:
|
||||
* the `sizeof` of optional reference is that of a pointer,
|
||||
* some bugs connected to copying optional references are gone,
|
||||
* all run-time bugs caused by incorrect reference binding on some compilers are now turned into compile-time errors,
|
||||
* you can swap optional references: it is like swapping pointers: shallow, underlying objects are not affected,
|
||||
* optional references to abstract types work.
|
||||
* Documented nested typedefs ([@https://svn.boost.org/trac/boost/ticket/5193 Trac #5193]).
|
||||
* Made the perfect-forwarding constructor SFINAE-friendly, which fixes [@https://svn.boost.org/trac/boost/ticket/12002 Trac #12002]. However, this only works in the newer platforms that correctly implement C++11 `<type_traits>`.
|
||||
* Fixed [@https://svn.boost.org/trac/boost/ticket/10445 Trac #10445].
|
||||
|
||||
|
||||
[heading Boost Release 1.60]
|
||||
|
||||
* Changed the implementation of `boost::none` again. Now it is a const object with internal linkage (as any other tag). This fixes [@https://svn.boost.org/trac/boost/ticket/11203 Trac #11203].
|
||||
|
||||
|
||||
[heading Boost Release 1.59]
|
||||
|
||||
* For C++03 compilers, added 0-argument overload for member function `emplace()`, and therewith removed the dependency on `<boost/utility/in_place_factory.hpp>`.
|
||||
* Fixed [@https://svn.boost.org/trac/boost/ticket/11241 Trac #11241].
|
||||
|
||||
[heading Boost Release 1.58]
|
||||
|
||||
* `boost::none_t` is no longer convertible from literal `0`. This avoids a bug where `optional<rational<int>> oi = 0;` would initialize an optional object with no contained value.
|
||||
* Improved the trick that prevents streaming out `optional` without header `optional_io.hpp` by using safe-bool idiom. This addresses [@https://svn.boost.org/trac/boost/ticket/10825 Trac #10825].
|
||||
* IOStream operators are now mentioned in documentation.
|
||||
* Added a way to manually disable move semantics: just define macro `BOOST_OPTIONAL_CONFIG_NO_RVALUE_REFERENCES`. This can be used to work around [@https://svn.boost.org/trac/boost/ticket/10399 Trac #10399].
|
||||
* It is no longer possible to assign `optional<U>` to `optional<T>` when `U` is not assignable or convertible to `T` ([@https://svn.boost.org/trac/boost/ticket/11087 Trac #11087]).
|
||||
* Value accessors now work correctly on rvalues of `optional<T&>` ([@https://svn.boost.org/trac/boost/ticket/10839 Trac #10839]).
|
||||
|
||||
|
||||
[heading Boost Release 1.57]
|
||||
|
||||
* [@https://github.com/boostorg/optional/pull/9 Git pull #9]: ['"Supply `<string>` to fix C++03 compile error on `logic_error("...")`"].
|
||||
|
||||
|
||||
[heading Boost Release 1.56]
|
||||
|
||||
* Added support for rvalue references. Now `optional<T>` works with moveable but non-copyable `T`'s,
|
||||
* Improved `swap` (now uses move operations),
|
||||
* Added function `emplace()`. This is the last of the requests from [@https://svn.boost.org/trac/boost/ticket/1841 Trac #1841],
|
||||
* `optional` is moveable, including conditional `noexcept` specifications, which make it `move_if_noexcept`-friendly,
|
||||
* Using explicit operator bool() on platforms that support it ([@https://svn.boost.org/trac/boost/ticket/4227 Trac #4227]) (breaking change),
|
||||
* Forward declaration of `operator<<(ostream&, optional const&)` to prevent inadvertent incorrect serialization of optional objects,
|
||||
* Removed deprecated function `reset()` from examples ([@https://svn.boost.org/trac/boost/ticket/9005 Trac #9005]),
|
||||
* Equality comparison with `boost::none` does not require that `T` be EqualityComparable,
|
||||
* Optional rvalue references are explicitly disallowed,
|
||||
* Binding temporaries to optional references is explicitly disallowed (breaking change),
|
||||
* More ways to access the contained value, functions `value()`, `value_or()`, `value_or_eval()`,
|
||||
* Updated and reorganized documentation, added tutorial and quick guide sections.
|
||||
|
||||
|
||||
|
||||
[endsect][/ relnotes]
|
62
doc/92_acknowledgments.qbk
Normal file
62
doc/92_acknowledgments.qbk
Normal file
@ -0,0 +1,62 @@
|
||||
[/
|
||||
Boost.Optional
|
||||
|
||||
Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
|
||||
[section:acknowledgements Acknowledgements]
|
||||
|
||||
[heading Pre-formal review]
|
||||
|
||||
* Peter Dimov suggested the name 'optional', and was the first to point out
|
||||
the need for aligned storage.
|
||||
* Douglas Gregor developed 'type_with_alignment', and later Eric Friedman
|
||||
coded 'aligned_storage', which are the core of the optional class
|
||||
implementation.
|
||||
* Andrei Alexandrescu and Brian Parker also worked with aligned storage
|
||||
techniques and their work influenced the current implementation.
|
||||
* Gennadiy Rozental made extensive and important comments which shaped the
|
||||
design.
|
||||
* Vesa Karvonen and Douglas Gregor made quite useful comparisons between
|
||||
optional, variant and any; and made other relevant comments.
|
||||
* Douglas Gregor and Peter Dimov commented on comparisons and evaluation
|
||||
in boolean contexts.
|
||||
* Eric Friedman helped understand the issues involved with aligned storage,
|
||||
move/copy operations and exception safety.
|
||||
* Many others have participated with useful comments: Aleksey Gurotov,
|
||||
Kevlin Henney, David Abrahams, and others I can't recall.
|
||||
|
||||
[heading Post-formal review]
|
||||
|
||||
* William Kempf carefully considered the originally proposed interface
|
||||
and suggested the new interface which is currently used. He also started and
|
||||
fueled the discussion about the analogy optional<>/smart pointer and about
|
||||
relational operators.
|
||||
* Peter Dimov, Joel de Guzman, David Abrahams, Tanton Gibbs and Ian Hanson
|
||||
focused on the relational semantics of optional (originally undefined);
|
||||
concluding with the fact that the pointer-like interface doesn't make it a
|
||||
pointer so it shall have deep relational operators.
|
||||
* Augustus Saunders also explored the different relational semantics between
|
||||
optional<> and a pointer and developed the OptionalPointee concept as an aid
|
||||
against potential conflicts on generic code.
|
||||
* Joel de Guzman noticed that optional<> can be seen as an API on top of
|
||||
variant<T,nil_t>.
|
||||
* Dave Gomboc explained the meaning and usage of the Haskell analog to
|
||||
optional<>: the Maybe type constructor (analogy originally pointed out by
|
||||
David Sankel).
|
||||
* Other comments were posted by Vincent Finn, Anthony Williams, Ed Brey,
|
||||
Rob Stewart, and others.
|
||||
* Joel de Guzman made the case for the support of references and helped
|
||||
with the proper semantics.
|
||||
* Mat Marcus shown the virtues of a value-oriented interface, influencing
|
||||
the current design, and contributed the idea of "none".
|
||||
* Vladimir Batov's design of Boost.Convert library motivated the development
|
||||
of value accessors for `optional`: functions `value`, `value_or`, `value_or_eval`.
|
||||
|
||||
[endsect]
|
||||
|
55
doc/Jamfile.v2
Normal file
55
doc/Jamfile.v2
Normal file
@ -0,0 +1,55 @@
|
||||
# Boost.Optional
|
||||
#
|
||||
# Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
|
||||
# Quickbook
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
using boostbook ;
|
||||
import quickbook ;
|
||||
|
||||
path-constant images : html ;
|
||||
|
||||
xml optional
|
||||
:
|
||||
00_optional.qbk
|
||||
;
|
||||
|
||||
install images
|
||||
:
|
||||
images/opt_align1.png
|
||||
images/opt_align2.png
|
||||
images/opt_align3.png
|
||||
images/opt_align4.png
|
||||
images/R.png
|
||||
images/space.png
|
||||
:
|
||||
<location>html/images
|
||||
;
|
||||
|
||||
boostbook standalone
|
||||
:
|
||||
optional
|
||||
:
|
||||
<format>html:<xsl:param>"boost.root=../../../.."
|
||||
<format>html:<xsl:param>"boost.libraries=../../../../libs/libraries.htm"
|
||||
<xsl:param>"chapter.autolabel=0"
|
||||
<xsl:param>"chunk.section.depth=8"
|
||||
<xsl:param>"toc.section.depth=1"
|
||||
<xsl:param>"toc.max.depth=2"
|
||||
<xsl:param>"generate.section.toc.level=1"
|
||||
<format>pdf:<xsl:param>"img.src.path=$(images)/"
|
||||
<format>pdf:<xsl:param>"boost.url.prefix=http://www.boost.org/doc/libs/release/libs/optional/doc/html"
|
||||
<format>docbook:<auto-index-internal>on
|
||||
;
|
||||
|
||||
###############################################################################
|
||||
alias boostdoc ;
|
||||
explicit boostdoc ;
|
||||
alias boostrelease : standalone ;
|
||||
explicit boostrelease ;
|
BIN
doc/images/R.png
Normal file
BIN
doc/images/R.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 293 B |
BIN
doc/images/opt_align1.png
Normal file
BIN
doc/images/opt_align1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 417 B |
BIN
doc/images/opt_align2.png
Normal file
BIN
doc/images/opt_align2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 472 B |
BIN
doc/images/opt_align3.png
Normal file
BIN
doc/images/opt_align3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 468 B |
BIN
doc/images/opt_align4.png
Normal file
BIN
doc/images/opt_align4.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 428 B |
BIN
doc/images/space.png
Normal file
BIN
doc/images/space.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 81 B |
1614
doc/optional.html
1614
doc/optional.html
File diff suppressed because it is too large
Load Diff
@ -1,28 +0,0 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
#ifndef BOOST_DETAIL_NONE_T_17SEP2003_HPP
|
||||
#define BOOST_DETAIL_NONE_T_17SEP2003_HPP
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
|
||||
struct none_helper{};
|
||||
|
||||
typedef int none_helper::*none_t ;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
@ -1,10 +1,11 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
// Copyright (C) 2014, 2015 Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
// See http://www.boost.org/libs/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
@ -12,20 +13,47 @@
|
||||
#ifndef BOOST_NONE_17SEP2003_HPP
|
||||
#define BOOST_NONE_17SEP2003_HPP
|
||||
|
||||
#include "boost/config.hpp"
|
||||
#include "boost/none_t.hpp"
|
||||
|
||||
// NOTE: Borland users have to include this header outside any precompiled headers
|
||||
// (bcc<=5.64 cannot include instance data in a precompiled header)
|
||||
// -- * To be verified, now that there's no unnamed namespace
|
||||
|
||||
namespace boost {
|
||||
|
||||
#ifdef BOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE
|
||||
|
||||
BOOST_INLINE_VARIABLE none_t BOOST_CONSTEXPR_OR_CONST none = (static_cast<none_t>(0)) ;
|
||||
|
||||
#elif defined BOOST_OPTIONAL_USE_SINGLETON_DEFINITION_OF_NONE
|
||||
|
||||
namespace detail { namespace optional_detail {
|
||||
|
||||
// the trick here is to make boost::none defined once as a global but in a header file
|
||||
template <typename T>
|
||||
struct none_instance
|
||||
{
|
||||
static const T instance;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
const T none_instance<T>::instance = T(); // global, but because 'tis a template, no cpp file required
|
||||
|
||||
} } // namespace detail::optional_detail
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
none_t const none = ((none_t)0) ;
|
||||
|
||||
// TU-local
|
||||
const none_t& none = detail::optional_detail::none_instance<none_t>::instance;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
BOOST_INLINE_VARIABLE BOOST_CONSTEXPR_OR_CONST none_t none ((none_t::init_tag()));
|
||||
|
||||
#endif // older definitions
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
||||
#endif // header guard
|
||||
|
@ -1,10 +1,11 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
// Copyright (C) 2014, 2024 Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
// See http://www.boost.org/libs/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
@ -12,13 +13,36 @@
|
||||
#ifndef BOOST_NONE_T_17SEP2003_HPP
|
||||
#define BOOST_NONE_T_17SEP2003_HPP
|
||||
|
||||
namespace boost {
|
||||
#include <boost/config.hpp>
|
||||
|
||||
namespace detail { struct none_helper{}; }
|
||||
#if defined (BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_REF_QUALIFIERS) \
|
||||
|| defined(BOOST_NO_CXX11_LAMBDAS) || defined(BOOST_NO_CXX11_DECLTYPE_N3276) || defined(BOOST_NO_CXX11_NOEXCEPT) || defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || defined(BOOST_NO_CXX11_DEFAULTED_MOVES) || defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
|
||||
|
||||
typedef int detail::none_helper::*none_t ;
|
||||
|
||||
} // namespace boost
|
||||
#error "Boost.Optional requires C++11 or later. If you have an older C++ version use Boost.Optional version 1.86 or earlier."
|
||||
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
#ifdef BOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE
|
||||
|
||||
namespace detail { struct none_helper{}; }
|
||||
typedef int detail::none_helper::*none_t ;
|
||||
|
||||
#elif defined BOOST_OPTIONAL_USE_SINGLETON_DEFINITION_OF_NONE
|
||||
|
||||
class none_t {};
|
||||
|
||||
#else
|
||||
|
||||
struct none_t
|
||||
{
|
||||
struct init_tag{};
|
||||
explicit BOOST_CONSTEXPR none_t(init_tag){} // to disable default constructor
|
||||
};
|
||||
|
||||
#endif // old implementation workarounds
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // header guard
|
||||
|
@ -4,7 +4,7 @@
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
// See http://www.boost.org/libs/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
|
41
include/boost/optional/bad_optional_access.hpp
Normal file
41
include/boost/optional/bad_optional_access.hpp
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright (C) 2014, Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
//
|
||||
#ifndef BOOST_BAD_OPTIONAL_ACCESS_22MAY2014_HPP
|
||||
#define BOOST_BAD_OPTIONAL_ACCESS_22MAY2014_HPP
|
||||
|
||||
#include <stdexcept>
|
||||
#if __cplusplus < 201103L
|
||||
#include <string> // to make converting-ctor std::string(char const*) visible
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
#if defined(__clang__)
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wweak-vtables"
|
||||
#endif
|
||||
|
||||
class bad_optional_access : public std::logic_error
|
||||
{
|
||||
public:
|
||||
bad_optional_access()
|
||||
: std::logic_error("Attempted to access the value of an uninitialized optional object.")
|
||||
{}
|
||||
};
|
||||
|
||||
#if defined(__clang__)
|
||||
# pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
59
include/boost/optional/detail/experimental_traits.hpp
Normal file
59
include/boost/optional/detail/experimental_traits.hpp
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright (C) 2017 Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_EXPERIMENTAL_TRAITS_04NOV2017_HPP
|
||||
#define BOOST_OPTIONAL_DETAIL_EXPERIMENTAL_TRAITS_04NOV2017_HPP
|
||||
|
||||
#include <boost/type_traits.hpp>
|
||||
|
||||
// The condition to use POD implementation
|
||||
|
||||
#ifdef BOOST_OPTIONAL_CONFIG_NO_POD_SPEC
|
||||
# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
|
||||
#elif defined BOOST_OPTIONAL_CONFIG_NO_SPEC_FOR_TRIVIAL_TYPES
|
||||
# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
|
||||
#elif !defined BOOST_HAS_TRIVIAL_MOVE_ASSIGN
|
||||
# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
|
||||
#elif !defined BOOST_HAS_TRIVIAL_MOVE_CONSTRUCTOR
|
||||
# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
|
||||
#elif !defined BOOST_HAS_TRIVIAL_COPY
|
||||
# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
|
||||
#elif !defined BOOST_HAS_TRIVIAL_ASSIGN
|
||||
# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
|
||||
#elif !defined BOOST_HAS_TRIVIAL_DESTRUCTOR
|
||||
# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
|
||||
#endif
|
||||
|
||||
|
||||
namespace boost { namespace optional_detail {
|
||||
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
|
||||
template <typename T>
|
||||
struct is_trivially_semiregular
|
||||
: boost::conditional<(boost::has_trivial_copy_constructor<T>::value &&
|
||||
boost::has_trivial_move_constructor<T>::value &&
|
||||
boost::has_trivial_destructor<T>::value &&
|
||||
boost::has_trivial_move_assign<T>::value &&
|
||||
boost::has_trivial_assign<T>::value),
|
||||
boost::true_type, boost::false_type>::type
|
||||
{};
|
||||
#else
|
||||
template <typename T>
|
||||
struct is_trivially_semiregular
|
||||
: boost::conditional<(boost::is_scalar<T>::value && !boost::is_const<T>::value && !boost::is_volatile<T>::value),
|
||||
boost::true_type, boost::false_type>::type
|
||||
{};
|
||||
#endif
|
||||
|
||||
|
||||
}} // boost::optional_detail
|
||||
|
||||
#endif
|
70
include/boost/optional/detail/optional_aligned_storage.hpp
Normal file
70
include/boost/optional/detail/optional_aligned_storage.hpp
Normal file
@ -0,0 +1,70 @@
|
||||
// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
|
||||
// Copyright (C) 2016 Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
// akrzemi1@gmail.com
|
||||
|
||||
#ifndef BOOST_OPTIONAL_OPTIONAL_DETAIL_OPTIONAL_ALIGNED_STORAGE_AJK_12FEB2016_HPP
|
||||
#define BOOST_OPTIONAL_OPTIONAL_DETAIL_OPTIONAL_ALIGNED_STORAGE_AJK_12FEB2016_HPP
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace optional_detail {
|
||||
// This local class is used instead of that in "aligned_storage.hpp"
|
||||
// because I've found the 'official' class to ICE BCB5.5
|
||||
// when some types are used with optional<>
|
||||
// (due to sizeof() passed down as a non-type template parameter)
|
||||
template <class T>
|
||||
class aligned_storage
|
||||
{
|
||||
// Borland ICEs if unnamed unions are used for this!
|
||||
// BOOST_MAY_ALIAS works around GCC warnings about breaking strict aliasing rules when casting storage address to T*
|
||||
union BOOST_MAY_ALIAS dummy_u
|
||||
{
|
||||
unsigned char data[ sizeof(T) ];
|
||||
BOOST_DEDUCED_TYPENAME type_with_alignment<
|
||||
::boost::alignment_of<T>::value >::type aligner_;
|
||||
} dummy_ ;
|
||||
|
||||
public:
|
||||
|
||||
#if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS)
|
||||
void const* address() const { return &dummy_; }
|
||||
void * address() { return &dummy_; }
|
||||
#else
|
||||
void const* address() const { return dummy_.data; }
|
||||
void * address() { return dummy_.data; }
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS)
|
||||
// This workaround is supposed to silence GCC warnings about broken strict aliasing rules
|
||||
T const* ptr_ref() const
|
||||
{
|
||||
union { void const* ap_pvoid; T const* as_ptype; } caster = { address() };
|
||||
return caster.as_ptype;
|
||||
}
|
||||
T * ptr_ref()
|
||||
{
|
||||
union { void* ap_pvoid; T* as_ptype; } caster = { address() };
|
||||
return caster.as_ptype;
|
||||
}
|
||||
#else
|
||||
T const* ptr_ref() const { return static_cast<T const*>(address()); }
|
||||
T * ptr_ref() { return static_cast<T *> (address()); }
|
||||
#endif
|
||||
|
||||
T const& ref() const { return *boost::core::launder(ptr_ref()); }
|
||||
T & ref() { return *boost::core::launder(ptr_ref()); }
|
||||
} ;
|
||||
|
||||
} // namespace optional_detail
|
||||
} // namespace boost
|
||||
|
||||
#endif // header guard
|
135
include/boost/optional/detail/optional_config.hpp
Normal file
135
include/boost/optional/detail/optional_config.hpp
Normal file
@ -0,0 +1,135 @@
|
||||
// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
|
||||
// Copyright (C) 2015 - 2017 Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_OPTIONAL_CONFIG_AJK_28JAN2015_HPP
|
||||
#define BOOST_OPTIONAL_DETAIL_OPTIONAL_CONFIG_AJK_28JAN2015_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/config/workaround.hpp>
|
||||
|
||||
#if (defined BOOST_NO_CXX11_RVALUE_REFERENCES) || (defined BOOST_OPTIONAL_CONFIG_NO_RVALUE_REFERENCES)
|
||||
# define BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
||||
#endif
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION,<=700)
|
||||
// AFAICT only Intel 7 correctly resolves the overload set
|
||||
// that includes the in-place factory taking functions,
|
||||
// so for the other icc versions, in-place factory support
|
||||
// is disabled
|
||||
# define BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
#endif
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_BORLANDC, <= 0x551)
|
||||
// BCB (5.5.1) cannot parse the nested template struct in an inplace factory.
|
||||
# define BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) \
|
||||
&& defined BOOST_BCB_PARTIAL_SPECIALIZATION_BUG
|
||||
// BCB (up to 5.64) has the following bug:
|
||||
// If there is a member function/operator template of the form
|
||||
// template<class Expr> mfunc( Expr expr ) ;
|
||||
// some calls are resolved to this even if there are other better matches.
|
||||
// The effect of this bug is that calls to converting ctors and assignments
|
||||
// are incorrectly sink to this general catch-all member function template as shown above.
|
||||
# define BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_MAY_ALIAS)
|
||||
// GCC since 3.3 and some other compilers have may_alias attribute that helps to alleviate
|
||||
// optimizer issues with regard to violation of the strict aliasing rules. The optional< T >
|
||||
// storage type is marked with this attribute in order to let the compiler know that it will
|
||||
// alias objects of type T and silence compilation warnings.
|
||||
# define BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS
|
||||
#endif
|
||||
|
||||
#if (defined(_MSC_VER) && _MSC_VER <= 1800)
|
||||
// on MSVC 2013 and earlier an unwanted temporary is created when you assign from
|
||||
// a const lvalue of integral type. Thus we bind not to the original address but
|
||||
// to a temporary.
|
||||
# define BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT
|
||||
#endif
|
||||
|
||||
#if (defined __GNUC__) && (!defined BOOST_INTEL_CXX_VERSION) && (!defined __clang__)
|
||||
// On some GCC versions an unwanted temporary is created when you copy-initialize
|
||||
// from a const lvalue of integral type. Thus we bind not to the original address but
|
||||
// to a temporary.
|
||||
|
||||
# if (__GNUC__ < 4)
|
||||
# define BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT
|
||||
# endif
|
||||
|
||||
# if (__GNUC__ == 4 && __GNUC_MINOR__ <= 5)
|
||||
# define BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT
|
||||
# endif
|
||||
|
||||
# if (__GNUC__ == 5 && __GNUC_MINOR__ < 2)
|
||||
# define BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT
|
||||
# endif
|
||||
|
||||
# if (__GNUC__ == 5 && __GNUC_MINOR__ == 2 && __GNUC_PATCHLEVEL__ == 0)
|
||||
# define BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT
|
||||
# endif
|
||||
|
||||
#endif // defined(__GNUC__)
|
||||
|
||||
#if (defined __GNUC__) && (!defined BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
// On some initial rvalue reference implementations GCC does it in a strange way,
|
||||
// preferring perfect-forwarding constructor to implicit copy constructor.
|
||||
|
||||
# if (__GNUC__ == 4 && __GNUC_MINOR__ == 4)
|
||||
# define BOOST_OPTIONAL_CONFIG_NO_LEGAL_CONVERT_FROM_REF
|
||||
# endif
|
||||
|
||||
# if (__GNUC__ == 4 && __GNUC_MINOR__ == 5)
|
||||
# define BOOST_OPTIONAL_CONFIG_NO_LEGAL_CONVERT_FROM_REF
|
||||
# endif
|
||||
|
||||
#endif // defined(__GNUC__)
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_DECLTYPE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800) && !BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40500) && !defined(__SUNPRO_CC)
|
||||
// this condition is a copy paste from is_constructible.hpp
|
||||
// I also disable SUNPRO, as it seems not to support type_traits correctly
|
||||
#else
|
||||
# define BOOST_OPTIONAL_DETAIL_NO_IS_CONSTRUCTIBLE_TRAIT
|
||||
#endif
|
||||
|
||||
#if defined __SUNPRO_CC
|
||||
# define BOOST_OPTIONAL_DETAIL_NO_SFINAE_FRIENDLY_CONSTRUCTORS
|
||||
#elif (defined _MSC_FULL_VER) && (_MSC_FULL_VER < 190023026)
|
||||
# define BOOST_OPTIONAL_DETAIL_NO_SFINAE_FRIENDLY_CONSTRUCTORS
|
||||
#elif defined BOOST_GCC && !defined BOOST_GCC_CXX11
|
||||
# define BOOST_OPTIONAL_DETAIL_NO_SFINAE_FRIENDLY_CONSTRUCTORS
|
||||
#elif defined BOOST_GCC_VERSION && BOOST_GCC_VERSION < 40800
|
||||
# define BOOST_OPTIONAL_DETAIL_NO_SFINAE_FRIENDLY_CONSTRUCTORS
|
||||
#endif
|
||||
|
||||
|
||||
// Detect support for defaulting move operations
|
||||
// (some older compilers implement rvalue references,
|
||||
// defaulted functions but move operations are not special members and cannot be defaulted)
|
||||
|
||||
#ifdef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
|
||||
# define BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS
|
||||
#elif BOOST_WORKAROUND(BOOST_MSVC, < 1900)
|
||||
# define BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS
|
||||
#elif BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40600)
|
||||
# define BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef BOOST_OPTIONAL_CONFIG_NO_DIRECT_STORAGE_SPEC
|
||||
# define BOOST_OPTIONAL_DETAIL_NO_DIRECT_STORAGE_SPEC
|
||||
#endif
|
||||
|
||||
|
||||
#endif // header guard
|
36
include/boost/optional/detail/optional_factory_support.hpp
Normal file
36
include/boost/optional/detail/optional_factory_support.hpp
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
|
||||
// Copyright (C) 2016 Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
// akrzemi1@gmail.com
|
||||
|
||||
#ifndef BOOST_OPTIONAL_OPTIONAL_DETAIL_OPTIONAL_FACTORY_SUPPORT_AJK_12FEB2016_HPP
|
||||
#define BOOST_OPTIONAL_OPTIONAL_DETAIL_OPTIONAL_FACTORY_SUPPORT_AJK_12FEB2016_HPP
|
||||
|
||||
// Daniel Wallin discovered that bind/apply.hpp badly interacts with the apply<>
|
||||
// member template of a factory as used in the optional<> implementation.
|
||||
// He proposed this simple fix which is to move the call to apply<> outside
|
||||
// namespace boost.
|
||||
namespace boost_optional_detail
|
||||
{
|
||||
template <class T, class Factory>
|
||||
inline void construct(Factory const& factory, void* address)
|
||||
{
|
||||
factory.BOOST_NESTED_TEMPLATE apply<T>(address);
|
||||
}
|
||||
}
|
||||
|
||||
namespace boost
|
||||
{
|
||||
class in_place_factory_base ;
|
||||
class typed_in_place_factory_base ;
|
||||
}
|
||||
|
||||
#endif // header guard
|
49
include/boost/optional/detail/optional_hash.hpp
Normal file
49
include/boost/optional/detail/optional_hash.hpp
Normal file
@ -0,0 +1,49 @@
|
||||
// Copyright (C) 2022 Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_OPTIONAL_HASH_AJK_20MAY2022_HPP
|
||||
#define BOOST_OPTIONAL_DETAIL_OPTIONAL_HASH_AJK_20MAY2022_HPP
|
||||
|
||||
#include <boost/optional/optional_fwd.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if !defined(BOOST_OPTIONAL_CONFIG_DO_NOT_SPECIALIZE_STD_HASH) && !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <typename T>
|
||||
struct hash<boost::optional<T> >
|
||||
{
|
||||
typedef std::size_t result_type;
|
||||
typedef boost::optional<T> argument_type;
|
||||
|
||||
BOOST_CONSTEXPR result_type operator()(const argument_type& arg) const {
|
||||
return arg ? std::hash<T>()(*arg) : result_type();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct hash<boost::optional<T&> >
|
||||
{
|
||||
typedef std::size_t result_type;
|
||||
typedef boost::optional<T&> argument_type;
|
||||
|
||||
BOOST_CONSTEXPR result_type operator()(const argument_type& arg) const {
|
||||
return arg ? std::hash<T>()(*arg) : result_type();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // !defined(BOOST_OPTIONAL_CONFIG_DO_NOT_SPECIALIZE_STD_HASH) && !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
|
||||
|
||||
#endif // header guard
|
280
include/boost/optional/detail/optional_reference_spec.hpp
Normal file
280
include/boost/optional/detail/optional_reference_spec.hpp
Normal file
@ -0,0 +1,280 @@
|
||||
// Copyright (C) 2015-2024 Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_OPTIONAL_REFERENCE_SPEC_AJK_03OCT2015_HPP
|
||||
#define BOOST_OPTIONAL_DETAIL_OPTIONAL_REFERENCE_SPEC_AJK_03OCT2015_HPP
|
||||
|
||||
#ifdef BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT
|
||||
#include <boost/type_traits/is_integral.hpp>
|
||||
#include <boost/type_traits/is_const.hpp>
|
||||
#endif
|
||||
|
||||
# if 1
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
||||
|
||||
template <class From>
|
||||
void prevent_binding_rvalue()
|
||||
{
|
||||
#ifndef BOOST_OPTIONAL_CONFIG_ALLOW_BINDING_TO_RVALUES
|
||||
BOOST_STATIC_ASSERT_MSG(boost::is_lvalue_reference<From>::value,
|
||||
"binding rvalue references to optional lvalue references is disallowed");
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T>
|
||||
BOOST_DEDUCED_TYPENAME boost::remove_reference<T>::type& forward_reference(T&& r)
|
||||
{
|
||||
BOOST_STATIC_ASSERT_MSG(boost::is_lvalue_reference<T>::value,
|
||||
"binding rvalue references to optional lvalue references is disallowed");
|
||||
return boost::forward<T>(r);
|
||||
}
|
||||
|
||||
#endif // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
||||
|
||||
|
||||
template <class T>
|
||||
struct is_const_integral
|
||||
{
|
||||
static const bool value = boost::is_const<T>::value && boost::is_integral<T>::value;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_const_integral_bad_for_conversion
|
||||
{
|
||||
#if (!defined BOOST_OPTIONAL_CONFIG_ALLOW_BINDING_TO_RVALUES) && (defined BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT)
|
||||
static const bool value = boost::is_const<T>::value && boost::is_integral<T>::value;
|
||||
#else
|
||||
static const bool value = false;
|
||||
#endif
|
||||
};
|
||||
|
||||
template <class From>
|
||||
void prevent_assignment_from_false_const_integral()
|
||||
{
|
||||
#ifndef BOOST_OPTIONAL_CONFIG_ALLOW_BINDING_TO_RVALUES
|
||||
#ifdef BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT
|
||||
// MSVC compiler without rvalue references: we need to disable the assignment from
|
||||
// const integral lvalue reference, as it may be an invalid temporary
|
||||
BOOST_STATIC_ASSERT_MSG(!is_const_integral<From>::value,
|
||||
"binding const lvalue references to integral types is disabled in this compiler");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
struct is_optional_
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template <class U>
|
||||
struct is_optional_< ::boost::optional<U> >
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_no_optional
|
||||
{
|
||||
static const bool value = !is_optional_<BOOST_DEDUCED_TYPENAME boost::decay<T>::type>::value;
|
||||
};
|
||||
|
||||
|
||||
template <class T, class U>
|
||||
struct is_same_decayed
|
||||
{
|
||||
static const bool value = ::boost::is_same<T, BOOST_DEDUCED_TYPENAME ::boost::remove_reference<U>::type>::value
|
||||
|| ::boost::is_same<T, const BOOST_DEDUCED_TYPENAME ::boost::remove_reference<U>::type>::value;
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
struct no_unboxing_cond
|
||||
{
|
||||
static const bool value = is_no_optional<U>::value && !is_same_decayed<T, U>::value;
|
||||
};
|
||||
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T>
|
||||
class optional<T&> : public optional_detail::optional_tag
|
||||
{
|
||||
T* ptr_;
|
||||
|
||||
public:
|
||||
typedef T& value_type;
|
||||
typedef T& reference_type;
|
||||
typedef T& reference_const_type;
|
||||
typedef T& rval_reference_type;
|
||||
typedef T* pointer_type;
|
||||
typedef T* pointer_const_type;
|
||||
|
||||
optional() BOOST_NOEXCEPT : ptr_() {}
|
||||
optional(none_t) BOOST_NOEXCEPT : ptr_() {}
|
||||
|
||||
template <class U>
|
||||
explicit optional(const optional<U&>& rhs) BOOST_NOEXCEPT : ptr_(rhs.get_ptr()) {}
|
||||
optional(const optional& rhs) BOOST_NOEXCEPT : ptr_(rhs.get_ptr()) {}
|
||||
|
||||
// the following two implement a 'conditionally explicit' constructor: condition is a hack for buggy compilers with screwed conversion construction from const int
|
||||
template <class U>
|
||||
explicit optional(U& rhs, BOOST_DEDUCED_TYPENAME boost::enable_if_c<detail::is_same_decayed<T, U>::value && detail::is_const_integral_bad_for_conversion<U>::value, bool>::type = true) BOOST_NOEXCEPT
|
||||
: ptr_(boost::addressof(rhs)) {}
|
||||
|
||||
template <class U>
|
||||
optional(U& rhs, BOOST_DEDUCED_TYPENAME boost::enable_if_c<detail::is_same_decayed<T, U>::value && !detail::is_const_integral_bad_for_conversion<U>::value, bool>::type = true) BOOST_NOEXCEPT
|
||||
: ptr_(boost::addressof(rhs)) {}
|
||||
|
||||
optional& operator=(const optional& rhs) BOOST_NOEXCEPT { ptr_ = rhs.get_ptr(); return *this; }
|
||||
template <class U>
|
||||
optional& operator=(const optional<U&>& rhs) BOOST_NOEXCEPT { ptr_ = rhs.get_ptr(); return *this; }
|
||||
optional& operator=(none_t) BOOST_NOEXCEPT { ptr_ = 0; return *this; }
|
||||
|
||||
|
||||
void swap(optional& rhs) BOOST_NOEXCEPT { std::swap(ptr_, rhs.ptr_); }
|
||||
T& get() const { BOOST_ASSERT(ptr_); return *ptr_; }
|
||||
|
||||
T* get_ptr() const BOOST_NOEXCEPT { return ptr_; }
|
||||
T* operator->() const { BOOST_ASSERT(ptr_); return ptr_; }
|
||||
T& operator*() const { BOOST_ASSERT(ptr_); return *ptr_; }
|
||||
|
||||
T& value() const
|
||||
{
|
||||
if (this->is_initialized())
|
||||
return this->get();
|
||||
else
|
||||
throw_exception(bad_optional_access());
|
||||
}
|
||||
|
||||
explicit operator bool() const BOOST_NOEXCEPT { return ptr_ != 0; }
|
||||
|
||||
void reset() BOOST_NOEXCEPT { ptr_ = 0; }
|
||||
|
||||
bool is_initialized() const BOOST_NOEXCEPT { return ptr_ != 0; }
|
||||
bool has_value() const BOOST_NOEXCEPT { return ptr_ != 0; }
|
||||
|
||||
template <typename F>
|
||||
optional<typename optional_detail::result_of<F, reference_const_type>::type>
|
||||
map(F f) const
|
||||
{
|
||||
if (this->has_value())
|
||||
return f(this->get());
|
||||
else
|
||||
return none;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
optional<typename optional_detail::result_value_type<F, reference_const_type>::type>
|
||||
flat_map(F f) const
|
||||
{
|
||||
if (this->has_value())
|
||||
return f(get());
|
||||
else
|
||||
return none;
|
||||
}
|
||||
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
||||
|
||||
optional(T&& /* rhs */) BOOST_NOEXCEPT { detail::prevent_binding_rvalue<T&&>(); }
|
||||
|
||||
template <class R>
|
||||
optional(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::no_unboxing_cond<T, R>, bool>::type = true) BOOST_NOEXCEPT
|
||||
: ptr_(boost::addressof(r)) { detail::prevent_binding_rvalue<R>(); }
|
||||
|
||||
template <class R>
|
||||
optional(bool cond, R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<R>, bool>::type = true) BOOST_NOEXCEPT
|
||||
: ptr_(cond ? boost::addressof(r) : 0) { detail::prevent_binding_rvalue<R>(); }
|
||||
|
||||
template <class R>
|
||||
BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<R>, optional<T&>&>::type
|
||||
operator=(R&& r) BOOST_NOEXCEPT { detail::prevent_binding_rvalue<R>(); ptr_ = boost::addressof(r); return *this; }
|
||||
|
||||
template <class R>
|
||||
void emplace(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<R>, bool>::type = true) BOOST_NOEXCEPT
|
||||
{ detail::prevent_binding_rvalue<R>(); ptr_ = boost::addressof(r); }
|
||||
|
||||
template <class R>
|
||||
T& get_value_or(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<R>, bool>::type = true) const BOOST_NOEXCEPT
|
||||
{ detail::prevent_binding_rvalue<R>(); return ptr_ ? *ptr_ : r; }
|
||||
|
||||
template <class R>
|
||||
T& value_or(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<R>, bool>::type = true) const BOOST_NOEXCEPT
|
||||
{ detail::prevent_binding_rvalue<R>(); return ptr_ ? *ptr_ : r; }
|
||||
|
||||
template <class R>
|
||||
void reset(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<R>, bool>::type = true) BOOST_NOEXCEPT
|
||||
{ detail::prevent_binding_rvalue<R>(); ptr_ = boost::addressof(r); }
|
||||
|
||||
template <class F>
|
||||
T& value_or_eval(F f) const { return ptr_ ? *ptr_ : detail::forward_reference(f()); }
|
||||
|
||||
#else // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
||||
|
||||
|
||||
// the following two implement a 'conditionally explicit' constructor
|
||||
template <class U>
|
||||
explicit optional(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if_c<detail::no_unboxing_cond<T, U>::value && detail::is_const_integral_bad_for_conversion<U>::value, bool>::type = true) BOOST_NOEXCEPT
|
||||
: ptr_(boost::addressof(v)) { }
|
||||
|
||||
template <class U>
|
||||
optional(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if_c<detail::no_unboxing_cond<T, U>::value && !detail::is_const_integral_bad_for_conversion<U>::value, bool>::type = true) BOOST_NOEXCEPT
|
||||
: ptr_(boost::addressof(v)) { }
|
||||
|
||||
template <class U>
|
||||
optional(bool cond, U& v, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<U>, bool>::type = true) BOOST_NOEXCEPT : ptr_(cond ? boost::addressof(v) : 0) {}
|
||||
|
||||
template <class U>
|
||||
BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<U>, optional<T&>&>::type
|
||||
operator=(U& v) BOOST_NOEXCEPT
|
||||
{
|
||||
detail::prevent_assignment_from_false_const_integral<U>();
|
||||
ptr_ = boost::addressof(v); return *this;
|
||||
}
|
||||
|
||||
template <class U>
|
||||
void emplace(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<U>, bool>::type = true) BOOST_NOEXCEPT
|
||||
{ ptr_ = boost::addressof(v); }
|
||||
|
||||
template <class U>
|
||||
T& get_value_or(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<U>, bool>::type = true) const BOOST_NOEXCEPT
|
||||
{ return ptr_ ? *ptr_ : v; }
|
||||
|
||||
template <class U>
|
||||
T& value_or(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<U>, bool>::type = true) const BOOST_NOEXCEPT
|
||||
{ return ptr_ ? *ptr_ : v; }
|
||||
|
||||
template <class U>
|
||||
void reset(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<U>, bool>::type = true) BOOST_NOEXCEPT
|
||||
{ ptr_ = boost::addressof(v); }
|
||||
|
||||
template <class F>
|
||||
T& value_or_eval(F f) const { return ptr_ ? *ptr_ : f(); }
|
||||
|
||||
#endif // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void swap ( optional<T&>& x, optional<T&>& y) BOOST_NOEXCEPT
|
||||
{
|
||||
x.swap(y);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // 1/0
|
||||
|
||||
#endif // header guard
|
196
include/boost/optional/detail/optional_relops.hpp
Normal file
196
include/boost/optional/detail/optional_relops.hpp
Normal file
@ -0,0 +1,196 @@
|
||||
// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
|
||||
// Copyright (C) 2015, 2024 Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_OPTIONAL_RELOPS_AJK_03OCT2015_HPP
|
||||
#define BOOST_OPTIONAL_DETAIL_OPTIONAL_RELOPS_AJK_03OCT2015_HPP
|
||||
|
||||
namespace boost {
|
||||
|
||||
// optional's relational operators ( ==, !=, <, >, <=, >= ) have deep-semantics (compare values).
|
||||
// WARNING: This is UNLIKE pointers. Use equal_pointees()/less_pointees() in generic code instead,
|
||||
// to obtain the same semantic for pointers.
|
||||
|
||||
|
||||
//
|
||||
// optional<T> vs optional<T> cases
|
||||
//
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator == ( optional<T> const& x, optional<T> const& y )
|
||||
{ return bool(x) && bool(y) ? *x == *y : bool(x) == bool(y); }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator < ( optional<T> const& x, optional<T> const& y )
|
||||
{ return !y ? false : (!x ? true : (*x) < (*y)); }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator != ( optional<T> const& x, optional<T> const& y )
|
||||
{ return !( x == y ) ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator > ( optional<T> const& x, optional<T> const& y )
|
||||
{ return y < x ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator <= ( optional<T> const& x, optional<T> const& y )
|
||||
{ return !( y < x ) ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator >= ( optional<T> const& x, optional<T> const& y )
|
||||
{ return !( x < y ) ; }
|
||||
|
||||
|
||||
//
|
||||
// optional<T> vs T cases
|
||||
//
|
||||
template<class T>
|
||||
inline
|
||||
bool operator == ( optional<T> const& x, T const& y )
|
||||
{ return x && (*x == y); }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator < ( optional<T> const& x, T const& y )
|
||||
{ return (!x) || (*x < y); }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator != ( optional<T> const& x, T const& y )
|
||||
{ return !( x == y ) ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator > ( optional<T> const& x, T const& y )
|
||||
{ return y < x ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator <= ( optional<T> const& x, T const& y )
|
||||
{ return !( y < x ) ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator >= ( optional<T> const& x, T const& y )
|
||||
{ return !( x < y ) ; }
|
||||
|
||||
//
|
||||
// T vs optional<T> cases
|
||||
//
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator == ( T const& x, optional<T> const& y )
|
||||
{ return y && (x == *y); }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator < ( T const& x, optional<T> const& y )
|
||||
{ return y && (x < *y); }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator != ( T const& x, optional<T> const& y )
|
||||
{ return !( x == y ) ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator > ( T const& x, optional<T> const& y )
|
||||
{ return y < x ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator <= ( T const& x, optional<T> const& y )
|
||||
{ return !( y < x ) ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator >= ( T const& x, optional<T> const& y )
|
||||
{ return !( x < y ) ; }
|
||||
|
||||
|
||||
//
|
||||
// optional<T> vs none cases
|
||||
//
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator == ( optional<T> const& x, none_t ) BOOST_NOEXCEPT
|
||||
{ return !x; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator < ( optional<T> const&, none_t )
|
||||
{ return false; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator != ( optional<T> const& x, none_t ) BOOST_NOEXCEPT
|
||||
{ return bool(x); }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator > ( optional<T> const& x, none_t y )
|
||||
{ return y < x ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator <= ( optional<T> const& x, none_t y )
|
||||
{ return !( y < x ) ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator >= ( optional<T> const& x, none_t y )
|
||||
{ return !( x < y ) ; }
|
||||
|
||||
//
|
||||
// none vs optional<T> cases
|
||||
//
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator == ( none_t , optional<T> const& y ) BOOST_NOEXCEPT
|
||||
{ return !y; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator < ( none_t , optional<T> const& y )
|
||||
{ return bool(y); }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator != ( none_t, optional<T> const& y ) BOOST_NOEXCEPT
|
||||
{ return bool(y); }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator > ( none_t x, optional<T> const& y )
|
||||
{ return y < x ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator <= ( none_t x, optional<T> const& y )
|
||||
{ return !( y < x ) ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator >= ( none_t x, optional<T> const& y )
|
||||
{ return !( x < y ) ; }
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // header guard
|
117
include/boost/optional/detail/optional_swap.hpp
Normal file
117
include/boost/optional/detail/optional_swap.hpp
Normal file
@ -0,0 +1,117 @@
|
||||
// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
|
||||
// Copyright (C) 2015 Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_OPTIONAL_SWAP_AJK_28JAN2015_HPP
|
||||
#define BOOST_OPTIONAL_DETAIL_OPTIONAL_SWAP_AJK_28JAN2015_HPP
|
||||
|
||||
#include <boost/core/invoke_swap.hpp>
|
||||
#include <boost/optional/optional_fwd.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace optional_detail {
|
||||
|
||||
template <bool use_default_constructor> struct swap_selector;
|
||||
|
||||
template <>
|
||||
struct swap_selector<true>
|
||||
{
|
||||
template <class T>
|
||||
static void optional_swap ( optional<T>& x, optional<T>& y )
|
||||
{
|
||||
const bool hasX = !!x;
|
||||
const bool hasY = !!y;
|
||||
|
||||
if ( !hasX && !hasY )
|
||||
return;
|
||||
|
||||
if( !hasX )
|
||||
x.emplace();
|
||||
else if ( !hasY )
|
||||
y.emplace();
|
||||
|
||||
// Boost.Core.Swap will take care of ADL and workarounds for broken compilers
|
||||
boost::core::invoke_swap(x.get(), y.get());
|
||||
|
||||
if( !hasX )
|
||||
y = boost::none ;
|
||||
else if( !hasY )
|
||||
x = boost::none ;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef BOOST_OPTIONAL_DETAIL_MOVE
|
||||
# undef BOOST_OPTIONAL_DETAIL_MOVE
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
||||
# define BOOST_OPTIONAL_DETAIL_MOVE(EXPR_) boost::move(EXPR_)
|
||||
#else
|
||||
# define BOOST_OPTIONAL_DETAIL_MOVE(EXPR_) EXPR_
|
||||
#endif
|
||||
|
||||
template <>
|
||||
struct swap_selector<false>
|
||||
{
|
||||
template <class T>
|
||||
static void optional_swap ( optional<T>& x, optional<T>& y )
|
||||
//BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && BOOST_NOEXCEPT_EXPR(boost::core::invoke_swap(*x, *y)))
|
||||
{
|
||||
if (x)
|
||||
{
|
||||
if (y)
|
||||
{
|
||||
boost::core::invoke_swap(*x, *y);
|
||||
}
|
||||
else
|
||||
{
|
||||
y = BOOST_OPTIONAL_DETAIL_MOVE(*x);
|
||||
x = boost::none;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (y)
|
||||
{
|
||||
x = BOOST_OPTIONAL_DETAIL_MOVE(*y);
|
||||
y = boost::none;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace optional_detail
|
||||
|
||||
#if (!defined BOOST_NO_CXX11_RVALUE_REFERENCES) && (!defined BOOST_CONFIG_RESTORE_OBSOLETE_SWAP_IMPLEMENTATION)
|
||||
|
||||
template<class T>
|
||||
struct optional_swap_should_use_default_constructor : boost::false_type {} ;
|
||||
|
||||
#else
|
||||
|
||||
template<class T>
|
||||
struct optional_swap_should_use_default_constructor : has_nothrow_default_constructor<T> {} ;
|
||||
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
inline void swap ( optional<T>& x, optional<T>& y )
|
||||
//BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && BOOST_NOEXCEPT_EXPR(boost::core::invoke_swap(*x, *y)))
|
||||
{
|
||||
optional_detail::swap_selector<optional_swap_should_use_default_constructor<T>::value>::optional_swap(x, y);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#undef BOOST_OPTIONAL_DETAIL_MOVE
|
||||
|
||||
#endif // header guard
|
@ -0,0 +1,510 @@
|
||||
// Copyright (C) 2017 Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
|
||||
// trivially-copyable version of the storage
|
||||
|
||||
template<class T>
|
||||
class tc_optional_base : public optional_tag
|
||||
{
|
||||
private :
|
||||
|
||||
typedef tc_optional_base<T> this_type ;
|
||||
|
||||
protected :
|
||||
|
||||
typedef T value_type ;
|
||||
|
||||
protected:
|
||||
typedef T & reference_type ;
|
||||
typedef T const& reference_const_type ;
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
||||
typedef T && rval_reference_type ;
|
||||
typedef T && reference_type_of_temporary_wrapper ;
|
||||
#endif
|
||||
typedef T * pointer_type ;
|
||||
typedef T const* pointer_const_type ;
|
||||
typedef T const& argument_type ;
|
||||
|
||||
tc_optional_base()
|
||||
:
|
||||
m_initialized(false), m_storage() {}
|
||||
|
||||
tc_optional_base ( none_t )
|
||||
:
|
||||
m_initialized(false), m_storage() {}
|
||||
|
||||
tc_optional_base ( init_value_tag, argument_type val )
|
||||
:
|
||||
m_initialized(true), m_storage(val) {}
|
||||
|
||||
tc_optional_base ( bool cond, argument_type val )
|
||||
:
|
||||
m_initialized(cond), m_storage(val) {}
|
||||
|
||||
// tc_optional_base ( tc_optional_base const& ) = default;
|
||||
|
||||
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
||||
|
||||
template<class Expr, class PtrExpr>
|
||||
explicit tc_optional_base ( Expr&& expr, PtrExpr const* tag )
|
||||
:
|
||||
m_initialized(false)
|
||||
{
|
||||
construct(boost::forward<Expr>(expr),tag);
|
||||
}
|
||||
|
||||
#else
|
||||
// This is used for both converting and in-place constructions.
|
||||
// Derived classes use the 'tag' to select the appropriate
|
||||
// implementation (the correct 'construct()' overload)
|
||||
template<class Expr>
|
||||
explicit tc_optional_base ( Expr const& expr, Expr const* tag )
|
||||
:
|
||||
m_initialized(false)
|
||||
{
|
||||
construct(expr,tag);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// tc_optional_base& operator= ( tc_optional_base const& ) = default;
|
||||
// ~tc_optional_base() = default;
|
||||
|
||||
// Assigns from another optional<T> (deep-copies the rhs value)
|
||||
void assign ( tc_optional_base const& rhs )
|
||||
{
|
||||
*this = rhs;
|
||||
}
|
||||
|
||||
// Assigns from another _convertible_ optional<U> (deep-copies the rhs value)
|
||||
template<class U>
|
||||
void assign ( optional<U> const& rhs )
|
||||
{
|
||||
if ( rhs.is_initialized() )
|
||||
#ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES
|
||||
m_storage = rhs.get();
|
||||
#else
|
||||
m_storage = static_cast<value_type>(rhs.get());
|
||||
#endif
|
||||
|
||||
m_initialized = rhs.is_initialized();
|
||||
}
|
||||
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
||||
// move-assigns from another _convertible_ optional<U> (deep-moves from the rhs value)
|
||||
template<class U>
|
||||
void assign ( optional<U>&& rhs )
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME optional<U>::rval_reference_type ref_type;
|
||||
if ( rhs.is_initialized() )
|
||||
m_storage = static_cast<ref_type>(rhs.get());
|
||||
m_initialized = rhs.is_initialized();
|
||||
}
|
||||
#endif
|
||||
|
||||
void assign ( argument_type val )
|
||||
{
|
||||
construct(val);
|
||||
}
|
||||
|
||||
void assign ( none_t ) { destroy(); }
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
||||
template<class Expr, class ExprPtr>
|
||||
void assign_expr ( Expr&& expr, ExprPtr const* tag )
|
||||
{
|
||||
construct(boost::forward<Expr>(expr),tag);
|
||||
}
|
||||
#else
|
||||
template<class Expr>
|
||||
void assign_expr ( Expr const& expr, Expr const* tag )
|
||||
{
|
||||
construct(expr,tag);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
public :
|
||||
|
||||
// Destroys the current value, if any, leaving this UNINITIALIZED
|
||||
// No-throw (assuming T::~T() doesn't)
|
||||
void reset() BOOST_NOEXCEPT { destroy(); }
|
||||
|
||||
// **DEPRECATED** Replaces the current value -if any- with 'val'
|
||||
void reset ( argument_type val ) BOOST_NOEXCEPT { assign(val); }
|
||||
|
||||
// Returns a pointer to the value if this is initialized, otherwise,
|
||||
// returns NULL.
|
||||
// No-throw
|
||||
pointer_const_type get_ptr() const { return m_initialized ? get_ptr_impl() : 0 ; }
|
||||
pointer_type get_ptr() { return m_initialized ? get_ptr_impl() : 0 ; }
|
||||
|
||||
bool is_initialized() const { return m_initialized ; }
|
||||
|
||||
protected :
|
||||
|
||||
void construct ( argument_type val )
|
||||
{
|
||||
m_storage = val ;
|
||||
m_initialized = true ;
|
||||
}
|
||||
|
||||
|
||||
#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
// Constructs in-place
|
||||
// upon exception *this is always uninitialized
|
||||
template<class... Args>
|
||||
void construct ( in_place_init_t, Args&&... args )
|
||||
{
|
||||
m_storage = value_type( boost::forward<Args>(args)... ) ;
|
||||
m_initialized = true ;
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
void emplace_assign ( Args&&... args )
|
||||
{
|
||||
construct(in_place_init, boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
explicit tc_optional_base ( in_place_init_t, Args&&... args )
|
||||
:
|
||||
m_initialized(false)
|
||||
{
|
||||
construct(in_place_init, boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
explicit tc_optional_base ( in_place_init_if_t, bool cond, Args&&... args )
|
||||
:
|
||||
m_initialized(false)
|
||||
{
|
||||
if ( cond )
|
||||
construct(in_place_init, boost::forward<Args>(args)...);
|
||||
}
|
||||
#elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
|
||||
template<class Arg>
|
||||
void construct ( in_place_init_t, Arg&& arg )
|
||||
{
|
||||
m_storage = value_type( boost::forward<Arg>(arg) );
|
||||
m_initialized = true ;
|
||||
}
|
||||
|
||||
void construct ( in_place_init_t )
|
||||
{
|
||||
m_storage = value_type();
|
||||
m_initialized = true ;
|
||||
}
|
||||
|
||||
template<class Arg>
|
||||
void emplace_assign ( Arg&& arg )
|
||||
{
|
||||
construct(in_place_init, boost::forward<Arg>(arg)) ;
|
||||
}
|
||||
|
||||
void emplace_assign ()
|
||||
{
|
||||
construct(in_place_init) ;
|
||||
}
|
||||
|
||||
template<class Arg>
|
||||
explicit tc_optional_base ( in_place_init_t, Arg&& arg )
|
||||
:
|
||||
m_initialized(false)
|
||||
{
|
||||
construct(in_place_init, boost::forward<Arg>(arg));
|
||||
}
|
||||
|
||||
explicit tc_optional_base ( in_place_init_t )
|
||||
:
|
||||
m_initialized(false), m_storage() {}
|
||||
|
||||
template<class Arg>
|
||||
explicit tc_optional_base ( in_place_init_if_t, bool cond, Arg&& arg )
|
||||
:
|
||||
m_initialized(false)
|
||||
{
|
||||
if ( cond )
|
||||
construct(in_place_init, boost::forward<Arg>(arg));
|
||||
}
|
||||
|
||||
explicit tc_optional_base ( in_place_init_if_t, bool cond )
|
||||
:
|
||||
m_initialized(false)
|
||||
{
|
||||
if ( cond )
|
||||
construct(in_place_init);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template<class Arg>
|
||||
void construct ( in_place_init_t, const Arg& arg )
|
||||
{
|
||||
m_storage = value_type( arg );
|
||||
m_initialized = true ;
|
||||
}
|
||||
|
||||
template<class Arg>
|
||||
void construct ( in_place_init_t, Arg& arg )
|
||||
{
|
||||
m_storage = value_type( arg );
|
||||
m_initialized = true ;
|
||||
}
|
||||
|
||||
void construct ( in_place_init_t )
|
||||
{
|
||||
m_storage = value_type();
|
||||
m_initialized = true ;
|
||||
}
|
||||
|
||||
template<class Arg>
|
||||
void emplace_assign ( const Arg& arg )
|
||||
{
|
||||
construct(in_place_init, arg);
|
||||
}
|
||||
|
||||
template<class Arg>
|
||||
void emplace_assign ( Arg& arg )
|
||||
{
|
||||
construct(in_place_init, arg);
|
||||
}
|
||||
|
||||
void emplace_assign ()
|
||||
{
|
||||
construct(in_place_init);
|
||||
}
|
||||
|
||||
template<class Arg>
|
||||
explicit tc_optional_base ( in_place_init_t, const Arg& arg )
|
||||
: m_initialized(false)
|
||||
{
|
||||
construct(in_place_init, arg);
|
||||
}
|
||||
|
||||
template<class Arg>
|
||||
explicit tc_optional_base ( in_place_init_t, Arg& arg )
|
||||
: m_initialized(false)
|
||||
{
|
||||
construct(in_place_init, arg);
|
||||
}
|
||||
|
||||
explicit tc_optional_base ( in_place_init_t )
|
||||
: m_initialized(false)
|
||||
{
|
||||
construct(in_place_init);
|
||||
}
|
||||
|
||||
template<class Arg>
|
||||
explicit tc_optional_base ( in_place_init_if_t, bool cond, const Arg& arg )
|
||||
: m_initialized(false)
|
||||
{
|
||||
if ( cond )
|
||||
construct(in_place_init, arg);
|
||||
}
|
||||
|
||||
template<class Arg>
|
||||
explicit tc_optional_base ( in_place_init_if_t, bool cond, Arg& arg )
|
||||
: m_initialized(false)
|
||||
{
|
||||
if ( cond )
|
||||
construct(in_place_init, arg);
|
||||
}
|
||||
|
||||
explicit tc_optional_base ( in_place_init_if_t, bool cond )
|
||||
: m_initialized(false)
|
||||
{
|
||||
if ( cond )
|
||||
construct(in_place_init);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
||||
// Constructs in-place using the given factory
|
||||
template<class Expr>
|
||||
void construct ( Expr&& factory, in_place_factory_base const* )
|
||||
{
|
||||
boost_optional_detail::construct<value_type>(factory, boost::addressof(m_storage));
|
||||
m_initialized = true ;
|
||||
}
|
||||
|
||||
// Constructs in-place using the given typed factory
|
||||
template<class Expr>
|
||||
void construct ( Expr&& factory, typed_in_place_factory_base const* )
|
||||
{
|
||||
factory.apply(boost::addressof(m_storage)) ;
|
||||
m_initialized = true ;
|
||||
}
|
||||
|
||||
template<class Expr>
|
||||
void assign_expr_to_initialized ( Expr&& factory, in_place_factory_base const* tag )
|
||||
{
|
||||
destroy();
|
||||
construct(factory,tag);
|
||||
}
|
||||
|
||||
// Constructs in-place using the given typed factory
|
||||
template<class Expr>
|
||||
void assign_expr_to_initialized ( Expr&& factory, typed_in_place_factory_base const* tag )
|
||||
{
|
||||
destroy();
|
||||
construct(factory,tag);
|
||||
}
|
||||
|
||||
#else
|
||||
// Constructs in-place using the given factory
|
||||
template<class Expr>
|
||||
void construct ( Expr const& factory, in_place_factory_base const* )
|
||||
{
|
||||
boost_optional_detail::construct<value_type>(factory, boost::addressof(m_storage));
|
||||
m_initialized = true ;
|
||||
}
|
||||
|
||||
// Constructs in-place using the given typed factory
|
||||
template<class Expr>
|
||||
void construct ( Expr const& factory, typed_in_place_factory_base const* )
|
||||
{
|
||||
factory.apply(boost::addressof(m_storage)) ;
|
||||
m_initialized = true ;
|
||||
}
|
||||
|
||||
template<class Expr>
|
||||
void assign_expr_to_initialized ( Expr const& factory, in_place_factory_base const* tag )
|
||||
{
|
||||
destroy();
|
||||
construct(factory,tag);
|
||||
}
|
||||
|
||||
// Constructs in-place using the given typed factory
|
||||
template<class Expr>
|
||||
void assign_expr_to_initialized ( Expr const& factory, typed_in_place_factory_base const* tag )
|
||||
{
|
||||
destroy();
|
||||
construct(factory,tag);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
||||
// Constructs using any expression implicitly convertible to the single argument
|
||||
// of a one-argument T constructor.
|
||||
// Converting constructions of optional<T> from optional<U> uses this function with
|
||||
// 'Expr' being of type 'U' and relying on a converting constructor of T from U.
|
||||
template<class Expr>
|
||||
void construct ( Expr&& expr, void const* )
|
||||
{
|
||||
m_storage = value_type(boost::forward<Expr>(expr)) ;
|
||||
m_initialized = true ;
|
||||
}
|
||||
|
||||
// Assigns using a form any expression implicitly convertible to the single argument
|
||||
// of a T's assignment operator.
|
||||
// Converting assignments of optional<T> from optional<U> uses this function with
|
||||
// 'Expr' being of type 'U' and relying on a converting assignment of T from U.
|
||||
template<class Expr>
|
||||
void assign_expr_to_initialized ( Expr&& expr, void const* )
|
||||
{
|
||||
assign_value( boost::forward<Expr>(expr) );
|
||||
}
|
||||
#else
|
||||
// Constructs using any expression implicitly convertible to the single argument
|
||||
// of a one-argument T constructor.
|
||||
// Converting constructions of optional<T> from optional<U> uses this function with
|
||||
// 'Expr' being of type 'U' and relying on a converting constructor of T from U.
|
||||
template<class Expr>
|
||||
void construct ( Expr const& expr, void const* )
|
||||
{
|
||||
m_storage = value_type(expr) ;
|
||||
m_initialized = true ;
|
||||
}
|
||||
|
||||
// Assigns using a form any expression implicitly convertible to the single argument
|
||||
// of a T's assignment operator.
|
||||
// Converting assignments of optional<T> from optional<U> uses this function with
|
||||
// 'Expr' being of type 'U' and relying on a converting assignment of T from U.
|
||||
template<class Expr>
|
||||
void assign_expr_to_initialized ( Expr const& expr, void const* )
|
||||
{
|
||||
assign_value(expr);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
|
||||
// BCB5.64 (and probably lower versions) workaround.
|
||||
// The in-place factories are supported by means of catch-all constructors
|
||||
// and assignment operators (the functions are parameterized in terms of
|
||||
// an arbitrary 'Expr' type)
|
||||
// This compiler incorrectly resolves the overload set and sinks optional<T> and optional<U>
|
||||
// to the 'Expr'-taking functions even though explicit overloads are present for them.
|
||||
// Thus, the following overload is needed to properly handle the case when the 'lhs'
|
||||
// is another optional.
|
||||
//
|
||||
// For VC<=70 compilers this workaround doesn't work because the compiler issues and error
|
||||
// instead of choosing the wrong overload
|
||||
//
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
||||
// Notice that 'Expr' will be optional<T> or optional<U> (but not tc_optional_base<..>)
|
||||
template<class Expr>
|
||||
void construct ( Expr&& expr, optional_tag const* )
|
||||
{
|
||||
if ( expr.is_initialized() )
|
||||
{
|
||||
// An exception can be thrown here.
|
||||
// It it happens, THIS will be left uninitialized.
|
||||
m_storage = value_type(boost::move(expr.get())) ;
|
||||
m_initialized = true ;
|
||||
}
|
||||
}
|
||||
#else
|
||||
// Notice that 'Expr' will be optional<T> or optional<U> (but not tc_optional_base<..>)
|
||||
template<class Expr>
|
||||
void construct ( Expr const& expr, optional_tag const* )
|
||||
{
|
||||
if ( expr.is_initialized() )
|
||||
{
|
||||
// An exception can be thrown here.
|
||||
// It it happens, THIS will be left uninitialized.
|
||||
m_storage = value_type(expr.get()) ;
|
||||
m_initialized = true ;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif // defined BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
|
||||
|
||||
void assign_value ( argument_type val ) { m_storage = val; }
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
||||
void assign_value ( rval_reference_type val ) { m_storage = static_cast<rval_reference_type>(val); }
|
||||
#endif
|
||||
|
||||
void destroy()
|
||||
{
|
||||
m_initialized = false;
|
||||
}
|
||||
|
||||
reference_const_type get_impl() const { return m_storage ; }
|
||||
reference_type get_impl() { return m_storage ; }
|
||||
|
||||
pointer_const_type get_ptr_impl() const { return boost::addressof(m_storage); }
|
||||
pointer_type get_ptr_impl() { return boost::addressof(m_storage); }
|
||||
|
||||
private :
|
||||
|
||||
bool m_initialized ;
|
||||
T m_storage ;
|
||||
} ;
|
File diff suppressed because it is too large
Load Diff
@ -1,21 +1,40 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
|
||||
// Copyright (C) 2016 Andrzej Krzemienski
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
// See http://www.boost.org/libs/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
// Revisions:
|
||||
// 10 May 2008 (added swap related forward declaration) Niels Dekker
|
||||
//
|
||||
#ifndef BOOST_OPTIONAL_OPTIONAL_FWD_FLC_19NOV2002_HPP
|
||||
#define BOOST_OPTIONAL_OPTIONAL_FWD_FLC_19NOV2002_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template<class T> class optional ;
|
||||
|
||||
// This forward is needed to refer to namespace scope swap from the member swap
|
||||
template<class T> void swap ( optional<T>& , optional<T>& ) ;
|
||||
|
||||
template<class T> struct optional_swap_should_use_default_constructor ;
|
||||
|
||||
#ifndef BOOST_OPTIONAL_CONFIG_DONT_SPECIALIZE_OPTIONAL_REFS
|
||||
|
||||
template<class T> class optional<T&> ;
|
||||
|
||||
template<class T> void swap ( optional<T&>& , optional<T&>& ) BOOST_NOEXCEPT;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
95
include/boost/optional/optional_io.hpp
Normal file
95
include/boost/optional/optional_io.hpp
Normal file
@ -0,0 +1,95 @@
|
||||
// Copyright (C) 2005, Fernando Luis Cacciola Carballal.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
#ifndef BOOST_OPTIONAL_OPTIONAL_IO_FLC_19NOV2002_HPP
|
||||
#define BOOST_OPTIONAL_OPTIONAL_IO_FLC_19NOV2002_HPP
|
||||
|
||||
#ifndef BOOST_NO_IOSTREAM
|
||||
#include <istream>
|
||||
#include <ostream>
|
||||
|
||||
#include "boost/none.hpp"
|
||||
#include "boost/optional/optional.hpp"
|
||||
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
template<class CharType, class CharTrait>
|
||||
inline
|
||||
std::basic_ostream<CharType, CharTrait>&
|
||||
operator<<(std::basic_ostream<CharType, CharTrait>& out, none_t)
|
||||
{
|
||||
if (out.good())
|
||||
{
|
||||
out << "--";
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
template<class CharType, class CharTrait, class T>
|
||||
inline
|
||||
std::basic_ostream<CharType, CharTrait>&
|
||||
operator<<(std::basic_ostream<CharType, CharTrait>& out, optional<T> const& v)
|
||||
{
|
||||
if (out.good())
|
||||
{
|
||||
if (!v)
|
||||
out << "--" ;
|
||||
else out << ' ' << *v ;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
template<class CharType, class CharTrait, class T>
|
||||
inline
|
||||
std::basic_istream<CharType, CharTrait>&
|
||||
operator>>(std::basic_istream<CharType, CharTrait>& in, optional<T>& v)
|
||||
{
|
||||
if (in.good())
|
||||
{
|
||||
int d = in.get();
|
||||
if (d == ' ')
|
||||
{
|
||||
T x;
|
||||
in >> x;
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
||||
v = boost::move(x);
|
||||
#else
|
||||
v = x;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
if (d == '-')
|
||||
{
|
||||
d = in.get();
|
||||
|
||||
if (d == '-')
|
||||
{
|
||||
v = none;
|
||||
return in;
|
||||
}
|
||||
}
|
||||
|
||||
in.setstate( std::ios::failbit );
|
||||
}
|
||||
}
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_NO_IOSTREAM
|
||||
#endif
|
10
index.html
10
index.html
@ -1,9 +1,13 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="0; URL=doc/optional.html">
|
||||
<meta http-equiv="refresh" content="0; URL=doc/html/index.html">
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="doc/optional.html">doc/optional.html</a>.
|
||||
<a href="doc/html/index.html">doc/html/index.html</a>. <hr>
|
||||
<p><EFBFBD> Copyright Beman Dawes, 2001</p>
|
||||
<p>Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy
|
||||
at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
17
meta/libraries.json
Normal file
17
meta/libraries.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"key": "optional",
|
||||
"boost-version": "1.30.0",
|
||||
"name": "Optional",
|
||||
"authors": [
|
||||
"Fernando Cacciola"
|
||||
],
|
||||
"description": "A value-semantic, type-safe wrapper for representing 'optional' (or 'nullable') objects of a given type. An optional object may or may not contain a value of the underlying type.",
|
||||
"category": [
|
||||
"Data"
|
||||
],
|
||||
"maintainers": [
|
||||
"Fernando Cacciola <fernando_cacciola -at- ciudad.com.ar>",
|
||||
"Andrzej Krzemienski <akrzemi1 -at- gmail.com>"
|
||||
],
|
||||
"cxxstd": "11"
|
||||
}
|
@ -1 +0,0 @@
|
||||
bin
|
11
test/CMakeLists.txt
Normal file
11
test/CMakeLists.txt
Normal file
@ -0,0 +1,11 @@
|
||||
# Copyright 2018, 2019 Peter Dimov
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
include(BoostTestJamfile OPTIONAL RESULT_VARIABLE HAVE_BOOST_TEST)
|
||||
|
||||
if(HAVE_BOOST_TEST)
|
||||
|
||||
boost_test_jamfile(FILE Jamfile.v2 LINK_LIBRARIES Boost::optional Boost::core Boost::bind Boost::mpl Boost::tuple)
|
||||
|
||||
endif()
|
36
test/Jamfile
36
test/Jamfile
@ -1,36 +0,0 @@
|
||||
# Boost.Optional Library test Jamfile
|
||||
#
|
||||
# Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
#
|
||||
# Use, modification, and distribution is subject to the Boost Software
|
||||
# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
|
||||
subproject libs/optional/test ;
|
||||
|
||||
# bring in rules for testing
|
||||
SEARCH on testing.jam = $(BOOST_BUILD_PATH) ;
|
||||
include testing.jam ;
|
||||
|
||||
# Make tests run by default.
|
||||
DEPENDS all : test ;
|
||||
|
||||
{
|
||||
test-suite optional :
|
||||
[ run optional_test.cpp ]
|
||||
[ run optional_test_tie.cpp ]
|
||||
[ run optional_test_ref.cpp ]
|
||||
[ run optional_test_inplace.cpp ]
|
||||
[ compile-fail optional_test_fail1.cpp ]
|
||||
[ compile-fail optional_test_fail2.cpp ]
|
||||
[ compile-fail optional_test_fail3a.cpp ]
|
||||
[ compile-fail optional_test_fail3b.cpp ]
|
||||
[ compile-fail optional_test_ref_fail1.cpp ]
|
||||
[ compile-fail optional_test_ref_fail2.cpp ]
|
||||
[ compile-fail optional_test_ref_fail3.cpp ]
|
||||
[ compile-fail optional_test_ref_fail4.cpp ]
|
||||
[ compile-fail optional_test_inplace_fail.cpp ]
|
||||
[ compile-fail optional_test_inplace_fail2.cpp ]
|
||||
;
|
||||
}
|
125
test/Jamfile.v2
125
test/Jamfile.v2
@ -1,34 +1,105 @@
|
||||
# Boost.Optional Library test Jamfile
|
||||
# Boost.Optional Library test Jamfile
|
||||
#
|
||||
# Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
# Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
# Copyright (C) 2014 - 2017 Andrzej Krzemienski
|
||||
# Copyright (C) 2024 Alexander Grund
|
||||
#
|
||||
# This material is provided "as is", with absolutely no warranty expressed
|
||||
# or implied. Any use is at your own risk.
|
||||
# Use, modification, and distribution is subject to the Boost Software
|
||||
# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
# Permission to use or copy this software for any purpose is hereby granted
|
||||
# without fee, provided the above notices are retained on all copies.
|
||||
# Permission to modify the code and to distribute modified code is granted,
|
||||
# provided the above notices are retained, and a notice that the code was
|
||||
# modified is included with the above copyright notice.
|
||||
# See http://www.boost.org/libs/optional for documentation.
|
||||
#
|
||||
# You are welcome to contact the author at:
|
||||
# akrzemi1@gmail.com
|
||||
#
|
||||
|
||||
import config : requires ;
|
||||
import testing ;
|
||||
|
||||
{
|
||||
test-suite optional :
|
||||
[ run optional_test.cpp ]
|
||||
[ run optional_test_tie.cpp ]
|
||||
[ run optional_test_ref.cpp ]
|
||||
[ run optional_test_inplace.cpp ]
|
||||
[ compile-fail optional_test_fail1.cpp ]
|
||||
[ compile-fail optional_test_fail2.cpp ]
|
||||
[ compile-fail optional_test_fail3a.cpp ]
|
||||
[ compile-fail optional_test_fail3b.cpp ]
|
||||
[ compile-fail optional_test_ref_fail1.cpp ]
|
||||
[ compile-fail optional_test_ref_fail2.cpp ]
|
||||
[ compile-fail optional_test_ref_fail3.cpp ]
|
||||
[ compile-fail optional_test_ref_fail4.cpp ]
|
||||
[ compile-fail optional_test_inplace_fail.cpp ]
|
||||
[ compile-fail optional_test_inplace_fail2.cpp ]
|
||||
;
|
||||
}
|
||||
project
|
||||
: requirements
|
||||
<library>/boost/optional//boost_optional
|
||||
[ requires
|
||||
cxx11_decltype
|
||||
cxx11_defaulted_functions
|
||||
cxx11_defaulted_moves
|
||||
cxx11_deleted_functions
|
||||
cxx11_explicit_conversion_operators
|
||||
cxx11_noexcept
|
||||
cxx11_rvalue_references
|
||||
cxx11_variadic_templates
|
||||
]
|
||||
;
|
||||
|
||||
|
||||
run optional_test.cpp : : : <library>/boost/bind//boost_bind <library>/boost/mpl//boost_mpl ;
|
||||
run optional_test_assign.cpp ;
|
||||
run optional_test_swap.cpp ;
|
||||
compile optional_test_wuninitialized.cpp ;
|
||||
run optional_test_conversions_from_U.cpp ;
|
||||
run optional_test_convert_from_T.cpp ;
|
||||
run optional_test_convert_assign.cpp ;
|
||||
run optional_test_empty_braces.cpp ;
|
||||
run optional_test_make_optional.cpp ;
|
||||
run optional_test_flat_map.cpp ;
|
||||
run optional_test_hash.cpp ;
|
||||
run optional_test_map.cpp ;
|
||||
run optional_test_tie.cpp : : : <library>/boost/tuple//boost_tuple ;
|
||||
run optional_test_ref_assign_portable_minimum.cpp ;
|
||||
run optional_test_ref_assign_mutable_int.cpp ;
|
||||
run optional_test_ref_assign_const_int.cpp ;
|
||||
run optional_test_ref_converting_ctor.cpp ;
|
||||
run optional_test_ref_convert_assign_non_int.cpp ;
|
||||
run optional_test_ref_convert_assign_mutable_int.cpp ;
|
||||
run optional_test_ref_convert_assign_const_int.cpp ;
|
||||
run optional_test_ref_portable_minimum.cpp ;
|
||||
run optional_test_ref_move.cpp ;
|
||||
run optional_test_ref_to_val.cpp ;
|
||||
run optional_test_inplace_factory.cpp ;
|
||||
run optional_test_io.cpp ;
|
||||
run optional_test_move.cpp ;
|
||||
run optional_test_noexcept_move.cpp ;
|
||||
run optional_test_cmp_none.cpp ;
|
||||
run optional_test_value_access.cpp ;
|
||||
run optional_test_emplace.cpp ;
|
||||
run optional_test_minimum_requirements.cpp ;
|
||||
run optional_test_msvc_bug_workaround.cpp ;
|
||||
run optional_test_member_T.cpp ;
|
||||
run optional_test_tc_base.cpp ;
|
||||
compile optional_test_sfinae_friendly_ctor.cpp ;
|
||||
compile optional_test_path_assignment.cpp ;
|
||||
compile-fail optional_test_fail_const_swap.cpp ;
|
||||
compile-fail optional_test_ref_convert_assign_const_int_prevented.cpp ;
|
||||
compile-fail optional_test_fail1.cpp ;
|
||||
compile-fail optional_test_fail3a.cpp ;
|
||||
compile-fail optional_test_fail3b.cpp ;
|
||||
compile-fail optional_test_ref_fail1.cpp ;
|
||||
compile-fail optional_test_ref_fail3.cpp ;
|
||||
compile-fail optional_test_ref_fail4.cpp ;
|
||||
compile-fail optional_test_inplace_fail.cpp ;
|
||||
compile-fail optional_test_inplace_fail2.cpp ;
|
||||
compile-fail optional_test_fail_implicit_bool_convert.cpp ;
|
||||
compile-fail optional_test_fail_copying_a_moveable_type.cpp ;
|
||||
compile-fail optional_test_fail_optional_rvalue_ref.cpp ;
|
||||
compile-fail optional_test_ref_fail_init_from_Trefref.cpp ;
|
||||
compile-fail optional_test_ref_fail_init_from_Urefref.cpp ;
|
||||
compile-fail optional_test_ref_fail_assign_from_Trefref.cpp ;
|
||||
compile-fail optional_test_ref_fail_assign_from_Urefref.cpp ;
|
||||
compile-fail optional_test_fail_convert_from_null.cpp ;
|
||||
compile-fail optional_test_fail_explicit_convert_in_value_or.cpp ;
|
||||
compile-fail optional_test_fail_explicit_convert_in_value_or_call.cpp ;
|
||||
compile-fail optional_test_fail_io_without_io.cpp ;
|
||||
compile-fail optional_test_fail_none_io_without_io.cpp ;
|
||||
compile-fail optional_test_fail_convert_assign_of_enums.cpp ;
|
||||
run optional_test_static_properties.cpp ;
|
||||
compile optional_test_maybe_uninitialized_warning.cpp ;
|
||||
compile optional_test_deleted_default_ctor.cpp ;
|
||||
compile optional_test_constructible_from_other.cpp ;
|
||||
#run optional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp ;
|
||||
run optional_xconfig_NO_PROPER_ASSIGN_FROM_CONST_INT_pass.cpp ;
|
||||
run-fail optional_xconfig_NO_PROPER_ASSIGN_FROM_CONST_INT_fail.cpp ;
|
||||
run optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_pass.cpp ;
|
||||
run-fail optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp ;
|
||||
run optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_pass.cpp ;
|
||||
compile-fail optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_fail.cpp ;
|
||||
|
17
test/cmake_install_test/CMakeLists.txt
Normal file
17
test/cmake_install_test/CMakeLists.txt
Normal file
@ -0,0 +1,17 @@
|
||||
# Copyright 2018, 2019 Peter Dimov
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
cmake_minimum_required(VERSION 3.5...3.16)
|
||||
|
||||
project(cmake_subdir_test LANGUAGES CXX)
|
||||
|
||||
find_package(boost_optional REQUIRED)
|
||||
|
||||
add_executable(main main.cpp)
|
||||
target_link_libraries(main Boost::optional)
|
||||
|
||||
enable_testing()
|
||||
add_test(main main)
|
||||
|
||||
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C $<CONFIG>)
|
13
test/cmake_install_test/main.cpp
Normal file
13
test/cmake_install_test/main.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright 2024 Peter Dimov
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/optional/optional.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
boost::optional<int> o1;
|
||||
boost::optional<int> o2( 0 );
|
||||
o1 = o2;
|
||||
return *o1;
|
||||
}
|
18
test/cmake_subdir_test/CMakeLists.txt
Normal file
18
test/cmake_subdir_test/CMakeLists.txt
Normal file
@ -0,0 +1,18 @@
|
||||
# Copyright 2018, 2019 Peter Dimov
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
cmake_minimum_required(VERSION 3.5...3.16)
|
||||
|
||||
project(cmake_subdir_test LANGUAGES CXX)
|
||||
|
||||
set(BOOST_INCLUDE_LIBRARIES optional)
|
||||
add_subdirectory(../../../.. boostorg/boost)
|
||||
|
||||
add_executable(main main.cpp)
|
||||
target_link_libraries(main Boost::optional)
|
||||
|
||||
enable_testing()
|
||||
add_test(main main)
|
||||
|
||||
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C $<CONFIG>)
|
13
test/cmake_subdir_test/main.cpp
Normal file
13
test/cmake_subdir_test/main.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright 2024 Peter Dimov
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/optional/optional.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
boost::optional<int> o1;
|
||||
boost::optional<int> o2( 0 );
|
||||
o1 = o2;
|
||||
return *o1;
|
||||
}
|
181
test/optional_ref_assign_test_defs.hpp
Normal file
181
test/optional_ref_assign_test_defs.hpp
Normal file
@ -0,0 +1,181 @@
|
||||
// Copyright (C) 2014 Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at: akrzemi1@gmail.com
|
||||
|
||||
#ifndef BOOST_OPTIONAL_TEST_OPTIONAL_REF_ASSIGN_TEST_DEFS_AK_07JAN2015_HPP
|
||||
#define BOOST_OPTIONAL_TEST_OPTIONAL_REF_ASSIGN_TEST_DEFS_AK_07JAN2015_HPP
|
||||
|
||||
#include "boost/optional/optional.hpp"
|
||||
|
||||
#ifdef BOOST_BORLANDC
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#include "boost/core/addressof.hpp"
|
||||
#include "testable_classes.hpp"
|
||||
|
||||
using boost::optional;
|
||||
using boost::none;
|
||||
using boost::addressof;
|
||||
|
||||
template <typename T>
|
||||
void test_copy_assignment_for_const()
|
||||
{
|
||||
const typename concrete_type_of<T>::type v(2);
|
||||
optional<const T&> o;
|
||||
o = optional<const T&>(v);
|
||||
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(o != none);
|
||||
BOOST_TEST(addressof(*o) == addressof(v));
|
||||
BOOST_TEST(val(*o) == val(v));
|
||||
BOOST_TEST(val(*o) == 2);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void test_copy_assignment_for_noconst_const()
|
||||
{
|
||||
typename concrete_type_of<T>::type v(2);
|
||||
optional<const T&> o;
|
||||
o = optional<const T&>(v);
|
||||
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(o != none);
|
||||
BOOST_TEST(addressof(*o) == addressof(v));
|
||||
BOOST_TEST(val(*o) == val(v));
|
||||
BOOST_TEST(val(*o) == 2);
|
||||
|
||||
val(v) = 9;
|
||||
BOOST_TEST(addressof(*o) == addressof(v));
|
||||
BOOST_TEST_EQ(val(*o), val(v));
|
||||
BOOST_TEST_EQ(val(*o), 9);
|
||||
BOOST_TEST_EQ(val(v), 9);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void test_copy_assignment_for()
|
||||
{
|
||||
typename concrete_type_of<T>::type v(2);
|
||||
optional<T&> o;
|
||||
o = optional<T&>(v);
|
||||
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(o != none);
|
||||
BOOST_TEST(addressof(*o) == addressof(v));
|
||||
BOOST_TEST(val(*o) == val(v));
|
||||
BOOST_TEST(val(*o) == 2);
|
||||
|
||||
val(v) = 9;
|
||||
BOOST_TEST(addressof(*o) == addressof(v));
|
||||
BOOST_TEST_EQ(val(*o), val(v));
|
||||
BOOST_TEST_EQ(val(*o), 9);
|
||||
BOOST_TEST_EQ(val(v), 9);
|
||||
|
||||
val(*o) = 7;
|
||||
BOOST_TEST(addressof(*o) == addressof(v));
|
||||
BOOST_TEST_EQ(val(*o), val(v));
|
||||
BOOST_TEST_EQ(val(*o), 7);
|
||||
BOOST_TEST_EQ(val(v), 7);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void test_rebinding_assignment_semantics_const()
|
||||
{
|
||||
const typename concrete_type_of<T>::type v(2), w(7);
|
||||
optional<const T&> o(v);
|
||||
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(addressof(*o) == addressof(v));
|
||||
BOOST_TEST_EQ(val(*o), val(v));
|
||||
BOOST_TEST_EQ(val(*o), 2);
|
||||
|
||||
o = optional<const T&>(w);
|
||||
BOOST_TEST_EQ(val(v), 2);
|
||||
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(addressof(*o) != addressof(v));
|
||||
BOOST_TEST_NE(val(*o), val(v));
|
||||
BOOST_TEST_NE(val(*o), 2);
|
||||
|
||||
BOOST_TEST(addressof(*o) == addressof(w));
|
||||
BOOST_TEST_EQ(val(*o), val(w));
|
||||
BOOST_TEST_EQ(val(*o), 7);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void test_rebinding_assignment_semantics_noconst_const()
|
||||
{
|
||||
typename concrete_type_of<T>::type v(2), w(7);
|
||||
optional<const T&> o(v);
|
||||
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(addressof(*o) == addressof(v));
|
||||
BOOST_TEST_EQ(val(*o), val(v));
|
||||
BOOST_TEST_EQ(val(*o), 2);
|
||||
|
||||
o = optional<const T&>(w);
|
||||
BOOST_TEST_EQ(val(v), 2);
|
||||
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(addressof(*o) != addressof(v));
|
||||
BOOST_TEST_NE(val(*o), val(v));
|
||||
BOOST_TEST_NE(val(*o), 2);
|
||||
|
||||
BOOST_TEST(addressof(*o) == addressof(w));
|
||||
BOOST_TEST_EQ(val(*o), val(w));
|
||||
BOOST_TEST_EQ(val(*o), 7);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void test_rebinding_assignment_semantics()
|
||||
{
|
||||
typename concrete_type_of<T>::type v(2), w(7);
|
||||
optional<T&> o(v);
|
||||
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(addressof(*o) == addressof(v));
|
||||
BOOST_TEST_EQ(val(*o), val(v));
|
||||
BOOST_TEST_EQ(val(*o), 2);
|
||||
|
||||
o = optional<T&>(w);
|
||||
BOOST_TEST_EQ(val(v), 2);
|
||||
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(addressof(*o) != addressof(v));
|
||||
BOOST_TEST_NE(val(*o), val(v));
|
||||
BOOST_TEST_NE(val(*o), 2);
|
||||
|
||||
BOOST_TEST(addressof(*o) == addressof(w));
|
||||
BOOST_TEST_EQ(val(*o), val(w));
|
||||
BOOST_TEST_EQ(val(*o), 7);
|
||||
|
||||
val(*o) = 8;
|
||||
BOOST_TEST(addressof(*o) == addressof(w));
|
||||
BOOST_TEST_EQ(val(*o), val(w));
|
||||
BOOST_TEST_EQ(val(*o), 8);
|
||||
BOOST_TEST_EQ(val(w), 8);
|
||||
BOOST_TEST_EQ(val(v), 2);
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
void test_converting_assignment()
|
||||
{
|
||||
typename concrete_type_of<T>::type v1(1), v2(2), v3(3);
|
||||
optional<U&> oA(v1), oB(none);
|
||||
|
||||
oA = v2;
|
||||
BOOST_TEST(oA);
|
||||
BOOST_TEST(addressof(*oA) == addressof(v2));
|
||||
|
||||
oB = v3;
|
||||
BOOST_TEST(oB);
|
||||
BOOST_TEST(addressof(*oB) == addressof(v3));
|
||||
}
|
||||
|
||||
#endif //BOOST_OPTIONAL_TEST_OPTIONAL_REF_ASSIGN_TEST_DEFS_AK_07JAN2015_HPP
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -9,23 +9,35 @@
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
// Revisions:
|
||||
// 12 May 2008 (added more swap tests)
|
||||
//
|
||||
#ifndef BOOST_NO_IOSTREAM
|
||||
#include<iostream>
|
||||
#endif // BOOST_NO_IOSTREAM
|
||||
#include<stdexcept>
|
||||
#include<string>
|
||||
|
||||
#define BOOST_ENABLE_ASSERT_HANDLER
|
||||
|
||||
#include "boost/optional.hpp"
|
||||
#include "boost/config.hpp"
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
#include "boost/bind/apply.hpp" // Included just to test proper interaction with boost::apply<> as reported by Daniel Wallin
|
||||
#endif
|
||||
#include "boost/mpl/bool.hpp"
|
||||
#include "boost/mpl/bool_fwd.hpp" // For mpl::true_ and mpl::false_
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#include "boost/optional/optional.hpp"
|
||||
|
||||
#ifdef BOOST_BORLANDC
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#include "boost/none.hpp"
|
||||
|
||||
#include "boost/test/minimal.hpp"
|
||||
#include "boost/core/lightweight_test.hpp"
|
||||
|
||||
#include "optional_test_common.cpp"
|
||||
#include "optional_test_common.hpp"
|
||||
|
||||
void test_implicit_construction ( optional<double> opt, double v, double z )
|
||||
{
|
||||
@ -39,12 +51,12 @@ void test_implicit_construction ( optional<X> opt, X const& v, X const& z )
|
||||
|
||||
void test_default_implicit_construction ( double, optional<double> opt )
|
||||
{
|
||||
BOOST_CHECK(!opt);
|
||||
BOOST_TEST(!opt);
|
||||
}
|
||||
|
||||
void test_default_implicit_construction ( X const&, optional<X> opt )
|
||||
{
|
||||
BOOST_CHECK(!opt);
|
||||
BOOST_TEST(!opt);
|
||||
}
|
||||
|
||||
//
|
||||
@ -68,7 +80,7 @@ void test_basics( T const* )
|
||||
check_uninitialized(def);
|
||||
|
||||
// Implicit construction
|
||||
// The first parameter is implicitely converted to optional<T>(a);
|
||||
// The first parameter is implicitly converted to optional<T>(a);
|
||||
test_implicit_construction(a,a,z);
|
||||
|
||||
// Direct initialization.
|
||||
@ -115,12 +127,8 @@ void test_basics( T const* )
|
||||
// Assignment
|
||||
// T::operator= ( T const& x ) is used to copy new value.
|
||||
set_pending_assign( ARG(T) ) ;
|
||||
set_pending_copy ( ARG(T) ) ;
|
||||
set_pending_dtor ( ARG(T) ) ;
|
||||
oa = ob ;
|
||||
check_is_not_pending_assign( ARG(T) ) ;
|
||||
check_is_pending_copy ( ARG(T) ) ;
|
||||
check_is_pending_dtor ( ARG(T) ) ;
|
||||
check_initialized(oa);
|
||||
check_value(oa,b,z);
|
||||
|
||||
@ -155,6 +163,95 @@ void test_basics( T const* )
|
||||
ob.reset();
|
||||
check_is_pending_dtor( ARG(T) ) ;
|
||||
check_uninitialized(ob);
|
||||
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void test_conditional_ctor_and_get_value_or ( T const* )
|
||||
{
|
||||
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
||||
|
||||
T a(321);
|
||||
|
||||
T z(123);
|
||||
|
||||
optional<T> const cdef0(false,a);
|
||||
|
||||
optional<T> def0(false,a);
|
||||
optional<T> def1 = boost::make_optional(false,a); // T is not within boost so ADL won't find make_optional unqualified
|
||||
check_uninitialized(def0);
|
||||
check_uninitialized(def1);
|
||||
|
||||
optional<T> const co0(true,a);
|
||||
|
||||
optional<T> o0(true,a);
|
||||
optional<T> o1 = boost::make_optional(true,a); // T is not within boost so ADL won't find make_optional unqualified
|
||||
|
||||
check_initialized(o0);
|
||||
check_initialized(o1);
|
||||
check_value(o0,a,z);
|
||||
check_value(o1,a,z);
|
||||
|
||||
T b = def0.get_value_or(z);
|
||||
BOOST_TEST( b == z ) ;
|
||||
|
||||
b = get_optional_value_or(def0,z);
|
||||
BOOST_TEST( b == z ) ;
|
||||
|
||||
b = o0.get_value_or(z);
|
||||
BOOST_TEST( b == a ) ;
|
||||
|
||||
b = get_optional_value_or(o0,z);
|
||||
BOOST_TEST( b == a ) ;
|
||||
|
||||
|
||||
T const& crz = z ;
|
||||
T& rz = z ;
|
||||
|
||||
T const& crzz = def0.get_value_or(crz);
|
||||
BOOST_TEST( crzz == crz ) ;
|
||||
|
||||
T& rzz = def0.get_value_or(rz);
|
||||
BOOST_TEST( rzz == rz ) ;
|
||||
|
||||
T const& crzzz = get_optional_value_or(cdef0,crz);
|
||||
BOOST_TEST( crzzz == crz ) ;
|
||||
|
||||
T& rzzz = get_optional_value_or(def0,rz);
|
||||
BOOST_TEST( rzzz == rz ) ;
|
||||
|
||||
T const& crb = o0.get_value_or(crz);
|
||||
BOOST_TEST( crb == a ) ;
|
||||
|
||||
T& rb = o0.get_value_or(rz);
|
||||
BOOST_TEST( rb == b ) ;
|
||||
|
||||
T const& crbb = get_optional_value_or(co0,crz);
|
||||
BOOST_TEST( crbb == b ) ;
|
||||
|
||||
T const& crbbb = get_optional_value_or(o0,crz);
|
||||
BOOST_TEST( crbbb == b ) ;
|
||||
|
||||
T& rbb = get_optional_value_or(o0,rz);
|
||||
BOOST_TEST( rbb == b ) ;
|
||||
|
||||
T& ra = a ;
|
||||
|
||||
optional<T&> defref(false,ra);
|
||||
BOOST_TEST(!defref);
|
||||
|
||||
optional<T&> ref(true,ra);
|
||||
BOOST_TEST(!!ref);
|
||||
|
||||
a = T(432);
|
||||
|
||||
BOOST_TEST( *ref == a ) ;
|
||||
|
||||
T& r1 = defref.get_value_or(z);
|
||||
BOOST_TEST( r1 == z ) ;
|
||||
|
||||
T& r2 = ref.get_value_or(z);
|
||||
BOOST_TEST( r2 == a ) ;
|
||||
}
|
||||
|
||||
//
|
||||
@ -170,18 +267,18 @@ void test_direct_value_manip( T const* )
|
||||
optional<T> const c_opt0(x) ;
|
||||
optional<T> opt0(x);
|
||||
|
||||
BOOST_CHECK( c_opt0.get().V() == x.V() ) ;
|
||||
BOOST_CHECK( opt0.get().V() == x.V() ) ;
|
||||
BOOST_TEST( c_opt0.get().V() == x.V() ) ;
|
||||
BOOST_TEST( opt0.get().V() == x.V() ) ;
|
||||
|
||||
BOOST_CHECK( c_opt0->V() == x.V() ) ;
|
||||
BOOST_CHECK( opt0->V() == x.V() ) ;
|
||||
BOOST_TEST( c_opt0->V() == x.V() ) ;
|
||||
BOOST_TEST( opt0->V() == x.V() ) ;
|
||||
|
||||
BOOST_CHECK( (*c_opt0).V() == x.V() ) ;
|
||||
BOOST_CHECK( (* opt0).V() == x.V() ) ;
|
||||
BOOST_TEST( (*c_opt0).V() == x.V() ) ;
|
||||
BOOST_TEST( (* opt0).V() == x.V() ) ;
|
||||
|
||||
T y(4);
|
||||
opt0 = y ;
|
||||
BOOST_CHECK( get(opt0).V() == y.V() ) ;
|
||||
BOOST_TEST( get(opt0).V() == y.V() ) ;
|
||||
}
|
||||
|
||||
//
|
||||
@ -199,45 +296,45 @@ void test_uninitialized_access( T const* )
|
||||
{
|
||||
// This should throw because 'def' is uninitialized
|
||||
T const& n = def.get() ;
|
||||
unused_variable(n);
|
||||
boost::ignore_unused(n);
|
||||
passed = true ;
|
||||
}
|
||||
catch (...) {}
|
||||
BOOST_CHECK(!passed);
|
||||
BOOST_TEST(!passed);
|
||||
|
||||
passed = false ;
|
||||
try
|
||||
{
|
||||
// This should throw because 'def' is uninitialized
|
||||
T const& n = *def ;
|
||||
unused_variable(n);
|
||||
boost::ignore_unused(n);
|
||||
passed = true ;
|
||||
}
|
||||
catch (...) {}
|
||||
BOOST_CHECK(!passed);
|
||||
BOOST_TEST(!passed);
|
||||
|
||||
passed = false ;
|
||||
try
|
||||
{
|
||||
T v(5) ;
|
||||
unused_variable(v);
|
||||
boost::ignore_unused(v);
|
||||
// This should throw because 'def' is uninitialized
|
||||
*def = v ;
|
||||
passed = true ;
|
||||
}
|
||||
catch (...) {}
|
||||
BOOST_CHECK(!passed);
|
||||
BOOST_TEST(!passed);
|
||||
|
||||
passed = false ;
|
||||
try
|
||||
{
|
||||
// This should throw because 'def' is uninitialized
|
||||
T v = *(def.operator->()) ;
|
||||
unused_variable(v);
|
||||
boost::ignore_unused(v);
|
||||
passed = true ;
|
||||
}
|
||||
catch (...) {}
|
||||
BOOST_CHECK(!passed);
|
||||
BOOST_TEST(!passed);
|
||||
}
|
||||
|
||||
#if BOOST_WORKAROUND( BOOST_INTEL_CXX_VERSION, <= 700) // Intel C++ 7.0
|
||||
@ -282,7 +379,7 @@ void test_throwing_direct_init( T const* )
|
||||
}
|
||||
catch ( ... ){}
|
||||
|
||||
BOOST_CHECK(!passed);
|
||||
BOOST_TEST(!passed);
|
||||
check_is_not_pending_copy( ARG(T) );
|
||||
check_instance_count(count, ARG(T) );
|
||||
|
||||
@ -318,7 +415,7 @@ void test_throwing_val_assign_on_uninitialized( T const* )
|
||||
}
|
||||
catch ( ... ) {}
|
||||
|
||||
BOOST_CHECK(!passed);
|
||||
BOOST_TEST(!passed);
|
||||
|
||||
check_is_not_pending_copy( ARG(T) );
|
||||
check_instance_count(count, ARG(T) );
|
||||
@ -356,15 +453,15 @@ void test_throwing_val_assign_on_initialized( T const* )
|
||||
{
|
||||
// This should:
|
||||
// Attempt to assign 'a' and throw.
|
||||
// opt is kept initialized but its value not neccesarily fully assigned
|
||||
// (in this test, incompletely assigned is flaged with the value -1 being set)
|
||||
// opt is kept initialized but its value not necessarily fully assigned
|
||||
// (in this test, incompletely assigned is flagged with the value -1 being set)
|
||||
set_pending_assign( ARG(T) ) ;
|
||||
opt.reset ( a ) ;
|
||||
passed = true ;
|
||||
}
|
||||
catch ( ... ) {}
|
||||
|
||||
BOOST_CHECK(!passed);
|
||||
BOOST_TEST(!passed);
|
||||
|
||||
check_is_not_pending_assign( ARG(T) );
|
||||
check_instance_count(count, ARG(T) );
|
||||
@ -403,7 +500,7 @@ void test_throwing_copy_initialization( T const* )
|
||||
}
|
||||
catch ( ... ) {}
|
||||
|
||||
BOOST_CHECK(!passed);
|
||||
BOOST_TEST(!passed);
|
||||
|
||||
check_is_not_pending_copy( ARG(T) );
|
||||
check_instance_count(count, ARG(T) );
|
||||
@ -446,7 +543,7 @@ void test_throwing_assign_to_uninitialized( T const* )
|
||||
}
|
||||
catch ( ... ) {}
|
||||
|
||||
BOOST_CHECK(!passed);
|
||||
BOOST_TEST(!passed);
|
||||
|
||||
check_is_not_pending_copy( ARG(T) );
|
||||
check_instance_count(count, ARG(T) );
|
||||
@ -481,15 +578,15 @@ void test_throwing_assign_to_initialized( T const* )
|
||||
{
|
||||
// This should:
|
||||
// Attempt to copy construct 'opt1.value()' into opt0 and throw.
|
||||
// opt0 is kept initialized but its value not neccesarily fully assigned
|
||||
// (in this test, incompletely assigned is flaged with the value -1 being set)
|
||||
// opt0 is kept initialized but its value not necessarily fully assigned
|
||||
// (in this test, incompletely assigned is flagged with the value -1 being set)
|
||||
set_pending_assign( ARG(T) ) ;
|
||||
opt0 = opt1 ;
|
||||
passed = true ;
|
||||
}
|
||||
catch ( ... ) {}
|
||||
|
||||
BOOST_CHECK(!passed);
|
||||
BOOST_TEST(!passed);
|
||||
|
||||
// opt0 was left uninitialized
|
||||
check_is_not_pending_assign( ARG(T) );
|
||||
@ -569,7 +666,7 @@ void test_throwing_swap( T const* )
|
||||
}
|
||||
catch ( ... ) {}
|
||||
|
||||
BOOST_CHECK(!passed);
|
||||
BOOST_TEST(!passed);
|
||||
|
||||
// optional's swap doesn't affect the initialized states of the arguments. Therefore,
|
||||
// the following must hold:
|
||||
@ -593,14 +690,14 @@ void test_throwing_swap( T const* )
|
||||
try
|
||||
{
|
||||
// This should attempt to swap optionals and fail at opt0.reset(*opt1)
|
||||
// Both opt0 and op1 are left unchanged (unswaped)
|
||||
// Both opt0 and op1 are left unchanged (unswapped)
|
||||
swap(opt0,opt1);
|
||||
|
||||
passed = true ;
|
||||
}
|
||||
catch ( ... ) {}
|
||||
|
||||
BOOST_CHECK(!passed);
|
||||
BOOST_TEST(!passed);
|
||||
|
||||
check_uninitialized(opt0);
|
||||
check_initialized(opt1);
|
||||
@ -617,9 +714,9 @@ void test_relops( T const* )
|
||||
{
|
||||
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
||||
|
||||
T v0(18);
|
||||
T v1(19);
|
||||
T v2(19);
|
||||
T v0(0);
|
||||
T v1(1);
|
||||
T v2(1);
|
||||
|
||||
optional<T> def0 ;
|
||||
optional<T> def1 ;
|
||||
@ -628,42 +725,69 @@ void test_relops( T const* )
|
||||
optional<T> opt2(v2);
|
||||
|
||||
// Check identity
|
||||
BOOST_CHECK ( def0 == def0 ) ;
|
||||
BOOST_CHECK ( opt0 == opt0 ) ;
|
||||
BOOST_CHECK ( !(def0 != def0) ) ;
|
||||
BOOST_CHECK ( !(opt0 != opt0) ) ;
|
||||
BOOST_TEST ( def0 == def0 ) ;
|
||||
BOOST_TEST ( opt0 == opt0 ) ;
|
||||
BOOST_TEST ( !(def0 != def0) ) ;
|
||||
BOOST_TEST ( !(opt0 != opt0) ) ;
|
||||
|
||||
// Check when both are uininitalized.
|
||||
BOOST_CHECK ( def0 == def1 ) ; // both uninitialized compare equal
|
||||
BOOST_CHECK ( !(def0 < def1) ) ; // uninitialized is never less than uninitialized
|
||||
BOOST_CHECK ( !(def0 > def1) ) ; // uninitialized is never greater than uninitialized
|
||||
BOOST_CHECK ( !(def0 != def1) ) ;
|
||||
BOOST_CHECK ( def0 <= def1 ) ;
|
||||
BOOST_CHECK ( def0 >= def1 ) ;
|
||||
// Check when both are uninitialized.
|
||||
BOOST_TEST ( def0 == def1 ) ; // both uninitialized compare equal
|
||||
BOOST_TEST ( !(def0 < def1) ) ; // uninitialized is never less than uninitialized
|
||||
BOOST_TEST ( !(def0 > def1) ) ; // uninitialized is never greater than uninitialized
|
||||
BOOST_TEST ( !(def0 != def1) ) ;
|
||||
BOOST_TEST ( def0 <= def1 ) ;
|
||||
BOOST_TEST ( def0 >= def1 ) ;
|
||||
|
||||
// Check when only lhs is uninitialized.
|
||||
BOOST_CHECK ( def0 != opt0 ) ; // uninitialized is never equal to initialized
|
||||
BOOST_CHECK ( !(def0 == opt0) ) ;
|
||||
BOOST_CHECK ( def0 < opt0 ) ; // uninitialized is always less than initialized
|
||||
BOOST_CHECK ( !(def0 > opt0) ) ;
|
||||
BOOST_CHECK ( def0 <= opt0 ) ;
|
||||
BOOST_CHECK ( !(def0 >= opt0) ) ;
|
||||
BOOST_TEST ( def0 != opt0 ) ; // uninitialized is never equal to initialized
|
||||
BOOST_TEST ( !(def0 == opt0) ) ;
|
||||
BOOST_TEST ( def0 < opt0 ) ; // uninitialized is always less than initialized
|
||||
BOOST_TEST ( !(def0 > opt0) ) ;
|
||||
BOOST_TEST ( def0 <= opt0 ) ;
|
||||
BOOST_TEST ( !(def0 >= opt0) ) ;
|
||||
|
||||
// Check when only rhs is uninitialized.
|
||||
BOOST_CHECK ( opt0 != def0 ) ; // initialized is never equal to uninitialized
|
||||
BOOST_CHECK ( !(opt0 == def0) ) ;
|
||||
BOOST_CHECK ( !(opt0 < def0) ) ; // initialized is never less than uninitialized
|
||||
BOOST_CHECK ( opt0 > def0 ) ;
|
||||
BOOST_CHECK ( !(opt0 <= def0) ) ;
|
||||
BOOST_CHECK ( opt0 >= opt0 ) ;
|
||||
BOOST_TEST ( opt0 != def0 ) ; // initialized is never equal to uninitialized
|
||||
BOOST_TEST ( !(opt0 == def0) ) ;
|
||||
BOOST_TEST ( !(opt0 < def0) ) ; // initialized is never less than uninitialized
|
||||
BOOST_TEST ( opt0 > def0 ) ;
|
||||
BOOST_TEST ( !(opt0 <= def0) ) ;
|
||||
BOOST_TEST ( opt0 >= opt0 ) ;
|
||||
|
||||
// If both are initialized, values are compared
|
||||
BOOST_CHECK ( opt0 != opt1 ) ;
|
||||
BOOST_CHECK ( opt1 == opt2 ) ;
|
||||
BOOST_CHECK ( opt0 < opt1 ) ;
|
||||
BOOST_CHECK ( opt1 > opt0 ) ;
|
||||
BOOST_CHECK ( opt1 <= opt2 ) ;
|
||||
BOOST_CHECK ( opt1 >= opt0 ) ;
|
||||
BOOST_TEST ( opt0 != opt1 ) ;
|
||||
BOOST_TEST ( opt1 == opt2 ) ;
|
||||
BOOST_TEST ( opt0 < opt1 ) ;
|
||||
BOOST_TEST ( opt1 > opt0 ) ;
|
||||
BOOST_TEST ( opt1 <= opt2 ) ;
|
||||
BOOST_TEST ( opt1 >= opt0 ) ;
|
||||
|
||||
// Compare against a value directly
|
||||
BOOST_TEST ( opt0 == v0 ) ;
|
||||
BOOST_TEST ( opt0 != v1 ) ;
|
||||
BOOST_TEST ( opt1 == v2 ) ;
|
||||
BOOST_TEST ( opt0 < v1 ) ;
|
||||
BOOST_TEST ( opt1 > v0 ) ;
|
||||
BOOST_TEST ( opt1 <= v2 ) ;
|
||||
BOOST_TEST ( opt1 >= v0 ) ;
|
||||
BOOST_TEST ( v0 != opt1 ) ;
|
||||
BOOST_TEST ( v1 == opt2 ) ;
|
||||
BOOST_TEST ( v0 < opt1 ) ;
|
||||
BOOST_TEST ( v1 > opt0 ) ;
|
||||
BOOST_TEST ( v1 <= opt2 ) ;
|
||||
BOOST_TEST ( v1 >= opt0 ) ;
|
||||
BOOST_TEST ( def0 != v0 ) ;
|
||||
BOOST_TEST ( !(def0 == v0) ) ;
|
||||
BOOST_TEST ( def0 < v0 ) ;
|
||||
BOOST_TEST ( !(def0 > v0) ) ;
|
||||
BOOST_TEST ( def0 <= v0 ) ;
|
||||
BOOST_TEST ( !(def0 >= v0) ) ;
|
||||
BOOST_TEST ( v0 != def0 ) ;
|
||||
BOOST_TEST ( !(v0 == def0) ) ;
|
||||
BOOST_TEST ( !(v0 < def0) ) ;
|
||||
BOOST_TEST ( v0 > def0 ) ;
|
||||
BOOST_TEST ( !(v0 <= def0) ) ;
|
||||
BOOST_TEST ( v0 >= opt0 ) ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@ -677,32 +801,68 @@ void test_none( T const* )
|
||||
optional<T> def1(none) ;
|
||||
optional<T> non_def( T(1234) ) ;
|
||||
|
||||
BOOST_CHECK ( def0 == none ) ;
|
||||
BOOST_CHECK ( non_def != none ) ;
|
||||
BOOST_CHECK ( !def1 ) ;
|
||||
BOOST_TEST ( def0 == none ) ;
|
||||
BOOST_TEST ( non_def != none ) ;
|
||||
BOOST_TEST ( !def1 ) ;
|
||||
BOOST_TEST ( !(non_def < none) ) ;
|
||||
BOOST_TEST ( non_def > none ) ;
|
||||
BOOST_TEST ( !(non_def <= none) ) ;
|
||||
BOOST_TEST ( non_def >= none ) ;
|
||||
|
||||
non_def = none ;
|
||||
BOOST_CHECK ( !non_def ) ;
|
||||
BOOST_TEST ( !non_def ) ;
|
||||
|
||||
test_default_implicit_construction(T(1),none);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void test_arrow( T const* )
|
||||
{
|
||||
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
||||
|
||||
T a(1234);
|
||||
|
||||
optional<T> oa(a) ;
|
||||
optional<T> const coa(a) ;
|
||||
|
||||
BOOST_TEST ( coa->V() == 1234 ) ;
|
||||
|
||||
oa->V() = 4321 ;
|
||||
|
||||
BOOST_TEST ( a.V() = 1234 ) ;
|
||||
BOOST_TEST ( (*oa).V() = 4321 ) ;
|
||||
}
|
||||
|
||||
void test_with_builtin_types()
|
||||
{
|
||||
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
||||
|
||||
test_basics( ARG(double) );
|
||||
test_conditional_ctor_and_get_value_or( ARG(double) );
|
||||
test_uninitialized_access( ARG(double) );
|
||||
test_no_throwing_swap( ARG(double) );
|
||||
test_relops( ARG(double) ) ;
|
||||
test_none( ARG(double) ) ;
|
||||
}
|
||||
|
||||
// MSVC < 11.0 doesn't destroy X when we call ptr->VBase::VBase.
|
||||
// Make sure that we work around this bug.
|
||||
struct VBase : virtual X
|
||||
{
|
||||
VBase(int v) : X(v) {}
|
||||
// MSVC 8.0 doesn't generate this correctly...
|
||||
VBase(const VBase& other) : X(static_cast<const X&>(other)) {}
|
||||
|
||||
VBase& operator=(VBase const& rhs) { X::operator=(rhs); return *this; }
|
||||
};
|
||||
|
||||
void test_with_class_type()
|
||||
{
|
||||
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
||||
|
||||
test_basics( ARG(X) );
|
||||
test_basics( ARG(VBase) );
|
||||
test_conditional_ctor_and_get_value_or( ARG(X) );
|
||||
test_direct_value_manip( ARG(X) );
|
||||
test_uninitialized_access( ARG(X) );
|
||||
test_throwing_direct_init( ARG(X) );
|
||||
@ -715,7 +875,8 @@ void test_with_class_type()
|
||||
test_throwing_swap( ARG(X) );
|
||||
test_relops( ARG(X) ) ;
|
||||
test_none( ARG(X) ) ;
|
||||
BOOST_CHECK ( X::count == 0 ) ;
|
||||
test_arrow( ARG(X) ) ;
|
||||
BOOST_TEST ( X::count == 0 ) ;
|
||||
}
|
||||
|
||||
int eat ( bool ) { return 1 ; }
|
||||
@ -734,7 +895,7 @@ void test_no_implicit_conversions_impl( T const& )
|
||||
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
||||
|
||||
optional<T> def ;
|
||||
BOOST_CHECK ( eat(def) == 0 ) ;
|
||||
BOOST_TEST ( eat(def) == 0 ) ;
|
||||
}
|
||||
|
||||
void test_no_implicit_conversions()
|
||||
@ -752,58 +913,48 @@ void test_no_implicit_conversions()
|
||||
test_no_implicit_conversions_impl(p);
|
||||
}
|
||||
|
||||
struct A {} ;
|
||||
void test_conversions1()
|
||||
|
||||
// Test for support for classes with overridden operator&
|
||||
class CustomAddressOfClass
|
||||
{
|
||||
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
||||
int n;
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR
|
||||
char c = 20 ;
|
||||
optional<char> opt0(c);
|
||||
optional<int> opt1(opt0);
|
||||
BOOST_CHECK(*opt1 == static_cast<int>(c));
|
||||
#endif
|
||||
public:
|
||||
CustomAddressOfClass() : n(0) {}
|
||||
CustomAddressOfClass(CustomAddressOfClass const& that) : n(that.n) {}
|
||||
CustomAddressOfClass& operator=(CustomAddressOfClass const& rhs) { n = rhs.n; return *this; }
|
||||
explicit CustomAddressOfClass(int m) : n(m) {}
|
||||
int* operator& () { return &n; }
|
||||
bool operator== (CustomAddressOfClass const& that) const { return n == that.n; }
|
||||
};
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_CONVERTING_ASSIGNMENT
|
||||
float f = 21.22f ;
|
||||
double d = f ;
|
||||
optional<float> opt2(f) ;
|
||||
optional<double> opt3 ;
|
||||
opt3 = opt2 ;
|
||||
BOOST_CHECK(*opt3 == d);
|
||||
#endif
|
||||
void test_custom_addressof_operator()
|
||||
{
|
||||
boost::optional< CustomAddressOfClass > o1(CustomAddressOfClass(10));
|
||||
BOOST_TEST(!!o1);
|
||||
BOOST_TEST(o1.get() == CustomAddressOfClass(10));
|
||||
|
||||
o1 = CustomAddressOfClass(20);
|
||||
BOOST_TEST(!!o1);
|
||||
BOOST_TEST(o1.get() == CustomAddressOfClass(20));
|
||||
|
||||
o1 = boost::none;
|
||||
BOOST_TEST(!o1);
|
||||
}
|
||||
|
||||
void test_conversions2()
|
||||
{
|
||||
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
||||
|
||||
char c = 20 ;
|
||||
optional<int> opt(c);
|
||||
BOOST_CHECK( get(opt) == static_cast<int>(c));
|
||||
|
||||
float f = 21.22f ;
|
||||
optional<double> opt1;
|
||||
opt1 = f ;
|
||||
BOOST_CHECK(*get(&opt1) == static_cast<double>(f));
|
||||
}
|
||||
|
||||
int test_main( int, char* [] )
|
||||
int main()
|
||||
{
|
||||
try
|
||||
{
|
||||
test_with_class_type();
|
||||
test_with_builtin_types();
|
||||
test_no_implicit_conversions();
|
||||
test_conversions1();
|
||||
test_conversions2();
|
||||
test_custom_addressof_operator();
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
BOOST_ERROR("Unexpected Exception caught!");
|
||||
}
|
||||
|
||||
return 0;
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
|
||||
|
30
test/optional_test_assign.cpp
Normal file
30
test/optional_test_assign.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright (C) 2018 Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
|
||||
#include "boost/core/lightweight_test.hpp"
|
||||
#include "boost/optional/optional.hpp"
|
||||
|
||||
void test_assignment_to_empty()
|
||||
{
|
||||
// this test used to fail on GCC 8.1.0/8.2.0/9.0.0 with -std=c++98
|
||||
boost::optional<int> oa, ob(1);
|
||||
BOOST_TEST(!oa);
|
||||
BOOST_TEST(ob);
|
||||
|
||||
oa = ob;
|
||||
BOOST_TEST(oa);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_assignment_to_empty();
|
||||
return boost::report_errors();
|
||||
}
|
83
test/optional_test_cmp_none.cpp
Normal file
83
test/optional_test_cmp_none.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
// Copyright (C) 2014 Andrzej Krzemienski.
|
||||
// Copyright (C) 2024 Alexander Grund
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
|
||||
#include "boost/optional/optional.hpp"
|
||||
|
||||
#ifdef BOOST_BORLANDC
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#include "boost/core/lightweight_test.hpp"
|
||||
#include "boost/none.hpp"
|
||||
|
||||
|
||||
struct SemiRegular // no operator==
|
||||
{
|
||||
private: void operator==(SemiRegular const&) const {}
|
||||
private: void operator!=(SemiRegular const&) const {}
|
||||
};
|
||||
|
||||
void test_equal_to_none_of_noncomparable_T()
|
||||
{
|
||||
boost::optional<SemiRegular> i = SemiRegular();
|
||||
boost::optional<SemiRegular> o;
|
||||
|
||||
BOOST_TEST(i != boost::none);
|
||||
BOOST_TEST(boost::none != i);
|
||||
BOOST_TEST(o == boost::none);
|
||||
BOOST_TEST(boost::none == o);
|
||||
}
|
||||
|
||||
void test_comparison_to_none()
|
||||
{
|
||||
using boost::none;
|
||||
boost::optional<SemiRegular> i = SemiRegular();
|
||||
// the default ordering of optional<size_t> is{ boost::none, 0, 1, 2, ... }
|
||||
// Hence boost::none < i for any engaged i
|
||||
// and all others operators ( ==, !=, <, <=, >, >= ) follow
|
||||
|
||||
BOOST_TEST(!(i == none));
|
||||
BOOST_TEST(i != none);
|
||||
BOOST_TEST(!(i < none));
|
||||
BOOST_TEST(!(i <= none));
|
||||
BOOST_TEST(i > none);
|
||||
BOOST_TEST(i >= none);
|
||||
// Comparison is symmetric
|
||||
BOOST_TEST(!(none == i));
|
||||
BOOST_TEST(none != i);
|
||||
BOOST_TEST(none < i);
|
||||
BOOST_TEST(none <= i);
|
||||
BOOST_TEST(!(none > i));
|
||||
BOOST_TEST(!(none >= i));
|
||||
|
||||
// An un-engaged optional is always equal to none
|
||||
boost::optional<SemiRegular> o;
|
||||
BOOST_TEST(o == none);
|
||||
BOOST_TEST(!(o != none));
|
||||
BOOST_TEST(!(o < none));
|
||||
BOOST_TEST(o <= none);
|
||||
BOOST_TEST(!(o > none));
|
||||
BOOST_TEST(o >= none);
|
||||
// Comparison is symmetric
|
||||
BOOST_TEST(none == o);
|
||||
BOOST_TEST(!(none != o));
|
||||
BOOST_TEST(!(none < o));
|
||||
BOOST_TEST(none <= o);
|
||||
BOOST_TEST(!(none > o));
|
||||
BOOST_TEST(none >= o);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_equal_to_none_of_noncomparable_T();
|
||||
return boost::report_errors();
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
// Copyright (C) 2014, Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -9,6 +10,8 @@
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
|
||||
#ifdef ENABLE_TRACE
|
||||
#define TRACE(msg) std::cout << msg << std::endl ;
|
||||
#else
|
||||
@ -37,7 +40,6 @@ void assertion_failed (char const * expr, char const * func, char const * file,
|
||||
|
||||
using boost::optional ;
|
||||
|
||||
template<class T> inline void unused_variable ( T ) {}
|
||||
|
||||
#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
|
||||
using boost::swap ;
|
||||
@ -49,12 +51,14 @@ using boost::get_pointer ;
|
||||
// via the safe_bool operator.
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1300) ) // 1300 == VC++ 7.1
|
||||
#define BOOST_OPTIONAL_NO_NULL_COMPARE
|
||||
#else
|
||||
#define BOOST_OPTIONAL_NO_NULL_COMPARE // Andrzej: I also disable 0 comparison everywhere
|
||||
#endif
|
||||
|
||||
#define ARG(T) (static_cast< T const* >(0))
|
||||
|
||||
//
|
||||
// Helper class used to verify the lifetime managment of the values held by optional
|
||||
// Helper class used to verify the lifetime management of the values held by optional
|
||||
//
|
||||
class X
|
||||
{
|
||||
@ -148,21 +152,21 @@ bool X::pending_assign = false ;
|
||||
bool X::throw_on_copy = false ;
|
||||
bool X::throw_on_assign = false ;
|
||||
|
||||
inline void set_pending_copy ( X const* x ) { X::pending_copy = true ; }
|
||||
inline void set_pending_dtor ( X const* x ) { X::pending_dtor = true ; }
|
||||
inline void set_pending_assign ( X const* x ) { X::pending_assign = true ; }
|
||||
inline void set_throw_on_copy ( X const* x ) { X::throw_on_copy = true ; }
|
||||
inline void set_throw_on_assign ( X const* x ) { X::throw_on_assign = true ; }
|
||||
inline void reset_throw_on_copy ( X const* x ) { X::throw_on_copy = false ; }
|
||||
inline void reset_throw_on_assign ( X const* x ) { X::throw_on_assign = false ; }
|
||||
inline void check_is_pending_copy ( X const* x ) { BOOST_CHECK( X::pending_copy ) ; }
|
||||
inline void check_is_pending_dtor ( X const* x ) { BOOST_CHECK( X::pending_dtor ) ; }
|
||||
inline void check_is_pending_assign ( X const* x ) { BOOST_CHECK( X::pending_assign ) ; }
|
||||
inline void check_is_not_pending_copy ( X const* x ) { BOOST_CHECK( !X::pending_copy ) ; }
|
||||
inline void check_is_not_pending_dtor ( X const* x ) { BOOST_CHECK( !X::pending_dtor ) ; }
|
||||
inline void check_is_not_pending_assign( X const* x ) { BOOST_CHECK( !X::pending_assign ) ; }
|
||||
inline void check_instance_count ( int c, X const* x ) { BOOST_CHECK( X::count == c ) ; }
|
||||
inline int get_instance_count ( X const* x ) { return X::count ; }
|
||||
inline void set_pending_copy ( X const* ) { X::pending_copy = true ; }
|
||||
inline void set_pending_dtor ( X const* ) { X::pending_dtor = true ; }
|
||||
inline void set_pending_assign ( X const* ) { X::pending_assign = true ; }
|
||||
inline void set_throw_on_copy ( X const* ) { X::throw_on_copy = true ; }
|
||||
inline void set_throw_on_assign ( X const* ) { X::throw_on_assign = true ; }
|
||||
inline void reset_throw_on_copy ( X const* ) { X::throw_on_copy = false ; }
|
||||
inline void reset_throw_on_assign ( X const* ) { X::throw_on_assign = false ; }
|
||||
inline void check_is_pending_copy ( X const* ) { BOOST_TEST( X::pending_copy ) ; }
|
||||
inline void check_is_pending_dtor ( X const* ) { BOOST_TEST( X::pending_dtor ) ; }
|
||||
inline void check_is_pending_assign ( X const* ) { BOOST_TEST( X::pending_assign ) ; }
|
||||
inline void check_is_not_pending_copy ( X const* ) { BOOST_TEST( !X::pending_copy ) ; }
|
||||
inline void check_is_not_pending_dtor ( X const* ) { BOOST_TEST( !X::pending_dtor ) ; }
|
||||
inline void check_is_not_pending_assign( X const* ) { BOOST_TEST( !X::pending_assign ) ; }
|
||||
inline void check_instance_count ( int c, X const* ) { BOOST_TEST( X::count == c ) ; }
|
||||
inline int get_instance_count ( X const* ) { return X::count ; }
|
||||
|
||||
inline void set_pending_copy (...) {}
|
||||
inline void set_pending_dtor (...) {}
|
||||
@ -185,21 +189,27 @@ template<class T>
|
||||
inline void check_uninitialized_const ( optional<T> const& opt )
|
||||
{
|
||||
#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
|
||||
BOOST_CHECK( opt == 0 ) ;
|
||||
BOOST_TEST( opt == 0 ) ;
|
||||
#endif
|
||||
BOOST_CHECK( !opt ) ;
|
||||
BOOST_CHECK( !get_pointer(opt) ) ;
|
||||
BOOST_CHECK( !opt.get_ptr() ) ;
|
||||
BOOST_TEST( !opt ) ;
|
||||
BOOST_TEST( !get_pointer(opt) ) ;
|
||||
BOOST_TEST( !opt.get_ptr() ) ;
|
||||
BOOST_TEST( !opt.has_value() ) ;
|
||||
BOOST_TEST( !opt.is_initialized() ) ;
|
||||
BOOST_TEST( opt == boost::none ) ;
|
||||
}
|
||||
template<class T>
|
||||
inline void check_uninitialized ( optional<T>& opt )
|
||||
{
|
||||
#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
|
||||
BOOST_CHECK( opt == 0 ) ;
|
||||
BOOST_TEST( opt == 0 ) ;
|
||||
#endif
|
||||
BOOST_CHECK( !opt ) ;
|
||||
BOOST_CHECK( !get_pointer(opt) ) ;
|
||||
BOOST_CHECK( !opt.get_ptr() ) ;
|
||||
BOOST_TEST( !opt ) ;
|
||||
BOOST_TEST( !get_pointer(opt) ) ;
|
||||
BOOST_TEST( !opt.get_ptr() ) ;
|
||||
BOOST_TEST( !opt.has_value() ) ;
|
||||
BOOST_TEST( !opt.is_initialized() ) ;
|
||||
BOOST_TEST( opt == boost::none ) ;
|
||||
|
||||
check_uninitialized_const(opt);
|
||||
}
|
||||
@ -207,29 +217,35 @@ inline void check_uninitialized ( optional<T>& opt )
|
||||
template<class T>
|
||||
inline void check_initialized_const ( optional<T> const& opt )
|
||||
{
|
||||
BOOST_CHECK( opt ) ;
|
||||
BOOST_TEST( opt ) ;
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
|
||||
BOOST_CHECK( opt != 0 ) ;
|
||||
BOOST_TEST( opt != 0 ) ;
|
||||
#endif
|
||||
|
||||
BOOST_CHECK ( !!opt ) ;
|
||||
BOOST_CHECK ( get_pointer(opt) ) ;
|
||||
BOOST_CHECK ( opt.get_ptr() ) ;
|
||||
BOOST_TEST ( !!opt ) ;
|
||||
BOOST_TEST ( get_pointer(opt) ) ;
|
||||
BOOST_TEST ( opt.get_ptr() ) ;
|
||||
BOOST_TEST ( opt.has_value() ) ;
|
||||
BOOST_TEST ( opt.is_initialized() ) ;
|
||||
BOOST_TEST ( opt != boost::none ) ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void check_initialized ( optional<T>& opt )
|
||||
{
|
||||
BOOST_CHECK( opt ) ;
|
||||
BOOST_TEST( opt ) ;
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
|
||||
BOOST_CHECK( opt != 0 ) ;
|
||||
BOOST_TEST( opt != 0 ) ;
|
||||
#endif
|
||||
|
||||
BOOST_CHECK ( !!opt ) ;
|
||||
BOOST_CHECK ( get_pointer(opt) ) ;
|
||||
BOOST_CHECK ( opt.get_ptr() ) ;
|
||||
BOOST_TEST ( !!opt ) ;
|
||||
BOOST_TEST ( get_pointer(opt) ) ;
|
||||
BOOST_TEST ( opt.get_ptr() ) ;
|
||||
BOOST_TEST ( opt.has_value() ) ;
|
||||
BOOST_TEST ( opt.is_initialized() ) ;
|
||||
BOOST_TEST ( opt != boost::none ) ;
|
||||
|
||||
check_initialized_const(opt);
|
||||
}
|
||||
@ -237,12 +253,12 @@ inline void check_initialized ( optional<T>& opt )
|
||||
template<class T>
|
||||
inline void check_value_const ( optional<T> const& opt, T const& v, T const& z )
|
||||
{
|
||||
BOOST_CHECK( *opt == v ) ;
|
||||
BOOST_CHECK( *opt != z ) ;
|
||||
BOOST_CHECK( opt.get() == v ) ;
|
||||
BOOST_CHECK( opt.get() != z ) ;
|
||||
BOOST_CHECK( (*(opt.operator->()) == v) ) ;
|
||||
BOOST_CHECK( *get_pointer(opt) == v ) ;
|
||||
BOOST_TEST( *opt == v ) ;
|
||||
BOOST_TEST( *opt != z ) ;
|
||||
BOOST_TEST( opt.get() == v ) ;
|
||||
BOOST_TEST( opt.get() != z ) ;
|
||||
BOOST_TEST( (*(opt.operator->()) == v) ) ;
|
||||
BOOST_TEST( *get_pointer(opt) == v ) ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@ -254,12 +270,12 @@ inline void check_value ( optional<T>& opt, T const& v, T const& z )
|
||||
reset_throw_on_copy( ARG(T) ) ;
|
||||
#endif
|
||||
|
||||
BOOST_CHECK( *opt == v ) ;
|
||||
BOOST_CHECK( *opt != z ) ;
|
||||
BOOST_CHECK( opt.get() == v ) ;
|
||||
BOOST_CHECK( opt.get() != z ) ;
|
||||
BOOST_CHECK( (*(opt.operator->()) == v) ) ;
|
||||
BOOST_CHECK( *get_pointer(opt) == v ) ;
|
||||
BOOST_TEST( *opt == v ) ;
|
||||
BOOST_TEST( *opt != z ) ;
|
||||
BOOST_TEST( opt.get() == v ) ;
|
||||
BOOST_TEST( opt.get() != z ) ;
|
||||
BOOST_TEST( (*(opt.operator->()) == v) ) ;
|
||||
BOOST_TEST( *get_pointer(opt) == v ) ;
|
||||
|
||||
check_value_const(opt,v,z);
|
||||
}
|
59
test/optional_test_constructible_from_other.cpp
Normal file
59
test/optional_test_constructible_from_other.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright (c) 2018 Andrey Semashev
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// The test verifies that Boost.Optional copy constructors do not attempt to invoke
|
||||
// the element type initializing constructors from templated arguments
|
||||
|
||||
#include <boost/optional/optional.hpp>
|
||||
#include <boost/core/enable_if.hpp>
|
||||
|
||||
struct no_type
|
||||
{
|
||||
char data;
|
||||
};
|
||||
|
||||
struct yes_type
|
||||
{
|
||||
char data[2];
|
||||
};
|
||||
|
||||
template< unsigned int Size >
|
||||
struct size_tag {};
|
||||
|
||||
template< typename T, typename U >
|
||||
struct is_constructible
|
||||
{
|
||||
static U& get();
|
||||
|
||||
template< typename T1 >
|
||||
static yes_type check_helper(size_tag< sizeof(static_cast< T1 >(get())) >*);
|
||||
template< typename T1 >
|
||||
static no_type check_helper(...);
|
||||
|
||||
static const bool value = sizeof(check_helper< T >(0)) == sizeof(yes_type);
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
class wrapper
|
||||
{
|
||||
public:
|
||||
wrapper() {}
|
||||
wrapper(wrapper const&) {}
|
||||
template< typename U >
|
||||
wrapper(U const&, typename boost::enable_if_c< is_constructible< T, U >::value, int >::type = 0) {}
|
||||
};
|
||||
|
||||
inline boost::optional< wrapper< int > > foo()
|
||||
{
|
||||
return boost::optional< wrapper< int > >();
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// Invokes boost::optional copy constructor. Should not invoke wrapper constructor from U.
|
||||
boost::optional< wrapper< int > > res = foo();
|
||||
return 0;
|
||||
}
|
111
test/optional_test_conversions_from_U.cpp
Normal file
111
test/optional_test_conversions_from_U.cpp
Normal file
@ -0,0 +1,111 @@
|
||||
// Copyright (C) 2014 Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at: akrzemi1@gmail.com
|
||||
|
||||
|
||||
#include "boost/optional/optional.hpp"
|
||||
|
||||
#ifdef BOOST_BORLANDC
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#include "boost/core/lightweight_test.hpp"
|
||||
|
||||
using boost::optional;
|
||||
|
||||
|
||||
// testing types:
|
||||
// X is convertible to Y
|
||||
// ADeriv is convertible to ABase
|
||||
struct X
|
||||
{
|
||||
int val;
|
||||
explicit X(int v) : val(v) {}
|
||||
};
|
||||
|
||||
struct Y
|
||||
{
|
||||
int yval;
|
||||
Y(X const& x) : yval(x.val) {}
|
||||
friend bool operator==(Y const& l, Y const& r) { return l.yval == r.yval; }
|
||||
};
|
||||
|
||||
struct ABase
|
||||
{
|
||||
int val;
|
||||
explicit ABase(int v) : val(v) {}
|
||||
friend bool operator==(ABase const& l, ABase const& r) { return l.val == r.val; }
|
||||
};
|
||||
|
||||
struct ADeriv : ABase
|
||||
{
|
||||
explicit ADeriv(int v) : ABase(v) {}
|
||||
};
|
||||
|
||||
|
||||
template <typename T, typename U>
|
||||
void test_convert_optional_U_to_optional_T_for()
|
||||
{
|
||||
#ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR
|
||||
{
|
||||
optional<U> ou(U(8));
|
||||
optional<T> ot1(ou);
|
||||
BOOST_TEST(ot1);
|
||||
BOOST_TEST(*ot1 == T(*ou));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_CONVERTING_ASSIGNMENT
|
||||
{
|
||||
optional<U> ou(U(8));
|
||||
optional<T> ot2;
|
||||
ot2 = ou;
|
||||
BOOST_TEST(ot2);
|
||||
BOOST_TEST(*ot2 == T(*ou));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_convert_optional_U_to_optional_T()
|
||||
{
|
||||
test_convert_optional_U_to_optional_T_for<Y, X>();
|
||||
test_convert_optional_U_to_optional_T_for<ABase, ADeriv>();
|
||||
test_convert_optional_U_to_optional_T_for<long, short>();
|
||||
test_convert_optional_U_to_optional_T_for<double, float>();
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
void test_convert_U_to_optional_T_for()
|
||||
{
|
||||
U u(8);
|
||||
optional<T> ot1(u);
|
||||
BOOST_TEST(ot1);
|
||||
BOOST_TEST(*ot1 == T(u));
|
||||
|
||||
optional<T> ot2;
|
||||
ot2 = u;
|
||||
BOOST_TEST(ot2);
|
||||
BOOST_TEST(*ot2 == T(u));
|
||||
}
|
||||
|
||||
void test_convert_U_to_optional_T()
|
||||
{
|
||||
test_convert_U_to_optional_T_for<Y, X>();
|
||||
test_convert_U_to_optional_T_for<ABase, ADeriv>();
|
||||
test_convert_U_to_optional_T_for<long, short>();
|
||||
test_convert_U_to_optional_T_for<double, float>();
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_convert_optional_U_to_optional_T();
|
||||
test_convert_U_to_optional_T();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
56
test/optional_test_convert_assign.cpp
Normal file
56
test/optional_test_convert_assign.cpp
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright (C) 2021 Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
|
||||
#include "boost/optional/optional.hpp"
|
||||
|
||||
#include "boost/core/lightweight_test.hpp"
|
||||
#include "boost/none.hpp"
|
||||
|
||||
//#ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR
|
||||
|
||||
using boost::optional;
|
||||
|
||||
struct implicit_bool_conv
|
||||
{
|
||||
operator bool() const { return false; }
|
||||
};
|
||||
|
||||
struct explicit_bool_conv
|
||||
{
|
||||
explicit operator bool() const BOOST_NOEXCEPT { return true; }
|
||||
};
|
||||
|
||||
template <typename To, typename From>
|
||||
void test_convert_assign()
|
||||
{
|
||||
optional<To> oi;
|
||||
oi = From();
|
||||
BOOST_TEST(oi);
|
||||
}
|
||||
|
||||
void test_no_bad_assignment()
|
||||
{
|
||||
#if !defined(BOOST_NO_CXX11_DECLTYPE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800)
|
||||
// this means that type trait `boost::is_assignable` works.
|
||||
BOOST_STATIC_ASSERT((boost::is_assignable<optional<bool>&, bool>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_assignable<optional<bool>&, implicit_bool_conv>::value));
|
||||
BOOST_STATIC_ASSERT((! boost::is_assignable<optional<bool>&, explicit_bool_conv>::value));
|
||||
#endif
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_convert_assign<int, short>();
|
||||
test_convert_assign<bool, implicit_bool_conv>();
|
||||
test_no_bad_assignment();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
70
test/optional_test_convert_from_T.cpp
Normal file
70
test/optional_test_convert_from_T.cpp
Normal file
@ -0,0 +1,70 @@
|
||||
// Copyright (C) 2014 Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
|
||||
#include "boost/optional/optional.hpp"
|
||||
|
||||
#ifdef BOOST_BORLANDC
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#include "boost/core/lightweight_test.hpp"
|
||||
#include "boost/none.hpp"
|
||||
|
||||
//#ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR
|
||||
|
||||
using boost::optional;
|
||||
using boost::none;
|
||||
|
||||
template <typename U>
|
||||
struct superconv
|
||||
{
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
||||
template <typename T>
|
||||
superconv(T&&) { BOOST_STATIC_ASSERT(sizeof(T) == 0); }
|
||||
#else
|
||||
template <typename T>
|
||||
superconv(const T&) { BOOST_STATIC_ASSERT(sizeof(T) == 0); }
|
||||
template <typename T>
|
||||
superconv( T&) { BOOST_STATIC_ASSERT(sizeof(T) == 0); }
|
||||
#endif
|
||||
|
||||
superconv() {}
|
||||
};
|
||||
|
||||
void test_optional_of_superconverting_T() // compile-time test
|
||||
{
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_NO_IS_CONSTRUCTIBLE_TRAIT
|
||||
superconv<optional<int> > s;
|
||||
superconv<optional<int> > & rs = s;
|
||||
optional<superconv<optional<int> > > os = rs;
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_optional_optional_T()
|
||||
{
|
||||
optional<int> oi1 (1), oiN;
|
||||
optional< optional<int> > ooi1 (oi1), ooiN(oiN);
|
||||
|
||||
BOOST_TEST(ooi1);
|
||||
BOOST_TEST(*ooi1);
|
||||
BOOST_TEST_EQ(**ooi1, 1);
|
||||
|
||||
BOOST_TEST(ooiN);
|
||||
BOOST_TEST(!*ooiN);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_optional_optional_T();
|
||||
test_optional_of_superconverting_T();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
66
test/optional_test_deleted_default_ctor.cpp
Normal file
66
test/optional_test_deleted_default_ctor.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
// Copyright 2017 Peter Dimov
|
||||
// Copyright 2017 Vinnie Falco
|
||||
// Copyright 2018 Andrzej Krzemienski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
//
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
|
||||
|
||||
int main()
|
||||
{
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
#include <utility>
|
||||
|
||||
class basic_multi_buffer;
|
||||
|
||||
class const_buffers_type // a similar declaration in boost.beast had problem
|
||||
{ // with boost optional
|
||||
basic_multi_buffer const* b_;
|
||||
|
||||
friend class basic_multi_buffer;
|
||||
|
||||
explicit
|
||||
const_buffers_type(basic_multi_buffer const& b);
|
||||
|
||||
public:
|
||||
const_buffers_type() = delete;
|
||||
const_buffers_type(const_buffers_type const&) = default;
|
||||
const_buffers_type& operator=(const_buffers_type const&) = default;
|
||||
};
|
||||
|
||||
void test_beast_example()
|
||||
{
|
||||
// test if it even compiles
|
||||
boost::optional< std::pair<const_buffers_type, int> > opt, opt2;
|
||||
opt = opt2;
|
||||
(void)opt;
|
||||
}
|
||||
|
||||
struct NotDefaultConstructible // minimal class exposing the problem
|
||||
{
|
||||
NotDefaultConstructible() = delete;
|
||||
};
|
||||
|
||||
void test_assign_for_non_default_constructible()
|
||||
{
|
||||
// test if it even compiles
|
||||
boost::optional<NotDefaultConstructible> opt, opt2;
|
||||
opt = opt2;
|
||||
(void)opt;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_beast_example();
|
||||
test_assign_for_non_default_constructible();
|
||||
}
|
||||
|
||||
#endif
|
390
test/optional_test_emplace.cpp
Normal file
390
test/optional_test_emplace.cpp
Normal file
@ -0,0 +1,390 @@
|
||||
// Copyright (C) 2014 Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
|
||||
#include "boost/optional/optional.hpp"
|
||||
|
||||
#ifdef BOOST_BORLANDC
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include "boost/core/lightweight_test.hpp"
|
||||
#include "boost/none.hpp"
|
||||
|
||||
//#ifndef BOOST_OPTIONAL_NO_CONVERTING_ASSIGNMENT
|
||||
//#ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR
|
||||
|
||||
using boost::optional;
|
||||
using boost::none;
|
||||
using boost::in_place_init;
|
||||
using boost::in_place_init_if;
|
||||
|
||||
#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
class Guard
|
||||
{
|
||||
public:
|
||||
int which_ctor;
|
||||
Guard () : which_ctor(0) { }
|
||||
Guard (int&, double&&) : which_ctor(1) { }
|
||||
Guard (int&&, double&) : which_ctor(2) { }
|
||||
Guard (int&&, double&&) : which_ctor(3) { }
|
||||
Guard (int&, double&) : which_ctor(4) { }
|
||||
Guard (std::string const&) : which_ctor(5) { }
|
||||
Guard (std::string &) : which_ctor(6) { }
|
||||
Guard (std::string &&) : which_ctor(7) { }
|
||||
private:
|
||||
Guard(Guard&&);
|
||||
Guard(Guard const&);
|
||||
void operator=(Guard &&);
|
||||
void operator=(Guard const&);
|
||||
};
|
||||
|
||||
|
||||
void test_emplace()
|
||||
{
|
||||
int i = 0;
|
||||
double d = 0.0;
|
||||
const std::string cs;
|
||||
std::string ms;
|
||||
optional<Guard> o;
|
||||
|
||||
o.emplace();
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(0 == o->which_ctor);
|
||||
|
||||
o.emplace(i, 2.0);
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(1 == o->which_ctor);
|
||||
|
||||
o.emplace(1, d);
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(2 == o->which_ctor);
|
||||
|
||||
o.emplace(1, 2.0);
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(3 == o->which_ctor);
|
||||
|
||||
o.emplace(i, d);
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(4 == o->which_ctor);
|
||||
|
||||
o.emplace(cs);
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(5 == o->which_ctor);
|
||||
|
||||
o.emplace(ms);
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(6 == o->which_ctor);
|
||||
|
||||
o.emplace(std::string());
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(7 == o->which_ctor);
|
||||
}
|
||||
|
||||
void test_in_place_ctor()
|
||||
{
|
||||
int i = 0;
|
||||
double d = 0.0;
|
||||
const std::string cs;
|
||||
std::string ms;
|
||||
|
||||
{
|
||||
optional<Guard> o (in_place_init);
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(0 == o->which_ctor);
|
||||
}
|
||||
{
|
||||
optional<Guard> o (in_place_init, i, 2.0);
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(1 == o->which_ctor);
|
||||
}
|
||||
{
|
||||
optional<Guard> o (in_place_init, 1, d);
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(2 == o->which_ctor);
|
||||
}
|
||||
{
|
||||
optional<Guard> o (in_place_init, 1, 2.0);
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(3 == o->which_ctor);
|
||||
}
|
||||
{
|
||||
optional<Guard> o (in_place_init, i, d);
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(4 == o->which_ctor);
|
||||
}
|
||||
{
|
||||
optional<Guard> o (in_place_init, cs);
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(5 == o->which_ctor);
|
||||
}
|
||||
{
|
||||
optional<Guard> o (in_place_init, ms);
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(6 == o->which_ctor);
|
||||
}
|
||||
{
|
||||
optional<Guard> o (in_place_init, std::string());
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(7 == o->which_ctor);
|
||||
}
|
||||
}
|
||||
|
||||
void test_in_place_if_ctor()
|
||||
{
|
||||
int i = 0;
|
||||
double d = 0.0;
|
||||
const std::string cs;
|
||||
std::string ms;
|
||||
|
||||
{
|
||||
optional<Guard> o (in_place_init_if, true);
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(0 == o->which_ctor);
|
||||
}
|
||||
{
|
||||
optional<Guard> o (in_place_init_if, true, i, 2.0);
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(1 == o->which_ctor);
|
||||
}
|
||||
{
|
||||
optional<Guard> o (in_place_init_if, true, 1, d);
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(2 == o->which_ctor);
|
||||
}
|
||||
{
|
||||
optional<Guard> o (in_place_init_if, true, 1, 2.0);
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(3 == o->which_ctor);
|
||||
}
|
||||
{
|
||||
optional<Guard> o (in_place_init_if, true, i, d);
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(4 == o->which_ctor);
|
||||
}
|
||||
{
|
||||
optional<Guard> o (in_place_init_if, true, cs);
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(5 == o->which_ctor);
|
||||
}
|
||||
{
|
||||
optional<Guard> o (in_place_init_if, true, ms);
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(6 == o->which_ctor);
|
||||
}
|
||||
{
|
||||
optional<Guard> o (in_place_init_if, true, std::string());
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(7 == o->which_ctor);
|
||||
}
|
||||
|
||||
{
|
||||
optional<Guard> o (in_place_init_if, false, 1, 2.0);
|
||||
BOOST_TEST(!o);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
|
||||
|
||||
|
||||
struct ThrowOnMove
|
||||
{
|
||||
ThrowOnMove(ThrowOnMove&&) { throw int(); }
|
||||
ThrowOnMove(ThrowOnMove const&) { throw int(); }
|
||||
ThrowOnMove(int){}
|
||||
};
|
||||
|
||||
|
||||
void test_no_moves_on_emplacement()
|
||||
{
|
||||
try {
|
||||
optional<ThrowOnMove> o;
|
||||
o.emplace(1);
|
||||
BOOST_TEST(o);
|
||||
}
|
||||
catch (...) {
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
|
||||
void test_no_moves_on_in_place_ctor()
|
||||
{
|
||||
try {
|
||||
optional<ThrowOnMove> o (in_place_init, 1);
|
||||
BOOST_TEST(o);
|
||||
|
||||
optional<ThrowOnMove> p (in_place_init_if, true, 1);
|
||||
BOOST_TEST(p);
|
||||
|
||||
optional<ThrowOnMove> q (in_place_init_if, false, 1);
|
||||
BOOST_TEST(!q);
|
||||
}
|
||||
catch (...) {
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
struct Thrower
|
||||
{
|
||||
Thrower(bool throw_) { if (throw_) throw int(); }
|
||||
|
||||
private:
|
||||
Thrower(Thrower const&);
|
||||
#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
|
||||
Thrower(Thrower&&);
|
||||
#endif
|
||||
};
|
||||
|
||||
void test_clear_on_throw()
|
||||
{
|
||||
optional<Thrower> ot;
|
||||
try {
|
||||
ot.emplace(false);
|
||||
BOOST_TEST(ot);
|
||||
} catch(...) {
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
|
||||
try {
|
||||
ot.emplace(true);
|
||||
BOOST_TEST(false);
|
||||
} catch(...) {
|
||||
BOOST_TEST(!ot);
|
||||
}
|
||||
}
|
||||
|
||||
void test_no_assignment_on_emplacement()
|
||||
{
|
||||
optional<const std::string> os, ot;
|
||||
BOOST_TEST(!os);
|
||||
os.emplace("wow");
|
||||
BOOST_TEST(os);
|
||||
BOOST_TEST_EQ(*os, "wow");
|
||||
|
||||
BOOST_TEST(!ot);
|
||||
ot.emplace();
|
||||
BOOST_TEST(ot);
|
||||
BOOST_TEST_EQ(*ot, "");
|
||||
}
|
||||
|
||||
namespace no_rvalue_refs {
|
||||
|
||||
class Guard
|
||||
{
|
||||
public:
|
||||
int which_ctor;
|
||||
Guard () : which_ctor(0) { }
|
||||
Guard (std::string const&) : which_ctor(5) { }
|
||||
Guard (std::string &) : which_ctor(6) { }
|
||||
private:
|
||||
Guard(Guard const&);
|
||||
void operator=(Guard const&);
|
||||
};
|
||||
|
||||
void test_emplace()
|
||||
{
|
||||
const std::string cs;
|
||||
std::string ms;
|
||||
optional<Guard> o;
|
||||
|
||||
o.emplace();
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(0 == o->which_ctor);
|
||||
|
||||
o.emplace(cs);
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(5 == o->which_ctor);
|
||||
|
||||
o.emplace(ms);
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(6 == o->which_ctor);
|
||||
}
|
||||
|
||||
void test_in_place_ctor()
|
||||
{
|
||||
const std::string cs;
|
||||
std::string ms;
|
||||
|
||||
{
|
||||
optional<Guard> o (in_place_init);
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(0 == o->which_ctor);
|
||||
}
|
||||
{
|
||||
optional<Guard> o (in_place_init, cs);
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(5 == o->which_ctor);
|
||||
}
|
||||
{
|
||||
optional<Guard> o (in_place_init, ms);
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(6 == o->which_ctor);
|
||||
}
|
||||
}
|
||||
|
||||
void test_in_place_if_ctor()
|
||||
{
|
||||
const std::string cs;
|
||||
std::string ms;
|
||||
|
||||
{
|
||||
optional<Guard> n (in_place_init_if, false);
|
||||
BOOST_TEST(!n);
|
||||
|
||||
optional<Guard> o (in_place_init_if, true);
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(0 == o->which_ctor);
|
||||
}
|
||||
{
|
||||
optional<Guard> n (in_place_init_if, false, cs);
|
||||
BOOST_TEST(!n);
|
||||
|
||||
optional<Guard> o (in_place_init_if, true, cs);
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(5 == o->which_ctor);
|
||||
}
|
||||
{
|
||||
optional<Guard> n (in_place_init_if, false, ms);
|
||||
BOOST_TEST(!n);
|
||||
|
||||
optional<Guard> o (in_place_init_if, true, ms);
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(6 == o->which_ctor);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace no_rvalue_ref
|
||||
|
||||
int main()
|
||||
{
|
||||
#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
test_emplace();
|
||||
test_in_place_ctor();
|
||||
test_in_place_if_ctor();
|
||||
#endif
|
||||
#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
|
||||
test_no_moves_on_emplacement();
|
||||
test_no_moves_on_in_place_ctor();
|
||||
#endif
|
||||
test_clear_on_throw();
|
||||
test_no_assignment_on_emplacement();
|
||||
no_rvalue_refs::test_emplace();
|
||||
no_rvalue_refs::test_in_place_ctor();
|
||||
no_rvalue_refs::test_in_place_if_ctor();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
57
test/optional_test_empty_braces.cpp
Normal file
57
test/optional_test_empty_braces.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
// Copyright (C) 2016 Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
|
||||
#include "boost/optional/optional.hpp"
|
||||
|
||||
#ifdef BOOST_BORLANDC
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#include "boost/core/lightweight_test.hpp"
|
||||
|
||||
//#ifndef BOOST_OPTIONAL_NO_CONVERTING_ASSIGNMENT
|
||||
//#ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR
|
||||
|
||||
using boost::optional;
|
||||
|
||||
struct Value
|
||||
{
|
||||
explicit Value(int) {}
|
||||
};
|
||||
|
||||
#ifndef BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX
|
||||
template <typename T>
|
||||
void test_brace_init()
|
||||
{
|
||||
optional<T> o = {};
|
||||
BOOST_TEST(!o);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void test_brace_assign()
|
||||
{
|
||||
optional<T> o;
|
||||
o = {};
|
||||
BOOST_TEST(!o);
|
||||
}
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifndef BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX
|
||||
test_brace_init<int>();
|
||||
test_brace_init<Value>();
|
||||
test_brace_assign<int>();
|
||||
test_brace_assign<Value>();
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
152
test/optional_test_experimental_traits.cpp
Normal file
152
test/optional_test_experimental_traits.cpp
Normal file
@ -0,0 +1,152 @@
|
||||
// Copyright (C) 2017 Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
|
||||
#include "boost/optional/optional.hpp"
|
||||
|
||||
#ifdef BOOST_BORLANDC
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#include "boost/core/lightweight_test.hpp"
|
||||
#include "boost/core/lightweight_test_trait.hpp"
|
||||
#include "boost/type_traits/is_base_of.hpp"
|
||||
#include "boost/optional/detail/experimental_traits.hpp"
|
||||
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS
|
||||
|
||||
struct PrivDefault
|
||||
{
|
||||
private: PrivDefault() {}
|
||||
};
|
||||
|
||||
struct CustDefault
|
||||
{
|
||||
CustDefault() {}
|
||||
};
|
||||
|
||||
struct CustomizedTrivial
|
||||
{
|
||||
CustomizedTrivial() {}
|
||||
};
|
||||
|
||||
struct DeletedDefault
|
||||
{
|
||||
BOOST_DELETED_FUNCTION(DeletedDefault())
|
||||
};
|
||||
|
||||
namespace boost { namespace optional_config {
|
||||
|
||||
template <> struct optional_uses_direct_storage_for<CustomizedTrivial> : boost::true_type {};
|
||||
|
||||
}}
|
||||
|
||||
struct CustDtor
|
||||
{
|
||||
~CustDtor() {}
|
||||
};
|
||||
|
||||
struct NoDefault
|
||||
{
|
||||
explicit NoDefault(int) {}
|
||||
};
|
||||
|
||||
struct Empty {};
|
||||
|
||||
template <typename T, typename U>
|
||||
struct Aggregate { T t; U u; };
|
||||
|
||||
struct CustAssign
|
||||
{
|
||||
CustAssign& operator=(CustAssign const&) { return *this; }
|
||||
};
|
||||
|
||||
struct CustMove
|
||||
{
|
||||
CustMove(CustMove &&) {}
|
||||
};
|
||||
|
||||
void test_type_traits()
|
||||
{
|
||||
// this only tests if type traits are implemented correctly
|
||||
BOOST_TEST_TRAIT_TRUE(( boost::optional_config::optional_uses_direct_storage_for<int> ));
|
||||
BOOST_TEST_TRAIT_TRUE(( boost::optional_config::optional_uses_direct_storage_for<double> ));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE(( boost::optional_config::optional_uses_direct_storage_for<CustomizedTrivial> ));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for<PrivDefault> ));
|
||||
BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for<NoDefault> ));
|
||||
BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for<CustDefault> ));
|
||||
BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for<Aggregate<int, CustDefault> > ));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for<CustDtor> ));
|
||||
BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for<CustAssign> ));
|
||||
BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for<CustMove> ));
|
||||
BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for<Aggregate<int, CustMove> > ));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular<int> ));
|
||||
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular<double> ));
|
||||
|
||||
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
|
||||
BOOST_TEST_TRAIT_TRUE(( boost::optional_config::optional_uses_direct_storage_for<Empty> ));
|
||||
BOOST_TEST_TRAIT_TRUE(( boost::optional_config::optional_uses_direct_storage_for<Aggregate<int, double> > ));
|
||||
BOOST_TEST_TRAIT_TRUE(( boost::optional_config::optional_uses_direct_storage_for<Aggregate<Aggregate<Empty, int>, double> > ));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular<Empty> ));
|
||||
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular<Aggregate<int, double> > ));
|
||||
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular<Aggregate<Aggregate<Empty, int>, double> > ));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular<PrivDefault> ));
|
||||
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular<NoDefault> ));
|
||||
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular<CustDefault> ));
|
||||
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular<Aggregate<int, CustDefault> > ));
|
||||
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular<DeletedDefault> ));
|
||||
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular<Aggregate<int, DeletedDefault> > ));
|
||||
#endif
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for<DeletedDefault> ));
|
||||
BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for<Aggregate<int, DeletedDefault> > ));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_trivially_semiregular<CustDtor> ));
|
||||
BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_trivially_semiregular<CustAssign> ));
|
||||
BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_trivially_semiregular<CustMove> ));
|
||||
BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_trivially_semiregular<Aggregate<int, CustMove> > ));
|
||||
}
|
||||
|
||||
void test_trivial_copyability()
|
||||
{
|
||||
BOOST_TEST_TRAIT_TRUE((boost::is_base_of<boost::optional_detail::tc_optional_base<int>, boost::optional<int> > ));
|
||||
BOOST_TEST_TRAIT_TRUE((boost::is_base_of<boost::optional_detail::tc_optional_base<double>, boost::optional<double> > ));
|
||||
BOOST_TEST_TRAIT_TRUE((boost::is_base_of<boost::optional_detail::tc_optional_base<CustomizedTrivial>, boost::optional<CustomizedTrivial> > ));
|
||||
BOOST_TEST_TRAIT_FALSE((boost::is_base_of<boost::optional_detail::tc_optional_base<DeletedDefault>, boost::optional<DeletedDefault> > ));
|
||||
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
|
||||
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular<boost::optional<int> > ));
|
||||
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular<boost::optional<double> > ));
|
||||
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular<boost::optional<CustomizedTrivial> > ));
|
||||
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular<boost::optional<Empty> > ));
|
||||
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular<boost::optional<Aggregate<int, double> > > ));
|
||||
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular<boost::optional<Aggregate<Aggregate<Empty, int>, double> > > ));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_trivially_semiregular<boost::optional<DeletedDefault> > ));
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS
|
||||
test_type_traits();
|
||||
test_trivial_copyability();
|
||||
#endif
|
||||
return boost::report_errors();
|
||||
}
|
@ -15,7 +15,7 @@
|
||||
// THIS TEST SHOULD FAIL TO COMPILE
|
||||
//
|
||||
#if BOOST_WORKAROUND( BOOST_INTEL_CXX_VERSION, <= 700) // Intel C++ 7.0
|
||||
// Interl C++ 7.0 incorrectly accepts the initialization "boost::optional<int> opt = 3"
|
||||
// Intel C++ 7.0 incorrectly accepts the initialization "boost::optional<int> opt = 3"
|
||||
// even though the ctor is explicit (c.f. 12.3.1.2), so the test uses another form of
|
||||
// copy-initialization: argument-passing (8.5.12)
|
||||
void helper ( boost::optional<int> ) ;
|
||||
|
@ -13,14 +13,16 @@
|
||||
|
||||
#include "boost/optional.hpp"
|
||||
|
||||
struct A {} ;
|
||||
struct B {} ;
|
||||
//
|
||||
// THIS TEST SHOULD FAIL TO COMPILE
|
||||
//
|
||||
void test_no_unsupported_conversion()
|
||||
{
|
||||
boost::optional<int> opt1(1) ;
|
||||
boost::optional< std::string > opt2 ;
|
||||
opt2 = opt1 ; // Cannot convert from "int" to "std::string"
|
||||
boost::optional<A> opt1;
|
||||
boost::optional<B> opt2;
|
||||
opt2 = opt1 ; // Cannot convert from "A" to "B"
|
||||
}
|
||||
|
||||
|
||||
|
26
test/optional_test_fail_const_swap.cpp
Normal file
26
test/optional_test_fail_const_swap.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright (C) 2018, Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
|
||||
#include "boost/optional.hpp"
|
||||
|
||||
// THIS TEST SHOULD FAIL TO COMPILE
|
||||
|
||||
void test_converting_assignment_of_different_enums()
|
||||
{
|
||||
const boost::optional<int> o1(1);
|
||||
const boost::optional<int> o2(2);
|
||||
swap(o1, o2); // no swap on const objects should compile
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_converting_assignment_of_different_enums();
|
||||
}
|
26
test/optional_test_fail_convert_assign_of_enums.cpp
Normal file
26
test/optional_test_fail_convert_assign_of_enums.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright (C) 2015, Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
|
||||
#include "boost/optional.hpp"
|
||||
|
||||
// THIS TEST SHOULD FAIL TO COMPILE
|
||||
|
||||
enum E1 {e1};
|
||||
enum E2 {e2};
|
||||
|
||||
void test_converting_assignment_of_different_enums()
|
||||
{
|
||||
boost::optional<E2> o2(e2);
|
||||
boost::optional<E1> o1;
|
||||
o1 = o2;
|
||||
}
|
||||
|
||||
int main() {}
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
// Copyright (C) 2014, Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -7,17 +7,19 @@
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
// akrzemi1@gmail.com
|
||||
//
|
||||
#include "boost/optional.hpp"
|
||||
|
||||
//
|
||||
// THIS TEST SHOULD FAIL TO COMPILE
|
||||
//
|
||||
void optional_reference__test_no_ptr_access()
|
||||
|
||||
struct NoInitFromNull{};
|
||||
|
||||
void test_conversion_from_null()
|
||||
{
|
||||
boost::optional<int&> opt ;
|
||||
opt.get_ptr();
|
||||
boost::optional<NoInitFromNull> opt = 0;
|
||||
}
|
||||
|
||||
|
36
test/optional_test_fail_copying_a_moveable_type.cpp
Normal file
36
test/optional_test_fail_copying_a_moveable_type.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright (C) 2014, Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
//
|
||||
#include "boost/optional.hpp"
|
||||
|
||||
class MoveOnly
|
||||
{
|
||||
public:
|
||||
int val;
|
||||
MoveOnly(int v) : val(v) {}
|
||||
MoveOnly(MoveOnly&& rhs) : val(rhs.val) { rhs.val = 0; }
|
||||
void operator=(MoveOnly&& rhs) {val = rhs.val; rhs.val = 0; }
|
||||
|
||||
private:
|
||||
MoveOnly(MoveOnly const&);
|
||||
void operator=(MoveOnly const&);
|
||||
};
|
||||
|
||||
//
|
||||
// THIS TEST SHOULD FAIL TO COMPILE
|
||||
//
|
||||
void test_copying_optional_with_noncopyable_T()
|
||||
{
|
||||
boost::optional<MoveOnly> opt1 ;
|
||||
boost::optional<MoveOnly> opt2(opt1) ;
|
||||
}
|
||||
|
||||
|
32
test/optional_test_fail_explicit_convert_in_value_or.cpp
Normal file
32
test/optional_test_fail_explicit_convert_in_value_or.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright (C) 2014, Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
//
|
||||
#include "boost/optional.hpp"
|
||||
|
||||
//
|
||||
// THIS TEST SHOULD FAIL TO COMPILE
|
||||
//
|
||||
|
||||
struct U
|
||||
{};
|
||||
|
||||
struct T
|
||||
{
|
||||
explicit T(U const&) {}
|
||||
};
|
||||
|
||||
|
||||
void test_implicit_conversion_to_bool()
|
||||
{
|
||||
boost::optional<T> opt;
|
||||
opt.value_or(U());
|
||||
}
|
||||
|
@ -0,0 +1,34 @@
|
||||
// Copyright (C) 2014, Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
//
|
||||
#include "boost/optional.hpp"
|
||||
|
||||
//
|
||||
// THIS TEST SHOULD FAIL TO COMPILE
|
||||
//
|
||||
|
||||
struct U
|
||||
{};
|
||||
|
||||
struct T
|
||||
{
|
||||
explicit T(U const&) {}
|
||||
};
|
||||
|
||||
U get_U() { return U(); }
|
||||
|
||||
|
||||
void test_verifying_the_implicit_conversion_to_bool()
|
||||
{
|
||||
boost::optional<T> opt;
|
||||
opt.value_or_eval(get_U);
|
||||
}
|
||||
|
28
test/optional_test_fail_implicit_bool_convert.cpp
Normal file
28
test/optional_test_fail_implicit_bool_convert.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright (C) 2014, Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
//
|
||||
#include "boost/optional.hpp"
|
||||
|
||||
//
|
||||
// THIS TEST SHOULD FAIL TO COMPILE
|
||||
//
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
|
||||
|
||||
bool test_implicit_conversion_to_bool()
|
||||
{
|
||||
boost::optional<int> opt;
|
||||
return opt;
|
||||
}
|
||||
|
||||
#else
|
||||
# error "Test skipped: this compiler does not support explicit conversion operators."
|
||||
#endif
|
24
test/optional_test_fail_io_without_io.cpp
Normal file
24
test/optional_test_fail_io_without_io.cpp
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright (C) 2015, Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
|
||||
#include <iostream>
|
||||
#include "boost/optional.hpp"
|
||||
// but no boost/optional/optional_io.hpp
|
||||
|
||||
// THIS TEST SHOULD FAIL TO COMPILE
|
||||
// Unless one includes header boost/optional/optional_io.hpp, it should not be possible
|
||||
// to stream out an optional object.
|
||||
|
||||
void test_streaming_out_optional()
|
||||
{
|
||||
boost::optional<int> opt;
|
||||
std::cout << opt;
|
||||
}
|
23
test/optional_test_fail_none_io_without_io.cpp
Normal file
23
test/optional_test_fail_none_io_without_io.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright (C) 2015, Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
|
||||
#include <iostream>
|
||||
#include "boost/none.hpp"
|
||||
// but no boost/optional/optional_io.hpp
|
||||
|
||||
// THIS TEST SHOULD FAIL TO COMPILE
|
||||
// Unless one includes header boost/optional/optional_io.hpp, it should not be possible
|
||||
// to stream out boost::none.
|
||||
|
||||
void test_streaming_out_none()
|
||||
{
|
||||
std::cout << boost::none;
|
||||
}
|
19
test/optional_test_fail_optional_rvalue_ref.cpp
Normal file
19
test/optional_test_fail_optional_rvalue_ref.cpp
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright (C) 2014, Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
//
|
||||
#include "boost/optional.hpp"
|
||||
//
|
||||
// THIS TEST SHOULD FAIL TO COMPILE
|
||||
//
|
||||
|
||||
boost::optional<int&&> oi;
|
||||
|
||||
|
275
test/optional_test_flat_map.cpp
Normal file
275
test/optional_test_flat_map.cpp
Normal file
@ -0,0 +1,275 @@
|
||||
// Copyright (C) 2018 Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
|
||||
#include "boost/optional/optional.hpp"
|
||||
|
||||
#ifdef BOOST_BORLANDC
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#include "boost/core/ignore_unused.hpp"
|
||||
#include "boost/core/lightweight_test.hpp"
|
||||
#include "boost/core/lightweight_test_trait.hpp"
|
||||
#include "boost/type_traits/is_same.hpp"
|
||||
|
||||
|
||||
using boost::optional;
|
||||
using boost::make_optional;
|
||||
using boost::is_same;
|
||||
|
||||
template <typename Expected, typename Deduced>
|
||||
void verify_type(Deduced)
|
||||
{
|
||||
BOOST_TEST_TRAIT_TRUE(( is_same<Expected, Deduced> ));
|
||||
}
|
||||
|
||||
struct Int
|
||||
{
|
||||
int i;
|
||||
explicit Int(int i_) : i(i_) {}
|
||||
};
|
||||
|
||||
struct convert_t
|
||||
{
|
||||
typedef optional<Int> result_type;
|
||||
optional<Int> operator()(int i) { if (i != 0) return Int(i); else return boost::none; }
|
||||
};
|
||||
|
||||
void test_flat_map_on_mutable_optional_with_function_object()
|
||||
{
|
||||
{
|
||||
optional<int> oi (1);
|
||||
verify_type< optional<Int> >(oi.flat_map(convert_t()));
|
||||
optional<Int> oI = oi.flat_map(convert_t());
|
||||
BOOST_TEST(bool(oI));
|
||||
BOOST_TEST_EQ(1, oI->i);
|
||||
}
|
||||
{
|
||||
optional<int> oi (0);
|
||||
optional<Int> oI = oi.flat_map(convert_t());
|
||||
BOOST_TEST(!oI);
|
||||
}
|
||||
{
|
||||
optional<int> oi;
|
||||
optional<Int> oI = oi.flat_map(convert_t());
|
||||
BOOST_TEST(!oI);
|
||||
}
|
||||
}
|
||||
|
||||
void test_flat_map_on_const_optional_with_function_object()
|
||||
{
|
||||
{
|
||||
const optional<int> oi (1);
|
||||
verify_type< optional<Int> >(oi.flat_map(convert_t()));
|
||||
optional<Int> oI = oi.flat_map(convert_t());
|
||||
BOOST_TEST(bool(oI));
|
||||
BOOST_TEST_EQ(1, oI->i);
|
||||
}
|
||||
{
|
||||
const optional<int> oi (0);
|
||||
optional<Int> oI = oi.flat_map(convert_t());
|
||||
BOOST_TEST(!oI);
|
||||
}
|
||||
{
|
||||
const optional<int> oi;
|
||||
optional<Int> oI = oi.flat_map(convert_t());
|
||||
BOOST_TEST(!oI);
|
||||
}
|
||||
}
|
||||
|
||||
void test_flat_map_with_lambda()
|
||||
{
|
||||
#if !defined BOOST_NO_CXX11_LAMBDAS && !defined BOOST_NO_CXX11_DECLTYPE_N3276
|
||||
{
|
||||
optional<int> oi (1);
|
||||
verify_type< optional<Int> >(oi.flat_map([](int i){ return optional<Int>(i == 0, Int(i)); }));
|
||||
optional<Int> oI = oi.flat_map([](int i){ return optional<Int>(i != 0, Int(i)); });
|
||||
BOOST_TEST(bool(oI));
|
||||
BOOST_TEST_EQ(1, oI->i);
|
||||
}
|
||||
{
|
||||
optional<int> oi (0);
|
||||
optional<Int> oI = oi.flat_map([](int i){ return optional<Int>(i != 0, Int(i)); });
|
||||
BOOST_TEST(!oI);
|
||||
}
|
||||
{
|
||||
optional<int> oi;
|
||||
optional<Int> oI = oi.flat_map([](int i){ return optional<Int>(i != 0, Int(i)); });
|
||||
BOOST_TEST(!oI);
|
||||
}
|
||||
#endif // lambdas
|
||||
}
|
||||
|
||||
struct get_opt_ref
|
||||
{
|
||||
typedef optional<int&> result_type;
|
||||
optional<int&> operator()(int& i) { return i != 0 ? optional<int&>(i) : optional<int&>(); }
|
||||
};
|
||||
|
||||
void test_flat_map_obj_to_ref()
|
||||
{
|
||||
{
|
||||
optional<int> oi (2);
|
||||
verify_type< optional<int&> >(oi.flat_map(get_opt_ref()));
|
||||
optional<int&> ori = oi.flat_map(get_opt_ref());
|
||||
BOOST_TEST(bool(ori));
|
||||
BOOST_TEST_EQ(2, *ori);
|
||||
*ori = 3;
|
||||
BOOST_TEST(bool(oi));
|
||||
BOOST_TEST_EQ(3, *oi);
|
||||
BOOST_TEST_EQ(3, *ori);
|
||||
}
|
||||
{
|
||||
optional<int> oi (0);
|
||||
optional<int&> ori = oi.flat_map(get_opt_ref());
|
||||
BOOST_TEST(!ori);
|
||||
}
|
||||
{
|
||||
optional<int> oi;
|
||||
optional<int&> ori = oi.flat_map(get_opt_ref());
|
||||
BOOST_TEST(!ori);
|
||||
}
|
||||
}
|
||||
|
||||
optional<int&> get_opt_int_ref(Int& i)
|
||||
{
|
||||
return i.i ? optional<int&>(i.i) : optional<int&>();
|
||||
}
|
||||
|
||||
void test_flat_map_ref_to_ref()
|
||||
{
|
||||
{
|
||||
Int I (5);
|
||||
optional<Int&> orI (I);
|
||||
verify_type< optional<int&> >(orI.flat_map(get_opt_int_ref));
|
||||
optional<int&> ori = orI.flat_map(get_opt_int_ref);
|
||||
BOOST_TEST(bool(ori));
|
||||
BOOST_TEST_EQ(5, *ori);
|
||||
*ori = 6;
|
||||
BOOST_TEST_EQ(6, *ori);
|
||||
BOOST_TEST_EQ(6, I.i);
|
||||
}
|
||||
{
|
||||
Int I (0);
|
||||
optional<Int&> orI (I);
|
||||
optional<int&> ori = orI.flat_map(get_opt_int_ref);
|
||||
BOOST_TEST(!ori);
|
||||
}
|
||||
{
|
||||
optional<Int&> orI;
|
||||
optional<int&> ori = orI.flat_map(get_opt_int_ref);
|
||||
BOOST_TEST(!ori);
|
||||
}
|
||||
}
|
||||
|
||||
optional< optional<Int> > make_opt_int(int i)
|
||||
{
|
||||
if (i == 0)
|
||||
return boost::none;
|
||||
else if (i == 1)
|
||||
return boost::make_optional(optional<Int>());
|
||||
else
|
||||
return boost::make_optional(boost::make_optional(Int(i)));
|
||||
}
|
||||
|
||||
void test_flat_map_opt_opt()
|
||||
{
|
||||
{
|
||||
optional<int> oi (9);
|
||||
verify_type<optional<optional<Int> > >(oi.flat_map(make_opt_int));
|
||||
optional<optional<Int> > ooI = oi.flat_map(make_opt_int);
|
||||
BOOST_TEST(bool(ooI));
|
||||
BOOST_TEST(bool(*ooI));
|
||||
BOOST_TEST_EQ(9, (**ooI).i);
|
||||
}
|
||||
{
|
||||
optional<int> oi (1);
|
||||
optional<optional<Int> > ooI = oi.flat_map(make_opt_int);
|
||||
BOOST_TEST(bool(ooI));
|
||||
BOOST_TEST(!*ooI);
|
||||
}
|
||||
{
|
||||
optional<int> oi (0);
|
||||
optional<optional<Int> > ooI = oi.flat_map(make_opt_int);
|
||||
BOOST_TEST(!ooI);
|
||||
}
|
||||
{
|
||||
optional<int> oi;
|
||||
optional<optional<Int> > ooI = oi.flat_map(make_opt_int);
|
||||
BOOST_TEST(!ooI);
|
||||
}
|
||||
}
|
||||
|
||||
#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
|
||||
struct MoveOnly
|
||||
{
|
||||
int value;
|
||||
explicit MoveOnly(int i) : value(i) {}
|
||||
MoveOnly(MoveOnly && r) : value(r.value) { r.value = 0; }
|
||||
MoveOnly& operator=(MoveOnly && r) { value = r.value; r.value = 0; return *this; }
|
||||
|
||||
private:
|
||||
MoveOnly(MoveOnly const&);
|
||||
void operator=(MoveOnly const&);
|
||||
};
|
||||
|
||||
MoveOnly makeMoveOnly(int i)
|
||||
{
|
||||
return MoveOnly(i);
|
||||
}
|
||||
|
||||
optional<MoveOnly> makeOptMoveOnly(int i)
|
||||
{
|
||||
return optional<MoveOnly>(MoveOnly(i));
|
||||
}
|
||||
|
||||
optional<int> get_val(MoveOnly m)
|
||||
{
|
||||
return optional<int>(m.value != 0, m.value);
|
||||
}
|
||||
|
||||
void test_flat_map_move_only()
|
||||
{
|
||||
{
|
||||
optional<MoveOnly> om (makeMoveOnly(1)), om2 (makeMoveOnly(2));
|
||||
verify_type<optional<int> >(boost::move(om).flat_map(get_val));
|
||||
optional<int> oi = boost::move(om2).flat_map(get_val);
|
||||
BOOST_TEST(bool(oi));
|
||||
BOOST_TEST_EQ(2, *oi);
|
||||
}
|
||||
{
|
||||
optional<int> oj = makeOptMoveOnly(4).flat_map(get_val);
|
||||
BOOST_TEST(bool(oj));
|
||||
BOOST_TEST_EQ(4, *oj);
|
||||
}
|
||||
{
|
||||
optional<int> oj = optional<MoveOnly>().flat_map(get_val);
|
||||
BOOST_TEST(!oj);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // no rvalue refs
|
||||
|
||||
int main()
|
||||
{
|
||||
test_flat_map_on_mutable_optional_with_function_object();
|
||||
test_flat_map_on_const_optional_with_function_object();
|
||||
test_flat_map_with_lambda();
|
||||
test_flat_map_obj_to_ref();
|
||||
test_flat_map_ref_to_ref();
|
||||
test_flat_map_opt_opt();
|
||||
|
||||
#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
|
||||
test_flat_map_move_only();
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
64
test/optional_test_hash.cpp
Normal file
64
test/optional_test_hash.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
// Copyright (C) 2014 Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
|
||||
#include "boost/optional/optional.hpp"
|
||||
#include "boost/config.hpp"
|
||||
#include "boost/core/lightweight_test.hpp"
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_SET) && !defined(BOOST_OPTIONAL_CONFIG_DO_NOT_SPECIALIZE_STD_HASH)
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
void test_unordered_map()
|
||||
{
|
||||
std::unordered_set<boost::optional<int> > set;
|
||||
set.insert(boost::optional<int>(1));
|
||||
set.insert(boost::optional<int>(1));
|
||||
|
||||
|
||||
BOOST_TEST(set.size() == 1u);
|
||||
BOOST_TEST(set.find(boost::optional<int>(1)) != set.end());
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void test_unordered_map()
|
||||
{}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(BOOST_OPTIONAL_CONFIG_DO_NOT_SPECIALIZE_STD_HASH) && !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
|
||||
|
||||
void tets_hash()
|
||||
{
|
||||
std::hash<boost::optional<int> > hash_int;
|
||||
boost::optional<int> oN;
|
||||
boost::optional<int> o1(1);
|
||||
|
||||
BOOST_TEST(hash_int(oN) == hash_int(oN));
|
||||
BOOST_TEST(hash_int(o1) == hash_int(o1));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void tets_hash()
|
||||
{}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
test_unordered_map();
|
||||
tets_hash();
|
||||
return boost::report_errors();
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
#include<iostream>
|
||||
#include<stdexcept>
|
||||
#include<string>
|
||||
|
||||
#define BOOST_ENABLE_ASSERT_HANDLER
|
||||
|
||||
#include "boost/optional/optional.hpp"
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
#include "boost/utility/in_place_factory.hpp"
|
||||
#include "boost/utility/typed_in_place_factory.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#include "boost/test/minimal.hpp"
|
||||
|
||||
#include "optional_test_common.cpp"
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
struct A
|
||||
{
|
||||
A ( double a0, std::string a1 ) : m_a0(a0), m_a1(a1) {}
|
||||
|
||||
friend bool operator == ( A const& x, A const& y )
|
||||
{ return x.m_a0 == y.m_a0 && x.m_a1 == y.m_a1 ; }
|
||||
|
||||
double m_a0 ;
|
||||
std::string m_a1 ;
|
||||
} ;
|
||||
|
||||
int test_main( int, char* [] )
|
||||
{
|
||||
double a00 = 3.14, a10 = 6.02e-23;
|
||||
std::string a01("pi"), a11("mol");
|
||||
|
||||
A a0(a00,a01);
|
||||
A a1(a10,a11);
|
||||
|
||||
boost::optional<A> opt1(a0);
|
||||
|
||||
boost::optional<A> opt2 ( boost::in_place(a00,a01) ) ;
|
||||
|
||||
boost::optional<A> opt3 ( boost::in_place<A>(a00,a01) ) ;
|
||||
|
||||
BOOST_CHECK( opt1 == opt2 ) ;
|
||||
BOOST_CHECK( opt2 == opt2 ) ;
|
||||
BOOST_CHECK( *opt2 == a0 ) ;
|
||||
|
||||
#ifndef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
|
||||
|
||||
opt2 = boost::in_place(a10,a11);
|
||||
BOOST_CHECK( *opt2 == a1 ) ;
|
||||
|
||||
opt3 = boost::in_place<A>(a10,a11);
|
||||
BOOST_CHECK( *opt3 == a1 ) ;
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int test_main( int, char* [] )
|
||||
{
|
||||
// If in-place factories are not supported there is nothing to test
|
||||
return 0 ;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
113
test/optional_test_inplace_factory.cpp
Normal file
113
test/optional_test_inplace_factory.cpp
Normal file
@ -0,0 +1,113 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
// Copyright (C) 2015 Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
|
||||
#include<string>
|
||||
#include "boost/optional/optional.hpp"
|
||||
|
||||
#ifdef BOOST_BORLANDC
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
#include "boost/utility/in_place_factory.hpp"
|
||||
#include "boost/utility/typed_in_place_factory.hpp"
|
||||
#endif
|
||||
|
||||
#include "boost/core/lightweight_test.hpp"
|
||||
#include "boost/none.hpp"
|
||||
|
||||
struct Guard
|
||||
{
|
||||
double num;
|
||||
std::string str;
|
||||
Guard() : num() {}
|
||||
Guard(double num_, std::string str_) : num(num_), str(str_) {}
|
||||
|
||||
friend bool operator==(const Guard& lhs, const Guard& rhs) { return lhs.num == rhs.num && lhs.str == rhs.str; }
|
||||
friend bool operator!=(const Guard& lhs, const Guard& rhs) { return !(lhs == rhs); }
|
||||
|
||||
private:
|
||||
Guard(const Guard&);
|
||||
Guard& operator=(const Guard&);
|
||||
};
|
||||
|
||||
void test_ctor()
|
||||
{
|
||||
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
Guard g0, g1(1.0, "one"), g2(2.0, "two");
|
||||
|
||||
boost::optional<Guard> og0 ( boost::in_place() );
|
||||
boost::optional<Guard> og1 ( boost::in_place(1.0, "one") );
|
||||
boost::optional<Guard> og1_( boost::in_place(1.0, "one") );
|
||||
boost::optional<Guard> og2 ( boost::in_place<Guard>(2.0, "two") );
|
||||
|
||||
BOOST_TEST(og0);
|
||||
BOOST_TEST(og1);
|
||||
BOOST_TEST(og1_);
|
||||
BOOST_TEST(og2);
|
||||
|
||||
BOOST_TEST(*og0 == g0);
|
||||
BOOST_TEST(*og1 == g1);
|
||||
BOOST_TEST(*og1_ == g1);
|
||||
BOOST_TEST(*og2 == g2);
|
||||
|
||||
BOOST_TEST(og1_ == og1);
|
||||
BOOST_TEST(og1_ != og2);
|
||||
BOOST_TEST(og1_ != og0);
|
||||
|
||||
boost::optional<unsigned int> o( boost::in_place(5) );
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(*o == 5);
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_assign()
|
||||
{
|
||||
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
#ifndef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
|
||||
Guard g0, g1(1.0, "one"), g2(2.0, "two");
|
||||
|
||||
boost::optional<Guard> og0, og1, og1_, og2;
|
||||
|
||||
og0 = boost::in_place();
|
||||
og1 = boost::in_place(1.0, "one");
|
||||
og1_ = boost::in_place(1.0, "one");
|
||||
og2 = boost::in_place<Guard>(2.0, "two");
|
||||
|
||||
BOOST_TEST(og0);
|
||||
BOOST_TEST(og1);
|
||||
BOOST_TEST(og1_);
|
||||
BOOST_TEST(og2);
|
||||
|
||||
BOOST_TEST(*og0 == g0);
|
||||
BOOST_TEST(*og1 == g1);
|
||||
BOOST_TEST(*og1_ == g1);
|
||||
BOOST_TEST(*og2 == g2);
|
||||
|
||||
BOOST_TEST(og1_ == og1);
|
||||
BOOST_TEST(og1_ != og2);
|
||||
BOOST_TEST(og1_ != og0);
|
||||
|
||||
boost::optional<unsigned int> o;
|
||||
o = boost::in_place(5);
|
||||
BOOST_TEST(o);
|
||||
BOOST_TEST(*o == 5);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_ctor();
|
||||
test_assign();
|
||||
return boost::report_errors();
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
// Copyright (C) 2015 Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -8,53 +9,45 @@
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
#include<iostream>
|
||||
#include<stdexcept>
|
||||
|
||||
#include<string>
|
||||
|
||||
#define BOOST_ENABLE_ASSERT_HANDLER
|
||||
|
||||
#include "boost/optional/optional.hpp"
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
#include "boost/utility/in_place_factory.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#ifdef BOOST_BORLANDC
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#include "boost/test/minimal.hpp"
|
||||
|
||||
#include "optional_test_common.cpp"
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
struct A
|
||||
{
|
||||
A ( double a0, std::string a1 ) : m_a0(a0), m_a1(a1) {}
|
||||
|
||||
friend bool operator == ( A const& x, A const& y )
|
||||
{ return x.m_a0 == y.m_a0 && x.m_a1 == y.m_a1 ; }
|
||||
|
||||
double m_a0 ;
|
||||
std::string m_a1 ;
|
||||
} ;
|
||||
|
||||
int test_main( int, char* [] )
|
||||
{
|
||||
int invalid_extra_parameter ;
|
||||
boost::optional<A> opt2 ( boost::in_place(3.14,"pi",invalid_extra_parameter) ) ;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int test_main( int, char* [] )
|
||||
{
|
||||
int invalid_extra_parameter ;
|
||||
boost::optional<A> opt2 ( A(3.14,"pi",invalid_extra_parameter) ) ;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#include "boost/utility/in_place_factory.hpp"
|
||||
#include "boost/utility/typed_in_place_factory.hpp"
|
||||
#endif
|
||||
|
||||
#include "boost/core/lightweight_test.hpp"
|
||||
#include "boost/none.hpp"
|
||||
|
||||
struct Guard
|
||||
{
|
||||
double num;
|
||||
std::string str;
|
||||
Guard() : num() {}
|
||||
Guard(double num_, std::string str_) : num(num_), str(str_) {}
|
||||
|
||||
friend bool operator==(const Guard& lhs, const Guard& rhs) { return lhs.num == rhs.num && lhs.str == rhs.str; }
|
||||
friend bool operator!=(const Guard& lhs, const Guard& rhs) { return !(lhs == rhs); }
|
||||
|
||||
private:
|
||||
Guard(const Guard&);
|
||||
Guard& operator=(const Guard&);
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
int excessive_param = 2;
|
||||
boost::optional<Guard> og1 ( boost::in_place(1.0, "one", excessive_param) );
|
||||
#else
|
||||
NOTHING_TO_TEST_SO_JUST_FAIL
|
||||
#endif
|
||||
return 0;
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
// Copyright (C) 2015 Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -8,55 +9,45 @@
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
#include<iostream>
|
||||
#include<stdexcept>
|
||||
|
||||
#include<string>
|
||||
|
||||
#define BOOST_ENABLE_ASSERT_HANDLER
|
||||
|
||||
#include "boost/optional/optional.hpp"
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
#include "boost/utility/typed_in_place_factory.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#ifdef BOOST_BORLANDC
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#include "boost/test/minimal.hpp"
|
||||
|
||||
#include "optional_test_common.cpp"
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
struct A
|
||||
{
|
||||
A ( double a0, std::string a1 ) : m_a0(a0), m_a1(a1) {}
|
||||
|
||||
friend bool operator == ( A const& x, A const& y )
|
||||
{ return x.m_a0 == y.m_a0 && x.m_a1 == y.m_a1 ; }
|
||||
|
||||
double m_a0 ;
|
||||
std::string m_a1 ;
|
||||
} ;
|
||||
|
||||
int test_main( int, char* [] )
|
||||
{
|
||||
// This must fail to compile.
|
||||
// The first template argument to in_place<> is the target-type,
|
||||
// not the first constructor parameter type.
|
||||
boost::optional<A> opt2 ( boost::in_place<int>(3.14,"pi") ) ;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int test_main( int, char* [] )
|
||||
{
|
||||
boost::optional<A> opt2 ( int(3.14) ) ;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#include "boost/utility/in_place_factory.hpp"
|
||||
#include "boost/utility/typed_in_place_factory.hpp"
|
||||
#endif
|
||||
|
||||
#include "boost/core/lightweight_test.hpp"
|
||||
#include "boost/none.hpp"
|
||||
|
||||
struct Guard
|
||||
{
|
||||
double num;
|
||||
std::string str;
|
||||
Guard() : num() {}
|
||||
Guard(double num_, std::string str_) : num(num_), str(str_) {}
|
||||
|
||||
friend bool operator==(const Guard& lhs, const Guard& rhs) { return lhs.num == rhs.num && lhs.str == rhs.str; }
|
||||
friend bool operator!=(const Guard& lhs, const Guard& rhs) { return !(lhs == rhs); }
|
||||
|
||||
private:
|
||||
Guard(const Guard&);
|
||||
Guard& operator=(const Guard&);
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
typedef int BAD_TARGET_TYPE;
|
||||
boost::optional<Guard> og1 ( boost::in_place<BAD_TARGET_TYPE>(1.0, "one") );
|
||||
#else
|
||||
NOTHING_TO_TEST_SO_JUST_FAIL
|
||||
#endif
|
||||
return 0;
|
||||
}
|
100
test/optional_test_io.cpp
Normal file
100
test/optional_test_io.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
// Copyright (C) 2014 Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
|
||||
#include "boost/optional/optional.hpp"
|
||||
#include "boost/optional/optional_io.hpp"
|
||||
#include "boost/core/lightweight_test.hpp"
|
||||
|
||||
#ifndef BOOST_NO_IOSTREAM
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#ifdef BOOST_BORLANDC
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
using boost::optional;
|
||||
|
||||
template<class Opt>
|
||||
void test2( Opt o, Opt buff )
|
||||
{
|
||||
std::stringstream s ;
|
||||
|
||||
const int markv = 123 ;
|
||||
int mark = 0 ;
|
||||
|
||||
s << o << " " << markv ;
|
||||
s >> buff >> mark ;
|
||||
|
||||
BOOST_TEST( buff == o ) ;
|
||||
BOOST_TEST( mark == markv ) ;
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
void test( T v, T w )
|
||||
{
|
||||
test2( boost::make_optional(v), optional<T> ());
|
||||
test2( boost::make_optional(v), boost::make_optional(w));
|
||||
test2( optional<T> () , optional<T> ());
|
||||
test2( optional<T> () , boost::make_optional(w));
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
void subtest_tag_none_reversibility_with_optional(optional<T> ov)
|
||||
{
|
||||
std::stringstream s;
|
||||
s << boost::none;
|
||||
s >> ov;
|
||||
BOOST_TEST(!ov);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void subtest_tag_none_equivalence_with_optional()
|
||||
{
|
||||
std::stringstream s, r;
|
||||
optional<T> ov;
|
||||
s << boost::none;
|
||||
r << ov;
|
||||
BOOST_TEST_EQ(s.str(), r.str());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void test_tag_none(T v)
|
||||
{
|
||||
subtest_tag_none_reversibility_with_optional(optional<T>(v));
|
||||
subtest_tag_none_reversibility_with_optional(optional<T>());
|
||||
subtest_tag_none_equivalence_with_optional<T>();
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
test(1,2);
|
||||
test(std::string("hello"), std::string("buffer"));
|
||||
test_tag_none(10);
|
||||
test_tag_none(std::string("text"));
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#else // BOOST_NO_IOSTREAM
|
||||
|
||||
int main()
|
||||
{
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#endif // BOOST_NO_IOSTREAM
|
121
test/optional_test_make_optional.cpp
Normal file
121
test/optional_test_make_optional.cpp
Normal file
@ -0,0 +1,121 @@
|
||||
// Copyright (C) 2017 Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
|
||||
#include "boost/optional/optional.hpp"
|
||||
|
||||
#ifdef BOOST_BORLANDC
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#include "boost/core/ignore_unused.hpp"
|
||||
#include "boost/core/lightweight_test.hpp"
|
||||
#include "boost/core/lightweight_test_trait.hpp"
|
||||
#include "boost/type_traits/is_same.hpp"
|
||||
|
||||
|
||||
using boost::optional;
|
||||
using boost::make_optional;
|
||||
using boost::is_same;
|
||||
|
||||
template <typename Expected, typename Deduced>
|
||||
void verify_type(Deduced)
|
||||
{
|
||||
BOOST_TEST_TRAIT_TRUE(( is_same<Expected, Deduced> ));
|
||||
}
|
||||
|
||||
#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
|
||||
struct MoveOnly
|
||||
{
|
||||
int value;
|
||||
explicit MoveOnly(int i) : value(i) {}
|
||||
MoveOnly(MoveOnly && r) : value(r.value) { r.value = 0; }
|
||||
MoveOnly& operator=(MoveOnly && r) { value = r.value; r.value = 0; return *this; }
|
||||
|
||||
private:
|
||||
MoveOnly(MoveOnly const&);
|
||||
void operator=(MoveOnly const&);
|
||||
};
|
||||
|
||||
MoveOnly makeMoveOnly(int i)
|
||||
{
|
||||
return MoveOnly(i);
|
||||
}
|
||||
|
||||
void test_make_optional_for_move_only_type()
|
||||
{
|
||||
verify_type< optional<MoveOnly> >(make_optional(makeMoveOnly(2)));
|
||||
verify_type< optional<MoveOnly> >(make_optional(true, makeMoveOnly(2)));
|
||||
|
||||
optional<MoveOnly> o1 = make_optional(makeMoveOnly(1));
|
||||
BOOST_TEST (o1);
|
||||
BOOST_TEST_EQ (1, o1->value);
|
||||
|
||||
optional<MoveOnly> o2 = make_optional(true, makeMoveOnly(2));
|
||||
BOOST_TEST (o2);
|
||||
BOOST_TEST_EQ (2, o2->value);
|
||||
|
||||
optional<MoveOnly> oN = make_optional(false, makeMoveOnly(2));
|
||||
BOOST_TEST (!oN);
|
||||
}
|
||||
|
||||
#endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
||||
|
||||
void test_make_optional_for_optional()
|
||||
{
|
||||
optional<int> oi;
|
||||
verify_type< optional< optional<int> > >(make_optional(oi));
|
||||
verify_type< optional< optional<int> > >(make_optional(true, oi));
|
||||
|
||||
optional< optional<int> > ooi = make_optional(oi);
|
||||
BOOST_TEST (ooi);
|
||||
BOOST_TEST (!*ooi);
|
||||
|
||||
optional< optional<int> > ooT = make_optional(true, oi);
|
||||
BOOST_TEST (ooT);
|
||||
BOOST_TEST (!*ooT);
|
||||
|
||||
optional< optional<int> > ooF = make_optional(false, oi);
|
||||
BOOST_TEST (!ooF);
|
||||
}
|
||||
|
||||
void test_nested_make_optional()
|
||||
{
|
||||
verify_type< optional< optional<int> > >(make_optional(make_optional(1)));
|
||||
verify_type< optional< optional<int> > >(make_optional(true, make_optional(true, 2)));
|
||||
|
||||
optional< optional<int> > oo1 = make_optional(make_optional(1));
|
||||
BOOST_TEST (oo1);
|
||||
BOOST_TEST (*oo1);
|
||||
BOOST_TEST_EQ (1, **oo1);
|
||||
|
||||
optional< optional<int> > oo2 = make_optional(true, make_optional(true, 2));
|
||||
BOOST_TEST (oo2);
|
||||
BOOST_TEST (*oo2);
|
||||
BOOST_TEST_EQ (2, **oo2);
|
||||
|
||||
optional< optional<int> > oo3 = make_optional(true, make_optional(false, 3));
|
||||
BOOST_TEST (oo3);
|
||||
BOOST_TEST (!*oo3);
|
||||
|
||||
optional< optional<int> > oo4 = make_optional(false, make_optional(true, 4));
|
||||
BOOST_TEST (!oo4);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
|
||||
test_make_optional_for_move_only_type();
|
||||
#endif
|
||||
test_make_optional_for_optional();
|
||||
test_nested_make_optional();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
192
test/optional_test_map.cpp
Normal file
192
test/optional_test_map.cpp
Normal file
@ -0,0 +1,192 @@
|
||||
// Copyright (C) 2018 Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
|
||||
#include "boost/optional/optional.hpp"
|
||||
|
||||
#ifdef BOOST_BORLANDC
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#include "boost/core/ignore_unused.hpp"
|
||||
#include "boost/core/lightweight_test.hpp"
|
||||
#include "boost/core/lightweight_test_trait.hpp"
|
||||
#include "boost/type_traits/is_same.hpp"
|
||||
|
||||
|
||||
using boost::optional;
|
||||
using boost::make_optional;
|
||||
using boost::is_same;
|
||||
|
||||
template <typename Expected, typename Deduced>
|
||||
void verify_type(Deduced)
|
||||
{
|
||||
BOOST_TEST_TRAIT_TRUE(( is_same<Expected, Deduced> ));
|
||||
}
|
||||
|
||||
#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
|
||||
struct MoveOnly
|
||||
{
|
||||
int value;
|
||||
explicit MoveOnly(int i) : value(i) {}
|
||||
MoveOnly(MoveOnly && r) : value(r.value) { r.value = 0; }
|
||||
MoveOnly& operator=(MoveOnly && r) { value = r.value; r.value = 0; return *this; }
|
||||
|
||||
private:
|
||||
MoveOnly(MoveOnly const&);
|
||||
void operator=(MoveOnly const&);
|
||||
};
|
||||
|
||||
MoveOnly makeMoveOnly(int i)
|
||||
{
|
||||
return MoveOnly(i);
|
||||
}
|
||||
|
||||
optional<MoveOnly> makeOptMoveOnly(int i)
|
||||
{
|
||||
return optional<MoveOnly>(MoveOnly(i));
|
||||
}
|
||||
|
||||
int get_val(MoveOnly m)
|
||||
{
|
||||
return m.value;
|
||||
}
|
||||
|
||||
void test_map_move_only()
|
||||
{
|
||||
optional<MoveOnly> om (makeMoveOnly(7)), om2 (makeMoveOnly(8));
|
||||
verify_type<optional<int> >(boost::move(om).map(get_val));
|
||||
optional<int> oi = boost::move(om2).map(get_val);
|
||||
BOOST_TEST(bool(oi));
|
||||
BOOST_TEST_EQ(8, *oi);
|
||||
|
||||
optional<int> oj = makeOptMoveOnly(4).map(get_val);
|
||||
BOOST_TEST(bool(oj));
|
||||
BOOST_TEST_EQ(4, *oj);
|
||||
|
||||
optional<MoveOnly> o_;
|
||||
optional<int> oi_ = boost::move(o_).map(get_val);
|
||||
BOOST_TEST(!oi_);
|
||||
}
|
||||
|
||||
#endif // no rvalue refs
|
||||
|
||||
struct Int
|
||||
{
|
||||
int i;
|
||||
explicit Int(int i_) : i(i_) {}
|
||||
};
|
||||
|
||||
struct convert_t
|
||||
{
|
||||
typedef Int result_type;
|
||||
Int operator()(int i) { return Int(i); }
|
||||
};
|
||||
|
||||
int& get_int_ref(Int& i)
|
||||
{
|
||||
return i.i;
|
||||
}
|
||||
|
||||
struct get_ref
|
||||
{
|
||||
typedef int& result_type;
|
||||
int& operator()(int& i) { return i; }
|
||||
};
|
||||
|
||||
void test_map()
|
||||
{
|
||||
optional<int> oi (1);
|
||||
verify_type<optional<Int> >(oi.map(convert_t()));
|
||||
optional<Int> oI = oi.map(convert_t());
|
||||
BOOST_TEST(bool(oI));
|
||||
BOOST_TEST_EQ(1, oI->i);
|
||||
|
||||
optional<Int> o_ = optional<int>().map(convert_t());
|
||||
BOOST_TEST(!o_);
|
||||
}
|
||||
|
||||
optional<Int> make_opt_int(int i)
|
||||
{
|
||||
if (i != 0)
|
||||
return Int(i);
|
||||
else
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
void test_map_optional()
|
||||
{
|
||||
optional<int> o9 (9), o0 (0), o_;
|
||||
verify_type<optional<optional<Int> > >(o9.map(make_opt_int));
|
||||
optional<optional<Int> > oo9 = o9.map(make_opt_int);
|
||||
BOOST_TEST(bool(oo9));
|
||||
BOOST_TEST(bool(*oo9));
|
||||
BOOST_TEST_EQ(9, (**oo9).i);
|
||||
|
||||
optional<optional<Int> > oo0 = o0.map(make_opt_int);
|
||||
BOOST_TEST(bool(oo0));
|
||||
BOOST_TEST(!*oo0);
|
||||
|
||||
optional<optional<Int> > oo_ = o_.map(make_opt_int);
|
||||
BOOST_TEST(!oo_);
|
||||
}
|
||||
|
||||
void test_map_with_lambda()
|
||||
{
|
||||
#if !defined BOOST_NO_CXX11_LAMBDAS && !defined BOOST_NO_CXX11_DECLTYPE_N3276
|
||||
optional<int> oi (1), oj(2);
|
||||
verify_type<optional<bool> >(oi.map([](int i){ return i == 1; }));
|
||||
optional<bool> ob = oi.map([](int i){ return i == 1; });
|
||||
optional<bool> oc = oj.map([](int i){ return i == 1; });
|
||||
BOOST_TEST(bool(ob));
|
||||
BOOST_TEST_EQ(true, *ob);
|
||||
BOOST_TEST(bool(oc));
|
||||
BOOST_TEST_EQ(false, *oc);
|
||||
#endif // lambdas
|
||||
}
|
||||
|
||||
void test_map_to_ref()
|
||||
{
|
||||
optional<int> oi (2);
|
||||
verify_type<optional<int&> >(oi.map(get_ref()));
|
||||
optional<int&> ori = oi.map(get_ref());
|
||||
BOOST_TEST(bool(ori));
|
||||
*ori = 3;
|
||||
BOOST_TEST(bool(oi));
|
||||
BOOST_TEST_EQ(3, *oi);
|
||||
BOOST_TEST_EQ(3, *ori);
|
||||
}
|
||||
|
||||
void test_map_optional_ref()
|
||||
{
|
||||
Int I (5);
|
||||
optional<Int&> ori (I);
|
||||
verify_type<optional<int&> >(ori.map(get_int_ref));
|
||||
optional<int&> orii = ori.map(get_int_ref);
|
||||
BOOST_TEST(bool(orii));
|
||||
BOOST_TEST_EQ(5, *orii);
|
||||
*orii = 6;
|
||||
BOOST_TEST_EQ(6, I.i);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
|
||||
test_map_move_only();
|
||||
#endif
|
||||
test_map_with_lambda();
|
||||
test_map();
|
||||
test_map_optional();
|
||||
test_map_to_ref();
|
||||
test_map_optional();
|
||||
test_map_optional_ref();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user