mirror of
https://github.com/boostorg/optional.git
synced 2025-06-26 20:41:44 +02:00
Compare commits
646 Commits
svn-tags/m
...
develop
Author | SHA1 | Date | |
---|---|---|---|
bfdf0c73f9 | |||
e1c6b5b737 | |||
1a8c2dcafd | |||
6134d0c274 | |||
121f3efde9 | |||
e210740301 | |||
c716bc552b | |||
5ad8b01512 | |||
d5a0e294a7 | |||
eab3caf7ed | |||
b8fd0bcb5f | |||
86f3288312 | |||
5e7fdf5ec5 | |||
e601f1ef2d | |||
b2c7f93ead | |||
c8bd18d6de | |||
7974207c7f | |||
c33708c1f9 | |||
2b33d57c82 | |||
76200db7c4 | |||
cfcd23d55b | |||
825f38f5b5 | |||
cacde054df | |||
1820ae55ef | |||
f91e03b35b | |||
ae15fc54b2 | |||
dc7909db4a | |||
1825c778ed | |||
f97e43ce13 | |||
cb68f6053d | |||
07b689fc3e | |||
cbfb66379b | |||
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 | |||
f89c517fa8 | |||
b831e5f88d | |||
88d002a7be | |||
dda39772ad | |||
ed504fae7b | |||
9a0013d668 | |||
361d945b5c | |||
d61baf2a94 | |||
1412c04b24 | |||
24c5f92413 | |||
07a80c1b9b | |||
7717a785de | |||
3db413cc30 | |||
46fafdb7c9 | |||
9aa4943b7a | |||
7cacecb6f9 |
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
|
614
.github/workflows/ci.yml
vendored
Normal file
614
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,614 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
- feature/**
|
||||
|
||||
env:
|
||||
UBSAN_OPTIONS: print_stacktrace=1
|
||||
|
||||
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-24.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"
|
||||
os: ubuntu-24.04
|
||||
install: clang-16
|
||||
- toolset: clang
|
||||
compiler: clang++-17
|
||||
cxxstd: "03,11,14,17,20,2b"
|
||||
os: ubuntu-24.04
|
||||
install: clang-17
|
||||
- toolset: clang
|
||||
cxxstd: "03,11,14,17,20,2b"
|
||||
os: macos-13
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
container:
|
||||
image: ${{matrix.container}}
|
||||
volumes:
|
||||
- /node20217:/node20217:rw,rshared
|
||||
- ${{ startsWith(matrix.container, 'ubuntu:1') && '/node20217:/__e/node20:ro,rshared' || ' ' }}
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
steps:
|
||||
- name: Setup container environment
|
||||
if: matrix.container
|
||||
run: |
|
||||
apt-get update
|
||||
apt-get -y install sudo python3 git g++ curl
|
||||
if [[ "${{matrix.container}}" == "ubuntu:1"* ]]; then
|
||||
# Node 20 doesn't work with Ubuntu 16/18 glibc: https://github.com/actions/checkout/issues/1590
|
||||
curl -sL https://archives.boost.io/misc/node/node-v20.9.0-linux-x64-glibc-217.tar.xz | tar -xJ --strip-components 1 -C /node20217
|
||||
fi
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- 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
|
33
CMakeLists.txt
Normal file
33
CMakeLists.txt
Normal file
@ -0,0 +1,33 @@
|
||||
# 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)
|
||||
if(NOT CMAKE_VERSION VERSION_LESS "3.19")
|
||||
file(GLOB_RECURSE headers include/*.hpp)
|
||||
target_sources(boost_optional PRIVATE ${headers})
|
||||
endif()
|
||||
|
||||
target_link_libraries(boost_optional
|
||||
INTERFACE
|
||||
Boost::assert
|
||||
Boost::config
|
||||
Boost::core
|
||||
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.
|
23
build.jam
Normal file
23
build.jam
Normal file
@ -0,0 +1,23 @@
|
||||
# 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/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
|
||||
;
|
113
doc/00_optional.qbk
Normal file
113
doc/00_optional.qbk
Normal file
@ -0,0 +1,113 @@
|
||||
[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]]
|
||||
|
||||
[/ Common terms ]
|
||||
|
||||
[def __UB__ [@https://en.cppreference.com/w/cpp/language/ub ['undefined behavior]]]
|
||||
|
||||
|
||||
[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 C++11 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:design Design Overview and Rationale]
|
||||
[include 11_development.qbk]
|
||||
[include 12_relational_operators.qbk]
|
||||
[include 13_convenience.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]
|
||||
[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]
|
||||
[section:advice Advice]
|
||||
[include 31_when_to_use.qbk]
|
||||
[include 32_on_performance.qbk]
|
||||
[endsect]
|
||||
[include 90_dependencies.qbk]
|
||||
[include 91_comparison_with_std.qbk]
|
||||
[include 92_relnotes.qbk]
|
||||
[include 93_acknowledgments.qbk]
|
195
doc/01_quick_start.qbk
Normal file
195
doc/01_quick_start.qbk
Normal file
@ -0,0 +1,195 @@
|
||||
[/
|
||||
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 Overview]
|
||||
|
||||
[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.design.in_place_factories In-Place Factories].]
|
||||
|
||||
[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]
|
||||
|
||||
[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]
|
||||
|
||||
[endsect]
|
130
doc/11_development.qbk
Normal file
130
doc/11_development.qbk
Normal file
@ -0,0 +1,130 @@
|
||||
[/
|
||||
Boost.Optional
|
||||
|
||||
Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
|
||||
Copyright (c) 2024 andrzej Krzemieński
|
||||
|
||||
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 Goals]
|
||||
|
||||
In C++ you can create an automatic object of a scalar type, and manipulate it,
|
||||
without assigning it the initial value.
|
||||
|
||||
{
|
||||
int i; // indeterminate value
|
||||
populate(&i);
|
||||
cout << i;
|
||||
}
|
||||
|
||||
Such an object is said to have ['indeterminate value]. If you subsequently
|
||||
assign a proper value to the object, all is fine; but if the program tries to
|
||||
read an indeterminate value, this is ['undefined behavior'], and since C++26
|
||||
this is ['erroneous behavior].
|
||||
In any case, the program is now likely to do something else than what the
|
||||
programmer intended. In case you have some object `i`, and you do not know if it
|
||||
has an indeterminate value, or a normal, intended, value, there is no way to
|
||||
check it, because the checking would require reading the value.
|
||||
|
||||
This is one of the primary problems that `optional` was intended to address: so
|
||||
that you may have a type that knows whether it has been assigned a proper value,
|
||||
and it can tell you that if requested.
|
||||
|
||||
In the case of type `int` the internal representation of such a class could be:
|
||||
|
||||
class OptionalInt
|
||||
{
|
||||
bool _has_value = false;
|
||||
int _value;
|
||||
};
|
||||
|
||||
In the general case, the internal representation is something equivalent to:
|
||||
|
||||
template <typename T>
|
||||
class Optional
|
||||
{
|
||||
bool _has_value = false;
|
||||
alignas(T) char _value [sizeof(T)];
|
||||
};
|
||||
|
||||
Next, because we need to pass around these "optional" `int`s as normal `int`s,
|
||||
like returning them from functions, when copying, we need to copy `_has_value`,
|
||||
which indicates whether we have the value or not, and, if we do have value, and
|
||||
only then, to also copy `_value`.
|
||||
|
||||
This means that our type requires ['deep copy] semantics.
|
||||
|
||||
[note
|
||||
This is a C++ equivalent of a
|
||||
[@https://hackage.haskell.org/package/base-4.20.0.1/docs/Data-Maybe.html Maybe]
|
||||
monad in [@http://www.haskell.org/ Haskell].
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:iface Interface Design]
|
||||
One part of the interface is for modifying and setting the initial state of
|
||||
the object. It has to be able to say that
|
||||
|
||||
* we want to store a specific value of type `T`,
|
||||
* we want to store no value.
|
||||
|
||||
The default constructor stores no value. Other than that, we require that
|
||||
the assignment and construction from a `T` reflects the former, while assignment
|
||||
and construction of a special ['tag] value `none` reflect the latter need.
|
||||
|
||||
optional<int> o1; // contains no value
|
||||
optional<int> o2 = 2; // contains value 2
|
||||
optional<int> o3 = none; // contains no value
|
||||
|
||||
o1 = 1; // assign value 1
|
||||
o2 = none; // assign a no-value
|
||||
o3 = {}; // assign a no-value
|
||||
|
||||
[heading Inspecting the State]
|
||||
|
||||
Inspecting the state of an optional object requires two steps:
|
||||
|
||||
* check if we have the value or not,
|
||||
* if so, read the stored value.
|
||||
|
||||
This 'procedure' is characteristic of inspecting pointers in C++, therefore the
|
||||
pointer-like syntax was chosen to represent this.
|
||||
|
||||
void inspect (optional<string> os)
|
||||
{
|
||||
if (os) { // contextual conversion to `bool`
|
||||
read_string(*os); // `operator*` to access the stored value
|
||||
read_int(os->size()); // `operator->` as shortcut for accessing members
|
||||
}
|
||||
}
|
||||
|
||||
Also, similarly to pointers, if you access the value when it is not there,
|
||||
you trigger __UB__.
|
||||
This library detects and reports it via
|
||||
[@../../../assert/assert.html `BOOST_ASSERT()`]. This common property of
|
||||
pointers and `optional<>` has been formalized into a concept __OPTIONAL_POINTEE__.
|
||||
|
||||
However, there is also the counter-intuitive part. All pointers embed ['shallow-copy]
|
||||
semantics: when you copy a pointer, the pointed-to object stays at the same location
|
||||
and you can access it via either of the pointers. This is unlike optional objects
|
||||
where the represented value is copied along.
|
||||
|
||||
[caution
|
||||
Optional objects are not pointers.
|
||||
]
|
||||
|
||||
There is a similar difference in relational operations: they compare deeply for
|
||||
`optional<>`, while they are shallow for pointers.
|
||||
|
||||
[note
|
||||
When you need a deep relational operations that work uniformly for `optional<>`
|
||||
and pointers in generic contexts, use functions
|
||||
[@../../../utility/OptionalPointee.html#equal `equal_pointees()`] and
|
||||
[@../../../utility/OptionalPointee.html#less `less_pointees()`].
|
||||
]
|
||||
|
||||
[endsect]
|
37
doc/12_relational_operators.qbk
Normal file
37
doc/12_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]
|
102
doc/13_convenience.qbk
Normal file
102
doc/13_convenience.qbk
Normal file
@ -0,0 +1,102 @@
|
||||
|
||||
[section Convenience Conversions and Deductions]
|
||||
|
||||
Unlike `std::optional`, `boost::optional` does not offer a number of
|
||||
"convenience" converting constructors, mixed relational operations and
|
||||
deductions for class template parameters.
|
||||
|
||||
std::optional oi = 1; // OK
|
||||
|
||||
std:string_view sv = "hi";
|
||||
std::optional<std::string> os = sv; // OK
|
||||
os == sv; // OK
|
||||
|
||||
std::optional<std::string> osv;
|
||||
std::optional<std::string> os2 = osv; // OK
|
||||
os2 == osv; // OK
|
||||
|
||||
They are practical, and sometimes stem from the argument for consistency:
|
||||
if `(optT && *optT == u)` works then `(optT == u)` should also work.
|
||||
|
||||
However, these intelligent convenience functions sometimes produce results
|
||||
that are counter to the programmer intentions and produce silent bugs.
|
||||
|
||||
Consider a more complicated example:
|
||||
|
||||
Threshold th = /*...*/;
|
||||
std::optional o = th;
|
||||
assert (o);
|
||||
|
||||
In this code, can we expect that thus initialized `optional` contains a value?
|
||||
The answer is: it depends on the type of `Threshold`. It can be defined as:
|
||||
|
||||
using Threshold = std::optional<int>;
|
||||
|
||||
And then the assertion will fire. This is because in this case the intelligence
|
||||
decides that since we already have an optional, the additional wrapping into
|
||||
a yet another optional is unnecessary.
|
||||
|
||||
If we explicitly specify the template type, the situation doesn't get less
|
||||
complicated.
|
||||
|
||||
Threshold th;
|
||||
std::optional<Threshold> o = th;
|
||||
assert(o);
|
||||
|
||||
Can this assertion fire? Now we have two competing constructors:
|
||||
|
||||
template <typename U>
|
||||
optional(U const&);
|
||||
|
||||
template <typename U>
|
||||
optional(optional<U> const&);
|
||||
|
||||
Which one will get chosen? Actually, we are lucky, and it is going to be the
|
||||
first one due to concept tricks. But let's try a different example:
|
||||
|
||||
Threshold th;
|
||||
std::optional<Threshold> o = th;
|
||||
assert(o);
|
||||
assert(o == th);
|
||||
|
||||
Here, the first assertion passes, but the second one fires. This is because
|
||||
there are two competing overloads of the comparison operator:
|
||||
|
||||
template <typename T, typename U>
|
||||
bool operator==(optional<T> const&, U const&);
|
||||
|
||||
template <typename T, typename U>
|
||||
bool operator==(optional<T> const&, optional<U> const&);
|
||||
|
||||
And this time there is no concept trickery, so the second overload is chosen,
|
||||
and gives different results: we are comparing an optional object `th`, which does
|
||||
not contain a value, with an optional object `o` which does contain a value.
|
||||
|
||||
This problem -- that the operations compile, but have runtime behavior counter
|
||||
to programmer's intuition -- gains new significance with the introduction of
|
||||
concepts to C++.
|
||||
|
||||
static_assert(std::equality_comparable_with<std::optional<Threshold>, Threshold>);
|
||||
|
||||
Concepts have both syntactic constraints and semantic constraints. Syntactic
|
||||
constraints are statically checked by the compiler. For semantic constraints,
|
||||
functions that use the concept trust the programmer that these constraints are
|
||||
met, and if not, this is __UB__.
|
||||
|
||||
These are problems with `std::optional`. `boost::optional` doesn't have these
|
||||
problems, because it does not offer the said convenience operations.
|
||||
|
||||
The design principle for `boost::optional` is not to offer functionality that
|
||||
nicely deduces the programmer intentions in 95% of the cases, and in the remaining
|
||||
5% renders effects counter to programmer expectations.
|
||||
|
||||
Instead, this library recommends using a more verbose syntax that works in 100%
|
||||
of the cases:
|
||||
|
||||
Threshold th;
|
||||
auto o = boost::make_potional(th); // *always* add a new layer of optionality
|
||||
|
||||
return boost::equal_pointees(o, th); // *always* unpack optionals for comparison
|
||||
return o && *o == th; // *always* treat the right-hand side argument as value
|
||||
|
||||
[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]
|
128
doc/16_optional_references.qbk
Normal file
128
doc/16_optional_references.qbk
Normal file
@ -0,0 +1,128 @@
|
||||
|
||||
[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.design.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]
|
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__]``
|
||||
inline constexpr 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__]``
|
||||
inline constexpr 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]
|
37
doc/31_when_to_use.qbk
Normal file
37
doc/31_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]
|
156
doc/32_on_performance.qbk
Normal file
156
doc/32_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]
|
77
doc/90_dependencies.qbk
Normal file
77
doc/90_dependencies.qbk
Normal file
@ -0,0 +1,77 @@
|
||||
[/
|
||||
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
|
||||
# static_assert
|
||||
# throw_exception
|
||||
# type_traits
|
||||
|
||||
[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]
|
48
doc/91_comparison_with_std.qbk
Normal file
48
doc/91_comparison_with_std.qbk
Normal file
@ -0,0 +1,48 @@
|
||||
[/
|
||||
Boost.Optional
|
||||
|
||||
Copyright (c) 2015 - 2024 Andrzej Krzemieński
|
||||
|
||||
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:std_comp Comparison with `std::optional`]
|
||||
|
||||
[table
|
||||
[]
|
||||
[ [[*`boost::optional`]] [[*`std::optional`]] [] ]
|
||||
[ [`optional<int> o = none;`] [`optional<int> o = nullopt;`] [Different name for no-value tag.] ]
|
||||
[ [`optional<X> o {in_place_init, a, b};`] [`optional<int> o {in_place, a, b};`] [Different name for in-place initialization tag.] ]
|
||||
[ [] [`optional<vector<int>> o {in_place, {1, 2, 3}};`
|
||||
|
||||
`o.emplace({4, 5, 6});`] [No in-place initialization with initializer-list in `boost`.] ]
|
||||
[ [`optional<X> o {in_place_init_if, cond, a, b};`] [] [No syntax for conditional in-place initialization in `std`.] ]
|
||||
[ [`optional<X> o {cond, x};`] [] [No syntax for conditional initialization from `T` in `std`.] ]
|
||||
[ [`optional<T> o {U{}};`
|
||||
|
||||
`optional<T> o {optional<U>{}};`] [`optional<T> o = U{};`
|
||||
|
||||
`optional<T> o = optional<U>{}`] [Constructors form `U` and `optional<U>` are explicit in `boost` and implicit in `std`.] ]
|
||||
[ [] [`optional o = 1;`] [No clever deduction of of `optional`'s template parameters in initialization in `boost`. ]]
|
||||
[ [`optional<X const&> o;`] [] [No optional references in `std`.] ]
|
||||
[ [] [`constexpr optional<int> o;`] [No `constexpr` interface in `boost`.] ]
|
||||
[ [`o.map(&f);`
|
||||
|
||||
`o.flat_map(&of);` ] [`o.transform(&f);`
|
||||
|
||||
`o.and_then(&of);`] [Different names and signatures for monadic interface functions. `boost` takes callbacks by value, `std` by universal reference.] ]
|
||||
[ [] [`o.or_else(&of);`] [No `or_else` function in `boost`.] ]
|
||||
[ [`o.value_or_eval(&f);`] [] [No `value_or_eval` function in `std`.] ]
|
||||
[ [] [`optional<T>{} == U{}`;
|
||||
|
||||
`optional<T>{} == optional<U>{}`] [No comparisons with `U` or `optional<U>` in `boost`.] ]
|
||||
[ [`make_optional(cond, v);`] [] [No `make_optional` with condition in `std`.] ]
|
||||
[ [] [`make_optional<T>(a, b);`] [No `make_optional` with specified `T` in `boost`.] ]
|
||||
[ [`std::cout << optional<int>{};`] [] [No printing to IOStreams in `std`.]]
|
||||
]
|
||||
|
||||
|
||||
[endsect][/ std_comp]
|
159
doc/92_relnotes.qbk
Normal file
159
doc/92_relnotes.qbk
Normal file
@ -0,0 +1,159 @@
|
||||
[/
|
||||
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; at least some C++11 features.
|
||||
* Dropped dependency on Boost.Utility.
|
||||
* Dropped dependency on Boost.Predef.
|
||||
* Dropped dependency on Boost.StaticAssert.
|
||||
* Dropped dependency on Boost.Move.
|
||||
* A bit faster implementation of some relational operations.
|
||||
* *Warning.* In the future releases we intend to introduce the range interface
|
||||
into `optional`, so that `std::ranges::range<optional<T>>` will be `true`.
|
||||
This may affect the overload resolution in programs that make decisions based
|
||||
on predicates such as `std::ranges::range`.
|
||||
* Tags `in_place_init` and `in_place_init_if` become `inline constexpr` and therewith leave smaller footprint in the executable. This addresses [@https://github.com/boostorg/optional/issues/103 issue #103].
|
||||
|
||||
|
||||
[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/93_acknowledgments.qbk
Normal file
62
doc/93_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 |
1445
doc/optional.html
1445
doc/optional.html
File diff suppressed because it is too large
Load Diff
@ -1,56 +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_UTILITY_INPLACE_FACTORY_25AGO2003_HPP
|
||||
#define BOOST_UTILITY_INPLACE_FACTORY_25AGO2003_HPP
|
||||
|
||||
#include <boost/detail/in_place_factory_prefix.hpp>
|
||||
|
||||
#include <boost/type.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
class InPlaceFactoryBase {} ;
|
||||
|
||||
#define BOOST_DEFINE_INPLACE_FACTORY_CLASS(z,n,_) \
|
||||
template< BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(n),class A) > \
|
||||
class BOOST_PP_CAT(InPlaceFactory, BOOST_PP_INC(n) ) : public InPlaceFactoryBase \
|
||||
{ \
|
||||
public: \
|
||||
\
|
||||
BOOST_PP_CAT(InPlaceFactory, BOOST_PP_INC(n) ) ( BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_INC(n),A,const& a) ) \
|
||||
: \
|
||||
BOOST_PP_ENUM( BOOST_PP_INC(n), BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_INIT, _ ) \
|
||||
{} \
|
||||
\
|
||||
template<class T> \
|
||||
void apply ( void* address BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(T) ) const \
|
||||
{ \
|
||||
new ( address ) T ( BOOST_PP_ENUM_PARAMS( BOOST_PP_INC(n), m_a ) ) ; \
|
||||
} \
|
||||
\
|
||||
BOOST_PP_REPEAT( BOOST_PP_INC(n), BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_DECL, _) \
|
||||
} ; \
|
||||
\
|
||||
template< BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(n),class A) > \
|
||||
BOOST_PP_CAT(InPlaceFactory, BOOST_PP_INC(n) ) < BOOST_PP_ENUM_PARAMS( BOOST_PP_INC(n), A ) > \
|
||||
in_place ( BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_INC(n),A, const& a) ) \
|
||||
{ \
|
||||
return BOOST_PP_CAT(InPlaceFactory, BOOST_PP_INC(n) ) < BOOST_PP_ENUM_PARAMS( BOOST_PP_INC(n), A ) > \
|
||||
( BOOST_PP_ENUM_PARAMS( BOOST_PP_INC(n), a ) ) ; \
|
||||
} ; \
|
||||
|
||||
BOOST_PP_REPEAT( BOOST_MAX_INPLACE_FACTORY_ARITY, BOOST_DEFINE_INPLACE_FACTORY_CLASS, BOOST_PP_EMPTY() )
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
@ -1,33 +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_UTILITY_INPLACE_FACTORY_PREFIX_25AGO2003_HPP
|
||||
#define BOOST_UTILITY_INPLACE_FACTORY_PREFIX_25AGO2003_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/preprocessor/repetition/enum.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
#include <boost/preprocessor/arithmetic/inc.hpp>
|
||||
#include <boost/preprocessor/punctuation/paren.hpp>
|
||||
#include <boost/preprocessor/facilities/empty.hpp>
|
||||
|
||||
#define BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_INIT(z,n,_) BOOST_PP_CAT(m_a,n) BOOST_PP_LPAREN() BOOST_PP_CAT(a,n) BOOST_PP_RPAREN()
|
||||
#define BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_DECL(z,n,_) BOOST_PP_CAT(A,n) const& BOOST_PP_CAT(m_a,n);
|
||||
#define BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_ARG(z,n,_) BOOST_PP_CAT(m_a,n)
|
||||
|
||||
#define BOOST_MAX_INPLACE_FACTORY_ARITY 10
|
||||
|
||||
#undef BOOST_UTILITY_INPLACE_FACTORY_SUFFIX_25AGO2003_HPP
|
||||
|
||||
#endif
|
||||
|
@ -1,23 +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_UTILITY_INPLACE_FACTORY_SUFFIX_25AGO2003_HPP
|
||||
#define BOOST_UTILITY_INPLACE_FACTORY_SUFFIX_25AGO2003_HPP
|
||||
|
||||
#undef BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_INIT
|
||||
#undef BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_DECL
|
||||
#undef BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_ARG
|
||||
#undef BOOST_MAX_INPLACE_FACTORY_ARITY
|
||||
|
||||
#undef BOOST_UTILITY_INPLACE_FACTORY_PREFIX_25AGO2003_HPP
|
||||
|
||||
#endif
|
||||
|
@ -1,31 +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_UTILITY_NONE_17SEP2003_HPP
|
||||
#define BOOST_UTILITY_NONE_17SEP2003_HPP
|
||||
|
||||
#include "boost/detail/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)
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace {
|
||||
|
||||
detail::none_t const none = ((detail::none_t)0) ;
|
||||
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
@ -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,57 +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_UTILITY_TYPED_INPLACE_FACTORY_25AGO2003_HPP
|
||||
#define BOOST_UTILITY_TYPED_INPLACE_FACTORY_25AGO2003_HPP
|
||||
|
||||
#include <boost/detail/in_place_factory_prefix.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
class TypedInPlaceFactoryBase {} ;
|
||||
|
||||
#define BOOST_DEFINE_TYPED_INPLACE_FACTORY_CLASS(z,n,_) \
|
||||
template< class T, BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(n),class A) > \
|
||||
class BOOST_PP_CAT(TypedInPlaceFactory, BOOST_PP_INC(n) ) : public TypedInPlaceFactoryBase \
|
||||
{ \
|
||||
public: \
|
||||
\
|
||||
typedef T value_type ; \
|
||||
\
|
||||
BOOST_PP_CAT(TypedInPlaceFactory, BOOST_PP_INC(n) ) ( BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_INC(n),A,const& a) ) \
|
||||
: \
|
||||
BOOST_PP_ENUM( BOOST_PP_INC(n), BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_INIT, _ ) \
|
||||
{} \
|
||||
\
|
||||
void apply ( void* address ) const \
|
||||
{ \
|
||||
new ( address ) T ( BOOST_PP_ENUM_PARAMS( BOOST_PP_INC(n), m_a ) ) ; \
|
||||
} \
|
||||
\
|
||||
BOOST_PP_REPEAT( BOOST_PP_INC(n), BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_DECL, _) \
|
||||
} ; \
|
||||
\
|
||||
template< class T, BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(n),class A) > \
|
||||
BOOST_PP_CAT(TypedInPlaceFactory, BOOST_PP_INC(n) ) < T , BOOST_PP_ENUM_PARAMS( BOOST_PP_INC(n), A ) > \
|
||||
in_place ( BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_INC(n),A, const& a) ) \
|
||||
{ \
|
||||
return BOOST_PP_CAT(TypedInPlaceFactory, BOOST_PP_INC(n) ) < T, BOOST_PP_ENUM_PARAMS( BOOST_PP_INC(n), A ) > \
|
||||
( BOOST_PP_ENUM_PARAMS( BOOST_PP_INC(n), a ) ) ; \
|
||||
} ; \
|
||||
|
||||
BOOST_PP_REPEAT( BOOST_MAX_INPLACE_FACTORY_ARITY, BOOST_DEFINE_TYPED_INPLACE_FACTORY_CLASS, BOOST_PP_EMPTY() )
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/detail/in_place_factory_suffix.hpp>
|
||||
|
||||
#endif
|
||||
|
59
include/boost/none.hpp
Normal file
59
include/boost/none.hpp
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
// Copyright (C) 2014, 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)
|
||||
//
|
||||
// See http://www.boost.org/libs/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
#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 {
|
||||
// TU-local
|
||||
const none_t& none = detail::optional_detail::none_instance<none_t>::instance;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
BOOST_INLINE_CONSTEXPR none_t none ((none_t::init_tag()));
|
||||
|
||||
#endif // older definitions
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // header guard
|
55
include/boost/none_t.hpp
Normal file
55
include/boost/none_t.hpp
Normal file
@ -0,0 +1,55 @@
|
||||
// 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/libs/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
#ifndef BOOST_NONE_T_17SEP2003_HPP
|
||||
#define BOOST_NONE_T_17SEP2003_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
|
||||
#if defined (BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) \
|
||||
|| defined(BOOST_NO_CXX11_LAMBDAS) || defined(BOOST_NO_CXX11_DECLTYPE_N3276) \
|
||||
|| defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) \
|
||||
|| defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) || defined(BOOST_NO_CXX11_STATIC_ASSERT)
|
||||
|
||||
#error "Boost.Optional requires some C++11 features since version 1.87. If you have an older C++ version use Boost.Optional version 1.86 or earlier."
|
||||
|
||||
#elif defined(BOOST_NO_CXX11_REF_QUALIFIERS) || defined(BOOST_NO_CXX11_NOEXCEPT) || defined(BOOST_NO_CXX11_DEFAULTED_MOVES)
|
||||
|
||||
BOOST_PRAGMA_MESSAGE("C++03 support is deprecated in Boost.Optional 1.83 and will be removed in Boost.Optional 1.88.")
|
||||
|
||||
#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
|
||||
@ -12,700 +12,7 @@
|
||||
#ifndef BOOST_OPTIONAL_FLC_19NOV2002_HPP
|
||||
#define BOOST_OPTIONAL_FLC_19NOV2002_HPP
|
||||
|
||||
#include<new>
|
||||
#include<algorithm>
|
||||
|
||||
#include "boost/config.hpp"
|
||||
#include "boost/assert.hpp"
|
||||
#include "boost/type.hpp"
|
||||
#include "boost/type_traits/alignment_of.hpp"
|
||||
#include "boost/type_traits/type_with_alignment.hpp"
|
||||
#include "boost/type_traits/remove_reference.hpp"
|
||||
#include "boost/type_traits/is_reference.hpp"
|
||||
#include "boost/mpl/if.hpp"
|
||||
#include "boost/mpl/bool.hpp"
|
||||
#include "boost/mpl/not.hpp"
|
||||
#include "boost/detail/reference_content.hpp"
|
||||
#include "boost/detail/none_t.hpp"
|
||||
#include "boost/utility/compare_pointees.hpp"
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
|
||||
// VC6.0 has the following bug:
|
||||
// When a templated assignment operator exist, an implicit conversion
|
||||
// constructing an optional<T> is used when assigment of the form:
|
||||
// optional<T> opt ; opt = T(...);
|
||||
// is compiled.
|
||||
// However, optional's ctor is _explicit_ and the assignemt shouldn't compile.
|
||||
// Therefore, for VC6.0 templated assignment is disabled.
|
||||
//
|
||||
#define BOOST_OPTIONAL_NO_CONVERTING_ASSIGNMENT
|
||||
#endif
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
|
||||
// VC7.0 has the following bug:
|
||||
// When both a non-template and a template copy-ctor exist
|
||||
// and the templated version is made 'explicit', the explicit is also
|
||||
// given to the non-templated version, making the class non-implicitely-copyable.
|
||||
//
|
||||
#define BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR
|
||||
#endif
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION,<=700)
|
||||
// AFAICT only VC7.1 correctly resolves the overload set
|
||||
// that includes the in-place factory taking functions,
|
||||
// so for the other VC versions, in-place factory support
|
||||
// is disabled
|
||||
#define BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
#endif
|
||||
|
||||
#if BOOST_WORKAROUND(__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) \
|
||||
&& BOOST_WORKAROUND(__BORLANDC__, <= 0x564)
|
||||
// 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 incrorrectly sink to this general catch-all member function template as shown above.
|
||||
#define BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
|
||||
#endif
|
||||
|
||||
|
||||
namespace boost {
|
||||
|
||||
class InPlaceFactoryBase ;
|
||||
class TypedInPlaceFactoryBase ;
|
||||
|
||||
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!
|
||||
union dummy_u
|
||||
{
|
||||
char data[ sizeof(T) ];
|
||||
BOOST_DEDUCED_TYPENAME type_with_alignment<
|
||||
::boost::alignment_of<T>::value >::type aligner_;
|
||||
} dummy_ ;
|
||||
|
||||
public:
|
||||
|
||||
void const* address() const { return &dummy_.data[0]; }
|
||||
void * address() { return &dummy_.data[0]; }
|
||||
} ;
|
||||
|
||||
template<class T>
|
||||
struct types_when_isnt_ref
|
||||
{
|
||||
typedef T const& reference_const_type ;
|
||||
typedef T & reference_type ;
|
||||
typedef T const* pointer_const_type ;
|
||||
typedef T * pointer_type ;
|
||||
typedef T const& argument_type ;
|
||||
} ;
|
||||
template<class T>
|
||||
struct types_when_is_ref
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type raw_type ;
|
||||
|
||||
typedef raw_type& reference_const_type ;
|
||||
typedef raw_type& reference_type ;
|
||||
typedef raw_type* pointer_const_type ;
|
||||
typedef raw_type* pointer_type ;
|
||||
typedef raw_type& argument_type ;
|
||||
} ;
|
||||
|
||||
struct optional_tag {} ;
|
||||
|
||||
template<class T>
|
||||
class optional_base : public optional_tag
|
||||
{
|
||||
private :
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME detail::make_reference_content<T>::type internal_type ;
|
||||
|
||||
typedef aligned_storage<internal_type> storage_type ;
|
||||
|
||||
typedef types_when_isnt_ref<T> types_when_not_ref ;
|
||||
typedef types_when_is_ref<T> types_when_ref ;
|
||||
|
||||
typedef optional_base<T> this_type ;
|
||||
|
||||
protected :
|
||||
|
||||
typedef T value_type ;
|
||||
|
||||
typedef mpl::true_ is_reference_tag ;
|
||||
typedef mpl::false_ is_not_reference_tag ;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME is_reference<T>::type is_reference_predicate ;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME mpl::if_<is_reference_predicate,types_when_ref,types_when_not_ref>::type types ;
|
||||
|
||||
typedef bool (this_type::*unspecified_bool_type)() const;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME types::reference_type reference_type ;
|
||||
typedef BOOST_DEDUCED_TYPENAME types::reference_const_type reference_const_type ;
|
||||
typedef BOOST_DEDUCED_TYPENAME types::pointer_type pointer_type ;
|
||||
typedef BOOST_DEDUCED_TYPENAME types::pointer_const_type pointer_const_type ;
|
||||
typedef BOOST_DEDUCED_TYPENAME types::argument_type argument_type ;
|
||||
|
||||
// Creates an optional<T> uninitialized.
|
||||
// No-throw
|
||||
optional_base()
|
||||
:
|
||||
m_initialized(false) {}
|
||||
|
||||
// Creates an optional<T> uninitialized.
|
||||
// No-throw
|
||||
optional_base ( detail::none_t const& )
|
||||
:
|
||||
m_initialized(false) {}
|
||||
|
||||
// Creates an optional<T> initialized with 'val'.
|
||||
// Can throw if T::T(T const&) does
|
||||
optional_base ( argument_type val )
|
||||
:
|
||||
m_initialized(false)
|
||||
{
|
||||
construct(val);
|
||||
}
|
||||
|
||||
// Creates a deep copy of another optional<T>
|
||||
// Can throw if T::T(T const&) does
|
||||
optional_base ( optional_base const& rhs )
|
||||
:
|
||||
m_initialized(false)
|
||||
{
|
||||
if ( rhs.is_initialized() )
|
||||
construct(rhs.get_impl());
|
||||
}
|
||||
|
||||
// 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 optional_base ( Expr const& expr, Expr const* tag )
|
||||
:
|
||||
m_initialized(false)
|
||||
{
|
||||
construct(expr,tag);
|
||||
}
|
||||
|
||||
// No-throw (assuming T::~T() doesn't)
|
||||
~optional_base() { destroy() ; }
|
||||
|
||||
// Assigns from another optional<T> (deep-copies the rhs value)
|
||||
// Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED
|
||||
void assign ( optional_base const& rhs )
|
||||
{
|
||||
destroy();
|
||||
if ( rhs.is_initialized() )
|
||||
construct(rhs.get_impl());
|
||||
}
|
||||
|
||||
// Assigns from a T (deep-copies the rhs value)
|
||||
// Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED
|
||||
void assign ( argument_type val )
|
||||
{
|
||||
destroy();
|
||||
construct(val);
|
||||
}
|
||||
|
||||
// Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED
|
||||
// No-throw (assuming T::~T() doesn't)
|
||||
void assign ( detail::none_t const& ) { destroy(); }
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
template<class Expr>
|
||||
void assign_expr ( Expr const& expr, Expr const* tag )
|
||||
{
|
||||
destroy();
|
||||
construct(expr,tag);
|
||||
}
|
||||
#endif
|
||||
|
||||
public :
|
||||
|
||||
// Destroys the current value, if any, leaving this UNINITIALIZED
|
||||
// No-throw (assuming T::~T() doesn't)
|
||||
void reset() { destroy(); }
|
||||
|
||||
// Replaces the current value -if any- with 'val'
|
||||
// Basic Guarantee: If T::T( T const& ) throws this is left UNINITIALIZED.
|
||||
void reset ( argument_type val ) { 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 )
|
||||
{
|
||||
new (m_storage.address()) internal_type(val) ;
|
||||
m_initialized = true ;
|
||||
}
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
// Constructs in-place using the given factory
|
||||
template<class Expr>
|
||||
void construct ( Expr const& factory, InPlaceFactoryBase const* )
|
||||
{
|
||||
BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ;
|
||||
factory.BOOST_NESTED_TEMPLATE apply<value_type>(m_storage.address()) ;
|
||||
m_initialized = true ;
|
||||
}
|
||||
|
||||
// Constructs in-place using the given typed factory
|
||||
template<class Expr>
|
||||
void construct ( Expr const& factory, TypedInPlaceFactoryBase const* )
|
||||
{
|
||||
BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ;
|
||||
factory.apply(m_storage.address()) ;
|
||||
m_initialized = true ;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Constructs using any expression implicitely 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* )
|
||||
{
|
||||
new (m_storage.address()) internal_type(expr) ;
|
||||
m_initialized = true ;
|
||||
}
|
||||
|
||||
#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 dosen't work becasue the comnpiler issues and error
|
||||
// instead of choosing the wrong overload
|
||||
//
|
||||
// Notice that 'Expr' will be optional<T> or optional<U> (but not 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.
|
||||
new (m_storage.address()) internal_type(expr.get()) ;
|
||||
m_initialized = true ;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void destroy()
|
||||
{
|
||||
if ( m_initialized )
|
||||
destroy_impl(is_reference_predicate()) ;
|
||||
}
|
||||
|
||||
unspecified_bool_type safe_bool() const { return m_initialized ? &this_type::is_initialized : 0 ; }
|
||||
|
||||
reference_const_type get_impl() const { return dereference(get_object(), is_reference_predicate() ) ; }
|
||||
reference_type get_impl() { return dereference(get_object(), is_reference_predicate() ) ; }
|
||||
|
||||
pointer_const_type get_ptr_impl() const { return cast_ptr(get_object(), is_reference_predicate() ) ; }
|
||||
pointer_type get_ptr_impl() { return cast_ptr(get_object(), is_reference_predicate() ) ; }
|
||||
|
||||
private :
|
||||
|
||||
// internal_type can be either T or reference_content<T>
|
||||
internal_type const* get_object() const { return static_cast<internal_type const*>(m_storage.address()); }
|
||||
internal_type * get_object() { return static_cast<internal_type *> (m_storage.address()); }
|
||||
|
||||
// reference_content<T> lacks an implicit conversion to T&, so the following is needed to obtain a proper reference.
|
||||
reference_const_type dereference( internal_type const* p, is_not_reference_tag ) const { return *p ; }
|
||||
reference_type dereference( internal_type* p, is_not_reference_tag ) { return *p ; }
|
||||
reference_const_type dereference( internal_type const* p, is_reference_tag ) const { return p->get() ; }
|
||||
reference_type dereference( internal_type* p, is_reference_tag ) { return p->get() ; }
|
||||
|
||||
void destroy_impl ( is_not_reference_tag ) { get_impl().~T() ; m_initialized = false ; }
|
||||
void destroy_impl ( is_reference_tag ) { m_initialized = false ; }
|
||||
|
||||
// If T is of reference type, trying to get a pointer to the held value must result in a compile-time error.
|
||||
// Decent compilers should disallow conversions from reference_content<T>* to T*, but just in case,
|
||||
// the following olverloads are used to filter out the case and guarantee an error in case of T being a reference.
|
||||
pointer_const_type cast_ptr( internal_type const* p, is_not_reference_tag ) const { return p ; }
|
||||
pointer_type cast_ptr( internal_type * p, is_not_reference_tag ) { return p ; }
|
||||
|
||||
bool m_initialized ;
|
||||
storage_type m_storage ;
|
||||
} ;
|
||||
|
||||
} // namespace optional_detail
|
||||
|
||||
template<class T>
|
||||
class optional : public optional_detail::optional_base<T>
|
||||
{
|
||||
typedef optional_detail::optional_base<T> base ;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME base::unspecified_bool_type unspecified_bool_type ;
|
||||
|
||||
public :
|
||||
|
||||
typedef optional<T> this_type ;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME base::value_type value_type ;
|
||||
typedef BOOST_DEDUCED_TYPENAME base::reference_type reference_type ;
|
||||
typedef BOOST_DEDUCED_TYPENAME base::reference_const_type reference_const_type ;
|
||||
typedef BOOST_DEDUCED_TYPENAME base::pointer_type pointer_type ;
|
||||
typedef BOOST_DEDUCED_TYPENAME base::pointer_const_type pointer_const_type ;
|
||||
typedef BOOST_DEDUCED_TYPENAME base::argument_type argument_type ;
|
||||
|
||||
// Creates an optional<T> uninitialized.
|
||||
// No-throw
|
||||
optional() : base() {}
|
||||
|
||||
// Creates an optional<T> uninitialized.
|
||||
// No-throw
|
||||
optional( detail::none_t const& none_ ) : base(none_) {}
|
||||
|
||||
// Creates an optional<T> initialized with 'val'.
|
||||
// Can throw if T::T(T const&) does
|
||||
optional ( argument_type val ) : base(val) {}
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR
|
||||
// NOTE: MSVC needs templated versions first
|
||||
|
||||
// Creates a deep copy of another convertible optional<U>
|
||||
// Requires a valid conversion from U to T.
|
||||
// Can throw if T::T(U const&) does
|
||||
template<class U>
|
||||
explicit optional ( optional<U> const& rhs )
|
||||
:
|
||||
base()
|
||||
{
|
||||
if ( rhs.is_initialized() )
|
||||
this->construct(rhs.get());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
// Creates an optional<T> with an expression which can be either
|
||||
// (a) An instance of InPlaceFactory (i.e. in_place(a,b,...,n);
|
||||
// (b) An instance of TypedInPlaceFactory ( i.e. in_place<T>(a,b,...,n);
|
||||
// (c) Any expression implicitely convertible to the single type
|
||||
// of a one-argument T's constructor.
|
||||
// (d*) Weak compilers (BCB) might also resolved Expr as optional<T> and optional<U>
|
||||
// even though explicit overloads are present for these.
|
||||
// Depending on the above some T ctor is called.
|
||||
// Can throw is the resolved T ctor throws.
|
||||
template<class Expr>
|
||||
explicit optional ( Expr const& expr ) : base(expr,&expr) {}
|
||||
#endif
|
||||
|
||||
// Creates a deep copy of another optional<T>
|
||||
// Can throw if T::T(T const&) does
|
||||
optional ( optional const& rhs ) : base(rhs) {}
|
||||
|
||||
// No-throw (assuming T::~T() doesn't)
|
||||
~optional() {}
|
||||
|
||||
#if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
|
||||
// Assigns from an expression. See corresponding constructor.
|
||||
// Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED
|
||||
template<class Expr>
|
||||
optional& operator= ( Expr expr )
|
||||
{
|
||||
this->assign_expr(expr,&expr);
|
||||
return *this ;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_CONVERTING_ASSIGNMENT
|
||||
// Assigns from another convertible optional<U> (converts && deep-copies the rhs value)
|
||||
// Requires a valid conversion from U to T.
|
||||
// Basic Guarantee: If T::T( U const& ) throws, this is left UNINITIALIZED
|
||||
template<class U>
|
||||
optional& operator= ( optional<U> const& rhs )
|
||||
{
|
||||
this->destroy(); // no-throw
|
||||
|
||||
if ( rhs.is_initialized() )
|
||||
{
|
||||
// An exception can be thrown here.
|
||||
// It it happens, THIS will be left uninitialized.
|
||||
this->assign(rhs.get());
|
||||
}
|
||||
return *this ;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Assigns from another optional<T> (deep-copies the rhs value)
|
||||
// Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED
|
||||
// (NOTE: On BCB, this operator is not actually called and left is left UNMODIFIED in case of a throw)
|
||||
optional& operator= ( optional const& rhs )
|
||||
{
|
||||
this->assign( rhs ) ;
|
||||
return *this ;
|
||||
}
|
||||
|
||||
// Assigns from a T (deep-copies the rhs value)
|
||||
// Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED
|
||||
optional& operator= ( argument_type val )
|
||||
{
|
||||
this->assign( val ) ;
|
||||
return *this ;
|
||||
}
|
||||
|
||||
// Assigns from a "none"
|
||||
// Which destroys the current value, if any, leaving this UNINITIALIZED
|
||||
// No-throw (assuming T::~T() doesn't)
|
||||
optional& operator= ( detail::none_t const& none_ )
|
||||
{
|
||||
this->assign( none_ ) ;
|
||||
return *this ;
|
||||
}
|
||||
|
||||
// Returns a reference to the value if this is initialized, otherwise,
|
||||
// the behaviour is UNDEFINED
|
||||
// No-throw
|
||||
reference_const_type get() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
|
||||
reference_type get() { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
|
||||
|
||||
// Returns a pointer to the value if this is initialized, otherwise,
|
||||
// the behaviour is UNDEFINED
|
||||
// No-throw
|
||||
pointer_const_type operator->() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
|
||||
pointer_type operator->() { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
|
||||
|
||||
// Returns a reference to the value if this is initialized, otherwise,
|
||||
// the behaviour is UNDEFINED
|
||||
// No-throw
|
||||
reference_const_type operator *() const { return this->get() ; }
|
||||
reference_type operator *() { return this->get() ; }
|
||||
|
||||
// implicit conversion to "bool"
|
||||
// No-throw
|
||||
operator unspecified_bool_type() const { return this->safe_bool() ; }
|
||||
|
||||
// This is provided for those compilers which don't like the conversion to bool
|
||||
// on some contexts.
|
||||
bool operator!() const { return !this->is_initialized() ; }
|
||||
} ;
|
||||
|
||||
// Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
|
||||
// No-throw
|
||||
template<class T>
|
||||
inline
|
||||
BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
|
||||
get ( optional<T> const& opt )
|
||||
{
|
||||
return opt.get() ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
BOOST_DEDUCED_TYPENAME optional<T>::reference_type
|
||||
get ( optional<T>& opt )
|
||||
{
|
||||
return opt.get() ;
|
||||
}
|
||||
|
||||
// Returns a pointer to the value if this is initialized, otherwise, returns NULL.
|
||||
// No-throw
|
||||
template<class T>
|
||||
inline
|
||||
BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
|
||||
get ( optional<T> const* opt )
|
||||
{
|
||||
return opt->get_ptr() ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
|
||||
get ( optional<T>* opt )
|
||||
{
|
||||
return opt->get_ptr() ;
|
||||
}
|
||||
|
||||
// Returns a pointer to the value if this is initialized, otherwise, returns NULL.
|
||||
// No-throw
|
||||
template<class T>
|
||||
inline
|
||||
BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
|
||||
get_pointer ( optional<T> const& opt )
|
||||
{
|
||||
return opt.get_ptr() ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
|
||||
get_pointer ( optional<T>& opt )
|
||||
{
|
||||
return opt.get_ptr() ;
|
||||
}
|
||||
|
||||
// optional's relational operators ( ==, !=, <, >, <=, >= ) have deep-semantics (compare values).
|
||||
// WARNING: This is UNLIKE pointers. Use equal_pointees()/less_pointess() in generic code instead.
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator == ( optional<T> const& x, optional<T> const& y )
|
||||
{ return equal_pointees(x,y); }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator < ( optional<T> const& x, optional<T> const& y )
|
||||
{ return less_pointees(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 ) ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator == ( optional<T> const& x, detail::none_t const& )
|
||||
{ return equal_pointees(x, optional<T>() ); }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator < ( optional<T> const& x, detail::none_t const& )
|
||||
{ return less_pointees(x,optional<T>() ); }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator != ( optional<T> const& x, detail::none_t const& y )
|
||||
{ return !( x == y ) ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator > ( optional<T> const& x, detail::none_t const& y )
|
||||
{ return y < x ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator <= ( optional<T> const& x, detail::none_t const& y )
|
||||
{ return !( y < x ) ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator >= ( optional<T> const& x, detail::none_t const& y )
|
||||
{ return !( x < y ) ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator == ( detail::none_t const& x, optional<T> const& y )
|
||||
{ return equal_pointees(optional<T>() ,y); }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator < ( detail::none_t const& x, optional<T> const& y )
|
||||
{ return less_pointees(optional<T>() ,y); }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator != ( detail::none_t const& x, optional<T> const& y )
|
||||
{ return !( x == y ) ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator > ( detail::none_t const& x, optional<T> const& y )
|
||||
{ return y < x ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator <= ( detail::none_t const& x, optional<T> const& y )
|
||||
{ return !( y < x ) ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator >= ( detail::none_t const& x, optional<T> const& y )
|
||||
{ return !( x < y ) ; }
|
||||
|
||||
//
|
||||
// The following swap implementation follows the GCC workaround as found in
|
||||
// "boost/detail/compressed_pair.hpp"
|
||||
//
|
||||
namespace optional_detail {
|
||||
|
||||
// GCC < 3.2 gets the using declaration at namespace scope (FLC, DWA)
|
||||
#if BOOST_WORKAROUND(__GNUC__, < 3) \
|
||||
|| BOOST_WORKAROUND(__GNUC__, == 3) && __GNUC_MINOR__ <= 2
|
||||
using std::swap;
|
||||
#define BOOST_OPTIONAL_STD_SWAP_INTRODUCED_AT_NS_SCOPE
|
||||
#endif
|
||||
|
||||
// optional's swap:
|
||||
// If both are initialized, calls swap(T&, T&), with whatever exception guarantess are given there.
|
||||
// If only one is initialized, calls I.reset() and U.reset(*I), with the Basic Guarantee
|
||||
// If both are uninitialized, do nothing (no-throw)
|
||||
template<class T>
|
||||
inline
|
||||
void optional_swap ( optional<T>& x, optional<T>& y )
|
||||
{
|
||||
if ( !x && !!y )
|
||||
{
|
||||
x.reset(*y); // Basic guarantee.
|
||||
y.reset();
|
||||
}
|
||||
else if ( !!x && !y )
|
||||
{
|
||||
y.reset(*x); // Basic guarantee.
|
||||
x.reset();
|
||||
}
|
||||
else if ( !!x && !!y )
|
||||
{
|
||||
// GCC > 3.2 and all other compilers have the using declaration at function scope (FLC)
|
||||
#ifndef BOOST_OPTIONAL_STD_SWAP_INTRODUCED_AT_NS_SCOPE
|
||||
// allow for Koenig lookup
|
||||
using std::swap ;
|
||||
#endif
|
||||
swap(*x,*y);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace optional_detail
|
||||
|
||||
template<class T> inline void swap ( optional<T>& x, optional<T>& y )
|
||||
{
|
||||
optional_detail::optional_swap(x,y);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
#include "boost/optional/optional.hpp"
|
||||
|
||||
#endif
|
||||
|
||||
|
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
|
144
include/boost/optional/detail/optional_config.hpp
Normal file
144
include/boost/optional/detail/optional_config.hpp
Normal file
@ -0,0 +1,144 @@
|
||||
// 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_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__)
|
||||
// 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
|
||||
|
||||
|
||||
#ifdef BOOST_NO_CXX11_REF_QUALIFIERS
|
||||
# define BOOST_OPTIONAL_CONST_REF_QUAL const
|
||||
# define BOOST_OPTIONAL_REF_QUAL
|
||||
#else
|
||||
# define BOOST_OPTIONAL_CONST_REF_QUAL const&
|
||||
# define BOOST_OPTIONAL_REF_QUAL &
|
||||
#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
|
||||
static_assert(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)
|
||||
{
|
||||
static_assert(boost::is_lvalue_reference<T>::value,
|
||||
"binding rvalue references to optional lvalue references is disallowed");
|
||||
return optional_detail::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
|
||||
static_assert(!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_) optional_detail::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_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,270 @@
|
||||
// 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 ;
|
||||
typedef T && rval_reference_type ;
|
||||
typedef T && reference_type_of_temporary_wrapper ;
|
||||
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;
|
||||
|
||||
template<class Expr, class PtrExpr>
|
||||
explicit tc_optional_base ( Expr&& expr, PtrExpr const* tag )
|
||||
:
|
||||
m_initialized(false)
|
||||
{
|
||||
construct(optional_detail::forward<Expr>(expr),tag);
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
void assign ( argument_type val )
|
||||
{
|
||||
construct(val);
|
||||
}
|
||||
|
||||
void assign ( none_t ) { destroy(); }
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
|
||||
template<class Expr, class ExprPtr>
|
||||
void assign_expr ( Expr&& expr, ExprPtr const* tag )
|
||||
{
|
||||
construct(optional_detail::forward<Expr>(expr),tag);
|
||||
}
|
||||
|
||||
#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 ;
|
||||
}
|
||||
|
||||
|
||||
// Constructs in-place
|
||||
// upon exception *this is always uninitialized
|
||||
template<class... Args>
|
||||
void construct ( in_place_init_t, Args&&... args )
|
||||
{
|
||||
m_storage = value_type( optional_detail::forward<Args>(args)... ) ;
|
||||
m_initialized = true ;
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
void emplace_assign ( Args&&... args )
|
||||
{
|
||||
construct(in_place_init, optional_detail::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
explicit tc_optional_base ( in_place_init_t, Args&&... args )
|
||||
:
|
||||
m_initialized(false)
|
||||
{
|
||||
construct(in_place_init, optional_detail::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, optional_detail::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// 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(optional_detail::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( optional_detail::forward<Expr>(expr) );
|
||||
}
|
||||
|
||||
#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
|
||||
//
|
||||
|
||||
// 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(optional_detail::move(expr.get())) ;
|
||||
m_initialized = true ;
|
||||
}
|
||||
}
|
||||
#endif // defined BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
|
||||
|
||||
void assign_value ( argument_type val ) { m_storage = val; }
|
||||
void assign_value ( rval_reference_type val ) { m_storage = static_cast<rval_reference_type>(val); }
|
||||
|
||||
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 ;
|
||||
} ;
|
41
include/boost/optional/detail/optional_utility.hpp
Normal file
41
include/boost/optional/detail/optional_utility.hpp
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright (C) 2024 Ryan Malcolm Underwood.
|
||||
//
|
||||
// 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:
|
||||
// typenametea@gmail.com
|
||||
|
||||
#ifndef BOOST_OPTIONAL_OPTIONAL_DETAIL_OPTIONAL_UTILITY_RMU_06OCT2024_HPP
|
||||
#define BOOST_OPTIONAL_OPTIONAL_DETAIL_OPTIONAL_UTILITY_RMU_06OCT2024_HPP
|
||||
|
||||
namespace boost {
|
||||
namespace optional_detail {
|
||||
|
||||
// Workaround: forward and move aren't constexpr in C++11
|
||||
template <class T>
|
||||
inline constexpr T&& forward(typename boost::remove_reference<T>::type& t) noexcept
|
||||
{
|
||||
return static_cast<T&&>(t);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline constexpr T&& forward(typename boost::remove_reference<T>::type&& t) noexcept
|
||||
{
|
||||
static_assert(!boost::is_lvalue_reference<T>::value, "Can not forward an rvalue as an lvalue.");
|
||||
return static_cast<T&&>(t);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline constexpr typename boost::remove_reference<T>::type&& move(T&& t) noexcept
|
||||
{
|
||||
return static_cast<typename boost::remove_reference<T>::type&&>(t);
|
||||
}
|
||||
|
||||
} // namespace optional_detail
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
1175
include/boost/optional/optional.hpp
Normal file
1175
include/boost/optional/optional.hpp
Normal file
File diff suppressed because it is too large
Load Diff
41
include/boost/optional/optional_fwd.hpp
Normal file
41
include/boost/optional/optional_fwd.hpp
Normal file
@ -0,0 +1,41 @@
|
||||
// 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
|
||||
//
|
||||
// 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
|
||||
|
91
include/boost/optional/optional_io.hpp
Normal file
91
include/boost/optional/optional_io.hpp
Normal file
@ -0,0 +1,91 @@
|
||||
// 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;
|
||||
v = optional_detail::move(x);
|
||||
}
|
||||
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::tuple Boost::utility)
|
||||
|
||||
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 ]
|
||||
;
|
||||
}
|
126
test/Jamfile.v2
126
test/Jamfile.v2
@ -1,34 +1,106 @@
|
||||
# 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_static_assert
|
||||
cxx11_variadic_templates
|
||||
]
|
||||
;
|
||||
|
||||
|
||||
run optional_test.cpp : : : <library>/boost/bind//boost_bind ;
|
||||
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,33 @@
|
||||
// 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
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#include "boost/optional/optional.hpp"
|
||||
|
||||
#ifdef BOOST_BORLANDC
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#include "boost/detail/none.hpp"
|
||||
#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 +49,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,9 +78,9 @@ 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.
|
||||
// 'oa' state is Initialized with 'a'
|
||||
// T::T( T const& x ) is used.
|
||||
@ -85,7 +95,7 @@ void test_basics( T const* )
|
||||
optional<T> ob ;
|
||||
|
||||
// Value-Assignment upon Uninitialized optional.
|
||||
// T::T ( T const& x ) is used.
|
||||
// T::T( T const& x ) is used.
|
||||
set_pending_copy( ARG(T) ) ;
|
||||
ob = a ;
|
||||
check_is_not_pending_copy( ARG(T) ) ;
|
||||
@ -93,12 +103,14 @@ void test_basics( T const* )
|
||||
check_value(ob,a,z);
|
||||
|
||||
// Value-Assignment upon Initialized optional.
|
||||
// T::T ( T const& x ) is used
|
||||
set_pending_dtor( ARG(T) ) ;
|
||||
set_pending_copy( ARG(T) ) ;
|
||||
// T::operator=( T const& x ) is used
|
||||
set_pending_assign( ARG(T) ) ;
|
||||
set_pending_copy ( ARG(T) ) ;
|
||||
set_pending_dtor ( ARG(T) ) ;
|
||||
ob = b ;
|
||||
check_is_not_pending_dtor( ARG(T) ) ;
|
||||
check_is_not_pending_copy( ARG(T) ) ;
|
||||
check_is_not_pending_assign( ARG(T) ) ;
|
||||
check_is_pending_copy ( ARG(T) ) ;
|
||||
check_is_pending_dtor ( ARG(T) ) ;
|
||||
check_initialized(ob);
|
||||
check_value(ob,b,z);
|
||||
|
||||
@ -111,13 +123,10 @@ void test_basics( T const* )
|
||||
check_value_const(oa2,a,z);
|
||||
|
||||
// Assignment
|
||||
// T::~T() is used to destroy previous value in ob.
|
||||
// T::T ( T const& x ) is used to copy new value.
|
||||
set_pending_dtor( ARG(T) ) ;
|
||||
set_pending_copy( ARG(T) ) ;
|
||||
// T::operator= ( T const& x ) is used to copy new value.
|
||||
set_pending_assign( ARG(T) ) ;
|
||||
oa = ob ;
|
||||
check_is_not_pending_dtor( ARG(T) ) ;
|
||||
check_is_not_pending_copy( ARG(T) ) ;
|
||||
check_is_not_pending_assign( ARG(T) ) ;
|
||||
check_initialized(oa);
|
||||
check_value(oa,b,z);
|
||||
|
||||
@ -152,6 +161,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 ) ;
|
||||
}
|
||||
|
||||
//
|
||||
@ -161,24 +259,24 @@ template<class T>
|
||||
void test_direct_value_manip( T const* )
|
||||
{
|
||||
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
||||
|
||||
|
||||
T x(3);
|
||||
|
||||
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_CHECK( c_opt0->V() == x.V() ) ;
|
||||
BOOST_CHECK( opt0->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_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() ) ;
|
||||
}
|
||||
|
||||
//
|
||||
@ -196,45 +294,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
|
||||
@ -279,9 +377,12 @@ 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) );
|
||||
|
||||
reset_throw_on_copy( ARG(T) ) ;
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
@ -312,11 +413,13 @@ 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) );
|
||||
check_uninitialized(opt);
|
||||
|
||||
reset_throw_on_copy( ARG(T) ) ;
|
||||
}
|
||||
|
||||
//
|
||||
@ -330,11 +433,10 @@ void test_throwing_val_assign_on_initialized( T const* )
|
||||
T z(0);
|
||||
T a(8);
|
||||
T b(9);
|
||||
T x(-1);
|
||||
|
||||
int count = get_instance_count( ARG(T) ) ;
|
||||
|
||||
reset_throw_on_copy( ARG(T) ) ;
|
||||
|
||||
optional<T> opt ( b ) ;
|
||||
++ count ;
|
||||
|
||||
@ -342,29 +444,29 @@ void test_throwing_val_assign_on_initialized( T const* )
|
||||
|
||||
check_value(opt,b,z);
|
||||
|
||||
set_throw_on_copy( ARG(T) ) ;
|
||||
set_throw_on_assign( ARG(T) ) ;
|
||||
|
||||
bool passed = false ;
|
||||
try
|
||||
{
|
||||
// This should:
|
||||
// Attempt to copy construct 'a' and throw.
|
||||
// opt should be left uninitialized (even though it was initialized)
|
||||
set_pending_dtor( ARG(T) ) ;
|
||||
set_pending_copy( ARG(T) ) ;
|
||||
// Attempt to assign 'a' and throw.
|
||||
// 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);
|
||||
|
||||
-- count ;
|
||||
|
||||
check_is_not_pending_dtor( ARG(T) );
|
||||
check_is_not_pending_copy( ARG(T) );
|
||||
check_is_not_pending_assign( ARG(T) );
|
||||
check_instance_count(count, ARG(T) );
|
||||
check_uninitialized(opt);
|
||||
check_initialized(opt);
|
||||
check_value(opt,x,z);
|
||||
|
||||
reset_throw_on_assign ( ARG(T) ) ;
|
||||
}
|
||||
|
||||
//
|
||||
@ -378,8 +480,6 @@ void test_throwing_copy_initialization( T const* )
|
||||
T z(0);
|
||||
T a(10);
|
||||
|
||||
reset_throw_on_copy( ARG(T) ) ;
|
||||
|
||||
optional<T> opt (a);
|
||||
|
||||
int count = get_instance_count( ARG(T) ) ;
|
||||
@ -398,7 +498,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) );
|
||||
@ -406,6 +506,8 @@ void test_throwing_copy_initialization( T const* )
|
||||
// Nothing should have happened to the source optional.
|
||||
check_initialized(opt);
|
||||
check_value(opt,a,z);
|
||||
|
||||
reset_throw_on_copy( ARG(T) ) ;
|
||||
}
|
||||
|
||||
//
|
||||
@ -420,8 +522,6 @@ void test_throwing_assign_to_uninitialized( T const* )
|
||||
T z(0);
|
||||
T a(11);
|
||||
|
||||
reset_throw_on_copy( ARG(T) ) ;
|
||||
|
||||
optional<T> opt0 ;
|
||||
optional<T> opt1(a) ;
|
||||
|
||||
@ -441,11 +541,13 @@ 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) );
|
||||
check_uninitialized(opt0);
|
||||
|
||||
reset_throw_on_copy( ARG(T) ) ;
|
||||
}
|
||||
|
||||
//
|
||||
@ -460,37 +562,37 @@ void test_throwing_assign_to_initialized( T const* )
|
||||
T z(0);
|
||||
T a(12);
|
||||
T b(13);
|
||||
|
||||
reset_throw_on_copy( ARG(T) ) ;
|
||||
T x(-1);
|
||||
|
||||
optional<T> opt0(a) ;
|
||||
optional<T> opt1(b) ;
|
||||
|
||||
int count = get_instance_count( ARG(T) ) ;
|
||||
|
||||
set_throw_on_copy( ARG(T) ) ;
|
||||
set_throw_on_assign( ARG(T) ) ;
|
||||
|
||||
bool passed = false ;
|
||||
try
|
||||
{
|
||||
// This should:
|
||||
// Attempt to copy construct 'opt1.value()' into opt0 and throw.
|
||||
// opt0 should be left unmodified or uninitialized
|
||||
set_pending_dtor( ARG(T) ) ;
|
||||
set_pending_copy( ARG(T) ) ;
|
||||
// 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
|
||||
-- count ;
|
||||
check_is_not_pending_dtor( ARG(T) );
|
||||
check_is_not_pending_copy( ARG(T) );
|
||||
check_is_not_pending_assign( ARG(T) );
|
||||
check_instance_count(count, ARG(T) );
|
||||
check_uninitialized(opt0);
|
||||
check_initialized(opt0);
|
||||
check_value(opt0,x,z);
|
||||
|
||||
reset_throw_on_assign( ARG(T) ) ;
|
||||
}
|
||||
|
||||
//
|
||||
@ -500,13 +602,11 @@ template<class T>
|
||||
void test_no_throwing_swap( T const* )
|
||||
{
|
||||
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
||||
|
||||
|
||||
T z(0);
|
||||
T a(14);
|
||||
T b(15);
|
||||
|
||||
reset_throw_on_copy( ARG(T) ) ;
|
||||
|
||||
optional<T> def0 ;
|
||||
optional<T> def1 ;
|
||||
optional<T> opt0(a) ;
|
||||
@ -541,16 +641,15 @@ template<class T>
|
||||
void test_throwing_swap( T const* )
|
||||
{
|
||||
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
||||
|
||||
|
||||
T a(16);
|
||||
T b(17);
|
||||
|
||||
reset_throw_on_copy( ARG(T) ) ;
|
||||
T x(-1);
|
||||
|
||||
optional<T> opt0(a) ;
|
||||
optional<T> opt1(b) ;
|
||||
|
||||
set_throw_on_copy( ARG(T) ) ;
|
||||
set_throw_on_assign( ARG(T) ) ;
|
||||
|
||||
//
|
||||
// Case 1: Both Initialized.
|
||||
@ -565,16 +664,20 @@ 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:
|
||||
check_initialized(opt0);
|
||||
check_initialized(opt1);
|
||||
check_value(opt0,x,a);
|
||||
check_value(opt1,b,x);
|
||||
|
||||
// Assuming swap(T&,T&) has at least the basic guarantee, these should hold.
|
||||
BOOST_CHECK( ( !opt0 || ( !!opt0 && ( ( *opt0 == a ) || ( *opt0 == b ) ) ) ) ) ;
|
||||
BOOST_CHECK( ( !opt1 || ( !!opt1 && ( ( *opt1 == a ) || ( *opt1 == b ) ) ) ) ) ;
|
||||
|
||||
//
|
||||
// Case 2: Only one Initialized.
|
||||
//
|
||||
reset_throw_on_copy( ARG(T) ) ;
|
||||
reset_throw_on_assign( ARG(T) ) ;
|
||||
|
||||
opt0.reset();
|
||||
opt1.reset(a);
|
||||
@ -585,18 +688,20 @@ void test_throwing_swap( T const* )
|
||||
try
|
||||
{
|
||||
// This should attempt to swap optionals and fail at opt0.reset(*opt1)
|
||||
// opt0 should be left uninitialized and opt1 unchanged.
|
||||
// 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);
|
||||
check_value(opt1,a,b);
|
||||
check_value(opt1,a,x);
|
||||
|
||||
reset_throw_on_copy( ARG(T) ) ;
|
||||
}
|
||||
|
||||
//
|
||||
@ -606,12 +711,10 @@ template<class T>
|
||||
void test_relops( T const* )
|
||||
{
|
||||
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
||||
|
||||
reset_throw_on_copy( ARG(T) ) ;
|
||||
|
||||
T v0(18);
|
||||
T v1(19);
|
||||
T v2(19);
|
||||
|
||||
T v0(0);
|
||||
T v1(1);
|
||||
T v2(1);
|
||||
|
||||
optional<T> def0 ;
|
||||
optional<T> def1 ;
|
||||
@ -620,42 +723,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>
|
||||
@ -664,37 +794,73 @@ void test_none( T const* )
|
||||
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
||||
|
||||
using boost::none ;
|
||||
|
||||
|
||||
optional<T> def0 ;
|
||||
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) );
|
||||
@ -707,7 +873,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 ; }
|
||||
@ -726,7 +893,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()
|
||||
@ -744,58 +911,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,241 +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
|
||||
//
|
||||
#ifdef ENABLE_TRACE
|
||||
#define TRACE(msg) std::cout << msg << std::endl ;
|
||||
#else
|
||||
#define TRACE(msg)
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
void assertion_failed (char const * expr, char const * func, char const * file, long )
|
||||
{
|
||||
using std::string ;
|
||||
string msg = string("Boost assertion failure for \"")
|
||||
+ string(expr)
|
||||
+ string("\" at file \"")
|
||||
+ string(file)
|
||||
+ string("\" function \"")
|
||||
+ string(func)
|
||||
+ string("\"") ;
|
||||
|
||||
TRACE(msg);
|
||||
|
||||
throw std::logic_error(msg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
using boost::optional ;
|
||||
|
||||
template<class T> inline void unused_variable ( T ) {}
|
||||
|
||||
#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
|
||||
using boost::swap ;
|
||||
using boost::get ;
|
||||
using boost::get_pointer ;
|
||||
#endif
|
||||
|
||||
// MSVC6.0 does not support comparisons of optional against a literal null pointer value (0)
|
||||
// via the safe_bool operator.
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1300) ) // 1300 == VC++ 7.1
|
||||
#define BOOST_OPTIONAL_NO_NULL_COMPARE
|
||||
#endif
|
||||
|
||||
#define ARG(T) (static_cast< T const* >(0))
|
||||
|
||||
//
|
||||
// Helper class used to verify the lifetime managment of the values held by optional
|
||||
//
|
||||
class X
|
||||
{
|
||||
public :
|
||||
|
||||
X ( int av ) : v(av)
|
||||
{
|
||||
++ count ;
|
||||
|
||||
TRACE ( "X::X(" << av << "). this=" << this ) ;
|
||||
}
|
||||
|
||||
X ( X const& rhs ) : v(rhs.v)
|
||||
{
|
||||
pending_copy = false ;
|
||||
|
||||
TRACE ( "X::X( X const& rhs). this=" << this << " rhs.v=" << rhs.v ) ;
|
||||
|
||||
if ( throw_on_copy )
|
||||
{
|
||||
TRACE ( "throwing exception in X's copy ctor" ) ;
|
||||
throw 0 ;
|
||||
}
|
||||
|
||||
++ count ;
|
||||
}
|
||||
|
||||
~X()
|
||||
{
|
||||
pending_dtor = false ;
|
||||
|
||||
-- count ;
|
||||
|
||||
TRACE ( "X::~X(). v=" << v << " this=" << this );
|
||||
}
|
||||
|
||||
X& operator= ( X const& rhs )
|
||||
{
|
||||
v = rhs.v ;
|
||||
|
||||
TRACE ( "X::operator =( X const& rhs). this=" << this << " rhs.v=" << rhs.v ) ;
|
||||
|
||||
return *this ;
|
||||
}
|
||||
|
||||
friend bool operator == ( X const& a, X const& b )
|
||||
{ return a.v == b.v ; }
|
||||
|
||||
friend bool operator != ( X const& a, X const& b )
|
||||
{ return a.v != b.v ; }
|
||||
|
||||
friend bool operator < ( X const& a, X const& b )
|
||||
{ return a.v < b.v ; }
|
||||
|
||||
int V() const { return v ; }
|
||||
int& V() { return v ; }
|
||||
|
||||
static int count ;
|
||||
static bool pending_copy ;
|
||||
static bool pending_dtor ;
|
||||
static bool throw_on_copy ;
|
||||
|
||||
private :
|
||||
|
||||
int v ;
|
||||
|
||||
private :
|
||||
|
||||
X() ;
|
||||
} ;
|
||||
|
||||
|
||||
int X::count = 0 ;
|
||||
bool X::pending_copy = false ;
|
||||
bool X::pending_dtor = false ;
|
||||
bool X::throw_on_copy = 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_throw_on_copy ( X const* x ) { X::throw_on_copy = true ; }
|
||||
inline void reset_throw_on_copy ( X const* x ) { X::throw_on_copy = 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_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_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 (...) {}
|
||||
inline void set_pending_dtor (...) {}
|
||||
inline void set_throw_on_copy (...) {}
|
||||
inline void reset_throw_on_copy (...) {}
|
||||
inline void check_is_pending_copy (...) {}
|
||||
inline void check_is_pending_dtor (...) {}
|
||||
inline void check_is_not_pending_copy(...) {}
|
||||
inline void check_is_not_pending_dtor(...) {}
|
||||
inline void check_instance_count (...) {}
|
||||
inline int get_instance_count (...) { return 0 ; }
|
||||
|
||||
|
||||
template<class T>
|
||||
inline void check_uninitialized_const ( optional<T> const& opt )
|
||||
{
|
||||
#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
|
||||
BOOST_CHECK( opt == 0 ) ;
|
||||
#endif
|
||||
BOOST_CHECK( !opt ) ;
|
||||
BOOST_CHECK( !get_pointer(opt) ) ;
|
||||
BOOST_CHECK( !opt.get_ptr() ) ;
|
||||
}
|
||||
template<class T>
|
||||
inline void check_uninitialized ( optional<T>& opt )
|
||||
{
|
||||
#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
|
||||
BOOST_CHECK( opt == 0 ) ;
|
||||
#endif
|
||||
BOOST_CHECK( !opt ) ;
|
||||
BOOST_CHECK( !get_pointer(opt) ) ;
|
||||
BOOST_CHECK( !opt.get_ptr() ) ;
|
||||
|
||||
check_uninitialized_const(opt);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void check_initialized_const ( optional<T> const& opt )
|
||||
{
|
||||
BOOST_CHECK( opt ) ;
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
|
||||
BOOST_CHECK( opt != 0 ) ;
|
||||
#endif
|
||||
|
||||
BOOST_CHECK ( !!opt ) ;
|
||||
BOOST_CHECK ( get_pointer(opt) ) ;
|
||||
BOOST_CHECK ( opt.get_ptr() ) ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void check_initialized ( optional<T>& opt )
|
||||
{
|
||||
BOOST_CHECK( opt ) ;
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
|
||||
BOOST_CHECK( opt != 0 ) ;
|
||||
#endif
|
||||
|
||||
BOOST_CHECK ( !!opt ) ;
|
||||
BOOST_CHECK ( get_pointer(opt) ) ;
|
||||
BOOST_CHECK ( opt.get_ptr() ) ;
|
||||
|
||||
check_initialized_const(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 ) ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void check_value ( optional<T>& opt, T const& v, T const& z )
|
||||
{
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) // 1200 == VC++ 6.0
|
||||
// For some reason, VC6.0 is creating a temporary while evaluating (*opt == v),
|
||||
// so we need to turn throw on copy off first.
|
||||
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 ) ;
|
||||
|
||||
check_value_const(opt,v,z);
|
||||
}
|
||||
|
||||
|
283
test/optional_test_common.hpp
Normal file
283
test/optional_test_common.hpp
Normal file
@ -0,0 +1,283 @@
|
||||
// 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/core/ignore_unused.hpp>
|
||||
|
||||
#ifdef ENABLE_TRACE
|
||||
#define TRACE(msg) std::cout << msg << std::endl ;
|
||||
#else
|
||||
#define TRACE(msg)
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
void assertion_failed (char const * expr, char const * func, char const * file, long )
|
||||
{
|
||||
using std::string ;
|
||||
string msg = string("Boost assertion failure for \"")
|
||||
+ string(expr)
|
||||
+ string("\" at file \"")
|
||||
+ string(file)
|
||||
+ string("\" function \"")
|
||||
+ string(func)
|
||||
+ string("\"") ;
|
||||
|
||||
TRACE(msg);
|
||||
|
||||
throw std::logic_error(msg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
using boost::optional ;
|
||||
|
||||
|
||||
#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
|
||||
using boost::swap ;
|
||||
using boost::get ;
|
||||
using boost::get_pointer ;
|
||||
#endif
|
||||
|
||||
// MSVC6.0 does not support comparisons of optional against a literal null pointer value (0)
|
||||
// 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 management of the values held by optional
|
||||
//
|
||||
class X
|
||||
{
|
||||
public :
|
||||
|
||||
X ( int av ) : v(av)
|
||||
{
|
||||
++ count ;
|
||||
|
||||
TRACE ( "X::X(" << av << "). this=" << this ) ;
|
||||
}
|
||||
|
||||
X ( X const& rhs ) : v(rhs.v)
|
||||
{
|
||||
pending_copy = false ;
|
||||
|
||||
TRACE ( "X::X( X const& rhs). this=" << this << " rhs.v=" << rhs.v ) ;
|
||||
|
||||
if ( throw_on_copy )
|
||||
{
|
||||
TRACE ( "throwing exception in X's copy ctor" ) ;
|
||||
throw 0 ;
|
||||
}
|
||||
|
||||
++ count ;
|
||||
}
|
||||
|
||||
~X()
|
||||
{
|
||||
pending_dtor = false ;
|
||||
|
||||
-- count ;
|
||||
|
||||
TRACE ( "X::~X(). v=" << v << " this=" << this );
|
||||
}
|
||||
|
||||
X& operator= ( X const& rhs )
|
||||
{
|
||||
pending_assign = false ;
|
||||
|
||||
if ( throw_on_assign )
|
||||
{
|
||||
TRACE ( "throwing exception in X's assignment" ) ;
|
||||
|
||||
v = -1 ;
|
||||
|
||||
throw 0 ;
|
||||
}
|
||||
else
|
||||
{
|
||||
v = rhs.v ;
|
||||
|
||||
TRACE ( "X::operator =( X const& rhs). this=" << this << " rhs.v=" << rhs.v ) ;
|
||||
}
|
||||
return *this ;
|
||||
}
|
||||
|
||||
friend bool operator == ( X const& a, X const& b )
|
||||
{ return a.v == b.v ; }
|
||||
|
||||
friend bool operator != ( X const& a, X const& b )
|
||||
{ return a.v != b.v ; }
|
||||
|
||||
friend bool operator < ( X const& a, X const& b )
|
||||
{ return a.v < b.v ; }
|
||||
|
||||
int V() const { return v ; }
|
||||
int& V() { return v ; }
|
||||
|
||||
static int count ;
|
||||
static bool pending_copy ;
|
||||
static bool pending_dtor ;
|
||||
static bool pending_assign ;
|
||||
static bool throw_on_copy ;
|
||||
static bool throw_on_assign ;
|
||||
|
||||
private :
|
||||
|
||||
int v ;
|
||||
|
||||
private :
|
||||
|
||||
X() ;
|
||||
} ;
|
||||
|
||||
|
||||
int X::count = 0 ;
|
||||
bool X::pending_copy = false ;
|
||||
bool X::pending_dtor = false ;
|
||||
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::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 (...) {}
|
||||
inline void set_pending_assign (...) {}
|
||||
inline void set_throw_on_copy (...) {}
|
||||
inline void set_throw_on_assign (...) {}
|
||||
inline void reset_throw_on_copy (...) {}
|
||||
inline void reset_throw_on_assign (...) {}
|
||||
inline void check_is_pending_copy (...) {}
|
||||
inline void check_is_pending_dtor (...) {}
|
||||
inline void check_is_pending_assign (...) {}
|
||||
inline void check_is_not_pending_copy (...) {}
|
||||
inline void check_is_not_pending_dtor (...) {}
|
||||
inline void check_is_not_pending_assign(...) {}
|
||||
inline void check_instance_count (...) {}
|
||||
inline int get_instance_count (...) { return 0 ; }
|
||||
|
||||
|
||||
template<class T>
|
||||
inline void check_uninitialized_const ( optional<T> const& opt )
|
||||
{
|
||||
#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
|
||||
BOOST_TEST( opt == 0 ) ;
|
||||
#endif
|
||||
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_TEST( opt == 0 ) ;
|
||||
#endif
|
||||
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);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void check_initialized_const ( optional<T> const& opt )
|
||||
{
|
||||
BOOST_TEST( opt ) ;
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
|
||||
BOOST_TEST( opt != 0 ) ;
|
||||
#endif
|
||||
|
||||
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_TEST( opt ) ;
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
|
||||
BOOST_TEST( opt != 0 ) ;
|
||||
#endif
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void check_value_const ( optional<T> const& opt, T const& v, T const& z )
|
||||
{
|
||||
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>
|
||||
inline void check_value ( optional<T>& opt, T const& v, T const& z )
|
||||
{
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) // 1200 == VC++ 6.0
|
||||
// For some reason, VC6.0 is creating a temporary while evaluating (*opt == v),
|
||||
// so we need to turn throw on copy off first.
|
||||
reset_throw_on_copy( ARG(T) ) ;
|
||||
#endif
|
||||
|
||||
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.
|
||||
static_assert((boost::is_assignable<optional<bool>&, bool>::value), "ERROR");
|
||||
static_assert((boost::is_assignable<optional<bool>&, implicit_bool_conv>::value), "ERROR");
|
||||
static_assert((! boost::is_assignable<optional<bool>&, explicit_bool_conv>::value), "ERROR");
|
||||
#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&&) { static_assert(sizeof(T) == 0, "ERROR"); }
|
||||
#else
|
||||
template <typename T>
|
||||
superconv(const T&) { static_assert(sizeof(T) == 0, "ERROR"); }
|
||||
template <typename T>
|
||||
superconv( T&) { static_assert(sizeof(T) == 0, "ERROR"); }
|
||||
#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> >(std::move(om).flat_map(get_val));
|
||||
optional<int> oi = std::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();
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user