forked from boostorg/utility
Compare commits
992 Commits
svn-branch
...
esp-idf-co
Author | SHA1 | Date | |
---|---|---|---|
7d5d019900 | |||
ff7f512a45 | |||
06548cf5fa | |||
932973fe39 | |||
c63d36cf5b | |||
0106ffda5f | |||
0c1d01d30a | |||
7ac95c156c | |||
eb29d71245 | |||
fe417f6237 | |||
d5c33889b9 | |||
11cff46019 | |||
f11a56c2a7 | |||
69f6588d7c | |||
6950023bca | |||
c3aab6a184 | |||
7717dac7bc | |||
63aadf3f0f | |||
0feb28b467 | |||
78f1b38930 | |||
e6edd4eb91 | |||
9d1284ef6d | |||
aa0ccfa65e | |||
c21d2818c7 | |||
5ae025b56a | |||
f3f7c3c041 | |||
bdc983b804 | |||
a1583e3072 | |||
30caa722c1 | |||
96169c9fc6 | |||
b6119df27f | |||
9941e831bb | |||
a8cdbe516d | |||
485a160dde | |||
2b0441e95f | |||
de106bf696 | |||
b9a91970be | |||
73bccf50db | |||
f7c17df050 | |||
51104850f6 | |||
301ad68447 | |||
5f5aa500d0 | |||
fede5878c3 | |||
a3ec92334d | |||
d186ad3539 | |||
1d6d44c1c4 | |||
0171af0f77 | |||
703a4bf752 | |||
05e0d1688d | |||
dcaf2c0e3b | |||
71107238eb | |||
28c90abaf0 | |||
2cc83cc7d5 | |||
e8fc7cc2a1 | |||
09d24c0516 | |||
3f51807f24 | |||
a04a0d9531 | |||
449a03e13d | |||
dc59afafdb | |||
e845ae6752 | |||
375382e1e6 | |||
6cca23a63a | |||
9ad7e51912 | |||
601f80e8c1 | |||
c960bef6ef | |||
6ab27d5689 | |||
3e2f0199cf | |||
9c2aa8d193 | |||
601fc9371f | |||
7aafdf92a0 | |||
a7570d7608 | |||
37168a3f4b | |||
e56171989a | |||
f00a5bf0d3 | |||
a4feaf4f24 | |||
688628f764 | |||
8faf831bd1 | |||
25cb7aa122 | |||
0ae5cebc7f | |||
1caa002121 | |||
691f3238d7 | |||
8b6da499a3 | |||
6e6d0777e8 | |||
64fffa0f97 | |||
5da340a2a4 | |||
9a4cff038b | |||
0c059a50ad | |||
bdc5b5cf3a | |||
86e7caefea | |||
7953ba56ba | |||
46f72656b3 | |||
e3a2a06011 | |||
a4752e066d | |||
957aeba2e9 | |||
2b436d7d50 | |||
882c9c86c4 | |||
c81d8e3990 | |||
75276a055d | |||
309e6a1b31 | |||
9eeb7f85c5 | |||
62c34f51f6 | |||
6a1917ceec | |||
47c9f69ffe | |||
7b74d2d494 | |||
57da5f0c18 | |||
dabf53a703 | |||
ff56b3649e | |||
31e0ae4c37 | |||
5fe9df91c0 | |||
f03b681d01 | |||
e120a83d1e | |||
424fea5881 | |||
53d9aa9d2f | |||
6b62dcc504 | |||
91ebdcd1dd | |||
e8d2b2ba76 | |||
ce64b13846 | |||
32c50e0814 | |||
05dda09fd3 | |||
a4cafcc75d | |||
796fb965be | |||
08da98a551 | |||
57b027f1cd | |||
db05c11f50 | |||
3d2a7f0c17 | |||
8858bad352 | |||
fc135e0d72 | |||
ebe44296ca | |||
bdf55e0b6f | |||
d4170ccdb5 | |||
e2d115db97 | |||
15cfa44937 | |||
473be2e4c1 | |||
6ad6bc005c | |||
7709f0e430 | |||
eacea4664d | |||
1fe5af5264 | |||
d2fb06e6a0 | |||
73baeb7a63 | |||
56f13625b1 | |||
ac4e8da91d | |||
426836d860 | |||
82df2b82fc | |||
f8a243bcff | |||
51f7f7f53e | |||
5f535a151c | |||
c88936800d | |||
96fbce5759 | |||
9d46de1578 | |||
976a4d2fc1 | |||
ea81279b35 | |||
7d101d420c | |||
d8acfef27b | |||
d7ae336915 | |||
b74f49f1e5 | |||
5977f11be8 | |||
ad0fc7c9d3 | |||
a6c175e2c3 | |||
874ca2307b | |||
5220260145 | |||
2f5a6fbcf1 | |||
51ba9f1b45 | |||
5cef1403b0 | |||
81ce4693f6 | |||
fb2f110eb4 | |||
2ed5ee9588 | |||
88c36c1941 | |||
0b2409a942 | |||
62b39548be | |||
2722fdcda3 | |||
792d0538d2 | |||
06ae661775 | |||
d9d076874e | |||
e25d85446e | |||
5bc9e47688 | |||
ec50f22b8b | |||
592382dc61 | |||
6cf9c22cf1 | |||
33475f87e4 | |||
21261a8630 | |||
7d60e8e378 | |||
10ff4d4fcd | |||
89bf74beee | |||
bfdcce0f97 | |||
330b49d602 | |||
68b26cddbe | |||
6c4ab93573 | |||
0876da45db | |||
00f02167e3 | |||
9960d9f395 | |||
ccfd741c0a | |||
c5c479d49c | |||
3e8f73c6ac | |||
38121f2af3 | |||
38b536ff05 | |||
9ae6492af9 | |||
816607e212 | |||
a3ab942bc2 | |||
0f1f793caf | |||
ff445c0ece | |||
9fae8be166 | |||
b90a28f0e1 | |||
febca584d9 | |||
21dc552cf9 | |||
fda210f597 | |||
3d853b0e83 | |||
4814d1ebfe | |||
e5932ebb08 | |||
93a2e25092 | |||
39577f86d1 | |||
8392991c46 | |||
c5b1256650 | |||
c56dd13592 | |||
181f302ee4 | |||
287844fe76 | |||
3982b6d633 | |||
0b492bee9c | |||
a9236d00a9 | |||
4313bfc323 | |||
f61c94e812 | |||
1dfacff7ec | |||
a25ac4550b | |||
d767054a79 | |||
08a1b7da61 | |||
8ab8e36dcf | |||
1caa745dd7 | |||
cf5ad341ed | |||
1f6de83fe2 | |||
cb6500161b | |||
13610caa36 | |||
6bcf4f92bf | |||
fa8301a56a | |||
7306c8c359 | |||
492fd7f091 | |||
4fbd789253 | |||
4522603132 | |||
cae8d90d65 | |||
2ec0488e2a | |||
520dff9270 | |||
8e24c798ad | |||
651a869d4f | |||
7a8f16efdc | |||
2fa70612bb | |||
f1edd107eb | |||
c185d2dfa9 | |||
4531b2a2a6 | |||
51e482edfe | |||
61d07273fc | |||
42d56fbd51 | |||
6a1e97f870 | |||
c0fdaba925 | |||
87bc4c8dce | |||
34c11cb995 | |||
beab2e74ca | |||
10b8041472 | |||
1ed9aaa2a4 | |||
5a54e21ec5 | |||
8e06104836 | |||
45d884ffd7 | |||
329ca0bae8 | |||
afd9ab17ec | |||
036f6b9107 | |||
da239df58d | |||
46b3739b79 | |||
c5fc075d07 | |||
5ce9683858 | |||
991539725e | |||
df8e0c2dae | |||
f5869d0f82 | |||
db7bba3259 | |||
379e2111e2 | |||
d1bfa8e7b0 | |||
de0e18ca0a | |||
8ae3bfa961 | |||
d4b5fde5a8 | |||
9c4d2843da | |||
ad61f347e4 | |||
b434003b13 | |||
50eafe2027 | |||
87b8e03ca9 | |||
d595357b41 | |||
79d9d9f514 | |||
c48f86c9e4 | |||
514e5299ca | |||
3bac7b132a | |||
9382b69eb1 | |||
52a64d6aec | |||
a292dba021 | |||
e25bd18bd8 | |||
80895c071c | |||
f90812f1d9 | |||
244c343efe | |||
14e9e95c17 | |||
fd9f12b8f1 | |||
96da5105ab | |||
ad98ca9c3c | |||
dfad2950ea | |||
44a98b121b | |||
d5e86bb576 | |||
65d9a78735 | |||
12d17bc26d | |||
03047e3f00 | |||
468fb2dd5f | |||
e97577a0ae | |||
a90bc68a7f | |||
b39e4e5aea | |||
37c8f45edc | |||
4dc9659097 | |||
3d1646cf51 | |||
adf57817ec | |||
1fd5883b34 | |||
fc4bc227b5 | |||
bcd50e9105 | |||
0f5ae0e73c | |||
e33f8b0055 | |||
497198c624 | |||
9df000eece | |||
8e4054467e | |||
7ae5e14681 | |||
b051dd665b | |||
eca8d9f1ef | |||
b813232bba | |||
15021632dc | |||
9baf33dd16 | |||
e02523e286 | |||
6bb1ce9b7b | |||
9092b9277b | |||
d09b37d3ef | |||
f3bb2a493c | |||
71b501a0b0 | |||
547c562464 | |||
91aab126e1 | |||
0d605befd4 | |||
4080fe22e3 | |||
1057ff4d9e | |||
2eda3f5299 | |||
9cb31aee6e | |||
2e4007413e | |||
98bb9e6300 | |||
1cdb78c30a | |||
1ab9131bca | |||
d51799518b | |||
f9540f360c | |||
c1fdb477c1 | |||
e0e16be802 | |||
9284a64936 | |||
6e2c1b6b53 | |||
e4d622019f | |||
05af0deaed | |||
1b2cd6378b | |||
9383bbc283 | |||
00d151828c | |||
f0c62e9e00 | |||
1730c1319b | |||
71205b6e84 | |||
856b01240a | |||
98d793152c | |||
611395441e | |||
dc8ffe92b8 | |||
c55d5ca7de | |||
943af35553 | |||
b35ef27b35 | |||
3cca2755cf | |||
124f4ea879 | |||
93f6e3473b | |||
0f43c44e97 | |||
4a08e3d0bf | |||
3d650b7f92 | |||
0568a114a8 | |||
7148d6c95e | |||
1cfe3145b4 | |||
7d8353f46a | |||
57d65d6a94 | |||
ac9f617f7f | |||
1920623a4f | |||
b6a55f878c | |||
a4e332c4c0 | |||
e9bbb50eb4 | |||
e8440e8855 | |||
c0cca9e8cc | |||
d63444f22e | |||
1f23425baa | |||
a89b0101fc | |||
ff0cb36416 | |||
37c5395e7a | |||
fb2d391928 | |||
3558d61c51 | |||
ad5cf8cf08 | |||
a201cbe646 | |||
2fc827ad23 | |||
8036d4370f | |||
88e7d86270 | |||
5fe00c4322 | |||
6b9f0103d5 | |||
eb613e1b16 | |||
923caf4410 | |||
36bc0a72ac | |||
d5cacff7c6 | |||
b9411f807f | |||
4111de6f68 | |||
df9315101e | |||
2637dfcc59 | |||
a7e8d28621 | |||
acf8b66a4f | |||
7aa68731b4 | |||
c11e08b6b7 | |||
2cfe775694 | |||
799b066e7d | |||
9fa5d63525 | |||
2a6cd0c9c4 | |||
5825b6c329 | |||
54c78121c2 | |||
2891cb52d6 | |||
0db9276e8c | |||
d6cb9a9176 | |||
ef0f82f62b | |||
9a16aaa2b9 | |||
e763315b55 | |||
87b3643647 | |||
c9d56eed6e | |||
e36315c151 | |||
fe653d0a9a | |||
26b39384e3 | |||
9525d062b3 | |||
6d196c4244 | |||
e83682c091 | |||
1d146d010a | |||
5684a2f2b3 | |||
95d2c38379 | |||
1aa48ea698 | |||
7d23c75eef | |||
d01eb82fb7 | |||
86791caf0e | |||
3279399fe3 | |||
87875cadda | |||
c58748cfd9 | |||
58bb88d4bd | |||
11d50ecb9f | |||
636283d7c2 | |||
1df0bf80bc | |||
8176af84e1 | |||
71e78a0081 | |||
f7e4b0e399 | |||
b7d4b6edae | |||
fb1d2effef | |||
94b91e8c92 | |||
d7cf3628f7 | |||
a4b8043e68 | |||
b273cd3914 | |||
ca7db1f361 | |||
b4a08fc80e | |||
9da96d9737 | |||
a991936c96 | |||
6239e685a2 | |||
2a7e81e07f | |||
e601fcb9c9 | |||
f29a5db08e | |||
22743ee125 | |||
e3c982287a | |||
13da21e7b1 | |||
82e1111bb8 | |||
b3ffef536d | |||
9339b32178 | |||
3770221507 | |||
e2c98762db | |||
e6cb3a77ee | |||
bbccfbbab4 | |||
8af4250c3c | |||
e30889304c | |||
b4dee80e61 | |||
74a6a693d3 | |||
bf713ad47a | |||
76b17c497b | |||
a47dce770c | |||
dab1e8e522 | |||
3de5974419 | |||
7eb1536590 | |||
583422cda2 | |||
9339431e03 | |||
ee146a02a1 | |||
c131cbd0b2 | |||
f2349baf7d | |||
f8bef7ba95 | |||
e54cbf3053 | |||
8745ca628a | |||
ba61e9d796 | |||
d5291d08b8 | |||
afe74fffbc | |||
61755605af | |||
cd12e322bd | |||
09a0137016 | |||
a1d3ec6c53 | |||
5be3004e6c | |||
d387905150 | |||
b514e40733 | |||
8cb975feb7 | |||
ffe151458e | |||
4003a9f74a | |||
211eb04f33 | |||
e57213b298 | |||
b02677375f | |||
61a6015b5a | |||
51f9adbfa1 | |||
682032a340 | |||
eaaf17a88f | |||
48cfd42123 | |||
76aa5d2f27 | |||
67afd7e315 | |||
75cf20cace | |||
ce67dde4f0 | |||
a69e872a91 | |||
91385ac627 | |||
61e9b93f7c | |||
d97b303777 | |||
e3640e45c2 | |||
3900e8ece4 | |||
e27fc4a853 | |||
b7cd171b2b | |||
f7aa9a8935 | |||
0af1959b30 | |||
5f0cf4f5de | |||
0282c8a141 | |||
b2e6a82adb | |||
6725719bd9 | |||
390372294a | |||
ffbbf38e12 | |||
9e73b2c6ae | |||
97e11b024e | |||
118e473a3d | |||
d4b6193f94 | |||
633832e872 | |||
d420c98a53 | |||
862cb2a4e0 | |||
d153ab4daa | |||
561f83b991 | |||
b012f16ee5 | |||
3d96ab26d4 | |||
8652bf51ec | |||
57124703f9 | |||
53f6d10652 | |||
ebe853ff2f | |||
487a5c1ea5 | |||
9168cb9c61 | |||
e1991374ae | |||
c4338b1ce8 | |||
ddd8a58ae0 | |||
d0ee9a7c28 | |||
10e83b490b | |||
4b24dba257 | |||
28061ba3a8 | |||
5d53e3f837 | |||
e86ce1cb1f | |||
f15c96ffb0 | |||
a487f72329 | |||
9f08ed6de0 | |||
2077d0dace | |||
7f2348269b | |||
6b6e1c3252 | |||
55f303baec | |||
d264005c11 | |||
2cde009bb1 | |||
7bfb7c8a61 | |||
5c42397244 | |||
782c132d99 | |||
36899afa3f | |||
7e3e326faf | |||
7019e18149 | |||
49faf23433 | |||
62836f2928 | |||
1ecf3ceb74 | |||
2aa48414c9 | |||
d215f2176c | |||
c286d62223 | |||
3fd0ea6e75 | |||
b050431638 | |||
b311fcefb2 | |||
899c92420c | |||
64a0e0cb20 | |||
ece6992540 | |||
6098304ea8 | |||
28fff2d821 | |||
0ce3885d59 | |||
1823481d96 | |||
cce5d77d2b | |||
3c5c2bc107 | |||
7a036f6f3a | |||
e632b0fb1f | |||
17bee9d43f | |||
177ee78bbb | |||
f1ec0c4d04 | |||
4a564744fe | |||
492a8ad213 | |||
8827b8ed8b | |||
8849fbc52d | |||
67f3ca090a | |||
8efae71f4a | |||
50bc75a802 | |||
ad0bcf4a00 | |||
f1c86c35c4 | |||
a5b85eda07 | |||
bafe37fdab | |||
be50b95508 | |||
96d573d6ca | |||
9b52e49fda | |||
2412b864d6 | |||
94865eabe6 | |||
50268d1b29 | |||
ad9108c1dc | |||
ab479794f3 | |||
691e4b6c34 | |||
28596e678d | |||
1beca24dd8 | |||
721764937f | |||
a511007d0f | |||
8ce58b1675 | |||
97b8966337 | |||
9ed68b8321 | |||
79bbf71d0d | |||
ac93de7c1b | |||
88099a882f | |||
d731b8e1c5 | |||
ac1567b3fc | |||
c1fd670480 | |||
01274cf6ac | |||
8080673977 | |||
a470b591fb | |||
e1a63495b6 | |||
7300ac83f1 | |||
882d38c2c7 | |||
33041ad664 | |||
6a2aa822f8 | |||
d5554eb6d7 | |||
13bdfb8bbd | |||
74462349c2 | |||
09ab16bfc1 | |||
ec46e40809 | |||
b3a971e7e9 | |||
7ddb559887 | |||
ea8c99b1d5 | |||
56b0846099 | |||
42e0001370 | |||
cd8f85afee | |||
bddd52c4b9 | |||
6aa648d315 | |||
8f03aeac4e | |||
3bb2568fad | |||
01e91a3799 | |||
55f3c351a3 | |||
3f72b10182 | |||
71cb8cb574 | |||
9ff18c2c96 | |||
c950825ef4 | |||
66ca84a45d | |||
d5ea07c737 | |||
06404f7d39 | |||
aa0096bf42 | |||
2d860e2574 | |||
66514f61ff | |||
63cde4d3fd | |||
1950f292df | |||
005c2f3cc8 | |||
09f7aab52d | |||
92a0602190 | |||
30a40f9f76 | |||
c9a3ab1d04 | |||
d9f8bae673 | |||
0782034333 | |||
3c7b409460 | |||
0808883f3c | |||
ee3551e8dc | |||
2f69501e55 | |||
95da2e90de | |||
5b83f641a8 | |||
6dd93ab916 | |||
c730ab4ffb | |||
505d419a1b | |||
d968b5f5b9 | |||
e55610a0d0 | |||
bf968794c9 | |||
ce6e9c6698 | |||
7ac180ed54 | |||
d809d4e832 | |||
271ea9e901 | |||
7cd572a326 | |||
90c56ba2ce | |||
a5439500f5 | |||
c0f0a4f51d | |||
7594e00460 | |||
f66e844ff1 | |||
62e8cc2b36 | |||
30236f8915 | |||
155e787ea3 | |||
1d60d49136 | |||
2dffdac9fe | |||
ddf00eb29d | |||
0a6acd8ce8 | |||
745322e797 | |||
9f10fc03ce | |||
84fbb3c896 | |||
865c707756 | |||
871f3a6779 | |||
aaca5ca871 | |||
5a4e19989f | |||
6ea398c446 | |||
1bd83d43e8 | |||
5ca5b4102b | |||
aca7699046 | |||
e702a944ca | |||
a157c345ee | |||
dcb2dd4736 | |||
ae19cd6236 | |||
3ab4d38931 | |||
18c7fb72b5 | |||
6bb092a9b1 | |||
f721b8b28c | |||
e5ba34472d | |||
082ae17eaf | |||
dd86e09ab4 | |||
baff23116e | |||
e549baf93a | |||
30d46adcb7 | |||
e854726be0 | |||
d198bd9d96 | |||
5eb23cecd0 | |||
eff2c75bba | |||
325bd73df7 | |||
0fcc554abd | |||
b685784155 | |||
ac90fdc611 | |||
51077e49f5 | |||
0c3199f72d | |||
62675a3bcd | |||
c26dbaa620 | |||
8201624959 | |||
f2116413d6 | |||
b0baebeb0a | |||
fb943b77d5 | |||
b4b39510fc | |||
6f0f05ba12 | |||
f0b64b6229 | |||
4229488989 | |||
acd2e6ef2b | |||
c26aaed71f | |||
326d7ad4d7 | |||
c76a2f4aab | |||
d8b0ff2d7e | |||
996ce2d307 | |||
167fa4154f | |||
0c7e7c3c39 | |||
9d8f8f41dc | |||
39c4445b39 | |||
7819b022ad | |||
65d27e7f86 | |||
212a70bf77 | |||
6b5dc18a46 | |||
0917f83b9c | |||
7322bd3903 | |||
e998010184 | |||
918a1c93e4 | |||
14c87853c2 | |||
d5a5b84a40 | |||
35d3c03d19 | |||
8933fbb254 | |||
c320330cd5 | |||
822b46a3df | |||
a821ef6e2c | |||
491db15997 | |||
b6c826a139 | |||
7b472a05ee | |||
9a07bc0d9b | |||
154d6bb198 | |||
0dde936e61 | |||
918bf25039 | |||
04fda4fb4e | |||
e14a250d6e | |||
806745f24e | |||
4231f774e4 | |||
dfc320124f | |||
be43ba1569 | |||
f3f879555a | |||
3155044abd | |||
484d184de5 | |||
3305cf1592 | |||
ec36cd8c54 | |||
61fb5a0b8f | |||
8024c3e9c7 | |||
2f5945d0cd | |||
929517d6d7 | |||
abcab174a5 | |||
801be90699 | |||
265c2348b8 | |||
fb95bcc64c | |||
aedc410525 | |||
7fa440c154 | |||
746e0fad2b | |||
1616f6f5a8 | |||
ca3e7d8530 | |||
f0f753ba6c | |||
532065b51b | |||
4bfb534bae | |||
95ba7a4381 | |||
e92213431e | |||
7dd7daee1b | |||
953cc46220 | |||
b5ae0ad86b | |||
c86fcbf456 | |||
6ded8b9ad6 | |||
bb6a6272e1 | |||
242634b3fc | |||
662cf14bf6 | |||
fe3aaf62cd | |||
cb189bd6be | |||
f57c914b8f | |||
7cec198e14 | |||
52d3120528 | |||
f1aff5670c | |||
632f682292 | |||
d1d0d6b788 | |||
3bd833c8ff | |||
1ef77b0853 | |||
074007ab8c | |||
c4b7aaf281 | |||
22b8494e9a | |||
c1c8329403 | |||
20a89040e1 | |||
1c7a2a1476 | |||
7c40cc0b63 | |||
73a9e0d351 | |||
dc9856744a | |||
88f4e47550 | |||
1be04eeec5 | |||
56acf9c325 | |||
c6e3957efc | |||
25e8284950 | |||
37a6537a5b | |||
80df1d8f12 | |||
75afed7f17 | |||
1d7066aee1 | |||
12272a38d4 | |||
04f901e52e | |||
fabfb31bf6 | |||
683701cd07 | |||
119c64be0b | |||
d429c9a7d8 | |||
1e8216431b | |||
e45b2e2136 | |||
9e6951009b | |||
a009a209f1 | |||
97605056ed | |||
8fcfa33d33 | |||
aa65e3da3b | |||
b4cfadb4d5 | |||
45a6249668 | |||
1d601aef4d | |||
32fb45eba9 | |||
2b7d10aceb | |||
5dc62711e1 | |||
252c02aca0 | |||
9655beb7ba | |||
f0ea53e77e | |||
4755b42909 | |||
ef9af03c6c | |||
7439073cbf | |||
aff985a563 | |||
db425222d5 | |||
e20af510f7 | |||
d8230c6a73 | |||
f5690787bf | |||
a4fd7b32dd | |||
f4336ec693 | |||
03d906976b | |||
4ba6a96822 | |||
1ea4140d56 | |||
351d4ecb15 | |||
7fbf84dcc6 | |||
3ff49b272d | |||
5b52e3d418 | |||
8c0eb498d3 | |||
48a81ef7ea | |||
f7610c9b26 | |||
1755eaf019 | |||
6b8b218efb | |||
333d79b345 | |||
f0fa436fe4 | |||
13e6d78fa8 | |||
7126ea2685 | |||
a37518cb4a | |||
64b3e8c3bd | |||
339937380e | |||
6156f0d302 | |||
00560e8e17 | |||
029ff9828f | |||
ec188c7c3e | |||
0a0296a5d0 | |||
6e26a5bbe7 | |||
dc1b6246a0 | |||
15f69eaf14 | |||
4774a0d325 | |||
be78ab72c9 | |||
0bc4a1b20d | |||
c8b674d105 | |||
b421d4725a | |||
1662bb5713 | |||
ad79a21abd | |||
19645a52e6 | |||
74c3077c9a | |||
1f29191329 | |||
4b636a7680 | |||
e6fc2555f3 | |||
e27d0fcf2a | |||
2643c33b20 | |||
71af1e77c8 | |||
99e7406bd9 | |||
413265f497 | |||
fe44cdf09b | |||
e413428d71 | |||
88b9822db7 | |||
24045c0cd7 | |||
d2aa9f4a84 | |||
d2a5fd169f | |||
4e350d9934 | |||
f3f697bbc8 | |||
c7c09696db | |||
dbcc58d984 | |||
8231310c4d | |||
2988140430 | |||
7387966005 | |||
e0a5a61375 | |||
66ecd70689 | |||
67f4f45653 | |||
1bf28b3de2 | |||
eb3c3435d7 | |||
8a81d8b16c | |||
bc9d8b13d0 | |||
4768b167ab | |||
591ff70ed1 | |||
7bf2ad0b22 | |||
409c79b2e4 | |||
d0410691a1 | |||
64e5115138 | |||
7ae912d83c | |||
2937f5876c | |||
8619c9b5c3 | |||
e4d5684f6b | |||
3d69cf95da | |||
18944572b7 | |||
3e9d0f80c2 | |||
a2c4d1990a | |||
404261c6ee | |||
87abc59612 | |||
cb98ddf7db | |||
7d2e6c9025 | |||
75eaa14a18 | |||
082d6e3b32 | |||
35b3770b6f | |||
5b9d20c7e2 | |||
5bbed2372e | |||
a9d407d239 | |||
3ca4a33a65 | |||
95197f427c | |||
84cdfb032c | |||
ec2ceb9c96 | |||
6286c893fd | |||
354aef0e8c | |||
139e33c36d | |||
e01de59cdd | |||
686f822dea | |||
9961d5c9af | |||
628be0d125 | |||
633e45f61a | |||
2f357c3805 | |||
cda0894d0d | |||
117720a8bc | |||
a6f6c3613a | |||
7914f5b931 | |||
a1add0a6f6 | |||
c032b337c4 | |||
ec363261ae | |||
97cde2183d | |||
7f43c682db | |||
0c9eee3c6b | |||
3b1afa3ba6 | |||
93e6a75125 | |||
52f8a7c0ca | |||
55bfeb646f | |||
75c9dd3be1 | |||
6392e2788f | |||
6a97f3f9ba | |||
6e5f52e279 | |||
7f92bed902 | |||
d68a11cc42 | |||
328a81e194 |
429
.github/workflows/ci.yml
vendored
Normal file
429
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,429 @@
|
||||
# Copyright 2021 Andrey Semashev
|
||||
#
|
||||
# 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)
|
||||
|
||||
name: CI
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
- feature/**
|
||||
|
||||
concurrency:
|
||||
group: ${{format('{0}:{1}', github.repository, github.ref)}}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
GIT_FETCH_JOBS: 8
|
||||
NET_RETRY_COUNT: 5
|
||||
DEFAULT_BUILD_VARIANT: debug,release
|
||||
|
||||
jobs:
|
||||
posix:
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
# Linux, gcc
|
||||
- toolset: gcc-4.4
|
||||
cxxstd: "98,0x"
|
||||
os: ubuntu-20.04
|
||||
container: ubuntu:16.04
|
||||
install:
|
||||
- g++-4.4
|
||||
sources:
|
||||
- "ppa:ubuntu-toolchain-r/test"
|
||||
- toolset: gcc-4.6
|
||||
cxxstd: "03,0x"
|
||||
os: ubuntu-20.04
|
||||
container: ubuntu:16.04
|
||||
install:
|
||||
- g++-4.6
|
||||
sources:
|
||||
- "ppa:ubuntu-toolchain-r/test"
|
||||
- toolset: gcc-4.7
|
||||
cxxstd: "03,11"
|
||||
os: ubuntu-20.04
|
||||
container: ubuntu:16.04
|
||||
install:
|
||||
- g++-4.7
|
||||
- toolset: gcc-4.8
|
||||
cxxstd: "03,11"
|
||||
os: ubuntu-18.04
|
||||
install:
|
||||
- g++-4.8
|
||||
- toolset: gcc-4.9
|
||||
cxxstd: "03,11"
|
||||
os: ubuntu-20.04
|
||||
container: ubuntu:16.04
|
||||
install:
|
||||
- g++-4.9
|
||||
- toolset: gcc-5
|
||||
cxxstd: "03,11,14,1z"
|
||||
os: ubuntu-20.04
|
||||
container: ubuntu:16.04
|
||||
install:
|
||||
- g++-5
|
||||
- toolset: gcc-6
|
||||
cxxstd: "03,11,14,1z"
|
||||
os: ubuntu-18.04
|
||||
install:
|
||||
- g++-6
|
||||
- toolset: gcc-7
|
||||
cxxstd: "03,11,14,17"
|
||||
os: ubuntu-18.04
|
||||
install:
|
||||
- g++-7
|
||||
- toolset: gcc-8
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-18.04
|
||||
install:
|
||||
- g++-8
|
||||
- toolset: gcc-9
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-18.04
|
||||
install:
|
||||
- g++-9
|
||||
- toolset: gcc-10
|
||||
cxxstd: "03,11,14,17,20"
|
||||
os: ubuntu-20.04
|
||||
install:
|
||||
- g++-10
|
||||
- toolset: gcc-11
|
||||
cxxstd: "03,11,14,17,20"
|
||||
os: ubuntu-20.04
|
||||
install:
|
||||
- g++-11
|
||||
sources:
|
||||
- "ppa:ubuntu-toolchain-r/test"
|
||||
- name: UBSAN
|
||||
toolset: gcc-11
|
||||
cxxstd: "03,11,14,17,20"
|
||||
ubsan: 1
|
||||
build_variant: debug
|
||||
os: ubuntu-20.04
|
||||
install:
|
||||
- g++-11
|
||||
sources:
|
||||
- "ppa:ubuntu-toolchain-r/test"
|
||||
|
||||
# Linux, clang
|
||||
- toolset: clang
|
||||
compiler: clang++-3.5
|
||||
cxxstd: "03,11"
|
||||
os: ubuntu-20.04
|
||||
container: ubuntu:16.04
|
||||
install:
|
||||
- clang-3.5
|
||||
- toolset: clang
|
||||
compiler: clang++-3.6
|
||||
cxxstd: "03,11,14"
|
||||
os: ubuntu-20.04
|
||||
container: ubuntu:16.04
|
||||
install:
|
||||
- clang-3.6
|
||||
- toolset: clang
|
||||
compiler: clang++-3.7
|
||||
cxxstd: "03,11,14"
|
||||
os: ubuntu-20.04
|
||||
container: ubuntu:16.04
|
||||
install:
|
||||
- clang-3.7
|
||||
- toolset: clang
|
||||
compiler: clang++-3.8
|
||||
cxxstd: "03,11,14"
|
||||
os: ubuntu-20.04
|
||||
container: ubuntu:16.04
|
||||
install:
|
||||
- clang-3.8
|
||||
- toolset: clang
|
||||
compiler: clang++-3.9
|
||||
cxxstd: "03,11,14"
|
||||
os: ubuntu-18.04
|
||||
install:
|
||||
- clang-3.9
|
||||
- toolset: clang
|
||||
compiler: clang++-4.0
|
||||
cxxstd: "03,11,14"
|
||||
os: ubuntu-18.04
|
||||
install:
|
||||
- clang-4.0
|
||||
- toolset: clang
|
||||
compiler: clang++-5.0
|
||||
cxxstd: "03,11,14,1z"
|
||||
os: ubuntu-18.04
|
||||
install:
|
||||
- clang-5.0
|
||||
- toolset: clang
|
||||
compiler: clang++-6.0
|
||||
cxxstd: "03,11,14,17"
|
||||
os: ubuntu-18.04
|
||||
install:
|
||||
- clang-6.0
|
||||
- toolset: clang
|
||||
compiler: clang++-7
|
||||
cxxstd: "03,11,14,17"
|
||||
os: ubuntu-18.04
|
||||
install:
|
||||
- clang-7
|
||||
# Note: clang-8 does not fully support C++20, so it is not compatible with libstdc++-8 in this mode
|
||||
- toolset: clang
|
||||
compiler: clang++-8
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-18.04
|
||||
install:
|
||||
- clang-8
|
||||
- g++-7
|
||||
gcc_toolchain: 7
|
||||
- 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,20"
|
||||
os: ubuntu-20.04
|
||||
install:
|
||||
- clang-10
|
||||
- toolset: clang
|
||||
compiler: clang++-11
|
||||
cxxstd: "03,11,14,17,20"
|
||||
os: ubuntu-20.04
|
||||
install:
|
||||
- clang-11
|
||||
- toolset: clang
|
||||
compiler: clang++-12
|
||||
cxxstd: "03,11,14,17,20"
|
||||
os: ubuntu-20.04
|
||||
install:
|
||||
- clang-12
|
||||
- toolset: clang
|
||||
compiler: clang++-12
|
||||
cxxstd: "03,11,14,17,20"
|
||||
os: ubuntu-20.04
|
||||
install:
|
||||
- clang-12
|
||||
- libc++-12-dev
|
||||
- libc++abi-12-dev
|
||||
cxxflags: -stdlib=libc++
|
||||
linkflags: -stdlib=libc++
|
||||
- name: UBSAN
|
||||
toolset: clang
|
||||
compiler: clang++-12
|
||||
cxxstd: "03,11,14,17,20"
|
||||
cxxflags: -stdlib=libc++
|
||||
linkflags: -stdlib=libc++
|
||||
ubsan: 1
|
||||
build_variant: debug
|
||||
os: ubuntu-20.04
|
||||
install:
|
||||
- clang-12
|
||||
- libc++-12-dev
|
||||
- libc++abi-12-dev
|
||||
|
||||
- toolset: clang
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: macos-10.15
|
||||
|
||||
timeout-minutes: 60
|
||||
runs-on: ${{matrix.os}}
|
||||
container: ${{matrix.container}}
|
||||
|
||||
steps:
|
||||
- name: Setup environment
|
||||
run: |
|
||||
if [ -f "/etc/debian_version" ]
|
||||
then
|
||||
echo "DEBIAN_FRONTEND=noninteractive" >> $GITHUB_ENV
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
fi
|
||||
if [ -n "${{matrix.container}}" ]
|
||||
then
|
||||
echo "GHA_CONTAINER=${{matrix.container}}" >> $GITHUB_ENV
|
||||
if [ -f "/etc/debian_version" ]
|
||||
then
|
||||
apt-get -o Acquire::Retries=$NET_RETRY_COUNT update
|
||||
apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y sudo software-properties-common tzdata wget curl apt-transport-https ca-certificates make build-essential g++ python python3 perl git cmake
|
||||
fi
|
||||
fi
|
||||
git config --global pack.threads 0
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install packages
|
||||
if: matrix.install
|
||||
run: |
|
||||
declare -a SOURCE_KEYS SOURCES
|
||||
if [ -n "${{join(matrix.source_keys, ' ')}}" ]
|
||||
then
|
||||
SOURCE_KEYS=("${{join(matrix.source_keys, '" "')}}")
|
||||
fi
|
||||
if [ -n "${{join(matrix.sources, ' ')}}" ]
|
||||
then
|
||||
SOURCES=("${{join(matrix.sources, '" "')}}")
|
||||
fi
|
||||
for key in "${SOURCE_KEYS[@]}"
|
||||
do
|
||||
for i in {1..$NET_RETRY_COUNT}
|
||||
do
|
||||
echo "Adding key: $key"
|
||||
wget -O - "$key" | sudo apt-key add - && break || sleep 2
|
||||
done
|
||||
done
|
||||
if [ ${#SOURCES[@]} -gt 0 ]
|
||||
then
|
||||
APT_ADD_REPO_COMMON_ARGS=("-y")
|
||||
APT_ADD_REPO_SUPPORTED_ARGS="$(apt-add-repository --help | perl -ne 'if (/^\s*-n/) { print "n"; } elsif (/^\s*-P/) { print "P"; } elsif (/^\s*-S/) { print "S"; } elsif (/^\s*-U/) { print "U"; }')"
|
||||
if [ -n "$APT_ADD_REPO_SUPPORTED_ARGS" -a -z "${APT_ADD_REPO_SUPPORTED_ARGS##*n*}" ]
|
||||
then
|
||||
APT_ADD_REPO_COMMON_ARGS+=("-n")
|
||||
fi
|
||||
APT_ADD_REPO_HAS_SOURCE_ARGS="$([ -n "$APT_ADD_REPO_SUPPORTED_ARGS" -a -z "${APT_ADD_REPO_SUPPORTED_ARGS##*P*}" -a -z "${APT_ADD_REPO_SUPPORTED_ARGS##*S*}" -a -z "${APT_ADD_REPO_SUPPORTED_ARGS##*U*}" ] && echo 1 || echo 0)"
|
||||
for source in "${SOURCES[@]}"
|
||||
do
|
||||
for i in {1..$NET_RETRY_COUNT}
|
||||
do
|
||||
APT_ADD_REPO_ARGS=("${APT_ADD_REPO_COMMON_ARGS[@]}")
|
||||
if [ $APT_ADD_REPO_HAS_SOURCE_ARGS -ne 0 ]
|
||||
then
|
||||
case "$source" in
|
||||
"ppa:"*)
|
||||
APT_ADD_REPO_ARGS+=("-P")
|
||||
;;
|
||||
"deb "*)
|
||||
APT_ADD_REPO_ARGS+=("-S")
|
||||
;;
|
||||
*)
|
||||
APT_ADD_REPO_ARGS+=("-U")
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
APT_ADD_REPO_ARGS+=("$source")
|
||||
echo "apt-add-repository ${APT_ADD_REPO_ARGS[@]}"
|
||||
sudo -E apt-add-repository "${APT_ADD_REPO_ARGS[@]}" && break || sleep 2
|
||||
done
|
||||
done
|
||||
fi
|
||||
sudo apt-get -o Acquire::Retries=$NET_RETRY_COUNT update
|
||||
sudo apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y ${{join(matrix.install, ' ')}}
|
||||
|
||||
- name: Setup GCC Toolchain
|
||||
if: matrix.gcc_toolchain
|
||||
run: |
|
||||
GCC_TOOLCHAIN_ROOT="$HOME/gcc-toolchain"
|
||||
echo "GCC_TOOLCHAIN_ROOT=\"$GCC_TOOLCHAIN_ROOT\"" >> $GITHUB_ENV
|
||||
MULTIARCH_TRIPLET="$(dpkg-architecture -qDEB_HOST_MULTIARCH)"
|
||||
mkdir -p "$GCC_TOOLCHAIN_ROOT"
|
||||
ln -s /usr/include "$GCC_TOOLCHAIN_ROOT/include"
|
||||
ln -s /usr/bin "$GCC_TOOLCHAIN_ROOT/bin"
|
||||
mkdir -p "$GCC_TOOLCHAIN_ROOT/lib/gcc/$MULTIARCH_TRIPLET"
|
||||
ln -s "/usr/lib/gcc/$MULTIARCH_TRIPLET/${{matrix.gcc_toolchain}}" "$GCC_TOOLCHAIN_ROOT/lib/gcc/$MULTIARCH_TRIPLET/${{matrix.gcc_toolchain}}"
|
||||
|
||||
- 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
|
||||
BUILD_JOBS=$((nproc || sysctl -n hw.ncpu) 2> /dev/null)
|
||||
echo "BUILD_JOBS=$BUILD_JOBS" >> $GITHUB_ENV
|
||||
echo "CMAKE_BUILD_PARALLEL_LEVEL=$BUILD_JOBS" >> $GITHUB_ENV
|
||||
DEPINST_ARGS=()
|
||||
GIT_VERSION="$(git --version | sed -e 's/git version //')"
|
||||
GIT_HAS_JOBS=1
|
||||
if [ -f "/etc/debian_version" ]
|
||||
then
|
||||
if $(dpkg --compare-versions "$GIT_VERSION" lt 2.8.0)
|
||||
then
|
||||
GIT_HAS_JOBS=0
|
||||
fi
|
||||
else
|
||||
declare -a GIT_VER=(${GIT_VERSION//./ })
|
||||
declare -a GIT_MIN_VER=(2 8 0)
|
||||
for ((i=0; i<${#GIT_VER[@]}; i++))
|
||||
do
|
||||
if [ -z "${GIT_MIN_VER[i]}" ]
|
||||
then
|
||||
GIT_MIN_VER[i]=0
|
||||
fi
|
||||
if [ "${GIT_VER[i]}" -lt "${GIT_MIN_VER[i]}" ]
|
||||
then
|
||||
GIT_HAS_JOBS=0
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if [ "$GIT_HAS_JOBS" -ne 0 ]
|
||||
then
|
||||
DEPINST_ARGS+=("--git_args" "--jobs $GIT_FETCH_JOBS")
|
||||
fi
|
||||
cd ..
|
||||
git clone -b "$BOOST_BRANCH" --depth 1 "https://github.com/boostorg/boost.git" "boost-root"
|
||||
cd boost-root
|
||||
mkdir -p libs/$LIBRARY
|
||||
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
|
||||
git submodule update --init tools/boostdep
|
||||
DEPINST_ARGS+=("$LIBRARY")
|
||||
python tools/boostdep/depinst/depinst.py "${DEPINST_ARGS[@]}"
|
||||
if [ -z "${{matrix.cmake_tests}}" ]
|
||||
then
|
||||
./bootstrap.sh
|
||||
./b2 headers
|
||||
if [ -n "${{matrix.compiler}}" -o -n "$GCC_TOOLCHAIN_ROOT" ]
|
||||
then
|
||||
echo -n "using ${{matrix.toolset}} : : ${{matrix.compiler}}" > ~/user-config.jam
|
||||
if [ -n "$GCC_TOOLCHAIN_ROOT" ]
|
||||
then
|
||||
echo -n " : <compileflags>\"--gcc-toolchain=$GCC_TOOLCHAIN_ROOT\" <linkflags>\"--gcc-toolchain=$GCC_TOOLCHAIN_ROOT\"" >> ~/user-config.jam
|
||||
fi
|
||||
echo " ;" >> ~/user-config.jam
|
||||
fi
|
||||
fi
|
||||
|
||||
- name: Run tests
|
||||
if: matrix.cmake_tests == ''
|
||||
run: |
|
||||
cd ../boost-root
|
||||
B2_ARGS=("-j" "$BUILD_JOBS" "toolset=${{matrix.toolset}}" "cxxstd=${{matrix.cxxstd}}")
|
||||
if [ -n "${{matrix.build_variant}}" ]
|
||||
then
|
||||
B2_ARGS+=("variant=${{matrix.build_variant}}")
|
||||
else
|
||||
B2_ARGS+=("variant=$DEFAULT_BUILD_VARIANT")
|
||||
fi
|
||||
if [ -n "${{matrix.threading}}" ]
|
||||
then
|
||||
B2_ARGS+=("threading=${{matrix.threading}}")
|
||||
fi
|
||||
if [ -n "${{matrix.ubsan}}" ]
|
||||
then
|
||||
export UBSAN_OPTIONS="print_stacktrace=1"
|
||||
B2_ARGS+=("cxxflags=-fsanitize=undefined -fno-sanitize-recover=undefined" "linkflags=-fsanitize=undefined -fuse-ld=gold" "define=UBSAN=1" "debug-symbols=on" "visibility=global")
|
||||
fi
|
||||
if [ -n "${{matrix.cxxflags}}" ]
|
||||
then
|
||||
B2_ARGS+=("cxxflags=${{matrix.cxxflags}}")
|
||||
fi
|
||||
if [ -n "${{matrix.linkflags}}" ]
|
||||
then
|
||||
B2_ARGS+=("linkflags=${{matrix.linkflags}}")
|
||||
fi
|
||||
B2_ARGS+=("libs/$LIBRARY/test")
|
||||
./b2 "${B2_ARGS[@]}"
|
135
Assignable.html
135
Assignable.html
@ -1,116 +1,19 @@
|
||||
<HTML>
|
||||
<!--
|
||||
-- Copyright (c) Jeremy Siek 2000
|
||||
--
|
||||
-- Permission to use, copy, modify, distribute and sell this software
|
||||
-- and its documentation for any purpose is hereby granted without fee,
|
||||
-- provided that the above copyright notice appears in all copies and
|
||||
-- that both that copyright notice and this permission notice appear
|
||||
-- in supporting documentation. Silicon Graphics makes no
|
||||
-- representations about the suitability of this software for any
|
||||
-- purpose. It is provided "as is" without express or implied warranty.
|
||||
-->
|
||||
<Head>
|
||||
<Title>Assignable</Title>
|
||||
</HEAD>
|
||||
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
|
||||
ALINK="#ff0000">
|
||||
<IMG SRC="../../c++boost.gif"
|
||||
ALT="C++ Boost" width="277" height="86">
|
||||
<!--end header-->
|
||||
<BR Clear>
|
||||
<H1>Assignable</H1>
|
||||
|
||||
<h3>Description</h3>
|
||||
A type is Assignable if it is possible to assign one object of the type
|
||||
to another object of that type.
|
||||
|
||||
|
||||
<h3>Notation</h3>
|
||||
<Table>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
<tt>T</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
is type that is a model of Assignable
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
<tt>t</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
is an object of type <tt>T</tt>
|
||||
</TD>
|
||||
</tr>
|
||||
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
<tt>u</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
is an object of type <tt>T</tt> or possibly <tt>const T</tt>
|
||||
</TD>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
<h3>Definitions</h3>
|
||||
<h3>Valid expressions</h3>
|
||||
<Table border>
|
||||
<TR>
|
||||
<TH>
|
||||
Name
|
||||
</TH>
|
||||
<TH>
|
||||
Expression
|
||||
</TH>
|
||||
<TH>
|
||||
Return type
|
||||
</TH>
|
||||
<TH>
|
||||
Semantics
|
||||
</TH>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Assignment
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>t = u</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>T&</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>t</tt> is equivalent to <tt>u</tt>
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
</table>
|
||||
<h3>Models</h3>
|
||||
|
||||
<UL>
|
||||
<LI><tt>int</tt>
|
||||
<LI><tt>std::pair</tt>
|
||||
</UL>
|
||||
|
||||
<h3>See also</h3>
|
||||
<a href="http://www.sgi.com/tech/stl/DefaultConstructible.html">DefaultConstructible</A>
|
||||
and
|
||||
<A href="./CopyConstructible.html">CopyConstructible</A>
|
||||
|
||||
<br>
|
||||
<HR>
|
||||
<TABLE>
|
||||
<TR valign=top>
|
||||
<TD nowrap>Copyright © 2000</TD><TD>
|
||||
<A HREF=http://www.lsc.nd.edu/~jsiek>Jeremy Siek</A>, Univ.of Notre Dame (<A HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>)
|
||||
</TD></TR></TABLE>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Boost.Utility</title>
|
||||
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="./doc/html/index.html">./doc/html/index.html</a>
|
||||
<hr>
|
||||
<tt>
|
||||
Boost.Utility<br>
|
||||
<br>
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||
<br>
|
||||
</tt>
|
||||
</body>
|
||||
</html>
|
||||
|
48
CMakeLists.txt
Normal file
48
CMakeLists.txt
Normal file
@ -0,0 +1,48 @@
|
||||
# Copyright 2018 Peter Dimov
|
||||
# Copyright 2018 Andrey Semashev
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
if(NOT DEFINED IDF_TARGET)
|
||||
|
||||
cmake_minimum_required(VERSION 3.5...3.20)
|
||||
|
||||
project(boost_utility VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX)
|
||||
|
||||
add_library(boost_utility INTERFACE)
|
||||
add_library(Boost::utility ALIAS boost_utility)
|
||||
|
||||
target_include_directories(boost_utility INTERFACE include)
|
||||
|
||||
target_link_libraries(boost_utility
|
||||
INTERFACE
|
||||
Boost::config
|
||||
Boost::core
|
||||
Boost::io
|
||||
Boost::preprocessor
|
||||
Boost::static_assert
|
||||
Boost::throw_exception
|
||||
Boost::type_traits
|
||||
)
|
||||
|
||||
else()
|
||||
|
||||
FILE(GLOB_RECURSE headers include/*.h include/*.hpp)
|
||||
|
||||
idf_component_register(
|
||||
SRCS
|
||||
${headers}
|
||||
INCLUDE_DIRS
|
||||
include
|
||||
REQUIRES
|
||||
boost_config
|
||||
boost_core
|
||||
boost_io
|
||||
boost_preprocessor
|
||||
boost_static_assert
|
||||
boost_throw_exception
|
||||
boost_type_traits
|
||||
)
|
||||
|
||||
endif()
|
||||
|
19
Collection.html
Normal file
19
Collection.html
Normal file
@ -0,0 +1,19 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Boost.Utility</title>
|
||||
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="./doc/html/index.html">./doc/html/index.html</a>
|
||||
<hr>
|
||||
<tt>
|
||||
Boost.Utility<br>
|
||||
<br>
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||
<br>
|
||||
</tt>
|
||||
</body>
|
||||
</html>
|
@ -1,210 +1,19 @@
|
||||
<HTML>
|
||||
<!--
|
||||
-- Copyright (c) Jeremy Siek 2000
|
||||
--
|
||||
-- Permission to use, copy, modify, distribute and sell this software
|
||||
-- and its documentation for any purpose is hereby granted without fee,
|
||||
-- provided that the above copyright notice appears in all copies and
|
||||
-- that both that copyright notice and this permission notice appear
|
||||
-- in supporting documentation. Silicon Graphics makes no
|
||||
-- representations about the suitability of this software for any
|
||||
-- purpose. It is provided "as is" without express or implied warranty.
|
||||
-->
|
||||
<Head>
|
||||
<Title>Copy Constructible</Title>
|
||||
</HEAD>
|
||||
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
|
||||
ALINK="#ff0000">
|
||||
<IMG SRC="../../c++boost.gif"
|
||||
ALT="C++ Boost" width="277" height="86">
|
||||
<!--end header-->
|
||||
<BR Clear>
|
||||
<H1>Copy Constructible</H1>
|
||||
|
||||
<h3>Description</h3>
|
||||
A type is Copy Constructible if it is possible to copy objects of that
|
||||
type.
|
||||
|
||||
<h3>Notation</h3>
|
||||
<Table>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
<tt>T</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
is type that is a model of Copy Constructible
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
<tt>t</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
is an object of type <tt>T</tt>
|
||||
</TD>
|
||||
</tr>
|
||||
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
<tt>u</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
is an object of type <tt>const T</tt>
|
||||
</TD>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
<h3>Definitions</h3>
|
||||
<h3>Valid expressions</h3>
|
||||
<Table border>
|
||||
<TR>
|
||||
<TH>
|
||||
Name
|
||||
</TH>
|
||||
<TH>
|
||||
Expression
|
||||
</TH>
|
||||
<TH>
|
||||
Return type
|
||||
</TH>
|
||||
<TH>
|
||||
Semantics
|
||||
</TH>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Copy constructor
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>T(t)</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>T</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>t</tt> is equivalent to <tt>T(t)</tt>
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Copy constructor
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<pre>
|
||||
T(u)
|
||||
</pre>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>T</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>u</tt> is equivalent to <tt>T(u)</tt>
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Destructor
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<pre>
|
||||
t.~T()
|
||||
</pre>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>T</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Address Operator
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<pre>
|
||||
&t
|
||||
</pre>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>T*</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
denotes the address of <tt>t</tt>
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Address Operator
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<pre>
|
||||
&u
|
||||
</pre>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>T*</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
denotes the address of <tt>u</tt>
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
</table>
|
||||
<h3>Models</h3>
|
||||
|
||||
<UL>
|
||||
<LI><tt>int</tt>
|
||||
<LI><tt>std::pair</tt>
|
||||
</UL>
|
||||
|
||||
<h3>Concept Checking Class</h3>
|
||||
|
||||
<pre>
|
||||
template <class T>
|
||||
struct CopyConstructibleConcept
|
||||
{
|
||||
void constraints() {
|
||||
T a(b); // require copy constructor
|
||||
T* ptr = &a; // require address of operator
|
||||
const_constraints(a);
|
||||
ignore_unused_variable_warning(ptr);
|
||||
}
|
||||
void const_constraints(const T& a) {
|
||||
T c(a); // require const copy constructor
|
||||
const T* ptr = &a; // require const address of operator
|
||||
ignore_unused_variable_warning(c);
|
||||
ignore_unused_variable_warning(ptr);
|
||||
}
|
||||
T b;
|
||||
};
|
||||
</pre>
|
||||
|
||||
<h3>See also</h3>
|
||||
<A
|
||||
href="http://www.sgi.com/tech/stl/DefaultConstructible.html">Default Constructible</A>
|
||||
and
|
||||
<A hrefa="./Assignable.html">Assignable</A>
|
||||
|
||||
<br>
|
||||
<HR>
|
||||
<TABLE>
|
||||
<TR valign=top>
|
||||
<TD nowrap>Copyright © 2000</TD><TD>
|
||||
<A HREF=http://www.lsc.nd.edu/~jsiek>Jeremy Siek</A>, Univ.of Notre Dame (<A HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>)
|
||||
</TD></TR></TABLE>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Boost.Utility</title>
|
||||
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="./doc/html/index.html">./doc/html/index.html</a>
|
||||
<hr>
|
||||
<tt>
|
||||
Boost.Utility<br>
|
||||
<br>
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||
<br>
|
||||
</tt>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,212 +1,19 @@
|
||||
<HTML>
|
||||
<!--
|
||||
-- Copyright (c) Jeremy Siek 2000
|
||||
--
|
||||
-- Permission to use, copy, modify, distribute and sell this software
|
||||
-- and its documentation for any purpose is hereby granted without fee,
|
||||
-- provided that the above copyright notice appears in all copies and
|
||||
-- that both that copyright notice and this permission notice appear
|
||||
-- in supporting documentation. Silicon Graphics makes no
|
||||
-- representations about the suitability of this software for any
|
||||
-- purpose. It is provided "as is" without express or implied warranty.
|
||||
-->
|
||||
<!--
|
||||
-- Copyright (c) 1996-1999
|
||||
-- Silicon Graphics Computer Systems, Inc.
|
||||
--
|
||||
-- Permission to use, copy, modify, distribute and sell this software
|
||||
-- and its documentation for any purpose is hereby granted without fee,
|
||||
-- provided that the above copyright notice appears in all copies and
|
||||
-- that both that copyright notice and this permission notice appear
|
||||
-- in supporting documentation. Silicon Graphics makes no
|
||||
-- representations about the suitability of this software for any
|
||||
-- purpose. It is provided "as is" without express or implied warranty.
|
||||
--
|
||||
-- Copyright (c) 1994
|
||||
-- Hewlett-Packard Company
|
||||
--
|
||||
-- Permission to use, copy, modify, distribute and sell this software
|
||||
-- and its documentation for any purpose is hereby granted without fee,
|
||||
-- provided that the above copyright notice appears in all copies and
|
||||
-- that both that copyright notice and this permission notice appear
|
||||
-- in supporting documentation. Hewlett-Packard Company makes no
|
||||
-- representations about the suitability of this software for any
|
||||
-- purpose. It is provided "as is" without express or implied warranty.
|
||||
--
|
||||
-->
|
||||
<Head>
|
||||
<Title>LessThanComparable</Title>
|
||||
</Head>
|
||||
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
|
||||
ALINK="#ff0000">
|
||||
<IMG SRC="../../c++boost.gif"
|
||||
ALT="C++ Boost" width="277" height="86">
|
||||
<!--end header-->
|
||||
<BR Clear>
|
||||
<H1>LessThanComparable</H1>
|
||||
|
||||
<h3>Description</h3>
|
||||
A type is LessThanComparable if it is ordered: it must
|
||||
be possible to compare two objects of that type using <tt>operator<</tt>, and
|
||||
<tt>operator<</tt> must be a strict weak ordering relation.
|
||||
|
||||
|
||||
<h3>Refinement of</h3>
|
||||
<h3>Associated types</h3>
|
||||
<h3>Notation</h3>
|
||||
<Table>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
<tt>X</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
A type that is a model of LessThanComparable
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
<tt>x</tt>, <tt>y</tt>, <tt>z</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
Object of type <tt>X</tt>
|
||||
</TD>
|
||||
</tr>
|
||||
</table>
|
||||
<h3>Definitions</h3>
|
||||
Consider the relation <tt>!(x < y) && !(y < x)</tt>. If this relation is
|
||||
transitive (that is, if <tt>!(x < y) && !(y < x) && !(y < z) && !(z < y)</tt>
|
||||
implies <tt>!(x < z) && !(z < x)</tt>), then it satisfies the mathematical
|
||||
definition of an equivalence relation. In this case, <tt>operator<</tt>
|
||||
is a <i>strict weak ordering</i>.
|
||||
<P>
|
||||
If <tt>operator<</tt> is a strict weak ordering, and if each equivalence class
|
||||
has only a single element, then <tt>operator<</tt> is a <i>total ordering</i>.
|
||||
<h3>Valid expressions</h3>
|
||||
<Table border>
|
||||
<TR>
|
||||
<TH>
|
||||
Name
|
||||
</TH>
|
||||
<TH>
|
||||
Expression
|
||||
</TH>
|
||||
<TH>
|
||||
Type requirements
|
||||
</TH>
|
||||
<TH>
|
||||
Return type
|
||||
</TH>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Less
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>x < y</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
Convertible to <tt>bool</tt>
|
||||
</TD>
|
||||
</TR>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
<h3>Expression semantics</h3>
|
||||
<Table border>
|
||||
<TR>
|
||||
<TH>
|
||||
Name
|
||||
</TH>
|
||||
<TH>
|
||||
Expression
|
||||
</TH>
|
||||
<TH>
|
||||
Precondition
|
||||
</TH>
|
||||
<TH>
|
||||
Semantics
|
||||
</TH>
|
||||
<TH>
|
||||
Postcondition
|
||||
</TH>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Less
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>x < y</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>x</tt> and <tt>y</tt> are in the domain of <tt><</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
|
||||
</TD>
|
||||
</table>
|
||||
|
||||
|
||||
<h3>Complexity guarantees</h3>
|
||||
<h3>Invariants</h3>
|
||||
<Table border>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Irreflexivity
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>x < x</tt> must be false.
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Antisymmetry
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>x < y</tt> implies !(y < x) <A href="#2">[2]</A>
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Transitivity
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>x < y</tt> and <tt>y < z</tt> implies <tt>x < z</tt> <A href="#3">[3]</A>
|
||||
</TD>
|
||||
</tr>
|
||||
</table>
|
||||
<h3>Models</h3>
|
||||
<UL>
|
||||
<LI>
|
||||
int
|
||||
</UL>
|
||||
<h3>Notes</h3>
|
||||
<P><A name="1">[1]</A>
|
||||
Only <tt>operator<</tt> is fundamental; the other inequality operators
|
||||
are essentially syntactic sugar.
|
||||
<P><A name="2">[2]</A>
|
||||
Antisymmetry is a theorem, not an axiom: it follows from
|
||||
irreflexivity and transitivity.
|
||||
<P><A name="3">[3]</A>
|
||||
Because of irreflexivity and transitivity, <tt>operator<</tt> always
|
||||
satisfies the definition of a <i>partial ordering</i>. The definition of
|
||||
a <i>strict weak ordering</i> is stricter, and the definition of a
|
||||
<i>total ordering</i> is stricter still.
|
||||
<h3>See also</h3>
|
||||
<A href="http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</A>, <A href="http://www.sgi.com/tech/stl/StrictWeakOrdering.html">StrictWeakOrdering</A>
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
<HR>
|
||||
<TABLE>
|
||||
<TR valign=top>
|
||||
<TD nowrap>Copyright © 2000</TD><TD>
|
||||
<A HREF=http://www.lsc.nd.edu/~jsiek>Jeremy Siek</A>, Univ.of Notre Dame (<A HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>)
|
||||
</TD></TR></TABLE>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Boost.Utility</title>
|
||||
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="./doc/html/index.html">./doc/html/index.html</a>
|
||||
<hr>
|
||||
<tt>
|
||||
Boost.Utility<br>
|
||||
<br>
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||
<br>
|
||||
</tt>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,92 +1,19 @@
|
||||
<HTML>
|
||||
<!--
|
||||
-- Copyright (c) Jeremy Siek 2000
|
||||
--
|
||||
-- Permission to use, copy, modify, distribute and sell this software
|
||||
-- and its documentation for any purpose is hereby granted without fee,
|
||||
-- provided that the above copyright notice appears in all copies and
|
||||
-- that both that copyright notice and this permission notice appear
|
||||
-- in supporting documentation. Silicon Graphics makes no
|
||||
-- representations about the suitability of this software for any
|
||||
-- purpose. It is provided "as is" without express or implied warranty.
|
||||
-->
|
||||
<Head>
|
||||
<Title>MultiPassInputIterator</Title>
|
||||
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
|
||||
ALINK="#ff0000">
|
||||
<IMG SRC="../../c++boost.gif"
|
||||
ALT="C++ Boost" width="277" height="86">
|
||||
|
||||
<BR Clear>
|
||||
|
||||
<H2>
|
||||
<A NAME="concept:MultiPassInputIterator"></A>
|
||||
Multi-Pass Input Iterator
|
||||
</H2>
|
||||
|
||||
This concept is a refinement of <a
|
||||
href="http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>,
|
||||
adding the requirements that the iterator can be used to make multiple
|
||||
passes through a range, and that if <TT>it1 == it2</TT> and
|
||||
<TT>it1</TT> is dereferenceable then <TT>++it1 == ++it2</TT>. The
|
||||
Multi-Pass Input Iterator is very similar to the <a
|
||||
href="http://www.sgi.com/tech/stl/ForwardIterator.hmtl">Forward Iterator</a>. The
|
||||
only difference is that a <a
|
||||
href="http://www.sgi.com/tech/stl/ForwardIterator.hmtl">Forward Iterator</a>
|
||||
requires the <TT>reference</TT> type to be <TT>value_type&</TT>, whereas
|
||||
MultiPassInputIterator is like <a
|
||||
href="http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>
|
||||
in that the <TT>reference</TT> type merely has to be convertible to
|
||||
<TT>value_type</TT>.
|
||||
|
||||
|
||||
<h3>Design Notes</h3>
|
||||
|
||||
comments by Valentin Bonnard:
|
||||
|
||||
<p> I think that introducing Multi-Pass Input Iterator isn't the right
|
||||
solution. Do you also want to define Multi-Pass Bidirectionnal Iterator
|
||||
and Multi-Pass Random Access Iterator ? I don't, definitly. It only
|
||||
confuses the issue. The problem lies into the existing hierarchy of
|
||||
iterators, which mixes movabillity, modifiabillity and lvalue-ness,
|
||||
and these are clearly independant.
|
||||
|
||||
<p> The terms Forward, Bidirectionnal and Random Access are about
|
||||
movabillity and shouldn't be used to mean anything else. In a
|
||||
completly orthogonal way, iterators can be immutable, mutable, or
|
||||
neither. Lvalueness of iterators is also orthogonal with
|
||||
immutabillity. With these clean concepts, your Multi-Pass Input Iterator
|
||||
is just called a Forward Iterator.
|
||||
|
||||
<p>
|
||||
Other translations are:<br>
|
||||
std::Forward Iterator -> ForwardIterator & Lvalue Iterator<br>
|
||||
std::Bidirectionnal Iterator -> Bidirectionnal Iterator & Lvalue Iterator<br>
|
||||
std::Random Access Iterator -> Random Access Iterator & Lvalue Iterator<br>
|
||||
|
||||
<p>
|
||||
Note that in practice the only operation not allowed on my
|
||||
Forward Iterator which is allowed on std::Forward Iterator is
|
||||
<tt>&*it</tt>. I think that <tt>&*</tt> is rarely needed in generic code.
|
||||
|
||||
<p>
|
||||
reply by Jeremy Siek:
|
||||
|
||||
<p>
|
||||
The above analysis by Valentin is right on. Of course, there is
|
||||
the problem with backward compatibility. The current STL implementations
|
||||
are based on the old definition of Forward Iterator. The right course
|
||||
of action is to get Forward Iterator, etc. changed in the C++ standard.
|
||||
Once that is done we can drop Multi-Pass Input Iterator.
|
||||
|
||||
|
||||
<br>
|
||||
<HR>
|
||||
<TABLE>
|
||||
<TR valign=top>
|
||||
<TD nowrap>Copyright © 2000</TD><TD>
|
||||
<A HREF=file:///c:/boost/site/people/jeremy_siek.htm>Jeremy Siek</A>, Univ.of Notre Dame (<A HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>)
|
||||
</TD></TR></TABLE>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Boost.Utility</title>
|
||||
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="./doc/html/index.html">./doc/html/index.html</a>
|
||||
<hr>
|
||||
<tt>
|
||||
Boost.Utility<br>
|
||||
<br>
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||
<br>
|
||||
</tt>
|
||||
</body>
|
||||
</html>
|
||||
|
19
OptionalPointee.html
Normal file
19
OptionalPointee.html
Normal file
@ -0,0 +1,19 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Boost.Utility</title>
|
||||
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="./doc/html/index.html">./doc/html/index.html</a>
|
||||
<hr>
|
||||
<tt>
|
||||
Boost.Utility<br>
|
||||
<br>
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||
<br>
|
||||
</tt>
|
||||
</body>
|
||||
</html>
|
26
README.md
Normal file
26
README.md
Normal file
@ -0,0 +1,26 @@
|
||||
# 
|
||||
|
||||
Boost.Utility, part of collection of the [Boost C++ Libraries](https://github.com/boostorg), provides a number of smaller components, too small to be called libraries in their own right. See the documentation for the list of components.
|
||||
|
||||
### Directories
|
||||
|
||||
* **doc** - Documentation sources
|
||||
* **include** - Interface headers of Boost.Utility
|
||||
* **test** - Boost.Utility unit tests
|
||||
|
||||
### More information
|
||||
|
||||
* [Documentation](https://boost.org/libs/utility)
|
||||
* [Report bugs](https://github.com/boostorg/utility/issues/new). Be sure to mention Boost version, Boost.Utility component, platform and compiler you're using. A small compilable code sample to reproduce the problem is always good as well.
|
||||
* Submit your patches as pull requests against **develop** branch. Note that by submitting patches you agree to license your modifications under the [Boost Software License, Version 1.0](https://www.boost.org/LICENSE_1_0.txt).
|
||||
|
||||
### Build status
|
||||
|
||||
Branch | GitHub Actions | AppVeyor | Test Matrix | Dependencies |
|
||||
:-------------: | -------------- | -------- | ----------- | ------------ |
|
||||
[`master`](https://github.com/boostorg/utility/tree/master) | [](https://github.com/boostorg/utility/actions?query=branch%3Amaster) | [](https://ci.appveyor.com/project/Lastique/utility/branch/master) | [](http://www.boost.org/development/tests/master/developer/utility.html) | [](https://pdimov.github.io/boostdep-report/master/utility.html)
|
||||
[`develop`](https://github.com/boostorg/utility/tree/develop) | [](https://github.com/boostorg/utility/actions?query=branch%3Adevelop) | [](https://ci.appveyor.com/project/Lastique/utility/branch/develop) | [](http://www.boost.org/development/tests/develop/developer/utility.html) | [](https://pdimov.github.io/boostdep-report/develop/utility.html)
|
||||
|
||||
### License
|
||||
|
||||
Distributed under the [Boost Software License, Version 1.0](https://www.boost.org/LICENSE_1_0.txt).
|
104
appveyor.yml
Normal file
104
appveyor.yml
Normal file
@ -0,0 +1,104 @@
|
||||
# Copyright 2016-2019 Peter Dimov
|
||||
# Copyright 2019, 2022 Andrey Semashev
|
||||
# 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)
|
||||
|
||||
version: 1.0.{build}-{branch}
|
||||
|
||||
shallow_clone: true
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- develop
|
||||
- /feature\/.*/
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- TOOLSET: msvc-9.0,msvc-10.0,msvc-11.0
|
||||
ADDRMD: 32
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
- TOOLSET: msvc-12.0,msvc-14.0
|
||||
ADDRMD: 32,64
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
- TOOLSET: msvc-14.1
|
||||
CXXSTD: 14,17,latest
|
||||
ADDRMD: 32,64
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
- TOOLSET: msvc-14.2
|
||||
ADDRMD: 32,64
|
||||
CXXSTD: 14,17,20,latest
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
- TOOLSET: msvc-14.3
|
||||
ADDRMD: 32,64
|
||||
CXXSTD: 14,17,20,latest
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
|
||||
- TOOLSET: clang-win
|
||||
ADDRMD: 32
|
||||
CXXSTD: 14,17,latest
|
||||
ENV_SCRIPT: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars32.bat
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
- TOOLSET: clang-win
|
||||
ADDRMD: 64
|
||||
CXXSTD: 14,17,latest
|
||||
ENV_SCRIPT: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
- TOOLSET: gcc
|
||||
CXXSTD: 03,11,14,1z
|
||||
ADDPATH: C:\cygwin\bin;
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
- TOOLSET: gcc
|
||||
CXXSTD: 03,11,14,1z
|
||||
ADDPATH: C:\cygwin64\bin;
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
- TOOLSET: gcc
|
||||
CXXSTD: 03,11,14,1z
|
||||
ADDPATH: C:\mingw\bin;
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
- TOOLSET: gcc
|
||||
CXXSTD: 03,11,14,1z
|
||||
ADDPATH: C:\mingw-w64\x86_64-6.3.0-posix-seh-rt_v5-rev1\mingw64\bin;
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
- TOOLSET: gcc
|
||||
CXXSTD: 03,11,14,17
|
||||
ADDPATH: C:\mingw-w64\x86_64-7.3.0-posix-seh-rt_v5-rev0\mingw64\bin;
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
- TOOLSET: gcc
|
||||
CXXSTD: 03,11,14,17,2a
|
||||
ADDPATH: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin;
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
|
||||
install:
|
||||
- set GIT_FETCH_JOBS=8
|
||||
- set BOOST_BRANCH=develop
|
||||
- if "%APPVEYOR_REPO_BRANCH%" == "master" set BOOST_BRANCH=master
|
||||
- cd ..
|
||||
- git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root
|
||||
- cd boost-root
|
||||
- git submodule init tools/build
|
||||
- git submodule init tools/boost_install
|
||||
- git submodule init libs/headers
|
||||
- git submodule init libs/assert
|
||||
- git submodule init libs/config
|
||||
- git submodule init libs/core
|
||||
- git submodule init libs/io
|
||||
- git submodule init libs/preprocessor
|
||||
- git submodule init libs/static_assert
|
||||
- git submodule init libs/throw_exception
|
||||
- git submodule init libs/type_traits
|
||||
- git submodule init libs/container_hash
|
||||
- git submodule init libs/integer
|
||||
- git submodule init libs/detail
|
||||
- git submodule update --jobs %GIT_FETCH_JOBS%
|
||||
- xcopy /s /e /q %APPVEYOR_BUILD_FOLDER% libs\utility\
|
||||
- cmd /c bootstrap
|
||||
- b2 -d0 headers
|
||||
|
||||
build: off
|
||||
|
||||
test_script:
|
||||
- PATH=%ADDPATH%%PATH%
|
||||
- if not "%ENV_SCRIPT%" == "" call "%ENV_SCRIPT%"
|
||||
- if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD%
|
||||
- if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD%
|
||||
- b2 -j %NUMBER_OF_PROCESSORS% libs/utility/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release
|
769
call_traits.htm
769
call_traits.htm
@ -1,762 +1,19 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type"
|
||||
content="text/html; charset=iso-8859-1">
|
||||
<meta name="Template"
|
||||
content="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<title>Call Traits</title>
|
||||
<title>Boost.Utility</title>
|
||||
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF"
|
||||
vlink="#800080">
|
||||
|
||||
<h1><img src="../../c++boost.gif" width="276" height="86">Header
|
||||
<<a href="../../boost/detail/call_traits.hpp">boost/call_traits.hpp</a>></h1>
|
||||
|
||||
<p>All of the contents of <boost/call_traits.hpp> are
|
||||
defined inside namespace boost.</p>
|
||||
|
||||
<p>The template class call_traits<T> encapsulates the
|
||||
"best" method to pass a parameter of some type T to or
|
||||
from a function, and consists of a collection of typedefs defined
|
||||
as in the table below. The purpose of call_traits is to ensure
|
||||
that problems like "<a href="#refs">references to references</a>"
|
||||
never occur, and that parameters are passed in the most efficient
|
||||
manner possible (see <a href="#examples">examples</a>). In each
|
||||
case if your existing practice is to use the type defined on the
|
||||
left, then replace it with the call_traits defined type on the
|
||||
right. </p>
|
||||
|
||||
<p>Note that for compilers that do not support either partial
|
||||
specialization or member templates, no benefit will occur from
|
||||
using call_traits: the call_traits defined types will always be
|
||||
the same as the existing practice in this case. In addition if
|
||||
only member templates and not partial template specialisation is
|
||||
support by the compiler (for example Visual C++ 6) then
|
||||
call_traits can not be used with array types (although it can be
|
||||
used to solve the reference to reference problem).</p>
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="1" width="797">
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#008080"><p
|
||||
align="center">Existing practice</p>
|
||||
</td>
|
||||
<td valign="top" width="35%" bgcolor="#008080"><p
|
||||
align="center">call_traits equivalent</p>
|
||||
</td>
|
||||
<td valign="top" width="32%" bgcolor="#008080"><p
|
||||
align="center">Description</p>
|
||||
</td>
|
||||
<td valign="top" width="16%" bgcolor="#008080"><p
|
||||
align="center">Notes</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%"><p align="center">T<br>
|
||||
(return by value)</p>
|
||||
</td>
|
||||
<td valign="top" width="35%"><p align="center"><code>call_traits<T>::value_type</code></p>
|
||||
</td>
|
||||
<td valign="top" width="32%">Defines a type that
|
||||
represents the "value" of type T. Use this for
|
||||
functions that return by value, or possibly for stored
|
||||
values of type T.</td>
|
||||
<td valign="top" width="16%"><p align="center">2</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%"><p align="center">T&<br>
|
||||
(return value)</p>
|
||||
</td>
|
||||
<td valign="top" width="35%"><p align="center"><code>call_traits<T>::reference</code></p>
|
||||
</td>
|
||||
<td valign="top" width="32%">Defines a type that
|
||||
represents a reference to type T. Use for functions that
|
||||
would normally return a T&.</td>
|
||||
<td valign="top" width="16%"><p align="center">1</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%"><p align="center">const
|
||||
T&<br>
|
||||
(return value)</p>
|
||||
</td>
|
||||
<td valign="top" width="35%"><p align="center"><code>call_traits<T>::const_reference</code></p>
|
||||
</td>
|
||||
<td valign="top" width="32%">Defines a type that
|
||||
represents a constant reference to type T. Use for
|
||||
functions that would normally return a const T&.</td>
|
||||
<td valign="top" width="16%"><p align="center">1</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%"><p align="center">const
|
||||
T&<br>
|
||||
(function parameter)</p>
|
||||
</td>
|
||||
<td valign="top" width="35%"><p align="center"><code>call_traits<T>::param_type</code></p>
|
||||
</td>
|
||||
<td valign="top" width="32%">Defines a type that
|
||||
represents the "best" way to pass a parameter
|
||||
of type T to a function.</td>
|
||||
<td valign="top" width="16%"><p align="center">1,3</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>Notes:</p>
|
||||
|
||||
<ol>
|
||||
<li>If T is already reference type, then call_traits is
|
||||
defined such that <a href="#refs">references to
|
||||
references</a> do not occur (requires partial
|
||||
specialization).</li>
|
||||
<li>If T is an array type, then call_traits defines <code>value_type</code>
|
||||
as a "constant pointer to type" rather than an
|
||||
"array of type" (requires partial
|
||||
specialization). Note that if you are using value_type as
|
||||
a stored value then this will result in storing a "constant
|
||||
pointer to an array" rather than the array itself.
|
||||
This may or may not be a good thing depending upon what
|
||||
you actually need (in other words take care!).</li>
|
||||
<li>If T is a small built in type or a pointer, then <code>param_type</code>
|
||||
is defined as <code>T const</code>, instead of <code>T
|
||||
const&</code>. This can improve the ability of the
|
||||
compiler to optimize loops in the body of the function if
|
||||
they depend upon the passed parameter, the semantics of
|
||||
the passed parameter is otherwise unchanged (requires
|
||||
partial specialization).</li>
|
||||
</ol>
|
||||
|
||||
<p> </p>
|
||||
|
||||
<h3>Copy constructibility</h3>
|
||||
|
||||
<p>The following table defines which call_traits types can always
|
||||
be copy-constructed from which other types, those entries marked
|
||||
with a '?' are true only if and only if T is copy constructible:</p>
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="1" width="766">
|
||||
<tr>
|
||||
<td valign="top" width="17%"> </td>
|
||||
<td valign="top" colspan="5" width="85%"
|
||||
bgcolor="#008080"><p align="center">To:</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#008080">From:</td>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">T</p>
|
||||
</td>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">value_type</p>
|
||||
</td>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">reference</p>
|
||||
</td>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">const_reference</p>
|
||||
</td>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">param_type</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0">T</td>
|
||||
<td valign="top" width="17%"><p align="center">?</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">?</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0">value_type</td>
|
||||
<td valign="top" width="17%"><p align="center">?</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">?</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">N</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">N</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0">reference</td>
|
||||
<td valign="top" width="17%"><p align="center">?</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">?</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0">const_reference</td>
|
||||
<td valign="top" width="17%"><p align="center">?</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">N</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">N</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0">param_type</td>
|
||||
<td valign="top" width="17%"><p align="center">?</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">?</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">N</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">N</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p> </p>
|
||||
|
||||
<p>If T is an assignable type the following assignments are
|
||||
possible:</p>
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="1" width="766">
|
||||
<tr>
|
||||
<td valign="top" width="17%"> </td>
|
||||
<td valign="top" colspan="5" width="85%"
|
||||
bgcolor="#008080"><p align="center">To:</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#008080">From:</td>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">T</p>
|
||||
</td>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">value_type</p>
|
||||
</td>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">reference</p>
|
||||
</td>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">const_reference</p>
|
||||
</td>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">param_type</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0">T</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">-</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">-</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">-</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0">value_type</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">-</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">-</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">-</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0">reference</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">-</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">-</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">-</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0">const_reference</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">-</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">-</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">-</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0">param_type</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">-</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">-</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">-</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p> </p>
|
||||
|
||||
<h3><a name="examples"></a>Examples</h3>
|
||||
|
||||
<p>The following table shows the effect that call_traits has on
|
||||
various types, the table assumes that the compiler supports
|
||||
partial specialization: if it doesn't then all types behave in
|
||||
the same way as the entry for "myclass", and
|
||||
call_traits can not be used with reference or array types.</p>
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="1" width="766">
|
||||
<tr>
|
||||
<td valign="top" width="17%"> </td>
|
||||
<td valign="top" colspan="5" width="85%"
|
||||
bgcolor="#008080"><p align="center">Call_traits type:</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#008080"><p
|
||||
align="center">Original type T</p>
|
||||
</td>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">value_type</p>
|
||||
</td>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">reference</p>
|
||||
</td>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">const_reference</p>
|
||||
</td>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">param_type</p>
|
||||
</td>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">Applies to:</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">myclass</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">myclass</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">myclass&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const
|
||||
myclass&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">myclass
|
||||
const&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">All user
|
||||
defined types.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">int</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">int</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">int&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const
|
||||
int&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">int const</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">All small
|
||||
built-in types.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">int*</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">int*</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">int*&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">int*const&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">int* const</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">All
|
||||
pointer types.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">int&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">int&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">int&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const
|
||||
int&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">int&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">All
|
||||
reference types.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">const int&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const
|
||||
int&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const
|
||||
int&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const
|
||||
int&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const
|
||||
int&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">All
|
||||
constant-references.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">int[3]</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const int*</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">int(&)[3]</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const int(&)[3]</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const int*
|
||||
const</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">All array
|
||||
types.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">const int[3]</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const int*</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const int(&)[3]</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const int(&)[3]</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const int*
|
||||
const</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">All
|
||||
constant-array types.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p> </p>
|
||||
|
||||
<h4>Example 1:</h4>
|
||||
|
||||
<p>The following class is a trivial class that stores some type T
|
||||
by value (see the <a href="call_traits_test.cpp">call_traits_test.cpp</a>
|
||||
file), the aim is to illustrate how each of the available
|
||||
call_traits typedefs may be used:</p>
|
||||
|
||||
<pre>template <class T>
|
||||
struct contained
|
||||
{
|
||||
// define our typedefs first, arrays are stored by value
|
||||
// so value_type is not the same as result_type:
|
||||
typedef typename boost::call_traits<T>::param_type param_type;
|
||||
typedef typename boost::call_traits<T>::reference reference;
|
||||
typedef typename boost::call_traits<T>::const_reference const_reference;
|
||||
typedef T value_type;
|
||||
typedef typename boost::call_traits<T>::value_type result_type;
|
||||
|
||||
// stored value:
|
||||
value_type v_;
|
||||
|
||||
// constructors:
|
||||
contained() {}
|
||||
contained(param_type p) : v_(p){}
|
||||
// return byval:
|
||||
result_type value() { return v_; }
|
||||
// return by_ref:
|
||||
reference get() { return v_; }
|
||||
const_reference const_get()const { return v_; }
|
||||
// pass value:
|
||||
void call(param_type p){}
|
||||
|
||||
};</pre>
|
||||
|
||||
<h4><a name="refs"></a>Example 2 (the reference to reference
|
||||
problem):</h4>
|
||||
|
||||
<p>Consider the definition of std::binder1st:</p>
|
||||
|
||||
<pre>template <class Operation>
|
||||
class binder1st :
|
||||
public unary_function<typename Operation::second_argument_type, typename Operation::result_type>
|
||||
{
|
||||
protected:
|
||||
Operation op;
|
||||
typename Operation::first_argument_type value;
|
||||
public:
|
||||
binder1st(const Operation& x, const typename Operation::first_argument_type& y);
|
||||
typename Operation::result_type operator()(const typename Operation::second_argument_type& x) const;
|
||||
}; </pre>
|
||||
|
||||
<p>Now consider what happens in the relatively common case that
|
||||
the functor takes its second argument as a reference, that
|
||||
implies that <code>Operation::second_argument_type</code> is a
|
||||
reference type, <code>operator()</code> will now end up taking a
|
||||
reference to a reference as an argument, and that is not
|
||||
currently legal. The solution here is to modify <code>operator()</code>
|
||||
to use call_traits:</p>
|
||||
|
||||
<pre>typename Operation::result_type operator()(typename call_traits<typename Operation::second_argument_type>::param_type x) const;</pre>
|
||||
|
||||
<p>Now in the case that <code>Operation::second_argument_type</code>
|
||||
is a reference type, the argument is passed as a reference, and
|
||||
the no "reference to reference" occurs.</p>
|
||||
|
||||
<h4><a name="ex3"></a>Example 3 (the make_pair problem):</h4>
|
||||
|
||||
<p>If we pass the name of an array as one (or both) arguments to <code>std::make_pair</code>,
|
||||
then template argument deduction deduces the passed parameter as
|
||||
"const reference to array of T", this also applies to
|
||||
string literals (which are really array literals). Consequently
|
||||
instead of returning a pair of pointers, it tries to return a
|
||||
pair of arrays, and since an array type is not copy-constructible
|
||||
the code fails to compile. One solution is to explicitly cast the
|
||||
arguments to make_pair to pointers, but call_traits provides a
|
||||
better (i.e. automatic) solution (and one that works safely even
|
||||
in generic code where the cast might do the wrong thing):</p>
|
||||
|
||||
<pre>template <class T1, class T2>
|
||||
std::pair<
|
||||
typename boost::call_traits<T1>::value_type,
|
||||
typename boost::call_traits<T2>::value_type>
|
||||
make_pair(const T1& t1, const T2& t2)
|
||||
{
|
||||
return std::pair<
|
||||
typename boost::call_traits<T1>::value_type,
|
||||
typename boost::call_traits<T2>::value_type>(t1, t2);
|
||||
}</pre>
|
||||
|
||||
<p>Here, the deduced argument types will be automatically
|
||||
degraded to pointers if the deduced types are arrays, similar
|
||||
situations occur in the standard binders and adapters: in
|
||||
principle in any function that "wraps" a temporary
|
||||
whose type is deduced. Note that the function arguments to
|
||||
make_pair are not expressed in terms of call_traits: doing so
|
||||
would prevent template argument deduction from functioning.</p>
|
||||
|
||||
<h4><a name="ex4"></a>Example 4 (optimising fill):</h4>
|
||||
|
||||
<p>The call_traits template will "optimize" the passing
|
||||
of a small built-in type as a function parameter, this mainly has
|
||||
an effect when the parameter is used within a loop body. In the
|
||||
following example (see <a href="algo_opt_examples.cpp">algo_opt_examples.cpp</a>),
|
||||
a version of std::fill is optimized in two ways: if the type
|
||||
passed is a single byte built-in type then std::memset is used to
|
||||
effect the fill, otherwise a conventional C++ implemention is
|
||||
used, but with the passed parameter "optimized" using
|
||||
call_traits:</p>
|
||||
|
||||
<pre>namespace detail{
|
||||
|
||||
template <bool opt>
|
||||
struct filler
|
||||
{
|
||||
template <typename I, typename T>
|
||||
static void do_fill(I first, I last, typename boost::call_traits<T>::param_type val);
|
||||
{
|
||||
while(first != last)
|
||||
{
|
||||
*first = val;
|
||||
++first;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct filler<true>
|
||||
{
|
||||
template <typename I, typename T>
|
||||
static void do_fill(I first, I last, T val)
|
||||
{
|
||||
memset(first, val, last-first);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <class I, class T>
|
||||
inline void fill(I first, I last, const T& val)
|
||||
{
|
||||
enum{ can_opt = boost::is_pointer<I>::value
|
||||
&& boost::is_arithmetic<T>::value
|
||||
&& (sizeof(T) == 1) };
|
||||
typedef detail::filler<can_opt> filler_t;
|
||||
filler_t::template do_fill<I,T>(first, last, val);
|
||||
}</pre>
|
||||
|
||||
<p>Footnote: the reason that this is "optimal" for
|
||||
small built-in types is that with the value passed as "T
|
||||
const" instead of "const T&" the compiler is
|
||||
able to tell both that the value is constant and that it is free
|
||||
of aliases. With this information the compiler is able to cache
|
||||
the passed value in a register, unroll the loop, or use
|
||||
explicitly parallel instructions: if any of these are supported.
|
||||
Exactly how much mileage you will get from this depends upon your
|
||||
compiler - we could really use some accurate benchmarking
|
||||
software as part of boost for cases like this.</p>
|
||||
|
||||
<p>Note that the function arguments to fill are not expressed in
|
||||
terms of call_traits: doing so would prevent template argument
|
||||
deduction from functioning. Instead fill acts as a "thin
|
||||
wrapper" that is there to perform template argument
|
||||
deduction, the compiler will optimise away the call to fill all
|
||||
together, replacing it with the call to filler<>::do_fill,
|
||||
which does use call_traits.</p>
|
||||
|
||||
<h3>Rationale</h3>
|
||||
|
||||
<p>The following notes are intended to briefly describe the
|
||||
rational behind choices made in call_traits.</p>
|
||||
|
||||
<p>All user-defined types follow "existing practice"
|
||||
and need no comment.</p>
|
||||
|
||||
<p>Small built-in types (what the standard calls fundamental
|
||||
types [3.9.1]) differ from existing practice only in the <i>param_type</i>
|
||||
typedef. In this case passing "T const" is compatible
|
||||
with existing practice, but may improve performance in some cases
|
||||
(see <a href="#ex4">Example 4</a>), in any case this should never
|
||||
be any worse than existing practice.</p>
|
||||
|
||||
<p>Pointers follow the same rational as small built-in types.</p>
|
||||
|
||||
<p>For reference types the rational follows <a href="#refs">Example
|
||||
2</a> - references to references are not allowed, so the
|
||||
call_traits members must be defined such that these problems do
|
||||
not occur. There is a proposal to modify the language such that
|
||||
"a reference to a reference is a reference" (issue #106,
|
||||
submitted by Bjarne Stroustrup), call_traits<T>::value_type
|
||||
and call_traits<T>::param_type both provide the same effect
|
||||
as that proposal, without the need for a language change (in
|
||||
other words it's a workaround).</p>
|
||||
|
||||
<p>For array types, a function that takes an array as an argument
|
||||
will degrade the array type to a pointer type: this means that
|
||||
the type of the actual parameter is different from its declared
|
||||
type, something that can cause endless problems in template code
|
||||
that relies on the declared type of a parameter. For example:</p>
|
||||
|
||||
<pre>template <class T>
|
||||
struct A
|
||||
{
|
||||
void foo(T t);
|
||||
};</pre>
|
||||
|
||||
<p><font face="Times New Roman">In this case if we instantiate
|
||||
A<int[2]> then the declared type of the parameter passed to
|
||||
member function foo is int[2], but it's actual type is const int*,
|
||||
if we try to use the type T within the function body, then there
|
||||
is a strong likelyhood that our code will not compile:</font></p>
|
||||
|
||||
<pre>template <class T>
|
||||
void A<T>::foo(T t)
|
||||
{
|
||||
T dup(t); // doesn't compile for case that T is an array.
|
||||
}</pre>
|
||||
|
||||
<p>By using call_traits the degradation from array to pointer is
|
||||
explicit, and the type of the parameter is the same as it's
|
||||
declared type:</p>
|
||||
|
||||
<pre>template <class T>
|
||||
struct A
|
||||
{
|
||||
void foo(typename call_traits<T>::value_type t);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void A<T>::foo(typename call_traits<T>::value_type t)
|
||||
{
|
||||
typename call_traits<T>::value_type dup(t); // OK even if T is an array type.
|
||||
}</pre>
|
||||
|
||||
<p>For value_type (return by value), again only a pointer may be
|
||||
returned, not a copy of the whole array, and again call_traits
|
||||
makes the degradation explicit. The value_type member is useful
|
||||
whenever an array must be explicitly degraded to a pointer - <a
|
||||
href="#ex3">Example 3</a> provides the test case (Footnote: the
|
||||
array specialisation for call_traits is the least well understood
|
||||
of all the call_traits specialisations, if the given semantics
|
||||
cause specific problems for you, or don't solve a particular
|
||||
array-related problem, then I would be interested to hear about
|
||||
it. Most people though will probably never need to use this
|
||||
specialisation).</p>
|
||||
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="./doc/html/utility/utilities/call_traits.html">./doc/html/utility/utilities/call_traits.html</a>
|
||||
<hr>
|
||||
|
||||
<p>Revised 01 September 2000</p>
|
||||
|
||||
<p><EFBFBD> Copyright boost.org 2000. Permission to copy, use, modify,
|
||||
sell and distribute this document is granted provided this
|
||||
copyright notice appears in all copies. This document is provided
|
||||
"as is" without express or implied warranty, and with
|
||||
no claim as to its suitability for any purpose.</p>
|
||||
|
||||
<p>Based on contributions by Steve Cleary, Beman Dawes, Howard
|
||||
Hinnant and John Maddock.</p>
|
||||
|
||||
<p>Maintained by <a href="mailto:John_Maddock@compuserve.com">John
|
||||
Maddock</a>, the latest version of this file can be found at <a
|
||||
href="http://www.boost.org/">www.boost.org</a>, and the boost
|
||||
discussion list at <a href="http://www.yahoogroups.com/list/boost">www.yahoogroups.com/list/boost</a>.</p>
|
||||
|
||||
<p>.</p>
|
||||
|
||||
<p> </p>
|
||||
|
||||
<p> </p>
|
||||
<tt>
|
||||
Boost.Utility<br>
|
||||
<br>
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||
<br>
|
||||
</tt>
|
||||
</body>
|
||||
</html>
|
||||
|
19
checked_delete.html
Normal file
19
checked_delete.html
Normal file
@ -0,0 +1,19 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Boost.Utility</title>
|
||||
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="../core/doc/html/core/checked_delete.html">../core/doc/html/core/checked_delete.html</a>
|
||||
<hr>
|
||||
<tt>
|
||||
Boost.Utility<br>
|
||||
<br>
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||
<br>
|
||||
</tt>
|
||||
</body>
|
||||
</html>
|
@ -1,31 +0,0 @@
|
||||
// Boost checked_delete test program ---------------------------------------//
|
||||
|
||||
// (C) Copyright Beman Dawes 2001. Permission to copy, use, modify, sell
|
||||
// and distribute this software is granted provided this copyright
|
||||
// notice appears in all copies. This software is provided "as is" without
|
||||
// express or implied warranty, and with no claim as to its suitability for
|
||||
// any purpose.
|
||||
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
// Revision History
|
||||
// 21 May 01 Initial version (Beman Dawes)
|
||||
|
||||
#include <boost/utility.hpp> // for checked_delete
|
||||
|
||||
// This program demonstrates compiler errors when trying to delete an
|
||||
// incomplete type.
|
||||
|
||||
namespace
|
||||
{
|
||||
class Incomplete;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
Incomplete * p;
|
||||
boost::checked_delete(p); // should cause compile time error
|
||||
Incomplete ** pa;
|
||||
boost::checked_array_delete(pa); // should cause compile time error
|
||||
return 0;
|
||||
} // main
|
@ -1,98 +1,19 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type"
|
||||
content="text/html; charset=iso-8859-1">
|
||||
<meta name="Template"
|
||||
content="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage Express 2.0">
|
||||
<title>Header </title>
|
||||
<boost/compressed_pair.hpp>
|
||||
<title>Boost.Utility</title>
|
||||
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF"
|
||||
vlink="#800080">
|
||||
|
||||
<h2><img src="../../c++boost.gif" width="276" height="86">Header
|
||||
<<a href="../../boost/detail/compressed_pair.hpp">boost/compressed_pair.hpp</a>></h2>
|
||||
|
||||
<p>All of the contents of <boost/compressed_pair.hpp> are
|
||||
defined inside namespace boost.</p>
|
||||
|
||||
<p>The class compressed pair is very similar to std::pair, but if
|
||||
either of the template arguments are empty classes, then the
|
||||
"empty member optimisation" is applied to compress the
|
||||
size of the pair.</p>
|
||||
|
||||
<pre>template <class T1, class T2>
|
||||
class compressed_pair
|
||||
{
|
||||
public:
|
||||
typedef T1 first_type;
|
||||
typedef T2 second_type;
|
||||
typedef typename call_traits<first_type>::param_type first_param_type;
|
||||
typedef typename call_traits<second_type>::param_type second_param_type;
|
||||
typedef typename call_traits<first_type>::reference first_reference;
|
||||
typedef typename call_traits<second_type>::reference second_reference;
|
||||
typedef typename call_traits<first_type>::const_reference first_const_reference;
|
||||
typedef typename call_traits<second_type>::const_reference second_const_reference;
|
||||
|
||||
compressed_pair() : base() {}
|
||||
compressed_pair(first_param_type x, second_param_type y);
|
||||
explicit compressed_pair(first_param_type x);
|
||||
explicit compressed_pair(second_param_type y);
|
||||
|
||||
compressed_pair& operator=(const compressed_pair&);
|
||||
|
||||
first_reference first();
|
||||
first_const_reference first() const;
|
||||
|
||||
second_reference second();
|
||||
second_const_reference second() const;
|
||||
|
||||
void swap(compressed_pair& y);
|
||||
};</pre>
|
||||
|
||||
<p>The two members of the pair can be accessed using the member
|
||||
functions first() and second(). Note that not all member
|
||||
functions can be instantiated for all template parameter types.
|
||||
In particular compressed_pair can be instantiated for reference
|
||||
and array types, however in these cases the range of constructors
|
||||
that can be used are limited. If types T1 and T2 are the same
|
||||
type, then there is only one version of the single-argument
|
||||
constructor, and this constructor initialises both values in the
|
||||
pair to the passed value.</p>
|
||||
|
||||
<p>Note that compressed_pair can not be instantiated if either of
|
||||
the template arguments is a union type, unless there is compiler
|
||||
support for boost::is_union, or if boost::is_union is specialised
|
||||
for the union type.</p>
|
||||
|
||||
<p>Finally, a word of caution for Visual C++ 6 users: if either
|
||||
argument is an empty type, then assigning to that member will
|
||||
produce memory corruption, unless the empty type has a "do
|
||||
nothing" assignment operator defined. This is due to a bug
|
||||
in the way VC6 generates implicit assignment operators.</p>
|
||||
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="./doc/html/utility/utilities/compressed_pair.html">./doc/html/utility/utilities/compressed_pair.html</a>
|
||||
<hr>
|
||||
|
||||
<p>Revised 08 May 2001</p>
|
||||
|
||||
<p><EFBFBD> Copyright boost.org 2000. Permission to copy, use, modify,
|
||||
sell and distribute this document is granted provided this
|
||||
copyright notice appears in all copies. This document is provided
|
||||
"as is" without express or implied warranty, and with
|
||||
no claim as to its suitability for any purpose.</p>
|
||||
|
||||
<p>Based on contributions by Steve Cleary, Beman Dawes, Howard
|
||||
Hinnant and John Maddock.</p>
|
||||
|
||||
<p>Maintained by <a href="mailto:John_Maddock@compuserve.com">John
|
||||
Maddock</a>, the latest version of this file can be found at <a
|
||||
href="http://www.boost.org">www.boost.org</a>, and the boost
|
||||
discussion list at <a
|
||||
href="http://www.yahoogroups.com/list/boost">www.yahoogroups.com/list/boost</a>.</p>
|
||||
|
||||
<p> </p>
|
||||
<tt>
|
||||
Boost.Utility<br>
|
||||
<br>
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||
<br>
|
||||
</tt>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,325 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<title>Counting Iterator Adaptor Documentation</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
|
||||
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)"
|
||||
align="center" width="277" height="86">
|
||||
|
||||
<h1>Counting Iterator Adaptor</h1>
|
||||
|
||||
Defined in header
|
||||
<a href="../../boost/counting_iterator.hpp">boost/counting_iterator.hpp</a>
|
||||
|
||||
<p>
|
||||
How would you fill up a vector with the numbers zero
|
||||
through one hundred using <a
|
||||
href="http://www.sgi.com/tech/stl/copy.html"><tt>std::copy()</tt></a>? The
|
||||
only iterator operation missing from builtin integer types is an
|
||||
<tt>operator*()</tt> that returns the current
|
||||
value of the integer. The counting iterator adaptor adds this crucial piece of
|
||||
functionality to whatever type it wraps. One can use the
|
||||
counting iterator adaptor not only with integer types, but with any
|
||||
type that is <tt>Incrementable</tt> (see type requirements <a href="#requirements">below</a>). The
|
||||
following <b>pseudo-code</b> shows the general idea of how the
|
||||
counting iterator is implemented.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
// inside a hypothetical counting_iterator class...
|
||||
typedef Incrementable value_type;
|
||||
value_type counting_iterator::operator*() const {
|
||||
return this->base; // no dereference!
|
||||
}
|
||||
</pre>
|
||||
|
||||
All of the other operators of the counting iterator behave in the same
|
||||
fashion as the <tt>Incrementable</tt> base type.
|
||||
|
||||
<h2>Synopsis</h2>
|
||||
|
||||
<pre>
|
||||
namespace boost {
|
||||
template <class Incrementable>
|
||||
struct <a href="#counting_iterator_traits">counting_iterator_traits</a>;
|
||||
|
||||
template <class Incrementable>
|
||||
struct <a href="#counting_iterator_generator">counting_iterator_generator</a>;
|
||||
|
||||
template <class Incrementable>
|
||||
typename counting_iterator_generator<Incrementable>::type
|
||||
<a href="#make_counting_iterator">make_counting_iterator</a>(Incrementable x);
|
||||
}
|
||||
</pre>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2><a name="counting_iterator_generator">The Counting Iterator Type
|
||||
Generator</a></h2>
|
||||
|
||||
The class template <tt>counting_iterator_generator<Incrementable></tt> is a <a href="../../more/generic_programming.html#type_generator">type generator</a> for counting iterators.
|
||||
|
||||
<pre>
|
||||
template <class Incrementable>
|
||||
class counting_iterator_generator
|
||||
{
|
||||
public:
|
||||
typedef <a href="./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a><...> type;
|
||||
};
|
||||
</pre>
|
||||
|
||||
<h3>Example</h3>
|
||||
|
||||
In this example we use the counting iterator generator to create a
|
||||
counting iterator, and count from zero to four.
|
||||
|
||||
<pre>
|
||||
#include <boost/config.hpp>
|
||||
#include <iostream>
|
||||
#include <boost/counting_iterator.hpp>
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
// Example of using counting_iterator_generator
|
||||
std::cout << "counting from 0 to 4:" << std::endl;
|
||||
boost::counting_iterator_generator<int>::type first(0), last(4);
|
||||
std::copy(first, last, std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
// to be continued...
|
||||
</pre>
|
||||
The output from this part is:
|
||||
<pre>
|
||||
counting from 0 to 4:
|
||||
0 1 2 3
|
||||
</pre>
|
||||
|
||||
<h3>Template Parameters</h3>
|
||||
|
||||
<Table border>
|
||||
<TR>
|
||||
<TH>Parameter</TH><TH>Description</TH>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD><tt>Incrementable</tt></TD>
|
||||
<TD>The type being wrapped by the adaptor.</TD>
|
||||
</TR>
|
||||
|
||||
</Table>
|
||||
|
||||
<h3>Model of</h3>
|
||||
|
||||
If the <tt>Incrementable</tt> type has all of the functionality of a
|
||||
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
|
||||
Access Iterator</a> except the <tt>operator*()</tt>, then the counting
|
||||
iterator will be a model of <a
|
||||
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
|
||||
Access Iterator</a>. If the <tt>Incrementable</tt> type has less
|
||||
functionality, then the counting iterator will have correspondingly
|
||||
less functionality.
|
||||
|
||||
<h3><a name="requirements">Type Requirements</a></h3>
|
||||
|
||||
The <tt>Incrementable</tt> type must be <a
|
||||
href="http://www.sgi.com/tech/stl/DefaultConstructible.html">Default
|
||||
Constructible</a>, <a href="./CopyConstructible.html">Copy
|
||||
Constructible</a>, and <a href="./Assignable.html">Assignable</a>.
|
||||
Also, the <tt>Incrementable</tt> type must provide access to an
|
||||
associated <tt>difference_type</tt> and <tt>iterator_category</tt>
|
||||
through the <a
|
||||
href="#counting_iterator_traits"><tt>counting_iterator_traits</tt></a>
|
||||
class.
|
||||
|
||||
<p>
|
||||
Furthermore, if you wish to create a counting iterator that is a <a
|
||||
href="http://www.sgi.com/tech/stl/ForwardIterator.html"> Forward
|
||||
Iterator</a>, then the following expressions must be valid:
|
||||
<pre>
|
||||
Incrementable i, j;
|
||||
++i // pre-increment
|
||||
i == j // operator equal
|
||||
</pre>
|
||||
If you wish to create a counting iterator that is a <a
|
||||
href="http://www.sgi.com/tech/stl/BidirectionalIterator.html">
|
||||
Bidirectional Iterator</a>, then pre-decrement is also required:
|
||||
<pre>
|
||||
--i
|
||||
</pre>
|
||||
If you wish to create a counting iterator that is a <a
|
||||
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html"> Random
|
||||
Access Iterator</a>, then these additional expressions are also required:
|
||||
<pre>
|
||||
<a href="#counting_iterator_traits">counting_iterator_traits</a><Incrementable>::difference_type n;
|
||||
i += n
|
||||
n = i - j
|
||||
i < j
|
||||
</pre>
|
||||
|
||||
|
||||
|
||||
<h3>Members</h3>
|
||||
|
||||
The counting iterator type implements the member functions and
|
||||
operators required of the <a
|
||||
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
|
||||
Access Iterator</a> concept. In addition it has the following
|
||||
constructor:
|
||||
|
||||
<pre>
|
||||
counting_iterator_generator::type(const Incrementable& i)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
<hr>
|
||||
<p>
|
||||
|
||||
|
||||
<h2><a name="make_counting_iterator">The Counting Iterator Object Generator</a></h2>
|
||||
|
||||
<pre>
|
||||
template <class Incrementable>
|
||||
typename counting_iterator_generator<Incrementable>::type
|
||||
make_counting_iterator(Incrementable base);
|
||||
</pre>
|
||||
|
||||
An <a href="../../more/generic_programming.html#object_generator">object
|
||||
generator</a> function that provides a convenient way to create counting
|
||||
iterators.<p>
|
||||
|
||||
|
||||
|
||||
<h3>Example</h3>
|
||||
|
||||
In this example we count from negative five to positive five, this
|
||||
time using the <tt>make_counting_iterator()</tt> function to save some
|
||||
typing.
|
||||
|
||||
<pre>
|
||||
// continuing from previous example...
|
||||
|
||||
std::cout << "counting from -5 to 4:" << std::endl;
|
||||
std::copy(boost::make_counting_iterator(-5),
|
||||
boost::make_counting_iterator(5),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
// to be continued...
|
||||
</pre>
|
||||
The output from this part is:
|
||||
<pre>
|
||||
counting from -5 to 4:
|
||||
-5 -4 -3 -2 -1 0 1 2 3 4
|
||||
</pre>
|
||||
|
||||
In the next example we create an array of numbers, and then create a
|
||||
second array of pointers, where each pointer is the address of a
|
||||
number in the first array. The counting iterator makes it easy to do
|
||||
this since dereferencing a counting iterator that is wrapping an
|
||||
iterator over the array of numbers just returns a pointer to the
|
||||
current location in the array. We then use the <a
|
||||
href="./indirect_iterator.htm">indirect iterator adaptor</a> to print
|
||||
out the number in the array by accessing the numbers through the array
|
||||
of pointers.
|
||||
|
||||
<pre>
|
||||
// continuing from previous example...
|
||||
|
||||
const int N = 7;
|
||||
std::vector<int> numbers;
|
||||
// Fill "numbers" array with [0,N)
|
||||
std::copy(boost::make_counting_iterator(0), boost::make_counting_iterator(N),
|
||||
std::back_inserter(numbers));
|
||||
|
||||
std::vector<std::vector<int>::iterator> pointers;
|
||||
|
||||
// Use counting iterator to fill in the array of pointers.
|
||||
std::copy(boost::make_counting_iterator(numbers.begin()),
|
||||
boost::make_counting_iterator(numbers.end()),
|
||||
std::back_inserter(pointers));
|
||||
|
||||
// Use indirect iterator to print out numbers by accessing
|
||||
// them through the array of pointers.
|
||||
std::cout << "indirectly printing out the numbers from 0 to "
|
||||
<< N << std::endl;
|
||||
std::copy(boost::make_indirect_iterator(pointers.begin()),
|
||||
boost::make_indirect_iterator(pointers.end()),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
</pre>
|
||||
The output is:
|
||||
<pre>
|
||||
indirectly printing out the numbers from 0 to 7
|
||||
0 1 2 3 4 5 6
|
||||
</pre>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2><a name="counting_iterator_traits">Counting Iterator Traits</a></h2>
|
||||
|
||||
The counting iterator adaptor needs to determine the appropriate
|
||||
<tt>difference_type</tt> and <tt>iterator_category</tt> to use based on the
|
||||
<tt>Incrementable</tt> type supplied by the user. The
|
||||
<tt>counting_iterator_traits</tt> class provides these types. If the
|
||||
<tt>Incrementable</tt> type is an integral type or an iterator, these types
|
||||
will be correctly deduced by the <tt>counting_iterator_traits</tt> provided by
|
||||
the library. Otherwise, the user must specialize
|
||||
<tt>counting_iterator_traits</tt> for her type or add nested typedefs to
|
||||
her type to fulfill the needs of
|
||||
<a href="http://www.sgi.com/tech/stl/iterator_traits.html">
|
||||
<tt>std::iterator_traits</tt></a>.
|
||||
|
||||
<p>The following pseudocode describes how the <tt>counting_iterator_traits</tt> are determined:
|
||||
|
||||
<pre>
|
||||
template <class Incrementable>
|
||||
struct counting_iterator_traits
|
||||
{
|
||||
if (numeric_limits<Incrementable>::is_specialized) {
|
||||
if (!numeric_limits<Incrementable>::is_integer)
|
||||
COMPILE_TIME_ERROR;
|
||||
|
||||
if (!numeric_limits<Incrementable>::is_bounded
|
||||
&& numeric_limits<Incrementable>::is_signed) {
|
||||
typedef Incrementable difference_type;
|
||||
}
|
||||
else if (numeric_limits<Incrementable>::is_integral) {
|
||||
typedef <i>next-larger-signed-type-or-intmax_t</i> difference_type;
|
||||
}
|
||||
typedef std::random_access_iterator_tag iterator_category;
|
||||
} else {
|
||||
typedef std::iterator_traits<Incrementable>::difference_type difference_type;
|
||||
typedef std::iterator_traits<Incrementable>::iterator_category iterator_category;
|
||||
}
|
||||
};
|
||||
</pre>
|
||||
|
||||
<p>The italicized sections above are implementation details, but it is important
|
||||
to know that the <tt>difference_type</tt> for integral types is selected so that
|
||||
it can always represent the difference between two values if such a built-in
|
||||
integer exists. On platforms with a working <tt>std::numeric_limits</tt>
|
||||
implementation, the <tt>difference_type</tt> for any variable-length signed
|
||||
integer type <tt>T</tt> is <tt>T</tt> itself.
|
||||
|
||||
<hr>
|
||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->08 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14892" --></p>
|
||||
<p><EFBFBD> Copyright Jeremy Siek 2000. Permission to copy, use,
|
||||
modify, sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided "as is"
|
||||
without express or implied warranty, and with no claim as to its suitability for
|
||||
any purpose.</p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
<!-- LocalWords: html charset alt gif hpp incrementable const namespace htm
|
||||
-->
|
||||
<!-- LocalWords: struct typename iostream int Siek CopyConstructible pre
|
||||
-->
|
||||
|
@ -1,53 +0,0 @@
|
||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
#include <boost/counting_iterator.hpp>
|
||||
#include <boost/iterator_adaptors.hpp>
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
// Example of using counting_iterator_generator
|
||||
std::cout << "counting from 0 to 4:" << std::endl;
|
||||
boost::counting_iterator_generator<int>::type first(0), last(4);
|
||||
std::copy(first, last, std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
// Example of using make_counting_iterator()
|
||||
std::cout << "counting from -5 to 4:" << std::endl;
|
||||
std::copy(boost::make_counting_iterator(-5),
|
||||
boost::make_counting_iterator(5),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
// Example of using counting iterator to create an array of pointers.
|
||||
const int N = 7;
|
||||
std::vector<int> numbers;
|
||||
// Fill "numbers" array with [0,N)
|
||||
std::copy(boost::make_counting_iterator(0), boost::make_counting_iterator(N),
|
||||
std::back_inserter(numbers));
|
||||
|
||||
std::vector<std::vector<int>::iterator> pointers;
|
||||
|
||||
// Use counting iterator to fill in the array of pointers.
|
||||
std::copy(boost::make_counting_iterator(numbers.begin()),
|
||||
boost::make_counting_iterator(numbers.end()),
|
||||
std::back_inserter(pointers));
|
||||
|
||||
// Use indirect iterator to print out numbers by accessing
|
||||
// them through the array of pointers.
|
||||
std::cout << "indirectly printing out the numbers from 0 to "
|
||||
<< N << std::endl;
|
||||
std::copy(boost::make_indirect_iterator(pointers.begin()),
|
||||
boost::make_indirect_iterator(pointers.end()),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,263 +0,0 @@
|
||||
// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears in
|
||||
// all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
//
|
||||
// Revision History
|
||||
// 16 Feb 2001 Added a missing const. Made the tests run (somewhat) with
|
||||
// plain MSVC again. (David Abrahams)
|
||||
// 11 Feb 2001 #if 0'd out use of counting_iterator on non-numeric types in
|
||||
// MSVC without STLport, so that the other tests may proceed
|
||||
// (David Abrahams)
|
||||
// 04 Feb 2001 Added use of iterator_tests.hpp (David Abrahams)
|
||||
// 28 Jan 2001 Removed not_an_iterator detritus (David Abrahams)
|
||||
// 24 Jan 2001 Initial revision (David Abrahams)
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(disable:4786) // identifier truncated in debug info
|
||||
#endif
|
||||
|
||||
#include <boost/pending/iterator_tests.hpp>
|
||||
#include <boost/counting_iterator.hpp>
|
||||
#include <boost/detail/iterator.hpp>
|
||||
#include <iostream>
|
||||
#include <climits>
|
||||
#include <iterator>
|
||||
#include <stdlib.h>
|
||||
#include <boost/utility.hpp>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <cassert>
|
||||
#ifndef BOOST_NO_LIMITS
|
||||
# include <limits>
|
||||
#endif
|
||||
#ifndef BOOST_NO_SLIST
|
||||
# include <slist>
|
||||
#endif
|
||||
|
||||
template <class T> struct is_numeric
|
||||
{
|
||||
enum { value =
|
||||
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
|
||||
std::numeric_limits<T>::is_specialized
|
||||
#else
|
||||
// Causes warnings with GCC, but how else can I detect numeric types at
|
||||
// compile-time?
|
||||
(boost::is_convertible<int,T>::value &&
|
||||
boost::is_convertible<T,int>::value)
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
// Special tests for RandomAccess CountingIterators.
|
||||
template <class CountingIterator>
|
||||
void category_test(
|
||||
CountingIterator start,
|
||||
CountingIterator finish,
|
||||
std::random_access_iterator_tag)
|
||||
{
|
||||
typedef typename
|
||||
boost::detail::iterator_traits<CountingIterator>::difference_type
|
||||
difference_type;
|
||||
difference_type distance = boost::detail::distance(start, finish);
|
||||
|
||||
// Pick a random position internal to the range
|
||||
difference_type offset = (unsigned)rand() % distance;
|
||||
assert(offset >= 0);
|
||||
CountingIterator internal = start;
|
||||
std::advance(internal, offset);
|
||||
|
||||
// Try some binary searches on the range to show that it's ordered
|
||||
assert(std::binary_search(start, finish, *internal));
|
||||
CountingIterator x,y;
|
||||
boost::tie(x,y) = std::equal_range(start, finish, *internal);
|
||||
assert(boost::detail::distance(x, y) == 1);
|
||||
|
||||
// Show that values outside the range can't be found
|
||||
assert(!std::binary_search(start, boost::prior(finish), *finish));
|
||||
|
||||
// Do the generic random_access_iterator_test
|
||||
typedef typename CountingIterator::value_type value_type;
|
||||
std::vector<value_type> v;
|
||||
for (value_type z = *start; z != *finish; ++z)
|
||||
v.push_back(z);
|
||||
if (v.size() >= 2)
|
||||
{
|
||||
// Note that this test requires a that the first argument is
|
||||
// dereferenceable /and/ a valid iterator prior to the first argument
|
||||
boost::random_access_iterator_test(start + 1, v.size() - 1, v.begin() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Special tests for bidirectional CountingIterators
|
||||
template <class CountingIterator>
|
||||
void category_test(CountingIterator start, CountingIterator finish, std::bidirectional_iterator_tag)
|
||||
{
|
||||
if (finish != start
|
||||
&& finish != boost::next(start)
|
||||
&& finish != boost::next(boost::next(start)))
|
||||
{
|
||||
// Note that this test requires a that the first argument is
|
||||
// dereferenceable /and/ a valid iterator prior to the first argument
|
||||
boost::bidirectional_iterator_test(boost::next(start), boost::next(*start), boost::next(boost::next(*start)));
|
||||
}
|
||||
}
|
||||
|
||||
template <class CountingIterator>
|
||||
void category_test(CountingIterator start, CountingIterator finish, std::forward_iterator_tag)
|
||||
{
|
||||
if (finish != start && finish != boost::next(start))
|
||||
boost::forward_iterator_test(start, *start, boost::next(*start));
|
||||
}
|
||||
|
||||
template <class CountingIterator>
|
||||
void test_aux(CountingIterator start, CountingIterator finish)
|
||||
{
|
||||
typedef typename CountingIterator::iterator_category category;
|
||||
typedef typename CountingIterator::value_type value_type;
|
||||
|
||||
// If it's a RandomAccessIterator we can do a few delicate tests
|
||||
category_test(start, finish, category());
|
||||
|
||||
// Okay, brute force...
|
||||
for (CountingIterator p = start; p != finish && boost::next(p) != finish; ++p)
|
||||
{
|
||||
assert(boost::next(*p) == *boost::next(p));
|
||||
}
|
||||
|
||||
// prove that a reference can be formed to these values
|
||||
typedef typename CountingIterator::value_type value;
|
||||
const value* q = &*start;
|
||||
(void)q; // suppress unused variable warning
|
||||
}
|
||||
|
||||
template <class Incrementable>
|
||||
void test(Incrementable start, Incrementable finish)
|
||||
{
|
||||
test_aux(boost::make_counting_iterator(start), boost::make_counting_iterator(finish));
|
||||
}
|
||||
|
||||
template <class Integer>
|
||||
void test_integer(Integer* = 0) // default arg works around MSVC bug
|
||||
{
|
||||
Integer start = 0;
|
||||
Integer finish = 120;
|
||||
test(start, finish);
|
||||
}
|
||||
|
||||
template <class Container>
|
||||
void test_container(Container* = 0) // default arg works around MSVC bug
|
||||
{
|
||||
Container c(1 + (unsigned)rand() % 1673);
|
||||
|
||||
const typename Container::iterator start = c.begin();
|
||||
|
||||
// back off by 1 to leave room for dereferenceable value at the end
|
||||
typename Container::iterator finish = start;
|
||||
std::advance(finish, c.size() - 1);
|
||||
|
||||
test(start, finish);
|
||||
|
||||
typedef typename Container::const_iterator const_iterator;
|
||||
test(const_iterator(start), const_iterator(finish));
|
||||
}
|
||||
|
||||
class my_int1 {
|
||||
public:
|
||||
my_int1() { }
|
||||
my_int1(int x) : m_int(x) { }
|
||||
my_int1& operator++() { ++m_int; return *this; }
|
||||
bool operator==(const my_int1& x) const { return m_int == x.m_int; }
|
||||
private:
|
||||
int m_int;
|
||||
};
|
||||
|
||||
namespace boost {
|
||||
template <>
|
||||
struct counting_iterator_traits<my_int1> {
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
};
|
||||
}
|
||||
|
||||
class my_int2 {
|
||||
public:
|
||||
typedef void value_type;
|
||||
typedef void pointer;
|
||||
typedef void reference;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::bidirectional_iterator_tag iterator_category;
|
||||
|
||||
my_int2() { }
|
||||
my_int2(int x) : m_int(x) { }
|
||||
my_int2& operator++() { ++m_int; return *this; }
|
||||
my_int2& operator--() { --m_int; return *this; }
|
||||
bool operator==(const my_int2& x) const { return m_int == x.m_int; }
|
||||
private:
|
||||
int m_int;
|
||||
};
|
||||
|
||||
class my_int3 {
|
||||
public:
|
||||
typedef void value_type;
|
||||
typedef void pointer;
|
||||
typedef void reference;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::random_access_iterator_tag iterator_category;
|
||||
|
||||
my_int3() { }
|
||||
my_int3(int x) : m_int(x) { }
|
||||
my_int3& operator++() { ++m_int; return *this; }
|
||||
my_int3& operator+=(std::ptrdiff_t n) { m_int += n; return *this; }
|
||||
std::ptrdiff_t operator-(const my_int3& x) const { return m_int - x.m_int; }
|
||||
my_int3& operator--() { --m_int; return *this; }
|
||||
bool operator==(const my_int3& x) const { return m_int == x.m_int; }
|
||||
bool operator!=(const my_int3& x) const { return m_int != x.m_int; }
|
||||
bool operator<(const my_int3& x) const { return m_int < x.m_int; }
|
||||
private:
|
||||
int m_int;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
// Test the built-in integer types.
|
||||
test_integer<char>();
|
||||
test_integer<unsigned char>();
|
||||
test_integer<signed char>();
|
||||
test_integer<wchar_t>();
|
||||
test_integer<short>();
|
||||
test_integer<unsigned short>();
|
||||
test_integer<int>();
|
||||
test_integer<unsigned int>();
|
||||
test_integer<long>();
|
||||
test_integer<unsigned long>();
|
||||
#if defined(ULLONG_MAX) || defined(ULONG_LONG_MAX)
|
||||
test_integer<long long>();
|
||||
test_integer<unsigned long long>();
|
||||
#endif
|
||||
|
||||
// wrapping an iterator or non-built-in integer type causes an INTERNAL
|
||||
// COMPILER ERROR in MSVC without STLport. I'm clueless as to why.
|
||||
#if !defined(BOOST_MSVC) || defined(__SGI_STL_PORT)
|
||||
// Test user-defined type.
|
||||
test_integer<my_int1>();
|
||||
test_integer<my_int2>();
|
||||
test_integer<my_int3>();
|
||||
|
||||
// Some tests on container iterators, to prove we handle a few different categories
|
||||
test_container<std::vector<int> >();
|
||||
test_container<std::list<int> >();
|
||||
# ifndef BOOST_NO_SLIST
|
||||
test_container<BOOST_STD_EXTENSION_NAMESPACE::slist<int> >();
|
||||
# endif
|
||||
|
||||
// Also prove that we can handle raw pointers.
|
||||
int array[2000];
|
||||
test(boost::make_counting_iterator(array), boost::make_counting_iterator(array+2000-1));
|
||||
#endif
|
||||
std::cout << "test successful " << std::endl;
|
||||
return 0;
|
||||
}
|
4
doc/.gitignore
vendored
Normal file
4
doc/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
html
|
||||
xml
|
||||
temp
|
||||
out.txt
|
81
doc/BOOST_BINARY.qbk
Normal file
81
doc/BOOST_BINARY.qbk
Normal file
@ -0,0 +1,81 @@
|
||||
[/
|
||||
/ Copyright (c) 2012 Marshall Clow
|
||||
/ Copyright (c) 2021, Alan Freitas
|
||||
/ 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)
|
||||
/]
|
||||
|
||||
[/===============]
|
||||
[#sec:BOOST_BINARY]
|
||||
[section Binary Integer Literals]
|
||||
[/===============]
|
||||
|
||||
[section Introduction]
|
||||
|
||||
The macro `BOOST_BINARY` is used for the representation of binary
|
||||
literals. It takes as an argument a binary number arranged as an
|
||||
arbitrary amount of 1s and 0s in groupings of length 1 to 8, with
|
||||
groups separated by spaces. The macro serves as a replacement for
|
||||
[@https://en.cppreference.com/w/cpp/language/integer_literal binary integer literals],
|
||||
adopted in C++14.
|
||||
|
||||
The type of the literal yielded is determined by the same rules as
|
||||
those of [@https://en.cppreference.com/w/cpp/language/integer_literal hex and octal literals].
|
||||
By implementation, this macro expands directly to an octal literal during preprocessing, so
|
||||
there is no overhead at runtime and the result is usable in any place that an octal literal
|
||||
would be.
|
||||
|
||||
In order to directly support binary literals with suffixes,
|
||||
additional macros of the form `BOOST_BINARY_XXX` are also
|
||||
provided, where `XXX` is a standard integer suffix in all capital
|
||||
letters.
|
||||
|
||||
In addition, LL and ULL suffixes may be used for representing
|
||||
`long long` and `unsigned long long` types in compilers which provide
|
||||
them as an extension.
|
||||
|
||||
The `BOOST_BINARY` family of macros resides in the header
|
||||
[@../../../../boost/utility/binary.hpp <boost/utility/binary.hpp>].
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Example]
|
||||
|
||||
```
|
||||
void foo( int );
|
||||
|
||||
void foo( unsigned long );
|
||||
|
||||
void bar()
|
||||
{
|
||||
int value1 = BOOST_BINARY( 100 111000 01 1 110 );
|
||||
|
||||
unsigned long value2 = BOOST_BINARY_UL( 100 001 ); // unsigned long
|
||||
|
||||
long long value3 = BOOST_BINARY_LL( 11 000 ); // long long if supported
|
||||
|
||||
__assert__( BOOST_BINARY( 10010 )
|
||||
& BOOST_BINARY( 11000 )
|
||||
== BOOST_BINARY( 10000 )
|
||||
);
|
||||
|
||||
foo( BOOST_BINARY( 1010 ) ); // calls the first foo
|
||||
|
||||
foo( BOOST_BINARY_LU( 1010 ) ); // calls the second foo
|
||||
}
|
||||
```
|
||||
|
||||
[endsect]
|
||||
|
||||
[/===============]
|
||||
[xinclude tmp/boost_binary_reference.xml]
|
||||
[/===============]
|
||||
|
||||
|
||||
[section Acknowledgments]
|
||||
|
||||
Contributed by Matt Calabrese.
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
413
doc/Jamfile.v2
Normal file
413
doc/Jamfile.v2
Normal file
@ -0,0 +1,413 @@
|
||||
# Copyright John Maddock 2005. Use, modification, and distribution are
|
||||
# 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)
|
||||
|
||||
import project ;
|
||||
import doxygen ;
|
||||
import quickbook ;
|
||||
|
||||
project boost/libs/utility/doc ;
|
||||
|
||||
path-constant INCLUDES : ../../.. ;
|
||||
path-constant boost-images : ../../../doc/src/images ;
|
||||
|
||||
# Generate XML doxygen reference for base_from_member component in base_from_member_reference.xml
|
||||
doxygen base_from_member_reference
|
||||
:
|
||||
$(INCLUDES)/boost/utility/base_from_member.hpp
|
||||
:
|
||||
<location>tmp
|
||||
<doxygen:param>ENABLE_PREPROCESSING=YES
|
||||
<doxygen:param>EXPAND_ONLY_PREDEF=YES
|
||||
<doxygen:param>EXTRACT_ALL=NO
|
||||
<doxygen:param>EXTRACT_PRIVATE=NO
|
||||
<doxygen:param>HIDE_UNDOC_MEMBERS=YES
|
||||
<doxygen:param>MACRO_EXPANSION=YES
|
||||
<doxygen:param>"PREDEFINED= \\
|
||||
BOOST_UTILITY_DOCS \\
|
||||
BOOST_SYMBOL_VISIBLE= \\
|
||||
BOOST_FORCEINLINE=inline \\
|
||||
BOOST_GPU_ENABLED= \\
|
||||
BOOST_STATIC_ASSERT(x)= \\
|
||||
BOOST_STATIC_ASSERT_MSG(x,y)= \\
|
||||
BOOST_STATIC_CONSTANT(x,y)=\"static constexpr x y\" \\
|
||||
BOOST_RV_REF(x)=\"x&&\" \\
|
||||
BOOST_NESTED_TEMPLATE=template \\
|
||||
BOOST_CONSTEXPR=constexpr \\
|
||||
BOOST_CXX14_CONSTEXPR=constexpr \\
|
||||
BOOST_OPERATORS_CONSTEXPR=constexpr \\
|
||||
BOOST_CONSTEXPR_OR_CONST=constexpr \\
|
||||
BOOST_NOEXCEPT=noexcept \\
|
||||
BOOST_NOEXCEPT_IF(x)=noexcept(x) \\
|
||||
BOOST_NOEXCEPT_OR_NOTHROW=noexcept \\
|
||||
BOOST_COPY_ASSIGN_REF(x)=\"x const&\" \\
|
||||
BOOST_DEFAULTED_FUNCTION(x,y)=\"x = default;\" \\
|
||||
BOOST_DELETED_FUNCTION(x)=\"x = delete;\" \\
|
||||
BOOST_EXPLICIT_OPERATOR_BOOL()=\"explicit operator bool() const;\" \\
|
||||
BOOST_REF_CONST=const"
|
||||
<doxygen:param>"EXCLUDE_SYMBOLS= \\
|
||||
detail \\
|
||||
F \\
|
||||
result_of_has_result_type_impl \\
|
||||
conditional \\
|
||||
boost::operators_impl"
|
||||
<xsl:param>"boost.doxygen.reftitle=Reference"
|
||||
<xsl:param>"boost.doxygen.refid=base_from_member.reference"
|
||||
;
|
||||
|
||||
# Generate XML doxygen reference for boost_binary component in boost_binary_reference.xml
|
||||
doxygen boost_binary_reference
|
||||
:
|
||||
$(INCLUDES)/boost/utility/binary.hpp
|
||||
:
|
||||
<location>tmp
|
||||
<doxygen:param>ENABLE_PREPROCESSING=YES
|
||||
<doxygen:param>EXPAND_ONLY_PREDEF=YES
|
||||
<doxygen:param>EXTRACT_ALL=NO
|
||||
<doxygen:param>EXTRACT_PRIVATE=NO
|
||||
<doxygen:param>HIDE_UNDOC_MEMBERS=YES
|
||||
<doxygen:param>MACRO_EXPANSION=YES
|
||||
<doxygen:param>"PREDEFINED= \\
|
||||
BOOST_UTILITY_DOCS \\
|
||||
BOOST_SYMBOL_VISIBLE= \\
|
||||
BOOST_FORCEINLINE=inline \\
|
||||
BOOST_GPU_ENABLED= \\
|
||||
BOOST_STATIC_ASSERT(x)= \\
|
||||
BOOST_STATIC_ASSERT_MSG(x,y)= \\
|
||||
BOOST_STATIC_CONSTANT(x,y)=\"static constexpr x y\" \\
|
||||
BOOST_RV_REF(x)=\"x&&\" \\
|
||||
BOOST_NESTED_TEMPLATE=template \\
|
||||
BOOST_CONSTEXPR=constexpr \\
|
||||
BOOST_CXX14_CONSTEXPR=constexpr \\
|
||||
BOOST_OPERATORS_CONSTEXPR=constexpr \\
|
||||
BOOST_CONSTEXPR_OR_CONST=constexpr \\
|
||||
BOOST_NOEXCEPT=noexcept \\
|
||||
BOOST_NOEXCEPT_IF(x)=noexcept(x) \\
|
||||
BOOST_NOEXCEPT_OR_NOTHROW=noexcept \\
|
||||
BOOST_COPY_ASSIGN_REF(x)=\"x const&\" \\
|
||||
BOOST_DEFAULTED_FUNCTION(x,y)=\"x = default;\" \\
|
||||
BOOST_DELETED_FUNCTION(x)=\"x = delete;\" \\
|
||||
BOOST_EXPLICIT_OPERATOR_BOOL()=\"explicit operator bool() const;\" \\
|
||||
BOOST_REF_CONST=const"
|
||||
<doxygen:param>"EXCLUDE_SYMBOLS= \\
|
||||
detail \\
|
||||
F \\
|
||||
result_of_has_result_type_impl \\
|
||||
conditional \\
|
||||
boost::operators_impl"
|
||||
<xsl:param>"boost.doxygen.reftitle=Reference"
|
||||
<xsl:param>"boost.doxygen.refid=boost_binary.reference"
|
||||
;
|
||||
|
||||
# Generate XML doxygen reference for call_traits component in call_traits_reference.xml
|
||||
doxygen call_traits_reference
|
||||
:
|
||||
$(INCLUDES)/boost/call_traits.hpp
|
||||
$(INCLUDES)/boost/detail/call_traits.hpp
|
||||
:
|
||||
<location>tmp
|
||||
<doxygen:param>ENABLE_PREPROCESSING=YES
|
||||
<doxygen:param>EXPAND_ONLY_PREDEF=YES
|
||||
<doxygen:param>EXTRACT_ALL=NO
|
||||
<doxygen:param>EXTRACT_PRIVATE=NO
|
||||
<doxygen:param>HIDE_UNDOC_MEMBERS=YES
|
||||
<doxygen:param>MACRO_EXPANSION=YES
|
||||
<doxygen:param>"PREDEFINED= \\
|
||||
BOOST_UTILITY_DOCS \\
|
||||
BOOST_SYMBOL_VISIBLE= \\
|
||||
BOOST_FORCEINLINE=inline \\
|
||||
BOOST_GPU_ENABLED= \\
|
||||
BOOST_STATIC_ASSERT(x)= \\
|
||||
BOOST_STATIC_ASSERT_MSG(x,y)= \\
|
||||
BOOST_STATIC_CONSTANT(x,y)=\"static constexpr x y\" \\
|
||||
BOOST_RV_REF(x)=\"x&&\" \\
|
||||
BOOST_NESTED_TEMPLATE=template \\
|
||||
BOOST_CONSTEXPR=constexpr \\
|
||||
BOOST_CXX14_CONSTEXPR=constexpr \\
|
||||
BOOST_OPERATORS_CONSTEXPR=constexpr \\
|
||||
BOOST_CONSTEXPR_OR_CONST=constexpr \\
|
||||
BOOST_NOEXCEPT=noexcept \\
|
||||
BOOST_NOEXCEPT_IF(x)=noexcept(x) \\
|
||||
BOOST_NOEXCEPT_OR_NOTHROW=noexcept \\
|
||||
BOOST_COPY_ASSIGN_REF(x)=\"x const&\" \\
|
||||
BOOST_DEFAULTED_FUNCTION(x,y)=\"x = default;\" \\
|
||||
BOOST_DELETED_FUNCTION(x)=\"x = delete;\" \\
|
||||
BOOST_EXPLICIT_OPERATOR_BOOL()=\"explicit operator bool() const;\" \\
|
||||
BOOST_REF_CONST=const"
|
||||
<doxygen:param>"EXCLUDE_SYMBOLS= \\
|
||||
detail \\
|
||||
F \\
|
||||
result_of_has_result_type_impl \\
|
||||
conditional \\
|
||||
boost::operators_impl"
|
||||
<xsl:param>"boost.doxygen.reftitle=Reference"
|
||||
<xsl:param>"boost.doxygen.refid=call_traits.reference"
|
||||
;
|
||||
|
||||
# Generate XML doxygen reference for compressed_pair component in compressed_pair_reference.xml
|
||||
doxygen compressed_pair_reference
|
||||
:
|
||||
$(INCLUDES)/boost/compressed_pair.hpp
|
||||
$(INCLUDES)/boost/detail/compressed_pair.hpp
|
||||
:
|
||||
<location>tmp
|
||||
<doxygen:param>ENABLE_PREPROCESSING=YES
|
||||
<doxygen:param>EXPAND_ONLY_PREDEF=YES
|
||||
<doxygen:param>EXTRACT_ALL=NO
|
||||
<doxygen:param>EXTRACT_PRIVATE=NO
|
||||
<doxygen:param>HIDE_UNDOC_MEMBERS=YES
|
||||
<doxygen:param>MACRO_EXPANSION=YES
|
||||
<doxygen:param>"PREDEFINED= \\
|
||||
BOOST_UTILITY_DOCS \\
|
||||
BOOST_SYMBOL_VISIBLE= \\
|
||||
BOOST_FORCEINLINE=inline \\
|
||||
BOOST_GPU_ENABLED= \\
|
||||
BOOST_STATIC_ASSERT(x)= \\
|
||||
BOOST_STATIC_ASSERT_MSG(x,y)= \\
|
||||
BOOST_STATIC_CONSTANT(x,y)=\"static constexpr x y\" \\
|
||||
BOOST_RV_REF(x)=\"x&&\" \\
|
||||
BOOST_NESTED_TEMPLATE=template \\
|
||||
BOOST_CONSTEXPR=constexpr \\
|
||||
BOOST_CXX14_CONSTEXPR=constexpr \\
|
||||
BOOST_OPERATORS_CONSTEXPR=constexpr \\
|
||||
BOOST_CONSTEXPR_OR_CONST=constexpr \\
|
||||
BOOST_NOEXCEPT=noexcept \\
|
||||
BOOST_NOEXCEPT_IF(x)=noexcept(x) \\
|
||||
BOOST_NOEXCEPT_OR_NOTHROW=noexcept \\
|
||||
BOOST_COPY_ASSIGN_REF(x)=\"x const&\" \\
|
||||
BOOST_DEFAULTED_FUNCTION(x,y)=\"x = default;\" \\
|
||||
BOOST_DELETED_FUNCTION(x)=\"x = delete;\" \\
|
||||
BOOST_EXPLICIT_OPERATOR_BOOL()=\"explicit operator bool() const;\" \\
|
||||
BOOST_REF_CONST=const"
|
||||
<doxygen:param>"EXCLUDE_SYMBOLS= \\
|
||||
detail \\
|
||||
F \\
|
||||
result_of_has_result_type_impl \\
|
||||
conditional \\
|
||||
boost::operators_impl"
|
||||
<xsl:param>"boost.doxygen.reftitle=Reference"
|
||||
<xsl:param>"boost.doxygen.refid=compressed_pair.reference"
|
||||
;
|
||||
|
||||
# Generate XML doxygen reference for in_place_factory component in in_place_factory_reference.xml
|
||||
doxygen in_place_factory_reference
|
||||
:
|
||||
$(INCLUDES)/boost/utility/in_place_factory.hpp
|
||||
$(INCLUDES)/boost/utility/typed_in_place_factory.hpp
|
||||
:
|
||||
<location>tmp
|
||||
<doxygen:param>ENABLE_PREPROCESSING=YES
|
||||
<doxygen:param>EXPAND_ONLY_PREDEF=YES
|
||||
<doxygen:param>EXTRACT_ALL=NO
|
||||
<doxygen:param>EXTRACT_PRIVATE=NO
|
||||
<doxygen:param>HIDE_UNDOC_MEMBERS=YES
|
||||
<doxygen:param>MACRO_EXPANSION=YES
|
||||
<doxygen:param>"PREDEFINED= \\
|
||||
BOOST_UTILITY_DOCS \\
|
||||
BOOST_SYMBOL_VISIBLE= \\
|
||||
BOOST_FORCEINLINE=inline \\
|
||||
BOOST_GPU_ENABLED= \\
|
||||
BOOST_STATIC_ASSERT(x)= \\
|
||||
BOOST_STATIC_ASSERT_MSG(x,y)= \\
|
||||
BOOST_STATIC_CONSTANT(x,y)=\"static constexpr x y\" \\
|
||||
BOOST_RV_REF(x)=\"x&&\" \\
|
||||
BOOST_NESTED_TEMPLATE=template \\
|
||||
BOOST_CONSTEXPR=constexpr \\
|
||||
BOOST_CXX14_CONSTEXPR=constexpr \\
|
||||
BOOST_OPERATORS_CONSTEXPR=constexpr \\
|
||||
BOOST_CONSTEXPR_OR_CONST=constexpr \\
|
||||
BOOST_NOEXCEPT=noexcept \\
|
||||
BOOST_NOEXCEPT_IF(x)=noexcept(x) \\
|
||||
BOOST_NOEXCEPT_OR_NOTHROW=noexcept \\
|
||||
BOOST_COPY_ASSIGN_REF(x)=\"x const&\" \\
|
||||
BOOST_DEFAULTED_FUNCTION(x,y)=\"x = default;\" \\
|
||||
BOOST_DELETED_FUNCTION(x)=\"x = delete;\" \\
|
||||
BOOST_EXPLICIT_OPERATOR_BOOL()=\"explicit operator bool() const;\" \\
|
||||
BOOST_REF_CONST=const"
|
||||
<doxygen:param>"EXCLUDE_SYMBOLS= \\
|
||||
detail \\
|
||||
F \\
|
||||
result_of_has_result_type_impl \\
|
||||
conditional \\
|
||||
boost::operators_impl"
|
||||
<xsl:param>"boost.doxygen.reftitle=Reference"
|
||||
<xsl:param>"boost.doxygen.refid=in_place_factory.reference"
|
||||
;
|
||||
|
||||
# Generate XML doxygen reference for operators component in operators_reference.xml
|
||||
# we skip operators_reference because operators.hpp is not adapted for doxygen
|
||||
|
||||
# Generate XML doxygen reference for result_of component in result_of_reference.xml
|
||||
doxygen result_of_reference
|
||||
:
|
||||
$(INCLUDES)/boost/utility/result_of.hpp
|
||||
:
|
||||
<location>tmp
|
||||
<doxygen:param>ENABLE_PREPROCESSING=YES
|
||||
<doxygen:param>EXPAND_ONLY_PREDEF=YES
|
||||
<doxygen:param>EXTRACT_ALL=NO
|
||||
<doxygen:param>EXTRACT_PRIVATE=NO
|
||||
<doxygen:param>HIDE_UNDOC_MEMBERS=YES
|
||||
<doxygen:param>MACRO_EXPANSION=YES
|
||||
<doxygen:param>"PREDEFINED= \\
|
||||
BOOST_UTILITY_DOCS \\
|
||||
BOOST_SYMBOL_VISIBLE= \\
|
||||
BOOST_FORCEINLINE=inline \\
|
||||
BOOST_GPU_ENABLED= \\
|
||||
BOOST_STATIC_ASSERT(x)= \\
|
||||
BOOST_STATIC_ASSERT_MSG(x,y)= \\
|
||||
BOOST_STATIC_CONSTANT(x,y)=\"static constexpr x y\" \\
|
||||
BOOST_RV_REF(x)=\"x&&\" \\
|
||||
BOOST_NESTED_TEMPLATE=template \\
|
||||
BOOST_CONSTEXPR=constexpr \\
|
||||
BOOST_CXX14_CONSTEXPR=constexpr \\
|
||||
BOOST_OPERATORS_CONSTEXPR=constexpr \\
|
||||
BOOST_CONSTEXPR_OR_CONST=constexpr \\
|
||||
BOOST_NOEXCEPT=noexcept \\
|
||||
BOOST_NOEXCEPT_IF(x)=noexcept(x) \\
|
||||
BOOST_NOEXCEPT_OR_NOTHROW=noexcept \\
|
||||
BOOST_COPY_ASSIGN_REF(x)=\"x const&\" \\
|
||||
BOOST_DEFAULTED_FUNCTION(x,y)=\"x = default;\" \\
|
||||
BOOST_DELETED_FUNCTION(x)=\"x = delete;\" \\
|
||||
BOOST_EXPLICIT_OPERATOR_BOOL()=\"explicit operator bool() const;\" \\
|
||||
BOOST_REF_CONST=const"
|
||||
<doxygen:param>"EXCLUDE_SYMBOLS= \\
|
||||
detail \\
|
||||
F \\
|
||||
result_of_has_result_type_impl \\
|
||||
conditional \\
|
||||
boost::operators_impl"
|
||||
<xsl:param>"boost.doxygen.reftitle=Reference"
|
||||
<xsl:param>"boost.doxygen.refid=result_of.reference"
|
||||
;
|
||||
|
||||
# Generate XML doxygen reference for string_view component in string_view_reference.xml
|
||||
doxygen string_view_reference
|
||||
:
|
||||
$(INCLUDES)/boost/utility/string_view.hpp
|
||||
:
|
||||
<location>tmp
|
||||
<doxygen:param>ENABLE_PREPROCESSING=YES
|
||||
<doxygen:param>EXPAND_ONLY_PREDEF=YES
|
||||
<doxygen:param>EXTRACT_ALL=NO
|
||||
<doxygen:param>EXTRACT_PRIVATE=NO
|
||||
<doxygen:param>HIDE_UNDOC_MEMBERS=YES
|
||||
<doxygen:param>MACRO_EXPANSION=YES
|
||||
<doxygen:param>"PREDEFINED= \\
|
||||
BOOST_UTILITY_DOCS \\
|
||||
BOOST_SYMBOL_VISIBLE= \\
|
||||
BOOST_FORCEINLINE=inline \\
|
||||
BOOST_GPU_ENABLED= \\
|
||||
BOOST_STATIC_ASSERT(x)= \\
|
||||
BOOST_STATIC_ASSERT_MSG(x,y)= \\
|
||||
BOOST_STATIC_CONSTANT(x,y)=\"static constexpr x y\" \\
|
||||
BOOST_RV_REF(x)=\"x&&\" \\
|
||||
BOOST_NESTED_TEMPLATE=template \\
|
||||
BOOST_CONSTEXPR=constexpr \\
|
||||
BOOST_CXX14_CONSTEXPR=constexpr \\
|
||||
BOOST_OPERATORS_CONSTEXPR=constexpr \\
|
||||
BOOST_CONSTEXPR_OR_CONST=constexpr \\
|
||||
BOOST_NOEXCEPT=noexcept \\
|
||||
BOOST_NOEXCEPT_IF(x)=noexcept(x) \\
|
||||
BOOST_NOEXCEPT_OR_NOTHROW=noexcept \\
|
||||
BOOST_COPY_ASSIGN_REF(x)=\"x const&\" \\
|
||||
BOOST_DEFAULTED_FUNCTION(x,y)=\"x = default;\" \\
|
||||
BOOST_DELETED_FUNCTION(x)=\"x = delete;\" \\
|
||||
BOOST_EXPLICIT_OPERATOR_BOOL()=\"explicit operator bool() const;\" \\
|
||||
BOOST_REF_CONST=const"
|
||||
<doxygen:param>"EXCLUDE_SYMBOLS= \\
|
||||
detail \\
|
||||
F \\
|
||||
result_of_has_result_type_impl \\
|
||||
conditional \\
|
||||
boost::operators_impl"
|
||||
<xsl:param>"boost.doxygen.reftitle=Reference"
|
||||
<xsl:param>"boost.doxygen.refid=string_view.reference"
|
||||
;
|
||||
|
||||
# Generate XML doxygen reference for value_init component in value_init_reference.xml
|
||||
doxygen value_init_reference
|
||||
:
|
||||
$(INCLUDES)/boost/utility/value_init.hpp
|
||||
:
|
||||
<location>tmp
|
||||
<doxygen:param>ENABLE_PREPROCESSING=YES
|
||||
<doxygen:param>EXPAND_ONLY_PREDEF=YES
|
||||
<doxygen:param>EXTRACT_ALL=NO
|
||||
<doxygen:param>EXTRACT_PRIVATE=NO
|
||||
<doxygen:param>HIDE_UNDOC_MEMBERS=YES
|
||||
<doxygen:param>MACRO_EXPANSION=YES
|
||||
<doxygen:param>"PREDEFINED= \\
|
||||
BOOST_UTILITY_DOCS \\
|
||||
BOOST_SYMBOL_VISIBLE= \\
|
||||
BOOST_FORCEINLINE=inline \\
|
||||
BOOST_GPU_ENABLED= \\
|
||||
BOOST_STATIC_ASSERT(x)= \\
|
||||
BOOST_STATIC_ASSERT_MSG(x,y)= \\
|
||||
BOOST_STATIC_CONSTANT(x,y)=\"static constexpr x y\" \\
|
||||
BOOST_RV_REF(x)=\"x&&\" \\
|
||||
BOOST_NESTED_TEMPLATE=template \\
|
||||
BOOST_CONSTEXPR=constexpr \\
|
||||
BOOST_CXX14_CONSTEXPR=constexpr \\
|
||||
BOOST_OPERATORS_CONSTEXPR=constexpr \\
|
||||
BOOST_CONSTEXPR_OR_CONST=constexpr \\
|
||||
BOOST_NOEXCEPT=noexcept \\
|
||||
BOOST_NOEXCEPT_IF(x)=noexcept(x) \\
|
||||
BOOST_NOEXCEPT_OR_NOTHROW=noexcept \\
|
||||
BOOST_COPY_ASSIGN_REF(x)=\"x const&\" \\
|
||||
BOOST_DEFAULTED_FUNCTION(x,y)=\"x = default;\" \\
|
||||
BOOST_DELETED_FUNCTION(x)=\"x = delete;\" \\
|
||||
BOOST_EXPLICIT_OPERATOR_BOOL()=\"explicit operator bool() const;\" \\
|
||||
BOOST_REF_CONST=const"
|
||||
<doxygen:param>"EXCLUDE_SYMBOLS= \\
|
||||
detail \\
|
||||
F \\
|
||||
result_of_has_result_type_impl \\
|
||||
conditional \\
|
||||
boost::operators_impl"
|
||||
<xsl:param>"boost.doxygen.reftitle=Reference"
|
||||
<xsl:param>"boost.doxygen.refid=value_init.reference"
|
||||
;
|
||||
|
||||
# Generate main.xml boostbook documentation from main.qbk quickbook documentation
|
||||
xml main : main.qbk ;
|
||||
|
||||
# Generate ./html documentation from main.xml boostbook documentation
|
||||
# Each doxygen reference in quickbook files with [xinclude tmp/<component>_reference.xml] becomes:
|
||||
# <xi:include href="../../../../libs/utility/doc/tmp/<component>_reference.xml"/>
|
||||
# in boostbook.
|
||||
# All of these <xi:include> commands give the reference the id "utility.reference"
|
||||
boostbook standalone_main
|
||||
:
|
||||
main
|
||||
:
|
||||
<dependency>base_from_member_reference
|
||||
<dependency>boost_binary_reference
|
||||
<dependency>call_traits_reference
|
||||
<dependency>compressed_pair_reference
|
||||
<dependency>in_place_factory_reference
|
||||
<dependency>result_of_reference
|
||||
<dependency>string_view_reference
|
||||
<dependency>value_init_reference
|
||||
# File name of HTML output:
|
||||
# <xsl:param>root.filename=main
|
||||
<xsl:param>boost.root=../../../..
|
||||
<format>pdf:<xsl:param>"boost.url.prefix=http://www.boost.org/doc/libs/release/libs/utility/doc/html"
|
||||
# How far down we chunk nested sections: no more than two so utility component pages include their reference
|
||||
<xsl:param>chunk.section.depth=2 # 8
|
||||
# Don't put the first section on the same page as the TOC:
|
||||
<xsl:param>chunk.first.sections=1 # 1
|
||||
# How far down sections get TOC: 2 so we show each Utility component in main page but no more than that
|
||||
<xsl:param>toc.section.depth=2 # 2
|
||||
# Max depth in each TOC: 2 so we show each Utility component in main page but no more than that
|
||||
<xsl:param>toc.max.depth=2 # 2
|
||||
# How far down we go with TOC's in main page: 2 so each Utility component page has 1 level TOC
|
||||
<xsl:param>generate.section.toc.level=2 # 2
|
||||
;
|
||||
|
||||
###############################################################################
|
||||
alias boostdoc ;
|
||||
explicit boostdoc ;
|
||||
|
||||
alias boostrelease : standalone_main ;
|
||||
explicit boostrelease ;
|
376
doc/base_from_member.qbk
Normal file
376
doc/base_from_member.qbk
Normal file
@ -0,0 +1,376 @@
|
||||
[/
|
||||
Copyright 2001, 2003, 2004, 2012 Daryle Walker.
|
||||
Copyright (c) 2021, Alan Freitas
|
||||
|
||||
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
|
||||
]
|
||||
|
||||
[section:base_from_member Base from Member]
|
||||
[block'''<?dbhtml stop-chunking?>''']
|
||||
|
||||
[section Introduction]
|
||||
|
||||
The class templates __base_from_member__ support the base-from-member idiom.
|
||||
When developing a class, sometimes a base class needs to be initialized
|
||||
with a member of the current class. As a na\u00EFve example:
|
||||
|
||||
```
|
||||
#include <streambuf> /* for std::streambuf */
|
||||
#include <ostream> /* for std::ostream */
|
||||
|
||||
class fdoutbuf
|
||||
: public __std_streambuf__
|
||||
{
|
||||
public:
|
||||
explicit fdoutbuf( int fd );
|
||||
//...
|
||||
};
|
||||
|
||||
class fdostream
|
||||
: public __std_ostream__
|
||||
{
|
||||
protected:
|
||||
fdoutbuf buf;
|
||||
public:
|
||||
explicit fdostream( int fd )
|
||||
: buf( fd ), __std_ostream__( &buf ) {}
|
||||
//...
|
||||
};
|
||||
```
|
||||
|
||||
This is undefined because C++'s initialization order mandates that the base
|
||||
class is initialized before the member it uses. [@http://www.moocat.org R.
|
||||
Samuel Klatchko] developed a way around this by using the initialization
|
||||
order in his favor. Base classes are initialized in order of declaration, so
|
||||
moving the desired member to another base class, that is initialized before
|
||||
the desired base class, can ensure proper initialization.
|
||||
|
||||
A custom base class can be made for this idiom:
|
||||
|
||||
#include <streambuf> /* for std::streambuf */
|
||||
#include <ostream> /* for std::ostream */
|
||||
|
||||
class fdoutbuf
|
||||
: public __std_streambuf__
|
||||
{
|
||||
public:
|
||||
explicit fdoutbuf( int fd );
|
||||
//...
|
||||
};
|
||||
|
||||
struct fdostream_pbase
|
||||
{
|
||||
fdoutbuf sbuffer;
|
||||
|
||||
explicit fdostream_pbase( int fd )
|
||||
: sbuffer( fd ) {}
|
||||
};
|
||||
|
||||
class fdostream
|
||||
: private fdostream_pbase
|
||||
, public __std_ostream__
|
||||
{
|
||||
typedef fdostream_pbase pbase_type;
|
||||
typedef __std_ostream__ base_type;
|
||||
|
||||
public:
|
||||
explicit fdostream( int fd )
|
||||
: pbase_type( fd ), base_type( &sbuffer ) {}
|
||||
//...
|
||||
};
|
||||
|
||||
Other projects can use similar custom base classes. The technique is basic
|
||||
enough to make a template, with a sample template class in this library.
|
||||
The main template parameter is the type of the enclosed member. The
|
||||
template class has several (explicit) constructor member templates, which
|
||||
implicitly type the constructor arguments and pass them to the member. The
|
||||
template class uses implicit copy construction and assignment, cancelling
|
||||
them if the enclosed member is non-copyable.
|
||||
|
||||
Manually coding a base class may be better if the construction and/or
|
||||
copying needs are too complex for the supplied template class, or if the
|
||||
compiler is not advanced enough to use it.
|
||||
|
||||
Since base classes are unnamed, a class cannot have multiple (direct) base
|
||||
classes of the same type. The supplied template class has an extra template
|
||||
parameter, an integer, that exists solely to provide type differentiation.
|
||||
This parameter has a default value so a single use of a particular member
|
||||
type does not need to concern itself with the integer.
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Synopsis]
|
||||
|
||||
#include <type_traits> /* exposition only */
|
||||
|
||||
#ifndef BOOST_BASE_FROM_MEMBER_MAX_ARITY
|
||||
#define BOOST_BASE_FROM_MEMBER_MAX_ARITY 10
|
||||
#endif
|
||||
|
||||
template < typename MemberType, int UniqueID = 0 >
|
||||
class __base_from_member__
|
||||
{
|
||||
protected:
|
||||
MemberType member;
|
||||
|
||||
#if ``['C++11 is in use]``
|
||||
template< typename ...T >
|
||||
explicit constexpr __base_from_member__( T&& ...x )
|
||||
noexcept( __std_is_nothrow_constructible__<MemberType, T...>::value );
|
||||
#else
|
||||
__base_from_member__();
|
||||
|
||||
template< typename T1 >
|
||||
explicit __base_from_member__( T1 x1 );
|
||||
|
||||
template< typename T1, typename T2 >
|
||||
__base_from_member__( T1 x1, T2 x2 );
|
||||
|
||||
//...
|
||||
|
||||
template< typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6, typename T7, typename T8, typename T9,
|
||||
typename T10 >
|
||||
__base_from_member__( T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, T6 x6, T7 x7,
|
||||
T8 x8, T9 x9, T10 x10 );
|
||||
#endif
|
||||
};
|
||||
|
||||
template < typename MemberType, int UniqueID >
|
||||
class __base_from_member__<MemberType&, UniqueID>
|
||||
{
|
||||
protected:
|
||||
MemberType& member;
|
||||
|
||||
explicit constexpr __base_from_member__( MemberType& x )
|
||||
noexcept;
|
||||
};
|
||||
|
||||
The class template has a first template parameter `MemberType` representing
|
||||
the type of the based-member. It has a last template parameter `UniqueID`,
|
||||
that is an `int`, to differentiate between multiple base classes that use
|
||||
the same based-member type. The last template parameter has a default value
|
||||
of zero if it is omitted. The class template has a protected data member
|
||||
called `member` that the derived class can use for later base classes or
|
||||
itself.
|
||||
|
||||
If the appropriate features of C++11 are present, there will be a single
|
||||
constructor template. It implements ['perfect forwarding] to the best
|
||||
constructor call of `member` if any. The constructor template is marked
|
||||
both `constexpr` and `explicit`. The former will be ignored if the
|
||||
corresponding inner constructor call of `member` does not have the marker.
|
||||
The latter binds the other way; always taking effect, even when the inner
|
||||
constructor call does not have the marker. The constructor template
|
||||
propagates the `noexcept` status of the inner constructor call. The
|
||||
constructor template has a trailing parameter with a default value that
|
||||
disables the template when its signature is too close to the signatures of
|
||||
the automatically-defined non-template copy- and/or move-constructors of
|
||||
__base_from_member__.
|
||||
|
||||
On earlier-standard compilers, there is a default constructor and several
|
||||
constructor member templates. These constructor templates can take as many
|
||||
arguments (currently up to ten) as possible and pass them to a constructor
|
||||
of the data member.
|
||||
|
||||
A specialization for member references offers a single constructor taking
|
||||
a `MemberType&`, which is the only way to initialize a reference.
|
||||
|
||||
Since C++ does not allow any way to explicitly state the template parameters
|
||||
of a templated constructor, make sure that the arguments are already close
|
||||
as possible to the actual type used in the data member's desired constructor.
|
||||
Explicit conversions may be necessary.
|
||||
|
||||
The `BOOST_BASE_FROM_MEMBER_MAX_ARITY` macro constant specifies the maximum
|
||||
argument length for the constructor templates. The constant may be overridden
|
||||
if more (or less) argument configurations are needed. The constant may be
|
||||
read for code that is expandable like the class template and needs to
|
||||
maintain the same maximum size. (Example code would be a class that uses
|
||||
this class template as a base class for a member with a flexible set of
|
||||
constructors.) This constant is ignored when C++11 features are present.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Basic Usage]
|
||||
|
||||
With the starting example, the `fdoutbuf` sub-object needs to be
|
||||
encapsulated in a base class that is inherited before `__std_ostream__`.
|
||||
|
||||
```
|
||||
#include <boost/utility/base_from_member.hpp>
|
||||
|
||||
#include <streambuf> // for std::streambuf
|
||||
#include <ostream> // for __std_ostream__
|
||||
|
||||
class fdoutbuf
|
||||
: public __std_streambuf__
|
||||
{
|
||||
public:
|
||||
explicit fdoutbuf( int fd );
|
||||
//...
|
||||
};
|
||||
|
||||
class fdostream
|
||||
: private __boost_base_from_member__<fdoutbuf>
|
||||
, public __std_ostream__
|
||||
{
|
||||
// Helper typedef's
|
||||
typedef __boost_base_from_member__<fdoutbuf> pbase_type;
|
||||
typedef __std_ostream__ base_type;
|
||||
|
||||
public:
|
||||
explicit fdostream( int fd )
|
||||
: pbase_type( fd ), base_type( &member ){}
|
||||
//...
|
||||
};
|
||||
```
|
||||
|
||||
The base-from-member idiom is an implementation detail, so it should not
|
||||
be visible to the clients (or any derived classes) of `fdostream`. Due to
|
||||
the initialization order, the `fdoutbuf` sub-object will get initialized
|
||||
before the `__std_ostream__` sub-object does, making the former sub-object
|
||||
safe to use in the latter sub-object's construction. Since the `fdoutbuf`
|
||||
sub-object of the final type is the only sub-object with the name `member`
|
||||
that name can be used unqualified within the final class.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Multiple Sub-Objects]
|
||||
|
||||
The base-from-member class templates should commonly involve only one
|
||||
base-from-member sub-object, usually for attaching a stream-buffer to an
|
||||
I/O stream. The next example demonstrates how to use multiple
|
||||
base-from-member sub-objects and the resulting qualification issues.
|
||||
|
||||
```
|
||||
#include <boost/utility/base_from_member.hpp>
|
||||
|
||||
#include <cstddef> /* for NULL */
|
||||
|
||||
struct an_int
|
||||
{
|
||||
int y;
|
||||
|
||||
an_int( float yf );
|
||||
};
|
||||
|
||||
class switcher
|
||||
{
|
||||
public:
|
||||
switcher();
|
||||
switcher( double, int * );
|
||||
//...
|
||||
};
|
||||
|
||||
class flow_regulator
|
||||
{
|
||||
public:
|
||||
flow_regulator( switcher &, switcher & );
|
||||
//...
|
||||
};
|
||||
|
||||
template < unsigned Size >
|
||||
class fan
|
||||
{
|
||||
public:
|
||||
explicit fan( switcher );
|
||||
//...
|
||||
};
|
||||
|
||||
class system
|
||||
: private __boost_base_from_member__<an_int>
|
||||
, private __boost_base_from_member__<switcher>
|
||||
, private __boost_base_from_member__<switcher, 1>
|
||||
, private __boost_base_from_member__<switcher, 2>
|
||||
, protected flow_regulator
|
||||
, public fan<6>
|
||||
{
|
||||
// Helper typedef's
|
||||
typedef __boost_base_from_member__<an_int> pbase0_type;
|
||||
typedef __boost_base_from_member__<switcher> pbase1_type;
|
||||
typedef __boost_base_from_member__<switcher, 1> pbase2_type;
|
||||
typedef __boost_base_from_member__<switcher, 2> pbase3_type;
|
||||
|
||||
typedef flow_regulator base1_type;
|
||||
typedef fan<6> base2_type;
|
||||
|
||||
public:
|
||||
system( double x );
|
||||
//...
|
||||
};
|
||||
|
||||
system::system( double x )
|
||||
: pbase0_type( 0.2 )
|
||||
, pbase1_type()
|
||||
, pbase2_type( -16, &this->pbase0_type::member.y )
|
||||
, pbase3_type( x, static_cast<int *>(NULL) )
|
||||
, base1_type( pbase3_type::member, pbase1_type::member )
|
||||
, base2_type( pbase2_type::member )
|
||||
{
|
||||
//...
|
||||
}
|
||||
```
|
||||
|
||||
The final class has multiple sub-objects with the name `member`, so any
|
||||
use of that name needs qualification by a name of the appropriate base
|
||||
type. Using `typedef`s ease mentioning the base types.
|
||||
|
||||
However, the fix introduces a new problem when a pointer is needed. Using the
|
||||
address operator with a sub-object qualified with its class's name results in a
|
||||
pointer-to-member (here, having a type of `an_int __boost_base_from_member__<an_int, 0>::*`)
|
||||
instead of a pointer to the member (having a type of `an_int*`).
|
||||
The new problem is fixed by qualifying the sub-object with `this->` and is needed
|
||||
just for pointers, and not for references or values.
|
||||
|
||||
There are some argument conversions in the initialization. The constructor
|
||||
argument for `pbase0_type` is converted from `double` to `float`. The first
|
||||
constructor argument for `pbase2_type` is converted from `int` to `double`.
|
||||
|
||||
The second constructor argument for `pbase3_type` is a special case of
|
||||
necessary conversion; all forms of the null-pointer literal in C++ (except
|
||||
`nullptr` from C++11) also look like compile-time integral expressions, so
|
||||
C++ always interprets such code as an integer when it has overloads that can
|
||||
take either an integer or a pointer.
|
||||
|
||||
The last conversion is necessary for the compiler to call a constructor form
|
||||
with the exact pointer type used in `switcher`'s constructor. (If C++11's
|
||||
__nullptr__ is used, it still needs a conversion if multiple pointer types can
|
||||
be accepted in a constructor call but `__std_nullptr_t__` cannot.)
|
||||
|
||||
[endsect]
|
||||
|
||||
[/===============]
|
||||
[xinclude tmp/base_from_member_reference.xml]
|
||||
[/===============]
|
||||
|
||||
[section Acknowledgments]
|
||||
|
||||
Author: Walker, Daryle
|
||||
|
||||
Copyright 2001, 2003, 2004, 2012 Daryle Walker
|
||||
|
||||
* [@http://www.boost.org/people/ed_brey.htm Ed Brey] suggested some interface
|
||||
changes.
|
||||
|
||||
* [@http://www.moocat.org R. Samuel Klatchko] ([@mailto:rsk@moocat.org
|
||||
rsk@moocat.org], [@mailto:rsk@brightmail.com rsk@brightmail.com]) invented
|
||||
the idiom of how to use a class member for initializing a base class.
|
||||
|
||||
* [@http://www.boost.org/people/dietmar_kuehl.htm Dietmar Kuehl] popularized the
|
||||
base-from-member idiom in his [@http://www.informatik.uni-konstanz.de/~kuehl/c++/iostream/
|
||||
IOStream example classes].
|
||||
|
||||
* Jonathan Turkanis supplied an implementation of generating the constructor
|
||||
templates that can be controlled and automated with macros. The
|
||||
implementation uses the [@boost:/libs/preprocessor/index.html Preprocessor library].
|
||||
|
||||
* [@http://www.boost.org/people/daryle_walker.html">Daryle Walker] started the
|
||||
library. Contributed the test file [@../../../test/base_from_member_test.cpp
|
||||
base_from_member_test.cpp].
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
443
doc/call_traits.qbk
Normal file
443
doc/call_traits.qbk
Normal file
@ -0,0 +1,443 @@
|
||||
[/
|
||||
/ Copyright (c) 2012 Marshall Clow
|
||||
/ Copyright (c) 2021, Alan Freitas
|
||||
/
|
||||
/ 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 Call Traits]
|
||||
[/===============]
|
||||
|
||||
[section Introduction]
|
||||
|
||||
All of the contents of [@../../../../boost/call_traits.hpp `<boost/call_traits.hpp>`] are
|
||||
defined inside `namespace boost`.
|
||||
|
||||
The template class __call_traits_T__ encapsulates the
|
||||
"best" method to pass a parameter of some type `T` to or
|
||||
from a function, and consists of a collection of `typedef`s defined
|
||||
as in the table below. The purpose of __call_traits__ is to ensure
|
||||
that problems like [link sec:refs "references to references"]
|
||||
never occur, and that parameters are passed in the most efficient
|
||||
manner possible, as in the [link sec:examples examples]. In each
|
||||
case, if your existing practice is to use the type defined on the
|
||||
left, then replace it with the __call_traits__ defined type on the
|
||||
right.
|
||||
|
||||
Note that for compilers that do not support either partial
|
||||
specialization or member templates, no benefit will occur from
|
||||
using __call_traits__: the __call_traits__ defined types will always be
|
||||
the same as the existing practice in this case. In addition if
|
||||
only member templates and not partial template specialisation is
|
||||
support by the compiler (for example Visual C++ 6) then
|
||||
__call_traits__ cannot be used with array types, although it can still be
|
||||
used to solve the reference to reference problem.
|
||||
|
||||
[table __call_traits__ types
|
||||
[[Existing practice] [__call_traits__ equivalent] [Description] [Notes]]
|
||||
[
|
||||
[`T`
|
||||
|
||||
(return by value)
|
||||
]
|
||||
[
|
||||
__call_traits_T__`::value_type`
|
||||
]
|
||||
[
|
||||
Defines a type that represents the "value" of type `T`.
|
||||
|
||||
Use this for functions that return by value, or possibly for stored values of type `T`.
|
||||
]
|
||||
[2]
|
||||
]
|
||||
[
|
||||
[`T&`
|
||||
|
||||
(return value)
|
||||
]
|
||||
[
|
||||
__call_traits_T__`::reference`
|
||||
]
|
||||
[
|
||||
Defines a type that represents a reference to type `T`.
|
||||
|
||||
Use for functions that would normally return a `T&`.
|
||||
]
|
||||
[1]
|
||||
]
|
||||
[
|
||||
[`const T&`
|
||||
|
||||
(return value)
|
||||
]
|
||||
[
|
||||
__call_traits_T__`::const_reference`
|
||||
]
|
||||
[
|
||||
Defines a type that represents a constant reference to type `T`.
|
||||
|
||||
Use for functions that would normally return a `const T&`.
|
||||
]
|
||||
[1]
|
||||
]
|
||||
[
|
||||
[`const T&`
|
||||
|
||||
(function parameter)
|
||||
]
|
||||
[
|
||||
__call_traits_T__`::param_type`
|
||||
]
|
||||
[
|
||||
Defines a type that represents the "best" way to pass a parameter of type `T` to a function.
|
||||
]
|
||||
[1,3]
|
||||
]
|
||||
]
|
||||
|
||||
Notes:
|
||||
|
||||
# If `T` is already reference type, then __call_traits__ is
|
||||
defined such that [link sec:refs "references to references"]
|
||||
do not occur (requires partial specialization).
|
||||
# If `T` is an array type, then __call_traits__ defines `value_type`
|
||||
as a "constant pointer to type" rather than an
|
||||
"array of type" (requires partial specialization).
|
||||
Note that if you are using `value_type` as a stored value
|
||||
then this will result in storing a "constant pointer to
|
||||
an array" rather than the array itself. This may or may
|
||||
not be a good thing depending upon what you actually
|
||||
need (in other words take care!).
|
||||
# If `T` is a small built in type or a pointer, then `param_type`
|
||||
is defined as `T const`, instead of `T const&`. This can
|
||||
improve the ability of the compiler to optimize loops in
|
||||
the body of the function if they depend upon the passed
|
||||
parameter, the semantics of the passed parameter is
|
||||
otherwise unchanged (requires partial specialization).
|
||||
|
||||
|
||||
[endsect]
|
||||
[section Copy constructibility]
|
||||
|
||||
The following table defines which __call_traits__ types can always
|
||||
be copy-constructed from which other types:
|
||||
|
||||
[table Which __call_traits__ types can always be copy-constructed from which other types
|
||||
[[] [To `T`] [To `value_type`] [To `reference`] [To `const_reference`] [To `param_type`]]
|
||||
[[From `T`] [iff `T` is copy constructible] [iff `T` is copy constructible] [Yes] [Yes] [Yes]]
|
||||
[[From `value_type`] [iff `T` is copy constructible] [iff `T` is copy constructible] [No] [No] [Yes]]
|
||||
[[From `reference`] [iff `T` is copy constructible] [iff `T` is copy constructible] [Yes] [Yes] [Yes]]
|
||||
[[From `const_reference`] [iff `T` is copy constructible] [No] [No] [Yes] [Yes]]
|
||||
[[From `param_type`] [iff `T` is copy constructible] [iff `T` is copy constructible] [No] [No] [Yes]]
|
||||
]
|
||||
|
||||
If `T` is an assignable type the following assignments are possible:
|
||||
|
||||
[table Which __call_traits__ types are assignable from which other types
|
||||
[[] [To `T`] [To `value_type`] [To `reference`] [To `const_reference`] [To `param_type`]]
|
||||
[[From `T`] [Yes] [Yes] [-] [-] [-]]
|
||||
[[From `value_type`] [Yes] [Yes] [-] [-] [-]]
|
||||
[[From `reference`] [Yes] [Yes] [-] [-] [-]]
|
||||
[[From `const_reference`] [Yes] [Yes] [-] [-] [-]]
|
||||
[[From `param_type`] [Yes] [Yes] [-] [-] [-]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[#sec:examples]
|
||||
[section Examples]
|
||||
|
||||
The following table shows the effect that __call_traits__ has on
|
||||
various types.
|
||||
|
||||
[table Examples of __call_traits__ types
|
||||
[[] [__call_traits__::`value_type`] [__call_traits__::`reference`] [__call_traits__::`const_reference`] [__call_traits__::`param_type`] [Applies to:]]
|
||||
[[From `my_class`] [`my_class`] [`my_class&`] [`const my_class&`] [`my_class const&`] [All user-defined types]]
|
||||
[[From `int`] [`int`] [`int&`] [`const int&`] [`int const`] [All small built-in types]]
|
||||
[[From `int*`] [`int*`] [`int*&`] [`int* const &`] [`int* const`] [All pointer types]]
|
||||
[[From `int&`] [`int&`] [`int&`] [`const int&`] [`int&`] [All reference types]]
|
||||
[[From `const int&`] [`const int&`] [`const int&`] [`const int&`] [`const int&`] [All constant reference types]]
|
||||
[[From `int[3]`] [`const int*`] [`int(&)[3]`] [`const int(&)[3]`] [`const int* const`] [All array types]]
|
||||
[[From `const int[3]`] [`const int*`] [`const int(&)[3]`] [`const int(&)[3]`] [`const int* const`] [All constant array types]]
|
||||
]
|
||||
|
||||
The table assumes the compiler supports partial
|
||||
specialization: if it does not then all types behave in
|
||||
the same way as the entry for "`my_class`", and
|
||||
__call_traits__ can not be used with reference or array types.
|
||||
|
||||
[section Example 1:]
|
||||
|
||||
The following class is a trivial class that stores some type `T`
|
||||
by value (see the [@../../../test/call_traits_test.cpp `call_traits_test.cpp`]
|
||||
file). The aim is to illustrate how each of the available
|
||||
__call_traits__ `typedef`s may be used:
|
||||
|
||||
```
|
||||
template <class T>
|
||||
struct contained
|
||||
{
|
||||
// define our typedefs first, arrays are stored by value
|
||||
// so value_type is not the same as result_type:
|
||||
typedef typename __boost_call_traits__<T>::param_type param_type;
|
||||
typedef typename __boost_call_traits__<T>::reference reference;
|
||||
typedef typename __boost_call_traits__<T>::const_reference const_reference;
|
||||
typedef T value_type;
|
||||
typedef typename __boost_call_traits__<T>::value_type result_type;
|
||||
|
||||
// stored value:
|
||||
value_type v_;
|
||||
|
||||
// constructors:
|
||||
contained() {}
|
||||
contained(param_type p) : v_(p){}
|
||||
// return byval:
|
||||
result_type value() { return v_; }
|
||||
// return by_ref:
|
||||
reference get() { return v_; }
|
||||
const_reference const_get()const { return v_; }
|
||||
// pass value:
|
||||
void call(param_type p){}
|
||||
|
||||
};
|
||||
```
|
||||
[endsect]
|
||||
|
||||
[#sec:refs]
|
||||
[section Example 2 (the reference to reference problem):]
|
||||
|
||||
Consider the definition of __std_binder1st__:
|
||||
|
||||
```
|
||||
template <class Operation>
|
||||
class binder1st :
|
||||
public __std_unary_function__<typename Operation::second_argument_type, typename Operation::result_type>
|
||||
{
|
||||
protected:
|
||||
Operation op;
|
||||
typename Operation::first_argument_type value;
|
||||
public:
|
||||
binder1st(const Operation& x, const typename Operation::first_argument_type& y);
|
||||
typename Operation::result_type operator()(const typename Operation::second_argument_type& x) const;
|
||||
};
|
||||
```
|
||||
|
||||
Now consider what happens in the relatively common case that
|
||||
the functor takes its second argument as a reference, that
|
||||
implies that `Operation::second_argument_type` is a
|
||||
reference type, `operator()` will now end up taking a
|
||||
reference to a reference as an argument, and that is not
|
||||
currently legal. The solution here is to modify `operator()`
|
||||
to use __call_traits__:
|
||||
|
||||
```
|
||||
typename Operation::result_type operator()(typename __call_traits__<typename Operation::second_argument_type>::param_type x) const;
|
||||
```
|
||||
|
||||
Now in the case that `Operation::second_argument_type`
|
||||
is a reference type, the argument is passed as a reference, and
|
||||
the no "reference to reference" occurs.
|
||||
|
||||
[endsect]
|
||||
|
||||
[#sec:example3]
|
||||
[section Example 3 (the `make_pair` problem):]
|
||||
|
||||
If we pass the name of an array as one (or both) arguments to `__std_make_pair__`,
|
||||
then template argument deduction deduces the passed parameter as
|
||||
"const reference to array of `T`", this also applies to
|
||||
string literals (which are really array literals). Consequently
|
||||
instead of returning a pair of pointers, it tries to return a
|
||||
pair of arrays, and since an array type is not copy-constructible
|
||||
the code fails to compile. One solution is to explicitly cast the
|
||||
arguments to __std_make_pair__ to pointers, but __call_traits__ provides a
|
||||
better automatic solution that works safely even in generic code where the
|
||||
cast might do the wrong thing:
|
||||
|
||||
```
|
||||
template <class T1, class T2>
|
||||
__std_pair__<
|
||||
typename __boost_call_traits__<T1>::value_type,
|
||||
typename __boost_call_traits__<T2>::value_type>
|
||||
make_pair(const T1& t1, const T2& t2)
|
||||
{
|
||||
return __std_pair__<
|
||||
typename __boost_call_traits__<T1>::value_type,
|
||||
typename __boost_call_traits__<T2>::value_type>(t1, t2);
|
||||
}
|
||||
```
|
||||
|
||||
Here, the deduced argument types will be automatically
|
||||
degraded to pointers if the deduced types are arrays, similar
|
||||
situations occur in the standard binders and adapters: in
|
||||
principle in any function that "wraps" a temporary
|
||||
whose type is deduced. Note that the function arguments to
|
||||
__std_make_pair__ are not expressed in terms of __call_traits__: doing so
|
||||
would prevent template argument deduction from functioning.
|
||||
[endsect]
|
||||
|
||||
[#sec:example4]
|
||||
[section Example 4 (optimising fill):]
|
||||
|
||||
The __call_traits__ template will "optimize" the passing
|
||||
of a small built-in type as a function parameter. This mainly has
|
||||
an effect when the parameter is used within a loop body.
|
||||
|
||||
In the following example (see [@boost:/libs/type_traits/examples/fill_example.cpp `fill_example.cpp`]),
|
||||
a version of __std_fill__ is optimized in two ways: if the type
|
||||
passed is a single byte built-in type then __std_memset__ is used to
|
||||
effect the fill, otherwise a conventional C++ implementation is
|
||||
used, but with the passed parameter "optimized" using
|
||||
__call_traits__:
|
||||
|
||||
```
|
||||
template <bool opt>
|
||||
struct filler
|
||||
{
|
||||
template <typename I, typename T>
|
||||
static void do_fill(I first, I last, typename __boost_call_traits__<T>::param_type val)
|
||||
{
|
||||
while(first != last)
|
||||
{
|
||||
*first = val;
|
||||
++first;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct filler<true>
|
||||
{
|
||||
template <typename I, typename T>
|
||||
static void do_fill(I first, I last, T val)
|
||||
{
|
||||
__std_memset__(first, val, last-first);
|
||||
}
|
||||
};
|
||||
|
||||
template <class I, class T>
|
||||
inline void fill(I first, I last, const T& val)
|
||||
{
|
||||
enum { can_opt = boost::is_pointer<I>::value
|
||||
&& boost::is_arithmetic<T>::value
|
||||
&& (sizeof(T) == 1) };
|
||||
typedef filler<can_opt> filler_t;
|
||||
filler_t::template do_fill<I,T>(first, last, val);
|
||||
}
|
||||
```
|
||||
|
||||
The reason that this is "optimal" for small built-in types is that
|
||||
with the value passed as `T const` instead of `const T&` the compiler is
|
||||
able to tell both that the value is constant and that it is free
|
||||
of aliases. With this information the compiler is able to cache
|
||||
the passed value in a register, unroll the loop, or use
|
||||
explicitly parallel instructions: if any of these are supported.
|
||||
Exactly how much mileage you will get from this depends upon your
|
||||
compiler - we could really use some accurate benchmarking
|
||||
software as part of boost for cases like this.
|
||||
|
||||
Note that the function arguments to fill are not expressed in
|
||||
terms of __call_traits__: doing so would prevent template argument
|
||||
deduction from functioning. Instead fill acts as a "thin
|
||||
wrapper" that is there to perform template argument
|
||||
deduction, the compiler will optimise away the call to fill all
|
||||
together, replacing it with the call to `filler<>::do_fill`,
|
||||
which does use __call_traits__.
|
||||
|
||||
[endsect]
|
||||
[endsect]
|
||||
|
||||
[section Rationale]
|
||||
|
||||
The following notes are intended to briefly describe the
|
||||
rationale behind choices made in __call_traits__.
|
||||
|
||||
All user-defined types follow "existing practice" and need no comment.
|
||||
|
||||
Small built-in types, what the standard calls [@https://en.cppreference.com/w/cpp/language/types fundamental
|
||||
types], differ from existing practice only in the `param_type`
|
||||
`typedef`. In this case passing `T const` is compatible
|
||||
with existing practice, but may improve performance in some cases
|
||||
(see [link sec:example4 Example 4]). In any case this should never
|
||||
be any worse than existing practice.
|
||||
|
||||
Pointers follow the same rationale as small built-in types.
|
||||
|
||||
For reference types the rationale follows [link sec:refs Example 2]
|
||||
- references to references are not allowed, so the __call_traits__
|
||||
members must be defined such that these problems do
|
||||
not occur. There is a proposal to modify the language such that
|
||||
"a reference to a reference is a reference" (issue #106,
|
||||
submitted by Bjarne Stroustrup). __call_traits_T__`::value_type`
|
||||
and __call_traits_T__`::param_type` both provide the same effect
|
||||
as that proposal, without the need for a language change. In
|
||||
other words, it's a workaround.
|
||||
|
||||
For array types, a function that takes an array as an argument
|
||||
will degrade the array type to a pointer type: this means that
|
||||
the type of the actual parameter is different from its declared
|
||||
type, something that can cause endless problems in template code
|
||||
that relies on the declared type of a parameter.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
template <class T>
|
||||
struct A
|
||||
{
|
||||
void foo(T t);
|
||||
};
|
||||
```
|
||||
|
||||
In this case if we instantiate `A<int[2]>` then the declared type of
|
||||
the parameter passed to member function `foo` is `int[2]`, but its
|
||||
actual type is `const int*`. If we try to use the type `T` within the
|
||||
function body, then there is a strong likelihood that our code will not compile:
|
||||
|
||||
```
|
||||
template <class T>
|
||||
void A<T>::foo(T t)
|
||||
{
|
||||
T dup(t); // doesn't compile for case that T is an array.
|
||||
}
|
||||
```
|
||||
|
||||
By using __call_traits__ the degradation from array to pointer is
|
||||
explicit, and the type of the parameter is the same as it's
|
||||
declared type:
|
||||
|
||||
```
|
||||
template <class T>
|
||||
struct A
|
||||
{
|
||||
void foo(typename __call_traits__<T>::value_type t);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void A<T>::foo(typename __call_traits__<T>::value_type t)
|
||||
{
|
||||
typename __call_traits__<T>::value_type dup(t); // OK even if T is an array type.
|
||||
}
|
||||
```
|
||||
|
||||
For `value_type` (return by value), again only a pointer may be
|
||||
returned, not a copy of the whole array, and again __call_traits__
|
||||
makes the degradation explicit. The `value_type` member is useful
|
||||
whenever an array must be explicitly degraded to a pointer -
|
||||
[link sec:example3 Example 3] provides the test case.
|
||||
|
||||
Footnote: the array specialisation for __call_traits__ is the least
|
||||
well understood of all the __call_traits__ specialisations. If the given
|
||||
semantics cause specific problems for you, or does not solve a particular
|
||||
array-related problem, then I would be interested to hear about
|
||||
it. Most people though will probably never need to use this
|
||||
specialisation.
|
||||
|
||||
[endsect]
|
||||
|
||||
[/===============]
|
||||
[xinclude tmp/call_traits_reference.xml]
|
||||
[/===============]
|
||||
|
||||
[endsect]
|
98
doc/compressed_pair.qbk
Normal file
98
doc/compressed_pair.qbk
Normal file
@ -0,0 +1,98 @@
|
||||
[/
|
||||
Copyright 2000 Beman Dawes & John Maddock.
|
||||
Copyright (c) 2021, Alan Freitas
|
||||
|
||||
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
|
||||
]
|
||||
|
||||
[section Compressed Pair]
|
||||
|
||||
[section Introduction]
|
||||
|
||||
All of the contents of [@../../../../boost/compressed_pair.hpp `<boost/compressed_pair.hpp>`] are defined inside
|
||||
`namespace boost`.
|
||||
|
||||
The class __compressed_pair__ is very similar to __std_pair__. However, if either of
|
||||
the template arguments are empty classes, then the
|
||||
[@https://en.cppreference.com/w/cpp/language/ebo ['empty base-class optimisation]]
|
||||
is applied to compress the size of the pair.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Synopsis]
|
||||
|
||||
```cpp
|
||||
template <class T1, class T2>
|
||||
class __compressed_pair__
|
||||
{
|
||||
public:
|
||||
typedef T1 first_type;
|
||||
typedef T2 second_type;
|
||||
typedef typename __call_traits__<first_type>::param_type first_param_type;
|
||||
typedef typename __call_traits__<second_type>::param_type second_param_type;
|
||||
typedef typename __call_traits__<first_type>::reference first_reference;
|
||||
typedef typename __call_traits__<second_type>::reference second_reference;
|
||||
typedef typename __call_traits__<first_type>::const_reference first_const_reference;
|
||||
typedef typename __call_traits__<second_type>::const_reference second_const_reference;
|
||||
|
||||
compressed_pair() : base() {}
|
||||
compressed_pair(first_param_type x, second_param_type y);
|
||||
explicit compressed_pair(first_param_type x);
|
||||
explicit compressed_pair(second_param_type y);
|
||||
|
||||
compressed_pair& operator=(const compressed_pair&);
|
||||
|
||||
first_reference first();
|
||||
first_const_reference first() const;
|
||||
|
||||
second_reference second();
|
||||
second_const_reference second() const;
|
||||
|
||||
void swap(compressed_pair& y);
|
||||
};
|
||||
```
|
||||
|
||||
The two members of the pair can be accessed using the member functions
|
||||
`first()` and `second()`. Note that not all member functions can be
|
||||
instantiated for all template parameter types. In particular
|
||||
__compressed_pair__ can be instantiated for reference and array types,
|
||||
however in these cases the range of constructors that can be used is
|
||||
limited. If types `T1` and `T2` are the same type, then there is only
|
||||
one version of the single-argument constructor, and this constructor
|
||||
initialises both values in the pair to the passed value.
|
||||
|
||||
Note that if either member is a [@https://en.cppreference.com/w/cpp/named_req/PODType POD]
|
||||
type, then that member is not zero-initialized by the __compressed_pair__ default constructor:
|
||||
it is up to you to supply an initial value for these types if you want them to have
|
||||
a default value.
|
||||
|
||||
Note that __compressed_pair__ can not be instantiated if either of the
|
||||
template arguments is a union type, unless there is compiler support for
|
||||
[@boost:/libs/type_traits/index.html `boost::is_union`], or
|
||||
if [@boost:/libs/type_traits/index.html `boost::is_union`] is
|
||||
specialised for the union type.
|
||||
|
||||
Finally, a word of caution for Visual C++ 6 users: if either argument is an
|
||||
empty type, then assigning to that member will produce memory corruption,
|
||||
unless the empty type has a "do nothing" assignment operator defined. This
|
||||
is due to a bug in the way VC6 generates implicit assignment operators.
|
||||
|
||||
[endsect]
|
||||
|
||||
[/===============]
|
||||
[xinclude tmp/compressed_pair_reference.xml]
|
||||
[/===============]
|
||||
|
||||
[section Acknowledgments]
|
||||
|
||||
Based on contributions by Steve Cleary, Beman Dawes, Howard Hinnant and
|
||||
John Maddock.
|
||||
|
||||
Maintained by [@mailto:john@johnmaddock.co.uk John Maddock].
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
308
doc/in_place_factory.qbk
Normal file
308
doc/in_place_factory.qbk
Normal file
@ -0,0 +1,308 @@
|
||||
[/
|
||||
/ Copyright (c) 2012 Marshall Clow
|
||||
/ Copyright (c) 2021, Alan Freitas
|
||||
/
|
||||
/ 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)
|
||||
/]
|
||||
|
||||
[/===============]
|
||||
[#sec:in_place_factory]
|
||||
[section In-place Factory]
|
||||
[/===============]
|
||||
|
||||
[section Introduction]
|
||||
|
||||
Suppose we have a class
|
||||
|
||||
```
|
||||
struct X
|
||||
{
|
||||
X ( int, __std_string__ ) ;
|
||||
};
|
||||
```
|
||||
|
||||
And a container for it which supports an empty state. That is, a container which can contain zero objects:
|
||||
|
||||
```
|
||||
struct C
|
||||
{
|
||||
C() : contained_(0) {}
|
||||
~C() { delete contained_ ; }
|
||||
X* contained_ ;
|
||||
};
|
||||
```
|
||||
|
||||
A container designed to support an empty state typically does not require the contained type to be
|
||||
__DefaultConstructible__, but it typically requires it to be __CopyConstructible__ as a mechanism to
|
||||
initialize the object to store:
|
||||
|
||||
```
|
||||
struct C
|
||||
{
|
||||
C() : contained_(0) {}
|
||||
C ( X const& v ) : contained_ ( new X(v) ) {}
|
||||
~C() { delete contained_ ; }
|
||||
X* contained_ ;
|
||||
};
|
||||
```
|
||||
|
||||
There is a subtle problem with this: since the mechanism used to initialize the stored object is copy construction,
|
||||
there must exist a previously constructed source object to copy from. This object is likely to be temporary and serve
|
||||
no purpose besides being the source:
|
||||
|
||||
```
|
||||
void foo()
|
||||
{
|
||||
// Temporary object created.
|
||||
C c( 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 supplies the arguments for the `X` constructor
|
||||
directly to the container:
|
||||
|
||||
```
|
||||
struct C
|
||||
{
|
||||
C() : contained_(0) {}
|
||||
C ( X const& v ) : contained_ ( new X(v) ) {}
|
||||
C ( int a0, __std_string__ a1 ) : contained_ ( new X(a0,a1) ) {}
|
||||
~C() { delete contained_ ; }
|
||||
X* contained_ ;
|
||||
};
|
||||
```
|
||||
|
||||
```
|
||||
void foo()
|
||||
{
|
||||
// Wrapped object constructed in-place
|
||||
// No temporary created.
|
||||
C c(123,"hello");
|
||||
}
|
||||
```
|
||||
|
||||
Clearly, this solution does not scale well since the container must duplicate all the constructor overloads
|
||||
from the contained type, or at least all those which are to be supported directly in the container.
|
||||
|
||||
[endsect]
|
||||
[section Framework]
|
||||
|
||||
This library proposes a framework to allow some containers to directly construct contained objects in-place without requiring
|
||||
the entire set of constructor overloads from the contained type. It also allows the container to remove the __CopyConstructible__
|
||||
requirement from the contained type since objects can be directly constructed in-place without need of a copy.
|
||||
|
||||
The only requirement on the container is that it must provide proper storage. That is, the container should be
|
||||
correctly aligned and sized. Naturally, the container will typically support uninitialized storage to avoid the
|
||||
in-place construction to override a fully-constructed object, as this would defeat the purpose of in-place construction.
|
||||
|
||||
For this purpose, the framework provides two concepts called: InPlaceFactories and TypedInPlaceFactories.
|
||||
Helpers to declare these classes are declared in [@../../../../boost/utility/in_place_factory.hpp `<boost/utility/in_place_factory.hpp>`]
|
||||
and [@../../../../boost/utility/typed_in_place_factory.hpp `<boost/utility/typed_in_place_factory.hpp>`].
|
||||
|
||||
Essentially, these classes hold a sequence of actual parameters and a method to construct an object in place using these parameters.
|
||||
Each member of the family differs only in the number and type of the parameter list. The first family
|
||||
takes the type of the object to construct directly in method provided for that
|
||||
purpose, whereas the second family incorporates that type in the factory class
|
||||
itself. From the container point of view, using the framework amounts to calling the
|
||||
factory's method to contruct the object in place. From the user point of view, it amounts to creating
|
||||
the right factory object to hold the parameters and pass it to the container.
|
||||
|
||||
The following simplified example shows the basic idea. A complete example follows the formal specification of the framework:
|
||||
|
||||
```
|
||||
struct C
|
||||
{
|
||||
template <class InPlaceFactory>
|
||||
C ( InPlaceFactory const& aFactory )
|
||||
:
|
||||
contained_ ( uninitialized_storage() )
|
||||
{
|
||||
aFactory.template apply<X>(contained_);
|
||||
}
|
||||
|
||||
~C()
|
||||
{
|
||||
contained_ -> X::~X();
|
||||
delete[] contained_ ;
|
||||
}
|
||||
|
||||
char* uninitialized_storage() { return new char[sizeof(X)] ; }
|
||||
|
||||
char* contained_ ;
|
||||
};
|
||||
|
||||
void foo()
|
||||
{
|
||||
C c( in_place(123,"hello") ) ;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
[endsect]
|
||||
[section Specification]
|
||||
|
||||
The following is the first member of the family of `InPlaceFactory` classes, along with its corresponding helper template function.
|
||||
The rest of the family varies only in the number and type of template and constructor parameters.
|
||||
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
|
||||
struct __in_place_factory_base__ {};
|
||||
|
||||
template<class A0>
|
||||
class in_place_factory : public __in_place_factory_base__
|
||||
{
|
||||
public:
|
||||
in_place_factory ( A0 const& a0 ) : m_a0(a0) {}
|
||||
|
||||
template< class T >
|
||||
void apply ( void* address ) const
|
||||
{
|
||||
new (address) T(m_a0);
|
||||
}
|
||||
|
||||
private:
|
||||
A0 const& m_a0 ;
|
||||
};
|
||||
|
||||
template<class A0>
|
||||
in_place_factory<A0> in_place ( A0 const& a0 )
|
||||
{
|
||||
return in_place_factory<A0>(a0);
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Similarly, the following is the first member of the family of `typed_in_place_factory` classes, along with its corresponding
|
||||
helper template function. The rest of the family varies only in the number and type of template and constructor parameters.
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
|
||||
struct __typed_in_place_factory_base__ {};
|
||||
|
||||
template<class T, class A0>
|
||||
class typed_in_place_factory : public __typed_in_place_factory_base__
|
||||
{
|
||||
public:
|
||||
typed_in_place_factory ( A0 const& a0 ) : m_a0(a0) {}
|
||||
|
||||
void apply ( void* address ) const
|
||||
{
|
||||
new (address) T(m_a0);
|
||||
}
|
||||
|
||||
private:
|
||||
A0 const& m_a0 ;
|
||||
};
|
||||
|
||||
template<class T, class A0>
|
||||
typed_in_place_factory<A0> in_place ( A0 const& a0 )
|
||||
{
|
||||
return typed_in_place_factory<T,A0>(a0);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
As you can see, the `in_place_factory` and `typed_in_place_factory` template classes vary only in the way they specify
|
||||
the target type: in the first family, the type is given as a template argument to the apply member function while in the
|
||||
second it is given directly as part of the factory class.
|
||||
|
||||
When the container holds a unique non-polymorphic type, such as the case of [@boost:/libs/optional/index.html Boost.Optional],
|
||||
it knows the exact dynamic-type of the contained object and can pass it to the `apply()` method of a non-typed factory.
|
||||
In this case, end users can use an `in_place_factory` instance which can be constructed without the type of the object to construct.
|
||||
|
||||
However, if the container holds heterogeneous or polymorphic objects, such as the case of [@boost:/libs/variant/index.html Boost.Variant],
|
||||
the dynamic-type of the object to be constructed must be known by the factory. In this case, end users must use a `typed_in_place_factory`
|
||||
instead.
|
||||
|
||||
[endsect]
|
||||
[section Container-side Usage]
|
||||
|
||||
As shown in the introductory simplified example, the container class must contain methods that accept an instance of
|
||||
these factories and pass the object's storage to the factory's apply method.
|
||||
|
||||
However, the type of the factory class cannot be completely specified in the container class because that would
|
||||
defeat the whole purpose of the factories which is to allow the container to accept a variadic argument list
|
||||
for the constructor of its contained object.
|
||||
|
||||
The correct function overload must be based on the only distinctive and common
|
||||
characteristic of all the classes in each family: the base class.
|
||||
|
||||
Depending on the container class, you can use `enable_if` to generate the right overload, or use the following
|
||||
dispatch technique, which is used in the [@boost:/libs/optional/index.html Boost.Optional] class:
|
||||
|
||||
|
||||
```
|
||||
struct C
|
||||
{
|
||||
C() : contained_(0) {}
|
||||
C ( X const& v ) : contained_ ( new X(v) ) {}
|
||||
|
||||
template <class Expr>
|
||||
C ( Expr const& expr )
|
||||
:
|
||||
contained_ ( uninitialized_storage() )
|
||||
{
|
||||
construct(expr,&expr);
|
||||
}
|
||||
|
||||
~C() { delete contained_ ; }
|
||||
|
||||
template<class InPlaceFactory>
|
||||
void construct ( InPlaceFactory const& aFactory, boost::__in_place_factory_base__* )
|
||||
{
|
||||
aFactory.template apply<X>(contained_);
|
||||
}
|
||||
|
||||
template<class TypedInPlaceFactory>
|
||||
void construct ( TypedInPlaceFactory const& aFactory, boost::__typed_in_place_factory_base__* )
|
||||
{
|
||||
aFactory.apply(contained_);
|
||||
}
|
||||
|
||||
X* uninitialized_storage() { return static_cast<X*>(new char[sizeof(X)]) ; }
|
||||
|
||||
X* contained_ ;
|
||||
};
|
||||
```
|
||||
|
||||
[endsect]
|
||||
[section User-side Usage]
|
||||
|
||||
End users pass to the container an instance of a factory object holding the actual parameters needed to construct the
|
||||
contained object directly within the container. For this, the helper template function `in_place` is used.
|
||||
|
||||
The call `in_place(a0,a1,a2,...,an)` constructs a (non-typed) `in_place_factory` instance with the given argument list.
|
||||
|
||||
The call `in_place<T>(a0,a1,a2,...,an)` constructs a `typed_in_place_factory` instance with the given argument list for the
|
||||
type `T`.
|
||||
|
||||
```
|
||||
void foo()
|
||||
{
|
||||
C a( in_place(123, "hello") ) ; // in_place_factory passed
|
||||
C b( in_place<X>(456, "world") ) ; // typed_in_place_factory passed
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
[endsect]
|
||||
|
||||
[/===============]
|
||||
[#boost.typed_in_place_factory_base]
|
||||
[xinclude tmp/in_place_factory_reference.xml]
|
||||
[/===============]
|
||||
|
||||
[section Acknowledgments]
|
||||
|
||||
Copyright Fernando Luis Cacciola Carballal, 2004
|
||||
|
||||
[endsect]
|
||||
[endsect]
|
BIN
doc/logo.png
Normal file
BIN
doc/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
539
doc/logo.svg
Normal file
539
doc/logo.svg
Normal file
@ -0,0 +1,539 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="744.09448819"
|
||||
height="1052.3622047"
|
||||
id="svg6858"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="utility.svg">
|
||||
<defs
|
||||
id="defs6860">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4453-7-8-6-7-3-5"
|
||||
id="linearGradient10687-2-5"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="753.02301"
|
||||
y1="3132.0801"
|
||||
x2="1146.25"
|
||||
y2="3132.0801" />
|
||||
<linearGradient
|
||||
id="linearGradient4453-7-8-6-7-3-5">
|
||||
<stop
|
||||
style="stop-color:#aac4dd;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4455-61-8-7-1-2-8" />
|
||||
<stop
|
||||
style="stop-color:#c2dbe9;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4457-4-1-9-1-12-1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4453-7-8-6-7-3-5"
|
||||
id="linearGradient10685-2-2"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="753.02301"
|
||||
y1="3132.0801"
|
||||
x2="1146.25"
|
||||
y2="3132.0801" />
|
||||
<linearGradient
|
||||
id="linearGradient6749">
|
||||
<stop
|
||||
style="stop-color:#aac4dd;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop6751" />
|
||||
<stop
|
||||
style="stop-color:#c2dbe9;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop6753" />
|
||||
</linearGradient>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath3387-3-6-4-2-8-4">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 862.109,3289.75 -109.086,-190.45 69.122,-124.42 164.511,-0.47 c 0,0 111.044,188.28 116.564,197.63 7.66,0 43.03,0 43.03,0 l -67.03,117.71 -217.111,0 z"
|
||||
id="path3389-2-0-7-7-8-9" />
|
||||
</clipPath>
|
||||
<linearGradient
|
||||
y2="3132.0801"
|
||||
x2="1146.25"
|
||||
y1="3132.0801"
|
||||
x1="753.02301"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient4492-8-8"
|
||||
xlink:href="#linearGradient4453-7-8-6-7-3-5"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
id="linearGradient6758">
|
||||
<stop
|
||||
style="stop-color:#aac4dd;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop6760" />
|
||||
<stop
|
||||
style="stop-color:#c2dbe9;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop6762" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4453-7-8-6-7-3-5"
|
||||
id="linearGradient10691-7-8"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="1026.6899"
|
||||
y1="2937.73"
|
||||
x2="1463.14"
|
||||
y2="2937.73" />
|
||||
<linearGradient
|
||||
id="linearGradient6765">
|
||||
<stop
|
||||
style="stop-color:#aac4dd;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop6767" />
|
||||
<stop
|
||||
style="stop-color:#c2dbe9;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop6769" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4453-7-8-6-7-3-5"
|
||||
id="linearGradient10689-4-2"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="1026.6899"
|
||||
y1="2937.73"
|
||||
x2="1463.14"
|
||||
y2="2937.73" />
|
||||
<linearGradient
|
||||
id="linearGradient6772">
|
||||
<stop
|
||||
style="stop-color:#aac4dd;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop6774" />
|
||||
<stop
|
||||
style="stop-color:#c2dbe9;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop6776" />
|
||||
</linearGradient>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath3369-1-5-6-1-0-7">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 1131.64,3128.5 -104.95,-181.12 116.38,-200.42 208.05,0.94 112.02,191.63 -112.08,188.97 -219.42,0 z"
|
||||
id="path3371-89-4-1-6-0-1" />
|
||||
</clipPath>
|
||||
<linearGradient
|
||||
y2="2937.73"
|
||||
x2="1463.14"
|
||||
y1="2937.73"
|
||||
x1="1026.6899"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient4498-5-7"
|
||||
xlink:href="#linearGradient4453-7-8-6-7-3-5"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
id="linearGradient6781">
|
||||
<stop
|
||||
style="stop-color:#aac4dd;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop6783" />
|
||||
<stop
|
||||
style="stop-color:#c2dbe9;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop6785" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4459-1-2-8-9-9-5"
|
||||
id="linearGradient10695-9-9"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="646.55499"
|
||||
y1="2736.25"
|
||||
x2="1088.27"
|
||||
y2="2736.25" />
|
||||
<linearGradient
|
||||
id="linearGradient4459-1-2-8-9-9-5">
|
||||
<stop
|
||||
id="stop4461-2-1-5-2-5-0"
|
||||
offset="0"
|
||||
style="stop-color:#839bc2;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop4463-3-2-8-7-30-3"
|
||||
offset="1"
|
||||
style="stop-color:#9fb6d4;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4459-1-2-8-9-9-5"
|
||||
id="linearGradient10693-9-4"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="646.55499"
|
||||
y1="2736.25"
|
||||
x2="1088.27"
|
||||
y2="2736.25" />
|
||||
<linearGradient
|
||||
id="linearGradient6792">
|
||||
<stop
|
||||
id="stop6794"
|
||||
offset="0"
|
||||
style="stop-color:#839bc2;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop6796"
|
||||
offset="1"
|
||||
style="stop-color:#9fb6d4;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath3351-4-7-3-5-95-0">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 757.242,2926.25 -110.687,-189.11 110.656,-190.89 219.437,0 111.622,189.1 -111.59,190.9 -219.438,0 z"
|
||||
id="path3353-1-9-3-4-1-1" />
|
||||
</clipPath>
|
||||
<linearGradient
|
||||
y2="2736.25"
|
||||
x2="1088.27"
|
||||
y1="2736.25"
|
||||
x1="646.55499"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient4510-1-5"
|
||||
xlink:href="#linearGradient4459-1-2-8-9-9-5"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
id="linearGradient6801">
|
||||
<stop
|
||||
id="stop6803"
|
||||
offset="0"
|
||||
style="stop-color:#839bc2;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop6805"
|
||||
offset="1"
|
||||
style="stop-color:#9fb6d4;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#radialGradient3327-8-4-8-0-2-4"
|
||||
id="radialGradient10699-1-3"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cx="997.46997"
|
||||
cy="2896.25"
|
||||
fx="997.46997"
|
||||
fy="2896.25"
|
||||
r="583.73999" />
|
||||
<radialGradient
|
||||
fx="0"
|
||||
fy="0"
|
||||
cx="0"
|
||||
cy="0"
|
||||
r="1"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(58.375,0,0,-58.375,99.75,289.625)"
|
||||
spreadMethod="pad"
|
||||
id="radialGradient3327-8-4-8-0-2-4">
|
||||
<stop
|
||||
style="stop-opacity:1;stop-color:#aeaeb3"
|
||||
offset="0"
|
||||
id="stop3329-7-0-1-0-33-2" />
|
||||
<stop
|
||||
style="stop-opacity:1;stop-color:#ffffff"
|
||||
offset="0.949438"
|
||||
id="stop3331-4-3-0-0-97-3" />
|
||||
<stop
|
||||
style="stop-opacity:1;stop-color:#ffffff"
|
||||
offset="1"
|
||||
id="stop3333-2-4-9-7-2-2" />
|
||||
</radialGradient>
|
||||
<radialGradient
|
||||
r="583.73999"
|
||||
fy="2896.25"
|
||||
fx="997.46997"
|
||||
cy="2896.25"
|
||||
cx="997.46997"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient13050"
|
||||
xlink:href="#radialGradient3327-8-4-8-0-2-4"
|
||||
inkscape:collect="always" />
|
||||
<radialGradient
|
||||
fx="0"
|
||||
fy="0"
|
||||
cx="0"
|
||||
cy="0"
|
||||
r="1"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(58.375,0,0,-58.375,99.75,289.625)"
|
||||
spreadMethod="pad"
|
||||
id="radialGradient6813">
|
||||
<stop
|
||||
style="stop-opacity:1;stop-color:#aeaeb3"
|
||||
offset="0"
|
||||
id="stop6815" />
|
||||
<stop
|
||||
style="stop-opacity:1;stop-color:#ffffff"
|
||||
offset="0.949438"
|
||||
id="stop6817" />
|
||||
<stop
|
||||
style="stop-opacity:1;stop-color:#ffffff"
|
||||
offset="1"
|
||||
id="stop6819" />
|
||||
</radialGradient>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath3323-7-2-4-5-3-4">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 997.469,2312.51 c -322.379,0 -583.739,261.36 -583.739,583.74 0,322.38 261.36,583.74 583.739,583.74 322.381,0 583.741,-261.36 583.741,-583.74 0,-322.38 -261.36,-583.74 -583.741,-583.74"
|
||||
id="path3325-9-2-9-5-04-9" />
|
||||
</clipPath>
|
||||
<radialGradient
|
||||
r="583.73999"
|
||||
fy="2896.25"
|
||||
fx="997.46997"
|
||||
cy="2896.25"
|
||||
cx="997.46997"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient4516-8-2"
|
||||
xlink:href="#radialGradient3327-8-4-8-0-2-4"
|
||||
inkscape:collect="always" />
|
||||
<radialGradient
|
||||
fx="0"
|
||||
fy="0"
|
||||
cx="0"
|
||||
cy="0"
|
||||
r="1"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(58.375,0,0,-58.375,99.75,289.625)"
|
||||
spreadMethod="pad"
|
||||
id="radialGradient6824">
|
||||
<stop
|
||||
style="stop-opacity:1;stop-color:#aeaeb3"
|
||||
offset="0"
|
||||
id="stop6826" />
|
||||
<stop
|
||||
style="stop-opacity:1;stop-color:#ffffff"
|
||||
offset="0.949438"
|
||||
id="stop6828" />
|
||||
<stop
|
||||
style="stop-opacity:1;stop-color:#ffffff"
|
||||
offset="1"
|
||||
id="stop6830" />
|
||||
</radialGradient>
|
||||
<radialGradient
|
||||
r="583.73999"
|
||||
fy="2896.25"
|
||||
fx="997.46997"
|
||||
cy="2896.25"
|
||||
cx="997.46997"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient6856"
|
||||
xlink:href="#radialGradient3327-8-4-8-0-2-4"
|
||||
inkscape:collect="always" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.4"
|
||||
inkscape:cx="234.05635"
|
||||
inkscape:cy="581.46313"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1680"
|
||||
inkscape:window-height="982"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3066" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata6863">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<g
|
||||
id="g3319-1-2-5-1-4-4"
|
||||
transform="matrix(0.10419818,0,0,-0.10419818,137.10955,897.00327)"
|
||||
style="fill:url(#radialGradient10699-1-3);fill-opacity:1"
|
||||
inkscape:export-filename="C:\Users\Adam\Desktop\bg_logo1.png"
|
||||
inkscape:export-xdpi="63.625523"
|
||||
inkscape:export-ydpi="63.625523">
|
||||
<g
|
||||
clip-path="url(#clipPath3323-7-2-4-5-3-4)"
|
||||
id="g3321-9-2-7-4-3-9"
|
||||
style="fill:url(#radialGradient6856);fill-opacity:1">
|
||||
<path
|
||||
id="path3335-8-7-3-8-92-0"
|
||||
style="fill:url(#radialGradient4516-8-2);fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 997.469,2312.51 c -322.379,0 -583.739,261.36 -583.739,583.74 0,322.38 261.36,583.74 583.739,583.74 322.381,0 583.741,-261.36 583.741,-583.74 0,-322.38 -261.36,-583.74 -583.741,-583.74"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="g3347-6-8-3-7-4-4"
|
||||
transform="matrix(0.125,0,0,-0.125,112.08304,959.82207)"
|
||||
style="fill:url(#linearGradient10695-9-9);fill-opacity:1"
|
||||
inkscape:export-filename="C:\Users\Adam\Desktop\bg_logo1.png"
|
||||
inkscape:export-xdpi="63.625523"
|
||||
inkscape:export-ydpi="63.625523">
|
||||
<g
|
||||
clip-path="url(#clipPath3351-4-7-3-5-95-0)"
|
||||
id="g3349-5-5-4-7-9-4"
|
||||
style="fill:url(#linearGradient10693-9-4);fill-opacity:1">
|
||||
<path
|
||||
id="path3361-0-8-2-9-0-9"
|
||||
style="fill:url(#linearGradient4510-1-5);fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 757.242,2926.25 -110.687,-189.11 110.656,-190.89 219.437,0 111.622,189.1 -111.59,190.9 -219.438,0"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
<path
|
||||
id="path3363-6-9-0-1-5-8"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 194.34816,617.68335 13.106,-22.3925 25.99649,0 13.21487,22.60874 -13.21487,22.39125 -25.99649,0 -13.106,-22.60749 z m 40.53761,-24.8925 -28.86524,0 -0.72412,1.23749 -13.106,22.39251 -0.73575,1.25625 0.73087,1.26 13.106,22.60744 0.72263,1.24634 28.86374,0 0.72512,-1.22884 13.215,-22.39119 0.74625,-1.265 -0.74,-1.26751 -13.21537,-22.60875 -0.72313,-1.23874"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:export-filename="C:\Users\Adam\Desktop\bg_logo1.png"
|
||||
inkscape:export-xdpi="63.625523"
|
||||
inkscape:export-ydpi="63.625523" />
|
||||
<g
|
||||
id="g3365-0-4-1-9-7-5"
|
||||
transform="matrix(0.125,0,0,-0.125,112.08304,959.82207)"
|
||||
style="fill:url(#linearGradient10691-7-8);fill-opacity:1"
|
||||
inkscape:export-filename="C:\Users\Adam\Desktop\bg_logo1.png"
|
||||
inkscape:export-xdpi="63.625523"
|
||||
inkscape:export-ydpi="63.625523">
|
||||
<g
|
||||
clip-path="url(#clipPath3369-1-5-6-1-0-7)"
|
||||
id="g3367-2-4-2-8-4-3"
|
||||
style="fill:url(#linearGradient10689-4-2);fill-opacity:1">
|
||||
<path
|
||||
id="path3379-4-6-7-6-7-2"
|
||||
style="fill:url(#linearGradient4498-5-7);fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 1131.64,3128.5 -104.95,-181.12 116.38,-200.42 208.05,0.94 112.02,191.63 -112.08,188.97 -219.42,0"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
<path
|
||||
id="path3381-6-8-0-0-66-3"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 241.86427,591.39959 12.3925,-21.38999 25.99625,0 13.27125,22.37625 -13.27125,22.7025 -24.56875,0.11 -13.82,-23.79876 z m 39.8125,-23.88999 -28.86125,0 -0.7225,1.24625 -12.3925,21.39 -0.72625,1.255 0.7275,1.25374 13.82,23.79876 0.7275,1.25125 1.44625,-0.006 24.56875,-0.11 1.4275,-0.006 0.72,-1.2325 13.27125,-22.7025 0.7425,-1.27 -0.75125,-1.26625 -13.27125,-22.37625 -0.72625,-1.225"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:export-filename="C:\Users\Adam\Desktop\bg_logo1.png"
|
||||
inkscape:export-xdpi="63.625523"
|
||||
inkscape:export-ydpi="63.625523" />
|
||||
<g
|
||||
id="g3383-5-5-2-2-3-0"
|
||||
transform="matrix(0.125,0,0,-0.125,112.08304,959.82207)"
|
||||
style="fill:url(#linearGradient10687-2-5);fill-opacity:1"
|
||||
inkscape:export-filename="C:\Users\Adam\Desktop\bg_logo1.png"
|
||||
inkscape:export-xdpi="63.625523"
|
||||
inkscape:export-ydpi="63.625523">
|
||||
<g
|
||||
clip-path="url(#clipPath3387-3-6-4-2-8-4)"
|
||||
id="g3385-0-6-4-8-0-1"
|
||||
style="fill:url(#linearGradient10685-2-2);fill-opacity:1">
|
||||
<path
|
||||
id="path3397-9-6-1-6-9-7"
|
||||
style="fill:url(#linearGradient4492-8-8);fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 862.109,3289.75 -109.086,-190.45 69.122,-124.42 164.511,-0.47 c 0,0 111.044,188.28 116.564,197.63 7.66,0 43.03,0 43.03,0 l -67.03,117.71 -217.111,0"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
<path
|
||||
id="path3399-6-7-3-2-0-1"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 207.64603,572.41959 12.92424,-22.56624 25.68775,0 6.95625,12.21375 -3.94375,0 -14.56837,24.7025 -19.11525,-0.055 -7.94087,-14.295 z m 40.06574,-25.06624 -28.59012,0 -0.71975,1.2575 -12.92537,22.56625 -0.70112,1.22375 0.68512,1.23249 7.94137,14.295 0.71087,1.2825 1.46638,0.004 19.11525,0.055 1.43212,0.004 0.729,-1.23375 13.84375,-23.47249 6.81625,0 -2.12875,-3.7375 -6.95625,-12.21375 -0.71875,-1.2625"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:export-filename="C:\Users\Adam\Desktop\bg_logo1.png"
|
||||
inkscape:export-xdpi="63.625523"
|
||||
inkscape:export-ydpi="63.625523" />
|
||||
<g
|
||||
transform="matrix(1.25,0,0,-1.25,105.02062,972.84257)"
|
||||
id="g3465-0-8-9"
|
||||
inkscape:export-filename="C:\Users\Adam\Desktop\bg_logo1.png"
|
||||
inkscape:export-xdpi="63.625523"
|
||||
inkscape:export-ydpi="63.625523">
|
||||
<text
|
||||
id="text3467-9-0-8"
|
||||
transform="matrix(1,0,-0.17627963,-1,0,0)"
|
||||
x="116.98372"
|
||||
y="-267.77499"
|
||||
style="font-size:11.81779194px">
|
||||
<tspan
|
||||
sodipodi:role="line"
|
||||
style="font-size:46.39999771px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#49608a;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:Denmark;-inkscape-font-specification:Denmark"
|
||||
x="116.98372"
|
||||
y="-267.77499"
|
||||
id="tspan13239">UTILITY</tspan>
|
||||
<tspan
|
||||
sodipodi:role="line"
|
||||
style="font-size:46.39999771px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#49608a;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:Denmark;-inkscape-font-specification:Denmark"
|
||||
x="116.98372"
|
||||
y="-209.77499"
|
||||
id="tspan11278-3" />
|
||||
</text>
|
||||
<text
|
||||
id="text3471-0-51-2"
|
||||
transform="matrix(0.99235617,0,-0.17763746,-1.0077027,0,0)"
|
||||
style="font-size:38.40000153px"
|
||||
x="112.74373"
|
||||
y="-306.75479">
|
||||
<tspan
|
||||
id="tspan3473-6-0-9"
|
||||
sodipodi:role="line"
|
||||
style="font-size:38.40000153px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#49608a;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:Denmark;-inkscape-font-specification:Denmark"
|
||||
x="112.74373"
|
||||
y="-306.75479">boost</tspan>
|
||||
</text>
|
||||
</g>
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none"
|
||||
d="m 201.43967,613.81579 4.64114,4.2175 3.3738,-3.71306 -0.92817,-0.84354 1.68708,-1.85636 20.53445,20.81026 4.2175,-4.64111 -22.22144,-18.95384 c 0,0 1.69594,-1.83698 2.53062,-2.78454 2.53905,-2.76559 5.98925,-4.72587 5.98925,-4.72587 0,0 -6.03647,0.58224 -8.76507,2.21476 -0.84428,0.92751 -6.75676,7.40649 -6.75676,7.40649 l -0.92819,-0.84355 -3.37382,3.71308"
|
||||
id="path13283"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccccccccc" />
|
||||
<g
|
||||
id="g3086"
|
||||
transform="matrix(0.99872217,-0.05053738,0.05053738,0.99872217,-31.539183,11.181538)">
|
||||
<path
|
||||
sodipodi:nodetypes="ccccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path13243"
|
||||
d="m 227.74101,611.16418 -15.09943,12.783 2.55659,3.01989 15.09944,-12.78302 c 3.56324,2.16769 7.58975,-1.2411 7.0464,-5.96538 l -4.02652,3.40879 -2.55659,-3.01989 4.02652,-3.40879 c -3.56324,-2.16769 -8.59639,2.0933 -7.04641,5.9654 z"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path13243-1"
|
||||
d="m 215.25729,626.9851 15.08951,-12.7947 -2.55893,-3.01791 -15.08952,12.79471 c -3.56492,-2.16491 -7.58878,1.24699 -7.04177,5.97085 l 4.02388,-3.41192 2.55892,3.01791 -4.02387,3.41192 c 3.56491,2.16492 8.59476,-2.09997 7.04178,-5.97086 z"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 20 KiB |
234
doc/main.qbk
Normal file
234
doc/main.qbk
Normal file
@ -0,0 +1,234 @@
|
||||
[/
|
||||
Copyright (c) 2021, Alan Freitas
|
||||
|
||||
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)
|
||||
|
||||
Official repository: https://github.com/boostorg/utility
|
||||
]
|
||||
|
||||
[/#############################################
|
||||
DOCUMENT INFO
|
||||
###############################################]
|
||||
|
||||
[library Boost.Utility
|
||||
[id utility]
|
||||
[quickbook 1.6]
|
||||
[copyright 2001 Beman Dawes]
|
||||
[purpose Utility Library]
|
||||
[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])
|
||||
]
|
||||
[authors [Dawes, Beman]]
|
||||
[category template]
|
||||
[category generic]
|
||||
]
|
||||
|
||||
[template mdash[]'''—''']
|
||||
[template ndash[]'''–''']
|
||||
[template sect[]'''§''']
|
||||
[template hellip[]'''…''']
|
||||
|
||||
[template indexterm1[term1]'''<indexterm><primary>'''[term1]'''</primary></indexterm>''']
|
||||
[template indexterm2[term1 term2]'''<indexterm><primary>'''[term1]'''</primary><secondary>'''[term2]'''</secondary></indexterm>''']
|
||||
|
||||
[template include_file[path][^<'''<ulink url="https://github.com/boostorg/utility/blob/master/include/'''[path]'''">'''[path]'''</ulink>'''>]]
|
||||
[template issue[n]'''<ulink url="https://github.com/boostorg/utility/issues/'''[n]'''">#'''[n]'''</ulink>''']
|
||||
|
||||
[/ Named Requirements ]
|
||||
|
||||
[def __Handler__ ['Handler]]
|
||||
[def __Allocator__ [@https://en.cppreference.com/w/cpp/named_req/Allocator ['Allocator]]]
|
||||
[def __CopyAssignable__ [@https://en.cppreference.com/w/cpp/named_req/CopyAssignable ['CopyAssignable]]]
|
||||
[def __CopyConstructible__ [@https://en.cppreference.com/w/cpp/named_req/CopyConstructible ['CopyConstructible]]]
|
||||
[def __Copyable__ [@https://en.cppreference.com/w/cpp/concepts/copyable ['Copyable]]]
|
||||
[def __DefaultConstructible__ [@https://en.cppreference.com/w/cpp/named_req/DefaultConstructible ['DefaultConstructible]]]
|
||||
[def __Hash__ [@https://en.cppreference.com/w/cpp/named_req/Hash ['Hash]]]
|
||||
[def __InputIterator__ [@https://en.cppreference.com/w/cpp/named_req/InputIterator ['InputIterator]]]
|
||||
[def __MoveAssignable__ [@https://en.cppreference.com/w/cpp/named_req/MoveAssignable ['MoveAssignable]]]
|
||||
[def __MoveConstructible__ [@https://en.cppreference.com/w/cpp/named_req/MoveConstructible ['MoveConstructible]]]
|
||||
[def __RandomAccessIterator__ [@https://en.cppreference.com/w/cpp/named_req/RandomAccessIterator ['RandomAccessIterator]]]
|
||||
[def __Regular__ [@https://en.cppreference.com/w/cpp/concepts/regular ['Regular]]]
|
||||
[def __Swappable__ [@https://en.cppreference.com/w/cpp/named_req/Swappable ['Swappable]]]
|
||||
|
||||
[/ Boost types ]
|
||||
[/ (Macros are defined here because these macros are often referenced in other components) ]
|
||||
[/ (operators macros link to the a table of operators because there's no doxygen reference for the operators) ]
|
||||
|
||||
[def __BOOST_BINARY__ [link sec:BOOST_BINARY `BOOST_BINARY`]]
|
||||
[def __in_place_factory__ [link sec:in_place_factory `in_place_factory`]]
|
||||
|
||||
[def __boost_base_from_member__ [link boost.base_from_member `boost::base_from_member`]]
|
||||
[def __boost_call_traits__ [link boost.call_traits `boost::call_traits`]]
|
||||
[def __boost_result_of__ [link boost.result_of `boost::result_of`]]
|
||||
[def __boost_tr1_result_of__ [link boost.tr1_result_of `boost::tr1_result_of`]]
|
||||
[def __boost_string_view__ [link boost.basic_string_view `boost::string_view`]]
|
||||
[def __boost_basic_string_view__ [link boost.basic_string_view `boost::basic_string_view`]]
|
||||
|
||||
[def __additive1__ [link sec:arithmetic `additive1`]]
|
||||
[def __additive2__ [link sec:arithmetic `additive2`]]
|
||||
[def __arithmetic1__ [link sec:arithmetic `arithmetic1`]]
|
||||
[def __arithmetic2__ [link sec:arithmetic `arithmetic2`]]
|
||||
[def __base_from_member__ [link boost.base_from_member `base_from_member`]]
|
||||
[def __basic_string_ref__ [link boost.basic_string_view `basic_string_ref`]]
|
||||
[def __basic_string_view__ [link boost.basic_string_view `basic_string_view`]]
|
||||
[def __bidirectional_iteratable__ [link sec:arithmetic `bidirectional_iteratable`]]
|
||||
[def __bidirectional_iterator_helper__ [link sec:arithmetic `bidirectional_iterator_helper`]]
|
||||
[def __bitwise1__ [link sec:arithmetic `bitwise1`]]
|
||||
[def __bitwise2__ [link sec:arithmetic `bitwise2`]]
|
||||
[def __call_traits__ [link boost.call_traits `call_traits`]]
|
||||
[def __call_traits_T__ [link boost.call_traits `call_traits<T>`]]
|
||||
[def __call_traits_lt__T___ [link boost.call_traits `call_traits<T&>`]]
|
||||
[def __call_traits_lt__T_lb_N_rb__gt___ [link boost.call_traits `call_traits< T[N]>`]]
|
||||
[def __call_traits_lt__const_T_lb_N_rb__gt___ [link boost.call_traits `call_traits< const T[N]>`]]
|
||||
[def __compressed_pair__ [link boost.compressed_pair `compressed_pair`]]
|
||||
[def __decrementable__ [link sec:arithmetic `decrementable`]]
|
||||
[def __dereferenceable__ [link sec:arithmetic `dereferenceable`]]
|
||||
[def __equal_pointees__ [link sec:arithmetic `equal_pointees`]]
|
||||
[def __equal_pointees_t__ [link sec:arithmetic `equal_pointees_t`]]
|
||||
[def __equality_comparable1__ [link sec:arithmetic `equality_comparable1`]]
|
||||
[def __equality_comparable2__ [link sec:arithmetic `equality_comparable2`]]
|
||||
[def __equivalent1__ [link sec:arithmetic `equivalent1`]]
|
||||
[def __equivalent2__ [link sec:arithmetic `equivalent2`]]
|
||||
[def __euclidean_ring_operators1__ [link sec:arithmetic `euclidean_ring_operators1`]]
|
||||
[def __euclidean_ring_operators2__ [link sec:arithmetic `euclidean_ring_operators2`]]
|
||||
[def __field_operators1__ [link sec:arithmetic `field_operators1`]]
|
||||
[def __field_operators2__ [link sec:arithmetic `field_operators2`]]
|
||||
[def __forward_iteratable__ [link sec:arithmetic `forward_iteratable`]]
|
||||
[def __forward_iterator_helper__ [link sec:arithmetic `forward_iterator_helper`]]
|
||||
[def __get__ [link boost.get `get`]]
|
||||
[def __hash_range__ [link boost.hash_range `hash_range`]]
|
||||
[def __hash_value__ [link boost.hash_value `hash_value`]]
|
||||
[def __in_place_factory_base__ [link boost.in_place_factory_base `in_place_factory_base`]]
|
||||
[def __incrementable__ [link sec:arithmetic `incrementable`]]
|
||||
[def __indexable__ [link sec:arithmetic `indexable`]]
|
||||
[def __initialized__ [link boost.initialized `initialized`]]
|
||||
[def __initialized_value__ [link boost.initialized_value `initialized_value`]]
|
||||
[def __initialized_value_t__ [link boost.initialized_value_t `initialized_value_t`]]
|
||||
[def __input_iteratable__ [link sec:arithmetic `input_iteratable`]]
|
||||
[def __input_iterator_helper__ [link sec:arithmetic `input_iterator_helper`]]
|
||||
[def __integer_arithmetic1__ [link sec:arithmetic `integer_arithmetic1`]]
|
||||
[def __integer_arithmetic2__ [link sec:arithmetic `integer_arithmetic2`]]
|
||||
[def __integer_multiplicative1__ [link sec:arithmetic `integer_multiplicative1`]]
|
||||
[def __integer_multiplicative2__ [link sec:arithmetic `integer_multiplicative2`]]
|
||||
[def __is_chained_base__ [link sec:arithmetic `is_chained_base`]]
|
||||
[def __less_pointees__ [link boost.less_pointees `less_pointees`]]
|
||||
[def __less_pointees_t__ [link boost.less_pointees_t `less_pointees_t`]]
|
||||
[def __less_than_comparable1__ [link sec:arithmetic `less_than_comparable1`]]
|
||||
[def __less_than_comparable2__ [link sec:arithmetic `less_than_comparable2`]]
|
||||
[def __multiplicative1__ [link sec:arithmetic `multiplicative1`]]
|
||||
[def __multiplicative2__ [link sec:arithmetic `multiplicative2`]]
|
||||
[def __operator_eq__eq__ [link sec:arithmetic `operator==`]]
|
||||
[def __operator_gt__ [link sec:arithmetic `operator_gt_`]]
|
||||
[def __operator_gt__eq__ [link sec:arithmetic `operator>`]]
|
||||
[def __operator_lt__ [link sec:arithmetic `operator<`]]
|
||||
[def __operator_lt__eq__ [link sec:arithmetic `operator<=`]]
|
||||
[def __operator_lt__lt__ [link sec:arithmetic `operator<<`]]
|
||||
[def __operator_not__eq__ [link sec:arithmetic `operator!=`]]
|
||||
[def __operators2__ [link sec:arithmetic `operators2`]]
|
||||
[def __operators__ [link sec:arithmetic `operators`]]
|
||||
[def __operators_lt_T__ [link sec:arithmetic `operators<T,T>`]]
|
||||
[def __ordered_euclidean_ring_operators1__ [link sec:arithmetic `ordered_euclidean_ring_operators1`]]
|
||||
[def __ordered_euclidean_ring_operators2__ [link sec:arithmetic `ordered_euclidean_ring_operators2`]]
|
||||
[def __ordered_euclidian_ring_operators1__ [link sec:arithmetic `ordered_euclidian_ring_operators1`]]
|
||||
[def __ordered_euclidian_ring_operators2__ [link sec:arithmetic `ordered_euclidian_ring_operators2`]]
|
||||
[def __ordered_field_operators1__ [link sec:arithmetic `ordered_field_operators1`]]
|
||||
[def __ordered_field_operators2__ [link sec:arithmetic `ordered_field_operators2`]]
|
||||
[def __ordered_ring_operators1__ [link sec:arithmetic `ordered_ring_operators1`]]
|
||||
[def __ordered_ring_operators2__ [link sec:arithmetic `ordered_ring_operators2`]]
|
||||
[def __output_iteratable__ [link sec:arithmetic `output_iteratable`]]
|
||||
[def __output_iterator_helper__ [link sec:arithmetic `output_iterator_helper`]]
|
||||
[def __partially_ordered1__ [link sec:arithmetic `partially_ordered1`]]
|
||||
[def __partially_ordered2__ [link sec:arithmetic `partially_ordered2`]]
|
||||
[def __random_access_iteratable__ [link sec:arithmetic `random_access_iteratable`]]
|
||||
[def __random_access_iterator_helper__ [link sec:arithmetic `random_access_iterator_helper`]]
|
||||
[def __result_of__ [link boost.result_of `result_of`]]
|
||||
[def __ring_operators1__ [link sec:arithmetic `ring_operators1`]]
|
||||
[def __ring_operators2__ [link sec:arithmetic `ring_operators2`]]
|
||||
[def __shiftable1__ [link sec:arithmetic `shiftable1`]]
|
||||
[def __shiftable2__ [link sec:arithmetic `shiftable2`]]
|
||||
[def __string_ref__ [link boost.basic_string_view `string_ref`]]
|
||||
[def __string_view__ [link boost.basic_string_view `string_view`]]
|
||||
[def __swap__ [link sec:arithmetic `swap`]]
|
||||
[def __totally_ordered1__ [link sec:arithmetic `totally_ordered1`]]
|
||||
[def __totally_ordered2__ [link sec:arithmetic `totally_ordered2`]]
|
||||
[def __tr1_result_of__ [link boost.tr1_result_of `tr1_result_of`]]
|
||||
[def __typed_in_place_factory_base__ [link boost.typed_in_place_factory_base `typed_in_place_factory_base`]]
|
||||
[def __u16string_ref__ [link boost.basic_string_view `u16string_ref`]]
|
||||
[def __u16string_view__ [link boost.basic_string_view `u16string_view`]]
|
||||
[def __u32string_ref__ [link boost.basic_string_view `u32string_ref`]]
|
||||
[def __u32string_view__ [link boost.basic_string_view `u32string_view`]]
|
||||
[def __unit_steppable__ [link sec:arithmetic `unit_steppable`]]
|
||||
[def __value_initialized__ [link boost.value_initialized `value_initialized`]]
|
||||
[def __wstring_ref__ [link boost.basic_string_view `wstring_ref`]]
|
||||
[def __wstring_view__ [link boost.basic_string_view `wstring_view`]]
|
||||
|
||||
[/ std:: types ]
|
||||
|
||||
[def __assert__ [@https://en.cppreference.com/w/cpp/error/assert `assert`]]
|
||||
[def __decltype__ [@https://en.cppreference.com/w/cpp/language/decltype `decltype`]]
|
||||
[def __initializer_list__ [@https://en.cppreference.com/w/cpp/utility/initializer_list `std::initializer_list`]]
|
||||
[def __nullptr__ [@https://en.cppreference.com/w/cpp/language/nullptr `nullptr`]]
|
||||
[def __std_addressof__ [@https://en.cppreference.com/w/cpp/memory/addressof `std::addressof`]]
|
||||
[def __std_array__ [@https://en.cppreference.com/w/cpp/container/array `std::array`]]
|
||||
[def __std_basic_string__ [@https://en.cppreference.com/w/cpp/string/basic_string `std::basic_string`]]
|
||||
[def __std_basic_string_view__ [@https://en.cppreference.com/w/cpp/string/basic_string_view `std::basic_string_view`]]
|
||||
[def __std_binder1st__ [@https://en.cppreference.com/w/cpp/utility/functional/binder12 `std::binder1st`]]
|
||||
[def __std_complex__ [@https://en.cppreference.com/w/cpp/numeric/complex `std::complex`]]
|
||||
[def __std_declval__ [@https://en.cppreference.com/w/cpp/utility/declval `std::declval`]]
|
||||
[def __std_enable_if__ [@https://en.cppreference.com/w/cpp/types/enable_if `std::enable_if`]]
|
||||
[def __std_enable_if_t__ [@https://en.cppreference.com/w/cpp/types/enable_if `std::enable_if_t`]]
|
||||
[def __std_fill__ [@https://en.cppreference.com/w/cpp/algorithm/fill `std::fill`]]
|
||||
[def __std_hash__ [@https://en.cppreference.com/w/cpp/utility/hash `std::hash`]]
|
||||
[def __std_initializer_list__ [@https://en.cppreference.com/w/cpp/utility/initializer_list `std::initializer_list`]]
|
||||
[def __std_is_nothrow_constructible__ [@https://en.cppreference.com/w/cpp/types/is_constructible `std::is_nothrow_constructible`]]
|
||||
[def __std_make_pair__ [@https://en.cppreference.com/w/cpp/utility/pair/make_pair `std::make_pair`]]
|
||||
[def __std_memory_resource__ [@https://en.cppreference.com/w/cpp/memory/memory_resource `std::pmr::memory_resource`]]
|
||||
[def __std_memset__ [@https://en.cppreference.com/w/cpp/string/byte/memset `std::memset`]]
|
||||
[def __std_next__ [@https://en.cppreference.com/w/cpp/iterator/next `std::next`]]
|
||||
[def __std_nullptr_t__ [@https://en.cppreference.com/w/cpp/types/nullptr_t `std::nullptr_t`]]
|
||||
[def __std_ostream__ [@https://en.cppreference.com/w/cpp/io/basic_ostream `std::ostream`]]
|
||||
[def __std_ostream__ [@https://en.cppreference.com/w/cpp/io/basic_ostream `__std_ostream__`]]
|
||||
[def __std_pair__ [@https://en.cppreference.com/w/cpp/utility/pair `std::pair`]]
|
||||
[def __std_polymorphic_allocator__ [@https://en.cppreference.com/w/cpp/memory/polymorphic_allocator `std::pmr::polymorphic_allocator`]]
|
||||
[def __std_prev__ [@https://en.cppreference.com/w/cpp/iterator/prev `std::prev`]]
|
||||
[def __std_ptrdiff_t__ [@https://en.cppreference.com/w/cpp/types/ptrdiff_t `std::ptrdiff_t`]]
|
||||
[def __std_remove__ [@https://en.cppreference.com/w/cpp/algorithm/remove `std::remove`]]
|
||||
[def __std_result_of__ [@https://en.cppreference.com/w/cpp/types/result_of `std::result_of`]]
|
||||
[def __std_sort__ [@https://en.cppreference.com/w/cpp/algorithm/sort `std::sort`]]
|
||||
[def __std_streambuf__ [@https://en.cppreference.com/w/cpp/header/streambuf `std::streambuf`]]
|
||||
[def __std_string__ [@https://en.cppreference.com/w/cpp/string/basic_string `std::string`]]
|
||||
[def __std_string_view__ [@https://en.cppreference.com/w/cpp/string/basic_string_view `std::string_view`]]
|
||||
[def __std_unary_function__ [@https://en.cppreference.com/w/cpp/utility/functional/unary_function `std::unary_function`]]
|
||||
[def __std_unordered_map__ [@https://en.cppreference.com/w/cpp/container/unordered_map `std::unordered_map`]]
|
||||
[def __std_uses_allocator__ [@https://en.cppreference.com/w/cpp/memory/uses_allocator `std::uses_allocator`]]
|
||||
[def __std_vector__ [@https://en.cppreference.com/w/cpp/container/vector `std::vector`]]
|
||||
|
||||
[/ Dingbats ]
|
||||
|
||||
[def __good__ [role green \u2714]]
|
||||
[def __bad__ [role red \u2718]]
|
||||
|
||||
[/-----------------------------------------------------------------------------]
|
||||
|
||||
[include overview.qbk]
|
||||
|
||||
[include utilities.qbk]
|
||||
|
||||
[include other.qbk]
|
||||
|
||||
[#sec:reference]
|
||||
[section:ref Quick Reference]
|
||||
|
||||
[/ Reference table ]
|
||||
[xinclude quickref.xml]
|
||||
|
||||
[/ Generated reference files ]
|
||||
[/ [include reference.qbk] ]
|
||||
|
||||
[/ Generated index ]
|
||||
[/ [xinclude index.xml] ]
|
||||
|
||||
[endsect]
|
2008
doc/operators.qbk
Normal file
2008
doc/operators.qbk
Normal file
File diff suppressed because it is too large
Load Diff
29
doc/other.qbk
Normal file
29
doc/other.qbk
Normal file
@ -0,0 +1,29 @@
|
||||
[/
|
||||
Copyright (c) 2021 Alan de Freitas (alandefreitas@gmail.com)
|
||||
|
||||
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)
|
||||
|
||||
Official repository: https://github.com/boostorg/utility
|
||||
]
|
||||
|
||||
[section:utilities More Utilities]
|
||||
|
||||
Some utilities have been moved from Boost.Utilities to more appropriate Boost libraries:
|
||||
|
||||
# Moved to [@boost:/libs/core/index.html Boost.Core]
|
||||
# [@boost:/libs/core/doc/html/core/addressof.html addressof]
|
||||
# [@boost:/libs/core/doc/html/core/checked_delete.html checked_delete]
|
||||
# [@boost:/libs/core/doc/html/core/enable_if.html enable_if]
|
||||
# [@boost:/libs/core/doc/html/core/noncopyable.html noncopyable]
|
||||
# Moved to [@boost:/libs/type_traits/index.html Boost.TypeTraits]
|
||||
# [@boost:/libs/type_traits/doc/html/boost_typetraits/reference/declval.html declval]
|
||||
# Moved to [@boost:/libs/iterator/index.html Boost.Iterator]
|
||||
# [@boost:/libs/iterator/doc/generator_iterator.htm generator iterator adaptors]
|
||||
# [@boost:/libs/iterator/doc/html/iterator/algorithms/next_prior.html next/prior]
|
||||
# Moved to [@boost:/libs/io/index.html Boost.IO]
|
||||
# [@boost:/libs/io/doc/html/io.html ostream_string]
|
||||
# Moved to [@boost:/libs/throw_exception/index.html Boost.ThrowException]
|
||||
# [@boost:/libs/throw_exception/doc/html/throw_exception.html#using_boost_throw_exception throw_exception]
|
||||
|
||||
[endsect]
|
46
doc/overview.qbk
Normal file
46
doc/overview.qbk
Normal file
@ -0,0 +1,46 @@
|
||||
[/
|
||||
Copyright (c) 2021 Alan de Freitas (alandefreitas@gmail.com)
|
||||
|
||||
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)
|
||||
|
||||
Official repository: https://github.com/boostorg/utility
|
||||
]
|
||||
|
||||
[section Overview]
|
||||
[block'''<?dbhtml stop-chunking?>''']
|
||||
|
||||
Boost.Utility is a collection of small, useful, and general-purpose components for language support.
|
||||
|
||||
Over time,
|
||||
|
||||
* several components have been moved to more appropriate Boost libraries and
|
||||
* many of these components had variants accepted into the C++ standard
|
||||
|
||||
When the component has moved to another Boost library, Boost.Utility headers still lead to the appropriate headers
|
||||
in other libraries.
|
||||
|
||||
[table:id Components
|
||||
[[Boost.Utility] [Moved to Boost] [C++ Standard variant]]
|
||||
[[[@boost:/libs/core/doc/html/core/addressof.html `addressof`]] [[@boost:/libs/core/index.html Boost.Core]] [C++11 __std_addressof__]]
|
||||
[[__base_from_member__] [] []]
|
||||
[[__BOOST_BINARY__] [] [C++14 [@https://en.cppreference.com/w/cpp/language/integer_literal Binary integer literal]]]
|
||||
[[__call_traits__] [] []]
|
||||
[[[@boost:/libs/core/doc/html/core/checked_delete.html `checked_delete`]] [[@boost:/libs/core/index.html Boost.Core]] []]
|
||||
[[__compressed_pair__] [] []]
|
||||
[[[@boost:/libs/type_traits/doc/html/boost_typetraits/reference/declval.html `declval`]] [[@boost:/libs/type_traits/index.html Boost.TypeTraits]] [C++11 __std_declval__]]
|
||||
[[[@boost:/libs/core/doc/html/core/enable_if.html `enable_if`]] [[@boost:/libs/core/index.html Boost.Core]] [C++11 __std_enable_if__]]
|
||||
[[[@boost:/libs/iterator/doc/generator_iterator.htm generator iterator adaptors]] [[@boost:/libs/iterator/index.html Boost.Iterator]] []]
|
||||
[[__in_place_factory__] [] []]
|
||||
[[[@boost:/libs/iterator/index.html `iterator_adaptors`]] [[@boost:/libs/iterator/index.html Boost.Iterator]] []]
|
||||
[[[@boost:/libs/iterator/doc/html/iterator/algorithms/next_prior.html `next` / `prior`]] [[@boost:/libs/iterator/index.html Boost.Iterator]] [C++11 __std_next__ / __std_prev__]]
|
||||
[[[@boost:/libs/core/doc/html/core/noncopyable.html `noncopyable`]] [[@boost:/libs/core/index.html Boost.Core]] []]
|
||||
[[[link sec:operators `operators`]] [] []]
|
||||
[[[@boost:/libs/io/doc/html/io.html `ostream_string`]] [[@boost:/libs/io/index.html Boost.IO]] []]
|
||||
[[__result_of__] [] [C++11 __std_result_of__]]
|
||||
[[__string_view__] [] [C++17 __std_string_view__]]
|
||||
[[[@boost:/libs/throw_exception/doc/html/throw_exception.html#using_boost_throw_exception `throw_exception`]] [[@boost:/libs/throw_exception/index.html Boost.ThrowException]] []]
|
||||
[[[link sec:value_init `value_init`]] [] [C++11 [@https://en.cppreference.com/w/cpp/language/list_initialization List initialization]]]
|
||||
]
|
||||
|
||||
[endsect]
|
497
doc/quickref.xml
Normal file
497
doc/quickref.xml
Normal file
@ -0,0 +1,497 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "../../../tools/boostbook/dtd/boostbook.dtd">
|
||||
|
||||
<!--
|
||||
Copyright (c) 2021, Alan Freitas
|
||||
|
||||
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
|
||||
-->
|
||||
|
||||
<!-- See also https://tdg.docbook.org/tdg/5.1/ -->
|
||||
|
||||
<!-- Doxygen reference -->
|
||||
<informaltable frame="all">
|
||||
<tgroup cols="4">
|
||||
<colspec colname="a"/>
|
||||
<colspec colname="b"/>
|
||||
<colspec colname="c"/>
|
||||
<colspec colname="d"/>
|
||||
|
||||
<thead>
|
||||
<row>
|
||||
<entry valign="center" namest="a" nameend="a">
|
||||
<bridgehead renderas="sect2">Base from Member</bridgehead>
|
||||
</entry>
|
||||
<entry valign="center" namest="b" nameend="b">
|
||||
<bridgehead renderas="sect2">Call Traits</bridgehead>
|
||||
</entry>
|
||||
<entry valign="center" namest="c" nameend="c">
|
||||
<bridgehead renderas="sect2">Compressed Pair</bridgehead>
|
||||
</entry>
|
||||
<entry valign="center" namest="d" nameend="d">
|
||||
<bridgehead renderas="sect2">In-place Factory</bridgehead>
|
||||
</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<!-- base_from_member -->
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Classes</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="boost.base_from_member">base_from_member</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
|
||||
<!-- call_traits -->
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Type Traits</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="boost.call_traits">call_traits</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="boost.call_traits">call_traits<T&></link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="boost.call_traits">call_traits<T[N]>
|
||||
</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="boost.call_traits">call_traits<const
|
||||
T[N]>
|
||||
</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
|
||||
<!-- compressed_pair -->
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Classes</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="boost.compressed_pair">compressed_pair</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
|
||||
<bridgehead renderas="sect3">Functions</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="header.boost.detail.compressed_pair_hpp">swap</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
|
||||
<!-- in_place_factory -->
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Classes</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="boost.in_place_factory_base">in_place_factory_base</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="boost.typed_in_place_factory_base">typed_in_place_factory_base
|
||||
</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
|
||||
<tgroup cols="5">
|
||||
<colspec colname="a"/>
|
||||
<colspec colname="b"/>
|
||||
<colspec colname="c"/>
|
||||
<colspec colname="d"/>
|
||||
<colspec colname="e"/>
|
||||
|
||||
<thead>
|
||||
<row>
|
||||
<entry valign="center" namest="a" nameend="e">
|
||||
<bridgehead renderas="sect2">Operators</bridgehead>
|
||||
</entry>
|
||||
</row>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<row>
|
||||
<entry valign="top">
|
||||
<!-- 13 classes per cell -->
|
||||
<bridgehead renderas="sect3">Classes (1 of 5)</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">additive1</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">additive2</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">arithmetic1</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">arithmetic2</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">bidirectional_iteratable</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">
|
||||
bidirectional_iterator_helper
|
||||
</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">bitwise1</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">bitwise2</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">decrementable</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">dereferenceable</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">equality_comparable1</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">equality_comparable2</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">equivalent1</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Classes (2 of 5)</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">equivalent2</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">euclidean_ring_operators1
|
||||
</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">euclidean_ring_operators2
|
||||
</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">field_operators1</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">field_operators2</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">forward_iteratable</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">forward_iterator_helper</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">incrementable</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">indexable</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">input_iteratable</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">input_iterator_helper</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">integer_arithmetic1</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">integer_arithmetic2</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Classes (3 of 5)</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">integer_multiplicative1</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">integer_multiplicative2</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">is_chained_base</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">less_than_comparable1</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">less_than_comparable2</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">multiplicative1</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">multiplicative2</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">operators</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">operators2</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">operators<T,T></link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">
|
||||
ordered_euclidean_ring_operators1
|
||||
</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">
|
||||
ordered_euclidean_ring_operators2
|
||||
</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">
|
||||
ordered_euclidian_ring_operators1
|
||||
</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Classes (4 of 5)</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">
|
||||
ordered_euclidian_ring_operators2
|
||||
</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">ordered_field_operators1</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">ordered_field_operators2</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">ordered_ring_operators1</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">ordered_ring_operators2</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">output_iteratable</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">output_iterator_helper</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">partially_ordered1</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">partially_ordered2</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">random_access_iteratable</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">
|
||||
random_access_iterator_helper
|
||||
</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">ring_operators1</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">ring_operators2</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Classes (5 of 5)</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">shiftable1</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">shiftable2</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">totally_ordered1</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">totally_ordered2</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">unit_steppable</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
<bridgehead renderas="sect3">Type Traits</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">is_chained_base</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
|
||||
<tgroup cols="5">
|
||||
<colspec colname="a"/>
|
||||
<colspec colname="b"/>
|
||||
<colspec colname="c"/>
|
||||
<colspec colname="d"/>
|
||||
<colspec colname="e"/>
|
||||
|
||||
<thead>
|
||||
<row>
|
||||
<entry valign="center" namest="a" nameend="a">
|
||||
<bridgehead renderas="sect2">Result of</bridgehead>
|
||||
</entry>
|
||||
<entry valign="center" namest="b" nameend="d">
|
||||
<bridgehead renderas="sect2">String View</bridgehead>
|
||||
</entry>
|
||||
<entry valign="center" namest="e" nameend="e">
|
||||
<bridgehead renderas="sect2">Value Init</bridgehead>
|
||||
</entry>
|
||||
</row>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<row>
|
||||
<!-- result_of -->
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Type Traits</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="boost.result_of">result_of</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="boost.tr1_result_of">tr1_result_of</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
|
||||
<!-- string_view -->
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Aliases</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="boost.basic_string_view">string_view</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="boost.basic_string_view">u16string_ref</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="boost.basic_string_view">u16string_view</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="boost.basic_string_view">u32string_ref</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="boost.basic_string_view">u32string_view</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="boost.basic_string_view">wstring_ref</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="boost.basic_string_view">wstring_view</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="boost.basic_string_view">string_ref</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Classes</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="boost.basic_string_view">basic_string_ref</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="boost.basic_string_view">basic_string_view</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
<bridgehead renderas="sect3">Functions</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="boost.hash_range">hash_range</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="boost.hash_value">hash_value</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Operators</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="header.boost.utility.string_view_hpp">operator==</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="header.boost.utility.string_view_hpp">operator!=</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="header.boost.utility.string_view_hpp">operator<</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="header.boost.utility.string_view_hpp">operator<=</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="header.boost.utility.string_view_hpp">operator></link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="header.boost.utility.string_view_hpp">operator>=</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="header.boost.utility.string_view_hpp">operator<<</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
|
||||
<!-- value_init -->
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Classes</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="boost.initialized">initialized</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="boost.initialized_value_t">initialized_value_t</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="boost.value_initialized">value_initialized</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
<bridgehead renderas="sect3">Functions</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="header.boost.utility.value_init_hpp">get</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="header.boost.utility.value_init_hpp">swap</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
<bridgehead renderas="sect3">Constants</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="boost.initialized_value">initialized_value</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
421
doc/result_of.qbk
Normal file
421
doc/result_of.qbk
Normal file
@ -0,0 +1,421 @@
|
||||
[/
|
||||
/ Copyright (c) 2012 Marshall Clow
|
||||
/ Copyright (c) 2021, Alan Freitas
|
||||
/
|
||||
/ 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 Result of]
|
||||
[/===============]
|
||||
|
||||
[section Introduction]
|
||||
|
||||
The class template __result_of__ helps determine the type of a
|
||||
call expression. For example, given an lvalue `f` of type `F`
|
||||
and lvalues `t1`,`t2`, ..., `tN` of types `T1`, `T2`, ..., `TN`,
|
||||
respectively, the type __result_of__`<F(T1, T2, ..., TN)>::type` defines
|
||||
the result type of the expression `f(t1, t2, ...,tN)`.
|
||||
|
||||
This implementation permits the type `F` to be a function pointer,
|
||||
function reference, member function pointer, or class type. By default,
|
||||
N may be any value between 0 and 16. To change the upper limit, define
|
||||
the macro `BOOST_RESULT_OF_NUM_ARGS` to the maximum value for N. Class
|
||||
template __result_of__ resides in the header
|
||||
[@../../../../boost/utility/result_of.hpp `<boost/utility/result_of.hpp>`].
|
||||
|
||||
If your compiler's support for __decltype__ is adequate, __result_of__
|
||||
automatically uses it to deduce the type of the call expression, in
|
||||
which case __result_of__`<F(T1, T2, ..., TN)>::type` names the type
|
||||
__decltype__`(boost::declval<F>()(boost::declval<T1>(),
|
||||
boost::declval<T2>(), ..., boost::declval<TN>()))`, as in the
|
||||
following example.
|
||||
|
||||
```
|
||||
struct functor {
|
||||
template<class T>
|
||||
T operator()(T x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
||||
typedef __boost_result_of__<functor(int)>::type type; // type is int
|
||||
```
|
||||
|
||||
You can test whether __result_of__ is using __decltype__ by checking if
|
||||
the macro `BOOST_RESULT_OF_USE_DECLTYPE` is defined after
|
||||
including `result_of.hpp`. You can also force __result_of__ to use
|
||||
__decltype__ by defining `BOOST_RESULT_OF_USE_DECLTYPE` prior
|
||||
to including `result_of.hpp`.
|
||||
|
||||
If __decltype__ is not used, then automatic result type deduction of function
|
||||
objects is not possible. Instead, __result_of__ uses the following protocol
|
||||
to allow the programmer to specify a type. When `F` is a class type with a
|
||||
member type `result_type`, `result_of<F(T1, T2, ..., TN)>::type` is
|
||||
`F::result_type`. When `F` does not contain `result_type`,
|
||||
`result_of<F(T1, T2, ..., TN)>::type` is
|
||||
`F::result<F(T1, T2, ..., TN)>::type` when
|
||||
`N > 0` or `void` when `N = 0`.
|
||||
|
||||
Note that it is the responsibility of the programmer to ensure that
|
||||
function objects accurately advertise their result
|
||||
type via this protocol, as in the following example.
|
||||
|
||||
```
|
||||
struct functor {
|
||||
template <class> struct result;
|
||||
|
||||
template<class F, class T>
|
||||
struct result<F(T)> {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
T operator()(T x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
||||
typedef __boost_result_of__<functor(int)>::type type; // type is int
|
||||
```
|
||||
|
||||
Since __decltype__ is a language feature standardized in C++11, if you are
|
||||
writing a function object to be used with __result_of__, for maximum
|
||||
portability, you might consider following the above protocol
|
||||
even if your compiler has proper __decltype__ support.
|
||||
|
||||
If you wish to continue to use the protocol on compilers that
|
||||
support __decltype__, there are two options:
|
||||
|
||||
* You can use __boost_tr1_result_of__, which is also defined in
|
||||
[@../../../boost/utility/result_of.hpp `<boost/utility/result_of.hpp>`].
|
||||
|
||||
* Alternatively, you can define the macro `BOOST_RESULT_OF_USE_TR1`,
|
||||
which causes __result_of__ to use the protocol described above instead
|
||||
of __decltype__. If you choose to follow the protocol, take care to
|
||||
ensure that the `result_type` and `result<>` members accurately
|
||||
represent the return type of `operator()` given a call expression.
|
||||
|
||||
Additionally, __boost_result_of__ provides a third mode of operation,
|
||||
which some users may find convenient. When
|
||||
`BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK` is defined,
|
||||
__boost_result_of__ behaves as follows. If the function object has a member
|
||||
type `result_type` or member template `result<>`, then __boost_result_of__
|
||||
will use the TR1 protocol.
|
||||
|
||||
Otherwise, __boost_result_of__ will use __decltype__. Using TR1 with
|
||||
a __decltype__ fallback may workaround certain problems at the cost of portability.
|
||||
For example:
|
||||
|
||||
* Deficient compiler: If your code requires __boost_result_of__ to work
|
||||
with incomplete return types but your compiler's __decltype__ implementation
|
||||
does not support incomplete return types, then you can use the TR1 protocol
|
||||
as a workaround. Support for incomplete return types was added late in the
|
||||
C++11 standardization process
|
||||
(see [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3276.pdf N3276])
|
||||
and is not implemented by some compilers.
|
||||
|
||||
* Deficient legacy code: If your existing TR1 function object advertises a different type than
|
||||
the actual result type deduced by __decltype__, then using TR1 with a __decltype__ fallback
|
||||
will allow you to work with both your existing TR1 function objects and new C++11
|
||||
function object. This situation could occur if your legacy function objects
|
||||
misused the TR1 protocol. See the documentation on known [link sec:result_of_tr1_diff differences]
|
||||
between __boost_result_of__ and TR1.
|
||||
|
||||
* [#BOOST_NO_RESULT_OF] This implementation of __result_of__ requires class template
|
||||
partial specialization, the ability to parse function types properly, and support
|
||||
for SFINAE. If __result_of__ is not supported by your compiler, including the header
|
||||
[@../../../boost/utility/result_of.hpp `<boost/utility/result_of.hpp>`] will define
|
||||
the macro `BOOST_NO_RESULT_OF`.
|
||||
|
||||
For additional information about __result_of__, see the C++ Library
|
||||
Technical Report, [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf N1836],
|
||||
or, for motivation and design rationale, the __result_of__
|
||||
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1454.html proposal].
|
||||
|
||||
[endsect]
|
||||
|
||||
[#sec:result_of_guidelines]
|
||||
[section Usage guidelines for __boost_result_of__]
|
||||
|
||||
The following are general suggestions about when and how to use __boost_result_of__.
|
||||
|
||||
# If you are targeting C++11 and are not concerned about portability to
|
||||
non-compliant compilers or previous versions of the standard, then use
|
||||
`__std_result_of__`. If `__std_result_of__` meets your needs, then
|
||||
there's no reason to stop using it.
|
||||
|
||||
# If you are targeting C++11 but may port your code to legacy compilers
|
||||
at some time in the future, then use __boost_result_of__ with __decltype__.
|
||||
When __decltype__ is used __boost_result_of__ and `__std_result_of__` are usually
|
||||
interchangeable. See the documentation on known [link sec:result_of_cxx11_diff differences]
|
||||
between __boost_result_of__ and C++11 __std_result_of__.
|
||||
|
||||
# If compiler portability is required, use __boost_result_of__ with the TR1 protocol
|
||||
|
||||
Regardless of how you configure __boost_result_of__, it is
|
||||
important to bear in mind that the return type of a
|
||||
function may change depending on its arguments, and
|
||||
additionally, the return type of a member function may
|
||||
change depending on the cv-qualification of the
|
||||
object. __boost_result_of__ must be passed
|
||||
the appropriately cv-qualified types in order to
|
||||
deduce the corresponding return type.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
struct functor {
|
||||
int& operator()(int);
|
||||
int const& operator()(int) const;
|
||||
|
||||
float& operator()(float&);
|
||||
float const& operator()(float const&);
|
||||
};
|
||||
|
||||
typedef __boost_result_of__<
|
||||
functor(int)
|
||||
>::type type1; // type1 is int &
|
||||
|
||||
typedef __boost_result_of__<
|
||||
const functor(int)
|
||||
>::type type2; // type2 is int const &
|
||||
|
||||
typedef __boost_result_of__<
|
||||
functor(float&)
|
||||
>::type type3; // type3 is float &
|
||||
|
||||
typedef __boost_result_of__<
|
||||
functor(float const&)
|
||||
>::type type4; // type4 is float const &
|
||||
```
|
||||
|
||||
[endsect]
|
||||
|
||||
[#sec:result_of_tr1_protocol_guidelines]
|
||||
[section Usage guidelines for the TR1 result_of protocol]
|
||||
|
||||
On compliant C++11 compilers, __boost_result_of__ can
|
||||
use __decltype__ to deduce the type of any
|
||||
call expression, including calls to function
|
||||
objects. However, on pre-C++11 compilers or on
|
||||
compilers without adequate decltype support,
|
||||
additional scaffolding is needed from function
|
||||
objects as described above. The following are
|
||||
suggestions about how to use the TR1 protocol.
|
||||
|
||||
* When the return type does not depend on the
|
||||
argument types or the cv-qualification of the
|
||||
function object, simply
|
||||
define `result_type`. There is no need
|
||||
to use the `result` template unless the
|
||||
return type varies.</li>
|
||||
|
||||
* Use the protocol specified type when defining
|
||||
function prototypes. This can help ensure the
|
||||
actual return type does not get out of sync with
|
||||
the protocol specification. For example:
|
||||
|
||||
```
|
||||
struct functor {
|
||||
typedef int result_type;
|
||||
result_type operator()(int);
|
||||
};
|
||||
```
|
||||
|
||||
* Always specify the `result` specialization near the corresponding
|
||||
`operator()` overload. This can make it easier to keep the specializations
|
||||
in sync with the overloads. For example:
|
||||
|
||||
```
|
||||
struct functor {
|
||||
template<class> struct result;
|
||||
|
||||
template<class F>
|
||||
struct result<F(int)> {
|
||||
typedef int& type;
|
||||
};
|
||||
result<functor(int)>::type operator()(int);
|
||||
|
||||
template<class F>
|
||||
struct result<const F(int)> {
|
||||
typedef int const& type;
|
||||
};
|
||||
result<const functor(int)>::type operator()(int) const;
|
||||
};
|
||||
```
|
||||
|
||||
* Use type transformations to simplify
|
||||
the `result` template specialization. For
|
||||
example, the following uses [@../type_traits/doc/html/index.html Boost.TypeTraits]
|
||||
to specialize the `result` template for
|
||||
a single `operator()` that can be called on
|
||||
both a const and non-const function object with
|
||||
either an lvalue or rvalue argument.
|
||||
|
||||
```
|
||||
struct functor {
|
||||
template<class> struct result;
|
||||
|
||||
template<class F, class T>
|
||||
struct result<F(T)>
|
||||
: boost::remove_cv<
|
||||
typename boost::remove_reference<T>::type
|
||||
>
|
||||
{};
|
||||
|
||||
template<class T>
|
||||
T operator()(T const& x) const;
|
||||
};
|
||||
```
|
||||
|
||||
[endsect]
|
||||
|
||||
[#sec:result_of_tr1_diff]
|
||||
[section Known differences between __boost_result_of__ and __boost_tr1_result_of__]
|
||||
|
||||
When using __decltype__, __boost_result_of__ ignores the TR1 protocol and instead deduces the
|
||||
return type of function objects directly via __decltype__. In most situations, users
|
||||
will not notice a difference, so long as they use the protocol correctly. The following are situations in
|
||||
which the type deduced by __boost_result_of__ is known to differ depending on whether
|
||||
__decltype__ or the TR1 protocol is used.
|
||||
|
||||
TR1 protocol misusage: When using the TR1 protocol, __boost_result_of__ cannot
|
||||
detect whether the actual type of a call to a function object is the same as the
|
||||
type specified by the protocol, which allows for the possibility of inadvertent
|
||||
mismatches between the specified type and the actual type. When using __decltype__,
|
||||
these subtle bugs may result in compilation errors. For example:
|
||||
|
||||
```
|
||||
struct functor {
|
||||
typedef short result_type;
|
||||
int operator()(short);
|
||||
};
|
||||
|
||||
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<__boost_result_of__<functor(short)>::type, int>::value
|
||||
));
|
||||
|
||||
#else
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<__boost_result_of__<functor(short)>::type, short>::value
|
||||
));
|
||||
|
||||
#endif
|
||||
```
|
||||
|
||||
Note that the user can force __boost_result_of__ to use the TR1
|
||||
protocol even on platforms that support __decltype__ by
|
||||
defining `BOOST_RESULT_OF_USE_TR1`.
|
||||
|
||||
Nullary function objects: When using the TR1 protocol, __boost_result_of__
|
||||
cannot always deduce the type of calls to nullary function objects, in which case the
|
||||
type defaults to void. When using __decltype__, __boost_result_of__ always gives the
|
||||
actual type of the call expression. For example:
|
||||
|
||||
```
|
||||
struct functor {
|
||||
template<class> struct result {
|
||||
typedef int type;
|
||||
};
|
||||
int operator()();
|
||||
};
|
||||
|
||||
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<__boost_result_of__<functor()>::type, int>::value
|
||||
));
|
||||
|
||||
#else
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<__boost_result_of__<functor()>::type, void>::value
|
||||
));
|
||||
|
||||
#endif
|
||||
```
|
||||
|
||||
Note that there are some workarounds for the nullary function problem.
|
||||
So long as the return type does not vary, `result_type` can always be used to
|
||||
specify the return type regardless of arity. If the return type does vary,
|
||||
then the user can specialize __boost_result_of__ itself for nullary calls.
|
||||
|
||||
Non-class prvalues and cv-qualification: When using the TR1 protocol, __boost_result_of__ will
|
||||
report the cv-qualified type specified by `result_type` or the `result` template regardless of
|
||||
the actual cv-qualification of the call expression. When using __decltype__, __boost_result_of__
|
||||
will report the actual type of the call expression, which is not cv-qualified when the expression
|
||||
is a non-class prvalue. For example:
|
||||
|
||||
```
|
||||
struct functor {
|
||||
template<class> struct result;
|
||||
template<class F, class T> struct result<F(const T)> {
|
||||
typedef const T type;
|
||||
};
|
||||
|
||||
const short operator()(const short);
|
||||
int const & operator()(int const &);
|
||||
};
|
||||
|
||||
// Non-prvalue call expressions work the same with or without decltype.
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<
|
||||
__boost_result_of__<functor(int const &)>::type,
|
||||
int const &
|
||||
::value
|
||||
));
|
||||
|
||||
// Non-class prvalue call expressions are not actually cv-qualified,
|
||||
// but only the decltype-based result_of reports this accurately.
|
||||
|
||||
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<
|
||||
__boost_result_of__<functor(const short)>::type,
|
||||
short
|
||||
::value
|
||||
));
|
||||
|
||||
#else
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<
|
||||
__boost_result_of__<functor(const short)>::type,
|
||||
const short
|
||||
::value
|
||||
));
|
||||
|
||||
#endif
|
||||
```
|
||||
|
||||
[endsect]
|
||||
|
||||
[#sec:result_of_cxx11_diff]
|
||||
[section Known differences between __boost_result_of__ and C++11 result_of]
|
||||
|
||||
When using __decltype__, __boost_result_of__ implements most of the C++11 __std_result_of__
|
||||
specification. One known exception is that __boost_result_of__ does not implement the
|
||||
requirements regarding pointers to member data.
|
||||
|
||||
[endsect]
|
||||
|
||||
[/===============]
|
||||
[xinclude tmp/result_of_reference.xml]
|
||||
[/===============]
|
||||
|
||||
[section Acknowledgments]
|
||||
|
||||
Created by Doug Gregor. Contributions from Daniel Walker, Eric Niebler, Michel Morin and others.
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
209
doc/string_view.qbk
Normal file
209
doc/string_view.qbk
Normal file
@ -0,0 +1,209 @@
|
||||
[/
|
||||
/ Copyright (c) 2012 Marshall Clow
|
||||
/ Copyright (c) 2021, Alan Freitas
|
||||
/
|
||||
/ 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 String View]
|
||||
[/===============]
|
||||
|
||||
[section Introduction]
|
||||
|
||||
The class __boost_string_view__ and other classes derived from __basic_string_view__ represent references to strings or substrings. When you are parsing/processing strings from some external source, frequently you want to pass a piece of text to a procedure for specialized processing. Before __std_string_view__, the canonical way to do this used to be a __std_string__, but that has certain drawbacks:
|
||||
|
||||
1) If you are processing a buffer of text (say a HTTP response or the contents of a file), then you have to create the string from the text you want to pass, which involves memory allocation and copying of data.
|
||||
|
||||
2) If a routine receives a constant __std_string__ and wants to pass a portion of that string to another routine, then it must create a new string of that substring.
|
||||
|
||||
3) If a routine receives a constant __std_string__ and wants to return a portion of the string, then it must create a new string to return.
|
||||
|
||||
__boost_string_view__ is designed to solve these efficiency problems. A __boost_string_view__ is a read-only reference to a contiguous sequence of characters, and provides much of the functionality of __std_string__. A __boost_string_view__ is cheap to create, copy and pass by value, because it does not actually own the storage that it points to.
|
||||
|
||||
A __boost_string_view__ is implemented as a small struct that contains a pointer to the start of the character `data` and a `count`. A __boost_string_view__ is cheap to create and cheap to copy.
|
||||
|
||||
__boost_string_view__ acts as a container; it includes all the methods that you would expect in a container, including iteration support, `operator[]`, `at` and `size`. It can be used with any of the iterator-based algorithms in the STL - as long as you do not need to change the underlying data. For example, __std_sort__ and __std_remove__ will not work.
|
||||
|
||||
Besides generic container functionality, __boost_string_view__ provides a subset of the interface of __std_string__. This makes it easy to replace parameters of type `const __std_string__ &` with __boost_string_view__. Like __std_string__, __boost_string_view__ has a static member variable named `npos` to denote the result of failed searches, and to mean "the end".
|
||||
|
||||
[caution Because a __boost_string_view__ does not own the data that it refers to, it introduces lifetime issues into code that uses it. The programmer must ensure that the data that a __string_view__ refers to exists as long as the __string_view__ does.]
|
||||
|
||||
[note
|
||||
|
||||
Boost.Utility also includes the class __string_ref__:
|
||||
|
||||
- __string_ref__ is the initial implementation of Jeffrey Yaskin's [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html N3442:
|
||||
string_ref: a non-owning reference to a string].
|
||||
|
||||
- __string_view__ is an updated implementation to reflect the Library Fundamentals TS [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html N4480: \[string.view\]].
|
||||
|
||||
Please prefer __string_view__ / __basic_string_view__ over __string_ref__ / __basic_string_ref__:
|
||||
|
||||
- The __basic_string_view__ class better matches __std_basic_string_view__.
|
||||
|
||||
- __basic_string_view__ has WAY more constexpr support.
|
||||
|
||||
- Code that uses __basic_string_ref__ should continue to work.
|
||||
|
||||
- Not much code depends on __basic_string_ref__ anymore.
|
||||
|
||||
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[/===============]
|
||||
[section Examples]
|
||||
[/===============]
|
||||
|
||||
Integrating __string_view__ into your code is fairly simple. Wherever you pass a `const __std_string__ &` or __std_string__ as a parameter, that's a candidate for passing a __boost_string_view__.
|
||||
|
||||
```
|
||||
__std_string__ extract_part ( const __std_string__ &bar ) {
|
||||
return bar.substr ( 2, 3 );
|
||||
}
|
||||
|
||||
if ( extract_part ( "ABCDEFG" ).front() == 'C' ) { /* do something */ }
|
||||
```
|
||||
|
||||
Let's figure out what happens in this contrived example.
|
||||
|
||||
* First, a temporary string is created from the string literal `"ABCDEFG"`, and it is passed (by reference) to the routine `extract_part`.
|
||||
* Then a second string is created in the call `__std_string__::substr` and returned to `extract_part` (this copy may be elided by RVO).
|
||||
* Then `extract_part` returns that string back to the caller (again this copy may be elided).
|
||||
* The first temporary string is deallocated, and `front` is called on the second string, and then it is deallocated as well.
|
||||
|
||||
Two __std_string__ s are created, and two copy operations. That is potentially four memory allocations and deallocations, and the associated copying of data.
|
||||
|
||||
Now let's look at the same code with __string_view__:
|
||||
|
||||
```
|
||||
__boost_string_view__ extract_part ( __boost_string_view__ bar ) {
|
||||
return bar.substr ( 2, 3 );
|
||||
}
|
||||
|
||||
if ( extract_part ( "ABCDEFG" ).front() == "C" ) { /* do something */ }
|
||||
```
|
||||
|
||||
No memory allocations. No copying of character data. No changes to the code other than the types. There are two __string_view__ s created, and two __string_view__ s copied, but those are cheap operations.
|
||||
[endsect]
|
||||
|
||||
[/=================]
|
||||
[section:reference Synopsis]
|
||||
[/=================]
|
||||
|
||||
The header file [@../../../../boost/utility/string_view.hpp `<boost/utility/string_view.hpp>`] defines a template __boost_basic_string_view__, and four specializations __string_view__, __wstring_view__, __u16string_view__, __u32string_view__ - for `char` / `wchar_t` / `char16_t` / `char32_t`.
|
||||
|
||||
`#include <boost/utility/string_view.hpp>`
|
||||
|
||||
Construction and copying:
|
||||
|
||||
```
|
||||
constexpr basic_string_view (); // Constructs an empty string_view
|
||||
constexpr basic_string_view(const charT* str); // Constructs from a NULL-terminated string
|
||||
constexpr basic_string_view(const charT* str, size_type len); // Constructs from a pointer, length pair
|
||||
template<typename Allocator>
|
||||
basic_string_view(const __std_basic_string__<charT, traits, Allocator>& str); // Constructs from a std::string
|
||||
basic_string_view (const basic_string_view &rhs);
|
||||
basic_string_view& operator=(const basic_string_view &rhs);
|
||||
```
|
||||
|
||||
__string_view__ does not define a move constructor nor a move-assignment operator because copying a __string_view__ is just a cheap as moving one.
|
||||
|
||||
Basic container-like functions:
|
||||
|
||||
```
|
||||
constexpr size_type size() const ;
|
||||
constexpr size_type length() const ;
|
||||
constexpr size_type max_size() const ;
|
||||
constexpr bool empty() const ;
|
||||
|
||||
// All iterators are const_iterators
|
||||
constexpr const_iterator begin() const ;
|
||||
constexpr const_iterator cbegin() const ;
|
||||
constexpr const_iterator end() const ;
|
||||
constexpr const_iterator cend() const ;
|
||||
const_reverse_iterator rbegin() const ;
|
||||
const_reverse_iterator crbegin() const ;
|
||||
const_reverse_iterator rend() const ;
|
||||
const_reverse_iterator crend() const ;
|
||||
```
|
||||
|
||||
Access to the individual elements (all of which are const):
|
||||
|
||||
```
|
||||
constexpr const charT& operator[](size_type pos) const ;
|
||||
const charT& at(size_t pos) const ;
|
||||
constexpr const charT& front() const ;
|
||||
constexpr const charT& back() const ;
|
||||
constexpr const charT* data() const ;
|
||||
```
|
||||
|
||||
Modifying the __string_view__ (but not the underlying data):
|
||||
|
||||
```
|
||||
void clear();
|
||||
void remove_prefix(size_type n);
|
||||
void remove_suffix(size_type n);
|
||||
```
|
||||
|
||||
Searching:
|
||||
|
||||
```
|
||||
size_type find(basic_string_view s) const ;
|
||||
size_type find(charT c) const ;
|
||||
size_type rfind(basic_string_view s) const ;
|
||||
size_type rfind(charT c) const ;
|
||||
size_type find_first_of(charT c) const ;
|
||||
size_type find_last_of (charT c) const ;
|
||||
|
||||
size_type find_first_of(basic_string_view s) const ;
|
||||
size_type find_last_of(basic_string_view s) const ;
|
||||
size_type find_first_not_of(basic_string_view s) const ;
|
||||
size_type find_first_not_of(charT c) const ;
|
||||
size_type find_last_not_of(basic_string_view s) const ;
|
||||
size_type find_last_not_of(charT c) const ;
|
||||
```
|
||||
|
||||
String-like operations:
|
||||
|
||||
```
|
||||
constexpr basic_string_view substr(size_type pos, size_type n=npos) const ; // Creates a new string_view
|
||||
bool starts_with(charT c) const ;
|
||||
bool starts_with(basic_string_view x) const ;
|
||||
bool ends_with(charT c) const ;
|
||||
bool ends_with(basic_string_view x) const ;
|
||||
```
|
||||
[endsect]
|
||||
|
||||
|
||||
[/===============]
|
||||
[section History]
|
||||
[/===============]
|
||||
|
||||
[h5 boost 1.71]
|
||||
* Glen Fernandes updated the implementation of the stream insertion operator to
|
||||
write directly to the `basic_streambuf` and refactored that functionality into
|
||||
a common utility.
|
||||
|
||||
[h5 boost 1.53]
|
||||
* Introduced
|
||||
|
||||
[endsect]
|
||||
|
||||
[/===============]
|
||||
[xinclude tmp/string_view_reference.xml]
|
||||
[/===============]
|
||||
|
||||
[/===============]
|
||||
[section Acknowledgments]
|
||||
[/===============]
|
||||
|
||||
Author: Clow, Marshall
|
||||
|
||||
Copyright 2012 Marshall Clow
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
2
doc/tmp/.gitignore
vendored
Normal file
2
doc/tmp/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*.qbk
|
||||
*.xml
|
32
doc/utilities.qbk
Normal file
32
doc/utilities.qbk
Normal file
@ -0,0 +1,32 @@
|
||||
[/
|
||||
Copyright (c) 2021 Alan de Freitas (alandefreitas@gmail.com)
|
||||
|
||||
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)
|
||||
|
||||
Official repository: https://github.com/boostorg/utility
|
||||
]
|
||||
|
||||
[section:utilities Utilities]
|
||||
|
||||
The entire contents of Boost.Utility are in `namespace boost`.
|
||||
|
||||
[warning
|
||||
|
||||
Direct use of the header [@../../../../boost/utility.hpp `<boost/utility.hpp>`] is discouraged and it will be deprecated.
|
||||
|
||||
Please include the headers relative to individual components instead.
|
||||
|
||||
]
|
||||
|
||||
[include base_from_member.qbk]
|
||||
[include BOOST_BINARY.qbk]
|
||||
[include call_traits.qbk]
|
||||
[include compressed_pair.qbk]
|
||||
[include in_place_factory.qbk]
|
||||
[include operators.qbk]
|
||||
[include result_of.qbk]
|
||||
[include string_view.qbk]
|
||||
[include value_init.qbk]
|
||||
|
||||
[endsect]
|
584
doc/value_init.qbk
Normal file
584
doc/value_init.qbk
Normal file
@ -0,0 +1,584 @@
|
||||
[/
|
||||
/ Copyright (c) 2012 Marshall Clow
|
||||
/ Copyright (c) 2021, Alan Freitas
|
||||
/
|
||||
/ 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)
|
||||
/]
|
||||
|
||||
[/===============]
|
||||
[#sec:value_init]
|
||||
[section Value Init]
|
||||
|
||||
[/===============]
|
||||
|
||||
[section Introduction]
|
||||
|
||||
Constructing and initializing objects in a generic way is difficult in
|
||||
C++. The problem is that there are several different rules that apply
|
||||
for initialization. Depending on the type, the value of a newly constructed
|
||||
object can be zero-initialized (logically 0), default-constructed (using
|
||||
the default constructor), or indeterminate. When writing generic code,
|
||||
this problem must be addressed. The template __value_initialized__ provides
|
||||
a solution with consistent syntax for value initialization of scalar,
|
||||
union and class types. Moreover, __value_initialized__ offers a workaround to various
|
||||
compiler issues regarding value-initialization.
|
||||
|
||||
Furthermore, a `const` object __initialized_value__ is provided,
|
||||
to avoid repeating the type name when retrieving the value from a
|
||||
`__value_initialized__<T>` object.
|
||||
|
||||
There are various ways to initialize a variable, in C++. The following
|
||||
declarations all ['may] have a local variable initialized to its default
|
||||
value:
|
||||
|
||||
```
|
||||
T1 var1;
|
||||
T2 var2 = 0;
|
||||
T3 var3 = {};
|
||||
T4 var4 = T4();
|
||||
```
|
||||
|
||||
Unfortunately, whether or not any of those declarations correctly
|
||||
initialize the variable very much depends on its type. The first
|
||||
declaration is valid for any __DefaultConstructible__ type by definition.
|
||||
|
||||
However, it does not always do an initialization. It correctly initializes
|
||||
the variable when it's an instance of a class, and the author of the class
|
||||
has provided a proper default constructor. On the other hand, the value of
|
||||
`var1` is ['indeterminate] when its type is an arithmetic type, like `int`,
|
||||
`float`, or `char`.
|
||||
|
||||
An arithmetic variable is of course initialized properly by the second declaration,
|
||||
`T2 var2 = 0`. But this initialization form will not usually work for a
|
||||
class type, unless the class was especially written to support being
|
||||
initialized that way.
|
||||
|
||||
The third form, `T3 var3 = {}`, initializes an aggregate, typically a "C-style"
|
||||
`struct` or a "C-style" array. However, at the time this library was developed,
|
||||
the syntax did not allow for a class that has an explicitly declared constructor.
|
||||
|
||||
The fourth form is the most generic form of them, as it can be used to initialize
|
||||
arithmetic types, class types, aggregates, pointers, and other types.
|
||||
The declaration, `T4 var4 = T4()`, should be read as follows: First a temporary
|
||||
object is created, by `T4()`. This object is [link sec:valueinit value-initialized].
|
||||
Next the temporary object is copied to the named variable, `var4`. Afterwards,
|
||||
the temporary is destroyed. While the copying and the destruction are likely to
|
||||
be optimized away, C++ still requires the type `T4` to be __CopyConstructible__.
|
||||
So `T4` needs to be ['both] __DefaultConstructible__ ['and] __CopyConstructible__.
|
||||
|
||||
A class may not be CopyConstructible, for example because it may have a
|
||||
private and undefined copy constructor, or because it may be derived from
|
||||
`boost::noncopyable`. Scott Meyers \[[link sec:references 2]\] explains why a
|
||||
class would be defined like that.
|
||||
|
||||
There is another, less obvious disadvantage to the fourth form, `T4 var4 = T4()`:
|
||||
It suffers from various [link sec:compiler_issues compiler issues], causing
|
||||
a variable to be left uninitialized in some compiler specific cases.
|
||||
|
||||
The template __value_initialized__ offers a generic way to initialize
|
||||
an object, like `T4 var4 = T4()`, but without requiring its type
|
||||
to be __CopyConstructible__. And it offers a workaround to those compiler issues
|
||||
regarding value-initialization as well. It allows getting an initialized
|
||||
variable of any type; it ['only] requires the type to be __DefaultConstructible__.
|
||||
A properly ['value-initialized] object of type `T` is constructed by the following
|
||||
declaration:
|
||||
|
||||
```
|
||||
value_initialized<T> var;
|
||||
```
|
||||
|
||||
The template __initialized__ offers both value-initialization and direct-initialization.
|
||||
It is especially useful as a data member type, allowing the very same object
|
||||
to be either direct-initialized or value-initialized.
|
||||
|
||||
The `const` object __initialized_value__ allows value-initializing a variable as follows:
|
||||
|
||||
```
|
||||
T var = initialized_value;
|
||||
```
|
||||
|
||||
This form of initialization is semantically equivalent to `T4 var4 = T4()`,
|
||||
but robust against the aforementioned compiler issues.
|
||||
|
||||
[endsect]
|
||||
|
||||
[#sec:details]
|
||||
[section Details]
|
||||
|
||||
The C++ standard \[[link sec:references 3]\] contains the definitions
|
||||
of `zero-initialization` and `default-initialization`. Informally, zero-initialization
|
||||
means that the object is given the initial value `0` converted to the type and
|
||||
default-initialization means that [@https://en.cppreference.com/w/cpp/named_req/PODType POD] \[[link sec:references 4]\] types are zero-initialized,
|
||||
while non-POD class types are initialized with their corresponding default constructors.
|
||||
|
||||
A ['declaration] can contain an ['initializer], which specifies the
|
||||
object's initial value. The initializer can be just '()', which states that
|
||||
the object shall be value-initialized (but see below). However, if a ['declaration]
|
||||
has no ['initializer] and it is of a non-`const`, non-`static` POD type, the
|
||||
initial value is indeterminate: (see [sect]8.5, \[dcl.init\], for the
|
||||
accurate definitions).
|
||||
|
||||
```
|
||||
int x; // no initializer. x value is indeterminate.
|
||||
__std_string__ s; // no initializer, s is default-constructed.
|
||||
|
||||
int y = int();
|
||||
// y is initialized using copy-initialization
|
||||
// but the temporary uses an empty set of parentheses as the initializer,
|
||||
// so it is default-constructed.
|
||||
// A default constructed POD type is zero-initialized,
|
||||
// therefore, y == 0.
|
||||
|
||||
void foo ( __std_string__ ) ;
|
||||
foo ( __std_string__() ) ;
|
||||
// the temporary string is default constructed
|
||||
// as indicated by the initializer ()
|
||||
```
|
||||
|
||||
[#sec:valueinit]
|
||||
[h5 value-initialization]
|
||||
|
||||
The first [@http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html Technical
|
||||
Corrigendum for the C++ Standard] (TC1), whose draft was released to the public in
|
||||
November 2001, introduced [@http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#178 Core
|
||||
Issue 178], among many other issues.
|
||||
|
||||
That issue introduced the new concept of `value-initialization`, and also fixed the
|
||||
wording for zero-initialization. Informally, value-initialization is similar to
|
||||
default-initialization with the exception that in some cases non-static data members
|
||||
and base class sub-objects are also value-initialized.
|
||||
|
||||
The difference is that an object that is value-initialized will not have, or at least
|
||||
is less likely to have, indeterminate values for data members and base class sub-objects;
|
||||
unlike the case of an object default constructed (see Core Issue 178 for a
|
||||
normative description).
|
||||
|
||||
In order to specify value-initialization of an object we need to use the
|
||||
empty-set initializer: `()`.
|
||||
|
||||
As before, a declaration with no initializer specifies default-initialization,
|
||||
and a declaration with a non-empty initializer specifies copy (`=xxx`) or
|
||||
direct (`xxx`) initialization.
|
||||
|
||||
```
|
||||
template<class T> void eat(T);
|
||||
|
||||
int x ; // indeterminate initial value.
|
||||
|
||||
__std_string__ s; // default-initialized.
|
||||
|
||||
eat ( int() ) ; // value-initialized
|
||||
|
||||
eat ( __std_string__() ) ; // value-initialized
|
||||
```
|
||||
|
||||
[#sec:valueinitsyn]
|
||||
[h5 value-initialization syntax]
|
||||
|
||||
Value initialization is specified using `()`. However, the empty set of
|
||||
parentheses is not permitted by the syntax of initializers because it is
|
||||
parsed as the declaration of a function taking no arguments:
|
||||
|
||||
```
|
||||
int x() ; // declares function int(*)()
|
||||
```
|
||||
|
||||
Thus, the empty `()` must be put in some other initialization context.
|
||||
|
||||
One alternative is to use copy-initialization syntax:
|
||||
|
||||
```
|
||||
int x = int();
|
||||
```
|
||||
|
||||
This works perfectly fine for POD types. But for non-POD class types,
|
||||
copy-initialization searches for a suitable constructor, which could be,
|
||||
for instance, the copy-constructor. It also searches for a suitable conversion
|
||||
sequence but this does not apply in this context.
|
||||
|
||||
For an arbitrary unknown type, using this syntax may not have the
|
||||
value-initialization effect intended because we don't know if a copy
|
||||
from a default constructed object is exactly the same as a default
|
||||
constructed object, and the compiler is allowed, in
|
||||
some cases, but never required to, optimize the copy away.
|
||||
|
||||
One possible generic solution is to use value-initialization of a non static
|
||||
data member:
|
||||
|
||||
```
|
||||
template<class T>
|
||||
struct W
|
||||
{
|
||||
// value-initialization of 'data' here.
|
||||
W() : data() {}
|
||||
|
||||
T data;
|
||||
};
|
||||
|
||||
W<int> w;
|
||||
// w.data is value-initialized for any type.
|
||||
```
|
||||
|
||||
This is the solution as it was supplied by earlier versions of the
|
||||
`__value_initialized__<T>` template class. Unfortunately this approach
|
||||
suffered from various compiler issues.
|
||||
|
||||
[#sec:compiler_issues]
|
||||
[h5 Compiler issues]
|
||||
|
||||
Various compilers have not yet fully implemented value-initialization.
|
||||
So when an object should be ['value-initialized] according to the C++ Standard,
|
||||
it ['may] in practice still be left uninitialized, because of those
|
||||
compiler issues. It is hard to make a general statement on what those issues
|
||||
are like, because they depend on the compiler you are using, its version number,
|
||||
and the type of object you would like to have value-initialized.
|
||||
|
||||
All compilers we have tested so far support value-initialization for arithmetic types properly.
|
||||
However, various compilers may leave some types of ['aggregates] uninitialized, when they
|
||||
should be value-initialized. Value-initialization of objects of a pointer-to-member type may also
|
||||
go wrong on various compilers.
|
||||
|
||||
At the moment of writing, May 2010, the following reported issues regarding
|
||||
value-initialization are still there in current compiler releases:
|
||||
|
||||
|
||||
|
||||
* [@https://connect.microsoft.com/VisualStudio/feedback/details/100744 Microsoft Visual Studio Feedback ID 100744, Value-initialization in new-expression]: Reported by Pavel Kuznetsov (MetaCommunications Engineering), 2005.
|
||||
* [@http://connect.microsoft.com/VisualStudio/feedback/details/484295 Microsoft Visual Studio Feedback ID 484295, VC++ does not value-initialize members of derived classes without user-declared constructor] Reported by Sylvester Hesp, 2009.
|
||||
* [@https://connect.microsoft.com/VisualStudio/feedback/details/499606 Microsoft Visual Studio Feedback ID 499606, Presence of copy constructor breaks member class initialization] Reported by Alex Vakulenko, 2009
|
||||
* [@http://qc.embarcadero.com/wc/qcmain.aspx?d=83751 Embarcadero/C++Builder Report 83751, Value-initialization: arrays should have each element value-initialized] Reported by Niels Dekker (LKEB), 2010.
|
||||
* [@http://qc.embarcadero.com/wc/qcmain.aspx?d=83851 Embarcadero/C++Builder Report 83851, Value-initialized temporary triggers internal backend error C1798] Reported by Niels Dekker, 2010.
|
||||
* [@http://qc.embarcadero.com/wc/qcmain.aspx?d=84279 Embarcadero/C++Builder Report 84279, Internal compiler error (F1004), value-initializing member function pointer by "new T()"] Reported by Niels Dekker, 2010
|
||||
* Sun CR 6947016, Sun 5.10 may fail to value-initialize an object of a non-POD aggregate. Reported to Steve Clamage by Niels Dekker, 2010.
|
||||
* IBM's XL V10.1 and V11.1 may fail to value-initialize a temporary of a non-POD aggregate. Reported to Michael Wong by Niels Dekker, 2010.
|
||||
* Intel support issue 589832, Attempt to value-initialize pointer-to-member triggers internal error on Intel 11.1. Reported by John Maddock, 2010.
|
||||
|
||||
Note that all known GCC issues regarding value-initialization are fixed with GCC version 4.4, including
|
||||
[@http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30111 GCC Bug 30111]. Clang also has completely implemented
|
||||
value-initialization, as far as we know, now that [@http://llvm.org/bugs/show_bug.cgi?id=7139 Clang Bug 7139]
|
||||
is fixed.
|
||||
|
||||
New versions of __value_initialized__ (Boost release version 1.35 or higher) offer a workaround to these
|
||||
issues: __value_initialized__ may now clear its internal data, prior to constructing the object that it
|
||||
contains. It will do so for those compilers that need to have such a workaround, based on the
|
||||
[@boost:/libs/config/doc/html/boost_config/boost_macro_reference.html#boost_config.boost_macro_reference.macros_that_describe_defects
|
||||
compiler defect macro] `BOOST_NO_COMPLETE_VALUE_INITIALIZATION`.
|
||||
|
||||
[endsect]
|
||||
|
||||
[#sec:types]
|
||||
[section Types and objects]
|
||||
|
||||
[#sec:val_init]
|
||||
[section `template class value_initialized<T>`]
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
|
||||
template<class T>
|
||||
class __value_initialized__
|
||||
{
|
||||
|
||||
public :
|
||||
|
||||
__value_initialized__() : x() {}
|
||||
|
||||
operator T const &() const { return x ; }
|
||||
|
||||
operator T&() { return x ; }
|
||||
|
||||
T const &data() const { return x ; }
|
||||
|
||||
T& data() { return x ; }
|
||||
|
||||
void swap( __value_initialized__& );
|
||||
|
||||
private :
|
||||
|
||||
[unspecified] x ;
|
||||
|
||||
} ;
|
||||
|
||||
template<class T>
|
||||
|
||||
T const& get ( __value_initialized__<T> const& x )
|
||||
{
|
||||
return x.data();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T& get ( __value_initialized__<T>& x )
|
||||
{
|
||||
return x.data();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void swap ( __value_initialized__<T>& lhs, __value_initialized__<T>& rhs )
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
```
|
||||
|
||||
An object of this template class is a `T`-wrapper convertible to `'T&'` whose
|
||||
wrapped object (data member of type `T`) is [link sec:valueinit value-initialized] upon default-initialization
|
||||
of this wrapper class:
|
||||
|
||||
```
|
||||
int zero = 0;
|
||||
__value_initialized__<int> x;
|
||||
assert( x == zero ) ;
|
||||
|
||||
__std_string__ def;
|
||||
__value_initialized__< __std_string__ > y;
|
||||
assert( y == def ) ;
|
||||
```
|
||||
|
||||
The purpose of this wrapper is to provide a consistent syntax for value initialization
|
||||
of scalar, union and class types (POD and non-POD) since the correct syntax for value
|
||||
initialization varies (see [link sec:valueinitsyn value-initialization syntax]).
|
||||
|
||||
The wrapped object can be accessed either through the conversion operator
|
||||
`T&`, the member function `data()`, or the non-member function `get()`:
|
||||
|
||||
```
|
||||
void watch(int);
|
||||
|
||||
__value_initialized__<int> x;
|
||||
|
||||
watch(x) ; // operator T& used.
|
||||
watch(x.data());
|
||||
watch( get(x) ) // function get() used
|
||||
```
|
||||
|
||||
Both `const` and non-`const` objects can be wrapped. Mutable objects can be
|
||||
modified directly from within the wrapper but constant objects cannot:
|
||||
|
||||
When `T` is a __Swappable__ type, `__value_initialized__<T>`
|
||||
is swappable as well, by calling its `swap` member function
|
||||
as well as by calling `boost::swap`.
|
||||
|
||||
```
|
||||
__value_initialized__<int> x;
|
||||
static_cast<int&>(x) = 1 ; // OK
|
||||
get(x) = 1 ; // OK
|
||||
|
||||
__value_initialized__<int const> y ;
|
||||
static_cast<int&>(y) = 1 ; // ERROR: cannot cast to int&
|
||||
static_cast<int const&>(y) = 1 ; // ERROR: cannot modify a const value
|
||||
get(y) = 1 ; // ERROR: cannot modify a const value
|
||||
```
|
||||
|
||||
[warning
|
||||
|
||||
The __value_initialized__ implementation of Boost version 1.40.0 and older
|
||||
allowed ['non-const] access to the wrapped object, from a constant wrapper,
|
||||
both by its conversion operator and its `data()` member function.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
__value_initialized__<int> const x_c;
|
||||
int& xr = x_c ; // OK, conversion to int& available even though x_c is itself const.
|
||||
xr = 2 ;
|
||||
```
|
||||
|
||||
The reason for this obscure behavior was that some compilers did not accept the following valid code:
|
||||
|
||||
```
|
||||
struct X
|
||||
{
|
||||
operator int&() ;
|
||||
operator int const&() const ;
|
||||
};
|
||||
X x ;
|
||||
(x == 1) ; // ERROR HERE!
|
||||
```
|
||||
|
||||
The current version of __value_initialized__ no longer has this obscure behavior.
|
||||
As compilers nowadays widely support overloading the conversion operator by having a `const`
|
||||
and a `non-const` version, we have decided to fix the issue accordingly. So the current version
|
||||
supports the idea of logical constness.
|
||||
|
||||
]
|
||||
|
||||
[h5 Recommended practice: The non-member get() idiom]
|
||||
|
||||
The obscure behavior of being able to modify a non-`const`
|
||||
wrapped object from within a constant wrapper (as was supported by previous
|
||||
versions of __value_initialized__) can be avoided if access to the wrapped object
|
||||
is always performed with the `get()` idiom:
|
||||
|
||||
```
|
||||
value_initialized<int> x;
|
||||
get(x) = 1; // OK
|
||||
value_initialized<int const> cx;
|
||||
get(x) = 1; // ERROR: Cannot modify a const object
|
||||
|
||||
value_initialized<int> const x_c;
|
||||
get(x_c) = 1; // ERROR: Cannot modify a const object
|
||||
|
||||
value_initialized<int const> const cx_c;
|
||||
get(cx_c) = 1; // ERROR: Cannot modify a const object
|
||||
```
|
||||
|
||||
[endsect]
|
||||
|
||||
[#sec:initialized]
|
||||
[section `template class initialized<T>`]
|
||||
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
|
||||
template<class T>
|
||||
class __initialized__
|
||||
{
|
||||
|
||||
public :
|
||||
|
||||
__initialized__() : x() {}
|
||||
|
||||
explicit __initialized__(T const & arg) : x(arg) {}
|
||||
|
||||
operator T const &() const;
|
||||
|
||||
operator T&();
|
||||
|
||||
T const &data() const;
|
||||
|
||||
T& data();
|
||||
|
||||
void swap( __initialized__& );
|
||||
|
||||
private :
|
||||
|
||||
[unspecified] x ;
|
||||
|
||||
};
|
||||
|
||||
template<class T>
|
||||
T const& get ( __initialized__<T> const& x );
|
||||
|
||||
template<class T>
|
||||
T& get ( __initialized__<T>& x );
|
||||
|
||||
template<class T>
|
||||
void swap ( __initialized__<T>& lhs, __initialized__<T>& rhs );
|
||||
|
||||
} // namespace boost
|
||||
```
|
||||
|
||||
The template class `boost::__initialized__<T>` supports both value-initialization
|
||||
and direct-initialization, so its interface is a superset of the interface
|
||||
of `__value_initialized__<T>`: Its default-constructor value-initializes the
|
||||
wrapped object just like the default-constructor of `__value_initialized__<T>`,
|
||||
but `boost::__initialized__<T>` also offers an extra `explicit`
|
||||
constructor, which direct-initializes the wrapped object by the specified value.
|
||||
|
||||
`__initialized__<T>` is especially useful when the wrapped
|
||||
object must be either value-initialized or direct-initialized, depending on
|
||||
runtime conditions. For example, `__initialized__<T>` could
|
||||
hold the value of a data member that may be value-initialized by some
|
||||
constructors, and direct-initialized by others.
|
||||
|
||||
On the other hand, if it is known beforehand that the
|
||||
object must ['always] be value-initialized, `__value_initialized__<T>`
|
||||
may be preferable. And if the object must always be
|
||||
direct-initialized, none of the two wrappers really needs to be used.
|
||||
|
||||
[endsect]
|
||||
|
||||
[#sec:initialized_value]
|
||||
[section `initialized_value`]
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
class __initialized_value_t__
|
||||
{
|
||||
public :
|
||||
template <class T> operator T() const ;
|
||||
};
|
||||
|
||||
__initialized_value_t__ const initialized_value = {} ;
|
||||
|
||||
} // namespace boost
|
||||
```
|
||||
|
||||
__initialized_value__ provides a convenient way to get
|
||||
an initialized value: its conversion operator provides an appropriate
|
||||
['value-initialized] object for any __CopyConstructible__ type.
|
||||
|
||||
Suppose you need to have an initialized variable of type `T`.
|
||||
You could do it as follows:
|
||||
|
||||
```
|
||||
T var = T();
|
||||
```
|
||||
|
||||
But as mentioned before, this form suffers from various compiler issues.
|
||||
The template __value_initialized__ offers a workaround:
|
||||
|
||||
```
|
||||
T var = get( __value_initialized__<T>() );
|
||||
```
|
||||
|
||||
Unfortunately both forms repeat the type name, which
|
||||
is rather short now (`T`), but could of course be
|
||||
more like `Namespace::Template<Arg>::Type`.
|
||||
|
||||
Instead, one could use __initialized_value__ as follows:
|
||||
|
||||
```
|
||||
T var = __initialized_value__;
|
||||
```
|
||||
|
||||
[endsect]
|
||||
[endsect]
|
||||
|
||||
[#sec:references]
|
||||
[section References]
|
||||
|
||||
# Bjarne Stroustrup, Gabriel Dos Reis, and J. Stephen Adamczyk wrote various papers,
|
||||
proposing to extend the support for brace-enclosed ['initializer lists]
|
||||
in C++. This [@https://en.cppreference.com/w/cpp/language/list_initialization feature] has
|
||||
now been available since C++11. This would allow a variable `var` of any __DefaultConstructible__ type
|
||||
`T` to be ['value-initialized] by doing `T var = {}`. The papers are listed at Bjarne's web page,
|
||||
[@http://www.research.att.com/~bs/WG21.html My C++ Standards committee papers].
|
||||
|
||||
# Scott Meyers, Effective C++, Third Edition, item 6, ['Explicitly disallow the use of
|
||||
compiler-generated functions you do not want], [@http://www.aristeia.com/books.html Scott Meyers: Books and CDs]
|
||||
|
||||
# The C++ Standard, Second edition (2003), ISO/IEC 14882:2003
|
||||
|
||||
# POD stands for [@https://en.cppreference.com/w/cpp/named_req/PODType "Plain Old Data"]
|
||||
|
||||
[endsect]
|
||||
|
||||
[/===============]
|
||||
[xinclude tmp/value_init_reference.xml]
|
||||
[/===============]
|
||||
|
||||
[#sec:acknowledgements]
|
||||
[section Acknowledgements]
|
||||
|
||||
__value_initialized__ was developed by Fernando Cacciola, with help and suggestions
|
||||
from David Abrahams and Darin Adler.
|
||||
|
||||
Special thanks to Bjorn Karlsson who carefully edited and completed this documentation.
|
||||
|
||||
__value_initialized__ was reimplemented by Fernando Cacciola and Niels Dekker
|
||||
for Boost release version 1.35 (2008), offering a workaround to various compiler issues.
|
||||
|
||||
`boost::__initialized__` was very much inspired by feedback from Edward Diener and Jeffrey Hellrung.
|
||||
|
||||
__initialized_value__ was written by Niels Dekker, and added to Boost release version 1.36 (2008).
|
||||
|
||||
Developed by [@mailto:fernando_cacciola@hotmail.com Fernando Cacciola]. The latest version of
|
||||
this file can be found at [@http://www.boost.org www.boost.org].
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
19
enable_if.html
Normal file
19
enable_if.html
Normal file
@ -0,0 +1,19 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Boost.Utility</title>
|
||||
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="../core/doc/html/core/enable_if.html">../core/doc/html/core/enable_if.html</a>
|
||||
<hr>
|
||||
<tt>
|
||||
Boost.Utility<br>
|
||||
<br>
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||
<br>
|
||||
</tt>
|
||||
</body>
|
||||
</html>
|
@ -1,273 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<title>Filter Iterator Adaptor Documentation</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
|
||||
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)"
|
||||
align="center" width="277" height="86">
|
||||
|
||||
<h1>Filter Iterator Adaptor</h1>
|
||||
|
||||
Defined in header
|
||||
<a href="../../boost/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a>
|
||||
|
||||
|
||||
<p>
|
||||
The filter iterator adaptor creates a view of an iterator range in
|
||||
which some elements of the range are skipped over. A <a
|
||||
href="http://www.sgi.com/tech/stl/Predicate.html">Predicate</a>
|
||||
function object controls which elements are skipped. When the
|
||||
predicate is applied to an element, if it returns <tt>true</tt> then
|
||||
the element is retained and if it returns <tt>false</tt> then the
|
||||
element is skipped over.
|
||||
|
||||
|
||||
<h2>Synopsis</h2>
|
||||
|
||||
<pre>
|
||||
namespace boost {
|
||||
template <class Predicate, class BaseIterator, ...>
|
||||
class filter_iterator_generator;
|
||||
|
||||
template <class Predicate, class BaseIterator>
|
||||
typename filter_iterator_generator<Predicate, BaseIterator>::type
|
||||
make_filter_iterator(BaseIterator first, BaseIterator last, const Predicate& p = Predicate());
|
||||
}
|
||||
</pre>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2><a name="filter_iterator_generator">The Filter Iterator Type
|
||||
Generator</a></h2>
|
||||
|
||||
The class <tt>filter_iterator_generator</tt> is a helper class whose
|
||||
purpose is to construct a filter iterator type. The template
|
||||
parameters for this class are the <tt>Predicate</tt> function object
|
||||
type and the <tt>BaseIterator</tt> type that is being wrapped. In
|
||||
most cases the associated types for the wrapped iterator can be
|
||||
deduced from <tt>std::iterator_traits</tt>, but in some situations the
|
||||
user may want to override these types, so there are also template
|
||||
parameters for each of the iterator's associated types.
|
||||
|
||||
<pre>
|
||||
template <class Predicate, class BaseIterator,
|
||||
class Value, class Reference, class Pointer, class Category, class Distance>
|
||||
class filter_iterator_generator
|
||||
{
|
||||
public:
|
||||
typedef <tt><a href="./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a><...></tt> type; // the resulting filter iterator type
|
||||
}
|
||||
</pre>
|
||||
|
||||
|
||||
<h3>Example</h3>
|
||||
|
||||
The following example uses filter iterator to print out all the
|
||||
positive integers in an array.
|
||||
|
||||
<pre>
|
||||
struct is_positive_number {
|
||||
bool operator()(int x) { return 0 < x; }
|
||||
};
|
||||
int main() {
|
||||
int numbers[] = { 0, -1, 4, -3, 5, 8, -2 };
|
||||
const int N = sizeof(numbers)/sizeof(int);
|
||||
|
||||
typedef boost::filter_iterator_generator<is_positive_number, int*, int>::type FilterIter;
|
||||
is_positive_number predicate;
|
||||
FilterIter::policies_type policies(predicate, numbers + N);
|
||||
FilterIter filter_iter_first(numbers, policies);
|
||||
FilterIter filter_iter_last(numbers + N, policies);
|
||||
|
||||
std::copy(filter_iter_first, filter_iter_last, std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
The output is:
|
||||
<pre>
|
||||
4 5 8
|
||||
</pre>
|
||||
|
||||
|
||||
<h3>Template Parameters</h3>
|
||||
|
||||
<Table border>
|
||||
<TR>
|
||||
<TH>Parameter</TH><TH>Description</TH>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD><a href="http://www.sgi.com/tech/stl/Predicate.html"><tt>Predicate</tt></a></TD>
|
||||
<TD>The function object that determines which elements are retained and which elements are skipped.
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD><tt>BaseIterator</tt></TD>
|
||||
<TD>The iterator type being wrapped. This type must at least be a model
|
||||
of the <a href="http://www.sgi.com/tech/stl/InputIterator">InputIterator</a> concept.</TD>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD><tt>Value</tt></TD>
|
||||
<TD>The <tt>value_type</tt> of the resulting iterator,
|
||||
unless const. If const, a conforming compiler strips constness for the
|
||||
<tt>value_type</tt>. Typically the default for this parameter is the
|
||||
appropriate type<a href="#1">[1]</a>.<br> <b>Default:</b>
|
||||
<tt>std::iterator_traits<BaseIterator>::value_type</TD>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD><tt>Reference</tt></TD>
|
||||
<TD>The <tt>reference</tt> type of the resulting iterator, and in
|
||||
particular, the result type of <tt>operator*()</tt>. Typically the default for
|
||||
this parameter is the appropriate type.<br> <b>Default:</b> If
|
||||
<tt>Value</tt> is supplied, <tt>Value&</tt> is used. Otherwise
|
||||
<tt>std::iterator_traits<BaseIterator>::reference</tt> is
|
||||
used.</TD>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD><tt>Pointer</tt></TD>
|
||||
<TD>The <tt>pointer</tt> type of the resulting iterator, and in
|
||||
particular, the result type of <tt>operator->()</tt>.
|
||||
Typically the default for
|
||||
this parameter is the appropriate type.<br>
|
||||
<b>Default:</b> If <tt>Value</tt> was supplied, then <tt>Value*</tt>,
|
||||
otherwise <tt>std::iterator_traits<BaseIterator>::pointer</tt>.</TD>
|
||||
</TR>
|
||||
|
||||
|
||||
<TR>
|
||||
<TD><tt>Category</tt></TD>
|
||||
<TD>The <tt>iterator_category</tt> type for the resulting iterator.
|
||||
Typically the
|
||||
default for this parameter is the appropriate type. If you override
|
||||
this parameter, do not use <tt>bidirectional_iterator_tag</tt>
|
||||
because filter iterators can not go in reverse.<br>
|
||||
<b>Default:</b> <tt>std::iterator_traits<BaseIterator>::iterator_category</tt></TD>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD><tt>Distance</tt></TD>
|
||||
<TD>The <tt>difference_type</tt> for the resulting iterator. Typically the default for
|
||||
this parameter is the appropriate type.<br>
|
||||
<b>Default:</b> <tt>std::iterator_traits<BaseIterator>::difference_type</TD>
|
||||
</TR>
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
<h3>Model of</h3>
|
||||
|
||||
The filter iterator adaptor (the type
|
||||
<tt>filter_iterator_generator<...>::type</tt>) may be a model of <a
|
||||
href="http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a> or <a
|
||||
href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>
|
||||
depending on the adapted iterator type.
|
||||
|
||||
|
||||
<h3>Members</h3>
|
||||
|
||||
The filter iterator type implements all of the member functions and
|
||||
operators required of the <a
|
||||
href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>
|
||||
concept. In addition it has the following constructor:
|
||||
|
||||
<pre>filter_iterator_generator::type(const BaseIterator& it, const Policies& p = Policies())</pre>
|
||||
|
||||
<p>
|
||||
The policies type has only one public function, which is its constructor:
|
||||
|
||||
<pre>filter_iterator_generator::policies_type(const Predicate& p, const BaseIterator& end)</pre>
|
||||
|
||||
<p>
|
||||
<hr>
|
||||
<p>
|
||||
|
||||
<h2><a name="make_filter_iterator">The Make Filter Iterator Function</a></h2>
|
||||
|
||||
<pre>
|
||||
template <class Predicate, class BaseIterator>
|
||||
typename detail::filter_generator<Predicate, BaseIterator>::type
|
||||
make_filter_iterator(BaseIterator first, BaseIterator last, const Predicate& p = Predicate())
|
||||
</pre>
|
||||
|
||||
This function provides a convenient way to create filter iterators.
|
||||
|
||||
<h3>Example</h3>
|
||||
|
||||
In this example we print out all numbers in the array that are
|
||||
greater than negative two.
|
||||
|
||||
<pre>
|
||||
int main()
|
||||
{
|
||||
int numbers[] = { 0, -1, 4, -3, 5, 8, -2 };
|
||||
const int N = sizeof(numbers)/sizeof(int);
|
||||
|
||||
std::copy(boost::make_filter_iterator(numbers, numbers + N,
|
||||
std::bind2nd(std::greater<int>(), -2)),
|
||||
boost::make_filter_iterator(numbers + N, numbers + N,
|
||||
std::bind2nd(std::greater<int>(), -2)),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
}
|
||||
</pre>
|
||||
The output is:
|
||||
<pre>
|
||||
0 -1 4 5 8
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
In the next example we print the positive numbers using the
|
||||
<tt>make_filter_iterator()</tt> function.
|
||||
|
||||
<pre>
|
||||
struct is_positive_number {
|
||||
bool operator()(int x) { return 0 < x; }
|
||||
};
|
||||
int main()
|
||||
{
|
||||
int numbers[] = { 0, -1, 4, -3, 5, 8, -2 };
|
||||
const int N = sizeof(numbers)/sizeof(int);
|
||||
|
||||
std::copy(boost::make_filter_iterator<is_positive_number>(numbers, numbers + N),
|
||||
boost::make_filter_iterator<is_positive_number>(numbers + N, numbers + N),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
The output is:
|
||||
<pre>
|
||||
4 5 8
|
||||
</pre>
|
||||
|
||||
|
||||
<h3>Notes</h3>
|
||||
|
||||
<a name="1">[1]</a> If the compiler does not support partial
|
||||
specialization and the wrapped iterator type is a builtin pointer then
|
||||
the <tt>Value</tt> type must be explicitly specified (don't use the
|
||||
default).
|
||||
|
||||
|
||||
<hr>
|
||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->09 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14894" --></p>
|
||||
<p><EFBFBD> Copyright Jeremy Siek 2000. Permission to copy, use,
|
||||
modify, sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided "as is"
|
||||
without express or implied warranty, and with no claim as to its suitability for
|
||||
any purpose.</p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1,53 +0,0 @@
|
||||
// Example of using the filter iterator adaptor from
|
||||
// boost/iterator_adaptors.hpp.
|
||||
|
||||
// (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <boost/iterator_adaptors.hpp>
|
||||
|
||||
struct is_positive_number {
|
||||
bool operator()(int x) { return 0 < x; }
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
int numbers[] = { 0, -1, 4, -3, 5, 8, -2 };
|
||||
const int N = sizeof(numbers)/sizeof(int);
|
||||
|
||||
// Example using make_filter_iterator()
|
||||
std::copy(boost::make_filter_iterator<is_positive_number>(numbers, numbers + N),
|
||||
boost::make_filter_iterator<is_positive_number>(numbers + N, numbers + N),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
// Example using filter_iterator_generator
|
||||
typedef boost::filter_iterator_generator<is_positive_number, int*, int>::type
|
||||
FilterIter;
|
||||
is_positive_number predicate;
|
||||
FilterIter::policies_type policies(predicate, numbers + N);
|
||||
FilterIter filter_iter_first(numbers, policies);
|
||||
FilterIter filter_iter_last(numbers + N, policies);
|
||||
|
||||
std::copy(filter_iter_first, filter_iter_last, std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
// Another example using make_filter_iterator()
|
||||
std::copy(boost::make_filter_iterator(numbers, numbers + N,
|
||||
std::bind2nd(std::greater<int>(), -2)),
|
||||
boost::make_filter_iterator(numbers + N, numbers + N,
|
||||
std::bind2nd(std::greater<int>(), -2)),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
// (C) Copyright Jeremy Siek 2001. Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
// Revision History:
|
||||
|
||||
// 27 Feb 2001 Jeremy Siek
|
||||
// Initial checkin.
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/function_output_iterator.hpp>
|
||||
|
||||
struct string_appender {
|
||||
string_appender(std::string& s) : m_str(s) { }
|
||||
void operator()(const std::string& x) const {
|
||||
m_str += x;
|
||||
}
|
||||
std::string& m_str;
|
||||
};
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
std::vector<std::string> x;
|
||||
x.push_back("hello");
|
||||
x.push_back(" ");
|
||||
x.push_back("world");
|
||||
x.push_back("!");
|
||||
|
||||
std::string s = "";
|
||||
std::copy(x.begin(), x.end(),
|
||||
boost::make_function_output_iterator(string_appender(s)));
|
||||
|
||||
std::cout << s << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,169 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta name="generator" content="HTML Tidy, see www.w3.org">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
|
||||
<title>Function Output Iterator Adaptor Documentation</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
|
||||
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align=
|
||||
"center" width="277" height="86">
|
||||
|
||||
<h1>Function Output Iterator Adaptor</h1>
|
||||
Defined in header <a href=
|
||||
"../../boost/function_output_iterator.hpp">boost/function_output_iterator.hpp</a>
|
||||
|
||||
<p>The function output iterator adaptor makes it easier to create
|
||||
custom output iterators. The adaptor takes a <a
|
||||
href="http://www.sgi.com/tech/stl/UnaryFunction.html">Unary
|
||||
Function</a> and creates a model of <a
|
||||
href="http://www.sgi.com/tech/stl/OutputIterator.html">Output
|
||||
Iterator</a>. Each item assigned to the output iterator is passed
|
||||
as an argument to the unary function. The motivation for this
|
||||
iterator is that creating a C++ Standard conforming output
|
||||
iterator is non-trivial, particularly because the proper
|
||||
implementation usually requires a proxy object. On the other hand,
|
||||
creating a function (or function object) is much simpler.
|
||||
|
||||
<h2>Synopsis</h2>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
namespace boost {
|
||||
template <class UnaryFunction>
|
||||
class function_output_iterator;
|
||||
|
||||
template <class UnaryFunction>
|
||||
function_output_iterator<UnaryFunction>
|
||||
make_function_output_iterator(const UnaryFunction& f = UnaryFunction())
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<h3>Example</h3>
|
||||
|
||||
In this example we create an output iterator that appends
|
||||
each item onto the end of a string, using the <tt>string_appender</tt>
|
||||
function.
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/function_output_iterator.hpp>
|
||||
|
||||
struct string_appender {
|
||||
string_appender(std::string& s) : m_str(s) { }
|
||||
void operator()(const std::string& x) const {
|
||||
m_str += x;
|
||||
}
|
||||
std::string& m_str;
|
||||
};
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
std::vector<std::string> x;
|
||||
x.push_back("hello");
|
||||
x.push_back(" ");
|
||||
x.push_back("world");
|
||||
x.push_back("!");
|
||||
|
||||
std::string s = "";
|
||||
std::copy(x.begin(), x.end(),
|
||||
boost::make_function_output_iterator(string_appender(s)));
|
||||
|
||||
std::cout << s << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2><a name="function_output_iterator">The Function Output Iterator Class</a></h2>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
template <class UnaryFunction>
|
||||
class function_output_iterator;
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
The <tt>function_output_iterator</tt> class creates an <a
|
||||
href="http://www.sgi.com/tech/stl/OutputIterator.html">Output
|
||||
Iterator</a> out of a
|
||||
<a href="http://www.sgi.com/tech/stl/UnaryFunction.html">Unary
|
||||
Function</a>. Each item assigned to the output iterator is passed
|
||||
as an argument to the unary function.
|
||||
|
||||
<h3>Template Parameters</h3>
|
||||
|
||||
<table border>
|
||||
<tr>
|
||||
<th>Parameter
|
||||
|
||||
<th>Description
|
||||
|
||||
<tr>
|
||||
<td><tt>UnaryFunction</tt>
|
||||
|
||||
<td>The function type being wrapped. The return type of the
|
||||
function is not used, so it can be <tt>void</tt>. The
|
||||
function must be a model of <a
|
||||
href="http://www.sgi.com/tech/stl/UnaryFunction.html">Unary
|
||||
Function</a>.</td>
|
||||
</table>
|
||||
|
||||
<h3>Concept Model</h3>
|
||||
The function output iterator class is a model of <a
|
||||
href="http://www.sgi.com/tech/stl/OutputIterator.html">Output
|
||||
Iterator</a>.
|
||||
|
||||
<h2>Members</h3>
|
||||
The function output iterator implements the member functions
|
||||
and operators required of the <a
|
||||
href="http://www.sgi.com/tech/stl/OutputIterator.html">Output
|
||||
Iterator</a> concept. In addition it has the following constructor:
|
||||
<pre>
|
||||
explicit function_output_iterator(const UnaryFunction& f = UnaryFunction())
|
||||
</pre>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
<hr>
|
||||
<h2><a name="make_function_output_iterator">The Function Output Iterator Object
|
||||
Generator</a></h2>
|
||||
|
||||
The <tt>make_function_output_iterator()</tt> function provides a
|
||||
more convenient way to create function output iterator objects. The
|
||||
function saves the user the trouble of explicitly writing out the
|
||||
iterator types. If the default argument is used, the function
|
||||
type must be provided as an explicit template argument.
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
template <class UnaryFunction>
|
||||
function_output_iterator<UnaryFunction>
|
||||
make_function_output_iterator(const UnaryFunction& f = UnaryFunction())
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>© Copyright Jeremy Siek 2001. Permission to copy, use,
|
||||
modify, sell and distribute this document is granted provided this
|
||||
copyright notice appears in all copies. This document is provided
|
||||
"as is" without express or implied warranty, and with no claim as
|
||||
to its suitability for any purpose.
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,366 +0,0 @@
|
||||
// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears in
|
||||
// all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
//
|
||||
// Revision History
|
||||
// 11 Feb 2001 Compile with Borland, re-enable failing tests (David Abrahams)
|
||||
// 29 Jan 2001 Initial revision (David Abrahams)
|
||||
|
||||
#include <boost/half_open_range.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
#include <iterator>
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <cassert>
|
||||
#include <stdexcept>
|
||||
#ifndef BOOST_NO_LIMITS
|
||||
# include <limits>
|
||||
#endif
|
||||
#ifndef BOOST_NO_SLIST
|
||||
# include <slist>
|
||||
#endif
|
||||
|
||||
inline unsigned unsigned_random(unsigned max)
|
||||
{
|
||||
return (max > 0) ? (unsigned)rand() % max : 0;
|
||||
}
|
||||
|
||||
// Special tests for ranges supporting random access
|
||||
template <class T>
|
||||
void category_test_1(
|
||||
const boost::half_open_range<T>& r, std::random_access_iterator_tag)
|
||||
{
|
||||
typedef boost::half_open_range<T> range;
|
||||
typedef typename range::size_type size_type;
|
||||
size_type size = r.size();
|
||||
|
||||
// pick a random offset
|
||||
size_type offset = unsigned_random(size);
|
||||
|
||||
typename range::value_type x = *(r.begin() + offset);
|
||||
// test contains(value_type)
|
||||
assert(r.contains(r.start()) == !r.empty());
|
||||
assert(!r.contains(r.finish()));
|
||||
assert(r.contains(x) == (offset != size));
|
||||
|
||||
range::const_iterator p = r.find(x);
|
||||
assert((p == r.end()) == (x == r.finish()));
|
||||
assert(r.find(r.finish()) == r.end());
|
||||
|
||||
if (offset != size)
|
||||
{
|
||||
assert(x == r[offset]);
|
||||
assert(x == r.at(offset));
|
||||
}
|
||||
|
||||
bool caught_out_of_range = false;
|
||||
try {
|
||||
bool never_initialized = x == r.at(size);
|
||||
(void)never_initialized;
|
||||
}
|
||||
catch(std::out_of_range&)
|
||||
{
|
||||
caught_out_of_range = true;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
}
|
||||
assert(caught_out_of_range);
|
||||
}
|
||||
|
||||
// Those tests must be skipped for other ranges
|
||||
template <class T>
|
||||
void category_test_1(
|
||||
const boost::half_open_range<T>&, std::forward_iterator_tag)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned indices[][2] = { {0,0},{0,1},{0,2},{0,3},
|
||||
{1,1},{1,2},{1,3},
|
||||
{2,2},{2,3},
|
||||
{3,3}};
|
||||
|
||||
template <class Range>
|
||||
void category_test_2(
|
||||
const std::vector<Range>& ranges, unsigned i, unsigned j, std::random_access_iterator_tag)
|
||||
{
|
||||
typedef Range range;
|
||||
const range& ri = ranges[i];
|
||||
const range& rj = ranges[j];
|
||||
|
||||
if (indices[i][0] <= indices[j][0] && indices[i][1] >= indices[j][1])
|
||||
assert(ri.contains(rj));
|
||||
|
||||
if (ri.contains(rj))
|
||||
assert((ri & rj) == rj);
|
||||
assert(boost::intersects(ri, rj) == !(ri & rj).empty());
|
||||
|
||||
range t1(ri);
|
||||
t1 &= rj;
|
||||
assert(t1 == range(indices[i][0] > indices[j][0] ? ri.start() : rj.start(),
|
||||
indices[i][1] < indices[j][1] ? ri.finish() : rj.finish()));
|
||||
assert(t1 == (ri & rj));
|
||||
|
||||
range t2(ri);
|
||||
t2 |= rj;
|
||||
|
||||
if (ri.empty())
|
||||
assert(t2 == rj);
|
||||
else if (rj.empty())
|
||||
assert(t2 == ri);
|
||||
else
|
||||
assert(t2 == range(indices[i][0] < indices[j][0] ? ri.start() : rj.start(),
|
||||
indices[i][1] > indices[j][1] ? ri.finish() : rj.finish()));
|
||||
assert(t2 == (ri | rj));
|
||||
if (i == j)
|
||||
assert(ri == rj);
|
||||
|
||||
if (ri.empty() || rj.empty())
|
||||
assert((ri == rj) == (ri.empty() && rj.empty()));
|
||||
else
|
||||
assert((ri == rj) == (ri.start() == rj.start() && ri.finish() == rj.finish()));
|
||||
|
||||
assert((ri == rj) == !(ri != rj));
|
||||
|
||||
bool same = ri == rj;
|
||||
bool one_empty = ri.empty() != rj.empty();
|
||||
|
||||
std::less<range> less;
|
||||
std::less_equal<range> less_equal;
|
||||
std::greater<range> greater;
|
||||
std::greater_equal<range> greater_equal;
|
||||
|
||||
if (same)
|
||||
{
|
||||
assert(greater_equal(ri,rj));
|
||||
assert(less_equal(ri,rj));
|
||||
assert(!greater(ri,rj));
|
||||
assert(!less(ri,rj));
|
||||
}
|
||||
else if (one_empty)
|
||||
{
|
||||
const range& empty = ri.empty() ? ri : rj;
|
||||
const range& non_empty = rj.empty() ? ri : rj;
|
||||
|
||||
assert(less(empty,non_empty));
|
||||
assert(less_equal(empty,non_empty));
|
||||
assert(!greater(empty,non_empty));
|
||||
assert(!greater_equal(empty,non_empty));
|
||||
assert(!less(non_empty,empty));
|
||||
assert(!less_equal(non_empty,empty));
|
||||
assert(greater(non_empty,empty));
|
||||
assert(greater_equal(non_empty,empty));
|
||||
}
|
||||
else {
|
||||
if (indices[i][0] < indices[j][0] ||
|
||||
indices[i][0] == indices[j][0] && indices[i][1] < indices[j][1])
|
||||
{
|
||||
assert(!greater_equal(ri,rj));
|
||||
assert(less(ri,rj));
|
||||
}
|
||||
|
||||
if (indices[i][0] < indices[j][0] ||
|
||||
indices[i][0] == indices[j][0] && indices[i][1] <= indices[j][1])
|
||||
{
|
||||
assert(!greater(ri,rj));
|
||||
assert(less_equal(ri,rj));
|
||||
}
|
||||
|
||||
if (indices[i][0] > indices[j][0] ||
|
||||
indices[i][0] == indices[j][0] && indices[i][1] > indices[j][1])
|
||||
{
|
||||
assert(!less_equal(ri,rj));
|
||||
assert(greater(ri,rj));
|
||||
}
|
||||
|
||||
if (indices[i][0] > indices[j][0] ||
|
||||
indices[i][0] == indices[j][0] && indices[i][1] >= indices[j][1])
|
||||
{
|
||||
assert(!less(ri,rj));
|
||||
assert(greater_equal(ri,rj));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <class Range>
|
||||
void category_test_2(
|
||||
const std::vector<Range>&, unsigned, unsigned, std::forward_iterator_tag)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void category_test_2(
|
||||
const std::vector<boost::half_open_range<T> >&, unsigned, unsigned, std::bidirectional_iterator_tag)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Range>
|
||||
void test_back(Range& x, std::bidirectional_iterator_tag)
|
||||
{
|
||||
assert(x.back() == boost::prior(x.finish()));
|
||||
}
|
||||
|
||||
template <class Range>
|
||||
void test_back(Range& x, std::forward_iterator_tag)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
boost::half_open_range<T> range_identity(const boost::half_open_range<T>& x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void test(T x0, T x1, T x2, T x3)
|
||||
{
|
||||
std::vector<boost::half_open_range<T> > ranges;
|
||||
typedef boost::half_open_range<T> range;
|
||||
|
||||
T bounds[4] = { x0, x1, x2, x3 };
|
||||
|
||||
const std::size_t num_ranges = sizeof(indices)/sizeof(*indices);
|
||||
// test construction
|
||||
for (std::size_t n = 0; n < num_ranges;++n)
|
||||
{
|
||||
T start = bounds[indices[n][0]];
|
||||
T finish = bounds[indices[n][1]];
|
||||
boost::half_open_range<T> r(start, finish);
|
||||
ranges.push_back(r);
|
||||
}
|
||||
|
||||
// test implicit conversion from std::pair<T,T>
|
||||
range converted = std::pair<T,T>(x0,x0);
|
||||
(void)converted;
|
||||
|
||||
// test assignment, equality and inequality
|
||||
range r00 = range(x0, x0);
|
||||
assert(r00 == range(x0,x0));
|
||||
assert(r00 == range(x1,x1)); // empty ranges are all equal
|
||||
if (x3 != x0)
|
||||
assert(r00 != range(x0, x3));
|
||||
r00 = range(x0, x3);
|
||||
assert(r00 == range(x0, x3));
|
||||
if (x3 != x0)
|
||||
assert(r00 != range(x0, x0));
|
||||
|
||||
typedef typename range::iterator iterator;
|
||||
typedef typename iterator::iterator_category category;
|
||||
|
||||
for (unsigned i = 0; i < num_ranges; ++i)
|
||||
{
|
||||
const range& r = ranges[i];
|
||||
|
||||
// test begin(), end(), basic iteration.
|
||||
unsigned count = 0;
|
||||
for (range::const_iterator p = r.begin(), finish = r.end();
|
||||
p != finish;
|
||||
++p, ++count)
|
||||
{
|
||||
assert(count < 2100);
|
||||
}
|
||||
|
||||
// test size(), empty(), front(), back()
|
||||
assert((unsigned)r.size() == count);
|
||||
if (indices[i][0] == indices[i][1])
|
||||
assert(r.empty());
|
||||
if (r.empty())
|
||||
assert(r.size() == 0);
|
||||
if (!r.empty())
|
||||
{
|
||||
assert(r.front() == r.start());
|
||||
test_back(r, category());
|
||||
}
|
||||
|
||||
// test swap
|
||||
range r1(r);
|
||||
range r2(x0,x3);
|
||||
const bool same = r1 == r2;
|
||||
r1.swap(r2);
|
||||
assert(r1 == range(x0,x3));
|
||||
assert(r2 == r);
|
||||
if (!same) {
|
||||
assert(r1 != r);
|
||||
assert(r2 != range(x0,x3));
|
||||
}
|
||||
|
||||
// do individual tests for random-access iterators
|
||||
category_test_1(r, category());
|
||||
}
|
||||
|
||||
for (unsigned j = 0; j < num_ranges; ++j) {
|
||||
for (unsigned k = 0; k < num_ranges; ++k) {
|
||||
category_test_2(ranges, j, k, category());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template <class Integer>
|
||||
void test_integer(Integer* = 0) // default arg works around MSVC bug
|
||||
{
|
||||
Integer a = 0;
|
||||
Integer b = a + unsigned_random(128 - a);
|
||||
Integer c = b + unsigned_random(128 - b);
|
||||
Integer d = c + unsigned_random(128 - c);
|
||||
|
||||
test(a, b, c, d);
|
||||
}
|
||||
|
||||
template <class Container>
|
||||
void test_container(Container* = 0) // default arg works around MSVC bug
|
||||
{
|
||||
Container c(unsigned_random(1673));
|
||||
|
||||
const typename Container::size_type offset1 = unsigned_random(c.size());
|
||||
const typename Container::size_type offset2 = unsigned_random(c.size() - offset1);
|
||||
typename Container::iterator internal1 = c.begin();
|
||||
std::advance(internal1, offset1);
|
||||
typename Container::iterator internal2 = internal1;
|
||||
std::advance(internal2, offset2);
|
||||
|
||||
test(c.begin(), internal1, internal2, c.end());
|
||||
|
||||
typedef typename Container::const_iterator const_iterator;
|
||||
test(const_iterator(c.begin()),
|
||||
const_iterator(internal1),
|
||||
const_iterator(internal2),
|
||||
const_iterator(c.end()));
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// Test the built-in integer types.
|
||||
test_integer<char>();
|
||||
test_integer<unsigned char>();
|
||||
test_integer<signed char>();
|
||||
test_integer<wchar_t>();
|
||||
test_integer<short>();
|
||||
test_integer<unsigned short>();
|
||||
test_integer<int>();
|
||||
test_integer<unsigned int>();
|
||||
test_integer<long>();
|
||||
test_integer<unsigned long>();
|
||||
#if defined(ULLONG_MAX) || defined(ULONG_LONG_MAX)
|
||||
test_integer<long long>();
|
||||
test_integer<unsigned long long>();
|
||||
#endif
|
||||
// Some tests on container iterators, to prove we handle a few different categories
|
||||
test_container<std::vector<int> >();
|
||||
test_container<std::list<int> >();
|
||||
#ifndef BOOST_NO_SLIST
|
||||
test_container<BOOST_STD_EXTENSION_NAMESPACE::slist<int> >();
|
||||
#endif
|
||||
// Also prove that we can handle raw pointers.
|
||||
int array[2000];
|
||||
const std::size_t a = 0;
|
||||
const std::size_t b = a + unsigned_random(2000 - a);
|
||||
const std::size_t c = b + unsigned_random(2000 - b);
|
||||
test(array, array+b, array+c, array+2000);
|
||||
return 0;
|
||||
}
|
44
identity_type/doc/Jamfile.v2
Normal file
44
identity_type/doc/Jamfile.v2
Normal file
@ -0,0 +1,44 @@
|
||||
|
||||
# Copyright (C) 2009-2012 Lorenzo Caminiti
|
||||
# Distributed under the Boost Software License, Version 1.0
|
||||
# (see accompanying file LICENSE_1_0.txt or a copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
# Home at http://www.boost.org/libs/utility/identity_type
|
||||
|
||||
import quickbook ;
|
||||
using boostbook ;
|
||||
|
||||
doxygen reference : ../../../../boost/utility/identity_type.hpp
|
||||
: <reftitle>"Reference"
|
||||
<doxygen:param>PREDEFINED="DOXYGEN"
|
||||
<doxygen:param>QUIET=YES
|
||||
<doxygen:param>WARN_IF_UNDOCUMENTED=NO
|
||||
<doxygen:param>HIDE_UNDOC_MEMBERS=YES
|
||||
<doxygen:param>HIDE_UNDOC_CLASSES=YES
|
||||
<doxygen:param>ALIASES=" Params=\"<b>Parameters:</b> <table border="0">\" Param{2}=\"<tr><td><b><tt>\\1</tt></b></td><td>\\2</td></tr>\" EndParams=\"</table>\" Returns=\"<b>Returns:</b>\" Note=\"<b>Note:</b>\" Warning=\"<b>Warning:</b>\" See=\"<b>See:</b>\" RefSect{2}=\"\\xmlonly<link linkend='boost_utility_identitytype.\\1'>\\2</link>\\endxmlonly\" RefClass{1}=\"\\xmlonly<computeroutput><classname alt='\\1'>\\1</classname></computeroutput>\\endxmlonly\" RefFunc{1}=\"\\xmlonly<computeroutput><functionname alt='\\1'>\\1</functionname></computeroutput>\\endxmlonly\" RefMacro{1}=\"\\xmlonly<computeroutput><macroname alt='\\1'>\\1</macroname></computeroutput>\\endxmlonly\" "
|
||||
;
|
||||
|
||||
# This target must be called "index" so to generate "index.html" file.
|
||||
xml index : identity_type.qbk : <dependency>reference ;
|
||||
|
||||
boostbook doc : index
|
||||
: <location>html
|
||||
<format>onehtml
|
||||
<xsl:param>toc.section.depth=0
|
||||
<xsl:param>html.stylesheet=../../../../../doc/src/boostbook.css
|
||||
<xsl:param>boost.root=../../../../..
|
||||
;
|
||||
|
||||
#
|
||||
# This is very imperfect - it results in both html and pdf docs being built,
|
||||
# for some reason I can't get the "onehtml" format specified above to play nice
|
||||
# with the usual incantations for mixed pdf/html builds. JM 06/2012.
|
||||
#
|
||||
boostbook pdf_doc : index
|
||||
:
|
||||
<format>pdf
|
||||
<format>html:<build>no
|
||||
;
|
||||
|
||||
install pdf_doc_install : pdf_doc : <location>. <name>identity_type.pdf <install-type>PDF ;
|
||||
explicit pdf_doc_install ;
|
252
identity_type/doc/html/index.html
Normal file
252
identity_type/doc/html/index.html
Normal file
@ -0,0 +1,252 @@
|
||||
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Boost.Utility/IdentityType 1.0.0</title><link rel="stylesheet" type="text/css" href="../../../../../doc/src/boostbook.css"><meta name="generator" content="DocBook XSL Stylesheets V1.76.1"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="chapter" title="Boost.Utility/IdentityType 1.0.0"><div class="titlepage"><div><div><h2 class="title"><a name="boost_utility_identitytype"></a>Boost.Utility/IdentityType 1.0.0</h2></div><div><div class="author"><h3 class="author"><span class="firstname">Lorenzo</span> <span class="surname">Caminiti <code class="email"><<a class="email" href="mailto:lorcaminiti@gmail.com">lorcaminiti@gmail.com</a>></code></span></h3></div></div><div><p class="copyright">Copyright © 2009-2012 Lorenzo
|
||||
Caminiti</p></div><div><div class="legalnotice" title="Legal Notice"><a name="boost_utility_identitytype.legal"></a><p>
|
||||
Distributed under the Boost Software License, Version 1.0 (see accompanying
|
||||
file LICENSE_1_0.txt or a copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p></div></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="section"><a href="#boost_utility_identitytype.motivation">Motivation</a></span></dt><dt><span class="section"><a href="#boost_utility_identitytype.solution">Solution</a></span></dt><dt><span class="section"><a href="#boost_utility_identitytype.templates">Templates</a></span></dt><dt><span class="section"><a href="#boost_utility_identitytype.abstract_types">Abstract Types</a></span></dt><dt><span class="section"><a href="#boost_utility_identitytype.annex__usage">Annex: Usage</a></span></dt><dt><span class="section"><a href="#boost_utility_identitytype.annex__implementation">Annex:
|
||||
Implementation</a></span></dt><dt><span class="section"><a href="#reference">Reference</a></span></dt></dl></div><p>
|
||||
This library allows to wrap types within round parenthesis so they can always
|
||||
be passed as macro parameters.
|
||||
</p><div class="section boost_utility_identitytype_motivation" title="Motivation"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="boost_utility_identitytype.motivation"></a><a class="link" href="#boost_utility_identitytype.motivation" title="Motivation">Motivation</a></h2></div></div></div><p>
|
||||
Consider the following macro which declares a variable named <code class="computeroutput"><span class="identifier">var</span></code><code class="literal"><span class="emphasis"><em>n</em></span></code>
|
||||
with the specified <code class="literal"><span class="emphasis"><em>type</em></span></code> (see also
|
||||
<a href="../../test/var_error.cpp" target="_top"><code class="literal">var_error.cpp</code></a>):
|
||||
</p><p>
|
||||
</p><pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">VAR</span><span class="special">(</span><span class="identifier">type</span><span class="special">,</span> <span class="identifier">n</span><span class="special">)</span> <span class="identifier">type</span> <span class="identifier">var</span> <span class="error">#</span><span class="preprocessor"># n</span>
|
||||
|
||||
<span class="identifier">VAR</span><span class="special">(</span><span class="keyword">int</span><span class="special">,</span> <span class="number">1</span><span class="special">);</span> <span class="comment">// OK.</span>
|
||||
<span class="identifier">VAR</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">>,</span> <span class="number">2</span><span class="special">);</span> <span class="comment">// Error.</span>
|
||||
</pre><p>
|
||||
</p><p>
|
||||
The first macro invocation works correctly declaring a variable named <code class="computeroutput"><span class="identifier">var1</span></code> of type <code class="computeroutput"><span class="keyword">int</span></code>.
|
||||
However, the second macro invocation fails generating a preprocessor error
|
||||
similar to the following:
|
||||
</p><pre class="programlisting">error: macro "VAR" passed 3 arguments, but takes just 2
|
||||
</pre><p>
|
||||
That is because the <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span></code> type passed as the first macro parameter
|
||||
contains a comma <code class="computeroutput"><span class="special">,</span></code> not wrapped
|
||||
by round parenthesis <code class="computeroutput"><span class="special">()</span></code>. The preprocessor
|
||||
interprets that unwrapped comma as a separation between macro parameters concluding
|
||||
that a total of three (and not two) parameters are passed to the macro in the
|
||||
following order:
|
||||
</p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem">
|
||||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special"><</span><span class="keyword">int</span></code>
|
||||
</li><li class="listitem">
|
||||
<code class="computeroutput"><span class="keyword">char</span><span class="special">></span></code>
|
||||
</li><li class="listitem">
|
||||
<code class="computeroutput"><span class="number">2</span></code>
|
||||
</li></ol></div><p>
|
||||
Note that, differently from the compiler, the preprocessor only recognizes
|
||||
round parenthesis <code class="computeroutput"><span class="special">()</span></code>. Angular
|
||||
<code class="computeroutput"><span class="special"><></span></code> and squared <code class="computeroutput"><span class="special">[]</span></code> parenthesis are not recognized by the preprocessor
|
||||
when parsing macro parameters.
|
||||
</p></div><div class="section boost_utility_identitytype_solution" title="Solution"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="boost_utility_identitytype.solution"></a><a class="link" href="#boost_utility_identitytype.solution" title="Solution">Solution</a></h2></div></div></div><p>
|
||||
In some cases, it might be possible to workaround this issue by avoiding to
|
||||
pass the type expression to the macro all together. For example, in the case
|
||||
above a <code class="computeroutput"><span class="keyword">typedef</span></code> could have been
|
||||
used to specify the type expression with the commas outside the macro (see
|
||||
also <a href="../../test/var.cpp" target="_top"><code class="literal">var.cpp</code></a>):
|
||||
</p><p>
|
||||
</p><pre class="programlisting"><span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">></span> <span class="identifier">map_type</span><span class="special">;</span>
|
||||
<span class="identifier">VAR</span><span class="special">(</span><span class="identifier">map_type</span><span class="special">,</span> <span class="number">3</span><span class="special">);</span> <span class="comment">// OK.</span>
|
||||
</pre><p>
|
||||
</p><p>
|
||||
When this is neither possible nor desired (e.g., see the function template
|
||||
<code class="computeroutput"><span class="identifier">f</span></code> in the section below), this
|
||||
library header <code class="computeroutput"><a class="link" href="#header.boost.utility.identity_type_hpp" title="Header <boost/utility/identity_type.hpp>">boost/utility/identity_type.hpp</a></code>
|
||||
defines a macro <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code>
|
||||
which can be used to workaround the issue while keeping the type expression
|
||||
as one of the macro parameters (see also <a href="../../test/var.cpp" target="_top"><code class="literal">var.cpp</code></a>).
|
||||
</p><p>
|
||||
</p><pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">utility</span><span class="special">/</span><span class="identifier">identity_type</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||||
|
||||
<span class="identifier">VAR</span><span class="special">(</span><span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">((</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">>)),</span> <span class="number">4</span><span class="special">);</span> <span class="comment">// OK.</span>
|
||||
</pre><p>
|
||||
</p><p>
|
||||
The <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code> macro
|
||||
expands to an expression that evaluates (at compile-time) to the specified
|
||||
type. The specified type is never split into multiple macro parameters because
|
||||
it is always wrapped by a set of extra round parenthesis <code class="computeroutput"><span class="special">()</span></code>.
|
||||
In fact, a total of two sets of round parenthesis must be used: The parenthesis
|
||||
to invoke the macro <code class="computeroutput"><span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">(...)</span></code> plus the inner parenthesis to wrap the
|
||||
type passed to the macro <code class="computeroutput"><span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">((...))</span></code>.
|
||||
</p><p>
|
||||
This macro works on any <a href="http://www.open-std.org/JTC1/SC22/WG21/docs/standards" target="_top">C++03</a>
|
||||
compiler (and it does not use <a href="http://en.wikipedia.org/wiki/Variadic_macro" target="_top">variadic
|
||||
macros</a>). <sup>[<a name="boost_utility_identitytype.solution.f0" href="#ftn.boost_utility_identitytype.solution.f0" class="footnote">1</a>]</sup> The authors originally developed and tested this library using
|
||||
GNU Compiler Collection (GCC) C++ 4.5.3 (with and without C++11 features enabled
|
||||
<code class="computeroutput"><span class="special">-</span><span class="identifier">std</span><span class="special">=</span><span class="identifier">c</span><span class="special">++</span><span class="number">0</span><span class="identifier">x</span></code>) on Cygwin
|
||||
and Miscrosoft Visual C++ (MSVC) 8.0 on Windows 7. See the library <a href="http://www.boost.org/development/tests/release/developer/utility-identity_type.html" target="_top">regressions
|
||||
test results</a> for more information on supported compilers and platforms.
|
||||
</p></div><div class="section boost_utility_identitytype_templates" title="Templates"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="boost_utility_identitytype.templates"></a><a class="link" href="#boost_utility_identitytype.templates" title="Templates">Templates</a></h2></div></div></div><p>
|
||||
This macro must be prefixed by <code class="computeroutput"><span class="keyword">typename</span></code>
|
||||
when used within templates. For example, let's program a macro that declares
|
||||
a function parameter named <code class="computeroutput"><span class="identifier">arg</span></code><code class="literal"><span class="emphasis"><em>n</em></span></code>
|
||||
with the specified <code class="literal"><span class="emphasis"><em>type</em></span></code> (see also
|
||||
<a href="../../test/template.cpp" target="_top"><code class="literal">template.cpp</code></a>):
|
||||
</p><p>
|
||||
</p><pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">ARG</span><span class="special">(</span><span class="identifier">type</span><span class="special">,</span> <span class="identifier">n</span><span class="special">)</span> <span class="identifier">type</span> <span class="identifier">arg</span> <span class="error">#</span><span class="preprocessor"># n</span>
|
||||
|
||||
<span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span>
|
||||
<span class="keyword">void</span> <span class="identifier">f</span><span class="special">(</span> <span class="comment">// Prefix macro with `typename` in templates.</span>
|
||||
<span class="identifier">ARG</span><span class="special">(</span><span class="keyword">typename</span> <span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">((</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">T</span><span class="special">>)),</span> <span class="number">1</span><span class="special">)</span>
|
||||
<span class="special">)</span> <span class="special">{</span>
|
||||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">arg1</span><span class="special">[</span><span class="number">0</span><span class="special">]</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
|
||||
<span class="special">}</span>
|
||||
</pre><p>
|
||||
</p><p>
|
||||
</p><pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">></span> <span class="identifier">a</span><span class="special">;</span>
|
||||
<span class="identifier">a</span><span class="special">[</span><span class="number">0</span><span class="special">]</span> <span class="special">=</span> <span class="char">'a'</span><span class="special">;</span>
|
||||
|
||||
<span class="identifier">f</span><span class="special"><</span><span class="keyword">char</span><span class="special">>(</span><span class="identifier">a</span><span class="special">);</span> <span class="comment">// OK...</span>
|
||||
<span class="comment">// f(a); // ... but error.</span>
|
||||
</pre><p>
|
||||
</p><p>
|
||||
However, note that the template parameter <code class="computeroutput"><span class="keyword">char</span></code>
|
||||
must be manually specified when invoking the function as in <code class="computeroutput"><span class="identifier">f</span><span class="special"><</span><span class="keyword">char</span><span class="special">>(</span><span class="identifier">a</span><span class="special">)</span></code>. In fact,
|
||||
when the <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code>
|
||||
macro is used to wrap a function template parameter, the template parameter
|
||||
can no longer be automatically deduced by the compiler form the function call
|
||||
as <code class="computeroutput"><span class="identifier">f</span><span class="special">(</span><span class="identifier">a</span><span class="special">)</span></code> would
|
||||
have done. <sup>[<a name="boost_utility_identitytype.templates.f0" href="#ftn.boost_utility_identitytype.templates.f0" class="footnote">2</a>]</sup> (This limitation does not apply to class templates because class
|
||||
template parameters must always be explicitly specified.) In other words, without
|
||||
using the <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code>
|
||||
macro, C++ would normally be able to automatically deduce the function template
|
||||
parameter as shown below:
|
||||
</p><p>
|
||||
</p><pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span>
|
||||
<span class="keyword">void</span> <span class="identifier">g</span><span class="special">(</span>
|
||||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">T</span><span class="special">></span> <span class="identifier">arg1</span>
|
||||
<span class="special">)</span> <span class="special">{</span>
|
||||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">arg1</span><span class="special">[</span><span class="number">0</span><span class="special">]</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
|
||||
<span class="special">}</span>
|
||||
</pre><p>
|
||||
</p><p>
|
||||
</p><pre class="programlisting"><span class="identifier">g</span><span class="special"><</span><span class="keyword">char</span><span class="special">>(</span><span class="identifier">a</span><span class="special">);</span> <span class="comment">// OK...</span>
|
||||
<span class="identifier">g</span><span class="special">(</span><span class="identifier">a</span><span class="special">);</span> <span class="comment">// ... and also OK.</span>
|
||||
</pre><p>
|
||||
</p></div><div class="section boost_utility_identitytype_abstract_types" title="Abstract Types"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="boost_utility_identitytype.abstract_types"></a><a class="link" href="#boost_utility_identitytype.abstract_types" title="Abstract Types">Abstract Types</a></h2></div></div></div><p>
|
||||
On some compilers (e.g., GCC), using this macro on abstract types (i.e., classes
|
||||
with one or more pure virtual functions) generates a compiler error. This can
|
||||
be avoided by manipulating the type adding and removing a reference to it.
|
||||
</p><p>
|
||||
Let's program a macro that performs a static assertion on a <a href="http://en.wikipedia.org/wiki/Template_metaprogramming" target="_top">Template
|
||||
Meta-Programming</a> (TMP) meta-function (similarly to Boost.MPL <a href="http://www.boost.org/doc/libs/1_36_0/libs/mpl/doc/refmanual/assert.html" target="_top"><code class="computeroutput"><span class="identifier">BOOST_MPL_ASSERT</span></code></a>). The <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code> macro can be used
|
||||
to pass a meta-function with multiple template parameters to the assert macro
|
||||
(so to handle the commas separating the template parameters). In this case,
|
||||
if the meta-function is an abstract type, it needs to be manipulated adding
|
||||
and removing a reference to it (see also <a href="../../test/abstract.cpp" target="_top"><code class="literal">abstract.cpp</code></a>):
|
||||
</p><p>
|
||||
</p><pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">TMP_ASSERT</span><span class="special">(</span><span class="identifier">metafunction</span><span class="special">)</span> <span class="special">\</span>
|
||||
<span class="identifier">BOOST_STATIC_ASSERT</span><span class="special">(</span><span class="identifier">metafunction</span><span class="special">::</span><span class="identifier">value</span><span class="special">)</span>
|
||||
|
||||
<span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">bool</span> <span class="identifier">b</span><span class="special">></span>
|
||||
<span class="keyword">struct</span> <span class="identifier">abstract</span> <span class="special">{</span>
|
||||
<span class="keyword">static</span> <span class="keyword">const</span> <span class="keyword">bool</span> <span class="identifier">value</span> <span class="special">=</span> <span class="identifier">b</span><span class="special">;</span>
|
||||
<span class="keyword">virtual</span> <span class="keyword">void</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">T</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">x</span><span class="special">)</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="comment">// Pure virtual function.</span>
|
||||
<span class="special">};</span>
|
||||
|
||||
<span class="identifier">TMP_ASSERT</span><span class="special">(</span>
|
||||
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">remove_reference</span><span class="special"><</span> <span class="comment">// Add and remove</span>
|
||||
<span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">((</span> <span class="comment">// reference for</span>
|
||||
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">add_reference</span><span class="special"><</span> <span class="comment">// abstract type.</span>
|
||||
<span class="identifier">abstract</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">true</span><span class="special">></span>
|
||||
<span class="special">>::</span><span class="identifier">type</span>
|
||||
<span class="special">))</span>
|
||||
<span class="special">>::</span><span class="identifier">type</span>
|
||||
<span class="special">);</span>
|
||||
</pre><p>
|
||||
</p></div><div class="section boost_utility_identitytype_annex__usage" title="Annex: Usage"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="boost_utility_identitytype.annex__usage"></a><a class="link" href="#boost_utility_identitytype.annex__usage" title="Annex: Usage">Annex: Usage</a></h2></div></div></div><p>
|
||||
The <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code> macro
|
||||
can be used either when calling a user-defined macro (as shown by the examples
|
||||
so far), or internally when implementing a user-defined macro (as shown below).
|
||||
When <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code> is
|
||||
used in the implementation of the user-defined macro, the caller of the user
|
||||
macro will have to specify the extra parenthesis (see also <a href="../../test/paren.cpp" target="_top"><code class="literal">paren.cpp</code></a>):
|
||||
</p><p>
|
||||
</p><pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">TMP_ASSERT_PAREN</span><span class="special">(</span><span class="identifier">parenthesized_metafunction</span><span class="special">)</span> <span class="special">\</span>
|
||||
<span class="comment">/* use `BOOST_IDENTITY_TYPE` in macro definition instead of invocation */</span> <span class="special">\</span>
|
||||
<span class="identifier">BOOST_STATIC_ASSERT</span><span class="special">(</span><span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">(</span><span class="identifier">parenthesized_metafunction</span><span class="special">)::</span><span class="identifier">value</span><span class="special">)</span>
|
||||
|
||||
<span class="preprocessor">#define</span> <span class="identifier">TMP_ASSERT</span><span class="special">(</span><span class="identifier">metafunction</span><span class="special">)</span> <span class="special">\</span>
|
||||
<span class="identifier">BOOST_STATIC_ASSERT</span><span class="special">(</span><span class="identifier">metafunction</span><span class="special">::</span><span class="identifier">value</span><span class="special">)</span>
|
||||
|
||||
<span class="comment">// Specify only extra parenthesis `((...))`.</span>
|
||||
<span class="identifier">TMP_ASSERT_PAREN</span><span class="special">((</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_const</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">></span> <span class="keyword">const</span><span class="special">>));</span>
|
||||
|
||||
<span class="comment">// Specify both the extra parenthesis `((...))` and `BOOST_IDENTITY_TYPE` macro.</span>
|
||||
<span class="identifier">TMP_ASSERT</span><span class="special">(</span><span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">((</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_const</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">></span> <span class="keyword">const</span><span class="special">>)));</span>
|
||||
</pre><p>
|
||||
</p><p>
|
||||
However, note that the caller will <span class="emphasis"><em>always</em></span> have to specify
|
||||
the extra parenthesis even when the macro parameters contain no comma:
|
||||
</p><p>
|
||||
</p><pre class="programlisting"><span class="identifier">TMP_ASSERT_PAREN</span><span class="special">((</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_const</span><span class="special"><</span><span class="keyword">int</span> <span class="keyword">const</span><span class="special">>));</span> <span class="comment">// Always extra `((...))`.</span>
|
||||
|
||||
<span class="identifier">TMP_ASSERT</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_const</span><span class="special"><</span><span class="keyword">int</span> <span class="keyword">const</span><span class="special">>);</span> <span class="comment">// No extra `((...))` and no macro.</span>
|
||||
</pre><p>
|
||||
</p><p>
|
||||
In some cases, using <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code>
|
||||
in the implementation of the user-defined macro might provide the best syntax
|
||||
for the caller. For example, this is the case for <code class="computeroutput"><span class="identifier">BOOST_MPL_ASSERT</span></code>
|
||||
because the majority of template meta-programming expressions contain unwrapped
|
||||
commas so it is less confusing for the user to always specify the extra parenthesis
|
||||
<code class="computeroutput"><span class="special">((...))</span></code> instead of using <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code>:
|
||||
</p><pre class="programlisting"><span class="identifier">BOOST_MPL_ASSERT</span><span class="special">((</span> <span class="comment">// Natural syntax.</span>
|
||||
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">mpl</span><span class="special">::</span><span class="identifier">and_</span><span class="special"><</span>
|
||||
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_const</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span>
|
||||
<span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_reference</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span>
|
||||
<span class="special">></span>
|
||||
<span class="special">));</span>
|
||||
</pre><p>
|
||||
However, in other situations it might be preferable to not require the extra
|
||||
parenthesis in the common cases and handle commas as special cases using <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code>. For example, this
|
||||
is the case for <a href="http://www.boost.org/libs/local_function" target="_top"><code class="computeroutput"><span class="identifier">BOOST_LOCAL_FUNCTION</span></code></a> for which always
|
||||
requiring the extra parenthesis <code class="computeroutput"><span class="special">((...))</span></code>
|
||||
around the types would lead to an unnatural syntax for the local function signature:
|
||||
</p><pre class="programlisting"><span class="keyword">int</span> <span class="identifier">BOOST_LOCAL_FUNCTION</span><span class="special">(</span> <span class="special">((</span><span class="keyword">int</span><span class="special">&))</span> <span class="identifier">x</span><span class="special">,</span> <span class="special">((</span><span class="keyword">int</span><span class="special">&))</span> <span class="identifier">y</span> <span class="special">)</span> <span class="special">{</span> <span class="comment">// Unnatural syntax.</span>
|
||||
<span class="keyword">return</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">y</span><span class="special">;</span>
|
||||
<span class="special">}</span> <span class="identifier">BOOST_LOCAL_FUNCTION_NAME</span><span class="special">(</span><span class="identifier">add</span><span class="special">)</span>
|
||||
</pre><p>
|
||||
Instead requiring the user to specify <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code>
|
||||
only when needed allows for the more natural syntax <code class="computeroutput"><span class="identifier">BOOST_LOCAL_FUNCTION</span><span class="special">(</span><span class="keyword">int</span><span class="special">&</span>
|
||||
<span class="identifier">x</span><span class="special">,</span> <span class="keyword">int</span><span class="special">&</span> <span class="identifier">y</span><span class="special">)</span></code> in the common cases when the parameter types
|
||||
contain no comma (while still allowing to specify parameter types with commas
|
||||
as special cases using <code class="computeroutput"><span class="identifier">BOOST_LOCAL_FUNCTION</span><span class="special">(</span><span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">((</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">>))&</span>
|
||||
<span class="identifier">x</span><span class="special">,</span> <span class="keyword">int</span><span class="special">&</span> <span class="identifier">y</span><span class="special">)</span></code>).
|
||||
</p></div><div class="section boost_utility_identitytype_annex__implementation" title="Annex: Implementation"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="boost_utility_identitytype.annex__implementation"></a><a class="link" href="#boost_utility_identitytype.annex__implementation" title="Annex: Implementation">Annex:
|
||||
Implementation</a></h2></div></div></div><p>
|
||||
The implementation of this library macro is equivalent to the following: <sup>[<a name="boost_utility_identitytype.annex__implementation.f0" href="#ftn.boost_utility_identitytype.annex__implementation.f0" class="footnote">3</a>]</sup>
|
||||
</p><pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">function_traits</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||||
|
||||
<span class="preprocessor">#define</span> <span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">(</span><span class="identifier">parenthesized_type</span><span class="special">)</span> <span class="special">\</span>
|
||||
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">function_traits</span><span class="special"><</span><span class="keyword">void</span> <span class="identifier">parenthesized_type</span><span class="special">>::</span><span class="identifier">arg1_type</span>
|
||||
</pre><p>
|
||||
Essentially, the type is wrapped between round parenthesis <code class="computeroutput"><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span>
|
||||
<span class="keyword">char</span><span class="special">>)</span></code>
|
||||
so it can be passed as a single macro parameter even if it contains commas.
|
||||
Then the parenthesized type is transformed into the type of a function returning
|
||||
<code class="computeroutput"><span class="keyword">void</span></code> and with the specified type
|
||||
as the type of the first and only argument <code class="computeroutput"><span class="keyword">void</span>
|
||||
<span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">>)</span></code>. Finally, the type of the first argument
|
||||
<code class="computeroutput"><span class="identifier">arg1_type</span></code> is extracted at compile-time
|
||||
using the <code class="computeroutput"><span class="identifier">function_traits</span></code> meta-function
|
||||
therefore obtaining the original type from the parenthesized type (effectively
|
||||
stripping the extra parenthesis from around the specified type).
|
||||
</p></div><div class="section reference" title="Reference"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="reference"></a>Reference</h2></div></div></div><div class="section header_boost_utility_identity_type_hpp" title="Header <boost/utility/identity_type.hpp>"><div class="titlepage"><div><div><h3 class="title"><a name="header.boost.utility.identity_type_hpp"></a>Header <<a href="../../../../../boost/utility/identity_type.hpp" target="_top">boost/utility/identity_type.hpp</a>></h3></div></div></div><p>Wrap type expressions with round parenthesis so they can be passed to macros even if they contain commas. </p><pre class="synopsis">
|
||||
|
||||
<a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a>(parenthesized_type)</pre><div class="refentry" title="Macro BOOST_IDENTITY_TYPE"><a name="BOOST_IDENTITY_TYPE"></a><div class="titlepage"></div><div class="refnamediv"><h2><span class="refentrytitle">Macro BOOST_IDENTITY_TYPE</span></h2><p>BOOST_IDENTITY_TYPE — This macro allows to wrap the specified type expression within extra round parenthesis so the type can be passed as a single macro parameter even if it contains commas (not already wrapped within round parenthesis). </p></div><h2 class="refsynopsisdiv-title">Synopsis</h2><div class="refsynopsisdiv"><pre class="synopsis"><span class="comment">// In header: <<a class="link" href="#header.boost.utility.identity_type_hpp" title="Header <boost/utility/identity_type.hpp>">boost/utility/identity_type.hpp</a>>
|
||||
|
||||
</span>BOOST_IDENTITY_TYPE(parenthesized_type)</pre></div><div class="refsect1" title="Description"><a name="id554262"></a><h2>Description</h2><p><span class="bold"><strong>Parameters:</strong></span> </p><div class="informaltable"><table class="table"><colgroup><col><col></colgroup><tbody><tr><td><span class="bold"><strong><code class="computeroutput">parenthesized_type</code></strong></span></td><td>The type expression to be passed as macro parameter wrapped by a single set of round parenthesis <code class="computeroutput">(...)</code>. This type expression can contain an arbitrary number of commas. </td></tr></tbody></table></div><p>
|
||||
</p><p>This macro works on any C++03 compiler (it does not use variadic macros).</p><p>This macro must be prefixed by <code class="computeroutput">typename</code> when used within templates. Note that the compiler will not be able to automatically determine function template parameters when they are wrapped with this macro (these parameters need to be explicitly specified when calling the function template).</p><p>On some compilers (like GCC), using this macro on abstract types requires to add and remove a reference to the specified type. </p></div></div></div></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a id="ftn.boost_utility_identitytype.solution.f0" href="#boost_utility_identitytype.solution.f0" class="para">1</a>] </sup>
|
||||
Using variadic macros, it would be possible to require a single set of extra
|
||||
parenthesis <code class="computeroutput"><span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">(</span></code><code class="literal"><span class="emphasis"><em>type</em></span></code><code class="computeroutput"><span class="special">)</span></code> instead of two <code class="computeroutput"><span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">((</span></code><code class="literal"><span class="emphasis"><em>type</em></span></code><code class="computeroutput"><span class="special">))</span></code> but variadic macros are not part of C++03
|
||||
(even if nowadays they are supported by most modern compilers and they are
|
||||
also part of C++11).
|
||||
</p></div><div class="footnote"><p><sup>[<a id="ftn.boost_utility_identitytype.templates.f0" href="#boost_utility_identitytype.templates.f0" class="para">2</a>] </sup>
|
||||
This is because the implementation of <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code>
|
||||
wraps the specified type within a meta-function.
|
||||
</p></div><div class="footnote"><p><sup>[<a id="ftn.boost_utility_identitytype.annex__implementation.f0" href="#boost_utility_identitytype.annex__implementation.f0" class="para">3</a>] </sup>
|
||||
There is absolutely no guarantee that the macro is actually implemented using
|
||||
the code listed in this documentation. The listed code is for explanatory
|
||||
purposes only.
|
||||
</p></div></div></div></body></html>
|
165
identity_type/doc/identity_type.qbk
Normal file
165
identity_type/doc/identity_type.qbk
Normal file
@ -0,0 +1,165 @@
|
||||
|
||||
[/ Copyright (C) 2009-2012 Lorenzo Caminiti ]
|
||||
[/ Distributed under the Boost Software License, Version 1.0 ]
|
||||
[/ (see accompanying file LICENSE_1_0.txt or a copy at ]
|
||||
[/ http://www.boost.org/LICENSE_1_0.txt) ]
|
||||
[/ Home at http://www.boost.org/libs/utility/identity_type ]
|
||||
|
||||
[library Boost.Utility/IdentityType
|
||||
[quickbook 1.5]
|
||||
[version 1.0.0]
|
||||
[copyright 2009-2012 Lorenzo Caminiti]
|
||||
[purpose wraps types with round parenthesis]
|
||||
[license
|
||||
Distributed under the Boost Software License, Version 1.0
|
||||
(see accompanying file LICENSE_1_0.txt or a copy at
|
||||
[@http://www.boost.org/LICENSE_1_0.txt])
|
||||
]
|
||||
[authors [Caminiti <email>lorcaminiti@gmail.com</email>, Lorenzo]]
|
||||
[category Utilities]
|
||||
]
|
||||
|
||||
This library allows to wrap types within round parenthesis so they can always be passed as macro parameters.
|
||||
|
||||
[import ../test/var_error.cpp]
|
||||
[import ../test/var.cpp]
|
||||
[import ../test/template.cpp]
|
||||
[import ../test/abstract.cpp]
|
||||
[import ../test/paren.cpp]
|
||||
|
||||
[section Motivation]
|
||||
|
||||
Consider the following macro which declares a variable named `var`[^['n]] with the specified [^['type]] (see also [@../../test/var_error.cpp =var_error.cpp=]):
|
||||
|
||||
[var_error]
|
||||
|
||||
The first macro invocation works correctly declaring a variable named `var1` of type `int`.
|
||||
However, the second macro invocation fails generating a preprocessor error similar to the following:
|
||||
|
||||
[pre
|
||||
error: macro "VAR" passed 3 arguments, but takes just 2
|
||||
]
|
||||
|
||||
That is because the `std::map` type passed as the first macro parameter contains a comma `,` not wrapped by round parenthesis `()`.
|
||||
The preprocessor interprets that unwrapped comma as a separation between macro parameters concluding that a total of three (and not two) parameters are passed to the macro in the following order:
|
||||
|
||||
# `std::map<int`
|
||||
# `char>`
|
||||
# `2`
|
||||
|
||||
Note that, differently from the compiler, the preprocessor only recognizes round parenthesis `()`.
|
||||
Angular `<>` and squared `[]` parenthesis are not recognized by the preprocessor when parsing macro parameters.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Solution]
|
||||
|
||||
In some cases, it might be possible to workaround this issue by avoiding to pass the type expression to the macro all together.
|
||||
For example, in the case above a `typedef` could have been used to specify the type expression with the commas outside the macro (see also [@../../test/var.cpp =var.cpp=]):
|
||||
|
||||
[var_typedef]
|
||||
|
||||
When this is neither possible nor desired (e.g., see the function template `f` in the section below), this library header [headerref boost/utility/identity_type.hpp] defines a macro [macroref BOOST_IDENTITY_TYPE] which can be used to workaround the issue while keeping the type expression as one of the macro parameters (see also [@../../test/var.cpp =var.cpp=]).
|
||||
|
||||
[var_ok]
|
||||
|
||||
The [macroref BOOST_IDENTITY_TYPE] macro expands to an expression that evaluates (at compile-time) to the specified type.
|
||||
The specified type is never split into multiple macro parameters because it is always wrapped by a set of extra round parenthesis `()`.
|
||||
In fact, a total of two sets of round parenthesis must be used: The parenthesis to invoke the macro `BOOST_IDENTITY_TYPE(...)` plus the inner parenthesis to wrap the type passed to the macro `BOOST_IDENTITY_TYPE((...))`.
|
||||
|
||||
This macro works on any [@http://www.open-std.org/JTC1/SC22/WG21/docs/standards C++03] compiler (and it does not use [@http://en.wikipedia.org/wiki/Variadic_macro variadic macros]).
|
||||
[footnote
|
||||
Using variadic macros, it would be possible to require a single set of extra parenthesis `BOOST_IDENTITY_TYPE(`[^['type]]`)` instead of two `BOOST_IDENTITY_TYPE((`[^['type]]`))` but variadic macros are not part of C++03 (even if nowadays they are supported by most modern compilers and they are also part of C++11).
|
||||
]
|
||||
The authors originally developed and tested this library using GNU Compiler Collection (GCC) C++ 4.5.3 (with and without C++11 features enabled `-std=c++0x`) on Cygwin and Miscrosoft Visual C++ (MSVC) 8.0 on Windows 7.
|
||||
See the library [@http://www.boost.org/development/tests/release/developer/utility-identity_type.html regressions test results] for more information on supported compilers and platforms.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Templates]
|
||||
|
||||
This macro must be prefixed by `typename` when used within templates.
|
||||
For example, let's program a macro that declares a function parameter named `arg`[^['n]] with the specified [^['type]] (see also [@../../test/template.cpp =template.cpp=]):
|
||||
|
||||
[template_f_decl]
|
||||
[template_f_call]
|
||||
|
||||
However, note that the template parameter `char` must be manually specified when invoking the function as in `f<char>(a)`.
|
||||
In fact, when the [macroref BOOST_IDENTITY_TYPE] macro is used to wrap a function template parameter, the template parameter can no longer be automatically deduced by the compiler form the function call as `f(a)` would have done.
|
||||
[footnote
|
||||
This is because the implementation of [macroref BOOST_IDENTITY_TYPE] wraps the specified type within a meta-function.
|
||||
]
|
||||
(This limitation does not apply to class templates because class template parameters must always be explicitly specified.)
|
||||
In other words, without using the [macroref BOOST_IDENTITY_TYPE] macro, C++ would normally be able to automatically deduce the function template parameter as shown below:
|
||||
|
||||
[template_g_decl]
|
||||
[template_g_call]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Abstract Types]
|
||||
|
||||
On some compilers (e.g., GCC), using this macro on abstract types (i.e., classes with one or more pure virtual functions) generates a compiler error.
|
||||
This can be avoided by manipulating the type adding and removing a reference to it.
|
||||
|
||||
Let's program a macro that performs a static assertion on a [@http://en.wikipedia.org/wiki/Template_metaprogramming Template Meta-Programming] (TMP) meta-function (similarly to Boost.MPL [@http://www.boost.org/doc/libs/1_36_0/libs/mpl/doc/refmanual/assert.html `BOOST_MPL_ASSERT`]).
|
||||
The [macroref BOOST_IDENTITY_TYPE] macro can be used to pass a meta-function with multiple template parameters to the assert macro (so to handle the commas separating the template parameters).
|
||||
In this case, if the meta-function is an abstract type, it needs to be manipulated adding and removing a reference to it (see also [@../../test/abstract.cpp =abstract.cpp=]):
|
||||
|
||||
[abstract]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Annex: Usage]
|
||||
|
||||
The [macroref BOOST_IDENTITY_TYPE] macro can be used either when calling a user-defined macro (as shown by the examples so far), or internally when implementing a user-defined macro (as shown below).
|
||||
When [macroref BOOST_IDENTITY_TYPE] is used in the implementation of the user-defined macro, the caller of the user macro will have to specify the extra parenthesis (see also [@../../test/paren.cpp =paren.cpp=]):
|
||||
|
||||
[paren]
|
||||
|
||||
However, note that the caller will /always/ have to specify the extra parenthesis even when the macro parameters contain no comma:
|
||||
|
||||
[paren_always]
|
||||
|
||||
In some cases, using [macroref BOOST_IDENTITY_TYPE] in the implementation of the user-defined macro might provide the best syntax for the caller.
|
||||
For example, this is the case for `BOOST_MPL_ASSERT` because the majority of template meta-programming expressions contain unwrapped commas so it is less confusing for the user to always specify the extra parenthesis `((...))` instead of using [macroref BOOST_IDENTITY_TYPE]:
|
||||
|
||||
BOOST_MPL_ASSERT(( // Natural syntax.
|
||||
boost::mpl::and_<
|
||||
boost::is_const<T>
|
||||
, boost::is_reference<T>
|
||||
>
|
||||
));
|
||||
|
||||
However, in other situations it might be preferable to not require the extra parenthesis in the common cases and handle commas as special cases using [macroref BOOST_IDENTITY_TYPE].
|
||||
For example, this is the case for [@http://www.boost.org/libs/local_function `BOOST_LOCAL_FUNCTION`] for which always requiring the extra parenthesis `((...))` around the types would lead to an unnatural syntax for the local function signature:
|
||||
|
||||
int BOOST_LOCAL_FUNCTION( ((int&)) x, ((int&)) y ) { // Unnatural syntax.
|
||||
return x + y;
|
||||
} BOOST_LOCAL_FUNCTION_NAME(add)
|
||||
|
||||
Instead requiring the user to specify [macroref BOOST_IDENTITY_TYPE] only when needed allows for the more natural syntax `BOOST_LOCAL_FUNCTION(int& x, int& y)` in the common cases when the parameter types contain no comma (while still allowing to specify parameter types with commas as special cases using `BOOST_LOCAL_FUNCTION(BOOST_IDENTITY_TYPE((std::map<int, char>))& x, int& y)`).
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Annex: Implementation]
|
||||
|
||||
The implementation of this library macro is equivalent to the following:
|
||||
[footnote
|
||||
There is absolutely no guarantee that the macro is actually implemented using the code listed in this documentation.
|
||||
The listed code is for explanatory purposes only.
|
||||
]
|
||||
|
||||
#include <boost/type_traits/function_traits.hpp>
|
||||
|
||||
#define BOOST_IDENTITY_TYPE(parenthesized_type) \
|
||||
boost::function_traits<void parenthesized_type>::arg1_type
|
||||
|
||||
Essentially, the type is wrapped between round parenthesis `(std::map<int, char>)` so it can be passed as a single macro parameter even if it contains commas.
|
||||
Then the parenthesized type is transformed into the type of a function returning `void` and with the specified type as the type of the first and only argument `void (std::map<int, char>)`.
|
||||
Finally, the type of the first argument `arg1_type` is extracted at compile-time using the `function_traits` meta-function therefore obtaining the original type from the parenthesized type (effectively stripping the extra parenthesis from around the specified type).
|
||||
|
||||
[endsect]
|
||||
|
||||
[xinclude reference.xml]
|
||||
|
15
identity_type/index.html
Normal file
15
identity_type/index.html
Normal file
@ -0,0 +1,15 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="0; URL=doc/html/index.html">
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, click this
|
||||
<a href="doc/html/index.html">link</a> <hr>
|
||||
<p>Copyright © Lorenzo Caminiti, 2009-2012</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 a copy at
|
||||
<a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
|
||||
</body>
|
||||
</html>
|
16
identity_type/test/Jamfile.v2
Normal file
16
identity_type/test/Jamfile.v2
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
# Copyright (C) 2009-2012 Lorenzo Caminiti
|
||||
# Distributed under the Boost Software License, Version 1.0
|
||||
# (see accompanying file LICENSE_1_0.txt or a copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
# Home at http://www.boost.org/libs/utility/identity_type
|
||||
|
||||
import testing ;
|
||||
|
||||
compile-fail var_error.cpp ;
|
||||
run var.cpp ;
|
||||
run template.cpp ;
|
||||
run abstract.cpp ;
|
||||
run noncopyable.cpp ;
|
||||
run paren.cpp ;
|
||||
|
35
identity_type/test/abstract.cpp
Normal file
35
identity_type/test/abstract.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
|
||||
// Copyright (C) 2009-2012 Lorenzo Caminiti
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// (see accompanying file LICENSE_1_0.txt or a copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
// Home at http://www.boost.org/libs/utility/identity_type
|
||||
|
||||
#include <boost/utility/identity_type.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_traits/add_reference.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
|
||||
//[abstract
|
||||
#define TMP_ASSERT(metafunction) \
|
||||
BOOST_STATIC_ASSERT(metafunction::value)
|
||||
|
||||
template<typename T, bool b>
|
||||
struct abstract {
|
||||
static const bool value = b;
|
||||
virtual void f(T const& x) = 0; // Pure virtual function.
|
||||
};
|
||||
|
||||
TMP_ASSERT(
|
||||
boost::remove_reference< // Add and remove
|
||||
BOOST_IDENTITY_TYPE(( // reference for
|
||||
boost::add_reference< // abstract type.
|
||||
abstract<int, true>
|
||||
>::type
|
||||
))
|
||||
>::type
|
||||
);
|
||||
//]
|
||||
|
||||
int main() { return 0; }
|
||||
|
25
identity_type/test/noncopyable.cpp
Normal file
25
identity_type/test/noncopyable.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
// Copyright (C) 2009-2012 Lorenzo Caminiti
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// (see accompanying file LICENSE_1_0.txt or a copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
// Home at http://www.boost.org/libs/utility/identity_type
|
||||
|
||||
#include <boost/utility/identity_type.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
//[noncopyable
|
||||
#define TMP_ASSERT(metafunction) \
|
||||
BOOST_STATIC_ASSERT(metafunction::value)
|
||||
|
||||
template<typename T, T init>
|
||||
struct noncopyable : boost::noncopyable {
|
||||
static const T value = init;
|
||||
};
|
||||
|
||||
TMP_ASSERT(BOOST_IDENTITY_TYPE((noncopyable<bool, true>)));
|
||||
//]
|
||||
|
||||
int main() { return 0; }
|
||||
|
35
identity_type/test/paren.cpp
Normal file
35
identity_type/test/paren.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
|
||||
// Copyright (C) 2009-2012 Lorenzo Caminiti
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// (see accompanying file LICENSE_1_0.txt or a copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
// Home at http://www.boost.org/libs/utility/identity_type
|
||||
|
||||
#include <boost/utility/identity_type.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_traits/is_const.hpp>
|
||||
#include <map>
|
||||
|
||||
//[paren
|
||||
#define TMP_ASSERT_PAREN(parenthesized_metafunction) \
|
||||
/* use `BOOST_IDENTITY_TYPE` in macro definition instead of invocation */ \
|
||||
BOOST_STATIC_ASSERT(BOOST_IDENTITY_TYPE(parenthesized_metafunction)::value)
|
||||
|
||||
#define TMP_ASSERT(metafunction) \
|
||||
BOOST_STATIC_ASSERT(metafunction::value)
|
||||
|
||||
// Specify only extra parenthesis `((...))`.
|
||||
TMP_ASSERT_PAREN((boost::is_const<std::map<int, char> const>));
|
||||
|
||||
// Specify both the extra parenthesis `((...))` and `BOOST_IDENTITY_TYPE` macro.
|
||||
TMP_ASSERT(BOOST_IDENTITY_TYPE((boost::is_const<std::map<int, char> const>)));
|
||||
//]
|
||||
|
||||
//[paren_always
|
||||
TMP_ASSERT_PAREN((boost::is_const<int const>)); // Always extra `((...))`.
|
||||
|
||||
TMP_ASSERT(boost::is_const<int const>); // No extra `((...))` and no macro.
|
||||
//]
|
||||
|
||||
int main() { return 0; }
|
||||
|
48
identity_type/test/template.cpp
Normal file
48
identity_type/test/template.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
|
||||
// Copyright (C) 2009-2012 Lorenzo Caminiti
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// (see accompanying file LICENSE_1_0.txt or a copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
// Home at http://www.boost.org/libs/utility/identity_type
|
||||
|
||||
#include <boost/utility/identity_type.hpp>
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
|
||||
//[template_f_decl
|
||||
#define ARG(type, n) type arg ## n
|
||||
|
||||
template<typename T>
|
||||
void f( // Prefix macro with `typename` in templates.
|
||||
ARG(typename BOOST_IDENTITY_TYPE((std::map<int, T>)), 1)
|
||||
) {
|
||||
std::cout << arg1[0] << std::endl;
|
||||
}
|
||||
//]
|
||||
|
||||
//[template_g_decl
|
||||
template<typename T>
|
||||
void g(
|
||||
std::map<int, T> arg1
|
||||
) {
|
||||
std::cout << arg1[0] << std::endl;
|
||||
}
|
||||
//]
|
||||
|
||||
int main() {
|
||||
//[template_f_call
|
||||
std::map<int, char> a;
|
||||
a[0] = 'a';
|
||||
|
||||
f<char>(a); // OK...
|
||||
// f(a); // ... but error.
|
||||
//]
|
||||
|
||||
//[template_g_call
|
||||
g<char>(a); // OK...
|
||||
g(a); // ... and also OK.
|
||||
//]
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
26
identity_type/test/var.cpp
Normal file
26
identity_type/test/var.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
|
||||
// Copyright (C) 2009-2012 Lorenzo Caminiti
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// (see accompanying file LICENSE_1_0.txt or a copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
// Home at http://www.boost.org/libs/utility/identity_type
|
||||
|
||||
#include <map>
|
||||
|
||||
#define VAR(type, n) type var ## n
|
||||
|
||||
VAR(int, 1); // OK.
|
||||
|
||||
//[var_typedef
|
||||
typedef std::map<int, char> map_type;
|
||||
VAR(map_type, 3); // OK.
|
||||
//]
|
||||
|
||||
//[var_ok
|
||||
#include <boost/utility/identity_type.hpp>
|
||||
|
||||
VAR(BOOST_IDENTITY_TYPE((std::map<int, char>)), 4); // OK.
|
||||
//]
|
||||
|
||||
int main() { return 0; }
|
||||
|
18
identity_type/test/var_error.cpp
Normal file
18
identity_type/test/var_error.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
// Copyright (C) 2009-2012 Lorenzo Caminiti
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// (see accompanying file LICENSE_1_0.txt or a copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
// Home at http://www.boost.org/libs/utility/identity_type
|
||||
|
||||
#include <map>
|
||||
|
||||
//[var_error
|
||||
#define VAR(type, n) type var ## n
|
||||
|
||||
VAR(int, 1); // OK.
|
||||
VAR(std::map<int, char>, 2); // Error.
|
||||
//]
|
||||
|
||||
int main() { return 0; }
|
||||
|
19
in_place_factories.html
Normal file
19
in_place_factories.html
Normal file
@ -0,0 +1,19 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Boost.Utility</title>
|
||||
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="./doc/html/utility/utilities/in_place_factory.html">./doc/html/utility/utilities/in_place_factory.html</a>
|
||||
<hr>
|
||||
<tt>
|
||||
Boost.Utility<br>
|
||||
<br>
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||
<br>
|
||||
</tt>
|
||||
</body>
|
||||
</html>
|
@ -1,10 +1,11 @@
|
||||
// (C) Copyright Boost.org 2000. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
|
||||
// Use, modification and distribution are 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/utility for most recent version including documentation.
|
||||
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
// See boost/detail/call_traits.hpp and boost/detail/ob_call_traits.hpp
|
||||
// See boost/detail/call_traits.hpp
|
||||
// for full copyright notices.
|
||||
|
||||
#ifndef BOOST_CALL_TRAITS_HPP
|
||||
@ -14,10 +15,6 @@
|
||||
#include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
#include <boost/detail/ob_call_traits.hpp>
|
||||
#else
|
||||
#include <boost/detail/call_traits.hpp>
|
||||
#endif
|
||||
|
||||
#endif // BOOST_CALL_TRAITS_HPP
|
||||
|
@ -1,10 +1,11 @@
|
||||
// (C) Copyright Boost.org 2000. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
|
||||
// Use, modification and distribution are 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/utility for most recent version including documentation.
|
||||
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
// See boost/detail/compressed_pair.hpp and boost/detail/ob_compressed_pair.hpp
|
||||
// See boost/detail/compressed_pair.hpp
|
||||
// for full copyright notices.
|
||||
|
||||
#ifndef BOOST_COMPRESSED_PAIR_HPP
|
||||
@ -14,10 +15,6 @@
|
||||
#include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
#include <boost/detail/ob_compressed_pair.hpp>
|
||||
#else
|
||||
#include <boost/detail/compressed_pair.hpp>
|
||||
#endif
|
||||
|
||||
#endif // BOOST_COMPRESSED_PAIR_HPP
|
||||
|
@ -1,10 +1,9 @@
|
||||
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
|
||||
// Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
// Use, modification and distribution are 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/utility for most recent version including documentation.
|
||||
|
||||
// call_traits: defines typedefs for function usage
|
||||
// (see libs/utility/call_traits.htm)
|
||||
@ -22,34 +21,51 @@
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
#include <boost/config.hpp>
|
||||
#endif
|
||||
#include <cstddef>
|
||||
|
||||
#ifndef BOOST_ARITHMETIC_TYPE_TRAITS_HPP
|
||||
#include <boost/type_traits/arithmetic_traits.hpp>
|
||||
#endif
|
||||
#ifndef BOOST_COMPOSITE_TYPE_TRAITS_HPP
|
||||
#include <boost/type_traits/composite_traits.hpp>
|
||||
#endif
|
||||
#include <boost/type_traits/is_arithmetic.hpp>
|
||||
#include <boost/type_traits/is_enum.hpp>
|
||||
#include <boost/type_traits/is_pointer.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
namespace boost{
|
||||
|
||||
namespace detail{
|
||||
|
||||
template <typename T, bool small_>
|
||||
struct ct_imp2
|
||||
{
|
||||
typedef const T& param_type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ct_imp2<T, true>
|
||||
{
|
||||
typedef const T param_type;
|
||||
};
|
||||
|
||||
template <typename T, bool isp, bool b1, bool b2>
|
||||
struct ct_imp
|
||||
{
|
||||
typedef const T& param_type;
|
||||
};
|
||||
|
||||
template <typename T, bool isp>
|
||||
struct ct_imp<T, isp, true, true>
|
||||
template <typename T, bool isp, bool b2>
|
||||
struct ct_imp<T, isp, true, b2>
|
||||
{
|
||||
typedef T const param_type;
|
||||
typedef typename ct_imp2<T, sizeof(T) <= sizeof(void*)>::param_type param_type;
|
||||
};
|
||||
|
||||
template <typename T, bool isp, bool b1>
|
||||
struct ct_imp<T, isp, b1, true>
|
||||
{
|
||||
typedef typename ct_imp2<T, sizeof(T) <= sizeof(void*)>::param_type param_type;
|
||||
};
|
||||
|
||||
template <typename T, bool b1, bool b2>
|
||||
struct ct_imp<T, true, b1, b2>
|
||||
{
|
||||
typedef T const param_type;
|
||||
typedef const T param_type;
|
||||
};
|
||||
|
||||
}
|
||||
@ -67,7 +83,12 @@ public:
|
||||
// however compiler bugs prevent this - instead pass three bool's to
|
||||
// ct_imp<T,bool,bool,bool> and add an extra partial specialisation
|
||||
// of ct_imp to handle the logic. (JM)
|
||||
typedef typename detail::ct_imp<T, ::boost::is_pointer<typename remove_const<T>::type>::value, ::boost::is_arithmetic<typename remove_const<T>::type>::value, sizeof(T) <= sizeof(void*)>::param_type param_type;
|
||||
typedef typename boost::detail::ct_imp<
|
||||
T,
|
||||
::boost::is_pointer<T>::value,
|
||||
::boost::is_arithmetic<T>::value,
|
||||
::boost::is_enum<T>::value
|
||||
>::param_type param_type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
@ -79,7 +100,7 @@ struct call_traits<T&>
|
||||
typedef T& param_type; // hh removed const
|
||||
};
|
||||
|
||||
#if defined(__BORLANDC__) && (__BORLANDC__ <= 0x551)
|
||||
#if BOOST_WORKAROUND( BOOST_BORLANDC, < 0x5A0 )
|
||||
// these are illegal specialisations; cv-qualifies applied to
|
||||
// references have no effect according to [8.3.2p1],
|
||||
// C++ Builder requires them though as it treats cv-qualified
|
||||
@ -108,8 +129,17 @@ struct call_traits<T&const volatile>
|
||||
typedef const T& const_reference;
|
||||
typedef T& param_type; // hh removed const
|
||||
};
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
struct call_traits< T * >
|
||||
{
|
||||
typedef T * value_type;
|
||||
typedef T * & reference;
|
||||
typedef T * const & const_reference;
|
||||
typedef T * const param_type; // hh removed const
|
||||
};
|
||||
#endif
|
||||
#if !defined(BOOST_NO_ARRAY_TYPE_SPECIALIZATIONS)
|
||||
template <typename T, std::size_t N>
|
||||
struct call_traits<T [N]>
|
||||
{
|
||||
@ -135,6 +165,7 @@ public:
|
||||
typedef const array_type& const_reference;
|
||||
typedef const T* const param_type;
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,14 +1,16 @@
|
||||
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
|
||||
// Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
// Use, modification and distribution are 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/utility for most recent version including documentation.
|
||||
|
||||
// compressed_pair: pair that "compresses" empty members
|
||||
// (see libs/utility/compressed_pair.htm)
|
||||
// (see libs/utility/doc/html/compressed_pair.html)
|
||||
//
|
||||
// JM changes 25 Jan 2004:
|
||||
// For the case where T1 == T2 and both are empty, then first() and second()
|
||||
// should return different objects.
|
||||
// JM changes 25 Jan 2000:
|
||||
// Removed default arguments from compressed_pair_switch to get
|
||||
// C++ Builder 4 to accept them
|
||||
@ -19,23 +21,36 @@
|
||||
#define BOOST_DETAIL_COMPRESSED_PAIR_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#ifndef BOOST_OBJECT_TYPE_TRAITS_HPP
|
||||
#include <boost/type_traits/object_traits.hpp>
|
||||
#endif
|
||||
#ifndef BOOST_SAME_TRAITS_HPP
|
||||
#include <boost/type_traits/same_traits.hpp>
|
||||
#endif
|
||||
#ifndef BOOST_CALL_TRAITS_HPP
|
||||
#include <boost/call_traits.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/type_traits/remove_cv.hpp>
|
||||
#include <boost/type_traits/is_empty.hpp>
|
||||
#include <boost/type_traits/is_final.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/call_traits.hpp>
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4512)
|
||||
#endif
|
||||
namespace boost
|
||||
{
|
||||
|
||||
template <class T1, class T2>
|
||||
class compressed_pair;
|
||||
|
||||
|
||||
// compressed_pair
|
||||
|
||||
namespace details
|
||||
{
|
||||
template<class T, bool E = boost::is_final<T>::value>
|
||||
struct compressed_pair_empty
|
||||
: ::boost::false_type { };
|
||||
|
||||
template<class T>
|
||||
struct compressed_pair_empty<T, false>
|
||||
: ::boost::is_empty<T> { };
|
||||
|
||||
// JM altered 26 Jan 2000:
|
||||
template <class T1, class T2, bool IsSame, bool FirstEmpty, bool SecondEmpty>
|
||||
struct compressed_pair_switch;
|
||||
@ -104,10 +119,10 @@ namespace details
|
||||
compressed_pair_imp(first_param_type x, second_param_type y)
|
||||
: first_(x), second_(y) {}
|
||||
|
||||
explicit compressed_pair_imp(first_param_type x)
|
||||
compressed_pair_imp(first_param_type x)
|
||||
: first_(x) {}
|
||||
|
||||
explicit compressed_pair_imp(second_param_type y)
|
||||
compressed_pair_imp(second_param_type y)
|
||||
: second_(y) {}
|
||||
|
||||
first_reference first() {return first_;}
|
||||
@ -116,10 +131,10 @@ namespace details
|
||||
second_reference second() {return second_;}
|
||||
second_const_reference second() const {return second_;}
|
||||
|
||||
void swap(compressed_pair_imp& y)
|
||||
void swap(::boost::compressed_pair<T1, T2>& y)
|
||||
{
|
||||
cp_swap(first_, y.first_);
|
||||
cp_swap(second_, y.second_);
|
||||
cp_swap(first_, y.first());
|
||||
cp_swap(second_, y.second());
|
||||
}
|
||||
private:
|
||||
first_type first_;
|
||||
@ -130,7 +145,7 @@ namespace details
|
||||
|
||||
template <class T1, class T2>
|
||||
class compressed_pair_imp<T1, T2, 1>
|
||||
: private T1
|
||||
: protected ::boost::remove_cv<T1>::type
|
||||
{
|
||||
public:
|
||||
typedef T1 first_type;
|
||||
@ -147,10 +162,10 @@ namespace details
|
||||
compressed_pair_imp(first_param_type x, second_param_type y)
|
||||
: first_type(x), second_(y) {}
|
||||
|
||||
explicit compressed_pair_imp(first_param_type x)
|
||||
compressed_pair_imp(first_param_type x)
|
||||
: first_type(x) {}
|
||||
|
||||
explicit compressed_pair_imp(second_param_type y)
|
||||
compressed_pair_imp(second_param_type y)
|
||||
: second_(y) {}
|
||||
|
||||
first_reference first() {return *this;}
|
||||
@ -159,10 +174,10 @@ namespace details
|
||||
second_reference second() {return second_;}
|
||||
second_const_reference second() const {return second_;}
|
||||
|
||||
void swap(compressed_pair_imp& y)
|
||||
void swap(::boost::compressed_pair<T1,T2>& y)
|
||||
{
|
||||
// no need to swap empty base class:
|
||||
cp_swap(second_, y.second_);
|
||||
cp_swap(second_, y.second());
|
||||
}
|
||||
private:
|
||||
second_type second_;
|
||||
@ -172,7 +187,7 @@ namespace details
|
||||
|
||||
template <class T1, class T2>
|
||||
class compressed_pair_imp<T1, T2, 2>
|
||||
: private T2
|
||||
: protected ::boost::remove_cv<T2>::type
|
||||
{
|
||||
public:
|
||||
typedef T1 first_type;
|
||||
@ -189,10 +204,10 @@ namespace details
|
||||
compressed_pair_imp(first_param_type x, second_param_type y)
|
||||
: second_type(y), first_(x) {}
|
||||
|
||||
explicit compressed_pair_imp(first_param_type x)
|
||||
compressed_pair_imp(first_param_type x)
|
||||
: first_(x) {}
|
||||
|
||||
explicit compressed_pair_imp(second_param_type y)
|
||||
compressed_pair_imp(second_param_type y)
|
||||
: second_type(y) {}
|
||||
|
||||
first_reference first() {return first_;}
|
||||
@ -201,10 +216,10 @@ namespace details
|
||||
second_reference second() {return *this;}
|
||||
second_const_reference second() const {return *this;}
|
||||
|
||||
void swap(compressed_pair_imp& y)
|
||||
void swap(::boost::compressed_pair<T1,T2>& y)
|
||||
{
|
||||
// no need to swap empty base class:
|
||||
cp_swap(first_, y.first_);
|
||||
cp_swap(first_, y.first());
|
||||
}
|
||||
|
||||
private:
|
||||
@ -215,8 +230,8 @@ namespace details
|
||||
|
||||
template <class T1, class T2>
|
||||
class compressed_pair_imp<T1, T2, 3>
|
||||
: private T1,
|
||||
private T2
|
||||
: protected ::boost::remove_cv<T1>::type,
|
||||
protected ::boost::remove_cv<T2>::type
|
||||
{
|
||||
public:
|
||||
typedef T1 first_type;
|
||||
@ -233,10 +248,10 @@ namespace details
|
||||
compressed_pair_imp(first_param_type x, second_param_type y)
|
||||
: first_type(x), second_type(y) {}
|
||||
|
||||
explicit compressed_pair_imp(first_param_type x)
|
||||
compressed_pair_imp(first_param_type x)
|
||||
: first_type(x) {}
|
||||
|
||||
explicit compressed_pair_imp(second_param_type y)
|
||||
compressed_pair_imp(second_param_type y)
|
||||
: second_type(y) {}
|
||||
|
||||
first_reference first() {return *this;}
|
||||
@ -246,16 +261,19 @@ namespace details
|
||||
second_const_reference second() const {return *this;}
|
||||
//
|
||||
// no need to swap empty bases:
|
||||
void swap(compressed_pair_imp&) {}
|
||||
void swap(::boost::compressed_pair<T1,T2>&) {}
|
||||
};
|
||||
|
||||
// JM
|
||||
// 4 T1 == T2, T1 and T2 both empty
|
||||
// Note does not actually store an instance of T2 at all -
|
||||
// but reuses T1 base class for both first() and second().
|
||||
// Originally this did not store an instance of T2 at all
|
||||
// but that led to problems beause it meant &x.first() == &x.second()
|
||||
// which is not true for any other kind of pair, so now we store an instance
|
||||
// of T2 just in case the user is relying on first() and second() returning
|
||||
// different objects (albeit both empty).
|
||||
template <class T1, class T2>
|
||||
class compressed_pair_imp<T1, T2, 4>
|
||||
: private T1
|
||||
: protected ::boost::remove_cv<T1>::type
|
||||
{
|
||||
public:
|
||||
typedef T1 first_type;
|
||||
@ -269,20 +287,21 @@ namespace details
|
||||
|
||||
compressed_pair_imp() {}
|
||||
|
||||
compressed_pair_imp(first_param_type x, second_param_type)
|
||||
: first_type(x) {}
|
||||
compressed_pair_imp(first_param_type x, second_param_type y)
|
||||
: first_type(x), m_second(y) {}
|
||||
|
||||
explicit compressed_pair_imp(first_param_type x)
|
||||
: first_type(x) {}
|
||||
compressed_pair_imp(first_param_type x)
|
||||
: first_type(x), m_second(x) {}
|
||||
|
||||
first_reference first() {return *this;}
|
||||
first_const_reference first() const {return *this;}
|
||||
|
||||
second_reference second() {return *this;}
|
||||
second_const_reference second() const {return *this;}
|
||||
second_reference second() {return m_second;}
|
||||
second_const_reference second() const {return m_second;}
|
||||
|
||||
void swap(compressed_pair_imp&) {}
|
||||
void swap(::boost::compressed_pair<T1,T2>&) {}
|
||||
private:
|
||||
T2 m_second;
|
||||
};
|
||||
|
||||
// 5 T1 == T2 and are not empty: //JM
|
||||
@ -305,7 +324,7 @@ namespace details
|
||||
compressed_pair_imp(first_param_type x, second_param_type y)
|
||||
: first_(x), second_(y) {}
|
||||
|
||||
explicit compressed_pair_imp(first_param_type x)
|
||||
compressed_pair_imp(first_param_type x)
|
||||
: first_(x), second_(x) {}
|
||||
|
||||
first_reference first() {return first_;}
|
||||
@ -314,10 +333,10 @@ namespace details
|
||||
second_reference second() {return second_;}
|
||||
second_const_reference second() const {return second_;}
|
||||
|
||||
void swap(compressed_pair_imp<T1, T2, 5>& y)
|
||||
void swap(::boost::compressed_pair<T1, T2>& y)
|
||||
{
|
||||
cp_swap(first_, y.first_);
|
||||
cp_swap(second_, y.second_);
|
||||
cp_swap(first_, y.first());
|
||||
cp_swap(second_, y.second());
|
||||
}
|
||||
private:
|
||||
first_type first_;
|
||||
@ -328,13 +347,15 @@ namespace details
|
||||
|
||||
template <class T1, class T2>
|
||||
class compressed_pair
|
||||
: private ::boost::details::compressed_pair_imp<T1, T2,
|
||||
#ifndef BOOST_UTILITY_DOCS
|
||||
: private ::boost::details::compressed_pair_imp<T1, T2,
|
||||
::boost::details::compressed_pair_switch<
|
||||
T1,
|
||||
T2,
|
||||
::boost::is_same<typename remove_cv<T1>::type, typename remove_cv<T2>::type>::value,
|
||||
::boost::is_empty<T1>::value,
|
||||
::boost::is_empty<T2>::value>::value>
|
||||
::boost::details::compressed_pair_empty<T1>::value,
|
||||
::boost::details::compressed_pair_empty<T2>::value>::value>
|
||||
#endif // BOOST_UTILITY_DOCS
|
||||
{
|
||||
private:
|
||||
typedef details::compressed_pair_imp<T1, T2,
|
||||
@ -342,8 +363,8 @@ private:
|
||||
T1,
|
||||
T2,
|
||||
::boost::is_same<typename remove_cv<T1>::type, typename remove_cv<T2>::type>::value,
|
||||
::boost::is_empty<T1>::value,
|
||||
::boost::is_empty<T2>::value>::value> base;
|
||||
::boost::details::compressed_pair_empty<T1>::value,
|
||||
::boost::details::compressed_pair_empty<T2>::value>::value> base;
|
||||
public:
|
||||
typedef T1 first_type;
|
||||
typedef T2 second_type;
|
||||
@ -373,13 +394,15 @@ public:
|
||||
//
|
||||
template <class T>
|
||||
class compressed_pair<T, T>
|
||||
#ifndef BOOST_UTILITY_DOCS
|
||||
: private details::compressed_pair_imp<T, T,
|
||||
::boost::details::compressed_pair_switch<
|
||||
T,
|
||||
T,
|
||||
::boost::is_same<typename remove_cv<T>::type, typename remove_cv<T>::type>::value,
|
||||
::boost::is_empty<T>::value,
|
||||
::boost::is_empty<T>::value>::value>
|
||||
::boost::details::compressed_pair_empty<T>::value,
|
||||
::boost::details::compressed_pair_empty<T>::value>::value>
|
||||
#endif // BOOST_UTILITY_DOCS
|
||||
{
|
||||
private:
|
||||
typedef details::compressed_pair_imp<T, T,
|
||||
@ -387,8 +410,8 @@ private:
|
||||
T,
|
||||
T,
|
||||
::boost::is_same<typename remove_cv<T>::type, typename remove_cv<T>::type>::value,
|
||||
::boost::is_empty<T>::value,
|
||||
::boost::is_empty<T>::value>::value> base;
|
||||
::boost::details::compressed_pair_empty<T>::value,
|
||||
::boost::details::compressed_pair_empty<T>::value>::value> base;
|
||||
public:
|
||||
typedef T first_type;
|
||||
typedef T second_type;
|
||||
@ -401,7 +424,10 @@ public:
|
||||
|
||||
compressed_pair() : base() {}
|
||||
compressed_pair(first_param_type x, second_param_type y) : base(x, y) {}
|
||||
explicit compressed_pair(first_param_type x) : base(x) {}
|
||||
#if !(defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530))
|
||||
explicit
|
||||
#endif
|
||||
compressed_pair(first_param_type x) : base(x) {}
|
||||
|
||||
first_reference first() {return base::first();}
|
||||
first_const_reference first() const {return base::first();}
|
||||
@ -409,7 +435,7 @@ public:
|
||||
second_reference second() {return base::second();}
|
||||
second_const_reference second() const {return base::second();}
|
||||
|
||||
void swap(compressed_pair& y) { base::swap(y); }
|
||||
void swap(::boost::compressed_pair<T,T>& y) { base::swap(y); }
|
||||
};
|
||||
|
||||
template <class T1, class T2>
|
||||
@ -422,7 +448,9 @@ swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
|
||||
|
||||
} // boost
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // BOOST_DETAIL_COMPRESSED_PAIR_HPP
|
||||
|
||||
|
||||
|
||||
|
@ -1,128 +0,0 @@
|
||||
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
|
||||
// Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
//
|
||||
// Crippled version for crippled compilers:
|
||||
// see libs/utility/call_traits.htm
|
||||
//
|
||||
|
||||
/* Release notes:
|
||||
01st October 2000:
|
||||
Fixed call_traits on VC6, using "poor man's partial specialisation",
|
||||
using ideas taken from "Generative programming" by Krzysztof Czarnecki
|
||||
& Ulrich Eisenecker.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_OB_CALL_TRAITS_HPP
|
||||
#define BOOST_OB_CALL_TRAITS_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
#include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_ARITHMETIC_TYPE_TRAITS_HPP
|
||||
#include <boost/type_traits/arithmetic_traits.hpp>
|
||||
#endif
|
||||
#ifndef BOOST_COMPOSITE_TYPE_TRAITS_HPP
|
||||
#include <boost/type_traits/composite_traits.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost{
|
||||
|
||||
#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES)
|
||||
//
|
||||
// use member templates to emulate
|
||||
// partial specialisation:
|
||||
//
|
||||
namespace detail{
|
||||
|
||||
template <class T>
|
||||
struct standard_call_traits
|
||||
{
|
||||
typedef T value_type;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef const T& param_type;
|
||||
};
|
||||
template <class T>
|
||||
struct simple_call_traits
|
||||
{
|
||||
typedef T value_type;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef const T param_type;
|
||||
};
|
||||
template <class T>
|
||||
struct reference_call_traits
|
||||
{
|
||||
typedef T value_type;
|
||||
typedef T reference;
|
||||
typedef T const_reference;
|
||||
typedef T param_type;
|
||||
};
|
||||
template <bool simple, bool reference>
|
||||
struct call_traits_chooser
|
||||
{
|
||||
template <class T>
|
||||
struct rebind
|
||||
{
|
||||
typedef standard_call_traits<T> type;
|
||||
};
|
||||
};
|
||||
template <>
|
||||
struct call_traits_chooser<true, false>
|
||||
{
|
||||
template <class T>
|
||||
struct rebind
|
||||
{
|
||||
typedef simple_call_traits<T> type;
|
||||
};
|
||||
};
|
||||
template <>
|
||||
struct call_traits_chooser<false, true>
|
||||
{
|
||||
template <class T>
|
||||
struct rebind
|
||||
{
|
||||
typedef reference_call_traits<T> type;
|
||||
};
|
||||
};
|
||||
} // namespace detail
|
||||
template <typename T>
|
||||
struct call_traits
|
||||
{
|
||||
private:
|
||||
typedef detail::call_traits_chooser<(is_pointer<T>::value || is_arithmetic<T>::value) && sizeof(T) <= sizeof(void*), is_reference<T>::value> chooser;
|
||||
typedef typename chooser::template rebind<T> bound_type;
|
||||
typedef typename bound_type::type call_traits_type;
|
||||
public:
|
||||
typedef typename call_traits_type::value_type value_type;
|
||||
typedef typename call_traits_type::reference reference;
|
||||
typedef typename call_traits_type::const_reference const_reference;
|
||||
typedef typename call_traits_type::param_type param_type;
|
||||
};
|
||||
|
||||
#else
|
||||
//
|
||||
// sorry call_traits is completely non-functional
|
||||
// blame your broken compiler:
|
||||
//
|
||||
|
||||
template <typename T>
|
||||
struct call_traits
|
||||
{
|
||||
typedef T value_type;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef const T& param_type;
|
||||
};
|
||||
|
||||
#endif // member templates
|
||||
|
||||
}
|
||||
|
||||
#endif // BOOST_OB_CALL_TRAITS_HPP
|
@ -1,17 +1,16 @@
|
||||
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
|
||||
// Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
// Use, modification and distribution are 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/utility for most recent version including documentation.
|
||||
// see libs/utility/compressed_pair.hpp
|
||||
//
|
||||
/* Release notes:
|
||||
20 Jan 2001:
|
||||
Fixed obvious bugs (David Abrahams)
|
||||
07 Oct 2000:
|
||||
Added better single argument constructor support.
|
||||
07 Oct 2000:
|
||||
Added better single argument constructor support.
|
||||
03 Oct 2000:
|
||||
Added VC6 support (JM).
|
||||
23rd July 2000:
|
||||
@ -21,10 +20,11 @@
|
||||
- John Maddock Jan 2000.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BOOST_UTILITY_DOCS
|
||||
#ifndef BOOST_OB_COMPRESSED_PAIR_HPP
|
||||
#define BOOST_OB_COMPRESSED_PAIR_HPP
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#ifndef BOOST_OBJECT_TYPE_TRAITS_HPP
|
||||
#include <boost/type_traits/object_traits.hpp>
|
||||
@ -38,7 +38,7 @@
|
||||
|
||||
namespace boost
|
||||
{
|
||||
#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES)
|
||||
#ifdef BOOST_MSVC6_MEMBER_TEMPLATES
|
||||
//
|
||||
// use member templates to emulate
|
||||
// partial specialisation. Note that due to
|
||||
@ -168,17 +168,6 @@ public:
|
||||
compressed_pair_1(const ::boost::compressed_pair<T1,T2>& x)
|
||||
: T2(x.second()), _first(x.first()) {}
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
// Total weirdness. If the assignment to _first is moved after
|
||||
// the call to the inherited operator=, then this breaks graph/test/graph.cpp
|
||||
// by way of iterator_adaptor.
|
||||
compressed_pair_1& operator=(const compressed_pair_1& x) {
|
||||
_first = x._first;
|
||||
T2::operator=(x);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
first_reference first() { return _first; }
|
||||
first_const_reference first() const { return _first; }
|
||||
|
||||
@ -293,22 +282,24 @@ public:
|
||||
typedef typename call_traits<second_type>::const_reference second_const_reference;
|
||||
|
||||
compressed_pair_4() : T1() {}
|
||||
compressed_pair_4(first_param_type x, second_param_type) : T1(x) {}
|
||||
compressed_pair_4(first_param_type x, second_param_type y) : T1(x), m_second(y) {}
|
||||
// only one single argument constructor since T1 == T2
|
||||
explicit compressed_pair_4(first_param_type x) : T1(x) {}
|
||||
explicit compressed_pair_4(first_param_type x) : T1(x), m_second(x) {}
|
||||
compressed_pair_4(const ::boost::compressed_pair<T1,T2>& x)
|
||||
: T1(x.first()){}
|
||||
: T1(x.first()), m_second(x.second()) {}
|
||||
|
||||
first_reference first() { return *this; }
|
||||
first_const_reference first() const { return *this; }
|
||||
|
||||
second_reference second() { return *this; }
|
||||
second_const_reference second() const { return *this; }
|
||||
second_reference second() { return m_second; }
|
||||
second_const_reference second() const { return m_second; }
|
||||
|
||||
void swap(compressed_pair_4& y)
|
||||
{
|
||||
// no need to swap empty base classes:
|
||||
}
|
||||
private:
|
||||
T2 m_second;
|
||||
};
|
||||
|
||||
// T1 == T2, not empty
|
||||
@ -504,6 +495,4 @@ inline void swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
|
||||
} // boost
|
||||
|
||||
#endif // BOOST_OB_COMPRESSED_PAIR_HPP
|
||||
|
||||
|
||||
|
||||
#endif // BOOST_UTILITY_DOCS
|
||||
|
File diff suppressed because it is too large
Load Diff
951
include/boost/operators_v1.hpp
Normal file
951
include/boost/operators_v1.hpp
Normal file
@ -0,0 +1,951 @@
|
||||
// Boost operators.hpp header file ----------------------------------------//
|
||||
|
||||
// (C) Copyright David Abrahams, Jeremy Siek, Daryle Walker 1999-2001.
|
||||
// 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/utility/operators.htm for documentation.
|
||||
|
||||
// Revision History
|
||||
// 22 Feb 16 Preserve old work-arounds. (Daniel Frey)
|
||||
// 16 Dec 10 Limit warning suppression for 4284 to older versions of VC++
|
||||
// (Matthew Bradbury, fixes #4432)
|
||||
// 07 Aug 08 Added "euclidean" spelling. (Daniel Frey)
|
||||
// 03 Apr 08 Make sure "convertible to bool" is sufficient
|
||||
// for T::operator<, etc. (Daniel Frey)
|
||||
// 24 May 07 Changed empty_base to depend on T, see
|
||||
// http://svn.boost.org/trac/boost/ticket/979
|
||||
// 21 Oct 02 Modified implementation of operators to allow compilers with a
|
||||
// correct named return value optimization (NRVO) to produce optimal
|
||||
// code. (Daniel Frey)
|
||||
// 02 Dec 01 Bug fixed in random_access_iteratable. (Helmut Zeisel)
|
||||
// 28 Sep 01 Factored out iterator operator groups. (Daryle Walker)
|
||||
// 27 Aug 01 'left' form for non commutative operators added;
|
||||
// additional classes for groups of related operators added;
|
||||
// workaround for empty base class optimization
|
||||
// bug of GCC 3.0 (Helmut Zeisel)
|
||||
// 25 Jun 01 output_iterator_helper changes: removed default template
|
||||
// parameters, added support for self-proxying, additional
|
||||
// documentation and tests (Aleksey Gurtovoy)
|
||||
// 29 May 01 Added operator classes for << and >>. Added input and output
|
||||
// iterator helper classes. Added classes to connect equality and
|
||||
// relational operators. Added classes for groups of related
|
||||
// operators. Reimplemented example operator and iterator helper
|
||||
// classes in terms of the new groups. (Daryle Walker, with help
|
||||
// from Alexy Gurtovoy)
|
||||
// 11 Feb 01 Fixed bugs in the iterator helpers which prevented explicitly
|
||||
// supplied arguments from actually being used (Dave Abrahams)
|
||||
// 04 Jul 00 Fixed NO_OPERATORS_IN_NAMESPACE bugs, major cleanup and
|
||||
// refactoring of compiler workarounds, additional documentation
|
||||
// (Alexy Gurtovoy and Mark Rodgers with some help and prompting from
|
||||
// Dave Abrahams)
|
||||
// 28 Jun 00 General cleanup and integration of bugfixes from Mark Rodgers and
|
||||
// Jeremy Siek (Dave Abrahams)
|
||||
// 20 Jun 00 Changes to accommodate Borland C++Builder 4 and Borland C++ 5.5
|
||||
// (Mark Rodgers)
|
||||
// 20 Jun 00 Minor fixes to the prior revision (Aleksey Gurtovoy)
|
||||
// 10 Jun 00 Support for the base class chaining technique was added
|
||||
// (Aleksey Gurtovoy). See documentation and the comments below
|
||||
// for the details.
|
||||
// 12 Dec 99 Initial version with iterator operators (Jeremy Siek)
|
||||
// 18 Nov 99 Change name "divideable" to "dividable", remove unnecessary
|
||||
// specializations of dividable, subtractable, modable (Ed Brey)
|
||||
// 17 Nov 99 Add comments (Beman Dawes)
|
||||
// Remove unnecessary specialization of operators<> (Ed Brey)
|
||||
// 15 Nov 99 Fix less_than_comparable<T,U> second operand type for first two
|
||||
// operators.(Beman Dawes)
|
||||
// 12 Nov 99 Add operators templates (Ed Brey)
|
||||
// 11 Nov 99 Add single template parameter version for compilers without
|
||||
// partial specialization (Beman Dawes)
|
||||
// 10 Nov 99 Initial version
|
||||
|
||||
// 10 Jun 00:
|
||||
// An additional optional template parameter was added to most of
|
||||
// operator templates to support the base class chaining technique (see
|
||||
// documentation for the details). Unfortunately, a straightforward
|
||||
// implementation of this change would have broken compatibility with the
|
||||
// previous version of the library by making it impossible to use the same
|
||||
// template name (e.g. 'addable') for both the 1- and 2-argument versions of
|
||||
// an operator template. This implementation solves the backward-compatibility
|
||||
// issue at the cost of some simplicity.
|
||||
//
|
||||
// One of the complications is an existence of special auxiliary class template
|
||||
// 'is_chained_base<>' (see 'detail' namespace below), which is used
|
||||
// to determine whether its template parameter is a library's operator template
|
||||
// or not. You have to specialize 'is_chained_base<>' for each new
|
||||
// operator template you add to the library.
|
||||
//
|
||||
// However, most of the non-trivial implementation details are hidden behind
|
||||
// several local macros defined below, and as soon as you understand them,
|
||||
// you understand the whole library implementation.
|
||||
|
||||
#ifndef BOOST_OPERATORS_V1_HPP
|
||||
#define BOOST_OPERATORS_V1_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
#if defined(__sgi) && !defined(__GNUC__)
|
||||
# pragma set woff 1234
|
||||
#endif
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, < 1600)
|
||||
# pragma warning( disable : 4284 ) // complaint about return type of
|
||||
#endif // operator-> not begin a UDT
|
||||
|
||||
namespace boost {
|
||||
namespace detail {
|
||||
|
||||
template <typename T> class empty_base {};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace boost
|
||||
|
||||
// In this section we supply the xxxx1 and xxxx2 forms of the operator
|
||||
// templates, which are explicitly targeted at the 1-type-argument and
|
||||
// 2-type-argument operator forms, respectively. Some compilers get confused
|
||||
// when inline friend functions are overloaded in namespaces other than the
|
||||
// global namespace. When BOOST_NO_OPERATORS_IN_NAMESPACE is defined, all of
|
||||
// these templates must go in the global namespace.
|
||||
|
||||
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||
namespace boost
|
||||
{
|
||||
#endif
|
||||
|
||||
// Basic operator classes (contributed by Dave Abrahams) ------------------//
|
||||
|
||||
// Note that friend functions defined in a class are implicitly inline.
|
||||
// See the C++ std, 11.4 [class.friend] paragraph 5
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct less_than_comparable2 : B
|
||||
{
|
||||
friend bool operator<=(const T& x, const U& y) { return !static_cast<bool>(x > y); }
|
||||
friend bool operator>=(const T& x, const U& y) { return !static_cast<bool>(x < y); }
|
||||
friend bool operator>(const U& x, const T& y) { return y < x; }
|
||||
friend bool operator<(const U& x, const T& y) { return y > x; }
|
||||
friend bool operator<=(const U& x, const T& y) { return !static_cast<bool>(y < x); }
|
||||
friend bool operator>=(const U& x, const T& y) { return !static_cast<bool>(y > x); }
|
||||
};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct less_than_comparable1 : B
|
||||
{
|
||||
friend bool operator>(const T& x, const T& y) { return y < x; }
|
||||
friend bool operator<=(const T& x, const T& y) { return !static_cast<bool>(y < x); }
|
||||
friend bool operator>=(const T& x, const T& y) { return !static_cast<bool>(x < y); }
|
||||
};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct equality_comparable2 : B
|
||||
{
|
||||
friend bool operator==(const U& y, const T& x) { return x == y; }
|
||||
friend bool operator!=(const U& y, const T& x) { return !static_cast<bool>(x == y); }
|
||||
friend bool operator!=(const T& y, const U& x) { return !static_cast<bool>(y == x); }
|
||||
};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct equality_comparable1 : B
|
||||
{
|
||||
friend bool operator!=(const T& x, const T& y) { return !static_cast<bool>(x == y); }
|
||||
};
|
||||
|
||||
// A macro which produces "name_2left" from "name".
|
||||
#define BOOST_OPERATOR2_LEFT(name) name##2##_##left
|
||||
|
||||
// NRVO-friendly implementation (contributed by Daniel Frey) ---------------//
|
||||
|
||||
#if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
|
||||
|
||||
// This is the optimal implementation for ISO/ANSI C++,
|
||||
// but it requires the compiler to implement the NRVO.
|
||||
// If the compiler has no NRVO, this is the best symmetric
|
||||
// implementation available.
|
||||
|
||||
#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
|
||||
struct NAME##2 : B \
|
||||
{ \
|
||||
friend T operator OP( const T& lhs, const U& rhs ) \
|
||||
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
|
||||
friend T operator OP( const U& lhs, const T& rhs ) \
|
||||
{ T nrv( rhs ); nrv OP##= lhs; return nrv; } \
|
||||
}; \
|
||||
\
|
||||
template <class T, class B = ::boost::detail::empty_base<T> > \
|
||||
struct NAME##1 : B \
|
||||
{ \
|
||||
friend T operator OP( const T& lhs, const T& rhs ) \
|
||||
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
|
||||
};
|
||||
|
||||
#define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
|
||||
struct NAME##2 : B \
|
||||
{ \
|
||||
friend T operator OP( const T& lhs, const U& rhs ) \
|
||||
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
|
||||
}; \
|
||||
\
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
|
||||
struct BOOST_OPERATOR2_LEFT(NAME) : B \
|
||||
{ \
|
||||
friend T operator OP( const U& lhs, const T& rhs ) \
|
||||
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
|
||||
}; \
|
||||
\
|
||||
template <class T, class B = ::boost::detail::empty_base<T> > \
|
||||
struct NAME##1 : B \
|
||||
{ \
|
||||
friend T operator OP( const T& lhs, const T& rhs ) \
|
||||
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
|
||||
};
|
||||
|
||||
#else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
|
||||
|
||||
// For compilers without NRVO the following code is optimal, but not
|
||||
// symmetric! Note that the implementation of
|
||||
// BOOST_OPERATOR2_LEFT(NAME) only looks cool, but doesn't provide
|
||||
// optimization opportunities to the compiler :)
|
||||
|
||||
#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
|
||||
struct NAME##2 : B \
|
||||
{ \
|
||||
friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
|
||||
friend T operator OP( const U& lhs, T rhs ) { return rhs OP##= lhs; } \
|
||||
}; \
|
||||
\
|
||||
template <class T, class B = ::boost::detail::empty_base<T> > \
|
||||
struct NAME##1 : B \
|
||||
{ \
|
||||
friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
|
||||
};
|
||||
|
||||
#define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
|
||||
struct NAME##2 : B \
|
||||
{ \
|
||||
friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
|
||||
}; \
|
||||
\
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
|
||||
struct BOOST_OPERATOR2_LEFT(NAME) : B \
|
||||
{ \
|
||||
friend T operator OP( const U& lhs, const T& rhs ) \
|
||||
{ return T( lhs ) OP##= rhs; } \
|
||||
}; \
|
||||
\
|
||||
template <class T, class B = ::boost::detail::empty_base<T> > \
|
||||
struct NAME##1 : B \
|
||||
{ \
|
||||
friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
|
||||
};
|
||||
|
||||
#endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
|
||||
|
||||
BOOST_BINARY_OPERATOR_COMMUTATIVE( multipliable, * )
|
||||
BOOST_BINARY_OPERATOR_COMMUTATIVE( addable, + )
|
||||
BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( subtractable, - )
|
||||
BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( dividable, / )
|
||||
BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( modable, % )
|
||||
BOOST_BINARY_OPERATOR_COMMUTATIVE( xorable, ^ )
|
||||
BOOST_BINARY_OPERATOR_COMMUTATIVE( andable, & )
|
||||
BOOST_BINARY_OPERATOR_COMMUTATIVE( orable, | )
|
||||
|
||||
#undef BOOST_BINARY_OPERATOR_COMMUTATIVE
|
||||
#undef BOOST_BINARY_OPERATOR_NON_COMMUTATIVE
|
||||
#undef BOOST_OPERATOR2_LEFT
|
||||
|
||||
// incrementable and decrementable contributed by Jeremy Siek
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct incrementable : B
|
||||
{
|
||||
friend T operator++(T& x, int)
|
||||
{
|
||||
incrementable_type nrv(x);
|
||||
++x;
|
||||
return nrv;
|
||||
}
|
||||
private: // The use of this typedef works around a Borland bug
|
||||
typedef T incrementable_type;
|
||||
};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct decrementable : B
|
||||
{
|
||||
friend T operator--(T& x, int)
|
||||
{
|
||||
decrementable_type nrv(x);
|
||||
--x;
|
||||
return nrv;
|
||||
}
|
||||
private: // The use of this typedef works around a Borland bug
|
||||
typedef T decrementable_type;
|
||||
};
|
||||
|
||||
// Iterator operator classes (contributed by Jeremy Siek) ------------------//
|
||||
|
||||
template <class T, class P, class B = ::boost::detail::empty_base<T> >
|
||||
struct dereferenceable : B
|
||||
{
|
||||
P operator->() const
|
||||
{
|
||||
return &*static_cast<const T&>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class I, class R, class B = ::boost::detail::empty_base<T> >
|
||||
struct indexable : B
|
||||
{
|
||||
R operator[](I n) const
|
||||
{
|
||||
return *(static_cast<const T&>(*this) + n);
|
||||
}
|
||||
};
|
||||
|
||||
// More operator classes (contributed by Daryle Walker) --------------------//
|
||||
// (NRVO-friendly implementation contributed by Daniel Frey) ---------------//
|
||||
|
||||
#if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
|
||||
|
||||
#define BOOST_BINARY_OPERATOR( NAME, OP ) \
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
|
||||
struct NAME##2 : B \
|
||||
{ \
|
||||
friend T operator OP( const T& lhs, const U& rhs ) \
|
||||
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
|
||||
}; \
|
||||
\
|
||||
template <class T, class B = ::boost::detail::empty_base<T> > \
|
||||
struct NAME##1 : B \
|
||||
{ \
|
||||
friend T operator OP( const T& lhs, const T& rhs ) \
|
||||
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
|
||||
};
|
||||
|
||||
#else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
|
||||
|
||||
#define BOOST_BINARY_OPERATOR( NAME, OP ) \
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
|
||||
struct NAME##2 : B \
|
||||
{ \
|
||||
friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
|
||||
}; \
|
||||
\
|
||||
template <class T, class B = ::boost::detail::empty_base<T> > \
|
||||
struct NAME##1 : B \
|
||||
{ \
|
||||
friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
|
||||
};
|
||||
|
||||
#endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
|
||||
|
||||
BOOST_BINARY_OPERATOR( left_shiftable, << )
|
||||
BOOST_BINARY_OPERATOR( right_shiftable, >> )
|
||||
|
||||
#undef BOOST_BINARY_OPERATOR
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct equivalent2 : B
|
||||
{
|
||||
friend bool operator==(const T& x, const U& y)
|
||||
{
|
||||
return !static_cast<bool>(x < y) && !static_cast<bool>(x > y);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct equivalent1 : B
|
||||
{
|
||||
friend bool operator==(const T&x, const T&y)
|
||||
{
|
||||
return !static_cast<bool>(x < y) && !static_cast<bool>(y < x);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct partially_ordered2 : B
|
||||
{
|
||||
friend bool operator<=(const T& x, const U& y)
|
||||
{ return static_cast<bool>(x < y) || static_cast<bool>(x == y); }
|
||||
friend bool operator>=(const T& x, const U& y)
|
||||
{ return static_cast<bool>(x > y) || static_cast<bool>(x == y); }
|
||||
friend bool operator>(const U& x, const T& y)
|
||||
{ return y < x; }
|
||||
friend bool operator<(const U& x, const T& y)
|
||||
{ return y > x; }
|
||||
friend bool operator<=(const U& x, const T& y)
|
||||
{ return static_cast<bool>(y > x) || static_cast<bool>(y == x); }
|
||||
friend bool operator>=(const U& x, const T& y)
|
||||
{ return static_cast<bool>(y < x) || static_cast<bool>(y == x); }
|
||||
};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct partially_ordered1 : B
|
||||
{
|
||||
friend bool operator>(const T& x, const T& y)
|
||||
{ return y < x; }
|
||||
friend bool operator<=(const T& x, const T& y)
|
||||
{ return static_cast<bool>(x < y) || static_cast<bool>(x == y); }
|
||||
friend bool operator>=(const T& x, const T& y)
|
||||
{ return static_cast<bool>(y < x) || static_cast<bool>(x == y); }
|
||||
};
|
||||
|
||||
// Combined operator classes (contributed by Daryle Walker) ----------------//
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct totally_ordered2
|
||||
: less_than_comparable2<T, U
|
||||
, equality_comparable2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct totally_ordered1
|
||||
: less_than_comparable1<T
|
||||
, equality_comparable1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct additive2
|
||||
: addable2<T, U
|
||||
, subtractable2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct additive1
|
||||
: addable1<T
|
||||
, subtractable1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct multiplicative2
|
||||
: multipliable2<T, U
|
||||
, dividable2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct multiplicative1
|
||||
: multipliable1<T
|
||||
, dividable1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct integer_multiplicative2
|
||||
: multiplicative2<T, U
|
||||
, modable2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct integer_multiplicative1
|
||||
: multiplicative1<T
|
||||
, modable1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct arithmetic2
|
||||
: additive2<T, U
|
||||
, multiplicative2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct arithmetic1
|
||||
: additive1<T
|
||||
, multiplicative1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct integer_arithmetic2
|
||||
: additive2<T, U
|
||||
, integer_multiplicative2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct integer_arithmetic1
|
||||
: additive1<T
|
||||
, integer_multiplicative1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct bitwise2
|
||||
: xorable2<T, U
|
||||
, andable2<T, U
|
||||
, orable2<T, U, B
|
||||
> > > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct bitwise1
|
||||
: xorable1<T
|
||||
, andable1<T
|
||||
, orable1<T, B
|
||||
> > > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct unit_steppable
|
||||
: incrementable<T
|
||||
, decrementable<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct shiftable2
|
||||
: left_shiftable2<T, U
|
||||
, right_shiftable2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct shiftable1
|
||||
: left_shiftable1<T
|
||||
, right_shiftable1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct ring_operators2
|
||||
: additive2<T, U
|
||||
, subtractable2_left<T, U
|
||||
, multipliable2<T, U, B
|
||||
> > > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct ring_operators1
|
||||
: additive1<T
|
||||
, multipliable1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct ordered_ring_operators2
|
||||
: ring_operators2<T, U
|
||||
, totally_ordered2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct ordered_ring_operators1
|
||||
: ring_operators1<T
|
||||
, totally_ordered1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct field_operators2
|
||||
: ring_operators2<T, U
|
||||
, dividable2<T, U
|
||||
, dividable2_left<T, U, B
|
||||
> > > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct field_operators1
|
||||
: ring_operators1<T
|
||||
, dividable1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct ordered_field_operators2
|
||||
: field_operators2<T, U
|
||||
, totally_ordered2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct ordered_field_operators1
|
||||
: field_operators1<T
|
||||
, totally_ordered1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct euclidian_ring_operators2
|
||||
: ring_operators2<T, U
|
||||
, dividable2<T, U
|
||||
, dividable2_left<T, U
|
||||
, modable2<T, U
|
||||
, modable2_left<T, U, B
|
||||
> > > > > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct euclidian_ring_operators1
|
||||
: ring_operators1<T
|
||||
, dividable1<T
|
||||
, modable1<T, B
|
||||
> > > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct ordered_euclidian_ring_operators2
|
||||
: totally_ordered2<T, U
|
||||
, euclidian_ring_operators2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct ordered_euclidian_ring_operators1
|
||||
: totally_ordered1<T
|
||||
, euclidian_ring_operators1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct euclidean_ring_operators2
|
||||
: ring_operators2<T, U
|
||||
, dividable2<T, U
|
||||
, dividable2_left<T, U
|
||||
, modable2<T, U
|
||||
, modable2_left<T, U, B
|
||||
> > > > > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct euclidean_ring_operators1
|
||||
: ring_operators1<T
|
||||
, dividable1<T
|
||||
, modable1<T, B
|
||||
> > > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct ordered_euclidean_ring_operators2
|
||||
: totally_ordered2<T, U
|
||||
, euclidean_ring_operators2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct ordered_euclidean_ring_operators1
|
||||
: totally_ordered1<T
|
||||
, euclidean_ring_operators1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class P, class B = ::boost::detail::empty_base<T> >
|
||||
struct input_iteratable
|
||||
: equality_comparable1<T
|
||||
, incrementable<T
|
||||
, dereferenceable<T, P, B
|
||||
> > > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct output_iteratable
|
||||
: incrementable<T, B
|
||||
> {};
|
||||
|
||||
template <class T, class P, class B = ::boost::detail::empty_base<T> >
|
||||
struct forward_iteratable
|
||||
: input_iteratable<T, P, B
|
||||
> {};
|
||||
|
||||
template <class T, class P, class B = ::boost::detail::empty_base<T> >
|
||||
struct bidirectional_iteratable
|
||||
: forward_iteratable<T, P
|
||||
, decrementable<T, B
|
||||
> > {};
|
||||
|
||||
// To avoid repeated derivation from equality_comparable,
|
||||
// which is an indirect base class of bidirectional_iterable,
|
||||
// random_access_iteratable must not be derived from totally_ordered1
|
||||
// but from less_than_comparable1 only. (Helmut Zeisel, 02-Dec-2001)
|
||||
template <class T, class P, class D, class R, class B = ::boost::detail::empty_base<T> >
|
||||
struct random_access_iteratable
|
||||
: bidirectional_iteratable<T, P
|
||||
, less_than_comparable1<T
|
||||
, additive2<T, D
|
||||
, indexable<T, D, R, B
|
||||
> > > > {};
|
||||
|
||||
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||
} // namespace boost
|
||||
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||
|
||||
|
||||
// BOOST_IMPORT_TEMPLATE1 .. BOOST_IMPORT_TEMPLATE4 -
|
||||
//
|
||||
// When BOOST_NO_OPERATORS_IN_NAMESPACE is defined we need a way to import an
|
||||
// operator template into the boost namespace. BOOST_IMPORT_TEMPLATE1 is used
|
||||
// for one-argument forms of operator templates; BOOST_IMPORT_TEMPLATE2 for
|
||||
// two-argument forms. Note that these macros expect to be invoked from within
|
||||
// boost.
|
||||
|
||||
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||
|
||||
// The template is already in boost so we have nothing to do.
|
||||
# define BOOST_IMPORT_TEMPLATE4(template_name)
|
||||
# define BOOST_IMPORT_TEMPLATE3(template_name)
|
||||
# define BOOST_IMPORT_TEMPLATE2(template_name)
|
||||
# define BOOST_IMPORT_TEMPLATE1(template_name)
|
||||
|
||||
#else // BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||
|
||||
# ifndef BOOST_NO_USING_TEMPLATE
|
||||
|
||||
// Bring the names in with a using-declaration
|
||||
// to avoid stressing the compiler.
|
||||
# define BOOST_IMPORT_TEMPLATE4(template_name) using ::template_name;
|
||||
# define BOOST_IMPORT_TEMPLATE3(template_name) using ::template_name;
|
||||
# define BOOST_IMPORT_TEMPLATE2(template_name) using ::template_name;
|
||||
# define BOOST_IMPORT_TEMPLATE1(template_name) using ::template_name;
|
||||
|
||||
# else
|
||||
|
||||
// Otherwise, because a Borland C++ 5.5 bug prevents a using declaration
|
||||
// from working, we are forced to use inheritance for that compiler.
|
||||
# define BOOST_IMPORT_TEMPLATE4(template_name) \
|
||||
template <class T, class U, class V, class W, class B = ::boost::detail::empty_base<T> > \
|
||||
struct template_name : ::template_name<T, U, V, W, B> {};
|
||||
|
||||
# define BOOST_IMPORT_TEMPLATE3(template_name) \
|
||||
template <class T, class U, class V, class B = ::boost::detail::empty_base<T> > \
|
||||
struct template_name : ::template_name<T, U, V, B> {};
|
||||
|
||||
# define BOOST_IMPORT_TEMPLATE2(template_name) \
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
|
||||
struct template_name : ::template_name<T, U, B> {};
|
||||
|
||||
# define BOOST_IMPORT_TEMPLATE1(template_name) \
|
||||
template <class T, class B = ::boost::detail::empty_base<T> > \
|
||||
struct template_name : ::template_name<T, B> {};
|
||||
|
||||
# endif // BOOST_NO_USING_TEMPLATE
|
||||
|
||||
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||
|
||||
//
|
||||
// Here's where we put it all together, defining the xxxx forms of the templates
|
||||
// in namespace boost. We also define specializations of is_chained_base<> for
|
||||
// the xxxx, xxxx1, and xxxx2 templates, importing them into boost:: as
|
||||
// necessary.
|
||||
//
|
||||
|
||||
// is_chained_base<> - a traits class used to distinguish whether an operator
|
||||
// template argument is being used for base class chaining, or is specifying a
|
||||
// 2nd argument type.
|
||||
|
||||
namespace boost {
|
||||
// A type parameter is used instead of a plain bool because Borland's compiler
|
||||
// didn't cope well with the more obvious non-type template parameter.
|
||||
namespace detail {
|
||||
struct true_t {};
|
||||
struct false_t {};
|
||||
} // namespace detail
|
||||
|
||||
// Unspecialized version assumes that most types are not being used for base
|
||||
// class chaining. We specialize for the operator templates defined in this
|
||||
// library.
|
||||
template<class T> struct is_chained_base {
|
||||
typedef ::boost::detail::false_t value;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
// Import a 4-type-argument operator template into boost (if necessary) and
|
||||
// provide a specialization of 'is_chained_base<>' for it.
|
||||
# define BOOST_OPERATOR_TEMPLATE4(template_name4) \
|
||||
BOOST_IMPORT_TEMPLATE4(template_name4) \
|
||||
template<class T, class U, class V, class W, class B> \
|
||||
struct is_chained_base< ::boost::template_name4<T, U, V, W, B> > { \
|
||||
typedef ::boost::detail::true_t value; \
|
||||
};
|
||||
|
||||
// Import a 3-type-argument operator template into boost (if necessary) and
|
||||
// provide a specialization of 'is_chained_base<>' for it.
|
||||
# define BOOST_OPERATOR_TEMPLATE3(template_name3) \
|
||||
BOOST_IMPORT_TEMPLATE3(template_name3) \
|
||||
template<class T, class U, class V, class B> \
|
||||
struct is_chained_base< ::boost::template_name3<T, U, V, B> > { \
|
||||
typedef ::boost::detail::true_t value; \
|
||||
};
|
||||
|
||||
// Import a 2-type-argument operator template into boost (if necessary) and
|
||||
// provide a specialization of 'is_chained_base<>' for it.
|
||||
# define BOOST_OPERATOR_TEMPLATE2(template_name2) \
|
||||
BOOST_IMPORT_TEMPLATE2(template_name2) \
|
||||
template<class T, class U, class B> \
|
||||
struct is_chained_base< ::boost::template_name2<T, U, B> > { \
|
||||
typedef ::boost::detail::true_t value; \
|
||||
};
|
||||
|
||||
// Import a 1-type-argument operator template into boost (if necessary) and
|
||||
// provide a specialization of 'is_chained_base<>' for it.
|
||||
# define BOOST_OPERATOR_TEMPLATE1(template_name1) \
|
||||
BOOST_IMPORT_TEMPLATE1(template_name1) \
|
||||
template<class T, class B> \
|
||||
struct is_chained_base< ::boost::template_name1<T, B> > { \
|
||||
typedef ::boost::detail::true_t value; \
|
||||
};
|
||||
|
||||
// BOOST_OPERATOR_TEMPLATE(template_name) defines template_name<> such that it
|
||||
// can be used for specifying both 1-argument and 2-argument forms. Requires the
|
||||
// existence of two previously defined class templates named '<template_name>1'
|
||||
// and '<template_name>2' which must implement the corresponding 1- and 2-
|
||||
// argument forms.
|
||||
//
|
||||
// The template type parameter O == is_chained_base<U>::value is used to
|
||||
// distinguish whether the 2nd argument to <template_name> is being used for
|
||||
// base class chaining from another boost operator template or is describing a
|
||||
// 2nd operand type. O == true_t only when U is actually an another operator
|
||||
// template from the library. Partial specialization is used to select an
|
||||
// implementation in terms of either '<template_name>1' or '<template_name>2'.
|
||||
//
|
||||
|
||||
# define BOOST_OPERATOR_TEMPLATE(template_name) \
|
||||
template <class T \
|
||||
,class U = T \
|
||||
,class B = ::boost::detail::empty_base<T> \
|
||||
,class O = typename is_chained_base<U>::value \
|
||||
> \
|
||||
struct template_name : template_name##2<T, U, B> {}; \
|
||||
\
|
||||
template<class T, class U, class B> \
|
||||
struct template_name<T, U, B, ::boost::detail::true_t> \
|
||||
: template_name##1<T, U> {}; \
|
||||
\
|
||||
template <class T, class B> \
|
||||
struct template_name<T, T, B, ::boost::detail::false_t> \
|
||||
: template_name##1<T, B> {}; \
|
||||
\
|
||||
template<class T, class U, class B, class O> \
|
||||
struct is_chained_base< ::boost::template_name<T, U, B, O> > { \
|
||||
typedef ::boost::detail::true_t value; \
|
||||
}; \
|
||||
\
|
||||
BOOST_OPERATOR_TEMPLATE2(template_name##2) \
|
||||
BOOST_OPERATOR_TEMPLATE1(template_name##1)
|
||||
|
||||
|
||||
|
||||
namespace boost {
|
||||
|
||||
BOOST_OPERATOR_TEMPLATE(less_than_comparable)
|
||||
BOOST_OPERATOR_TEMPLATE(equality_comparable)
|
||||
BOOST_OPERATOR_TEMPLATE(multipliable)
|
||||
BOOST_OPERATOR_TEMPLATE(addable)
|
||||
BOOST_OPERATOR_TEMPLATE(subtractable)
|
||||
BOOST_OPERATOR_TEMPLATE2(subtractable2_left)
|
||||
BOOST_OPERATOR_TEMPLATE(dividable)
|
||||
BOOST_OPERATOR_TEMPLATE2(dividable2_left)
|
||||
BOOST_OPERATOR_TEMPLATE(modable)
|
||||
BOOST_OPERATOR_TEMPLATE2(modable2_left)
|
||||
BOOST_OPERATOR_TEMPLATE(xorable)
|
||||
BOOST_OPERATOR_TEMPLATE(andable)
|
||||
BOOST_OPERATOR_TEMPLATE(orable)
|
||||
|
||||
BOOST_OPERATOR_TEMPLATE1(incrementable)
|
||||
BOOST_OPERATOR_TEMPLATE1(decrementable)
|
||||
|
||||
BOOST_OPERATOR_TEMPLATE2(dereferenceable)
|
||||
BOOST_OPERATOR_TEMPLATE3(indexable)
|
||||
|
||||
BOOST_OPERATOR_TEMPLATE(left_shiftable)
|
||||
BOOST_OPERATOR_TEMPLATE(right_shiftable)
|
||||
BOOST_OPERATOR_TEMPLATE(equivalent)
|
||||
BOOST_OPERATOR_TEMPLATE(partially_ordered)
|
||||
|
||||
BOOST_OPERATOR_TEMPLATE(totally_ordered)
|
||||
BOOST_OPERATOR_TEMPLATE(additive)
|
||||
BOOST_OPERATOR_TEMPLATE(multiplicative)
|
||||
BOOST_OPERATOR_TEMPLATE(integer_multiplicative)
|
||||
BOOST_OPERATOR_TEMPLATE(arithmetic)
|
||||
BOOST_OPERATOR_TEMPLATE(integer_arithmetic)
|
||||
BOOST_OPERATOR_TEMPLATE(bitwise)
|
||||
BOOST_OPERATOR_TEMPLATE1(unit_steppable)
|
||||
BOOST_OPERATOR_TEMPLATE(shiftable)
|
||||
BOOST_OPERATOR_TEMPLATE(ring_operators)
|
||||
BOOST_OPERATOR_TEMPLATE(ordered_ring_operators)
|
||||
BOOST_OPERATOR_TEMPLATE(field_operators)
|
||||
BOOST_OPERATOR_TEMPLATE(ordered_field_operators)
|
||||
BOOST_OPERATOR_TEMPLATE(euclidian_ring_operators)
|
||||
BOOST_OPERATOR_TEMPLATE(ordered_euclidian_ring_operators)
|
||||
BOOST_OPERATOR_TEMPLATE(euclidean_ring_operators)
|
||||
BOOST_OPERATOR_TEMPLATE(ordered_euclidean_ring_operators)
|
||||
BOOST_OPERATOR_TEMPLATE2(input_iteratable)
|
||||
BOOST_OPERATOR_TEMPLATE1(output_iteratable)
|
||||
BOOST_OPERATOR_TEMPLATE2(forward_iteratable)
|
||||
BOOST_OPERATOR_TEMPLATE2(bidirectional_iteratable)
|
||||
BOOST_OPERATOR_TEMPLATE4(random_access_iteratable)
|
||||
|
||||
#undef BOOST_OPERATOR_TEMPLATE
|
||||
#undef BOOST_OPERATOR_TEMPLATE4
|
||||
#undef BOOST_OPERATOR_TEMPLATE3
|
||||
#undef BOOST_OPERATOR_TEMPLATE2
|
||||
#undef BOOST_OPERATOR_TEMPLATE1
|
||||
#undef BOOST_IMPORT_TEMPLATE1
|
||||
#undef BOOST_IMPORT_TEMPLATE2
|
||||
#undef BOOST_IMPORT_TEMPLATE3
|
||||
#undef BOOST_IMPORT_TEMPLATE4
|
||||
|
||||
// The following 'operators' classes can only be used portably if the derived class
|
||||
// declares ALL of the required member operators.
|
||||
template <class T, class U>
|
||||
struct operators2
|
||||
: totally_ordered2<T,U
|
||||
, integer_arithmetic2<T,U
|
||||
, bitwise2<T,U
|
||||
> > > {};
|
||||
|
||||
template <class T, class U = T>
|
||||
struct operators : operators2<T, U> {};
|
||||
|
||||
template <class T> struct operators<T, T>
|
||||
: totally_ordered<T
|
||||
, integer_arithmetic<T
|
||||
, bitwise<T
|
||||
, unit_steppable<T
|
||||
> > > > {};
|
||||
|
||||
// Iterator helper classes (contributed by Jeremy Siek) -------------------//
|
||||
// (Input and output iterator helpers contributed by Daryle Walker) -------//
|
||||
// (Changed to use combined operator classes by Daryle Walker) ------------//
|
||||
template <class T,
|
||||
class V,
|
||||
class D = std::ptrdiff_t,
|
||||
class P = V const *,
|
||||
class R = V const &>
|
||||
struct input_iterator_helper
|
||||
: input_iteratable<T, P
|
||||
, std::iterator<std::input_iterator_tag, V, D, P, R
|
||||
> > {};
|
||||
|
||||
template<class T>
|
||||
struct output_iterator_helper
|
||||
: output_iteratable<T
|
||||
, std::iterator<std::output_iterator_tag, void, void, void, void
|
||||
> >
|
||||
{
|
||||
T& operator*() { return static_cast<T&>(*this); }
|
||||
T& operator++() { return static_cast<T&>(*this); }
|
||||
};
|
||||
|
||||
template <class T,
|
||||
class V,
|
||||
class D = std::ptrdiff_t,
|
||||
class P = V*,
|
||||
class R = V&>
|
||||
struct forward_iterator_helper
|
||||
: forward_iteratable<T, P
|
||||
, std::iterator<std::forward_iterator_tag, V, D, P, R
|
||||
> > {};
|
||||
|
||||
template <class T,
|
||||
class V,
|
||||
class D = std::ptrdiff_t,
|
||||
class P = V*,
|
||||
class R = V&>
|
||||
struct bidirectional_iterator_helper
|
||||
: bidirectional_iteratable<T, P
|
||||
, std::iterator<std::bidirectional_iterator_tag, V, D, P, R
|
||||
> > {};
|
||||
|
||||
template <class T,
|
||||
class V,
|
||||
class D = std::ptrdiff_t,
|
||||
class P = V*,
|
||||
class R = V&>
|
||||
struct random_access_iterator_helper
|
||||
: random_access_iteratable<T, P, D, R
|
||||
, std::iterator<std::random_access_iterator_tag, V, D, P, R
|
||||
> >
|
||||
{
|
||||
friend D requires_difference_operator(const T& x, const T& y) {
|
||||
return x - y;
|
||||
}
|
||||
}; // random_access_iterator_helper
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#if defined(__sgi) && !defined(__GNUC__)
|
||||
#pragma reset woff 1234
|
||||
#endif
|
||||
|
||||
#endif // BOOST_OPERATORS_V1_HPP
|
@ -1,119 +1,24 @@
|
||||
// boost utility.hpp header file -------------------------------------------//
|
||||
// Boost utility.hpp header file -------------------------------------------//
|
||||
|
||||
// (C) Copyright boost.org 1999. Permission to copy, use, modify, sell
|
||||
// and distribute this software is granted provided this copyright
|
||||
// notice appears in all copies. This software is provided "as is" without
|
||||
// express or implied warranty, and with no claim as to its suitability for
|
||||
// any purpose.
|
||||
// Copyright 1999-2003 Aleksey Gurtovoy. Use, modification, and distribution are
|
||||
// subject to the Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
|
||||
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
// Classes appear in alphabetical order
|
||||
|
||||
// Revision History
|
||||
// 21 May 01 checked_delete() and checked_array_delete() added (Beman Dawes,
|
||||
// suggested by Dave Abrahams, generalizing idea from Vladimir Prus)
|
||||
// 21 May 01 made next() and prior() inline (Beman Dawes)
|
||||
// 26 Jan 00 protected noncopyable destructor added (Miki Jovanovic)
|
||||
// 10 Dec 99 next() and prior() templates added (Dave Abrahams)
|
||||
// 30 Aug 99 moved cast templates to cast.hpp (Beman Dawes)
|
||||
// 3 Aug 99 cast templates added
|
||||
// 20 Jul 99 name changed to utility.hpp
|
||||
// 9 Jun 99 protected noncopyable default ctor
|
||||
// 2 Jun 99 Initial Version. Class noncopyable only contents (Dave Abrahams)
|
||||
// See <http://www.boost.org/libs/utility/> for the library's home page.
|
||||
|
||||
#ifndef BOOST_UTILITY_HPP
|
||||
#define BOOST_UTILITY_HPP
|
||||
|
||||
#include <boost/config.hpp> // broken compiler workarounds
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <cstddef> // for size_t
|
||||
#include <utility> // for std::pair
|
||||
// Use of this header is discouraged and it will be deprecated.
|
||||
// Please include one or more of the headers below instead.
|
||||
|
||||
namespace boost
|
||||
{
|
||||
// checked_delete() and checked_array_delete() -----------------------------//
|
||||
#include <boost/utility/base_from_member.hpp>
|
||||
#include <boost/utility/binary.hpp>
|
||||
#include <boost/utility/identity_type.hpp>
|
||||
|
||||
// verify that types are complete for increased safety
|
||||
|
||||
template< typename T >
|
||||
inline void checked_delete(T * x)
|
||||
{
|
||||
BOOST_STATIC_ASSERT( sizeof(T) != 0 ); // assert type complete at point
|
||||
// of instantiation
|
||||
delete x;
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
inline void checked_array_delete(T * x)
|
||||
{
|
||||
BOOST_STATIC_ASSERT( sizeof(T) != 0 ); // assert type complete at point
|
||||
// of instantiation
|
||||
delete [] x;
|
||||
}
|
||||
|
||||
// next() and prior() template functions -----------------------------------//
|
||||
|
||||
// Helper functions for classes like bidirectional iterators not supporting
|
||||
// operator+ and operator-.
|
||||
//
|
||||
// Usage:
|
||||
// const std::list<T>::iterator p = get_some_iterator();
|
||||
// const std::list<T>::iterator prev = boost::prior(p);
|
||||
|
||||
// Contributed by Dave Abrahams
|
||||
|
||||
template <class T>
|
||||
inline T next(T x) { return ++x; }
|
||||
|
||||
template <class T>
|
||||
inline T prior(T x) { return --x; }
|
||||
|
||||
|
||||
// class noncopyable -------------------------------------------------------//
|
||||
|
||||
// Private copy constructor and copy assignment ensure classes derived from
|
||||
// class noncopyable cannot be copied.
|
||||
|
||||
// Contributed by Dave Abrahams
|
||||
|
||||
class noncopyable
|
||||
{
|
||||
protected:
|
||||
noncopyable(){}
|
||||
~noncopyable(){}
|
||||
private: // emphasize the following members are private
|
||||
noncopyable( const noncopyable& );
|
||||
const noncopyable& operator=( const noncopyable& );
|
||||
}; // noncopyable
|
||||
|
||||
// class tied -------------------------------------------------------//
|
||||
|
||||
// A helper for conveniently assigning the two values from a pair
|
||||
// into separate variables. The idea for this comes from Jaakko J<>rvi's
|
||||
// Binder/Lambda Library.
|
||||
|
||||
// Constributed by Jeremy Siek
|
||||
|
||||
template <class A, class B>
|
||||
class tied {
|
||||
public:
|
||||
inline tied(A& a, B& b) : _a(a), _b(b) { }
|
||||
template <class U, class V>
|
||||
inline tied& operator=(const std::pair<U,V>& p) {
|
||||
_a = p.first;
|
||||
_b = p.second;
|
||||
return *this;
|
||||
}
|
||||
protected:
|
||||
A& _a;
|
||||
B& _b;
|
||||
};
|
||||
|
||||
template <class A, class B>
|
||||
inline tied<A,B> tie(A& a, B& b) { return tied<A,B>(a, b); }
|
||||
|
||||
} // namespace boost
|
||||
#include <boost/core/addressof.hpp>
|
||||
#include <boost/core/enable_if.hpp>
|
||||
#include <boost/core/checked_delete.hpp>
|
||||
#include <boost/core/noncopyable.hpp>
|
||||
|
||||
#endif // BOOST_UTILITY_HPP
|
||||
|
||||
|
173
include/boost/utility/base_from_member.hpp
Normal file
173
include/boost/utility/base_from_member.hpp
Normal file
@ -0,0 +1,173 @@
|
||||
// boost utility/base_from_member.hpp header file --------------------------//
|
||||
|
||||
// Copyright 2001, 2003, 2004, 2012 Daryle Walker. Use, modification, and
|
||||
// distribution are subject to the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or a copy at
|
||||
// <http://www.boost.org/LICENSE_1_0.txt>.)
|
||||
|
||||
// See <http://www.boost.org/libs/utility/> for the library's home page.
|
||||
|
||||
#ifndef BOOST_UTILITY_BASE_FROM_MEMBER_HPP
|
||||
#define BOOST_UTILITY_BASE_FROM_MEMBER_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/preprocessor/arithmetic/inc.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/remove_cv.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
|
||||
// Base-from-member arity configuration macro ------------------------------//
|
||||
|
||||
// The following macro determines how many arguments will be in the largest
|
||||
// constructor template of base_from_member. Constructor templates will be
|
||||
// generated from one argument to this maximum. Code from other files can read
|
||||
// this number if they need to always match the exact maximum base_from_member
|
||||
// uses. The maximum constructor length can be changed by overriding the
|
||||
// #defined constant. Make sure to apply the override, if any, for all source
|
||||
// files during project compiling for consistency.
|
||||
|
||||
// Contributed by Jonathan Turkanis
|
||||
|
||||
#ifndef BOOST_BASE_FROM_MEMBER_MAX_ARITY
|
||||
#define BOOST_BASE_FROM_MEMBER_MAX_ARITY 10
|
||||
#endif
|
||||
|
||||
|
||||
// An iteration of a constructor template for base_from_member -------------//
|
||||
|
||||
// A macro that should expand to:
|
||||
// template < typename T1, ..., typename Tn >
|
||||
// base_from_member( T1 x1, ..., Tn xn )
|
||||
// : member( x1, ..., xn )
|
||||
// {}
|
||||
// This macro should only persist within this file.
|
||||
|
||||
#ifndef BOOST_UTILITY_DOCS
|
||||
#define BOOST_PRIVATE_CTR_DEF( z, n, data ) \
|
||||
template < BOOST_PP_ENUM_PARAMS(n, typename T) > \
|
||||
base_from_member( BOOST_PP_ENUM_BINARY_PARAMS(n, T, x) ) \
|
||||
: member( BOOST_PP_ENUM_PARAMS(n, x) ) \
|
||||
{} \
|
||||
/**/
|
||||
#endif // BOOST_UTILITY_DOCS
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// Type-unmarking class template -------------------------------------------//
|
||||
|
||||
// Type-trait to get the raw type, i.e. the type without top-level reference nor
|
||||
// cv-qualification, from a type expression. Mainly for function arguments, any
|
||||
// reference part is stripped first.
|
||||
|
||||
// Contributed by Daryle Walker
|
||||
|
||||
template < typename T >
|
||||
struct remove_cv_ref
|
||||
{
|
||||
typedef typename ::boost::remove_cv<typename
|
||||
::boost::remove_reference<T>::type>::type type;
|
||||
|
||||
}; // boost::detail::remove_cv_ref
|
||||
|
||||
// Unmarked-type comparison class template ---------------------------------//
|
||||
|
||||
// Type-trait to check if two type expressions have the same raw type.
|
||||
|
||||
// Contributed by Daryle Walker, based on a work-around by Luc Danton
|
||||
|
||||
template < typename T, typename U >
|
||||
struct is_related
|
||||
: public ::boost::is_same<
|
||||
typename ::boost::detail::remove_cv_ref<T>::type,
|
||||
typename ::boost::detail::remove_cv_ref<U>::type >
|
||||
{};
|
||||
|
||||
// Enable-if-on-unidentical-unmarked-type class template -------------------//
|
||||
|
||||
// Enable-if on the first two type expressions NOT having the same raw type.
|
||||
|
||||
// Contributed by Daryle Walker, based on a work-around by Luc Danton
|
||||
|
||||
#ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES
|
||||
template<typename ...T>
|
||||
struct enable_if_unrelated
|
||||
: public ::boost::enable_if_c<true>
|
||||
{};
|
||||
|
||||
template<typename T, typename U, typename ...U2>
|
||||
struct enable_if_unrelated<T, U, U2...>
|
||||
: public ::boost::disable_if< ::boost::detail::is_related<T, U> >
|
||||
{};
|
||||
#endif
|
||||
|
||||
} // namespace boost::detail
|
||||
|
||||
|
||||
// Base-from-member class template -----------------------------------------//
|
||||
|
||||
// Helper to initialize a base object so a derived class can use this
|
||||
// object in the initialization of another base class. Used by
|
||||
// Dietmar Kuehl from ideas by Ron Klatcho to solve the problem of a
|
||||
// base class needing to be initialized by a member.
|
||||
|
||||
// Contributed by Daryle Walker
|
||||
|
||||
template < typename MemberType, int UniqueID = 0 >
|
||||
class base_from_member
|
||||
{
|
||||
protected:
|
||||
MemberType member;
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
|
||||
!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
|
||||
!defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) && \
|
||||
!(defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 4))
|
||||
template <typename ...T, typename EnableIf = typename
|
||||
::boost::detail::enable_if_unrelated<base_from_member, T...>::type>
|
||||
explicit BOOST_CONSTEXPR base_from_member( T&& ...x )
|
||||
BOOST_NOEXCEPT_IF( BOOST_NOEXCEPT_EXPR(::new ((void*) 0) MemberType(
|
||||
static_cast<T&&>(x)... )) ) // no std::is_nothrow_constructible...
|
||||
: member( static_cast<T&&>(x)... ) // ...nor std::forward needed
|
||||
{}
|
||||
#else
|
||||
base_from_member()
|
||||
: member()
|
||||
{}
|
||||
|
||||
template < typename T0 > explicit base_from_member( T0 x0 ) : member( x0 ) {}
|
||||
BOOST_PP_REPEAT_FROM_TO( 2, BOOST_PP_INC(BOOST_BASE_FROM_MEMBER_MAX_ARITY),
|
||||
BOOST_PRIVATE_CTR_DEF, _ )
|
||||
#endif
|
||||
|
||||
}; // boost::base_from_member
|
||||
|
||||
template < typename MemberType, int UniqueID >
|
||||
class base_from_member<MemberType&, UniqueID>
|
||||
{
|
||||
protected:
|
||||
MemberType& member;
|
||||
|
||||
explicit BOOST_CONSTEXPR base_from_member( MemberType& x )
|
||||
BOOST_NOEXCEPT
|
||||
: member( x )
|
||||
{}
|
||||
|
||||
}; // boost::base_from_member
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
// Undo any private macros
|
||||
#undef BOOST_PRIVATE_CTR_DEF
|
||||
|
||||
|
||||
#endif // BOOST_UTILITY_BASE_FROM_MEMBER_HPP
|
709
include/boost/utility/binary.hpp
Normal file
709
include/boost/utility/binary.hpp
Normal file
@ -0,0 +1,709 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2005 Matthew Calabrese
|
||||
|
||||
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)
|
||||
==============================================================================*/
|
||||
|
||||
#ifndef BOOST_UTILITY_BINARY_HPP
|
||||
#define BOOST_UTILITY_BINARY_HPP
|
||||
|
||||
/*=============================================================================
|
||||
|
||||
Binary Literal Utility
|
||||
______________________
|
||||
|
||||
|
||||
The following code works by converting the input bit pattern into a
|
||||
Boost.Preprocessor sequence, then converting groupings of 3 bits each into
|
||||
the corresponding octal digit, and finally concatenating all of the digits
|
||||
together along with a leading zero. This yields a standard octal literal
|
||||
with the desired value as specified in bits.
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
#include <boost/preprocessor/control/deduce_d.hpp>
|
||||
#include <boost/preprocessor/facilities/identity.hpp>
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
#include <boost/preprocessor/seq/cat.hpp>
|
||||
#include <boost/preprocessor/seq/transform.hpp>
|
||||
#include <boost/preprocessor/arithmetic/mod.hpp>
|
||||
#include <boost/preprocessor/seq/size.hpp>
|
||||
#include <boost/preprocessor/facilities/empty.hpp>
|
||||
#include <boost/preprocessor/control/while.hpp>
|
||||
|
||||
#define BOOST_BINARY( bit_groupings ) \
|
||||
BOOST_BINARY_LITERAL_D( BOOST_PP_DEDUCE_D(), bit_groupings )
|
||||
|
||||
#define BOOST_BINARY_U( bit_groupings ) \
|
||||
BOOST_SUFFIXED_BINARY_LITERAL( bit_groupings, U )
|
||||
|
||||
#define BOOST_BINARY_L( bit_groupings ) \
|
||||
BOOST_SUFFIXED_BINARY_LITERAL( bit_groupings, L )
|
||||
|
||||
#define BOOST_BINARY_UL( bit_groupings ) \
|
||||
BOOST_SUFFIXED_BINARY_LITERAL( bit_groupings, UL )
|
||||
|
||||
#define BOOST_BINARY_LU( bit_groupings ) \
|
||||
BOOST_SUFFIXED_BINARY_LITERAL( bit_groupings, LU )
|
||||
|
||||
#define BOOST_BINARY_LL( bit_groupings ) \
|
||||
BOOST_SUFFIXED_BINARY_LITERAL( bit_groupings, LL )
|
||||
|
||||
#define BOOST_BINARY_ULL( bit_groupings ) \
|
||||
BOOST_SUFFIXED_BINARY_LITERAL( bit_groupings, ULL )
|
||||
|
||||
#define BOOST_BINARY_LLU( bit_groupings ) \
|
||||
BOOST_SUFFIXED_BINARY_LITERAL( bit_groupings, LLU )
|
||||
|
||||
#define BOOST_SUFFIXED_BINARY_LITERAL( bit_groupings, suffix ) \
|
||||
BOOST_SUFFIXED_BINARY_LITERAL_D( BOOST_PP_DEDUCE_D(), bit_groupings, suffix )
|
||||
|
||||
#define BOOST_SUFFIXED_BINARY_LITERAL_D( d, bit_groupings, suffix ) \
|
||||
BOOST_PP_CAT( BOOST_BINARY_LITERAL_D( d, bit_groupings ), suffix )
|
||||
|
||||
#define BOOST_BINARY_LITERAL_D( d, bit_groupings ) \
|
||||
BOOST_PP_SEQ_CAT \
|
||||
( (0) BOOST_DETAIL_CREATE_BINARY_LITERAL_OCTAL_SEQUENCE( d, bit_groupings ) \
|
||||
)
|
||||
|
||||
#ifndef BOOST_UTILITY_DOCS
|
||||
#define BOOST_DETAIL_CREATE_BINARY_LITERAL_OCTAL_SEQUENCE( d, bit_groupings ) \
|
||||
BOOST_PP_SEQ_TRANSFORM \
|
||||
( BOOST_DETAIL_TRIPLE_TO_OCTAL_OPERATION \
|
||||
, BOOST_PP_NIL \
|
||||
, BOOST_PP_IDENTITY( BOOST_DETAIL_CONVERT_BIT_SEQUENCE_TO_TRIPLE_SEQUENCE )()\
|
||||
( BOOST_DETAIL_COMPLETE_TRIPLE_SEQUENCE \
|
||||
( \
|
||||
d \
|
||||
, BOOST_DETAIL_CREATE_BINARY_LITERAL_BIT_SEQUENCE( d, bit_groupings ) \
|
||||
) \
|
||||
) \
|
||||
)
|
||||
|
||||
#define BOOST_DETAIL_CONVERT_BIT_SEQUENCE_TO_TRIPLE_SEQUENCE( bit_sequence ) \
|
||||
BOOST_PP_CAT \
|
||||
( BOOST_DETAIL_CONVERT_BIT_SEQUENCE_TO_PARENTHETIC_TUPLE_1 bit_sequence \
|
||||
, END_BIT \
|
||||
)
|
||||
|
||||
#define BOOST_DETAIL_BITS_PER_OCTIT 3
|
||||
|
||||
#define BOOST_DETAIL_COMPLETE_TRIPLE_SEQUENCE( d, incomplete_nibble_sequence ) \
|
||||
BOOST_PP_CAT \
|
||||
( BOOST_DETAIL_CREATE_TRIPLE_COMPLETION_SEQUENCE_ \
|
||||
, BOOST_PP_MOD_D( d \
|
||||
, BOOST_PP_SEQ_SIZE( incomplete_nibble_sequence ) \
|
||||
, BOOST_DETAIL_BITS_PER_OCTIT \
|
||||
) \
|
||||
) \
|
||||
incomplete_nibble_sequence
|
||||
|
||||
#define BOOST_DETAIL_FIXED_COMPL( bit ) \
|
||||
BOOST_PP_CAT( BOOST_DETAIL_FIXED_COMPL_, bit )
|
||||
|
||||
#define BOOST_DETAIL_FIXED_COMPL_0 1
|
||||
|
||||
#define BOOST_DETAIL_FIXED_COMPL_1 0
|
||||
|
||||
#define BOOST_DETAIL_CREATE_BINARY_LITERAL_BIT_SEQUENCE( d, bit_groupings ) \
|
||||
BOOST_PP_EMPTY \
|
||||
BOOST_PP_CAT( BOOST_PP_WHILE_, d ) \
|
||||
( BOOST_DETAIL_BINARY_LITERAL_PREDICATE \
|
||||
, BOOST_DETAIL_BINARY_LITERAL_OPERATION \
|
||||
, bit_groupings () \
|
||||
)
|
||||
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_PREDICATE( d, state ) \
|
||||
BOOST_DETAIL_FIXED_COMPL( BOOST_DETAIL_IS_NULLARY_ARGS( state ) )
|
||||
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_OPERATION( d, state ) \
|
||||
BOOST_DETAIL_SPLIT_AND_SWAP \
|
||||
( BOOST_PP_CAT( BOOST_DETAIL_BINARY_LITERAL_ELEMENT_, state ) )
|
||||
|
||||
#define BOOST_DETAIL_TRIPLE_TO_OCTAL_OPERATION( s, dummy_param, tuple ) \
|
||||
BOOST_DETAIL_TERNARY_TRIPLE_TO_OCTAL tuple
|
||||
|
||||
#define BOOST_DETAIL_TERNARY_TRIPLE_TO_OCTAL( bit2, bit1, bit0 ) \
|
||||
BOOST_DETAIL_TRIPLE_TO_OCTAL_ ## bit2 ## bit1 ## bit0
|
||||
|
||||
#define BOOST_DETAIL_CREATE_TRIPLE_COMPLETION_SEQUENCE_1 (0)(0)
|
||||
#define BOOST_DETAIL_CREATE_TRIPLE_COMPLETION_SEQUENCE_2 (0)
|
||||
#define BOOST_DETAIL_CREATE_TRIPLE_COMPLETION_SEQUENCE_0
|
||||
|
||||
#define BOOST_DETAIL_CONVERT_BIT_SEQUENCE_TO_PARENTHETIC_TUPLE_1END_BIT
|
||||
|
||||
#define BOOST_DETAIL_CONVERT_BIT_SEQUENCE_TO_PARENTHETIC_TUPLE_1( bit ) \
|
||||
( ( bit, BOOST_DETAIL_CONVERT_BIT_SEQUENCE_TO_PARENTHETIC_TUPLE_2
|
||||
|
||||
#define BOOST_DETAIL_CONVERT_BIT_SEQUENCE_TO_PARENTHETIC_TUPLE_2( bit ) \
|
||||
bit, BOOST_DETAIL_CONVERT_BIT_SEQUENCE_TO_PARENTHETIC_TUPLE_3
|
||||
|
||||
#define BOOST_DETAIL_CONVERT_BIT_SEQUENCE_TO_PARENTHETIC_TUPLE_3( bit ) \
|
||||
bit ) ) BOOST_DETAIL_CONVERT_BIT_SEQUENCE_TO_PARENTHETIC_TUPLE_1
|
||||
|
||||
#define BOOST_DETAIL_SPLIT_AND_SWAP( params ) \
|
||||
BOOST_PP_IDENTITY( BOOST_DETAIL_SPLIT_AND_SWAP_PARAMS )()( params )
|
||||
|
||||
#define BOOST_DETAIL_SPLIT_AND_SWAP_PARAMS( first_param, second_param ) \
|
||||
second_param first_param
|
||||
|
||||
#define BOOST_DETAIL_LEFT_OF_COMMA( params ) \
|
||||
BOOST_PP_IDENTITY( BOOST_DETAIL_FIRST_MACRO_PARAM )()( params )
|
||||
|
||||
#define BOOST_DETAIL_FIRST_MACRO_PARAM( first_param, second_param ) \
|
||||
first_param
|
||||
|
||||
/* Begin derived concepts from Chaos by Paul Mensonides */
|
||||
|
||||
#define BOOST_DETAIL_IS_NULLARY_ARGS( param ) \
|
||||
BOOST_DETAIL_LEFT_OF_COMMA \
|
||||
( BOOST_PP_CAT( BOOST_DETAIL_IS_NULLARY_ARGS_R_ \
|
||||
, BOOST_DETAIL_IS_NULLARY_ARGS_C param \
|
||||
) \
|
||||
)
|
||||
|
||||
#define BOOST_DETAIL_IS_NULLARY_ARGS_C() \
|
||||
1
|
||||
|
||||
#define BOOST_DETAIL_IS_NULLARY_ARGS_R_1 \
|
||||
1, BOOST_PP_NIL
|
||||
|
||||
#define BOOST_DETAIL_IS_NULLARY_ARGS_R_BOOST_DETAIL_IS_NULLARY_ARGS_C \
|
||||
0, BOOST_PP_NIL
|
||||
|
||||
/* End derived concepts from Chaos by Paul Mensonides */
|
||||
|
||||
#define BOOST_DETAIL_TRIPLE_TO_OCTAL_000 0
|
||||
#define BOOST_DETAIL_TRIPLE_TO_OCTAL_001 1
|
||||
#define BOOST_DETAIL_TRIPLE_TO_OCTAL_010 2
|
||||
#define BOOST_DETAIL_TRIPLE_TO_OCTAL_011 3
|
||||
#define BOOST_DETAIL_TRIPLE_TO_OCTAL_100 4
|
||||
#define BOOST_DETAIL_TRIPLE_TO_OCTAL_101 5
|
||||
#define BOOST_DETAIL_TRIPLE_TO_OCTAL_110 6
|
||||
#define BOOST_DETAIL_TRIPLE_TO_OCTAL_111 7
|
||||
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0 (0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1 (1),
|
||||
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00 (0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01 (0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10 (1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11 (1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00 (0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01 (0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10 (1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11 (1)(1),
|
||||
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_000 (0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_001 (0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_010 (0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_011 (0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_100 (1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_101 (1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_110 (1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_111 (1)(1)(1),
|
||||
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0000 (0)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0001 (0)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0010 (0)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0011 (0)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0100 (0)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0101 (0)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0110 (0)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0111 (0)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1000 (1)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1001 (1)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1010 (1)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1011 (1)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1100 (1)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1101 (1)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1110 (1)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1111 (1)(1)(1)(1),
|
||||
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00000 (0)(0)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00001 (0)(0)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00010 (0)(0)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00011 (0)(0)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00100 (0)(0)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00101 (0)(0)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00110 (0)(0)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00111 (0)(0)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01000 (0)(1)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01001 (0)(1)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01010 (0)(1)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01011 (0)(1)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01100 (0)(1)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01101 (0)(1)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01110 (0)(1)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01111 (0)(1)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10000 (1)(0)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10001 (1)(0)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10010 (1)(0)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10011 (1)(0)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10100 (1)(0)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10101 (1)(0)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10110 (1)(0)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10111 (1)(0)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11000 (1)(1)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11001 (1)(1)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11010 (1)(1)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11011 (1)(1)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11100 (1)(1)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11101 (1)(1)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11110 (1)(1)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11111 (1)(1)(1)(1)(1),
|
||||
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_000000 (0)(0)(0)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_000001 (0)(0)(0)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_000010 (0)(0)(0)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_000011 (0)(0)(0)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_000100 (0)(0)(0)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_000101 (0)(0)(0)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_000110 (0)(0)(0)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_000111 (0)(0)(0)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_001000 (0)(0)(1)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_001001 (0)(0)(1)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_001010 (0)(0)(1)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_001011 (0)(0)(1)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_001100 (0)(0)(1)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_001101 (0)(0)(1)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_001110 (0)(0)(1)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_001111 (0)(0)(1)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_010000 (0)(1)(0)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_010001 (0)(1)(0)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_010010 (0)(1)(0)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_010011 (0)(1)(0)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_010100 (0)(1)(0)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_010101 (0)(1)(0)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_010110 (0)(1)(0)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_010111 (0)(1)(0)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_011000 (0)(1)(1)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_011001 (0)(1)(1)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_011010 (0)(1)(1)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_011011 (0)(1)(1)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_011100 (0)(1)(1)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_011101 (0)(1)(1)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_011110 (0)(1)(1)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_011111 (0)(1)(1)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_100000 (1)(0)(0)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_100001 (1)(0)(0)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_100010 (1)(0)(0)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_100011 (1)(0)(0)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_100100 (1)(0)(0)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_100101 (1)(0)(0)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_100110 (1)(0)(0)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_100111 (1)(0)(0)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_101000 (1)(0)(1)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_101001 (1)(0)(1)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_101010 (1)(0)(1)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_101011 (1)(0)(1)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_101100 (1)(0)(1)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_101101 (1)(0)(1)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_101110 (1)(0)(1)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_101111 (1)(0)(1)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_110000 (1)(1)(0)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_110001 (1)(1)(0)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_110010 (1)(1)(0)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_110011 (1)(1)(0)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_110100 (1)(1)(0)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_110101 (1)(1)(0)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_110110 (1)(1)(0)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_110111 (1)(1)(0)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_111000 (1)(1)(1)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_111001 (1)(1)(1)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_111010 (1)(1)(1)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_111011 (1)(1)(1)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_111100 (1)(1)(1)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_111101 (1)(1)(1)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_111110 (1)(1)(1)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_111111 (1)(1)(1)(1)(1)(1),
|
||||
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0000000 (0)(0)(0)(0)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0000001 (0)(0)(0)(0)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0000010 (0)(0)(0)(0)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0000011 (0)(0)(0)(0)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0000100 (0)(0)(0)(0)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0000101 (0)(0)(0)(0)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0000110 (0)(0)(0)(0)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0000111 (0)(0)(0)(0)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0001000 (0)(0)(0)(1)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0001001 (0)(0)(0)(1)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0001010 (0)(0)(0)(1)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0001011 (0)(0)(0)(1)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0001100 (0)(0)(0)(1)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0001101 (0)(0)(0)(1)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0001110 (0)(0)(0)(1)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0001111 (0)(0)(0)(1)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0010000 (0)(0)(1)(0)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0010001 (0)(0)(1)(0)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0010010 (0)(0)(1)(0)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0010011 (0)(0)(1)(0)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0010100 (0)(0)(1)(0)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0010101 (0)(0)(1)(0)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0010110 (0)(0)(1)(0)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0010111 (0)(0)(1)(0)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0011000 (0)(0)(1)(1)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0011001 (0)(0)(1)(1)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0011010 (0)(0)(1)(1)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0011011 (0)(0)(1)(1)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0011100 (0)(0)(1)(1)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0011101 (0)(0)(1)(1)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0011110 (0)(0)(1)(1)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0011111 (0)(0)(1)(1)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0100000 (0)(1)(0)(0)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0100001 (0)(1)(0)(0)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0100010 (0)(1)(0)(0)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0100011 (0)(1)(0)(0)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0100100 (0)(1)(0)(0)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0100101 (0)(1)(0)(0)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0100110 (0)(1)(0)(0)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0100111 (0)(1)(0)(0)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0101000 (0)(1)(0)(1)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0101001 (0)(1)(0)(1)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0101010 (0)(1)(0)(1)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0101011 (0)(1)(0)(1)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0101100 (0)(1)(0)(1)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0101101 (0)(1)(0)(1)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0101110 (0)(1)(0)(1)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0101111 (0)(1)(0)(1)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0110000 (0)(1)(1)(0)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0110001 (0)(1)(1)(0)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0110010 (0)(1)(1)(0)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0110011 (0)(1)(1)(0)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0110100 (0)(1)(1)(0)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0110101 (0)(1)(1)(0)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0110110 (0)(1)(1)(0)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0110111 (0)(1)(1)(0)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0111000 (0)(1)(1)(1)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0111001 (0)(1)(1)(1)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0111010 (0)(1)(1)(1)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0111011 (0)(1)(1)(1)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0111100 (0)(1)(1)(1)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0111101 (0)(1)(1)(1)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0111110 (0)(1)(1)(1)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0111111 (0)(1)(1)(1)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1000000 (1)(0)(0)(0)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1000001 (1)(0)(0)(0)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1000010 (1)(0)(0)(0)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1000011 (1)(0)(0)(0)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1000100 (1)(0)(0)(0)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1000101 (1)(0)(0)(0)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1000110 (1)(0)(0)(0)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1000111 (1)(0)(0)(0)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1001000 (1)(0)(0)(1)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1001001 (1)(0)(0)(1)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1001010 (1)(0)(0)(1)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1001011 (1)(0)(0)(1)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1001100 (1)(0)(0)(1)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1001101 (1)(0)(0)(1)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1001110 (1)(0)(0)(1)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1001111 (1)(0)(0)(1)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1010000 (1)(0)(1)(0)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1010001 (1)(0)(1)(0)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1010010 (1)(0)(1)(0)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1010011 (1)(0)(1)(0)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1010100 (1)(0)(1)(0)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1010101 (1)(0)(1)(0)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1010110 (1)(0)(1)(0)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1010111 (1)(0)(1)(0)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1011000 (1)(0)(1)(1)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1011001 (1)(0)(1)(1)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1011010 (1)(0)(1)(1)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1011011 (1)(0)(1)(1)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1011100 (1)(0)(1)(1)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1011101 (1)(0)(1)(1)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1011110 (1)(0)(1)(1)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1011111 (1)(0)(1)(1)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1100000 (1)(1)(0)(0)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1100001 (1)(1)(0)(0)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1100010 (1)(1)(0)(0)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1100011 (1)(1)(0)(0)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1100100 (1)(1)(0)(0)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1100101 (1)(1)(0)(0)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1100110 (1)(1)(0)(0)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1100111 (1)(1)(0)(0)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1101000 (1)(1)(0)(1)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1101001 (1)(1)(0)(1)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1101010 (1)(1)(0)(1)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1101011 (1)(1)(0)(1)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1101100 (1)(1)(0)(1)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1101101 (1)(1)(0)(1)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1101110 (1)(1)(0)(1)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1101111 (1)(1)(0)(1)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1110000 (1)(1)(1)(0)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1110001 (1)(1)(1)(0)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1110010 (1)(1)(1)(0)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1110011 (1)(1)(1)(0)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1110100 (1)(1)(1)(0)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1110101 (1)(1)(1)(0)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1110110 (1)(1)(1)(0)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1110111 (1)(1)(1)(0)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1111000 (1)(1)(1)(1)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1111001 (1)(1)(1)(1)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1111010 (1)(1)(1)(1)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1111011 (1)(1)(1)(1)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1111100 (1)(1)(1)(1)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1111101 (1)(1)(1)(1)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1111110 (1)(1)(1)(1)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1111111 (1)(1)(1)(1)(1)(1)(1),
|
||||
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00000000 (0)(0)(0)(0)(0)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00000001 (0)(0)(0)(0)(0)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00000010 (0)(0)(0)(0)(0)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00000011 (0)(0)(0)(0)(0)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00000100 (0)(0)(0)(0)(0)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00000101 (0)(0)(0)(0)(0)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00000110 (0)(0)(0)(0)(0)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00000111 (0)(0)(0)(0)(0)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00001000 (0)(0)(0)(0)(1)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00001001 (0)(0)(0)(0)(1)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00001010 (0)(0)(0)(0)(1)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00001011 (0)(0)(0)(0)(1)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00001100 (0)(0)(0)(0)(1)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00001101 (0)(0)(0)(0)(1)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00001110 (0)(0)(0)(0)(1)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00001111 (0)(0)(0)(0)(1)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00010000 (0)(0)(0)(1)(0)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00010001 (0)(0)(0)(1)(0)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00010010 (0)(0)(0)(1)(0)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00010011 (0)(0)(0)(1)(0)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00010100 (0)(0)(0)(1)(0)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00010101 (0)(0)(0)(1)(0)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00010110 (0)(0)(0)(1)(0)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00010111 (0)(0)(0)(1)(0)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00011000 (0)(0)(0)(1)(1)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00011001 (0)(0)(0)(1)(1)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00011010 (0)(0)(0)(1)(1)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00011011 (0)(0)(0)(1)(1)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00011100 (0)(0)(0)(1)(1)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00011101 (0)(0)(0)(1)(1)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00011110 (0)(0)(0)(1)(1)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00011111 (0)(0)(0)(1)(1)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00100000 (0)(0)(1)(0)(0)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00100001 (0)(0)(1)(0)(0)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00100010 (0)(0)(1)(0)(0)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00100011 (0)(0)(1)(0)(0)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00100100 (0)(0)(1)(0)(0)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00100101 (0)(0)(1)(0)(0)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00100110 (0)(0)(1)(0)(0)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00100111 (0)(0)(1)(0)(0)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00101000 (0)(0)(1)(0)(1)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00101001 (0)(0)(1)(0)(1)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00101010 (0)(0)(1)(0)(1)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00101011 (0)(0)(1)(0)(1)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00101100 (0)(0)(1)(0)(1)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00101101 (0)(0)(1)(0)(1)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00101110 (0)(0)(1)(0)(1)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00101111 (0)(0)(1)(0)(1)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00110000 (0)(0)(1)(1)(0)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00110001 (0)(0)(1)(1)(0)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00110010 (0)(0)(1)(1)(0)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00110011 (0)(0)(1)(1)(0)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00110100 (0)(0)(1)(1)(0)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00110101 (0)(0)(1)(1)(0)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00110110 (0)(0)(1)(1)(0)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00110111 (0)(0)(1)(1)(0)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00111000 (0)(0)(1)(1)(1)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00111001 (0)(0)(1)(1)(1)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00111010 (0)(0)(1)(1)(1)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00111011 (0)(0)(1)(1)(1)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00111100 (0)(0)(1)(1)(1)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00111101 (0)(0)(1)(1)(1)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00111110 (0)(0)(1)(1)(1)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00111111 (0)(0)(1)(1)(1)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01000000 (0)(1)(0)(0)(0)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01000001 (0)(1)(0)(0)(0)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01000010 (0)(1)(0)(0)(0)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01000011 (0)(1)(0)(0)(0)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01000100 (0)(1)(0)(0)(0)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01000101 (0)(1)(0)(0)(0)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01000110 (0)(1)(0)(0)(0)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01000111 (0)(1)(0)(0)(0)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01001000 (0)(1)(0)(0)(1)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01001001 (0)(1)(0)(0)(1)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01001010 (0)(1)(0)(0)(1)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01001011 (0)(1)(0)(0)(1)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01001100 (0)(1)(0)(0)(1)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01001101 (0)(1)(0)(0)(1)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01001110 (0)(1)(0)(0)(1)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01001111 (0)(1)(0)(0)(1)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01010000 (0)(1)(0)(1)(0)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01010001 (0)(1)(0)(1)(0)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01010010 (0)(1)(0)(1)(0)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01010011 (0)(1)(0)(1)(0)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01010100 (0)(1)(0)(1)(0)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01010101 (0)(1)(0)(1)(0)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01010110 (0)(1)(0)(1)(0)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01010111 (0)(1)(0)(1)(0)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01011000 (0)(1)(0)(1)(1)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01011001 (0)(1)(0)(1)(1)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01011010 (0)(1)(0)(1)(1)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01011011 (0)(1)(0)(1)(1)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01011100 (0)(1)(0)(1)(1)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01011101 (0)(1)(0)(1)(1)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01011110 (0)(1)(0)(1)(1)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01011111 (0)(1)(0)(1)(1)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01100000 (0)(1)(1)(0)(0)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01100001 (0)(1)(1)(0)(0)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01100010 (0)(1)(1)(0)(0)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01100011 (0)(1)(1)(0)(0)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01100100 (0)(1)(1)(0)(0)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01100101 (0)(1)(1)(0)(0)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01100110 (0)(1)(1)(0)(0)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01100111 (0)(1)(1)(0)(0)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01101000 (0)(1)(1)(0)(1)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01101001 (0)(1)(1)(0)(1)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01101010 (0)(1)(1)(0)(1)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01101011 (0)(1)(1)(0)(1)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01101100 (0)(1)(1)(0)(1)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01101101 (0)(1)(1)(0)(1)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01101110 (0)(1)(1)(0)(1)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01101111 (0)(1)(1)(0)(1)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01110000 (0)(1)(1)(1)(0)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01110001 (0)(1)(1)(1)(0)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01110010 (0)(1)(1)(1)(0)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01110011 (0)(1)(1)(1)(0)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01110100 (0)(1)(1)(1)(0)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01110101 (0)(1)(1)(1)(0)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01110110 (0)(1)(1)(1)(0)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01110111 (0)(1)(1)(1)(0)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01111000 (0)(1)(1)(1)(1)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01111001 (0)(1)(1)(1)(1)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01111010 (0)(1)(1)(1)(1)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01111011 (0)(1)(1)(1)(1)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01111100 (0)(1)(1)(1)(1)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01111101 (0)(1)(1)(1)(1)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01111110 (0)(1)(1)(1)(1)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01111111 (0)(1)(1)(1)(1)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10000000 (1)(0)(0)(0)(0)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10000001 (1)(0)(0)(0)(0)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10000010 (1)(0)(0)(0)(0)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10000011 (1)(0)(0)(0)(0)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10000100 (1)(0)(0)(0)(0)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10000101 (1)(0)(0)(0)(0)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10000110 (1)(0)(0)(0)(0)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10000111 (1)(0)(0)(0)(0)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10001000 (1)(0)(0)(0)(1)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10001001 (1)(0)(0)(0)(1)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10001010 (1)(0)(0)(0)(1)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10001011 (1)(0)(0)(0)(1)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10001100 (1)(0)(0)(0)(1)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10001101 (1)(0)(0)(0)(1)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10001110 (1)(0)(0)(0)(1)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10001111 (1)(0)(0)(0)(1)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10010000 (1)(0)(0)(1)(0)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10010001 (1)(0)(0)(1)(0)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10010010 (1)(0)(0)(1)(0)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10010011 (1)(0)(0)(1)(0)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10010100 (1)(0)(0)(1)(0)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10010101 (1)(0)(0)(1)(0)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10010110 (1)(0)(0)(1)(0)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10010111 (1)(0)(0)(1)(0)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10011000 (1)(0)(0)(1)(1)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10011001 (1)(0)(0)(1)(1)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10011010 (1)(0)(0)(1)(1)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10011011 (1)(0)(0)(1)(1)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10011100 (1)(0)(0)(1)(1)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10011101 (1)(0)(0)(1)(1)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10011110 (1)(0)(0)(1)(1)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10011111 (1)(0)(0)(1)(1)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10100000 (1)(0)(1)(0)(0)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10100001 (1)(0)(1)(0)(0)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10100010 (1)(0)(1)(0)(0)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10100011 (1)(0)(1)(0)(0)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10100100 (1)(0)(1)(0)(0)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10100101 (1)(0)(1)(0)(0)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10100110 (1)(0)(1)(0)(0)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10100111 (1)(0)(1)(0)(0)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10101000 (1)(0)(1)(0)(1)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10101001 (1)(0)(1)(0)(1)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10101010 (1)(0)(1)(0)(1)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10101011 (1)(0)(1)(0)(1)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10101100 (1)(0)(1)(0)(1)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10101101 (1)(0)(1)(0)(1)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10101110 (1)(0)(1)(0)(1)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10101111 (1)(0)(1)(0)(1)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10110000 (1)(0)(1)(1)(0)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10110001 (1)(0)(1)(1)(0)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10110010 (1)(0)(1)(1)(0)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10110011 (1)(0)(1)(1)(0)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10110100 (1)(0)(1)(1)(0)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10110101 (1)(0)(1)(1)(0)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10110110 (1)(0)(1)(1)(0)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10110111 (1)(0)(1)(1)(0)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10111000 (1)(0)(1)(1)(1)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10111001 (1)(0)(1)(1)(1)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10111010 (1)(0)(1)(1)(1)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10111011 (1)(0)(1)(1)(1)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10111100 (1)(0)(1)(1)(1)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10111101 (1)(0)(1)(1)(1)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10111110 (1)(0)(1)(1)(1)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10111111 (1)(0)(1)(1)(1)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11000000 (1)(1)(0)(0)(0)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11000001 (1)(1)(0)(0)(0)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11000010 (1)(1)(0)(0)(0)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11000011 (1)(1)(0)(0)(0)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11000100 (1)(1)(0)(0)(0)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11000101 (1)(1)(0)(0)(0)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11000110 (1)(1)(0)(0)(0)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11000111 (1)(1)(0)(0)(0)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11001000 (1)(1)(0)(0)(1)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11001001 (1)(1)(0)(0)(1)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11001010 (1)(1)(0)(0)(1)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11001011 (1)(1)(0)(0)(1)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11001100 (1)(1)(0)(0)(1)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11001101 (1)(1)(0)(0)(1)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11001110 (1)(1)(0)(0)(1)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11001111 (1)(1)(0)(0)(1)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11010000 (1)(1)(0)(1)(0)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11010001 (1)(1)(0)(1)(0)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11010010 (1)(1)(0)(1)(0)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11010011 (1)(1)(0)(1)(0)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11010100 (1)(1)(0)(1)(0)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11010101 (1)(1)(0)(1)(0)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11010110 (1)(1)(0)(1)(0)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11010111 (1)(1)(0)(1)(0)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11011000 (1)(1)(0)(1)(1)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11011001 (1)(1)(0)(1)(1)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11011010 (1)(1)(0)(1)(1)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11011011 (1)(1)(0)(1)(1)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11011100 (1)(1)(0)(1)(1)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11011101 (1)(1)(0)(1)(1)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11011110 (1)(1)(0)(1)(1)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11011111 (1)(1)(0)(1)(1)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11100000 (1)(1)(1)(0)(0)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11100001 (1)(1)(1)(0)(0)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11100010 (1)(1)(1)(0)(0)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11100011 (1)(1)(1)(0)(0)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11100100 (1)(1)(1)(0)(0)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11100101 (1)(1)(1)(0)(0)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11100110 (1)(1)(1)(0)(0)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11100111 (1)(1)(1)(0)(0)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11101000 (1)(1)(1)(0)(1)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11101001 (1)(1)(1)(0)(1)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11101010 (1)(1)(1)(0)(1)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11101011 (1)(1)(1)(0)(1)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11101100 (1)(1)(1)(0)(1)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11101101 (1)(1)(1)(0)(1)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11101110 (1)(1)(1)(0)(1)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11101111 (1)(1)(1)(0)(1)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11110000 (1)(1)(1)(1)(0)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11110001 (1)(1)(1)(1)(0)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11110010 (1)(1)(1)(1)(0)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11110011 (1)(1)(1)(1)(0)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11110100 (1)(1)(1)(1)(0)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11110101 (1)(1)(1)(1)(0)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11110110 (1)(1)(1)(1)(0)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11110111 (1)(1)(1)(1)(0)(1)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11111000 (1)(1)(1)(1)(1)(0)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11111001 (1)(1)(1)(1)(1)(0)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11111010 (1)(1)(1)(1)(1)(0)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11111011 (1)(1)(1)(1)(1)(0)(1)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11111100 (1)(1)(1)(1)(1)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11111101 (1)(1)(1)(1)(1)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11111110 (1)(1)(1)(1)(1)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11111111 (1)(1)(1)(1)(1)(1)(1)(1),
|
||||
#endif // BOOST_UTILITY_DOCS
|
||||
#endif
|
76
include/boost/utility/compare_pointees.hpp
Normal file
76
include/boost/utility/compare_pointees.hpp
Normal file
@ -0,0 +1,76 @@
|
||||
// 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/libs/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
#ifndef BOOST_UTILITY_COMPARE_POINTEES_25AGO2003_HPP
|
||||
#define BOOST_UTILITY_COMPARE_POINTEES_25AGO2003_HPP
|
||||
|
||||
#include<functional>
|
||||
|
||||
namespace boost {
|
||||
|
||||
// template<class OP> bool equal_pointees(OP const& x, OP const& y);
|
||||
// template<class OP> struct equal_pointees_t;
|
||||
//
|
||||
// Being OP a model of OptionalPointee (either a pointer or an optional):
|
||||
//
|
||||
// If both x and y have valid pointees, returns the result of (*x == *y)
|
||||
// If only one has a valid pointee, returns false.
|
||||
// If none have valid pointees, returns true.
|
||||
// No-throw
|
||||
template<class OptionalPointee>
|
||||
inline
|
||||
bool equal_pointees ( OptionalPointee const& x, OptionalPointee const& y )
|
||||
{
|
||||
return (!x) != (!y) ? false : ( !x ? true : (*x) == (*y) ) ;
|
||||
}
|
||||
|
||||
template<class OptionalPointee>
|
||||
struct equal_pointees_t
|
||||
{
|
||||
typedef bool result_type;
|
||||
typedef OptionalPointee first_argument_type;
|
||||
typedef OptionalPointee second_argument_type;
|
||||
|
||||
bool operator() ( OptionalPointee const& x, OptionalPointee const& y ) const
|
||||
{ return equal_pointees(x,y) ; }
|
||||
} ;
|
||||
|
||||
// template<class OP> bool less_pointees(OP const& x, OP const& y);
|
||||
// template<class OP> struct less_pointees_t;
|
||||
//
|
||||
// Being OP a model of OptionalPointee (either a pointer or an optional):
|
||||
//
|
||||
// If y has not a valid pointee, returns false.
|
||||
// ElseIf x has not a valid pointee, returns true.
|
||||
// ElseIf both x and y have valid pointees, returns the result of (*x < *y)
|
||||
// No-throw
|
||||
template<class OptionalPointee>
|
||||
inline
|
||||
bool less_pointees ( OptionalPointee const& x, OptionalPointee const& y )
|
||||
{
|
||||
return !y ? false : ( !x ? true : (*x) < (*y) ) ;
|
||||
}
|
||||
|
||||
template<class OptionalPointee>
|
||||
struct less_pointees_t
|
||||
{
|
||||
typedef bool result_type;
|
||||
typedef OptionalPointee first_argument_type;
|
||||
typedef OptionalPointee second_argument_type;
|
||||
|
||||
bool operator() ( OptionalPointee const& x, OptionalPointee const& y ) const
|
||||
{ return less_pointees(x,y) ; }
|
||||
} ;
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
36
include/boost/utility/detail/in_place_factory_prefix.hpp
Normal file
36
include/boost/utility/detail/in_place_factory_prefix.hpp
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
// Copyright (C) 2007, Tobias Schwinger.
|
||||
//
|
||||
// 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_UTILITY_DETAIL_INPLACE_FACTORY_PREFIX_04APR2007_HPP
|
||||
#define BOOST_UTILITY_DETAIL_INPLACE_FACTORY_PREFIX_04APR2007_HPP
|
||||
|
||||
#include <new>
|
||||
#include <cstddef>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
#include <boost/preprocessor/punctuation/paren.hpp>
|
||||
#include <boost/preprocessor/iteration/iterate.hpp>
|
||||
#include <boost/preprocessor/repetition/repeat.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/repetition/enum_trailing_params.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_MAX_INPLACE_FACTORY_ARITY 10
|
||||
|
||||
#undef BOOST_UTILITY_DETAIL_INPLACE_FACTORY_SUFFIX_04APR2007_HPP
|
||||
|
||||
#endif
|
||||
|
23
include/boost/utility/detail/in_place_factory_suffix.hpp
Normal file
23
include/boost/utility/detail/in_place_factory_suffix.hpp
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
// Copyright (C) 2007, Tobias Schwinger.
|
||||
//
|
||||
// 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_UTILITY_DETAIL_INPLACE_FACTORY_SUFFIX_04APR2007_HPP
|
||||
#define BOOST_UTILITY_DETAIL_INPLACE_FACTORY_SUFFIX_04APR2007_HPP
|
||||
|
||||
#undef BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_INIT
|
||||
#undef BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_DECL
|
||||
#undef BOOST_MAX_INPLACE_FACTORY_ARITY
|
||||
|
||||
#undef BOOST_UTILITY_DETAIL_INPLACE_FACTORY_PREFIX_04APR2007_HPP
|
||||
|
||||
#endif
|
||||
|
58
include/boost/utility/detail/minstd_rand.hpp
Normal file
58
include/boost/utility/detail/minstd_rand.hpp
Normal file
@ -0,0 +1,58 @@
|
||||
#ifndef BOOST_UTILITY_DETAIL_MINSTD_RAND_HPP_INCLUDED
|
||||
#define BOOST_UTILITY_DETAIL_MINSTD_RAND_HPP_INCLUDED
|
||||
|
||||
// Copyright 2017 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
|
||||
//
|
||||
// An implementation of minstd_rand that does not require
|
||||
// the Random library
|
||||
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class minstd_rand
|
||||
{
|
||||
private:
|
||||
|
||||
boost::uint_least32_t x_;
|
||||
|
||||
enum { a = 48271, m = 2147483647 };
|
||||
|
||||
public:
|
||||
|
||||
minstd_rand(): x_( 1 )
|
||||
{
|
||||
}
|
||||
|
||||
explicit minstd_rand( boost::uint_least32_t x ): x_( x % m )
|
||||
{
|
||||
if( x_ == 0 )
|
||||
{
|
||||
x_ = 1;
|
||||
}
|
||||
}
|
||||
|
||||
boost::uint_least32_t operator()()
|
||||
{
|
||||
boost::uint_least64_t y = x_;
|
||||
|
||||
y = ( a * y ) % m;
|
||||
|
||||
x_ = static_cast<boost::uint_least32_t>( y );
|
||||
|
||||
return x_;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_UTILITY_DETAIL_MINSTD_RAND_HPP_INCLUDED
|
218
include/boost/utility/detail/result_of_iterate.hpp
Normal file
218
include/boost/utility/detail/result_of_iterate.hpp
Normal file
@ -0,0 +1,218 @@
|
||||
// Boost result_of library
|
||||
|
||||
// Copyright Douglas Gregor 2004. 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)
|
||||
|
||||
// Copyright Daniel Walker, Eric Niebler, Michel Morin 2008-2012.
|
||||
// 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)
|
||||
|
||||
// For more information, see http://www.boost.org/libs/utility
|
||||
#if !defined(BOOST_PP_IS_ITERATING)
|
||||
# error Boost result_of - do not include this file!
|
||||
#endif
|
||||
|
||||
// CWPro8 requires an argument in a function type specialization
|
||||
#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3002)) && BOOST_PP_ITERATION() == 0
|
||||
# define BOOST_RESULT_OF_ARGS void
|
||||
#else
|
||||
# define BOOST_RESULT_OF_ARGS BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)
|
||||
#endif
|
||||
|
||||
#if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x551))
|
||||
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct tr1_result_of<F(BOOST_RESULT_OF_ARGS)>
|
||||
: conditional<
|
||||
is_pointer<F>::value || is_member_function_pointer<F>::value
|
||||
, boost::detail::tr1_result_of_impl<
|
||||
typename remove_cv<F>::type,
|
||||
typename remove_cv<F>::type(BOOST_RESULT_OF_ARGS),
|
||||
(boost::detail::result_of_has_result_type<F>::value)>
|
||||
, boost::detail::tr1_result_of_impl<
|
||||
F,
|
||||
F(BOOST_RESULT_OF_ARGS),
|
||||
(boost::detail::result_of_has_result_type<F>::value)> >::type { };
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
|
||||
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct result_of<F(BOOST_RESULT_OF_ARGS)>
|
||||
: detail::cpp0x_result_of<F(BOOST_RESULT_OF_ARGS)> { };
|
||||
#endif // BOOST_RESULT_OF_USE_DECLTYPE
|
||||
|
||||
#ifdef BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK
|
||||
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct result_of<F(BOOST_RESULT_OF_ARGS)>
|
||||
: conditional<detail::result_of_has_result_type<F>::value || detail::result_of_has_result<F>::value,
|
||||
tr1_result_of<F(BOOST_RESULT_OF_ARGS)>,
|
||||
detail::cpp0x_result_of<F(BOOST_RESULT_OF_ARGS)> >::type { };
|
||||
#endif // BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK
|
||||
|
||||
#if defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct cpp0x_result_of<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T))>
|
||||
: conditional<
|
||||
is_member_function_pointer<F>::value
|
||||
, detail::tr1_result_of_impl<
|
||||
typename remove_cv<F>::type,
|
||||
typename remove_cv<F>::type(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), false
|
||||
>
|
||||
, detail::cpp0x_result_of_impl<
|
||||
F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T))
|
||||
>
|
||||
>::type
|
||||
{};
|
||||
|
||||
#ifdef BOOST_NO_SFINAE_EXPR
|
||||
|
||||
template<typename F>
|
||||
struct BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION());
|
||||
|
||||
template<typename R BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), typename T)>
|
||||
struct BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION())<R(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), T))> {
|
||||
R operator()(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), T)) const;
|
||||
typedef result_of_private_type const &(*pfn_t)(...);
|
||||
operator pfn_t() const volatile;
|
||||
};
|
||||
|
||||
template<typename F>
|
||||
struct BOOST_PP_CAT(result_of_callable_fun_, BOOST_PP_ITERATION())
|
||||
: BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION())<F>
|
||||
{};
|
||||
|
||||
template<typename F>
|
||||
struct BOOST_PP_CAT(result_of_callable_fun_, BOOST_PP_ITERATION())<F *>
|
||||
: BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION())<F>
|
||||
{};
|
||||
|
||||
template<typename F>
|
||||
struct BOOST_PP_CAT(result_of_select_call_wrapper_type_, BOOST_PP_ITERATION())
|
||||
: conditional<
|
||||
is_class<typename remove_reference<F>::type>::value,
|
||||
result_of_wrap_callable_class<F>,
|
||||
type_identity<BOOST_PP_CAT(result_of_callable_fun_, BOOST_PP_ITERATION())<typename remove_cv<typename remove_reference<F>::type>::type> >
|
||||
>::type
|
||||
{};
|
||||
|
||||
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), typename T)>
|
||||
struct BOOST_PP_CAT(result_of_is_callable_, BOOST_PP_ITERATION()) {
|
||||
typedef typename BOOST_PP_CAT(result_of_select_call_wrapper_type_, BOOST_PP_ITERATION())<F>::type wrapper_t;
|
||||
static const bool value = (
|
||||
sizeof(result_of_no_type) == sizeof(detail::result_of_is_private_type(
|
||||
(boost::declval<wrapper_t>()(BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval<T, >() BOOST_PP_INTERCEPT)), result_of_weird_type())
|
||||
))
|
||||
);
|
||||
typedef integral_constant<bool, value> type;
|
||||
};
|
||||
|
||||
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), true>
|
||||
: lazy_enable_if<
|
||||
BOOST_PP_CAT(result_of_is_callable_, BOOST_PP_ITERATION())<F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), T)>
|
||||
, cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), false>
|
||||
>
|
||||
{};
|
||||
|
||||
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), false>
|
||||
{
|
||||
typedef decltype(
|
||||
boost::declval<F>()(
|
||||
BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval<T, >() BOOST_PP_INTERCEPT)
|
||||
)
|
||||
) type;
|
||||
};
|
||||
|
||||
#else // BOOST_NO_SFINAE_EXPR
|
||||
|
||||
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)),
|
||||
typename result_of_always_void<decltype(
|
||||
boost::declval<F>()(
|
||||
BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval<T, >() BOOST_PP_INTERCEPT)
|
||||
)
|
||||
)>::type> {
|
||||
typedef decltype(
|
||||
boost::declval<F>()(
|
||||
BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval<T, >() BOOST_PP_INTERCEPT)
|
||||
)
|
||||
) type;
|
||||
};
|
||||
|
||||
#endif // BOOST_NO_SFINAE_EXPR
|
||||
|
||||
} // namespace detail
|
||||
|
||||
#else // defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)
|
||||
|
||||
#if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x551))
|
||||
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct result_of<F(BOOST_RESULT_OF_ARGS)>
|
||||
: tr1_result_of<F(BOOST_RESULT_OF_ARGS)> { };
|
||||
#endif
|
||||
|
||||
#endif // defined(BOOST_RESULT_OF_USE_DECLTYPE)
|
||||
|
||||
#undef BOOST_RESULT_OF_ARGS
|
||||
|
||||
#if BOOST_PP_ITERATION() >= 1
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct tr1_result_of_impl<R (*)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), FArgs, false>
|
||||
{
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct tr1_result_of_impl<R (&)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), FArgs, false>
|
||||
{
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
#if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x551))
|
||||
template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct tr1_result_of_impl<R (T0::*)
|
||||
(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T)),
|
||||
FArgs, false>
|
||||
{
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct tr1_result_of_impl<R (T0::*)
|
||||
(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T))
|
||||
const,
|
||||
FArgs, false>
|
||||
{
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct tr1_result_of_impl<R (T0::*)
|
||||
(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T))
|
||||
volatile,
|
||||
FArgs, false>
|
||||
{
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct tr1_result_of_impl<R (T0::*)
|
||||
(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T))
|
||||
const volatile,
|
||||
FArgs, false>
|
||||
{
|
||||
typedef R type;
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
||||
#endif
|
190
include/boost/utility/detail/result_of_variadic.hpp
Normal file
190
include/boost/utility/detail/result_of_variadic.hpp
Normal file
@ -0,0 +1,190 @@
|
||||
// Boost result_of library
|
||||
|
||||
// Copyright Douglas Gregor 2004. 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)
|
||||
|
||||
// Copyright Daniel Walker, Eric Niebler, Michel Morin 2008-2012.
|
||||
// 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)
|
||||
|
||||
// For more information, see http://www.boost.org/libs/utility
|
||||
|
||||
#ifndef BOOST_RESULT_OF_HPP
|
||||
# error Boost result_of - do not include this file!
|
||||
#endif
|
||||
|
||||
template<typename F, typename... Args>
|
||||
struct tr1_result_of<F(Args...)>
|
||||
: conditional<
|
||||
is_pointer<F>::value || is_member_function_pointer<F>::value
|
||||
, boost::detail::tr1_result_of_impl<
|
||||
typename remove_cv<F>::type,
|
||||
typename remove_cv<F>::type(Args...),
|
||||
(boost::detail::result_of_has_result_type<F>::value)>
|
||||
, boost::detail::tr1_result_of_impl<
|
||||
F,
|
||||
F(Args...),
|
||||
(boost::detail::result_of_has_result_type<F>::value)> >::type { };
|
||||
|
||||
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
|
||||
template<typename F, typename... Args>
|
||||
struct result_of<F(Args...)>
|
||||
: detail::cpp0x_result_of<F(Args...)> { };
|
||||
#endif // BOOST_RESULT_OF_USE_DECLTYPE
|
||||
|
||||
#ifdef BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK
|
||||
template<typename F, typename... Args>
|
||||
struct result_of<F(Args...)>
|
||||
: conditional<detail::result_of_has_result_type<F>::value || detail::result_of_has_result<F>::value,
|
||||
tr1_result_of<F(Args...)>,
|
||||
detail::cpp0x_result_of<F(Args...)> >::type { };
|
||||
#endif // BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK
|
||||
|
||||
#if defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename F, typename... Args>
|
||||
struct cpp0x_result_of<F(Args...)>
|
||||
: conditional<
|
||||
is_member_function_pointer<F>::value
|
||||
, detail::tr1_result_of_impl<
|
||||
typename remove_cv<F>::type,
|
||||
typename remove_cv<F>::type(Args...), false
|
||||
>
|
||||
, detail::cpp0x_result_of_impl<
|
||||
F(Args...)
|
||||
>
|
||||
>::type
|
||||
{};
|
||||
|
||||
#ifdef BOOST_NO_SFINAE_EXPR
|
||||
|
||||
template<typename F>
|
||||
struct result_of_callable_fun_2;
|
||||
|
||||
template<typename R, typename... Args>
|
||||
struct result_of_callable_fun_2<R(Args...)> {
|
||||
R operator()(Args...) const;
|
||||
typedef result_of_private_type const &(*pfn_t)(...);
|
||||
operator pfn_t() const volatile;
|
||||
};
|
||||
|
||||
template<typename F>
|
||||
struct result_of_callable_fun
|
||||
: result_of_callable_fun_2<F>
|
||||
{};
|
||||
|
||||
template<typename F>
|
||||
struct result_of_callable_fun<F *>
|
||||
: result_of_callable_fun_2<F>
|
||||
{};
|
||||
|
||||
template<typename F>
|
||||
struct result_of_select_call_wrapper_type
|
||||
: conditional<
|
||||
is_class<typename remove_reference<F>::type>::value,
|
||||
result_of_wrap_callable_class<F>,
|
||||
type_identity<result_of_callable_fun<typename remove_cv<typename remove_reference<F>::type>::type> >
|
||||
>::type
|
||||
{};
|
||||
|
||||
template<typename F, typename... Args>
|
||||
struct result_of_is_callable {
|
||||
typedef typename result_of_select_call_wrapper_type<F>::type wrapper_t;
|
||||
static const bool value = (
|
||||
sizeof(result_of_no_type) == sizeof(detail::result_of_is_private_type(
|
||||
(boost::declval<wrapper_t>()(boost::declval<Args>()...), result_of_weird_type())
|
||||
))
|
||||
);
|
||||
typedef integral_constant<bool, value> type;
|
||||
};
|
||||
|
||||
template<typename F, typename... Args>
|
||||
struct cpp0x_result_of_impl<F(Args...), true>
|
||||
: lazy_enable_if<
|
||||
result_of_is_callable<F, Args...>
|
||||
, cpp0x_result_of_impl<F(Args...), false>
|
||||
>
|
||||
{};
|
||||
|
||||
template<typename F, typename... Args>
|
||||
struct cpp0x_result_of_impl<F(Args...), false>
|
||||
{
|
||||
typedef decltype(
|
||||
boost::declval<F>()(
|
||||
boost::declval<Args>()...
|
||||
)
|
||||
) type;
|
||||
};
|
||||
|
||||
#else // BOOST_NO_SFINAE_EXPR
|
||||
|
||||
template<typename F, typename... Args>
|
||||
struct cpp0x_result_of_impl<F(Args...),
|
||||
typename result_of_always_void<decltype(
|
||||
boost::declval<F>()(
|
||||
boost::declval<Args>()...
|
||||
)
|
||||
)>::type> {
|
||||
typedef decltype(
|
||||
boost::declval<F>()(
|
||||
boost::declval<Args>()...
|
||||
)
|
||||
) type;
|
||||
};
|
||||
|
||||
#endif // BOOST_NO_SFINAE_EXPR
|
||||
|
||||
} // namespace detail
|
||||
|
||||
#else // defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)
|
||||
|
||||
template<typename F, typename... Args>
|
||||
struct result_of<F(Args...)>
|
||||
: tr1_result_of<F(Args...)> { };
|
||||
|
||||
#endif // defined(BOOST_RESULT_OF_USE_DECLTYPE)
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename R, typename FArgs, typename... Args>
|
||||
struct tr1_result_of_impl<R (*)(Args...), FArgs, false>
|
||||
{
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
template<typename R, typename FArgs, typename... Args>
|
||||
struct tr1_result_of_impl<R (&)(Args...), FArgs, false>
|
||||
{
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
template<typename R, typename FArgs, typename C, typename... Args>
|
||||
struct tr1_result_of_impl<R (C::*)(Args...), FArgs, false>
|
||||
{
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
template<typename R, typename FArgs, typename C, typename... Args>
|
||||
struct tr1_result_of_impl<R (C::*)(Args...) const, FArgs, false>
|
||||
{
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
template<typename R, typename FArgs, typename C, typename... Args>
|
||||
struct tr1_result_of_impl<R (C::*)(Args...) volatile, FArgs, false>
|
||||
{
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
template<typename R, typename FArgs, typename C, typename... Args>
|
||||
struct tr1_result_of_impl<R (C::*)(Args...) const volatile, FArgs, false>
|
||||
{
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
}
|
46
include/boost/utility/identity_type.hpp
Normal file
46
include/boost/utility/identity_type.hpp
Normal file
@ -0,0 +1,46 @@
|
||||
|
||||
// Copyright (C) 2009-2012 Lorenzo Caminiti
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// (see accompanying file LICENSE_1_0.txt or a copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
// Home at http://www.boost.org/libs/utility/identity_type
|
||||
|
||||
/** @file
|
||||
Wrap type expressions with round parenthesis so they can be passed to macros
|
||||
even if they contain commas.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_IDENTITY_TYPE_HPP_
|
||||
#define BOOST_IDENTITY_TYPE_HPP_
|
||||
|
||||
#include <boost/type_traits/function_traits.hpp>
|
||||
|
||||
/**
|
||||
@brief This macro allows to wrap the specified type expression within extra
|
||||
round parenthesis so the type can be passed as a single macro parameter even if
|
||||
it contains commas (not already wrapped within round parenthesis).
|
||||
|
||||
@Params
|
||||
@Param{parenthesized_type,
|
||||
The type expression to be passed as macro parameter wrapped by a single set
|
||||
of round parenthesis <c>(...)</c>.
|
||||
This type expression can contain an arbitrary number of commas.
|
||||
}
|
||||
@EndParams
|
||||
|
||||
This macro works on any C++03 compiler (it does not use variadic macros).
|
||||
|
||||
This macro must be prefixed by <c>typename</c> when used within templates.
|
||||
Note that the compiler will not be able to automatically determine function
|
||||
template parameters when they are wrapped with this macro (these parameters
|
||||
need to be explicitly specified when calling the function template).
|
||||
|
||||
On some compilers (like GCC), using this macro on abstract types requires to
|
||||
add and remove a reference to the specified type.
|
||||
*/
|
||||
#define BOOST_IDENTITY_TYPE(parenthesized_type) \
|
||||
/* must NOT prefix this with `::` to work with parenthesized syntax */ \
|
||||
boost::function_traits< void parenthesized_type >::arg1_type
|
||||
|
||||
#endif // #include guard
|
||||
|
92
include/boost/utility/in_place_factory.hpp
Normal file
92
include/boost/utility/in_place_factory.hpp
Normal file
@ -0,0 +1,92 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
// Copyright (C) 2007, Tobias Schwinger.
|
||||
//
|
||||
// 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_UTILITY_INPLACE_FACTORY_04APR2007_HPP
|
||||
#ifndef BOOST_PP_IS_ITERATING
|
||||
|
||||
#include <boost/utility/detail/in_place_factory_prefix.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
class in_place_factory_base {} ;
|
||||
|
||||
#ifndef BOOST_UTILITY_DOCS
|
||||
#define BOOST_PP_ITERATION_LIMITS (0, BOOST_MAX_INPLACE_FACTORY_ARITY)
|
||||
#define BOOST_PP_FILENAME_1 <boost/utility/in_place_factory.hpp>
|
||||
#endif // BOOST_UTILITY_DOCS
|
||||
|
||||
#include BOOST_PP_ITERATE()
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/utility/detail/in_place_factory_suffix.hpp>
|
||||
|
||||
#ifndef BOOST_UTILITY_DOCS
|
||||
#define BOOST_UTILITY_INPLACE_FACTORY_04APR2007_HPP
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define N BOOST_PP_ITERATION()
|
||||
|
||||
#if N
|
||||
template< BOOST_PP_ENUM_PARAMS(N, class A) >
|
||||
#endif
|
||||
class BOOST_PP_CAT(in_place_factory,N)
|
||||
:
|
||||
public in_place_factory_base
|
||||
{
|
||||
public:
|
||||
|
||||
explicit BOOST_PP_CAT(in_place_factory,N)
|
||||
( BOOST_PP_ENUM_BINARY_PARAMS(N,A,const& a) )
|
||||
#if N > 0
|
||||
: BOOST_PP_ENUM(N, BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_INIT, _)
|
||||
#endif
|
||||
{}
|
||||
|
||||
template<class T>
|
||||
void* apply(void* address) const
|
||||
{
|
||||
return new(address) T( BOOST_PP_ENUM_PARAMS(N, m_a) );
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void* apply(void* address, std::size_t n) const
|
||||
{
|
||||
for(char* next = address = this->BOOST_NESTED_TEMPLATE apply<T>(address);
|
||||
!! --n;)
|
||||
this->BOOST_NESTED_TEMPLATE apply<T>(next = next+sizeof(T));
|
||||
return address;
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT(N, BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_DECL, _)
|
||||
};
|
||||
|
||||
#if N > 0
|
||||
template< BOOST_PP_ENUM_PARAMS(N, class A) >
|
||||
inline BOOST_PP_CAT(in_place_factory,N)< BOOST_PP_ENUM_PARAMS(N, A) >
|
||||
in_place( BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& a) )
|
||||
{
|
||||
return BOOST_PP_CAT(in_place_factory,N)< BOOST_PP_ENUM_PARAMS(N, A) >
|
||||
( BOOST_PP_ENUM_PARAMS(N, a) );
|
||||
}
|
||||
#else
|
||||
inline in_place_factory0 in_place()
|
||||
{
|
||||
return in_place_factory0();
|
||||
}
|
||||
#endif
|
||||
|
||||
#undef N
|
||||
#endif
|
||||
#endif
|
||||
|
256
include/boost/utility/result_of.hpp
Normal file
256
include/boost/utility/result_of.hpp
Normal file
@ -0,0 +1,256 @@
|
||||
// Boost result_of library
|
||||
|
||||
// Copyright Douglas Gregor 2004. 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)
|
||||
|
||||
// For more information, see http://www.boost.org/libs/utility
|
||||
#ifndef BOOST_RESULT_OF_HPP
|
||||
#define BOOST_RESULT_OF_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/type_traits/is_class.hpp>
|
||||
#include <boost/type_traits/is_pointer.hpp>
|
||||
#include <boost/type_traits/is_member_function_pointer.hpp>
|
||||
#include <boost/type_traits/remove_cv.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/type_traits/declval.hpp>
|
||||
#include <boost/type_traits/conditional.hpp>
|
||||
#include <boost/type_traits/type_identity.hpp>
|
||||
#include <boost/type_traits/integral_constant.hpp>
|
||||
#include <boost/core/enable_if.hpp>
|
||||
|
||||
#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
|
||||
# undef BOOST_RESULT_OF_NO_VARIADIC_TEMPLATES
|
||||
# define BOOST_RESULT_OF_NO_VARIADIC_TEMPLATES
|
||||
#endif
|
||||
#ifdef BOOST_RESULT_OF_NO_VARIADIC_TEMPLATES
|
||||
# include <boost/preprocessor/cat.hpp>
|
||||
# include <boost/preprocessor/iteration/iterate.hpp>
|
||||
# include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
# include <boost/preprocessor/repetition/enum_trailing_params.hpp>
|
||||
# include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
# include <boost/preprocessor/repetition/enum_shifted_params.hpp>
|
||||
# include <boost/preprocessor/facilities/intercept.hpp>
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_UTILITY_DOCS
|
||||
#ifndef BOOST_RESULT_OF_NUM_ARGS
|
||||
# define BOOST_RESULT_OF_NUM_ARGS 16
|
||||
#endif
|
||||
#endif // BOOST_UTILITY_DOCS
|
||||
|
||||
// Use the decltype-based version of result_of by default if the compiler
|
||||
// supports N3276 <http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2011/n3276.pdf>.
|
||||
// The user can force the choice by defining BOOST_RESULT_OF_USE_DECLTYPE,
|
||||
// BOOST_RESULT_OF_USE_TR1, or BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK but not more than one!
|
||||
#if (defined(BOOST_RESULT_OF_USE_DECLTYPE) && defined(BOOST_RESULT_OF_USE_TR1)) || \
|
||||
(defined(BOOST_RESULT_OF_USE_DECLTYPE) && defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)) || \
|
||||
(defined(BOOST_RESULT_OF_USE_TR1) && defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK))
|
||||
# error More than one of BOOST_RESULT_OF_USE_DECLTYPE, BOOST_RESULT_OF_USE_TR1 and \
|
||||
BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK cannot be defined at the same time.
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_UTILITY_DOCS
|
||||
#ifndef BOOST_RESULT_OF_USE_TR1
|
||||
# ifndef BOOST_RESULT_OF_USE_DECLTYPE
|
||||
# ifndef BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK
|
||||
# ifndef BOOST_NO_CXX11_DECLTYPE_N3276 // this implies !defined(BOOST_NO_CXX11_DECLTYPE)
|
||||
# define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
# else
|
||||
# define BOOST_RESULT_OF_USE_TR1
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
#endif // BOOST_UTILITY_DOCS
|
||||
|
||||
namespace boost {
|
||||
|
||||
template<typename F> struct result_of;
|
||||
template<typename F> struct tr1_result_of; // a TR1-style implementation of result_of
|
||||
|
||||
#if !defined(BOOST_NO_SFINAE)
|
||||
namespace detail {
|
||||
|
||||
typedef char result_of_yes_type; // sizeof(result_of_yes_type) == 1
|
||||
typedef char (&result_of_no_type)[2]; // sizeof(result_of_no_type) == 2
|
||||
|
||||
template<class T> struct result_of_has_type {};
|
||||
|
||||
template<class T> struct result_of_has_result_type_impl
|
||||
{
|
||||
template<class U> static result_of_yes_type f( result_of_has_type<typename U::result_type>* );
|
||||
template<class U> static result_of_no_type f( ... );
|
||||
|
||||
typedef boost::integral_constant<bool, sizeof(f<T>(0)) == sizeof(result_of_yes_type)> type;
|
||||
};
|
||||
|
||||
template<class T> struct result_of_has_result_type: result_of_has_result_type_impl<T>::type
|
||||
{
|
||||
};
|
||||
|
||||
// Work around a nvcc bug by only defining has_result when it's needed.
|
||||
#ifdef BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK
|
||||
|
||||
template<template<class> class C> struct result_of_has_template {};
|
||||
|
||||
template<class T> struct result_of_has_result_impl
|
||||
{
|
||||
template<class U> static result_of_yes_type f( result_of_has_template<U::template result>* );
|
||||
template<class U> static result_of_no_type f( ... );
|
||||
|
||||
typedef boost::integral_constant<bool, sizeof(f<T>(0)) == sizeof(result_of_yes_type)> type;
|
||||
};
|
||||
|
||||
template<class T> struct result_of_has_result: result_of_has_result_impl<T>::type
|
||||
{
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
template<typename F, typename FArgs, bool HasResultType> struct tr1_result_of_impl;
|
||||
|
||||
template<typename F> struct cpp0x_result_of;
|
||||
|
||||
#ifdef BOOST_NO_SFINAE_EXPR
|
||||
|
||||
// There doesn't seem to be any other way to turn this off such that the presence of
|
||||
// the user-defined operator,() below doesn't cause spurious warning all over the place,
|
||||
// so unconditionally and globally turn it off. (https://svn.boost.org/trac10/ticket/7663)
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(disable: 4913) // user defined binary operator ',' exists but no overload could convert all operands, default built-in binary operator ',' used
|
||||
#endif
|
||||
|
||||
struct result_of_private_type {};
|
||||
|
||||
struct result_of_weird_type {
|
||||
friend result_of_private_type operator,(result_of_private_type, result_of_weird_type);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
result_of_no_type result_of_is_private_type(T const &);
|
||||
result_of_yes_type result_of_is_private_type(result_of_private_type);
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4512) // assignment operator could not be generated.
|
||||
#endif
|
||||
template<typename C>
|
||||
struct result_of_callable_class : C {
|
||||
result_of_callable_class();
|
||||
typedef result_of_private_type const &(*pfn_t)(...);
|
||||
operator pfn_t() const volatile;
|
||||
};
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
template<typename C>
|
||||
struct result_of_wrap_callable_class {
|
||||
typedef result_of_callable_class<C> type;
|
||||
};
|
||||
|
||||
template<typename C>
|
||||
struct result_of_wrap_callable_class<C const> {
|
||||
typedef result_of_callable_class<C> const type;
|
||||
};
|
||||
|
||||
template<typename C>
|
||||
struct result_of_wrap_callable_class<C volatile> {
|
||||
typedef result_of_callable_class<C> volatile type;
|
||||
};
|
||||
|
||||
template<typename C>
|
||||
struct result_of_wrap_callable_class<C const volatile> {
|
||||
typedef result_of_callable_class<C> const volatile type;
|
||||
};
|
||||
|
||||
template<typename C>
|
||||
struct result_of_wrap_callable_class<C &> {
|
||||
typedef typename result_of_wrap_callable_class<C>::type &type;
|
||||
};
|
||||
|
||||
template<typename F, bool TestCallability = true> struct cpp0x_result_of_impl;
|
||||
|
||||
#else // BOOST_NO_SFINAE_EXPR
|
||||
|
||||
template<typename T>
|
||||
struct result_of_always_void
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
template<typename F, typename Enable = void> struct cpp0x_result_of_impl {};
|
||||
|
||||
#endif // BOOST_NO_SFINAE_EXPR
|
||||
|
||||
template<typename F>
|
||||
struct result_of_void_impl
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
template<typename R>
|
||||
struct result_of_void_impl<R (*)(void)>
|
||||
{
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
template<typename R>
|
||||
struct result_of_void_impl<R (&)(void)>
|
||||
{
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
// Determine the return type of a function pointer or pointer to member.
|
||||
template<typename F, typename FArgs>
|
||||
struct result_of_pointer
|
||||
: tr1_result_of_impl<typename remove_cv<F>::type, FArgs, false> { };
|
||||
|
||||
template<typename F, typename FArgs>
|
||||
struct tr1_result_of_impl<F, FArgs, true>
|
||||
{
|
||||
typedef typename F::result_type type;
|
||||
};
|
||||
|
||||
template<typename FArgs>
|
||||
struct is_function_with_no_args : false_type {};
|
||||
|
||||
template<typename F>
|
||||
struct is_function_with_no_args<F(void)> : true_type {};
|
||||
|
||||
template<typename F, typename FArgs>
|
||||
struct result_of_nested_result : F::template result<FArgs>
|
||||
{};
|
||||
|
||||
template<typename F, typename FArgs>
|
||||
struct tr1_result_of_impl<F, FArgs, false>
|
||||
: conditional<is_function_with_no_args<FArgs>::value,
|
||||
result_of_void_impl<F>,
|
||||
result_of_nested_result<F, FArgs> >::type
|
||||
{};
|
||||
|
||||
} // end namespace detail
|
||||
|
||||
#ifndef BOOST_RESULT_OF_NO_VARIADIC_TEMPLATES
|
||||
# include <boost/utility/detail/result_of_variadic.hpp>
|
||||
#else
|
||||
# define BOOST_PP_ITERATION_PARAMS_1 (3,(0,BOOST_RESULT_OF_NUM_ARGS,<boost/utility/detail/result_of_iterate.hpp>))
|
||||
# include BOOST_PP_ITERATE()
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
// inform dependency trackers, as they can't see through macro includes
|
||||
#include <boost/utility/detail/result_of_iterate.hpp>
|
||||
#endif
|
||||
|
||||
#else
|
||||
# define BOOST_NO_RESULT_OF 1
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif // BOOST_RESULT_OF_HPP
|
520
include/boost/utility/string_ref.hpp
Normal file
520
include/boost/utility/string_ref.hpp
Normal file
@ -0,0 +1,520 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2012-2015.
|
||||
Copyright (c) Glen Joseph Fernandes 2019 (glenjofe@gmail.com)
|
||||
|
||||
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)
|
||||
|
||||
For more information, see http://www.boost.org
|
||||
|
||||
Based on the StringRef implementation in LLVM (http://llvm.org) and
|
||||
N3422 by Jeffrey Yasskin
|
||||
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html
|
||||
|
||||
*/
|
||||
|
||||
#ifndef BOOST_STRING_REF_HPP
|
||||
#define BOOST_STRING_REF_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/io/ostream_put.hpp>
|
||||
#include <boost/utility/string_ref_fwd.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <iosfwd>
|
||||
|
||||
#if defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || (defined(BOOST_GCC) && ((BOOST_GCC+0) / 100) <= 406)
|
||||
// GCC 4.6 cannot handle a defaulted function with noexcept specifier
|
||||
#define BOOST_STRING_REF_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
// A helper functor because sometimes we don't have lambdas
|
||||
template <typename charT, typename traits>
|
||||
class string_ref_traits_eq {
|
||||
public:
|
||||
string_ref_traits_eq ( charT ch ) : ch_(ch) {}
|
||||
bool operator () ( charT val ) const { return traits::eq ( ch_, val ); }
|
||||
charT ch_;
|
||||
};
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
class basic_string_ref {
|
||||
public:
|
||||
// types
|
||||
typedef charT value_type;
|
||||
typedef const charT* pointer;
|
||||
typedef const charT& reference;
|
||||
typedef const charT& const_reference;
|
||||
typedef pointer const_iterator; // impl-defined
|
||||
typedef const_iterator iterator;
|
||||
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
||||
typedef const_reverse_iterator reverse_iterator;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
static BOOST_CONSTEXPR_OR_CONST size_type npos = size_type(-1);
|
||||
|
||||
// construct/copy
|
||||
BOOST_CONSTEXPR basic_string_ref () BOOST_NOEXCEPT
|
||||
: ptr_(NULL), len_(0) {}
|
||||
|
||||
// by defaulting these functions, basic_string_ref becomes
|
||||
// trivially copy/move constructible.
|
||||
BOOST_CONSTEXPR basic_string_ref (const basic_string_ref &rhs) BOOST_NOEXCEPT
|
||||
#ifndef BOOST_STRING_REF_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS
|
||||
= default;
|
||||
#else
|
||||
: ptr_(rhs.ptr_), len_(rhs.len_) {}
|
||||
#endif
|
||||
|
||||
basic_string_ref& operator=(const basic_string_ref &rhs) BOOST_NOEXCEPT
|
||||
#ifndef BOOST_STRING_REF_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS
|
||||
= default;
|
||||
#else
|
||||
{
|
||||
ptr_ = rhs.ptr_;
|
||||
len_ = rhs.len_;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
basic_string_ref(const charT* str) BOOST_NOEXCEPT
|
||||
: ptr_(str), len_(traits::length(str)) {}
|
||||
|
||||
template<typename Allocator>
|
||||
basic_string_ref(const std::basic_string<charT, traits, Allocator>& str)
|
||||
: ptr_(str.data()), len_(str.length()) {}
|
||||
|
||||
// #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
|
||||
// // Constructing a string_ref from a temporary string is a bad idea
|
||||
// template<typename Allocator>
|
||||
// basic_string_ref( std::basic_string<charT, traits, Allocator>&&)
|
||||
// = delete;
|
||||
// #endif
|
||||
|
||||
BOOST_CONSTEXPR basic_string_ref(const charT* str, size_type len) BOOST_NOEXCEPT
|
||||
: ptr_(str), len_(len) {}
|
||||
|
||||
#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
|
||||
template<typename Allocator>
|
||||
explicit operator std::basic_string<charT, traits, Allocator>() const {
|
||||
return std::basic_string<charT, traits, Allocator> ( begin(), end());
|
||||
}
|
||||
#endif
|
||||
|
||||
std::basic_string<charT, traits> to_string () const {
|
||||
return std::basic_string<charT, traits> ( begin(), end());
|
||||
}
|
||||
|
||||
// iterators
|
||||
BOOST_CONSTEXPR const_iterator begin() const { return ptr_; }
|
||||
BOOST_CONSTEXPR const_iterator cbegin() const { return ptr_; }
|
||||
BOOST_CONSTEXPR const_iterator end() const { return ptr_ + len_; }
|
||||
BOOST_CONSTEXPR const_iterator cend() const { return ptr_ + len_; }
|
||||
const_reverse_iterator rbegin() const { return const_reverse_iterator (end()); }
|
||||
const_reverse_iterator crbegin() const { return const_reverse_iterator (end()); }
|
||||
const_reverse_iterator rend() const { return const_reverse_iterator (begin()); }
|
||||
const_reverse_iterator crend() const { return const_reverse_iterator (begin()); }
|
||||
|
||||
// capacity
|
||||
BOOST_CONSTEXPR size_type size() const { return len_; }
|
||||
BOOST_CONSTEXPR size_type length() const { return len_; }
|
||||
BOOST_CONSTEXPR size_type max_size() const { return ~static_cast<size_type>(0) / (sizeof(value_type) * 2u); }
|
||||
BOOST_CONSTEXPR bool empty() const { return len_ == 0; }
|
||||
|
||||
// element access
|
||||
BOOST_CONSTEXPR const charT& operator[](size_type pos) const { return ptr_[pos]; }
|
||||
|
||||
const charT& at(size_type pos) const {
|
||||
if ( pos >= len_ )
|
||||
BOOST_THROW_EXCEPTION( std::out_of_range ( "boost::string_ref::at" ) );
|
||||
return ptr_[pos];
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR const charT& front() const { return ptr_[0]; }
|
||||
BOOST_CONSTEXPR const charT& back() const { return ptr_[len_-1]; }
|
||||
BOOST_CONSTEXPR const charT* data() const { return ptr_; }
|
||||
|
||||
// modifiers
|
||||
void clear() { len_ = 0; }
|
||||
void remove_prefix(size_type n) {
|
||||
if ( n > len_ )
|
||||
n = len_;
|
||||
ptr_ += n;
|
||||
len_ -= n;
|
||||
}
|
||||
|
||||
void remove_suffix(size_type n) {
|
||||
if ( n > len_ )
|
||||
n = len_;
|
||||
len_ -= n;
|
||||
}
|
||||
|
||||
|
||||
// basic_string_ref string operations
|
||||
basic_string_ref substr() const {
|
||||
return basic_string_ref(data(), size());
|
||||
}
|
||||
|
||||
basic_string_ref substr(size_type pos, size_type n=npos) const {
|
||||
if ( pos > size())
|
||||
BOOST_THROW_EXCEPTION( std::out_of_range ( "string_ref::substr" ) );
|
||||
return basic_string_ref(data() + pos, (std::min)(size() - pos, n));
|
||||
}
|
||||
|
||||
int compare(basic_string_ref x) const {
|
||||
const int cmp = traits::compare ( ptr_, x.ptr_, (std::min)(len_, x.len_));
|
||||
return cmp != 0 ? cmp : ( len_ == x.len_ ? 0 : len_ < x.len_ ? -1 : 1 );
|
||||
}
|
||||
|
||||
bool starts_with(charT c) const { return !empty() && traits::eq ( c, front()); }
|
||||
bool starts_with(basic_string_ref x) const {
|
||||
return len_ >= x.len_ && traits::compare ( ptr_, x.ptr_, x.len_ ) == 0;
|
||||
}
|
||||
|
||||
bool ends_with(charT c) const { return !empty() && traits::eq ( c, back()); }
|
||||
bool ends_with(basic_string_ref x) const {
|
||||
return len_ >= x.len_ && traits::compare ( ptr_ + len_ - x.len_, x.ptr_, x.len_ ) == 0;
|
||||
}
|
||||
|
||||
size_type find(basic_string_ref s) const {
|
||||
if (s.empty()) return 0;
|
||||
const_iterator iter = std::search ( this->cbegin (), this->cend (),
|
||||
s.cbegin (), s.cend (), traits::eq );
|
||||
return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
|
||||
}
|
||||
|
||||
size_type find(charT c) const {
|
||||
const_iterator iter = std::find_if ( this->cbegin (), this->cend (),
|
||||
detail::string_ref_traits_eq<charT, traits> ( c ));
|
||||
return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
|
||||
}
|
||||
|
||||
size_type rfind(basic_string_ref s) const {
|
||||
if (s.empty()) return 0;
|
||||
const_reverse_iterator iter = std::search ( this->crbegin (), this->crend (),
|
||||
s.crbegin (), s.crend (), traits::eq );
|
||||
return iter == this->crend () ? npos : (std::distance(iter, this->crend()) - s.size());
|
||||
}
|
||||
|
||||
size_type rfind(charT c) const {
|
||||
const_reverse_iterator iter = std::find_if ( this->crbegin (), this->crend (),
|
||||
detail::string_ref_traits_eq<charT, traits> ( c ));
|
||||
return iter == this->crend () ? npos : (this->size() - 1 - std::distance(this->crbegin(), iter));
|
||||
}
|
||||
|
||||
size_type find_first_of(charT c) const { return find (c); }
|
||||
size_type find_last_of (charT c) const { return rfind (c); }
|
||||
|
||||
size_type find_first_of(basic_string_ref s) const {
|
||||
const_iterator iter = std::find_first_of
|
||||
( this->cbegin (), this->cend (), s.cbegin (), s.cend (), traits::eq );
|
||||
return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
|
||||
}
|
||||
|
||||
size_type find_last_of(basic_string_ref s) const {
|
||||
const_reverse_iterator iter = std::find_first_of
|
||||
( this->crbegin (), this->crend (), s.cbegin (), s.cend (), traits::eq );
|
||||
return iter == this->crend () ? npos : (this->size() - 1 - std::distance(this->crbegin(), iter));
|
||||
}
|
||||
|
||||
size_type find_first_not_of(basic_string_ref s) const {
|
||||
const_iterator iter = find_not_of ( this->cbegin (), this->cend (), s );
|
||||
return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
|
||||
}
|
||||
|
||||
size_type find_first_not_of(charT c) const {
|
||||
for ( const_iterator iter = this->cbegin (); iter != this->cend (); ++iter )
|
||||
if ( !traits::eq ( c, *iter ))
|
||||
return std::distance ( this->cbegin (), iter );
|
||||
return npos;
|
||||
}
|
||||
|
||||
size_type find_last_not_of(basic_string_ref s) const {
|
||||
const_reverse_iterator iter = find_not_of ( this->crbegin (), this->crend (), s );
|
||||
return iter == this->crend () ? npos : (this->size() - 1 - std::distance(this->crbegin(), iter));
|
||||
}
|
||||
|
||||
size_type find_last_not_of(charT c) const {
|
||||
for ( const_reverse_iterator iter = this->crbegin (); iter != this->crend (); ++iter )
|
||||
if ( !traits::eq ( c, *iter ))
|
||||
return this->size() - 1 - std::distance(this->crbegin(), iter);
|
||||
return npos;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template <typename Iterator>
|
||||
Iterator find_not_of ( Iterator first, Iterator last, basic_string_ref s ) const {
|
||||
for ( ; first != last ; ++first )
|
||||
if ( 0 == traits::find ( s.ptr_, s.len_, *first ))
|
||||
return first;
|
||||
return last;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const charT *ptr_;
|
||||
std::size_t len_;
|
||||
};
|
||||
|
||||
|
||||
// Comparison operators
|
||||
// Equality
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator==(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y) {
|
||||
if ( x.size () != y.size ()) return false;
|
||||
return x.compare(y) == 0;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator==(basic_string_ref<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) {
|
||||
return x == basic_string_ref<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator==(const std::basic_string<charT, traits, Allocator> & x, basic_string_ref<charT, traits> y) {
|
||||
return basic_string_ref<charT, traits>(x) == y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator==(basic_string_ref<charT, traits> x, const charT * y) {
|
||||
return x == basic_string_ref<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator==(const charT * x, basic_string_ref<charT, traits> y) {
|
||||
return basic_string_ref<charT, traits>(x) == y;
|
||||
}
|
||||
|
||||
// Inequality
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator!=(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y) {
|
||||
if ( x.size () != y.size ()) return true;
|
||||
return x.compare(y) != 0;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator!=(basic_string_ref<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) {
|
||||
return x != basic_string_ref<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator!=(const std::basic_string<charT, traits, Allocator> & x, basic_string_ref<charT, traits> y) {
|
||||
return basic_string_ref<charT, traits>(x) != y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator!=(basic_string_ref<charT, traits> x, const charT * y) {
|
||||
return x != basic_string_ref<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator!=(const charT * x, basic_string_ref<charT, traits> y) {
|
||||
return basic_string_ref<charT, traits>(x) != y;
|
||||
}
|
||||
|
||||
// Less than
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator<(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y) {
|
||||
return x.compare(y) < 0;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator<(basic_string_ref<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) {
|
||||
return x < basic_string_ref<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator<(const std::basic_string<charT, traits, Allocator> & x, basic_string_ref<charT, traits> y) {
|
||||
return basic_string_ref<charT, traits>(x) < y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator<(basic_string_ref<charT, traits> x, const charT * y) {
|
||||
return x < basic_string_ref<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator<(const charT * x, basic_string_ref<charT, traits> y) {
|
||||
return basic_string_ref<charT, traits>(x) < y;
|
||||
}
|
||||
|
||||
// Greater than
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator>(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y) {
|
||||
return x.compare(y) > 0;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator>(basic_string_ref<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) {
|
||||
return x > basic_string_ref<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator>(const std::basic_string<charT, traits, Allocator> & x, basic_string_ref<charT, traits> y) {
|
||||
return basic_string_ref<charT, traits>(x) > y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator>(basic_string_ref<charT, traits> x, const charT * y) {
|
||||
return x > basic_string_ref<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator>(const charT * x, basic_string_ref<charT, traits> y) {
|
||||
return basic_string_ref<charT, traits>(x) > y;
|
||||
}
|
||||
|
||||
// Less than or equal to
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator<=(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y) {
|
||||
return x.compare(y) <= 0;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator<=(basic_string_ref<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) {
|
||||
return x <= basic_string_ref<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator<=(const std::basic_string<charT, traits, Allocator> & x, basic_string_ref<charT, traits> y) {
|
||||
return basic_string_ref<charT, traits>(x) <= y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator<=(basic_string_ref<charT, traits> x, const charT * y) {
|
||||
return x <= basic_string_ref<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator<=(const charT * x, basic_string_ref<charT, traits> y) {
|
||||
return basic_string_ref<charT, traits>(x) <= y;
|
||||
}
|
||||
|
||||
// Greater than or equal to
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator>=(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y) {
|
||||
return x.compare(y) >= 0;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator>=(basic_string_ref<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) {
|
||||
return x >= basic_string_ref<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator>=(const std::basic_string<charT, traits, Allocator> & x, basic_string_ref<charT, traits> y) {
|
||||
return basic_string_ref<charT, traits>(x) >= y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator>=(basic_string_ref<charT, traits> x, const charT * y) {
|
||||
return x >= basic_string_ref<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator>=(const charT * x, basic_string_ref<charT, traits> y) {
|
||||
return basic_string_ref<charT, traits>(x) >= y;
|
||||
}
|
||||
|
||||
// Inserter
|
||||
template<class charT, class traits>
|
||||
inline std::basic_ostream<charT, traits>&
|
||||
operator<<(std::basic_ostream<charT, traits>& os, const basic_string_ref<charT,traits>& str) {
|
||||
return boost::io::ostream_put(os, str.data(), str.size());
|
||||
}
|
||||
|
||||
#if 0
|
||||
// numeric conversions
|
||||
//
|
||||
// These are short-term implementations.
|
||||
// In a production environment, I would rather avoid the copying.
|
||||
//
|
||||
inline int stoi (string_ref str, size_t* idx=0, int base=10) {
|
||||
return std::stoi ( std::string(str), idx, base );
|
||||
}
|
||||
|
||||
inline long stol (string_ref str, size_t* idx=0, int base=10) {
|
||||
return std::stol ( std::string(str), idx, base );
|
||||
}
|
||||
|
||||
inline unsigned long stoul (string_ref str, size_t* idx=0, int base=10) {
|
||||
return std::stoul ( std::string(str), idx, base );
|
||||
}
|
||||
|
||||
inline long long stoll (string_ref str, size_t* idx=0, int base=10) {
|
||||
return std::stoll ( std::string(str), idx, base );
|
||||
}
|
||||
|
||||
inline unsigned long long stoull (string_ref str, size_t* idx=0, int base=10) {
|
||||
return std::stoull ( std::string(str), idx, base );
|
||||
}
|
||||
|
||||
inline float stof (string_ref str, size_t* idx=0) {
|
||||
return std::stof ( std::string(str), idx );
|
||||
}
|
||||
|
||||
inline double stod (string_ref str, size_t* idx=0) {
|
||||
return std::stod ( std::string(str), idx );
|
||||
}
|
||||
|
||||
inline long double stold (string_ref str, size_t* idx=0) {
|
||||
return std::stold ( std::string(str), idx );
|
||||
}
|
||||
|
||||
inline int stoi (wstring_ref str, size_t* idx=0, int base=10) {
|
||||
return std::stoi ( std::wstring(str), idx, base );
|
||||
}
|
||||
|
||||
inline long stol (wstring_ref str, size_t* idx=0, int base=10) {
|
||||
return std::stol ( std::wstring(str), idx, base );
|
||||
}
|
||||
|
||||
inline unsigned long stoul (wstring_ref str, size_t* idx=0, int base=10) {
|
||||
return std::stoul ( std::wstring(str), idx, base );
|
||||
}
|
||||
|
||||
inline long long stoll (wstring_ref str, size_t* idx=0, int base=10) {
|
||||
return std::stoll ( std::wstring(str), idx, base );
|
||||
}
|
||||
|
||||
inline unsigned long long stoull (wstring_ref str, size_t* idx=0, int base=10) {
|
||||
return std::stoull ( std::wstring(str), idx, base );
|
||||
}
|
||||
|
||||
inline float stof (wstring_ref str, size_t* idx=0) {
|
||||
return std::stof ( std::wstring(str), idx );
|
||||
}
|
||||
|
||||
inline double stod (wstring_ref str, size_t* idx=0) {
|
||||
return std::stod ( std::wstring(str), idx );
|
||||
}
|
||||
|
||||
inline long double stold (wstring_ref str, size_t* idx=0) {
|
||||
return std::stold ( std::wstring(str), idx );
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
namespace std {
|
||||
// Hashing
|
||||
template<> struct hash<boost::string_ref>;
|
||||
template<> struct hash<boost::u16string_ref>;
|
||||
template<> struct hash<boost::u32string_ref>;
|
||||
template<> struct hash<boost::wstring_ref>;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
37
include/boost/utility/string_ref_fwd.hpp
Normal file
37
include/boost/utility/string_ref_fwd.hpp
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2012-2012.
|
||||
|
||||
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)
|
||||
|
||||
For more information, see http://www.boost.org
|
||||
|
||||
Based on the StringRef implementation in LLVM (http://llvm.org) and
|
||||
N3422 by Jeffrey Yasskin
|
||||
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html
|
||||
|
||||
*/
|
||||
|
||||
#ifndef BOOST_STRING_REF_FWD_HPP
|
||||
#define BOOST_STRING_REF_FWD_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template<typename charT, typename traits = std::char_traits<charT> > class basic_string_ref;
|
||||
typedef basic_string_ref<char, std::char_traits<char> > string_ref;
|
||||
typedef basic_string_ref<wchar_t, std::char_traits<wchar_t> > wstring_ref;
|
||||
|
||||
#ifndef BOOST_NO_CXX11_CHAR16_T
|
||||
typedef basic_string_ref<char16_t, std::char_traits<char16_t> > u16string_ref;
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_CXX11_CHAR32_T
|
||||
typedef basic_string_ref<char32_t, std::char_traits<char32_t> > u32string_ref;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
689
include/boost/utility/string_view.hpp
Normal file
689
include/boost/utility/string_view.hpp
Normal file
@ -0,0 +1,689 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2012-2015.
|
||||
Copyright (c) Beman Dawes 2015
|
||||
Copyright (c) Glen Joseph Fernandes 2019 (glenjofe@gmail.com)
|
||||
|
||||
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)
|
||||
|
||||
For more information, see http://www.boost.org
|
||||
|
||||
Based on the StringRef implementation in LLVM (http://llvm.org) and
|
||||
N3422 by Jeffrey Yasskin
|
||||
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html
|
||||
Updated July 2015 to reflect the Library Fundamentals TS
|
||||
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html
|
||||
*/
|
||||
|
||||
#ifndef BOOST_STRING_VIEW_HPP
|
||||
#define BOOST_STRING_VIEW_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/io/ostream_put.hpp>
|
||||
#include <boost/utility/string_view_fwd.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <iosfwd>
|
||||
|
||||
#if defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || (defined(BOOST_GCC) && ((BOOST_GCC+0) / 100) <= 406)
|
||||
// GCC 4.6 cannot handle a defaulted function with noexcept specifier
|
||||
#define BOOST_STRING_VIEW_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
// A helper functor because sometimes we don't have lambdas
|
||||
template <typename charT, typename traits>
|
||||
class string_view_traits_eq {
|
||||
public:
|
||||
string_view_traits_eq ( charT ch ) : ch_(ch) {}
|
||||
bool operator()( charT val ) const { return traits::eq (ch_, val); }
|
||||
charT ch_;
|
||||
};
|
||||
}
|
||||
|
||||
template<typename charT, typename traits> // traits defaulted in string_view_fwd.hpp
|
||||
class basic_string_view {
|
||||
public:
|
||||
// types
|
||||
typedef traits traits_type;
|
||||
typedef charT value_type;
|
||||
typedef charT* pointer;
|
||||
typedef const charT* const_pointer;
|
||||
typedef charT& reference;
|
||||
typedef const charT& const_reference;
|
||||
typedef const_pointer const_iterator; // impl-defined
|
||||
typedef const_iterator iterator;
|
||||
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
||||
typedef const_reverse_iterator reverse_iterator;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
static BOOST_CONSTEXPR_OR_CONST size_type npos = size_type(-1);
|
||||
|
||||
// construct/copy
|
||||
BOOST_CONSTEXPR basic_string_view() BOOST_NOEXCEPT
|
||||
: ptr_(NULL), len_(0) {}
|
||||
|
||||
// by defaulting these functions, basic_string_ref becomes
|
||||
// trivially copy/move constructible.
|
||||
BOOST_CONSTEXPR basic_string_view(const basic_string_view &rhs) BOOST_NOEXCEPT
|
||||
#ifndef BOOST_STRING_VIEW_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS
|
||||
= default;
|
||||
#else
|
||||
: ptr_(rhs.ptr_), len_(rhs.len_) {}
|
||||
#endif
|
||||
|
||||
basic_string_view& operator=(const basic_string_view &rhs) BOOST_NOEXCEPT
|
||||
#ifndef BOOST_STRING_VIEW_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS
|
||||
= default;
|
||||
#else
|
||||
{
|
||||
ptr_ = rhs.ptr_;
|
||||
len_ = rhs.len_;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename Allocator>
|
||||
basic_string_view(const std::basic_string<charT, traits, Allocator>& str) BOOST_NOEXCEPT
|
||||
: ptr_(str.data()), len_(str.length()) {}
|
||||
|
||||
// #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
|
||||
// // Constructing a string_view from a temporary string is a bad idea
|
||||
// template<typename Allocator>
|
||||
// basic_string_view( std::basic_string<charT, traits, Allocator>&&)
|
||||
// = delete;
|
||||
// #endif
|
||||
|
||||
BOOST_CONSTEXPR basic_string_view(const charT* str)
|
||||
: ptr_(str), len_(traits::length(str)) {}
|
||||
|
||||
BOOST_CONSTEXPR basic_string_view(const charT* str, size_type len)
|
||||
: ptr_(str), len_(len) {}
|
||||
|
||||
// iterators
|
||||
BOOST_CONSTEXPR const_iterator begin() const BOOST_NOEXCEPT { return ptr_; }
|
||||
BOOST_CONSTEXPR const_iterator cbegin() const BOOST_NOEXCEPT { return ptr_; }
|
||||
BOOST_CONSTEXPR const_iterator end() const BOOST_NOEXCEPT { return ptr_ + len_; }
|
||||
BOOST_CONSTEXPR const_iterator cend() const BOOST_NOEXCEPT { return ptr_ + len_; }
|
||||
const_reverse_iterator rbegin() const BOOST_NOEXCEPT { return const_reverse_iterator(end()); }
|
||||
const_reverse_iterator crbegin() const BOOST_NOEXCEPT { return const_reverse_iterator(end()); }
|
||||
const_reverse_iterator rend() const BOOST_NOEXCEPT { return const_reverse_iterator(begin()); }
|
||||
const_reverse_iterator crend() const BOOST_NOEXCEPT { return const_reverse_iterator(begin()); }
|
||||
|
||||
// capacity
|
||||
BOOST_CONSTEXPR size_type size() const BOOST_NOEXCEPT { return len_; }
|
||||
BOOST_CONSTEXPR size_type length() const BOOST_NOEXCEPT { return len_; }
|
||||
BOOST_CONSTEXPR size_type max_size() const BOOST_NOEXCEPT { return ~static_cast<size_type>(0) / (sizeof(value_type) * 2u); }
|
||||
BOOST_CONSTEXPR bool empty() const BOOST_NOEXCEPT { return len_ == 0; }
|
||||
|
||||
// element access
|
||||
BOOST_CONSTEXPR const_reference operator[](size_type pos) const BOOST_NOEXCEPT { return ptr_[pos]; }
|
||||
|
||||
BOOST_CONSTEXPR const_reference at(size_type pos) const {
|
||||
return pos >= len_ ? BOOST_THROW_EXCEPTION(std::out_of_range("boost::string_view::at")), ptr_[0] : ptr_[pos];
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR const_reference front() const { return ptr_[0]; }
|
||||
BOOST_CONSTEXPR const_reference back() const { return ptr_[len_-1]; }
|
||||
BOOST_CONSTEXPR const_pointer data() const BOOST_NOEXCEPT { return ptr_; }
|
||||
|
||||
// modifiers
|
||||
void clear() BOOST_NOEXCEPT { len_ = 0; } // Boost extension
|
||||
|
||||
BOOST_CXX14_CONSTEXPR void remove_prefix(size_type n) {
|
||||
if ( n > len_ )
|
||||
n = len_;
|
||||
ptr_ += n;
|
||||
len_ -= n;
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR void remove_suffix(size_type n) {
|
||||
if ( n > len_ )
|
||||
n = len_;
|
||||
len_ -= n;
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR void swap(basic_string_view& s) BOOST_NOEXCEPT {
|
||||
std::swap(ptr_, s.ptr_);
|
||||
std::swap(len_, s.len_);
|
||||
}
|
||||
|
||||
// basic_string_view string operations
|
||||
#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
|
||||
template<typename Allocator>
|
||||
explicit operator std::basic_string<charT, traits, Allocator>() const {
|
||||
return std::basic_string<charT, traits, Allocator>(begin(), end());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS
|
||||
template<typename Allocator = std::allocator<charT> >
|
||||
std::basic_string<charT, traits, Allocator> to_string(const Allocator& a = Allocator()) const {
|
||||
return std::basic_string<charT, traits, Allocator>(begin(), end(), a);
|
||||
}
|
||||
#else
|
||||
std::basic_string<charT, traits> to_string() const {
|
||||
return std::basic_string<charT, traits>(begin(), end());
|
||||
}
|
||||
|
||||
template<typename Allocator>
|
||||
std::basic_string<charT, traits, Allocator> to_string(const Allocator& a) const {
|
||||
return std::basic_string<charT, traits, Allocator>(begin(), end(), a);
|
||||
}
|
||||
#endif
|
||||
|
||||
size_type copy(charT* s, size_type n, size_type pos=0) const {
|
||||
if (pos > size())
|
||||
BOOST_THROW_EXCEPTION(std::out_of_range("string_view::copy" ));
|
||||
size_type rlen = (std::min)(n, len_ - pos);
|
||||
traits_type::copy(s, data() + pos, rlen);
|
||||
return rlen;
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR basic_string_view substr() const {
|
||||
return basic_string_view(data(), size());
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR basic_string_view substr(size_type pos, size_type n=npos) const {
|
||||
if ( pos > size())
|
||||
BOOST_THROW_EXCEPTION( std::out_of_range ( "string_view::substr" ) );
|
||||
return basic_string_view(data() + pos, (std::min)(size() - pos, n));
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR int compare(basic_string_view x) const BOOST_NOEXCEPT {
|
||||
const int cmp = traits::compare(ptr_, x.ptr_, (std::min)(len_, x.len_));
|
||||
return cmp != 0 ? cmp : (len_ == x.len_ ? 0 : len_ < x.len_ ? -1 : 1);
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR int compare(size_type pos1, size_type n1, basic_string_view x)
|
||||
const {
|
||||
return substr(pos1, n1).compare(x);
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR int compare(size_type pos1, size_type n1,
|
||||
basic_string_view x, size_type pos2, size_type n2) const {
|
||||
return substr(pos1, n1).compare(x.substr(pos2, n2));
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR int compare(const charT* x) const {
|
||||
return compare(basic_string_view(x));
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR int compare(size_type pos1, size_type n1, const charT* x) const {
|
||||
return substr(pos1, n1).compare(basic_string_view(x));
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR int compare(size_type pos1, size_type n1,
|
||||
const charT* x, size_type n2) const {
|
||||
return substr(pos1, n1).compare(basic_string_view(x, n2));
|
||||
}
|
||||
|
||||
// Searches
|
||||
BOOST_CONSTEXPR bool starts_with(charT c) const BOOST_NOEXCEPT { // Boost extension
|
||||
return !empty() && traits::eq(c, front());
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR bool starts_with(basic_string_view x) const BOOST_NOEXCEPT { // Boost extension
|
||||
return len_ >= x.len_ && traits::compare(ptr_, x.ptr_, x.len_) == 0;
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR bool ends_with(charT c) const BOOST_NOEXCEPT { // Boost extension
|
||||
return !empty() && traits::eq(c, back());
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR bool ends_with(basic_string_view x) const BOOST_NOEXCEPT { // Boost extension
|
||||
return len_ >= x.len_ &&
|
||||
traits::compare(ptr_ + len_ - x.len_, x.ptr_, x.len_) == 0;
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR bool contains(basic_string_view s) const BOOST_NOEXCEPT {
|
||||
return find(s) != npos;
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR bool contains(charT c) const BOOST_NOEXCEPT {
|
||||
return find(c) != npos;
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR bool contains(const charT* s) const BOOST_NOEXCEPT {
|
||||
return find(s) != npos;
|
||||
}
|
||||
|
||||
// find
|
||||
BOOST_CXX14_CONSTEXPR size_type find(basic_string_view s, size_type pos = 0) const BOOST_NOEXCEPT {
|
||||
if (pos > size())
|
||||
return npos;
|
||||
if (s.empty())
|
||||
return pos;
|
||||
if (s.size() > size() - pos)
|
||||
return npos;
|
||||
const charT* cur = ptr_ + pos;
|
||||
const charT* last = cend() - s.size() + 1;
|
||||
for (; cur != last ; ++cur) {
|
||||
cur = traits::find(cur, last - cur, s[0]);
|
||||
if (!cur)
|
||||
return npos;
|
||||
if (traits::compare(cur, s.cbegin(), s.size()) == 0)
|
||||
return cur - ptr_;
|
||||
}
|
||||
return npos;
|
||||
}
|
||||
BOOST_CXX14_CONSTEXPR size_type find(charT c, size_type pos = 0) const BOOST_NOEXCEPT {
|
||||
if (pos > size())
|
||||
return npos;
|
||||
const charT* ret_ptr = traits::find(ptr_ + pos, len_ - pos, c);
|
||||
if (ret_ptr)
|
||||
return ret_ptr - ptr_;
|
||||
return npos;
|
||||
}
|
||||
BOOST_CXX14_CONSTEXPR size_type find(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT
|
||||
{ return find(basic_string_view(s, n), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find(const charT* s, size_type pos = 0) const BOOST_NOEXCEPT
|
||||
{ return find(basic_string_view(s), pos); }
|
||||
|
||||
// rfind
|
||||
BOOST_CXX14_CONSTEXPR size_type rfind(basic_string_view s, size_type pos = npos) const BOOST_NOEXCEPT {
|
||||
if (len_ < s.len_)
|
||||
return npos;
|
||||
if (pos > len_ - s.len_)
|
||||
pos = len_ - s.len_;
|
||||
if (s.len_ == 0u) // an empty string is always found
|
||||
return pos;
|
||||
for (const charT* cur = ptr_ + pos; ; --cur) {
|
||||
if (traits::compare(cur, s.ptr_, s.len_) == 0)
|
||||
return cur - ptr_;
|
||||
if (cur == ptr_)
|
||||
return npos;
|
||||
};
|
||||
}
|
||||
BOOST_CXX14_CONSTEXPR size_type rfind(charT c, size_type pos = npos) const BOOST_NOEXCEPT
|
||||
{ return rfind(basic_string_view(&c, 1), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type rfind(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT
|
||||
{ return rfind(basic_string_view(s, n), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type rfind(const charT* s, size_type pos = npos) const BOOST_NOEXCEPT
|
||||
{ return rfind(basic_string_view(s), pos); }
|
||||
|
||||
// find_first_of
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_of(basic_string_view s, size_type pos = 0) const BOOST_NOEXCEPT {
|
||||
if (pos >= len_ || s.len_ == 0)
|
||||
return npos;
|
||||
const_iterator iter = std::find_first_of
|
||||
(this->cbegin () + pos, this->cend (), s.cbegin (), s.cend (), traits::eq);
|
||||
return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
|
||||
}
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_of(charT c, size_type pos = 0) const BOOST_NOEXCEPT
|
||||
{ return find(c, pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_of(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT
|
||||
{ return find_first_of(basic_string_view(s, n), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_of(const charT* s, size_type pos = 0) const BOOST_NOEXCEPT
|
||||
{ return find_first_of(basic_string_view(s), pos); }
|
||||
|
||||
// find_last_of
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_of(basic_string_view s, size_type pos = npos) const BOOST_NOEXCEPT {
|
||||
if (s.len_ == 0u)
|
||||
return npos;
|
||||
if (pos >= len_)
|
||||
pos = 0;
|
||||
else
|
||||
pos = len_ - (pos+1);
|
||||
const_reverse_iterator iter = std::find_first_of
|
||||
( this->crbegin () + pos, this->crend (), s.cbegin (), s.cend (), traits::eq );
|
||||
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter);
|
||||
}
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_of(charT c, size_type pos = npos) const BOOST_NOEXCEPT
|
||||
{ return find_last_of(basic_string_view(&c, 1), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_of(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT
|
||||
{ return find_last_of(basic_string_view(s, n), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_of(const charT* s, size_type pos = npos) const BOOST_NOEXCEPT
|
||||
{ return find_last_of(basic_string_view(s), pos); }
|
||||
|
||||
// find_first_not_of
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_not_of(basic_string_view s, size_type pos = 0) const BOOST_NOEXCEPT {
|
||||
if (pos >= len_)
|
||||
return npos;
|
||||
if (s.len_ == 0)
|
||||
return pos;
|
||||
const_iterator iter = find_not_of ( this->cbegin () + pos, this->cend (), s );
|
||||
return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
|
||||
}
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_not_of(charT c, size_type pos = 0) const BOOST_NOEXCEPT
|
||||
{ return find_first_not_of(basic_string_view(&c, 1), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_not_of(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT
|
||||
{ return find_first_not_of(basic_string_view(s, n), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_not_of(const charT* s, size_type pos = 0) const BOOST_NOEXCEPT
|
||||
{ return find_first_not_of(basic_string_view(s), pos); }
|
||||
|
||||
// find_last_not_of
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_not_of(basic_string_view s, size_type pos = npos) const BOOST_NOEXCEPT {
|
||||
if (pos >= len_)
|
||||
pos = len_ - 1;
|
||||
if (s.len_ == 0u)
|
||||
return pos;
|
||||
pos = len_ - (pos+1);
|
||||
const_reverse_iterator iter = find_not_of ( this->crbegin () + pos, this->crend (), s );
|
||||
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter );
|
||||
}
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_not_of(charT c, size_type pos = npos) const BOOST_NOEXCEPT
|
||||
{ return find_last_not_of(basic_string_view(&c, 1), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_not_of(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT
|
||||
{ return find_last_not_of(basic_string_view(s, n), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_not_of(const charT* s, size_type pos = npos) const BOOST_NOEXCEPT
|
||||
{ return find_last_not_of(basic_string_view(s), pos); }
|
||||
|
||||
private:
|
||||
template <typename r_iter>
|
||||
size_type reverse_distance(r_iter first, r_iter last) const BOOST_NOEXCEPT {
|
||||
// Portability note here: std::distance is not NOEXCEPT, but calling it with a string_view::reverse_iterator will not throw.
|
||||
return len_ - 1 - std::distance ( first, last );
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
Iterator find_not_of(Iterator first, Iterator last, basic_string_view s) const BOOST_NOEXCEPT {
|
||||
for (; first != last ; ++first)
|
||||
if ( 0 == traits::find(s.ptr_, s.len_, *first))
|
||||
return first;
|
||||
return last;
|
||||
}
|
||||
|
||||
const charT *ptr_;
|
||||
std::size_t len_;
|
||||
};
|
||||
|
||||
|
||||
// Comparison operators
|
||||
// Equality
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator==(basic_string_view<charT, traits> x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
if (x.size () != y.size ()) return false;
|
||||
return x.compare(y) == 0;
|
||||
}
|
||||
|
||||
// Inequality
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator!=(basic_string_view<charT, traits> x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
if ( x.size () != y.size ()) return true;
|
||||
return x.compare(y) != 0;
|
||||
}
|
||||
|
||||
// Less than
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator<(basic_string_view<charT, traits> x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return x.compare(y) < 0;
|
||||
}
|
||||
|
||||
// Greater than
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator>(basic_string_view<charT, traits> x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return x.compare(y) > 0;
|
||||
}
|
||||
|
||||
// Less than or equal to
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator<=(basic_string_view<charT, traits> x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return x.compare(y) <= 0;
|
||||
}
|
||||
|
||||
// Greater than or equal to
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator>=(basic_string_view<charT, traits> x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return x.compare(y) >= 0;
|
||||
}
|
||||
|
||||
// "sufficient additional overloads of comparison functions"
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator==(basic_string_view<charT, traits> x,
|
||||
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
|
||||
return x == basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator==(const std::basic_string<charT, traits, Allocator> & x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) == y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator==(basic_string_view<charT, traits> x,
|
||||
const charT * y) BOOST_NOEXCEPT {
|
||||
return x == basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator==(const charT * x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) == y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator!=(basic_string_view<charT, traits> x,
|
||||
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
|
||||
return x != basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator!=(const std::basic_string<charT, traits, Allocator> & x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) != y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator!=(basic_string_view<charT, traits> x,
|
||||
const charT * y) BOOST_NOEXCEPT {
|
||||
return x != basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator!=(const charT * x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) != y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator<(basic_string_view<charT, traits> x,
|
||||
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
|
||||
return x < basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator<(const std::basic_string<charT, traits, Allocator> & x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) < y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator<(basic_string_view<charT, traits> x,
|
||||
const charT * y) BOOST_NOEXCEPT {
|
||||
return x < basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator<(const charT * x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) < y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator>(basic_string_view<charT, traits> x,
|
||||
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
|
||||
return x > basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator>(const std::basic_string<charT, traits, Allocator> & x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) > y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator>(basic_string_view<charT, traits> x,
|
||||
const charT * y) BOOST_NOEXCEPT {
|
||||
return x > basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator>(const charT * x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) > y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator<=(basic_string_view<charT, traits> x,
|
||||
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
|
||||
return x <= basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator<=(const std::basic_string<charT, traits, Allocator> & x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) <= y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator<=(basic_string_view<charT, traits> x,
|
||||
const charT * y) BOOST_NOEXCEPT {
|
||||
return x <= basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator<=(const charT * x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) <= y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator>=(basic_string_view<charT, traits> x,
|
||||
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
|
||||
return x >= basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator>=(const std::basic_string<charT, traits, Allocator> & x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) >= y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator>=(basic_string_view<charT, traits> x,
|
||||
const charT * y) BOOST_NOEXCEPT {
|
||||
return x >= basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator>=(const charT * x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) >= y;
|
||||
}
|
||||
|
||||
// Inserter
|
||||
template<class charT, class traits>
|
||||
inline std::basic_ostream<charT, traits>&
|
||||
operator<<(std::basic_ostream<charT, traits>& os,
|
||||
const basic_string_view<charT,traits>& str) {
|
||||
return boost::io::ostream_put(os, str.data(), str.size());
|
||||
}
|
||||
|
||||
#if 0
|
||||
// numeric conversions
|
||||
//
|
||||
// These are short-term implementations.
|
||||
// In a production environment, I would rather avoid the copying.
|
||||
//
|
||||
inline int stoi (string_view str, size_t* idx=0, int base=10) {
|
||||
return std::stoi ( std::string(str), idx, base );
|
||||
}
|
||||
|
||||
inline long stol (string_view str, size_t* idx=0, int base=10) {
|
||||
return std::stol ( std::string(str), idx, base );
|
||||
}
|
||||
|
||||
inline unsigned long stoul (string_view str, size_t* idx=0, int base=10) {
|
||||
return std::stoul ( std::string(str), idx, base );
|
||||
}
|
||||
|
||||
inline long long stoll (string_view str, size_t* idx=0, int base=10) {
|
||||
return std::stoll ( std::string(str), idx, base );
|
||||
}
|
||||
|
||||
inline unsigned long long stoull (string_view str, size_t* idx=0, int base=10) {
|
||||
return std::stoull ( std::string(str), idx, base );
|
||||
}
|
||||
|
||||
inline float stof (string_view str, size_t* idx=0) {
|
||||
return std::stof ( std::string(str), idx );
|
||||
}
|
||||
|
||||
inline double stod (string_view str, size_t* idx=0) {
|
||||
return std::stod ( std::string(str), idx );
|
||||
}
|
||||
|
||||
inline long double stold (string_view str, size_t* idx=0) {
|
||||
return std::stold ( std::string(str), idx );
|
||||
}
|
||||
|
||||
inline int stoi (wstring_view str, size_t* idx=0, int base=10) {
|
||||
return std::stoi ( std::wstring(str), idx, base );
|
||||
}
|
||||
|
||||
inline long stol (wstring_view str, size_t* idx=0, int base=10) {
|
||||
return std::stol ( std::wstring(str), idx, base );
|
||||
}
|
||||
|
||||
inline unsigned long stoul (wstring_view str, size_t* idx=0, int base=10) {
|
||||
return std::stoul ( std::wstring(str), idx, base );
|
||||
}
|
||||
|
||||
inline long long stoll (wstring_view str, size_t* idx=0, int base=10) {
|
||||
return std::stoll ( std::wstring(str), idx, base );
|
||||
}
|
||||
|
||||
inline unsigned long long stoull (wstring_view str, size_t* idx=0, int base=10) {
|
||||
return std::stoull ( std::wstring(str), idx, base );
|
||||
}
|
||||
|
||||
inline float stof (wstring_view str, size_t* idx=0) {
|
||||
return std::stof ( std::wstring(str), idx );
|
||||
}
|
||||
|
||||
inline double stod (wstring_view str, size_t* idx=0) {
|
||||
return std::stod ( std::wstring(str), idx );
|
||||
}
|
||||
|
||||
inline long double stold (wstring_view str, size_t* idx=0) {
|
||||
return std::stold ( std::wstring(str), idx );
|
||||
}
|
||||
#endif
|
||||
|
||||
// Forward declaration of Boost.ContainerHash function
|
||||
template <class It> std::size_t hash_range(It, It);
|
||||
|
||||
template <class charT, class traits>
|
||||
std::size_t hash_value(basic_string_view<charT, traits> s) {
|
||||
return boost::hash_range(s.begin(), s.end());
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
namespace std {
|
||||
// Hashing
|
||||
template<> struct hash<boost::string_view>;
|
||||
template<> struct hash<boost::u16string_view>;
|
||||
template<> struct hash<boost::u32string_view>;
|
||||
template<> struct hash<boost::wstring_view>;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
39
include/boost/utility/string_view_fwd.hpp
Normal file
39
include/boost/utility/string_view_fwd.hpp
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2012-2012.
|
||||
|
||||
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)
|
||||
|
||||
For more information, see http://www.boost.org
|
||||
|
||||
Based on the StringRef implementation in LLVM (http://llvm.org) and
|
||||
N3422 by Jeffrey Yasskin
|
||||
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html
|
||||
Updated July 2015 to reflect the Library Fundamentals TS
|
||||
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html
|
||||
|
||||
*/
|
||||
|
||||
#ifndef BOOST_STRING_VIEW_FWD_HPP
|
||||
#define BOOST_STRING_VIEW_FWD_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template<typename charT, typename traits = std::char_traits<charT> > class basic_string_view;
|
||||
typedef basic_string_view<char, std::char_traits<char> > string_view;
|
||||
typedef basic_string_view<wchar_t, std::char_traits<wchar_t> > wstring_view;
|
||||
|
||||
#ifndef BOOST_NO_CXX11_CHAR16_T
|
||||
typedef basic_string_view<char16_t, std::char_traits<char16_t> > u16string_view;
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_CXX11_CHAR32_T
|
||||
typedef basic_string_view<char32_t, std::char_traits<char32_t> > u32string_view;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
82
include/boost/utility/typed_in_place_factory.hpp
Normal file
82
include/boost/utility/typed_in_place_factory.hpp
Normal file
@ -0,0 +1,82 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
// Copyright (C) 2007, Tobias Schwinger.
|
||||
//
|
||||
// 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_UTILITY_TYPED_INPLACE_FACTORY_04APR2007_HPP
|
||||
#ifndef BOOST_PP_IS_ITERATING
|
||||
|
||||
#include <boost/utility/detail/in_place_factory_prefix.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
class typed_in_place_factory_base {} ;
|
||||
|
||||
#ifndef BOOST_UTILITY_DOCS
|
||||
#define BOOST_PP_ITERATION_LIMITS (0, BOOST_MAX_INPLACE_FACTORY_ARITY)
|
||||
#define BOOST_PP_FILENAME_1 <boost/utility/typed_in_place_factory.hpp>
|
||||
#endif // BOOST_UTILITY_DOCS
|
||||
|
||||
#include BOOST_PP_ITERATE()
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/utility/detail/in_place_factory_suffix.hpp>
|
||||
|
||||
#ifndef BOOST_UTILITY_DOCS
|
||||
#define BOOST_UTILITY_TYPED_INPLACE_FACTORY_04APR2007_HPP
|
||||
#endif // BOOST_UTILITY_DOCS
|
||||
|
||||
#else
|
||||
#define N BOOST_PP_ITERATION()
|
||||
|
||||
template< class T BOOST_PP_ENUM_TRAILING_PARAMS(N,class A) >
|
||||
class BOOST_PP_CAT(typed_in_place_factory,N)
|
||||
:
|
||||
public typed_in_place_factory_base
|
||||
{
|
||||
public:
|
||||
|
||||
typedef T value_type;
|
||||
|
||||
explicit BOOST_PP_CAT(typed_in_place_factory,N)
|
||||
( BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& a) )
|
||||
#if N > 0
|
||||
: BOOST_PP_ENUM(N, BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_INIT, _)
|
||||
#endif
|
||||
{}
|
||||
|
||||
void* apply (void* address) const
|
||||
{
|
||||
return new(address) T( BOOST_PP_ENUM_PARAMS(N, m_a) );
|
||||
}
|
||||
|
||||
void* apply (void* address, std::size_t n) const
|
||||
{
|
||||
for(void* next = address = this->apply(address); !! --n;)
|
||||
this->apply(next = static_cast<char *>(next) + sizeof(T));
|
||||
return address;
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT(N, BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_DECL, _)
|
||||
};
|
||||
|
||||
template< class T BOOST_PP_ENUM_TRAILING_PARAMS(N, class A) >
|
||||
inline BOOST_PP_CAT(typed_in_place_factory,N)<
|
||||
T BOOST_PP_ENUM_TRAILING_PARAMS(N, A) >
|
||||
in_place( BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& a) )
|
||||
{
|
||||
return BOOST_PP_CAT(typed_in_place_factory,N)<
|
||||
T BOOST_PP_ENUM_TRAILING_PARAMS(N, A) >( BOOST_PP_ENUM_PARAMS(N, a) );
|
||||
}
|
||||
|
||||
#undef N
|
||||
#endif
|
||||
#endif
|
||||
|
247
include/boost/utility/value_init.hpp
Normal file
247
include/boost/utility/value_init.hpp
Normal file
@ -0,0 +1,247 @@
|
||||
// (C) Copyright 2002-2008, Fernando Luis Cacciola Carballal.
|
||||
// Copyright 2020 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)
|
||||
//
|
||||
// 21 Ago 2002 (Created) Fernando Cacciola
|
||||
// 24 Dec 2007 (Refactored and worked around various compiler bugs) Fernando Cacciola, Niels Dekker
|
||||
// 23 May 2008 (Fixed operator= const issue, added initialized_value) Niels Dekker, Fernando Cacciola
|
||||
// 21 Ago 2008 (Added swap) Niels Dekker, Fernando Cacciola
|
||||
// 20 Feb 2009 (Fixed logical const-ness issues) Niels Dekker, Fernando Cacciola
|
||||
// 03 Apr 2010 (Added initialized<T>, suggested by Jeffrey Hellrung, fixing #3472) Niels Dekker
|
||||
// 30 May 2010 (Made memset call conditional, fixing #3869) Niels Dekker
|
||||
//
|
||||
#ifndef BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP
|
||||
#define BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP
|
||||
|
||||
// Note: The implementation of boost::value_initialized had to deal with the
|
||||
// fact that various compilers haven't fully implemented value-initialization.
|
||||
// The constructor of boost::value_initialized<T> works around these compiler
|
||||
// issues, by clearing the bytes of T, before constructing the T object it
|
||||
// contains. More details on these issues are at libs/utility/value_init.htm
|
||||
|
||||
#include <boost/config.hpp> // For BOOST_NO_COMPLETE_VALUE_INITIALIZATION.
|
||||
#include <boost/core/swap.hpp>
|
||||
#include <cstring>
|
||||
#include <cstddef>
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push)
|
||||
// It is safe to ignore the following warning from MSVC 7.1 or higher:
|
||||
// "warning C4351: new behavior: elements of array will be default initialized"
|
||||
#pragma warning(disable: 4351)
|
||||
// It is safe to ignore the following MSVC warning, which may pop up when T is
|
||||
// a const type: "warning C4512: assignment operator could not be generated".
|
||||
#pragma warning(disable: 4512)
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_UTILITY_DOCS
|
||||
|
||||
#ifdef BOOST_NO_COMPLETE_VALUE_INITIALIZATION
|
||||
// Implementation detail: The macro BOOST_DETAIL_VALUE_INIT_WORKAROUND_SUGGESTED
|
||||
// suggests that a workaround should be applied, because of compiler issues
|
||||
// regarding value-initialization.
|
||||
#define BOOST_DETAIL_VALUE_INIT_WORKAROUND_SUGGESTED
|
||||
#endif
|
||||
|
||||
// Implementation detail: The macro BOOST_DETAIL_VALUE_INIT_WORKAROUND
|
||||
// switches the value-initialization workaround either on or off.
|
||||
#ifndef BOOST_DETAIL_VALUE_INIT_WORKAROUND
|
||||
#ifdef BOOST_DETAIL_VALUE_INIT_WORKAROUND_SUGGESTED
|
||||
#define BOOST_DETAIL_VALUE_INIT_WORKAROUND 1
|
||||
#else
|
||||
#define BOOST_DETAIL_VALUE_INIT_WORKAROUND 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // BOOST_UTILITY_DOCS
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
|
||||
struct zero_init
|
||||
{
|
||||
zero_init()
|
||||
{
|
||||
}
|
||||
|
||||
zero_init( void * p, std::size_t n )
|
||||
{
|
||||
std::memset( p, 0, n );
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<class T>
|
||||
class initialized
|
||||
#if BOOST_DETAIL_VALUE_INIT_WORKAROUND
|
||||
: detail::zero_init
|
||||
#endif
|
||||
{
|
||||
private:
|
||||
|
||||
T data_;
|
||||
|
||||
public :
|
||||
|
||||
BOOST_GPU_ENABLED
|
||||
initialized():
|
||||
#if BOOST_DETAIL_VALUE_INIT_WORKAROUND
|
||||
zero_init( &const_cast< char& >( reinterpret_cast<char const volatile&>( data_ ) ), sizeof( data_ ) ),
|
||||
#endif
|
||||
data_()
|
||||
{
|
||||
}
|
||||
|
||||
BOOST_GPU_ENABLED
|
||||
explicit initialized(T const & arg): data_( arg )
|
||||
{
|
||||
}
|
||||
|
||||
BOOST_GPU_ENABLED
|
||||
T const & data() const
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
BOOST_GPU_ENABLED
|
||||
T& data()
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
BOOST_GPU_ENABLED
|
||||
void swap(initialized & arg)
|
||||
{
|
||||
::boost::swap( this->data(), arg.data() );
|
||||
}
|
||||
|
||||
BOOST_GPU_ENABLED
|
||||
operator T const &() const
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
BOOST_GPU_ENABLED
|
||||
operator T&()
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
} ;
|
||||
|
||||
template<class T>
|
||||
BOOST_GPU_ENABLED
|
||||
T const& get ( initialized<T> const& x )
|
||||
{
|
||||
return x.data() ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
BOOST_GPU_ENABLED
|
||||
T& get ( initialized<T>& x )
|
||||
{
|
||||
return x.data() ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
BOOST_GPU_ENABLED
|
||||
void swap ( initialized<T> & lhs, initialized<T> & rhs )
|
||||
{
|
||||
lhs.swap(rhs) ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
class value_initialized
|
||||
{
|
||||
private :
|
||||
|
||||
// initialized<T> does value-initialization by default.
|
||||
initialized<T> m_data;
|
||||
|
||||
public :
|
||||
|
||||
BOOST_GPU_ENABLED
|
||||
value_initialized()
|
||||
:
|
||||
m_data()
|
||||
{ }
|
||||
|
||||
BOOST_GPU_ENABLED
|
||||
T const & data() const
|
||||
{
|
||||
return m_data.data();
|
||||
}
|
||||
|
||||
BOOST_GPU_ENABLED
|
||||
T& data()
|
||||
{
|
||||
return m_data.data();
|
||||
}
|
||||
|
||||
BOOST_GPU_ENABLED
|
||||
void swap(value_initialized & arg)
|
||||
{
|
||||
m_data.swap(arg.m_data);
|
||||
}
|
||||
|
||||
BOOST_GPU_ENABLED
|
||||
operator T const &() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
BOOST_GPU_ENABLED
|
||||
operator T&()
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
template<class T>
|
||||
BOOST_GPU_ENABLED
|
||||
T const& get ( value_initialized<T> const& x )
|
||||
{
|
||||
return x.data() ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
BOOST_GPU_ENABLED
|
||||
T& get ( value_initialized<T>& x )
|
||||
{
|
||||
return x.data() ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
BOOST_GPU_ENABLED
|
||||
void swap ( value_initialized<T> & lhs, value_initialized<T> & rhs )
|
||||
{
|
||||
lhs.swap(rhs) ;
|
||||
}
|
||||
|
||||
|
||||
class initialized_value_t
|
||||
{
|
||||
public :
|
||||
|
||||
template <class T> BOOST_GPU_ENABLED operator T() const
|
||||
{
|
||||
return initialized<T>().data();
|
||||
}
|
||||
};
|
||||
|
||||
initialized_value_t const initialized_value = {} ;
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
19
index.html
Normal file
19
index.html
Normal file
@ -0,0 +1,19 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Boost.Utility</title>
|
||||
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="./doc/html/index.html">./doc/html/index.html</a>
|
||||
<hr>
|
||||
<tt>
|
||||
Boost.Utility<br>
|
||||
<br>
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||
<br>
|
||||
</tt>
|
||||
</body>
|
||||
</html>
|
@ -1,443 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta name="generator" content="HTML Tidy, see www.w3.org">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
|
||||
<title>Indirect Iterator Adaptor Documentation</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
|
||||
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align=
|
||||
"center" width="277" height="86">
|
||||
|
||||
<h1>Indirect Iterator Adaptor</h1>
|
||||
Defined in header <a href=
|
||||
"../../boost/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a>
|
||||
|
||||
<p>The indirect iterator adaptor augments an iterator by applying an
|
||||
<b>extra</b> dereference inside of <tt>operator*()</tt>. For example, this
|
||||
iterator makes it possible to view a container of pointers or
|
||||
smart-pointers (e.g. <tt>std::list<boost::shared_ptr<foo>
|
||||
></tt>) as if it were a container of the pointed-to type. The following
|
||||
<b>pseudo-code</b> shows the basic idea of the indirect iterator:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
// inside a hypothetical indirect_iterator class...
|
||||
typedef std::iterator_traits<BaseIterator>::value_type Pointer;
|
||||
typedef std::iterator_traits<Pointer>::reference reference;
|
||||
|
||||
reference indirect_iterator::operator*() const {
|
||||
return **this->base_iterator;
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<h2>Synopsis</h2>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
namespace boost {
|
||||
template <class BaseIterator,
|
||||
class Value, class Reference, class Category, class Pointer>
|
||||
struct indirect_iterator_generator;
|
||||
|
||||
template <class BaseIterator,
|
||||
class Value, class Reference, class ConstReference,
|
||||
class Category, class Pointer, class ConstPointer>
|
||||
struct indirect_iterator_pair_generator;
|
||||
|
||||
template <class BaseIterator>
|
||||
typename indirect_iterator_generator<BaseIterator>::type
|
||||
make_indirect_iterator(BaseIterator base)
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
<hr>
|
||||
|
||||
<h2><a name="indirect_iterator_generator">The Indirect Iterator Type
|
||||
Generator</a></h2>
|
||||
The <tt>indirect_iterator_generator</tt> template is a <a href=
|
||||
"../../more/generic_programming.html#type_generator">generator</a> of
|
||||
indirect iterator types. The main template parameter for this class is the
|
||||
<tt>BaseIterator</tt> type that is being wrapped. In most cases the type of
|
||||
the elements being pointed to can be deduced using
|
||||
<tt>std::iterator_traits</tt>, but in some situations the user may want to
|
||||
override this type, so there are also template parameters that allow a user
|
||||
to control the <tt>value_type</tt>, <tt>pointer</tt>, and
|
||||
<tt>reference</tt> types of the resulting iterators.
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
template <class BaseIterator,
|
||||
class Value, class Reference, class Pointer>
|
||||
class indirect_iterator_generator
|
||||
{
|
||||
public:
|
||||
typedef <tt><a href=
|
||||
"./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a><...></tt> type; // the resulting indirect iterator type
|
||||
};
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<h3>Example</h3>
|
||||
This example uses the <tt>indirect_iterator_generator</tt> to create
|
||||
indirect iterators which dereference the pointers stored in the
|
||||
<tt>pointers_to_chars</tt> array to access the <tt>char</tt>s in the
|
||||
<tt>characters</tt> array.
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
#include <boost/config.hpp>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <boost/iterator_adaptors.hpp>
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
char characters[] = "abcdefg";
|
||||
const int N = sizeof(characters)/sizeof(char) - 1; // -1 since characters has a null char
|
||||
char* pointers_to_chars[N]; // at the end.
|
||||
for (int i = 0; i < N; ++i)
|
||||
pointers_to_chars[i] = &characters[i];
|
||||
|
||||
boost::indirect_iterator_generator<char**, char>::type
|
||||
indirect_first(pointers_to_chars), indirect_last(pointers_to_chars + N);
|
||||
|
||||
std::copy(indirect_first, indirect_last, std::ostream_iterator<char>(std::cout, ","));
|
||||
std::cout << std::endl;
|
||||
|
||||
// to be continued...
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<h3>Template Parameters</h3>
|
||||
|
||||
<table border>
|
||||
<tr>
|
||||
<th>Parameter
|
||||
|
||||
<th>Description
|
||||
|
||||
<tr>
|
||||
<td><tt>BaseIterator</tt>
|
||||
|
||||
<td>The iterator type being wrapped. The <tt>value_type</tt>
|
||||
of the base iterator should itself be dereferenceable.
|
||||
The return type of the <tt>operator*</tt> for the
|
||||
<tt>value_type</tt> should match the <tt>Reference</tt> type.
|
||||
|
||||
<tr>
|
||||
<td><tt>Value</tt>
|
||||
|
||||
<td>The <tt>value_type</tt> of the resulting iterator, unless const. If
|
||||
Value is <tt>const X</tt>, a conforming compiler makes the
|
||||
<tt>value_type</tt> <tt><i>non-</i>const X</tt><a href=
|
||||
"iterator_adaptors.htm#1">[1]</a>. Note that if the default
|
||||
is used for <tt>Value</tt>, then there must be a valid specialization
|
||||
of <tt>iterator_traits</tt> for the value type of the base iterator.
|
||||
<br>
|
||||
<b>Default:</b> <tt>std::iterator_traits<<br>
|
||||
<20> std::iterator_traits<BaseIterator>::value_type
|
||||
>::value_type</tt><a href="#2">[2]</a>
|
||||
|
||||
<tr>
|
||||
<td><tt>Reference</tt>
|
||||
|
||||
<td>The <tt>reference</tt> type of the resulting iterator, and in
|
||||
particular, the result type of <tt>operator*()</tt>.<br>
|
||||
<b>Default:</b> <tt>Value&</tt>
|
||||
|
||||
<tr>
|
||||
<td><tt>Pointer</tt>
|
||||
|
||||
<td>The <tt>pointer</tt> type of the resulting iterator, and in
|
||||
particular, the result type of <tt>operator->()</tt>.<br>
|
||||
<b>Default:</b> <tt>Value*</tt>
|
||||
|
||||
<tr>
|
||||
<td><tt>Category</tt>
|
||||
<td>The <tt>iterator_category</tt> type for the resulting iterator.<br>
|
||||
<b>Default:</b>
|
||||
<tt>std::iterator_traits<BaseIterator>::iterator_category</tt>
|
||||
|
||||
</table>
|
||||
|
||||
<h3>Concept Model</h3>
|
||||
The indirect iterator will model whichever <a href=
|
||||
"http://www.sgi.com/tech/stl/Iterators.html">standard iterator
|
||||
concept category</a> is modeled by the base iterator. Thus, if the
|
||||
base iterator is a model of <a href=
|
||||
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
|
||||
Access Iterator</a> then so is the resulting indirect iterator. If
|
||||
the base iterator models a more restrictive concept, the resulting
|
||||
indirect iterator will model the same concept <a href="#3">[3]</a>.
|
||||
|
||||
<h3>Members</h3>
|
||||
The indirect iterator type implements the member functions and operators
|
||||
required of the <a href=
|
||||
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access
|
||||
Iterator</a> concept. In addition it has the following constructor:
|
||||
<pre>
|
||||
explicit indirect_iterator_generator::type(const BaseIterator& it)
|
||||
</pre>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>
|
||||
|
||||
<h2><a name="indirect_iterator_pair_generator">The Indirect Iterator Pair
|
||||
Generator</a></h2>
|
||||
Sometimes a pair of <tt>const</tt>/non-<tt>const</tt> pair of iterators is
|
||||
needed, such as when implementing a container. The
|
||||
<tt>indirect_iterator_pair_generator</tt> class makes it more convenient to
|
||||
create this pair of iterator types.
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
template <class BaseIterator,
|
||||
class Value, class Pointer, class Reference,
|
||||
class ConstPointer, class ConstReference>
|
||||
class indirect_iterator_pair_generator
|
||||
{
|
||||
public:
|
||||
typedef <tt><a href=
|
||||
"./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a><...></tt> iterator; // the mutable indirect iterator type
|
||||
typedef <tt><a href=
|
||||
"./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a><...></tt> const_iterator; // the immutable indirect iterator type
|
||||
};
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<h3>Example</h3>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
// continuing from the last example...
|
||||
|
||||
typedef boost::indirect_iterator_pair_generator<char**,
|
||||
char, char*, char&, const char*, const char&> PairGen;
|
||||
|
||||
char mutable_characters[N];
|
||||
char* pointers_to_mutable_chars[N];
|
||||
for (int i = 0; i < N; ++i)
|
||||
pointers_to_mutable_chars[i] = &mutable_characters[i];
|
||||
|
||||
PairGen::iterator mutable_indirect_first(pointers_to_mutable_chars),
|
||||
mutable_indirect_last(pointers_to_mutable_chars + N);
|
||||
PairGen::const_iterator const_indirect_first(pointers_to_chars),
|
||||
const_indirect_last(pointers_to_chars + N);
|
||||
|
||||
std::transform(const_indirect_first, const_indirect_last,
|
||||
mutable_indirect_first, std::bind1st(std::plus<char>(), 1));
|
||||
|
||||
std::copy(mutable_indirect_first, mutable_indirect_last,
|
||||
std::ostream_iterator<char>(std::cout, ","));
|
||||
std::cout << std::endl;
|
||||
// to be continued...
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>The output is:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
b,c,d,e,f,g,h,
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<h3>Template Parameters</h3>
|
||||
|
||||
<table border>
|
||||
<tr>
|
||||
<th>Parameter
|
||||
|
||||
<th>Description
|
||||
|
||||
<tr>
|
||||
<td><tt>BaseIterator</tt>
|
||||
|
||||
<td>The iterator type being wrapped. The <tt>value_type</tt> of the
|
||||
base iterator should itself be dereferenceable.
|
||||
The return type of the <tt>operator*</tt> for the
|
||||
<tt>value_type</tt> should match the <tt>Reference</tt> type.
|
||||
|
||||
<tr>
|
||||
<td><tt>Value</tt>
|
||||
|
||||
<td>The <tt>value_type</tt> of the resulting iterators.
|
||||
If Value is <tt>const X</tt>, a conforming compiler makes the
|
||||
<tt>value_type</tt> <tt><i>non-</i>const X</tt><a href=
|
||||
"iterator_adaptors.htm#1">[1]</a>. Note that if the default
|
||||
is used for <tt>Value</tt>, then there must be a valid
|
||||
specialization of <tt>iterator_traits</tt> for the value type
|
||||
of the base iterator.<br>
|
||||
|
||||
<b>Default:</b> <tt>std::iterator_traits<<br>
|
||||
<20> std::iterator_traits<BaseIterator>::value_type
|
||||
>::value_type</tt><a href="#2">[2]</a>
|
||||
|
||||
<tr>
|
||||
<td><tt>Reference</tt>
|
||||
|
||||
<td>The <tt>reference</tt> type of the resulting <tt>iterator</tt>, and
|
||||
in particular, the result type of its <tt>operator*()</tt>.<br>
|
||||
<b>Default:</b> <tt>Value&</tt>
|
||||
|
||||
<tr>
|
||||
<td><tt>Pointer</tt>
|
||||
|
||||
<td>The <tt>pointer</tt> type of the resulting <tt>iterator</tt>, and
|
||||
in particular, the result type of its <tt>operator->()</tt>.<br>
|
||||
<b>Default:</b> <tt>Value*</tt>
|
||||
|
||||
<tr>
|
||||
<td><tt>ConstReference</tt>
|
||||
|
||||
<td>The <tt>reference</tt> type of the resulting
|
||||
<tt>const_iterator</tt>, and in particular, the result type of its
|
||||
<tt>operator*()</tt>.<br>
|
||||
<b>Default:</b> <tt>const Value&</tt>
|
||||
|
||||
<tr>
|
||||
<td><tt>ConstPointer</tt>
|
||||
|
||||
<td>The <tt>pointer</tt> type of the resulting <tt>const_iterator</tt>,
|
||||
and in particular, the result type of its <tt>operator->()</tt>.<br>
|
||||
<b>Default:</b> <tt>const Value*</tt>
|
||||
|
||||
<tr>
|
||||
<td><tt>Category</tt>
|
||||
<td>The <tt>iterator_category</tt> type for the resulting iterator.<br>
|
||||
<b>Default:</b>
|
||||
<tt>std::iterator_traits<BaseIterator>::iterator_category</tt>
|
||||
</table>
|
||||
|
||||
<h3>Concept Model</h3>
|
||||
|
||||
The indirect iterators will model whichever <a href=
|
||||
"http://www.sgi.com/tech/stl/Iterators.html">standard iterator
|
||||
concept category</a> is modeled by the base iterator. Thus, if the
|
||||
base iterator is a model of <a href=
|
||||
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
|
||||
Access Iterator</a> then so are the resulting indirect
|
||||
iterators. If the base iterator models a more restrictive concept,
|
||||
the resulting indirect iterators will model the same concept <a
|
||||
href="#3">[3]</a>.
|
||||
|
||||
|
||||
<h3>Members</h3>
|
||||
The resulting <tt>iterator</tt> and <tt>const_iterator</tt> types implement
|
||||
the member functions and operators required of the <a href=
|
||||
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access
|
||||
Iterator</a> concept. In addition they support the following constructors:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
explicit indirect_iterator_pair_generator::iterator(const BaseIterator& it)
|
||||
explicit indirect_iterator_pair_generator::const_iterator(const BaseIterator& it)
|
||||
</pre>
|
||||
</blockquote>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>
|
||||
|
||||
<h2><a name="make_indirect_iterator">The Indirect Iterator Object
|
||||
Generator</a></h2>
|
||||
The <tt>make_indirect_iterator()</tt> function provides a more convenient
|
||||
way to create indirect iterator objects. The function saves the user the
|
||||
trouble of explicitly writing out the iterator types.
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
template <class BaseIterator>
|
||||
typename indirect_iterator_generator<BaseIterator>::type
|
||||
make_indirect_iterator(BaseIterator base)
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<h3>Example</h3>
|
||||
Here we again print the <tt>char</tt>s from the array <tt>characters</tt>
|
||||
by accessing them through the array of pointers <tt>pointer_to_chars</tt>,
|
||||
but this time we use the <tt>make_indirect_iterator()</tt> function which
|
||||
saves us some typing.
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
// continuing from the last example...
|
||||
|
||||
std::copy(boost::make_indirect_iterator(pointers_to_chars),
|
||||
boost::make_indirect_iterator(pointers_to_chars + N),
|
||||
std::ostream_iterator<char>(std::cout, ","));
|
||||
std::cout << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
The output is:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
a,b,c,d,e,f,g,
|
||||
</pre>
|
||||
</blockquote>
|
||||
<hr>
|
||||
|
||||
<h3>Notes</h3>
|
||||
|
||||
<p>
|
||||
|
||||
<p><a name="2">[2]</a> If your compiler does not support partial
|
||||
specialization and the base iterator or its <tt>value_type</tt> is a
|
||||
builtin pointer type, you will not be able to use the default for
|
||||
<tt>Value</tt> and will need to specify this type explicitly.
|
||||
|
||||
<p><a name="3">[3]</a>There is a caveat to which concept the
|
||||
indirect iterator can model. If the return type of the
|
||||
<tt>operator*</tt> for the base iterator's value type is not a
|
||||
true reference, then strickly speaking, the indirect iterator can
|
||||
not be a model of <a href=
|
||||
"http://www.sgi.com/tech/stl/ForwardIterator.html">Forward
|
||||
Iterator</a> or any of the concepts that refine it. In this case
|
||||
the <tt>Category</tt> for the indirect iterator should be
|
||||
specified as <tt>std::input_iterator_tag</tt>. However, even in
|
||||
this case, if the base iterator is a random access iterator, the
|
||||
resulting indirect iterator will still satisfy most of the
|
||||
requirements for <a href=
|
||||
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
|
||||
Access Iterator</a>.
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->08 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14892" -->
|
||||
|
||||
|
||||
<p>© Copyright Jeremy Siek and David Abrahams 2001. Permission to
|
||||
copy, use, modify, sell and distribute this document is granted provided
|
||||
this copyright notice appears in all copies. This document is provided "as
|
||||
is" without express or implied warranty, and with no claim as to its
|
||||
suitability for any purpose.
|
||||
<!-- LocalWords: html charset alt gif hpp BaseIterator const namespace struct
|
||||
-->
|
||||
|
||||
<!-- LocalWords: ConstPointer ConstReference typename iostream int abcdefg
|
||||
-->
|
||||
<!-- LocalWords: sizeof PairGen pre Jeremy Siek David Abrahams
|
||||
-->
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,60 +0,0 @@
|
||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <functional>
|
||||
#include <boost/iterator_adaptors.hpp>
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
char characters[] = "abcdefg";
|
||||
const int N = sizeof(characters)/sizeof(char) - 1; // -1 since characters has a null char
|
||||
char* pointers_to_chars[N]; // at the end.
|
||||
for (int i = 0; i < N; ++i)
|
||||
pointers_to_chars[i] = &characters[i];
|
||||
|
||||
// Example of using indirect_iterator_generator
|
||||
|
||||
boost::indirect_iterator_generator<char**, char>::type
|
||||
indirect_first(pointers_to_chars), indirect_last(pointers_to_chars + N);
|
||||
|
||||
std::copy(indirect_first, indirect_last, std::ostream_iterator<char>(std::cout, ","));
|
||||
std::cout << std::endl;
|
||||
|
||||
|
||||
// Example of using indirect_iterator_pair_generator
|
||||
|
||||
typedef boost::indirect_iterator_pair_generator<char**, char> PairGen;
|
||||
|
||||
char mutable_characters[N];
|
||||
char* pointers_to_mutable_chars[N];
|
||||
for (int i = 0; i < N; ++i)
|
||||
pointers_to_mutable_chars[i] = &mutable_characters[i];
|
||||
|
||||
PairGen::iterator mutable_indirect_first(pointers_to_mutable_chars),
|
||||
mutable_indirect_last(pointers_to_mutable_chars + N);
|
||||
PairGen::const_iterator const_indirect_first(pointers_to_chars),
|
||||
const_indirect_last(pointers_to_chars + N);
|
||||
|
||||
std::transform(const_indirect_first, const_indirect_last,
|
||||
mutable_indirect_first, std::bind1st(std::plus<char>(), 1));
|
||||
|
||||
std::copy(mutable_indirect_first, mutable_indirect_last,
|
||||
std::ostream_iterator<char>(std::cout, ","));
|
||||
std::cout << std::endl;
|
||||
|
||||
|
||||
// Example of using make_indirect_iterator()
|
||||
|
||||
std::copy(boost::make_indirect_iterator(pointers_to_chars),
|
||||
boost::make_indirect_iterator(pointers_to_chars + N),
|
||||
std::ostream_iterator<char>(std::cout, ","));
|
||||
std::cout << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,151 +0,0 @@
|
||||
// (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
// Revision History
|
||||
// 08 Mar 2001 Jeremy Siek
|
||||
// Moved test of indirect iterator into its own file. It to
|
||||
// to be in iterator_adaptor_test.cpp.
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/iterator_adaptors.hpp>
|
||||
#include <boost/pending/iterator_tests.hpp>
|
||||
#include <boost/concept_archetype.hpp>
|
||||
#include <stdlib.h>
|
||||
#include <deque>
|
||||
#include <set>
|
||||
|
||||
struct my_iterator_tag : public std::random_access_iterator_tag { };
|
||||
|
||||
using boost::dummyT;
|
||||
|
||||
typedef std::deque<int> storage;
|
||||
typedef std::deque<int*> pointer_deque;
|
||||
typedef std::set<storage::iterator> iterator_set;
|
||||
|
||||
void more_indirect_iterator_tests()
|
||||
{
|
||||
// For some reason all heck breaks loose in the compiler under these conditions.
|
||||
#if !defined(BOOST_MSVC) || !defined(__STL_DEBUG)
|
||||
storage store(1000);
|
||||
std::generate(store.begin(), store.end(), rand);
|
||||
|
||||
pointer_deque ptr_deque;
|
||||
iterator_set iter_set;
|
||||
|
||||
for (storage::iterator p = store.begin(); p != store.end(); ++p)
|
||||
{
|
||||
ptr_deque.push_back(&*p);
|
||||
iter_set.insert(p);
|
||||
}
|
||||
|
||||
typedef boost::indirect_iterator_pair_generator<
|
||||
pointer_deque::iterator
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
, int
|
||||
#endif
|
||||
> IndirectDeque;
|
||||
|
||||
IndirectDeque::iterator db(ptr_deque.begin());
|
||||
IndirectDeque::iterator de(ptr_deque.end());
|
||||
assert(static_cast<std::size_t>(de - db) == store.size());
|
||||
assert(db + store.size() == de);
|
||||
IndirectDeque::const_iterator dci(db);
|
||||
assert(db == dci);
|
||||
assert(dci == db);
|
||||
assert(dci != de);
|
||||
assert(dci < de);
|
||||
assert(dci <= de);
|
||||
assert(de >= dci);
|
||||
assert(de > dci);
|
||||
dci = de;
|
||||
assert(dci == de);
|
||||
|
||||
boost::random_access_iterator_test(db + 1, store.size() - 1, boost::next(store.begin()));
|
||||
|
||||
*db = 999;
|
||||
assert(store.front() == 999);
|
||||
|
||||
// Borland C++ is getting very confused about the typedef's here
|
||||
|
||||
typedef boost::indirect_iterator_generator<
|
||||
iterator_set::iterator
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
, int
|
||||
#endif
|
||||
>::type indirect_set_iterator;
|
||||
|
||||
typedef boost::indirect_iterator_generator<
|
||||
iterator_set::iterator,
|
||||
const int
|
||||
>::type const_indirect_set_iterator;
|
||||
|
||||
indirect_set_iterator sb(iter_set.begin());
|
||||
indirect_set_iterator se(iter_set.end());
|
||||
const_indirect_set_iterator sci(iter_set.begin());
|
||||
assert(sci == sb);
|
||||
assert(sci != se);
|
||||
sci = se;
|
||||
assert(sci == se);
|
||||
|
||||
*boost::prior(se) = 888;
|
||||
assert(store.back() == 888);
|
||||
assert(std::equal(sb, se, store.begin()));
|
||||
|
||||
boost::bidirectional_iterator_test(boost::next(sb), store[1], store[2]);
|
||||
assert(std::equal(db, de, store.begin()));
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
dummyT array[] = { dummyT(0), dummyT(1), dummyT(2),
|
||||
dummyT(3), dummyT(4), dummyT(5) };
|
||||
const int N = sizeof(array)/sizeof(dummyT);
|
||||
|
||||
// Test indirect_iterator_generator
|
||||
{
|
||||
dummyT* ptr[N];
|
||||
for (int k = 0; k < N; ++k)
|
||||
ptr[k] = array + k;
|
||||
|
||||
typedef boost::indirect_iterator_generator<dummyT**
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
, dummyT
|
||||
#endif
|
||||
>::type indirect_iterator;
|
||||
|
||||
typedef boost::indirect_iterator_generator<dummyT**, const dummyT>::type const_indirect_iterator;
|
||||
|
||||
indirect_iterator i(ptr);
|
||||
boost::random_access_iterator_test(i, N, array);
|
||||
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
boost::random_access_iterator_test(boost::make_indirect_iterator(ptr), N, array);
|
||||
#endif
|
||||
|
||||
// check operator->
|
||||
assert((*i).m_x == i->foo());
|
||||
|
||||
const_indirect_iterator j(ptr);
|
||||
boost::random_access_iterator_test(j, N, array);
|
||||
|
||||
dummyT*const* const_ptr = ptr;
|
||||
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
boost::random_access_iterator_test(boost::make_indirect_iterator(const_ptr), N, array);
|
||||
#endif
|
||||
boost::const_nonconst_iterator_test(i, ++j);
|
||||
|
||||
more_indirect_iterator_tests();
|
||||
}
|
||||
std::cout << "test successful " << std::endl;
|
||||
return 0;
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
// Test boost/pending/iterator_adaptors.hpp
|
||||
|
||||
// (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
// Revision History
|
||||
// 21 Jan 01 Initial version (Jeremy Siek)
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <list>
|
||||
#include <boost/pending/iterator_adaptors.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
typedef boost::iterator_adaptor<std::list<int>::iterator,
|
||||
boost::default_iterator_policies,
|
||||
int,int&,int*,std::bidirectional_iterator_tag> adaptor_type;
|
||||
|
||||
adaptor_type i;
|
||||
i += 4;
|
||||
return 0;
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
// Test boost/pending/iterator_adaptors.hpp
|
||||
|
||||
// (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
// Revision History
|
||||
// 21 Jan 01 Initial version (Jeremy Siek)
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <boost/pending/iterator_adaptors.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
typedef boost::iterator_adaptor<std::istream_iterator<int>,
|
||||
boost::default_iterator_policies,
|
||||
int,int&,int*,std::input_iterator_tag> adaptor_type;
|
||||
|
||||
adaptor_type iter;
|
||||
--iter;
|
||||
return 0;
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
// 8 Mar 2001 Jeremy Siek
|
||||
// Initial checkin.
|
||||
|
||||
#include <boost/iterator_adaptors.hpp>
|
||||
#include <boost/pending/iterator_tests.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
class bar { };
|
||||
void foo(bar) { }
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
using boost::dummyT;
|
||||
dummyT array[] = { dummyT(0), dummyT(1), dummyT(2),
|
||||
dummyT(3), dummyT(4), dummyT(5) };
|
||||
typedef boost::iterator_adaptor<dummyT*,
|
||||
boost::default_iterator_policies, dummyT> my_iter;
|
||||
my_iter mi(array);
|
||||
|
||||
{
|
||||
typedef boost::iterator_adaptor<my_iter, boost::default_iterator_policies,
|
||||
boost::iterator_traits_generator
|
||||
::reference<dummyT>
|
||||
::iterator_category<std::input_iterator_tag> > iter_type;
|
||||
|
||||
BOOST_STATIC_ASSERT((boost::is_same<iter_type::iterator_category*,
|
||||
std::input_iterator_tag*>::value));
|
||||
|
||||
BOOST_STATIC_ASSERT(( ! boost::is_convertible<iter_type::iterator_category*,
|
||||
std::forward_iterator_tag*>::value));
|
||||
|
||||
iter_type i(mi);
|
||||
boost::input_iterator_test(i, dummyT(0), dummyT(1));
|
||||
}
|
||||
{
|
||||
typedef boost::iterator_adaptor<dummyT*,
|
||||
boost::default_iterator_policies,
|
||||
boost::iterator_traits_generator
|
||||
::value_type<dummyT>
|
||||
::reference<const dummyT&>
|
||||
::pointer<const dummyT*>
|
||||
::iterator_category<std::forward_iterator_tag>
|
||||
::difference_type<std::ptrdiff_t> > adaptor_type;
|
||||
|
||||
adaptor_type i(array);
|
||||
|
||||
boost::input_iterator_test(i, dummyT(0), dummyT(1));
|
||||
int zero = 0;
|
||||
if (zero) // don't do this, just make sure it compiles
|
||||
assert((*i).m_x == i->foo());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <boost/pending/iterator_adaptors.hpp>
|
||||
#include <boost/pending/integer_range.hpp>
|
||||
|
||||
int
|
||||
main(int, char*[])
|
||||
{
|
||||
// This is a simple example of using the transform_iterators class to
|
||||
// generate iterators that multiply the value returned by dereferencing
|
||||
// the iterator. In this case we are multiplying by 2.
|
||||
// Would be cooler to use lambda library in this example.
|
||||
|
||||
int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||
|
||||
typedef std::binder1st< std::multiplies<int> > Function;
|
||||
typedef boost::transform_iterator<Function, int*,
|
||||
boost::iterator<std::random_access_iterator_tag, int>
|
||||
>::type doubling_iterator;
|
||||
|
||||
doubling_iterator i(x, std::bind1st(std::multiplies<int>(), 2)),
|
||||
i_end(x + sizeof(x)/sizeof(int), std::bind1st(std::multiplies<int>(), 2));
|
||||
|
||||
std::cout << "multiplying the array by 2:" << std::endl;
|
||||
while (i != i_end)
|
||||
std::cout << *i++ << " ";
|
||||
std::cout << std::endl;
|
||||
|
||||
// Here is an example of counting from 0 to 5 using the integer_range class.
|
||||
|
||||
boost::integer_range<int> r(0,5);
|
||||
|
||||
std::cout << "counting to from 0 to 4:" << std::endl;
|
||||
std::copy(r.begin(), r.end(), std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1,335 +0,0 @@
|
||||
// Test boost/iterator_adaptors.hpp
|
||||
|
||||
// (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
// Revision History
|
||||
// 08 Mar 01 Moved indirect and transform tests to separate files.
|
||||
// (Jeremy Siek)
|
||||
// 19 Feb 01 Take adavantage of improved iterator_traits to do more tests
|
||||
// on MSVC. Hack around an MSVC-with-STLport internal compiler
|
||||
// error. (David Abrahams)
|
||||
// 11 Feb 01 Added test of operator-> for forward and input iterators.
|
||||
// (Jeremy Siek)
|
||||
// 11 Feb 01 Borland fixes (David Abrahams)
|
||||
// 10 Feb 01 Use new adaptors interface. (David Abrahams)
|
||||
// 10 Feb 01 Use new filter_ interface. (David Abrahams)
|
||||
// 09 Feb 01 Use new reverse_ and indirect_ interfaces. Replace
|
||||
// BOOST_NO_STD_ITERATOR_TRAITS with
|
||||
// BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION to prove we've
|
||||
// normalized to core compiler capabilities (David Abrahams)
|
||||
// 08 Feb 01 Use Jeremy's new make_reverse_iterator form; add more
|
||||
// comprehensive testing. Force-decay array function arguments to
|
||||
// pointers.
|
||||
// 07 Feb 01 Added tests for the make_xxx_iterator() helper functions.
|
||||
// (Jeremy Siek)
|
||||
// 07 Feb 01 Replaced use of xxx_pair_generator with xxx_generator where
|
||||
// possible (which was all but the projection iterator).
|
||||
// (Jeremy Siek)
|
||||
// 06 Feb 01 Removed now-defaulted template arguments where possible
|
||||
// Updated names to correspond to new generator naming convention.
|
||||
// Added a trivial test for make_transform_iterator().
|
||||
// Gave traits for const iterators a mutable value_type, per std.
|
||||
// Resurrected my original tests for indirect iterators.
|
||||
// (David Abrahams)
|
||||
// 04 Feb 01 Fix for compilers without standard iterator_traits
|
||||
// (David Abrahams)
|
||||
// 13 Jun 00 Added const version of the iterator tests (Jeremy Siek)
|
||||
// 12 Dec 99 Initial version with iterator operators (Jeremy Siek)
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <iostream>
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
|
||||
#include <boost/iterator_adaptors.hpp>
|
||||
#include <boost/pending/iterator_tests.hpp>
|
||||
#include <boost/pending/integer_range.hpp>
|
||||
#include <boost/concept_archetype.hpp>
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <set>
|
||||
|
||||
struct my_iterator_tag : public std::random_access_iterator_tag { };
|
||||
|
||||
using boost::dummyT;
|
||||
|
||||
|
||||
struct mult_functor {
|
||||
typedef int result_type;
|
||||
typedef int argument_type;
|
||||
// Functors used with transform_iterator must be
|
||||
// DefaultConstructible, as the transform_iterator must be
|
||||
// DefaultConstructible to satisfy the requirements for
|
||||
// TrivialIterator.
|
||||
mult_functor() { }
|
||||
mult_functor(int aa) : a(aa) { }
|
||||
int operator()(int b) const { return a * b; }
|
||||
int a;
|
||||
};
|
||||
|
||||
template <class Pair>
|
||||
struct select1st_
|
||||
: public std::unary_function<Pair, typename Pair::first_type>
|
||||
{
|
||||
const typename Pair::first_type& operator()(const Pair& x) const {
|
||||
return x.first;
|
||||
}
|
||||
typename Pair::first_type& operator()(Pair& x) const {
|
||||
return x.first;
|
||||
}
|
||||
};
|
||||
|
||||
struct one_or_four {
|
||||
bool operator()(dummyT x) const {
|
||||
return x.foo() == 1 || x.foo() == 4;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::deque<int> storage;
|
||||
typedef std::deque<int*> pointer_deque;
|
||||
typedef std::set<storage::iterator> iterator_set;
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
dummyT array[] = { dummyT(0), dummyT(1), dummyT(2),
|
||||
dummyT(3), dummyT(4), dummyT(5) };
|
||||
const int N = sizeof(array)/sizeof(dummyT);
|
||||
|
||||
// sanity check, if this doesn't pass the test is buggy
|
||||
boost::random_access_iterator_test(array,N,array);
|
||||
|
||||
// Check that the policy concept checks and the default policy
|
||||
// implementation match up.
|
||||
boost::function_requires<
|
||||
boost::RandomAccessIteratorPoliciesConcept<
|
||||
boost::default_iterator_policies, int*,
|
||||
boost::iterator<std::random_access_iterator_tag, int, std::ptrdiff_t,
|
||||
int*, int&>
|
||||
> >();
|
||||
|
||||
// Test the iterator_adaptor
|
||||
{
|
||||
boost::iterator_adaptor<dummyT*, boost::default_iterator_policies, dummyT> i(array);
|
||||
boost::random_access_iterator_test(i, N, array);
|
||||
|
||||
boost::iterator_adaptor<const dummyT*, boost::default_iterator_policies, const dummyT> j(array);
|
||||
boost::random_access_iterator_test(j, N, array);
|
||||
boost::const_nonconst_iterator_test(i, ++j);
|
||||
}
|
||||
|
||||
// Test projection_iterator_pair_generator
|
||||
{
|
||||
typedef std::pair<dummyT,dummyT> Pair;
|
||||
Pair pair_array[N];
|
||||
for (int k = 0; k < N; ++k)
|
||||
pair_array[k].first = array[k];
|
||||
|
||||
typedef boost::projection_iterator_pair_generator<select1st_<Pair>,
|
||||
Pair*, const Pair*
|
||||
> Projection;
|
||||
|
||||
Projection::iterator i(pair_array);
|
||||
boost::random_access_iterator_test(i, N, array);
|
||||
|
||||
boost::random_access_iterator_test(boost::make_projection_iterator(pair_array, select1st_<Pair>()), N, array);
|
||||
boost::random_access_iterator_test(boost::make_projection_iterator< select1st_<Pair> >(pair_array), N, array);
|
||||
|
||||
Projection::const_iterator j(pair_array);
|
||||
boost::random_access_iterator_test(j, N, array);
|
||||
|
||||
boost::random_access_iterator_test(boost::make_const_projection_iterator(pair_array, select1st_<Pair>()), N, array);
|
||||
boost::random_access_iterator_test(boost::make_const_projection_iterator<select1st_<Pair> >(pair_array), N, array);
|
||||
|
||||
boost::const_nonconst_iterator_test(i, ++j);
|
||||
}
|
||||
|
||||
// Test reverse_iterator_generator
|
||||
{
|
||||
dummyT reversed[N];
|
||||
std::copy(array, array + N, reversed);
|
||||
std::reverse(reversed, reversed + N);
|
||||
|
||||
typedef boost::reverse_iterator_generator<dummyT*
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
, dummyT
|
||||
#endif
|
||||
>::type reverse_iterator;
|
||||
|
||||
reverse_iterator i(reversed + N);
|
||||
boost::random_access_iterator_test(i, N, array);
|
||||
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array);
|
||||
#endif
|
||||
|
||||
typedef boost::reverse_iterator_generator<const dummyT*
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
, const dummyT
|
||||
#endif
|
||||
>::type const_reverse_iterator;
|
||||
|
||||
const_reverse_iterator j(reversed + N);
|
||||
boost::random_access_iterator_test(j, N, array);
|
||||
|
||||
const dummyT* const_reversed = reversed;
|
||||
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array);
|
||||
#endif
|
||||
|
||||
boost::const_nonconst_iterator_test(i, ++j);
|
||||
}
|
||||
|
||||
// Test reverse_iterator_generator again, with traits fully deducible on all platforms
|
||||
{
|
||||
std::deque<dummyT> reversed_container;
|
||||
std::reverse_copy(array, array + N, std::back_inserter(reversed_container));
|
||||
const std::deque<dummyT>::iterator reversed = reversed_container.begin();
|
||||
|
||||
|
||||
typedef boost::reverse_iterator_generator<
|
||||
std::deque<dummyT>::iterator>::type reverse_iterator;
|
||||
typedef boost::reverse_iterator_generator<
|
||||
std::deque<dummyT>::const_iterator, const dummyT>::type const_reverse_iterator;
|
||||
|
||||
// MSVC/STLport gives an INTERNAL COMPILER ERROR when any computation
|
||||
// (e.g. "reversed + N") is used in the constructor below.
|
||||
const std::deque<dummyT>::iterator finish = reversed_container.end();
|
||||
reverse_iterator i(finish);
|
||||
|
||||
boost::random_access_iterator_test(i, N, array);
|
||||
boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array);
|
||||
|
||||
const_reverse_iterator j = reverse_iterator(finish);
|
||||
boost::random_access_iterator_test(j, N, array);
|
||||
|
||||
const std::deque<dummyT>::const_iterator const_reversed = reversed;
|
||||
boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array);
|
||||
|
||||
// Many compilers' builtin deque iterators don't interoperate well, though
|
||||
// STLport fixes that problem.
|
||||
#if defined(__SGI_STL_PORT) || !defined(__GNUC__) && !defined(__BORLANDC__) && !defined(BOOST_MSVC)
|
||||
boost::const_nonconst_iterator_test(i, ++j);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Test integer_range's iterators
|
||||
{
|
||||
int int_array[] = { 0, 1, 2, 3, 4, 5 };
|
||||
boost::integer_range<int> r(0, 5);
|
||||
boost::random_access_iterator_test(r.begin(), r.size(), int_array);
|
||||
}
|
||||
|
||||
// Test filter iterator
|
||||
{
|
||||
// Using typedefs for filter_gen::type confused Borland terribly.
|
||||
typedef boost::detail::non_bidirectional_category<dummyT*>::type category;
|
||||
|
||||
typedef boost::filter_iterator_generator<one_or_four, dummyT*
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
, dummyT
|
||||
#endif
|
||||
>::type filter_iter;
|
||||
|
||||
#if defined(__BORLANDC__)
|
||||
// Borland is choking on accessing the policies_type explicitly
|
||||
// from the filter_iter.
|
||||
boost::forward_iterator_test(make_filter_iterator(array, array+N,
|
||||
one_or_four()),
|
||||
dummyT(1), dummyT(4));
|
||||
#else
|
||||
filter_iter i(array, filter_iter::policies_type(one_or_four(), array + N));
|
||||
boost::forward_iterator_test(i, dummyT(1), dummyT(4));
|
||||
#endif
|
||||
|
||||
#if !defined(__BORLANDC__)
|
||||
//
|
||||
enum { is_forward = boost::is_same<
|
||||
filter_iter::iterator_category,
|
||||
std::forward_iterator_tag>::value };
|
||||
BOOST_STATIC_ASSERT(is_forward);
|
||||
#endif
|
||||
|
||||
// On compilers not supporting partial specialization, we can do more type
|
||||
// deduction with deque iterators than with pointers... unless the library
|
||||
// is broken ;-(
|
||||
#if !defined(BOOST_MSVC) || defined(__SGI_STL_PORT)
|
||||
std::deque<dummyT> array2;
|
||||
std::copy(array+0, array+N, std::back_inserter(array2));
|
||||
boost::forward_iterator_test(
|
||||
boost::make_filter_iterator(array2.begin(), array2.end(), one_or_four()),
|
||||
dummyT(1), dummyT(4));
|
||||
|
||||
boost::forward_iterator_test(
|
||||
boost::make_filter_iterator<one_or_four>(array2.begin(), array2.end()),
|
||||
dummyT(1), dummyT(4));
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_MSVC) // This just freaks MSVC out completely
|
||||
boost::forward_iterator_test(
|
||||
boost::make_filter_iterator<one_or_four>(
|
||||
boost::make_reverse_iterator(array2.end()),
|
||||
boost::make_reverse_iterator(array2.begin())
|
||||
),
|
||||
dummyT(4), dummyT(1));
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
boost::forward_iterator_test(
|
||||
boost::make_filter_iterator(array+0, array+N, one_or_four()),
|
||||
dummyT(1), dummyT(4));
|
||||
|
||||
boost::forward_iterator_test(
|
||||
boost::make_filter_iterator<one_or_four>(array, array + N),
|
||||
dummyT(1), dummyT(4));
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
// check operator-> with a forward iterator
|
||||
{
|
||||
boost::forward_iterator_archetype<dummyT> forward_iter;
|
||||
#if defined(__BORLANDC__)
|
||||
typedef boost::iterator_adaptor<boost::forward_iterator_archetype<dummyT>,
|
||||
boost::default_iterator_policies,
|
||||
dummyT, const dummyT&, const dummyT*,
|
||||
std::forward_iterator_tag, std::ptrdiff_t> adaptor_type;
|
||||
#else
|
||||
typedef boost::iterator_adaptor<boost::forward_iterator_archetype<dummyT>,
|
||||
boost::default_iterator_policies,
|
||||
boost::iterator_traits_generator
|
||||
::value_type<dummyT>
|
||||
::reference<const dummyT&>
|
||||
::pointer<const dummyT*>
|
||||
::iterator_category<std::forward_iterator_tag>
|
||||
::difference_type<std::ptrdiff_t> > adaptor_type;
|
||||
#endif
|
||||
adaptor_type i(forward_iter);
|
||||
int zero = 0;
|
||||
if (zero) // don't do this, just make sure it compiles
|
||||
assert((*i).m_x == i->foo());
|
||||
}
|
||||
// check operator-> with an input iterator
|
||||
{
|
||||
boost::input_iterator_archetype<dummyT> input_iter;
|
||||
typedef boost::iterator_adaptor<boost::input_iterator_archetype<dummyT>,
|
||||
boost::default_iterator_policies,
|
||||
dummyT, const dummyT&, const dummyT*,
|
||||
std::input_iterator_tag, std::ptrdiff_t> adaptor_type;
|
||||
adaptor_type i(input_iter);
|
||||
int zero = 0;
|
||||
if (zero) // don't do this, just make sure it compiles
|
||||
assert((*i).m_x == i->foo());
|
||||
}
|
||||
std::cout << "test successful " << std::endl;
|
||||
return 0;
|
||||
}
|
@ -1,891 +1,19 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta name="generator" content="HTML Tidy, see www.w3.org">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
|
||||
<title>Boost Iterator Adaptor Library</title>
|
||||
<title>Boost.Utility</title>
|
||||
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
|
||||
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align=
|
||||
"center" width="277" height="86">
|
||||
|
||||
<h1>Boost Iterator Adaptor Library</h1>
|
||||
|
||||
<h2>Introduction</h2>
|
||||
|
||||
<p>The Iterator Adaptor library allows you transform an arbitrary ``base''
|
||||
type into a standard-conforming iterator with the behaviors you choose.
|
||||
Doing so is especially easy if the ``base'' type is itself an iterator. The
|
||||
library also supplies several example <a href=
|
||||
"../../more/generic_programming.html#adaptors">adaptors</a> which apply
|
||||
specific useful behaviors to arbitrary base iterators.
|
||||
|
||||
<h2>Table of Contents</h2>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Header <tt><a href=
|
||||
"../../boost/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a></tt>
|
||||
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Generalized Iterator Adaptor
|
||||
|
||||
<ul>
|
||||
<li>Class template <tt><a href=
|
||||
"#iterator_adaptor">iterator_adaptor</a></tt>
|
||||
|
||||
<li><a href="#template_parameters">Template Parameters</a>
|
||||
|
||||
<li><a href="#named_template_parameters">Named Template Parameters</a>
|
||||
|
||||
<li><a href="#policies">The Policies Class</a>
|
||||
|
||||
<li><a href="#additional_members">Additional Class Members</a>
|
||||
|
||||
<li><a href="#example">Example</a>
|
||||
|
||||
<li>(<tt>const</tt>/non-<tt>const</tt>) <a href=
|
||||
"#iterator_interactions">Iterator Interactions</a>
|
||||
|
||||
<li><a href="#challenge">Challenge</a>
|
||||
|
||||
<li><a href="#concept_model">Concept Model</a>
|
||||
|
||||
<li><a href="#declaration_synopsis">Declaration Synopsis</a>
|
||||
|
||||
<li><a href="#notes">Notes</a>
|
||||
</ul>
|
||||
|
||||
<li>
|
||||
<a name="specialized_adaptors">Specialized Iterator Adaptors</a>
|
||||
|
||||
<ul>
|
||||
<li><a href="indirect_iterator.htm">Indirect Iterator Adaptor</a>
|
||||
|
||||
<li><a href="reverse_iterator.htm">Reverse Iterator Adaptor</a>
|
||||
|
||||
<li><a href="transform_iterator.htm">Transform Iterator
|
||||
Adaptor</a>
|
||||
|
||||
<li><a href="projection_iterator.htm">Projection Iterator
|
||||
Adaptor</a>
|
||||
|
||||
<li><a href="filter_iterator.htm">Filter Iterator Adaptor</a>
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
<li>Header <tt><a href=
|
||||
"../../boost/counting_iterator.hpp">boost/counting_iterator.hpp</a></tt><br>
|
||||
|
||||
<a href="counting_iterator.htm">Counting Iterator Adaptor</a>
|
||||
|
||||
<li>Header <tt><a href=
|
||||
"../../boost/function_output_iterator.hpp">boost/function_output_iterator.hpp</a></tt><br>
|
||||
|
||||
<a href="function_output_iterator.htm">Function Output Iterator Adaptor</a>
|
||||
</ul>
|
||||
|
||||
<p><b><a href="file:///c:/boost/site/people/dave_abrahams.htm">Dave
|
||||
Abrahams</a></b> started the library, applying <a href=
|
||||
"../../more/generic_programming.html#policy">policy class</a> technique and
|
||||
handling const/non-const iterator interactions. He also contributed the
|
||||
<tt><a href="indirect_iterator.htm">indirect_</a></tt> and <tt><a href=
|
||||
"reverse_iterator.htm">reverse_</a></tt> iterator generators, and expanded
|
||||
<tt><a href="counting_iterator.htm">counting_iterator_generator</a></tt> to
|
||||
cover all incrementable types. He edited most of the documentation,
|
||||
sometimes heavily.<br>
|
||||
<b><a href="file:///c:/boost/site/people/jeremy_siek.htm">Jeremy
|
||||
Siek</a></b> contributed the <a href="transform_iterator.htm">transform
|
||||
iterator</a> adaptor, the integer-only version of <tt><a href=
|
||||
"counting_iterator.htm">counting_iterator_generator</a></tt>,
|
||||
the <a href="function_output_iterator.htm">function output iterator</a>
|
||||
adaptor, and most of the documentation.<br>
|
||||
<b><a href="http://www.boost.org/people/john_potter.htm">John
|
||||
Potter</a></b> contributed the <tt><a href=
|
||||
"projection_iterator.htm">projection_</a></tt> and <tt><a href=
|
||||
"filter_iterator.htm">filter_</a></tt> iterator generators and made some
|
||||
simplifications to the main <tt><a href=
|
||||
"#iterator_adaptor">iterator_adaptor</a></tt> template.<br>
|
||||
|
||||
|
||||
<h2><a name="iterator_adaptor">Class template</a>
|
||||
<tt>iterator_adaptor</tt></h2>
|
||||
Implementing standard conforming iterators is a non-trivial task. There are
|
||||
some fine points such as the interactions between an iterator and its
|
||||
corresponding const_iterator, and there are myriad operators that should be
|
||||
implemented but are easily forgotten or mishandled, such as
|
||||
<tt>operator->()</tt>. Using <tt>iterator_adaptor</tt>, you can easily
|
||||
implement an iterator class, and even more easily extend and <a href=
|
||||
"../../more/generic_programming.html#adaptors">adapt</a> existing iterator
|
||||
types. Moreover, it is easy to make a pair of interoperable <tt>const</tt>
|
||||
and <tt>non-const</tt> iterators.
|
||||
|
||||
<p><tt>iterator_adaptor</tt> is declared like this:
|
||||
<pre>
|
||||
template <class Base, class Policies,
|
||||
class ValueOrNamedParams = typename std::iterator_traits<Base>::value_type,
|
||||
class ReferenceOrNamedParams = <i>...(see below)</i>,
|
||||
class PointerOrNamedParams = <i>...(see below)</i>,
|
||||
class CategoryOrNamedParams = typename std::iterator_traits<Base>::iterator_category,
|
||||
class DistanceOrNamedParams = typename std::iterator_traits<Base>::difference_type>
|
||||
struct iterator_adaptor;
|
||||
</pre>
|
||||
|
||||
<h3><a name="template_parameters">Template Parameters</a></h3>
|
||||
|
||||
<p>Although <tt>iterator_adaptor</tt> takes seven template parameters,
|
||||
defaults have been carefully chosen to minimize the number of parameters
|
||||
you must supply in most cases, especially if <tt>BaseType</tt> is an
|
||||
iterator.
|
||||
|
||||
<table border="1" summary="iterator_adaptor template parameters">
|
||||
<tr>
|
||||
<th>Parameter
|
||||
|
||||
<th>Description
|
||||
|
||||
<tr>
|
||||
<td><tt>BaseType</tt>
|
||||
|
||||
<td>The type being wrapped.
|
||||
|
||||
<tr>
|
||||
<td><tt>Policies</tt>
|
||||
|
||||
<td>A <a href="../../more/generic_programming.html#policy">policy
|
||||
class</a> that supplies core functionality to the resulting iterator. A
|
||||
detailed description can be found <a href="#policies">below</a>.
|
||||
|
||||
<tr>
|
||||
<td><tt>Value</tt>
|
||||
|
||||
<td>The <tt>value_type</tt> of the resulting iterator, unless const. If
|
||||
Value is <tt>const X</tt> the
|
||||
<tt>value_type</tt> will be (<i>non-</i><tt>const</tt>) <tt>X</tt><a href=
|
||||
"#1">[1]</a>. If the <tt>value_type</tt> you wish to use is an abstract
|
||||
base class see note <a href="#5">[5]</a>.<br>
|
||||
<b>Default:</b>
|
||||
<tt>std::iterator_traits<BaseType>::value_type</tt> <a href=
|
||||
"#2">[2]</a>
|
||||
|
||||
<tr>
|
||||
<td><tt>Reference</tt>
|
||||
|
||||
<td>The <tt>reference</tt> type of the resulting iterator, and in
|
||||
particular, the result type of <tt>operator*()</tt>.<br>
|
||||
<b>Default:</b> If <tt>Value</tt> is supplied, <tt>Value&</tt> is
|
||||
used. Otherwise
|
||||
<tt>std::iterator_traits<BaseType>::reference</tt> is used.
|
||||
|
||||
<tr>
|
||||
<td><tt>Pointer</tt>
|
||||
|
||||
<td>The <tt>pointer</tt> type of the resulting iterator, and in
|
||||
particular, the result type of <tt>operator->()</tt>.<br>
|
||||
<b>Default:</b> If <tt>Value</tt> was supplied, then <tt>Value*</tt>,
|
||||
otherwise <tt>std::iterator_traits<BaseType>::pointer</tt>.
|
||||
|
||||
<tr>
|
||||
<td><tt>Category</tt>
|
||||
|
||||
<td>The <tt>iterator_category</tt> type for the resulting iterator.<br>
|
||||
<b>Default:</b>
|
||||
<tt>std::iterator_traits<BaseType>::iterator_category</tt>
|
||||
|
||||
<tr>
|
||||
<td><tt>Distance</tt>
|
||||
|
||||
<td>The <tt>difference_type</tt> for the resulting iterator.<br>
|
||||
<b>Default:</b>
|
||||
<tt>std::iterator_traits<BaseType>::difference_type</tt>
|
||||
|
||||
<tr>
|
||||
<td><tt>NamedParams</tt>
|
||||
|
||||
<td>A list of named template parameters generated using the
|
||||
<a href="#iterator_traits_generator">
|
||||
<tt>iterator_traits_generator</tt></a> class (see below).
|
||||
</table>
|
||||
|
||||
<h3><a name="named_template_parameters">Named Template Parameters</a></h3>
|
||||
|
||||
With seven template parameters, providing arguments for
|
||||
<tt>iterator_adaptor</tt> in the correct order can be challenging.
|
||||
Also, often times one would like to specify the sixth or seventh
|
||||
template parameter, but use the defaults for the third through
|
||||
fifth. As a solution to these problems we provide a mechanism for
|
||||
naming the last five template parameters, and providing them in
|
||||
any order through the <tt>iterator_traits_generator</tt> class.
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
<a name="iterator_traits_generator">class iterator_traits_generator</a>
|
||||
{
|
||||
public:
|
||||
template <class Value>
|
||||
struct value_type : public <i>recursive magic</i> { };
|
||||
|
||||
template <class Reference>
|
||||
struct reference : public <i>recursive magic</i> { };
|
||||
|
||||
template <class Pointer>
|
||||
struct pointer : public <i>recursive magic</i> { };
|
||||
|
||||
template <class Distance>
|
||||
struct difference_type : public <i>recursive magic</i> { };
|
||||
|
||||
template <class Category>
|
||||
struct iterator_category : public <i>recursive magic</i> { };
|
||||
};
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
The <tt>iterator_traits_generator</tt> is used to create a list of
|
||||
of template arguments. For example, suppose you want to set the
|
||||
<tt>Reference</tt> and <tt>Category</tt> parameters, and use the
|
||||
defaults for the rest. Then you can use the traits generator as
|
||||
follows:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
iterator_traits_generator::reference<foo>::category<std::input_iterator_tag>
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
This generated type can then be passed into the <tt>iterator_adaptor</tt>
|
||||
class to replace any of the last five parameters. If you use the traits
|
||||
generator in the <i>i</i>th parameter position, then the parameters <i>i</i>
|
||||
through 7 will use the types specified in the generator. For example, the
|
||||
following adapts <tt>foo_iterator</tt> to create an <a href=
|
||||
"http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a> with
|
||||
<tt>reference</tt> type <tt>foo</tt>, and whose other traits are determined
|
||||
according to the defaults described <a href="#template_parameters">above</a>.
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
iterator_adaptor<foo_iterator, foo_policies,
|
||||
iterator_traits_generator
|
||||
::reference<foo>
|
||||
::iterator_category<std::input_iterator_tag>
|
||||
>
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
|
||||
<h3><a name="policies">The Policies Class</a></h3>
|
||||
|
||||
<p>The main task in using <tt>iterator_adaptor</tt> is creating an
|
||||
appropriate <tt>Policies</tt> class. The <tt>Policies</tt> class will become
|
||||
the functional heart of the resulting iterator, supplying the core
|
||||
operations that determine its behavior. The <tt>iterator_adaptor</tt>
|
||||
template defines all of the operators required of a <a href=
|
||||
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access
|
||||
Iterator</a> by dispatching to a <tt>Policies</tt> object. Your
|
||||
<tt>Policies</tt> class must implement a subset of the core iterator
|
||||
operations below corresponding to the iterator categories you want it to
|
||||
support.<br>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="../iterator/doc/generator_iterator.htm">../iterator/doc/generator_iterator.htm</a>
|
||||
<hr>
|
||||
<tt>
|
||||
Boost.Utility<br>
|
||||
<br>
|
||||
|
||||
|
||||
<table border="1" summary="iterator_adaptor Policies operations">
|
||||
<caption>
|
||||
<b>Core Iterator Operations</b><br>
|
||||
<tt>T</tt>: adapted iterator type; <tt>p</tt>: object of type T; <tt>n</tt>: <tt>T::size_type</tt>; <tt>x</tt>: <tt>T::difference_type</tt>; <tt>p1</tt>, <tt>p2</tt>: iterators
|
||||
</caption>
|
||||
|
||||
<tr>
|
||||
<th>Operation
|
||||
|
||||
<th>Effects
|
||||
|
||||
<th>Implements Operations
|
||||
|
||||
<th>Required for Iterator Categories
|
||||
|
||||
<tr>
|
||||
<td><tt>initialize</tt>
|
||||
|
||||
<td>optionally modify base iterator during iterator construction
|
||||
|
||||
<td>constructors
|
||||
|
||||
<td rowspan="4"><a href=
|
||||
"http://www.sgi.com/tech/stl/InputIterator.html">Input</a>/ <a href=
|
||||
"http://www.sgi.com/tech/stl/OutputIterator.html">Output</a>/ <a href=
|
||||
"http://www.sgi.com/tech/stl/ForwardIterator.html">Forward</a>/ <a
|
||||
href=
|
||||
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">Bidirectional</a>/
|
||||
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
|
||||
Access</a>
|
||||
|
||||
|
||||
<tr>
|
||||
<td><tt>dereference</tt>
|
||||
|
||||
<td>returns an element of the iterator's <tt>reference</tt> type
|
||||
|
||||
<td><tt>*p</tt>, <tt>p[n]</tt>
|
||||
|
||||
|
||||
<tr>
|
||||
<td><tt>equal</tt>
|
||||
|
||||
<td>tests the iterator for equality
|
||||
|
||||
<td><tt>p1 == p2</tt>, <tt>p1 != p2</tt>
|
||||
|
||||
<tr>
|
||||
<td><tt>increment</tt>
|
||||
|
||||
<td>increments the iterator
|
||||
|
||||
<td><tt>++p</tt>, <tt>p++</tt>
|
||||
|
||||
<tr>
|
||||
<td><tt>decrement</tt>
|
||||
|
||||
<td>decrements the iterator
|
||||
|
||||
<td><tt>--p</tt>, <tt>p--</tt>
|
||||
|
||||
<td><a href=
|
||||
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">Bidirectional</a>/
|
||||
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
|
||||
Access</a>
|
||||
|
||||
<tr>
|
||||
<td><tt>less</tt>
|
||||
|
||||
<td>imposes a <a href=
|
||||
"http://www.sgi.com/tech/stl/StrictWeakOrdering.html">Strict Weak
|
||||
Ordering</a> relation on iterators
|
||||
|
||||
<td>
|
||||
<tt>p1 < p2</tt>,
|
||||
<tt>p1 <= p2</tt>,
|
||||
<tt>p1 > p2</tt>,
|
||||
<tt>p1 >= p2</tt>
|
||||
|
||||
<td rowspan="3"><a href=
|
||||
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
|
||||
Access</a>
|
||||
|
||||
<tr>
|
||||
<td><tt>distance</tt>
|
||||
|
||||
<td>measures the distance between iterators
|
||||
|
||||
<td><tt>p1 - p2</tt>
|
||||
|
||||
<tr>
|
||||
<td><tt>advance</tt>
|
||||
|
||||
<td>adds an integer offset to iterators
|
||||
|
||||
<td>
|
||||
<tt>p + x</tt>,
|
||||
<tt>x + p</tt>,
|
||||
<tt>p += x</tt>,
|
||||
<tt>p - x</tt>,
|
||||
<tt>p -= x</tt>
|
||||
|
||||
</table>
|
||||
|
||||
<p>The library also supplies a "trivial" policy class,
|
||||
<tt>default_iterator_policies</tt>, which implements all seven of the core
|
||||
operations in the usual way. If you wish to create an iterator adaptor that
|
||||
only changes a few of the base type's behaviors, then you can derive your
|
||||
new policy class from <tt>default_iterator_policies</tt> to avoid retyping
|
||||
the usual behaviors. You should also look at
|
||||
<tt>default_iterator_policies</tt> as the ``boilerplate'' for your own
|
||||
policy classes, defining functions with the same interface. This is the
|
||||
definition of <tt>default_iterator_policies</tt>:<br>
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||
<br>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
struct <a name="default_iterator_policies">default_iterator_policies</a>
|
||||
{
|
||||
template <class BaseType>
|
||||
void initialize(BaseType&)
|
||||
{ }
|
||||
|
||||
template <class Reference, class BaseType>
|
||||
Reference dereference(type<Reference>, const BaseType& x) const
|
||||
{ return *x; }
|
||||
|
||||
template <class BaseType>
|
||||
static void increment(BaseType& x)
|
||||
{ ++x; }
|
||||
|
||||
template <class BaseType1, class BaseType2>
|
||||
bool equal(BaseType1& x, BaseType2& y) const
|
||||
{ return x == y; }
|
||||
|
||||
template <class BaseType>
|
||||
static void decrement(BaseType& x)
|
||||
{ --x; }
|
||||
|
||||
template <class BaseType, class DifferenceType>
|
||||
static void advance(BaseType& x, DifferenceType n)
|
||||
{ x += n; }
|
||||
|
||||
template <class Difference, class BaseType1, class BaseType2>
|
||||
Difference distance(type<Difference>, BaseType1& x, BaseType2& y) const
|
||||
{ return y - x; }
|
||||
|
||||
template <class BaseType1, class BaseType2>
|
||||
bool less(BaseType1& x, BaseType2& y) const
|
||||
{ return x < y; }
|
||||
};
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>Template member functions are used throughout
|
||||
<tt>default_iterator_policies</tt> so that it can be employed with a wide
|
||||
range of iterators. If we had used concrete types above, we'd have tied the
|
||||
usefulness of <tt>default_iterator_policies</tt> to a particular range of
|
||||
adapted iterators. If you follow the same pattern with your
|
||||
<tt>Policies</tt> classes, you can use them to generate more specialized
|
||||
adaptors along the lines of <a href="#specialized_adaptors">those supplied by this library</a>.
|
||||
|
||||
<h3><a name="additional_members">Additional Members</a></h3>
|
||||
In addition to all of the member functions required of a <a href=
|
||||
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access
|
||||
Iterator</a>, the <tt>iterator_adaptor</tt> class template defines the
|
||||
following members. <br>
|
||||
<br>
|
||||
|
||||
|
||||
<table border="1" summary="additional iterator_adaptor members">
|
||||
<tr>
|
||||
<td><tt>explicit iterator_adaptor(const Base&, const Policies& =
|
||||
Policies())</tt>
|
||||
<br><br>
|
||||
Construct an adapted iterator from a base object and a policies
|
||||
object. As this constructor is <tt>explicit</tt>, it does not
|
||||
provide for implicit conversions from the <tt>Base</tt> type to
|
||||
the iterator adaptor.
|
||||
|
||||
<tr>
|
||||
<td><tt>template <class B, class V, class R, class P><br>
|
||||
iterator_adaptor(const
|
||||
iterator_adaptor<B,Policies,V,R,P,Category,Distance>&)</tt>
|
||||
<br><br>
|
||||
This constructor allows for conversion from non-<tt>const</tt> to
|
||||
constant adapted iterators. See <a href=
|
||||
"#iterator_interactions">below</a> for more details.<br>
|
||||
Requires: <tt>B</tt> is convertible to <tt>Base</tt>.
|
||||
|
||||
<tr>
|
||||
<td><tt>base_type base() const;</tt>
|
||||
<br><br>
|
||||
Return a copy of the base object.
|
||||
</table>
|
||||
|
||||
<h3><a name="example">Example</a></h3>
|
||||
|
||||
<p>It is often useful to automatically apply some function to the value
|
||||
returned by dereferencing an iterator. The <a href=
|
||||
"./transform_iterator.htm">transform iterator</a> makes it easy to create
|
||||
an iterator adaptor which does just that. Here we will show how easy it is
|
||||
to implement the transform iterator using the <tt>iterator_adaptor</tt>
|
||||
template.
|
||||
|
||||
<p>We want to be able to adapt a range of iterators and functions, so the
|
||||
policies class will have a template parameter for the function type and it
|
||||
will have a data member of that type. We know that the function takes one
|
||||
argument and that we'll need to be able to deduce the <tt>result_type</tt>
|
||||
of the function so we can use it for the adapted iterator's
|
||||
<tt>value_type</tt>. <a href=
|
||||
"http://www.sgi.com/Technology/STL/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>
|
||||
is the <a href="../../more/generic_programming.html#concept">Concept</a>
|
||||
that fulfills those requirements.
|
||||
|
||||
<p>To implement a transform iterator we will only change one of the base
|
||||
iterator's behaviors, so the <tt>transform_iterator_policies</tt> class can
|
||||
inherit the rest from <tt>default_iterator_policies</tt>. We will define
|
||||
the <tt>dereference()</tt> member function, which is used to implement
|
||||
<tt>operator*()</tt> of the adapted iterator. The implementation will
|
||||
dereference the base iterator and apply the function object. The
|
||||
<tt>type<Reference></tt> parameter is used to convey the appropriate
|
||||
return type. The complete code for <tt>transform_iterator_policies</tt>
|
||||
is:<br>
|
||||
<br>
|
||||
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
template <class AdaptableUnaryFunction>
|
||||
struct transform_iterator_policies : public default_iterator_policies
|
||||
{
|
||||
transform_iterator_policies() { }
|
||||
|
||||
transform_iterator_policies(const AdaptableUnaryFunction& f)
|
||||
: m_f(f) { }
|
||||
|
||||
template <class Reference, class BaseIterator>
|
||||
Reference dereference(type<Reference>, const BaseIterator& i) const
|
||||
{ return m_f(*i); }
|
||||
|
||||
AdaptableUnaryFunction m_f;
|
||||
};
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>The next step is to use the <tt>iterator_adaptor</tt> template to
|
||||
construct the transform iterator type. The nicest way to package the
|
||||
construction of the transform iterator is to create a <a href=
|
||||
"../../more/generic_programming.html#type_generator">type generator</a>.
|
||||
The first template parameter to the generator will be the type of the
|
||||
function object and the second will be the base iterator type. We use
|
||||
<tt>iterator_adaptor</tt> to define the transform iterator type as a nested
|
||||
<tt>typedef</tt> inside the <tt>transform_iterator_generator</tt> class.
|
||||
Because the function may return by-value, we must limit the
|
||||
<tt>iterator_category</tt> to <a href=
|
||||
"http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>, and
|
||||
the iterator's <tt>reference</tt> type cannot be a true reference (the
|
||||
standard allows this for input iterators), so in this case we can use few
|
||||
of <tt>iterator_adaptor</tt>'s default template arguments.<br>
|
||||
<br>
|
||||
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
template <class AdaptableUnaryFunction, class Iterator>
|
||||
struct transform_iterator_generator
|
||||
{
|
||||
typedef typename AdaptableUnaryFunction::result_type value_type;
|
||||
public:
|
||||
typedef iterator_adaptor<Iterator,
|
||||
transform_iterator_policies<AdaptableUnaryFunction>,
|
||||
value_type, value_type, value_type*, std::input_iterator_tag>
|
||||
type;
|
||||
};
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>As a finishing touch, we will create an <a href=
|
||||
"../../more/generic_programming.html#object_generator">object generator</a>
|
||||
for the transform iterator. This is a function that makes it more
|
||||
convenient to create a transform iterator.<br>
|
||||
<br>
|
||||
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
template <class AdaptableUnaryFunction, class Iterator>
|
||||
typename transform_iterator_generator<AdaptableUnaryFunction,Iterator>::type
|
||||
make_transform_iterator(Iterator base,
|
||||
const AdaptableUnaryFunction& f = AdaptableUnaryFunction())
|
||||
{
|
||||
typedef typename transform_iterator_generator<AdaptableUnaryFunction,
|
||||
Iterator>::type result_t;
|
||||
return result_t(base, f);
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>Here is an example that shows how to use a transform iterator to iterate
|
||||
through a range of numbers, multiplying each of them by 2 and printing the
|
||||
result to standard output.<br>
|
||||
<br>
|
||||
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <boost/iterator_adaptors.hpp>
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||
const int N = sizeof(x)/sizeof(int);
|
||||
std::cout << "multiplying the array by 2:" << std::endl;
|
||||
std::copy(boost::make_transform_iterator(x, std::bind1st(std::multiplies<int>(), 2)),
|
||||
boost::make_transform_iterator(x + N, std::bind1st(std::multiplies<int>(), 2)),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
This output is:
|
||||
<pre>
|
||||
2 4 6 8 10 12 14 16
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<h3><a name="iterator_interactions">Iterator Interactions</a></h3>
|
||||
|
||||
<p>C++ allows <tt>const</tt> and non-<tt>const</tt> pointers to interact in
|
||||
the following intuitive ways:
|
||||
|
||||
<ul>
|
||||
<li>a non-<tt>const</tt> pointer to <tt>T</tt> can be implicitly
|
||||
converted to a <tt>const</tt> pointer to <tt>T</tt>.
|
||||
|
||||
<li><tt>const</tt> and non-<tt>const</tt> pointers to <tt>T</tt> can be
|
||||
freely mixed in comparison expressions.
|
||||
|
||||
<li><tt>const</tt> and non-<tt>const</tt> pointers to <tt>T</tt> can be
|
||||
freely subtracted, in any order.
|
||||
</ul>
|
||||
|
||||
Getting user-defined iterators to work together that way is nontrivial (see
|
||||
<a href="reverse_iterator.htm#interactions">here</a> for an example of where
|
||||
the C++ standard got it wrong), but <tt>iterator_adaptor</tt> can make it
|
||||
easy. The rules are as follows:
|
||||
|
||||
<ul>
|
||||
<li><a name="interoperable">Adapted iterators that share the same <tt>Policies</tt>,
|
||||
<tt>Category</tt>, and <tt>Distance</tt> parameters are called
|
||||
<i>interoperable</i>.</a>
|
||||
|
||||
<li>An adapted iterator can be implicitly converted to any other adapted
|
||||
iterator with which it is interoperable, so long as the <tt>Base</tt>
|
||||
type of the source iterator can be converted to the <tt>Base</tt> type of
|
||||
the target iterator.
|
||||
|
||||
<li>Interoperable iterators can be freely mixed in comparison expressions
|
||||
so long as the <tt>Policies</tt> class has <tt>equal</tt> (and, for
|
||||
random access iterators, <tt>less</tt>) members that can accept both
|
||||
<tt>Base</tt> types in either order.
|
||||
|
||||
<li>Interoperable iterators can be freely mixed in subtraction
|
||||
expressions so long as the <tt>Policies</tt> class has a
|
||||
<tt>distance</tt> member that can accept both <tt>Base</tt> types in
|
||||
either order.
|
||||
</ul>
|
||||
|
||||
<h4>Example</h4>
|
||||
|
||||
<p>The <a href="projection_iterator.htm">Projection Iterator</a> adaptor is similar to the <a
|
||||
href="./transform_iterator.htm">transform iterator adaptor</a> in that
|
||||
its <tt>operator*()</tt> applies some function to the result of
|
||||
dereferencing the base iterator and then returns the result. The
|
||||
difference is that the function must return a reference to some
|
||||
existing object (for example, a data member within the
|
||||
<tt>value_type</tt> of the base iterator).
|
||||
|
||||
<p>
|
||||
The <a
|
||||
href="projection_iterator.htm#projection_iterator_pair_generator">projection_iterator_pair_generator</a> template
|
||||
is a special two-<a href="../../more/generic_programming.html#type_generator">type generator</a> for mutable and constant versions of a
|
||||
projection iterator. It is defined as follows:
|
||||
<blockquote>
|
||||
<pre>
|
||||
template <class AdaptableUnaryFunction, class Iterator, class ConstIterator>
|
||||
struct projection_iterator_pair_generator {
|
||||
typedef typename AdaptableUnaryFunction::result_type value_type;
|
||||
typedef projection_iterator_policies<AdaptableUnaryFunction> policies;
|
||||
public:
|
||||
typedef iterator_adaptor<Iterator,policies,value_type> iterator;
|
||||
typedef iterator_adaptor<ConstIterator,policies,value_type,
|
||||
const value_type&,const value_type*> const_iterator;
|
||||
};
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>It is assumed that the <tt>Iterator</tt> and <tt>ConstIterator</tt> arguments are corresponding mutable
|
||||
and constant iterators. <ul>
|
||||
<li>
|
||||
Clearly, then, the
|
||||
<tt>projection_iterator_pair_generator</tt>'s <tt>iterator</tt> and
|
||||
<tt>const_iterator</tt> are <a href="#interoperable">interoperable</a>, since
|
||||
they share the same <tt>Policies</tt> and since <tt>Category</tt> and
|
||||
<tt>Distance</tt> as supplied by <tt>std::iterator_traits</tt> through the
|
||||
<a href="#template_parameters">default template parameters</a> to
|
||||
<tt>iterator_adaptor</tt> should be the same.
|
||||
|
||||
<li>Since <tt>Iterator</tt> can presumably be converted to
|
||||
<tt>ConstIterator</tt>, the projection <tt>iterator</tt> will be convertible to
|
||||
the projection <tt>const_iterator</tt>.
|
||||
|
||||
<li> Since <tt>projection_iterator_policies</tt> implements only the
|
||||
<tt>dereference</tt> operation, and inherits all other behaviors from <tt><a
|
||||
href="#default_iterator_policies">default_iterator_policies</a></tt>, which has
|
||||
fully-templatized <tt>equal</tt>, <tt>less</tt>, and <tt>distance</tt>
|
||||
operations, the <tt>iterator</tt> and <tt>const_iterator</tt> can be freely
|
||||
mixed in comparison and subtraction expressions.
|
||||
|
||||
</ul>
|
||||
|
||||
<h3><a name="challenge">Challenge</a></h3>
|
||||
|
||||
<p>There is an unlimited number of ways the <tt>iterator_adaptors</tt>
|
||||
class can be used to create iterators. One interesting exercise would be to
|
||||
re-implement the iterators of <tt>std::list</tt> and <tt>std::slist</tt>
|
||||
using <tt>iterator_adaptors</tt>, where the adapted <tt>Iterator</tt> types
|
||||
would be node pointers.
|
||||
|
||||
<h3><a name="concept_model">Concept Model</a></h3>
|
||||
Depending on the <tt>Base</tt> and <tt>Policies</tt> template parameters,
|
||||
an <tt>iterator_adaptor</tt> can be a <a href=
|
||||
"http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>, <a
|
||||
href="http://www.sgi.com/tech/stl/ForwardIterator.html">Forward
|
||||
Iterator</a>, <a href=
|
||||
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">Bidirectional
|
||||
Iterator</a>, or <a href=
|
||||
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access
|
||||
Iterator</a>.
|
||||
|
||||
<h3><a name="declaration_synopsis">Declaration Synopsis</a></h3>
|
||||
<pre>
|
||||
template <class Base, class Policies,
|
||||
class Value = typename std::iterator_traits<Base>::value_type,
|
||||
class Reference = <i>...(see below)</i>,
|
||||
class Pointer = <i>...(see below)</i>,
|
||||
class Category = typename std::iterator_traits<Base>::iterator_category,
|
||||
class Distance = typename std::iterator_traits<Base>::difference_type
|
||||
>
|
||||
struct iterator_adaptor
|
||||
{
|
||||
typedef Distance difference_type;
|
||||
typedef typename boost::remove_const<Value>::type value_type;
|
||||
typedef Pointer pointer;
|
||||
typedef Reference reference;
|
||||
typedef Category iterator_category;
|
||||
typedef Base base_type;
|
||||
typedef Policies policies_type;
|
||||
|
||||
iterator_adaptor();
|
||||
explicit iterator_adaptor(const Base&, const Policies& = Policies());
|
||||
|
||||
base_type base() const;
|
||||
|
||||
template <class B, class V, class R, class P>
|
||||
iterator_adaptor(
|
||||
const iterator_adaptor<B,Policies,V,R,P,Category,Distance>&);
|
||||
|
||||
reference operator*() const;
|
||||
<i>operator_arrow_result_type</i> operator->() const; <a href=
|
||||
"#3">[3]</a>
|
||||
<i>value_type</i> operator[](difference_type n) const; <a href="#3">[4]</a>
|
||||
|
||||
iterator_adaptor& operator++();
|
||||
iterator_adaptor& operator++(int);
|
||||
iterator_adaptor& operator--();
|
||||
iterator_adaptor& operator--(int);
|
||||
|
||||
iterator_adaptor& operator+=(difference_type n);
|
||||
iterator_adaptor& operator-=(difference_type n);
|
||||
|
||||
iterator_adaptor& operator-(Distance x) const;
|
||||
};
|
||||
|
||||
template <class B, class P, class V, class R, class Ptr,
|
||||
class C, class D1, class D2>
|
||||
iterator_adaptor<B,P,V,R,Ptr,C,D1>
|
||||
operator+(iterator_adaptor<B,P,V,R,Ptr,C,D1>, D2);
|
||||
|
||||
template <class B, class P, class V, class R, class Ptr,
|
||||
class C, class D1, class D2>
|
||||
iterator_adaptor<B,P,V,R,P,C,D1>
|
||||
operator+(D2, iterator_adaptor<B,P,V,R,Ptr,C,D1> p);
|
||||
|
||||
template <class B1, class B2, class P, class V1, class V2,
|
||||
class R1, class R2, class P1, class P2, class C, class D>
|
||||
Distance operator-(const iterator_adaptor<B1,P,V1,R1,P1,C,D>&,
|
||||
const iterator_adaptor<B2,P,V2,R2,P2,C,D>&);
|
||||
|
||||
template <class B1, class B2, class P, class V1, class V2,
|
||||
class R1, class R2, class P1, class P2, class C, class D>
|
||||
bool operator==(const iterator_adaptor<B1,P,V1,R1,P1,C,D>&,
|
||||
const iterator_adaptor<B2,P,V2,R2,P2,C,D>&);
|
||||
|
||||
// and similarly for operators !=, <, <=, >=, >
|
||||
</pre>
|
||||
|
||||
<h3><a name="notes">Notes</a></h3>
|
||||
|
||||
<p><a name="1">[1]</a> The standard specifies that the <tt>value_type</tt>
|
||||
of <tt>const</tt> iterators to <tt>T</tt> (e.g. <tt>const T*</tt>) is
|
||||
<tt><i>non-</i>const T</tt>, while the <tt>pointer</tt> and
|
||||
<tt>reference</tt> types for all <a href=
|
||||
"http://www.sgi.com/tech/stl/ForwardIterator.html">Forward Iterators</a> are
|
||||
<tt>const T*</tt> and <tt>const T&</tt>, respectively. Stripping the
|
||||
<tt>const</tt>-ness of <tt>Value</tt> allows you to easily
|
||||
make a <tt>const</tt> iterator adaptor by supplying a <tt>const</tt> type
|
||||
for <tt>Value</tt>, and allowing the defaults for the <tt>Pointer</tt> and
|
||||
<tt>Reference</tt> parameters to take effect. Although compilers that don't
|
||||
support partial specialization won't strip <tt>const</tt> for you, having a
|
||||
<tt>const value_type</tt> is often harmless in practice.
|
||||
|
||||
<p><a name="2">[2]</a> If your compiler does not support partial
|
||||
specialization and the base iterator is a builtin pointer type, you
|
||||
will not be able to use the default for <tt>Value</tt> and will have to
|
||||
specify this type explicitly.
|
||||
|
||||
<p><a name="3">[3]</a> The result type for the <tt>operator->()</tt>
|
||||
depends on the category and value type of the iterator and is somewhat
|
||||
complicated to describe. But be assured, it works in a stardard conforming
|
||||
fashion, providing access to members of the objects pointed to by the
|
||||
iterator.
|
||||
|
||||
<p><a name="4">[4]</a> The result type of <tt>operator[]()</tt> is
|
||||
<tt>value_type</tt> instead of <tt>reference</tt> as might be expected.
|
||||
There are two reasons for this choice. First, the C++ standard only
|
||||
requires that the return type of an arbitrary <a href=
|
||||
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access
|
||||
Iterator</a>'s <tt>operator[]</tt>be ``convertible to T'' (Table 76), so
|
||||
when adapting an arbitrary base iterator we may not have a reference to
|
||||
return. Second, and more importantly, for certain kinds of iterators,
|
||||
returning a reference could cause serious memory problems due to the
|
||||
reference being bound to a temporary object whose lifetime ends inside of
|
||||
the <tt>operator[]</tt>.
|
||||
|
||||
<p><a name="5">[5]</a>
|
||||
The <tt>value_type</tt> of an iterator may not be
|
||||
an abstract base class, however many common uses of iterators
|
||||
never need the <tt>value_type</tt>, only the <tt>reference</tt> type.
|
||||
If you wish to create such an iterator adaptor, use a dummy
|
||||
type such as <tt>char</tt> for the <tt>Value</tt> parameter,
|
||||
and use a reference to your abstract base class for
|
||||
the <tt>Reference</tt> parameter. Note that such an iterator
|
||||
does not fulfill the C++ standards requirements for a
|
||||
<a href= "http://www.sgi.com/tech/stl/ForwardIterator.html">
|
||||
Forward Iterator</a>, so you will need to use a less restrictive
|
||||
iterator category such as <tt>std::input_iterator_tag</tt>.
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->12 Jul 2001<!--webbot bot="Timestamp" endspan i-checksum="14985" -->
|
||||
|
||||
|
||||
<p>© Copyright Dave Abrahams and Jeremy Siek 2001. Permission to copy,
|
||||
use, modify, sell and distribute this document is granted provided this
|
||||
copyright notice appears in all copies. This document is provided "as is"
|
||||
without express or implied warranty, and with no claim as to its
|
||||
suitability for any purpose.
|
||||
|
||||
</tt>
|
||||
</body>
|
||||
|
||||
<!-- LocalWords: HTML html charset alt gif abrahams htm const
|
||||
incrementable david abrahams
|
||||
-->
|
||||
|
||||
<!-- LocalWords: jeremy siek mishandled interoperable typename struct Iter iter src
|
||||
-->
|
||||
|
||||
<!-- LocalWords: int bool ForwardIterator BidirectionalIterator BaseIterator
|
||||
-->
|
||||
|
||||
<!-- LocalWords: RandomAccessIterator DifferenceType AdaptableUnaryFunction
|
||||
-->
|
||||
|
||||
<!-- LocalWords: iostream hpp sizeof InputIterator constness ConstIterator
|
||||
David Abrahams
|
||||
-->
|
||||
</html>
|
||||
|
||||
|
@ -1,210 +0,0 @@
|
||||
// (C) Copyright David Abrahams 2001. Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
// Revision History
|
||||
// 04 Mar 2001 Patches for Intel C++ (Dave Abrahams)
|
||||
// 19 Feb 2001 Take advantage of improved iterator_traits to do more tests
|
||||
// on MSVC. Reordered some #ifdefs for coherency.
|
||||
// (David Abrahams)
|
||||
// 13 Feb 2001 Test new VC6 workarounds (David Abrahams)
|
||||
// 11 Feb 2001 Final fixes for Borland (David Abrahams)
|
||||
// 11 Feb 2001 Some fixes for Borland get it closer on that compiler
|
||||
// (David Abrahams)
|
||||
// 07 Feb 2001 More comprehensive testing; factored out static tests for
|
||||
// better reuse (David Abrahams)
|
||||
// 21 Jan 2001 Quick fix to my_iterator, which wasn't returning a
|
||||
// reference type from operator* (David Abrahams)
|
||||
// 19 Jan 2001 Initial version with iterator operators (David Abrahams)
|
||||
|
||||
#include <boost/detail/iterator.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <boost/operators.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
// An iterator for which we can get traits.
|
||||
struct my_iterator1
|
||||
: boost::forward_iterator_helper<my_iterator1, char, long, const char*, const char&>
|
||||
{
|
||||
my_iterator1(const char* p) : m_p(p) {}
|
||||
|
||||
bool operator==(const my_iterator1& rhs) const
|
||||
{ return this->m_p == rhs.m_p; }
|
||||
|
||||
my_iterator1& operator++() { ++this->m_p; return *this; }
|
||||
const char& operator*() { return *m_p; }
|
||||
private:
|
||||
const char* m_p;
|
||||
};
|
||||
|
||||
// Used to prove that we don't require std::iterator<> in the hierarchy under
|
||||
// MSVC6, and that we can compute all the traits for a standard-conforming UDT
|
||||
// iterator.
|
||||
struct my_iterator2
|
||||
: boost::equality_comparable<my_iterator2
|
||||
, boost::incrementable<my_iterator2
|
||||
, boost::dereferenceable<my_iterator2,const char*> > >
|
||||
{
|
||||
typedef char value_type;
|
||||
typedef long difference_type;
|
||||
typedef const char* pointer;
|
||||
typedef const char& reference;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
|
||||
my_iterator2(const char* p) : m_p(p) {}
|
||||
|
||||
bool operator==(const my_iterator2& rhs) const
|
||||
{ return this->m_p == rhs.m_p; }
|
||||
|
||||
my_iterator2& operator++() { ++this->m_p; return *this; }
|
||||
const char& operator*() { return *m_p; }
|
||||
private:
|
||||
const char* m_p;
|
||||
};
|
||||
|
||||
// Used to prove that we're not overly confused by the existence of
|
||||
// std::iterator<> in the hierarchy under MSVC6 - we should find that
|
||||
// boost::detail::iterator_traits<my_iterator3>::difference_type is int.
|
||||
struct my_iterator3 : my_iterator1
|
||||
{
|
||||
typedef int difference_type;
|
||||
my_iterator3(const char* p) : my_iterator1(p) {}
|
||||
};
|
||||
|
||||
template <class Iterator,
|
||||
class value_type, class difference_type, class pointer, class reference, class category>
|
||||
struct non_portable_tests
|
||||
{
|
||||
// Unfortunately, the VC6 standard library doesn't supply these :(
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<
|
||||
typename boost::detail::iterator_traits<Iterator>::pointer,
|
||||
pointer
|
||||
>::value));
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<
|
||||
typename boost::detail::iterator_traits<Iterator>::reference,
|
||||
reference
|
||||
>::value));
|
||||
};
|
||||
|
||||
template <class Iterator,
|
||||
class value_type, class difference_type, class pointer, class reference, class category>
|
||||
struct portable_tests
|
||||
{
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<
|
||||
typename boost::detail::iterator_traits<Iterator>::difference_type,
|
||||
difference_type
|
||||
>::value));
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<
|
||||
typename boost::detail::iterator_traits<Iterator>::iterator_category,
|
||||
category
|
||||
>::value));
|
||||
};
|
||||
|
||||
// Test iterator_traits
|
||||
template <class Iterator,
|
||||
class value_type, class difference_type, class pointer, class reference, class category>
|
||||
struct input_iterator_test
|
||||
: portable_tests<Iterator,value_type,difference_type,pointer,reference,category>
|
||||
{
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<
|
||||
typename boost::detail::iterator_traits<Iterator>::value_type,
|
||||
value_type
|
||||
>::value));
|
||||
};
|
||||
|
||||
template <class Iterator,
|
||||
class value_type, class difference_type, class pointer, class reference, class category>
|
||||
struct non_pointer_test
|
||||
: input_iterator_test<Iterator,value_type,difference_type,pointer,reference,category>
|
||||
, non_portable_tests<Iterator,value_type,difference_type,pointer,reference,category>
|
||||
{
|
||||
};
|
||||
|
||||
template <class Iterator,
|
||||
class value_type, class difference_type, class pointer, class reference, class category>
|
||||
struct maybe_pointer_test
|
||||
: portable_tests<Iterator,value_type,difference_type,pointer,reference,category>
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
, non_portable_tests<Iterator,value_type,difference_type,pointer,reference,category>
|
||||
#endif
|
||||
{
|
||||
};
|
||||
|
||||
input_iterator_test<std::istream_iterator<int>, int, std::ptrdiff_t, int*, int&, std::input_iterator_tag>
|
||||
istream_iterator_test;
|
||||
|
||||
//
|
||||
#if defined(__BORLANDC__) && !defined(__SGI_STL_PORT)
|
||||
typedef ::std::char_traits<char>::off_type distance;
|
||||
non_pointer_test<std::ostream_iterator<int>,int,
|
||||
distance,int*,int&,std::output_iterator_tag> ostream_iterator_test;
|
||||
#elif defined(BOOST_MSVC_STD_ITERATOR)
|
||||
non_pointer_test<std::ostream_iterator<int>,
|
||||
int, void, void, void, std::output_iterator_tag>
|
||||
ostream_iterator_test;
|
||||
#else
|
||||
non_pointer_test<std::ostream_iterator<int>,
|
||||
void, void, void, void, std::output_iterator_tag>
|
||||
ostream_iterator_test;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __KCC
|
||||
typedef long std_list_diff_type;
|
||||
#else
|
||||
typedef std::ptrdiff_t std_list_diff_type;
|
||||
#endif
|
||||
non_pointer_test<std::list<int>::iterator, int, std_list_diff_type, int*, int&, std::bidirectional_iterator_tag>
|
||||
list_iterator_test;
|
||||
|
||||
maybe_pointer_test<std::vector<int>::iterator, int, std::ptrdiff_t, int*, int&, std::random_access_iterator_tag>
|
||||
vector_iterator_test;
|
||||
|
||||
maybe_pointer_test<int*, int, std::ptrdiff_t, int*, int&, std::random_access_iterator_tag>
|
||||
int_pointer_test;
|
||||
|
||||
non_pointer_test<my_iterator1, char, long, const char*, const char&, std::forward_iterator_tag>
|
||||
my_iterator1_test;
|
||||
|
||||
non_pointer_test<my_iterator2, char, long, const char*, const char&, std::forward_iterator_tag>
|
||||
my_iterator2_test;
|
||||
|
||||
non_pointer_test<my_iterator3, char, int, const char*, const char&, std::forward_iterator_tag>
|
||||
my_iterator3_test;
|
||||
|
||||
int main()
|
||||
{
|
||||
char chars[100];
|
||||
int ints[100];
|
||||
|
||||
for (std::ptrdiff_t length = 3; length < 100; length += length / 3)
|
||||
{
|
||||
std::list<int> l(length);
|
||||
assert(boost::detail::distance(l.begin(), l.end()) == length);
|
||||
|
||||
std::vector<int> v(length);
|
||||
assert(boost::detail::distance(v.begin(), v.end()) == length);
|
||||
|
||||
assert(boost::detail::distance(&ints[0], ints + length) == length);
|
||||
assert(boost::detail::distance(my_iterator1(chars), my_iterator1(chars + length)) == length);
|
||||
assert(boost::detail::distance(my_iterator2(chars), my_iterator2(chars + length)) == length);
|
||||
assert(boost::detail::distance(my_iterator3(chars), my_iterator3(chars + length)) == length);
|
||||
}
|
||||
return 0;
|
||||
}
|
135
meta/libraries.json
Normal file
135
meta/libraries.json
Normal file
@ -0,0 +1,135 @@
|
||||
[
|
||||
{
|
||||
"key": "utility",
|
||||
"name": "Utility",
|
||||
"authors": [
|
||||
"Dave Abrahams and others"
|
||||
],
|
||||
"description": "Class noncopyable plus checked_delete(), checked_array_delete(), next(), prior() function templates, plus base-from-member idiom.",
|
||||
"documentation": "utility.htm",
|
||||
"category": [
|
||||
"Algorithms",
|
||||
"Function-objects",
|
||||
"Memory",
|
||||
"Miscellaneous",
|
||||
"Patterns"
|
||||
],
|
||||
"cxxstd": "03"
|
||||
},
|
||||
{
|
||||
"key": "utility/call_traits",
|
||||
"name": "Call Traits",
|
||||
"authors": [
|
||||
"John Maddock, Howard Hinnant, et al"
|
||||
],
|
||||
"description": "Defines types for passing parameters.",
|
||||
"documentation": "call_traits.htm",
|
||||
"category": [
|
||||
"Generic"
|
||||
],
|
||||
"cxxstd": "03"
|
||||
},
|
||||
{
|
||||
"key": "utility/compressed_pair",
|
||||
"name": "Compressed Pair",
|
||||
"authors": [
|
||||
"John Maddock, Howard Hinnant, et al"
|
||||
],
|
||||
"description": "Empty member optimization.",
|
||||
"documentation": "compressed_pair.htm",
|
||||
"category": [
|
||||
"Data",
|
||||
"Patterns"
|
||||
],
|
||||
"cxxstd": "03"
|
||||
},
|
||||
{
|
||||
"key": "utility/identity_type",
|
||||
"name": "Identity Type",
|
||||
"authors": [
|
||||
"Lorenzo Caminiti"
|
||||
],
|
||||
"description": "Wrap types within round parenthesis so they can always be passed as macro parameters.",
|
||||
"documentation": "identity_type/",
|
||||
"category": [
|
||||
"Preprocessor"
|
||||
],
|
||||
"maintainers": [
|
||||
"Lorenzo Caminiti <lorcaminiti -at- gmail.com>"
|
||||
],
|
||||
"cxxstd": "03"
|
||||
},
|
||||
{
|
||||
"key": "utility/in_place_factories",
|
||||
"name": "In Place Factory, Typed In Place Factory",
|
||||
"authors": [
|
||||
"Fernando Cacciola"
|
||||
],
|
||||
"description": "Generic in-place construction of contained objects with a variadic argument-list.",
|
||||
"documentation": "in_place_factories.html",
|
||||
"category": [
|
||||
"Generic"
|
||||
],
|
||||
"cxxstd": "03"
|
||||
},
|
||||
{
|
||||
"key": "utility/operators",
|
||||
"name": "Operators",
|
||||
"authors": [
|
||||
"Dave Abrahams",
|
||||
"Jeremy Siek"
|
||||
],
|
||||
"description": "Templates ease arithmetic classes and iterators.",
|
||||
"documentation": "operators.htm",
|
||||
"category": [
|
||||
"Generic",
|
||||
"Iterators",
|
||||
"Math"
|
||||
],
|
||||
"maintainers": [
|
||||
"Daniel Frey <d.frey -at- gmx.de>"
|
||||
],
|
||||
"cxxstd": "03"
|
||||
},
|
||||
{
|
||||
"key": "utility/result_of",
|
||||
"name": "Result Of",
|
||||
"description": "Determines the type of a function call expression.",
|
||||
"documentation": "utility.htm#result_of",
|
||||
"category": [
|
||||
"Function-objects"
|
||||
],
|
||||
"authors": "",
|
||||
"maintainers": [
|
||||
"Daniel Walker <daniel.j.walker -at- gmail.com>"
|
||||
],
|
||||
"cxxstd": "03"
|
||||
},
|
||||
{
|
||||
"key": "utility/string_ref",
|
||||
"name": "String Ref",
|
||||
"description": "String view templates.",
|
||||
"documentation": "doc/html/string_ref.html",
|
||||
"category": [
|
||||
"Containers"
|
||||
],
|
||||
"authors": "Marshall Clow",
|
||||
"maintainers": [
|
||||
"Marshall Clow <marshall -at- idio.com>"
|
||||
],
|
||||
"cxxstd": "03"
|
||||
},
|
||||
{
|
||||
"key": "utility/value_initialized",
|
||||
"name": "Value Initialized",
|
||||
"authors": [
|
||||
"Fernando Cacciola"
|
||||
],
|
||||
"description": "Wrapper for uniform-syntax value initialization, based on the original idea of David Abrahams.",
|
||||
"documentation": "value_init.htm",
|
||||
"category": [
|
||||
"Miscellaneous"
|
||||
],
|
||||
"cxxstd": "03"
|
||||
}
|
||||
]
|
@ -1,38 +0,0 @@
|
||||
// boost class noncopyable test program ------------------------------------//
|
||||
|
||||
// (C) Copyright boost.org 1999. Permission to copy, use, modify, sell
|
||||
// and distribute this software is granted provided this copyright
|
||||
// notice appears in all copies. This software is provided "as is" without
|
||||
// express or implied warranty, and with no claim as to its suitability for
|
||||
// any purpose.
|
||||
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
// Revision History
|
||||
// 9 Jun 99 Add unnamed namespace
|
||||
// 2 Jun 99 Initial Version
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <iostream>
|
||||
|
||||
// This program demonstrates compiler errors resulting from trying to copy
|
||||
// construct or copy assign a class object derived from class noncopyable.
|
||||
|
||||
namespace
|
||||
{
|
||||
class DontTreadOnMe : boost::noncopyable
|
||||
{
|
||||
public:
|
||||
DontTreadOnMe() { std::cout << "defanged!" << std::endl; }
|
||||
}; // DontTreadOnMe
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
int main()
|
||||
{
|
||||
DontTreadOnMe object1;
|
||||
DontTreadOnMe object2(object1);
|
||||
object1 = object2;
|
||||
return 0;
|
||||
} // main
|
||||
|
@ -1,387 +0,0 @@
|
||||
// (C) Copyright David Abrahams 2001. Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
// Revision History
|
||||
// 1 Apr 2001 Fixes for ICL; use BOOST_STATIC_CONSTANT
|
||||
// 11 Feb 2001 Fixes for Borland (David Abrahams)
|
||||
// 23 Jan 2001 Added test for wchar_t (David Abrahams)
|
||||
// 23 Jan 2001 Now statically selecting a test for signed numbers to avoid
|
||||
// warnings with fancy compilers. Added commentary and
|
||||
// additional dumping of traits data for tested types (David
|
||||
// Abrahams).
|
||||
// 21 Jan 2001 Initial version (David Abrahams)
|
||||
|
||||
#include <boost/detail/numeric_traits.hpp>
|
||||
#include <cassert>
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <climits>
|
||||
#include <typeinfo>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#ifndef BOOST_NO_LIMITS
|
||||
# include <limits>
|
||||
#endif
|
||||
|
||||
// =================================================================================
|
||||
// template class complement_traits<Number> --
|
||||
//
|
||||
// statically computes the max and min for 1s and 2s-complement binary
|
||||
// numbers. This helps on platforms without <limits> support. It also shows
|
||||
// an example of a recursive template that works with MSVC!
|
||||
//
|
||||
|
||||
template <unsigned size> struct complement; // forward
|
||||
|
||||
// The template complement, below, does all the real work, using "poor man's
|
||||
// partial specialization". We need complement_traits_aux<> so that MSVC doesn't
|
||||
// complain about undefined min/max as we're trying to recursively define them.
|
||||
template <class Number, unsigned size>
|
||||
struct complement_traits_aux
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(Number, max = complement<size>::template traits<Number>::max);
|
||||
BOOST_STATIC_CONSTANT(Number, min = complement<size>::template traits<Number>::min);
|
||||
};
|
||||
|
||||
template <unsigned size>
|
||||
struct complement
|
||||
{
|
||||
template <class Number>
|
||||
struct traits
|
||||
{
|
||||
private:
|
||||
// indirection through complement_traits_aux neccessary to keep MSVC happy
|
||||
typedef complement_traits_aux<Number, size - 1> prev;
|
||||
public:
|
||||
BOOST_STATIC_CONSTANT(Number, max =
|
||||
Number(Number(prev::max) << CHAR_BIT)
|
||||
+ Number(UCHAR_MAX));
|
||||
|
||||
BOOST_STATIC_CONSTANT(Number, min = Number(Number(prev::min) << CHAR_BIT));
|
||||
};
|
||||
};
|
||||
|
||||
// Template class complement_base<> -- defines values for min and max for
|
||||
// complement<1>, at the deepest level of recursion. Uses "poor man's partial
|
||||
// specialization" again.
|
||||
template <bool is_signed> struct complement_base;
|
||||
|
||||
template <> struct complement_base<false>
|
||||
{
|
||||
template <class Number>
|
||||
struct values
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(Number, min = 0);
|
||||
BOOST_STATIC_CONSTANT(Number, max = UCHAR_MAX);
|
||||
};
|
||||
};
|
||||
|
||||
template <> struct complement_base<true>
|
||||
{
|
||||
template <class Number>
|
||||
struct values
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(Number, min = SCHAR_MIN);
|
||||
BOOST_STATIC_CONSTANT(Number, max = SCHAR_MAX);
|
||||
};
|
||||
};
|
||||
|
||||
// Base specialization of complement, puts an end to the recursion.
|
||||
template <>
|
||||
struct complement<1>
|
||||
{
|
||||
template <class Number>
|
||||
struct traits
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(bool, is_signed = boost::detail::is_signed<Number>::value);
|
||||
BOOST_STATIC_CONSTANT(Number, min =
|
||||
complement_base<is_signed>::template values<Number>::min);
|
||||
BOOST_STATIC_CONSTANT(Number, max =
|
||||
complement_base<is_signed>::template values<Number>::max);
|
||||
};
|
||||
};
|
||||
|
||||
// Now here's the "pretty" template you're intended to actually use.
|
||||
// complement_traits<Number>::min, complement_traits<Number>::max are the
|
||||
// minimum and maximum values of Number if Number is a built-in integer type.
|
||||
template <class Number>
|
||||
struct complement_traits
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(Number, max = (complement_traits_aux<Number, sizeof(Number)>::max));
|
||||
BOOST_STATIC_CONSTANT(Number, min = (complement_traits_aux<Number, sizeof(Number)>::min));
|
||||
};
|
||||
|
||||
// =================================================================================
|
||||
|
||||
// Support for streaming various numeric types in exactly the format I want. I
|
||||
// needed this in addition to all the assertions so that I could see exactly
|
||||
// what was going on.
|
||||
//
|
||||
// Numbers go through a 2-stage conversion process (by default, though, no real
|
||||
// conversion).
|
||||
//
|
||||
template <class T> struct stream_as {
|
||||
typedef T t1;
|
||||
typedef T t2;
|
||||
};
|
||||
|
||||
// char types first get converted to unsigned char, then to unsigned.
|
||||
template <> struct stream_as<char> {
|
||||
typedef unsigned char t1;
|
||||
typedef unsigned t2;
|
||||
};
|
||||
template <> struct stream_as<unsigned char> {
|
||||
typedef unsigned char t1; typedef unsigned t2;
|
||||
};
|
||||
template <> struct stream_as<signed char> {
|
||||
typedef unsigned char t1; typedef unsigned t2;
|
||||
};
|
||||
|
||||
#if defined(BOOST_MSVC_STD_ITERATOR) // No intmax streaming built-in
|
||||
|
||||
// With this library implementation, __int64 and __uint64 get streamed as strings
|
||||
template <> struct stream_as<boost::uintmax_t> {
|
||||
typedef std::string t1;
|
||||
typedef std::string t2;
|
||||
};
|
||||
|
||||
template <> struct stream_as<boost::intmax_t> {
|
||||
typedef std::string t1;
|
||||
typedef std::string t2;
|
||||
};
|
||||
#endif
|
||||
|
||||
// Standard promotion process for streaming
|
||||
template <class T> struct promote
|
||||
{
|
||||
static typename stream_as<T>::t1 from(T x) {
|
||||
typedef typename stream_as<T>::t1 t1;
|
||||
return t1(x);
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(BOOST_MSVC_STD_ITERATOR) // No intmax streaming built-in
|
||||
|
||||
// On this platform, stream them as long/unsigned long if they fit.
|
||||
// Otherwise, write a string.
|
||||
template <> struct promote<boost::uintmax_t> {
|
||||
std::string static from(const boost::uintmax_t x) {
|
||||
if (x > ULONG_MAX)
|
||||
return std::string("large unsigned value");
|
||||
else
|
||||
return boost::lexical_cast<std::string>((unsigned long)x);
|
||||
}
|
||||
};
|
||||
template <> struct promote<boost::intmax_t> {
|
||||
std::string static from(const boost::intmax_t x) {
|
||||
if (x > boost::intmax_t(ULONG_MAX))
|
||||
return std::string("large positive signed value");
|
||||
else if (x >= 0)
|
||||
return boost::lexical_cast<std::string>((unsigned long)x);
|
||||
|
||||
if (x < boost::intmax_t(LONG_MIN))
|
||||
return std::string("large negative signed value");
|
||||
else
|
||||
return boost::lexical_cast<std::string>((long)x);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
// This is the function which converts types to the form I want to stream them in.
|
||||
template <class T>
|
||||
typename stream_as<T>::t2 stream_number(T x)
|
||||
{
|
||||
return promote<T>::from(x);
|
||||
}
|
||||
// =================================================================================
|
||||
|
||||
//
|
||||
// Tests for built-in signed and unsigned types
|
||||
//
|
||||
|
||||
// Tag types for selecting tests
|
||||
struct unsigned_tag {};
|
||||
struct signed_tag {};
|
||||
|
||||
// Tests for unsigned numbers. The extra default Number parameter works around
|
||||
// an MSVC bug.
|
||||
template <class Number>
|
||||
void test_aux(unsigned_tag, Number* = 0)
|
||||
{
|
||||
typedef typename boost::detail::numeric_traits<Number>::difference_type difference_type;
|
||||
BOOST_STATIC_ASSERT(!boost::detail::is_signed<Number>::value);
|
||||
BOOST_STATIC_ASSERT(
|
||||
(sizeof(Number) < sizeof(boost::intmax_t))
|
||||
| (boost::is_same<difference_type, boost::intmax_t>::value));
|
||||
|
||||
// Force casting to Number here to work around the fact that it's an enum on MSVC
|
||||
BOOST_STATIC_ASSERT(Number(complement_traits<Number>::max) > Number(0));
|
||||
BOOST_STATIC_ASSERT(Number(complement_traits<Number>::min) == Number(0));
|
||||
|
||||
const Number max = complement_traits<Number>::max;
|
||||
const Number min = complement_traits<Number>::min;
|
||||
|
||||
const Number test_max = (sizeof(Number) < sizeof(boost::intmax_t))
|
||||
? max
|
||||
: max / 2 - 1;
|
||||
|
||||
std::cout << std::hex << "(unsigned) min = " << stream_number(min) << ", max = "
|
||||
<< stream_number(max) << "..." << std::flush;
|
||||
std::cout << "difference_type = " << typeid(difference_type).name() << "..."
|
||||
<< std::flush;
|
||||
|
||||
difference_type d1 = boost::detail::numeric_distance(Number(0), test_max);
|
||||
difference_type d2 = boost::detail::numeric_distance(test_max, Number(0));
|
||||
|
||||
std::cout << "0->" << stream_number(test_max) << "==" << std::dec << stream_number(d1) << "; "
|
||||
<< std::hex << stream_number(test_max) << "->0==" << std::dec << stream_number(d2) << "..." << std::flush;
|
||||
|
||||
assert(d1 == difference_type(test_max));
|
||||
assert(d2 == -difference_type(test_max));
|
||||
}
|
||||
|
||||
// Tests for signed numbers. The extra default Number parameter works around an
|
||||
// MSVC bug.
|
||||
struct out_of_range_tag {};
|
||||
struct in_range_tag {};
|
||||
|
||||
// This test morsel gets executed for numbers whose difference will always be
|
||||
// representable in intmax_t
|
||||
template <class Number>
|
||||
void signed_test(in_range_tag, Number* = 0)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(boost::detail::is_signed<Number>::value);
|
||||
typedef typename boost::detail::numeric_traits<Number>::difference_type difference_type;
|
||||
const Number max = complement_traits<Number>::max;
|
||||
const Number min = complement_traits<Number>::min;
|
||||
|
||||
difference_type d1 = boost::detail::numeric_distance(min, max);
|
||||
difference_type d2 = boost::detail::numeric_distance(max, min);
|
||||
|
||||
std::cout << stream_number(min) << "->" << stream_number(max) << "==";
|
||||
std::cout << std::dec << stream_number(d1) << "; ";
|
||||
std::cout << std::hex << stream_number(max) << "->" << stream_number(min)
|
||||
<< "==" << std::dec << stream_number(d2) << "..." << std::flush;
|
||||
assert(d1 == difference_type(max) - difference_type(min));
|
||||
assert(d2 == difference_type(min) - difference_type(max));
|
||||
}
|
||||
|
||||
// This test morsel gets executed for numbers whose difference may exceed the
|
||||
// capacity of intmax_t.
|
||||
template <class Number>
|
||||
void signed_test(out_of_range_tag, Number* = 0)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(boost::detail::is_signed<Number>::value);
|
||||
typedef typename boost::detail::numeric_traits<Number>::difference_type difference_type;
|
||||
const Number max = complement_traits<Number>::max;
|
||||
const Number min = complement_traits<Number>::min;
|
||||
|
||||
difference_type min_distance = complement_traits<difference_type>::min;
|
||||
difference_type max_distance = complement_traits<difference_type>::max;
|
||||
|
||||
const Number n1 = Number(min + max_distance);
|
||||
const Number n2 = Number(max + min_distance);
|
||||
difference_type d1 = boost::detail::numeric_distance(min, n1);
|
||||
difference_type d2 = boost::detail::numeric_distance(max, n2);
|
||||
|
||||
std::cout << stream_number(min) << "->" << stream_number(n1) << "==";
|
||||
std::cout << std::dec << stream_number(d1) << "; ";
|
||||
std::cout << std::hex << stream_number(max) << "->" << stream_number(n2)
|
||||
<< "==" << std::dec << stream_number(d2) << "..." << std::flush;
|
||||
assert(d1 == max_distance);
|
||||
assert(d2 == min_distance);
|
||||
}
|
||||
|
||||
template <class Number>
|
||||
void test_aux(signed_tag, Number* = 0)
|
||||
{
|
||||
typedef typename boost::detail::numeric_traits<Number>::difference_type difference_type;
|
||||
BOOST_STATIC_ASSERT(boost::detail::is_signed<Number>::value);
|
||||
BOOST_STATIC_ASSERT(
|
||||
(sizeof(Number) < sizeof(boost::intmax_t))
|
||||
| (boost::is_same<difference_type, Number>::value));
|
||||
|
||||
// Force casting to Number here to work around the fact that it's an enum on MSVC
|
||||
BOOST_STATIC_ASSERT(Number(complement_traits<Number>::max) > Number(0));
|
||||
BOOST_STATIC_ASSERT(Number(complement_traits<Number>::min) < Number(0));
|
||||
|
||||
const Number max = complement_traits<Number>::max;
|
||||
const Number min = complement_traits<Number>::min;
|
||||
|
||||
std::cout << std::hex << "min = " << stream_number(min) << ", max = "
|
||||
<< stream_number(max) << "..." << std::flush;
|
||||
std::cout << "difference_type = " << typeid(difference_type).name() << "..."
|
||||
<< std::flush;
|
||||
|
||||
typedef typename boost::detail::if_true<
|
||||
(sizeof(Number) < sizeof(boost::intmax_t))>
|
||||
::template then<
|
||||
in_range_tag,
|
||||
out_of_range_tag
|
||||
>::type
|
||||
range_tag;
|
||||
signed_test<Number>(range_tag());
|
||||
}
|
||||
|
||||
|
||||
// Test for all numbers. The extra default Number parameter works around an MSVC
|
||||
// bug.
|
||||
template <class Number>
|
||||
void test(Number* = 0)
|
||||
{
|
||||
std::cout << "testing " << typeid(Number).name() << ":\n"
|
||||
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
|
||||
<< "is_signed: " << (std::numeric_limits<Number>::is_signed ? "true\n" : "false\n")
|
||||
<< "is_bounded: " << (std::numeric_limits<Number>::is_bounded ? "true\n" : "false\n")
|
||||
<< "digits: " << std::numeric_limits<Number>::digits << "\n"
|
||||
#endif
|
||||
<< "..." << std::flush;
|
||||
|
||||
// factoring out difference_type for the assert below confused Borland :(
|
||||
typedef boost::detail::is_signed<
|
||||
#ifndef BOOST_MSVC
|
||||
typename
|
||||
#endif
|
||||
boost::detail::numeric_traits<Number>::difference_type
|
||||
> is_signed;
|
||||
BOOST_STATIC_ASSERT(is_signed::value);
|
||||
|
||||
typedef typename boost::detail::if_true<
|
||||
boost::detail::is_signed<Number>::value
|
||||
>::template then<signed_tag, unsigned_tag>::type signedness;
|
||||
|
||||
test_aux<Number>(signedness());
|
||||
std::cout << "passed" << std::endl;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test<char>();
|
||||
test<unsigned char>();
|
||||
test<signed char>();
|
||||
test<wchar_t>();
|
||||
test<short>();
|
||||
test<unsigned short>();
|
||||
test<int>();
|
||||
test<unsigned int>();
|
||||
test<long>();
|
||||
test<unsigned long>();
|
||||
#if defined(ULLONG_MAX) || defined(ULONG_LONG_MAX)
|
||||
test<long long>();
|
||||
test<unsigned long long>();
|
||||
#elif defined(BOOST_MSVC)
|
||||
// The problem of not having compile-time static class constants other than
|
||||
// enums prevents this from working, since values get truncated.
|
||||
// test<boost::uintmax_t>();
|
||||
// test<boost::intmax_t>();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
1161
operators.htm
1161
operators.htm
File diff suppressed because it is too large
Load Diff
@ -1,657 +0,0 @@
|
||||
// Demonstrate and test boost/operators.hpp -------------------------------//
|
||||
|
||||
// (C) Copyright Beman Dawes 1999. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
// Revision History
|
||||
// 20 May 01 Output progress messages. Added tests for new operator
|
||||
// templates. Updated random number generator. Changed tests to
|
||||
// use Boost Test Tools library. (Daryle Walker)
|
||||
// 04 Jun 00 Added regression test for a bug I found (David Abrahams)
|
||||
// 17 Jun 00 Fix for broken compilers (Aleksey Gurtovoy)
|
||||
// ?? ??? 00 Major update to randomly test all one- and two- argument forms by
|
||||
// wrapping integral types and comparing the results of operations
|
||||
// to the results for the raw types (David Abrahams)
|
||||
// 12 Dec 99 Minor update, output confirmation message.
|
||||
// 15 Nov 99 Initial version
|
||||
|
||||
#define BOOST_INCLUDE_MAIN
|
||||
|
||||
#include <boost/config.hpp> // for BOOST_MSVC
|
||||
#include <boost/cstdlib.hpp> // for boost::exit_success
|
||||
#include <boost/operators.hpp> // for the tested items
|
||||
#include <boost/random/linear_congruential.hpp> // for boost::minstd_rand
|
||||
#include <boost/test/test_tools.hpp> // for main
|
||||
|
||||
#include <iostream> // for std::cout (std::endl indirectly)
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
// avoiding a template version of true_value so as to not confuse VC++
|
||||
int true_value(int x) { return x; }
|
||||
long true_value(long x) { return x; }
|
||||
signed char true_value(signed char x) { return x; }
|
||||
short true_value(short x) { return x; }
|
||||
unsigned int true_value(unsigned int x) { return x; }
|
||||
unsigned long true_value(unsigned long x) { return x; }
|
||||
unsigned char true_value(unsigned char x) { return x; }
|
||||
unsigned short true_value(unsigned short x) { return x; }
|
||||
|
||||
// The use of operators<> here tended to obscure
|
||||
// interactions with certain compiler bugs
|
||||
template <class T>
|
||||
class Wrapped1
|
||||
: boost::operators<Wrapped1<T> >
|
||||
, boost::shiftable<Wrapped1<T> >
|
||||
{
|
||||
public:
|
||||
explicit Wrapped1( T v = T() ) : _value(v) {}
|
||||
T value() const { return _value; }
|
||||
|
||||
bool operator<(const Wrapped1& x) const { return _value < x._value; }
|
||||
bool operator==(const Wrapped1& x) const { return _value == x._value; }
|
||||
|
||||
Wrapped1& operator+=(const Wrapped1& x)
|
||||
{ _value += x._value; return *this; }
|
||||
Wrapped1& operator-=(const Wrapped1& x)
|
||||
{ _value -= x._value; return *this; }
|
||||
Wrapped1& operator*=(const Wrapped1& x)
|
||||
{ _value *= x._value; return *this; }
|
||||
Wrapped1& operator/=(const Wrapped1& x)
|
||||
{ _value /= x._value; return *this; }
|
||||
Wrapped1& operator%=(const Wrapped1& x)
|
||||
{ _value %= x._value; return *this; }
|
||||
Wrapped1& operator|=(const Wrapped1& x)
|
||||
{ _value |= x._value; return *this; }
|
||||
Wrapped1& operator&=(const Wrapped1& x)
|
||||
{ _value &= x._value; return *this; }
|
||||
Wrapped1& operator^=(const Wrapped1& x)
|
||||
{ _value ^= x._value; return *this; }
|
||||
Wrapped1& operator<<=(const Wrapped1& x)
|
||||
{ _value <<= x._value; return *this; }
|
||||
Wrapped1& operator>>=(const Wrapped1& x)
|
||||
{ _value >>= x._value; return *this; }
|
||||
Wrapped1& operator++() { ++_value; return *this; }
|
||||
Wrapped1& operator--() { --_value; return *this; }
|
||||
|
||||
private:
|
||||
T _value;
|
||||
};
|
||||
template <class T>
|
||||
T true_value(Wrapped1<T> x) { return x.value(); }
|
||||
|
||||
template <class T, class U>
|
||||
class Wrapped2
|
||||
: boost::operators<Wrapped2<T, U> >
|
||||
, boost::operators2<Wrapped2<T, U>, U>
|
||||
, boost::shiftable1<Wrapped2<T, U>
|
||||
, boost::shiftable2<Wrapped2<T, U>, U > >
|
||||
{
|
||||
public:
|
||||
explicit Wrapped2( T v = T() ) : _value(v) {}
|
||||
T value() const { return _value; }
|
||||
|
||||
bool operator<(const Wrapped2& x) const { return _value < x._value; }
|
||||
bool operator==(const Wrapped2& x) const { return _value == x._value; }
|
||||
|
||||
Wrapped2& operator+=(const Wrapped2& x)
|
||||
{ _value += x._value; return *this; }
|
||||
Wrapped2& operator-=(const Wrapped2& x)
|
||||
{ _value -= x._value; return *this; }
|
||||
Wrapped2& operator*=(const Wrapped2& x)
|
||||
{ _value *= x._value; return *this; }
|
||||
Wrapped2& operator/=(const Wrapped2& x)
|
||||
{ _value /= x._value; return *this; }
|
||||
Wrapped2& operator%=(const Wrapped2& x)
|
||||
{ _value %= x._value; return *this; }
|
||||
Wrapped2& operator|=(const Wrapped2& x)
|
||||
{ _value |= x._value; return *this; }
|
||||
Wrapped2& operator&=(const Wrapped2& x)
|
||||
{ _value &= x._value; return *this; }
|
||||
Wrapped2& operator^=(const Wrapped2& x)
|
||||
{ _value ^= x._value; return *this; }
|
||||
Wrapped2& operator<<=(const Wrapped2& x)
|
||||
{ _value <<= x._value; return *this; }
|
||||
Wrapped2& operator>>=(const Wrapped2& x)
|
||||
{ _value >>= x._value; return *this; }
|
||||
Wrapped2& operator++() { ++_value; return *this; }
|
||||
Wrapped2& operator--() { --_value; return *this; }
|
||||
|
||||
bool operator<(U u) const { return _value < u; }
|
||||
bool operator>(U u) const { return _value > u; }
|
||||
bool operator==(U u) const { return _value == u; }
|
||||
Wrapped2& operator+=(U u) { _value += u; return *this; }
|
||||
Wrapped2& operator-=(U u) { _value -= u; return *this; }
|
||||
Wrapped2& operator*=(U u) { _value *= u; return *this; }
|
||||
Wrapped2& operator/=(U u) { _value /= u; return *this; }
|
||||
Wrapped2& operator%=(U u) { _value %= u; return *this; }
|
||||
Wrapped2& operator|=(U u) { _value |= u; return *this; }
|
||||
Wrapped2& operator&=(U u) { _value &= u; return *this; }
|
||||
Wrapped2& operator^=(U u) { _value ^= u; return *this; }
|
||||
Wrapped2& operator<<=(U u) { _value <<= u; return *this; }
|
||||
Wrapped2& operator>>=(U u) { _value >>= u; return *this; }
|
||||
|
||||
private:
|
||||
T _value;
|
||||
};
|
||||
template <class T, class U>
|
||||
T true_value(Wrapped2<T,U> x) { return x.value(); }
|
||||
|
||||
template <class T>
|
||||
class Wrapped3
|
||||
: boost::equivalent<Wrapped3<T> >
|
||||
, boost::partially_ordered<Wrapped3<T> >
|
||||
, boost::equality_comparable<Wrapped3<T> >
|
||||
{
|
||||
public:
|
||||
explicit Wrapped3( T v = T() ) : _value(v) {}
|
||||
T value() const { return _value; }
|
||||
|
||||
bool operator<(const Wrapped3& x) const { return _value < x._value; }
|
||||
|
||||
private:
|
||||
T _value;
|
||||
};
|
||||
template <class T>
|
||||
T true_value(Wrapped3<T> x) { return x.value(); }
|
||||
|
||||
template <class T, class U>
|
||||
class Wrapped4
|
||||
: boost::equality_comparable1<Wrapped4<T, U>
|
||||
, boost::equivalent1<Wrapped4<T, U>
|
||||
, boost::partially_ordered1<Wrapped4<T, U> > > >
|
||||
, boost::partially_ordered2<Wrapped4<T, U>, U
|
||||
, boost::equivalent2<Wrapped4<T, U>, U
|
||||
, boost::equality_comparable2<Wrapped4<T, U>, U> > >
|
||||
{
|
||||
public:
|
||||
explicit Wrapped4( T v = T() ) : _value(v) {}
|
||||
T value() const { return _value; }
|
||||
|
||||
bool operator<(const Wrapped4& x) const { return _value < x._value; }
|
||||
|
||||
bool operator<(U u) const { return _value < u; }
|
||||
bool operator>(U u) const { return _value > u; }
|
||||
|
||||
private:
|
||||
T _value;
|
||||
};
|
||||
template <class T, class U>
|
||||
T true_value(Wrapped4<T,U> x) { return x.value(); }
|
||||
|
||||
// MyInt uses only the single template-argument form of all_operators<>
|
||||
typedef Wrapped1<int> MyInt;
|
||||
|
||||
typedef Wrapped2<long, long> MyLong;
|
||||
|
||||
typedef Wrapped3<signed char> MyChar;
|
||||
|
||||
typedef Wrapped4<short, short> MyShort;
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void sanity_check(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
BOOST_TEST( true_value(y1) == true_value(y2) );
|
||||
BOOST_TEST( true_value(x1) == true_value(x2) );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_less_than_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
BOOST_TEST( (x1 < y1) == (x2 < y2) );
|
||||
BOOST_TEST( (x1 <= y1) == (x2 <= y2) );
|
||||
BOOST_TEST( (x1 >= y1) == (x2 >= y2) );
|
||||
BOOST_TEST( (x1 > y1) == (x2 > y2) );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_less_than_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
sanity_check( x1, y1, x2, y2 );
|
||||
test_less_than_comparable_aux( x1, y1, x2, y2 );
|
||||
test_less_than_comparable_aux( y1, x1, y2, x2 );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_equality_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
BOOST_TEST( (x1 == y1) == (x2 == y2) );
|
||||
BOOST_TEST( (x1 != y1) == (x2 != y2) );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_equality_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
sanity_check( x1, y1, x2, y2 );
|
||||
test_equality_comparable_aux( x1, y1, x2, y2 );
|
||||
test_equality_comparable_aux( y1, x1, y2, x2 );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_multipliable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
BOOST_TEST( (x1 * y1).value() == (x2 * y2) );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_multipliable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
sanity_check( x1, y1, x2, y2 );
|
||||
test_multipliable_aux( x1, y1, x2, y2 );
|
||||
test_multipliable_aux( y1, x1, y2, x2 );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_addable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
BOOST_TEST( (x1 + y1).value() == (x2 + y2) );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_addable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
sanity_check( x1, y1, x2, y2 );
|
||||
test_addable_aux( x1, y1, x2, y2 );
|
||||
test_addable_aux( y1, x1, y2, x2 );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_subtractable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
sanity_check( x1, y1, x2, y2 );
|
||||
BOOST_TEST( (x1 - y1).value() == (x2 - y2) );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_dividable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
sanity_check( x1, y1, x2, y2 );
|
||||
if ( y2 != 0 )
|
||||
BOOST_TEST( (x1 / y1).value() == (x2 / y2) );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_modable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
sanity_check( x1, y1, x2, y2 );
|
||||
if ( y2 != 0 )
|
||||
BOOST_TEST( (x1 % y1).value() == (x2 % y2) );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_xorable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
BOOST_TEST( (x1 ^ y1).value() == (x2 ^ y2) );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_xorable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
sanity_check( x1, y1, x2, y2 );
|
||||
test_xorable_aux( x1, y1, x2, y2 );
|
||||
test_xorable_aux( y1, x1, y2, x2 );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_andable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
BOOST_TEST( (x1 & y1).value() == (x2 & y2) );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_andable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
sanity_check( x1, y1, x2, y2 );
|
||||
test_andable_aux( x1, y1, x2, y2 );
|
||||
test_andable_aux( y1, x1, y2, x2 );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_orable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
BOOST_TEST( (x1 | y1).value() == (x2 | y2) );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_orable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
sanity_check( x1, y1, x2, y2 );
|
||||
test_orable_aux( x1, y1, x2, y2 );
|
||||
test_orable_aux( y1, x1, y2, x2 );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_left_shiftable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
sanity_check( x1, y1, x2, y2 );
|
||||
BOOST_TEST( (x1 << y1).value() == (x2 << y2) );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_right_shiftable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
sanity_check( x1, y1, x2, y2 );
|
||||
BOOST_TEST( (x1 >> y1).value() == (x2 >> y2) );
|
||||
}
|
||||
|
||||
template <class X1, class X2>
|
||||
void test_incrementable(X1 x1, X2 x2)
|
||||
{
|
||||
sanity_check( x1, x1, x2, x2 );
|
||||
BOOST_TEST( (x1++).value() == x2++ );
|
||||
BOOST_TEST( x1.value() == x2 );
|
||||
}
|
||||
|
||||
template <class X1, class X2>
|
||||
void test_decrementable(X1 x1, X2 x2)
|
||||
{
|
||||
sanity_check( x1, x1, x2, x2 );
|
||||
BOOST_TEST( (x1--).value() == x2-- );
|
||||
BOOST_TEST( x1.value() == x2 );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_all(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
test_less_than_comparable( x1, y1, x2, y2 );
|
||||
test_equality_comparable( x1, y1, x2, y2 );
|
||||
test_multipliable( x1, y1, x2, y2 );
|
||||
test_addable( x1, y1, x2, y2 );
|
||||
test_subtractable( x1, y1, x2, y2 );
|
||||
test_dividable( x1, y1, x2, y2 );
|
||||
test_modable( x1, y1, x2, y2 );
|
||||
test_xorable( x1, y1, x2, y2 );
|
||||
test_andable( x1, y1, x2, y2 );
|
||||
test_orable( x1, y1, x2, y2 );
|
||||
test_left_shiftable( x1, y1, x2, y2 );
|
||||
test_right_shiftable( x1, y1, x2, y2 );
|
||||
test_incrementable( x1, x2 );
|
||||
test_decrementable( x1, x2 );
|
||||
}
|
||||
|
||||
template <class Big, class Small>
|
||||
struct tester
|
||||
{
|
||||
void operator()(boost::minstd_rand& randomizer) const
|
||||
{
|
||||
Big b1 = Big( randomizer() );
|
||||
Big b2 = Big( randomizer() );
|
||||
Small s = Small( randomizer() );
|
||||
|
||||
test_all( Wrapped1<Big>(b1), Wrapped1<Big>(b2), b1, b2 );
|
||||
test_all( Wrapped2<Big, Small>(b1), s, b1, s );
|
||||
}
|
||||
};
|
||||
|
||||
// added as a regression test. We had a bug which this uncovered.
|
||||
struct Point
|
||||
: boost::addable<Point
|
||||
, boost::subtractable<Point> >
|
||||
{
|
||||
Point( int h, int v ) : h(h), v(v) {}
|
||||
Point() :h(0), v(0) {}
|
||||
const Point& operator+=( const Point& rhs )
|
||||
{ h += rhs.h; v += rhs.v; return *this; }
|
||||
const Point& operator-=( const Point& rhs )
|
||||
{ h -= rhs.h; v -= rhs.v; return *this; }
|
||||
|
||||
int h;
|
||||
int v;
|
||||
};
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
|
||||
// workaround for MSVC bug; for some reasons the compiler doesn't instantiate
|
||||
// inherited operator templates at the moment it must, so the following
|
||||
// explicit instantiations force it to do that.
|
||||
|
||||
#if defined(BOOST_MSVC) && (_MSC_VER <= 1200)
|
||||
template Wrapped1<int>;
|
||||
template Wrapped1<long>;
|
||||
template Wrapped1<unsigned int>;
|
||||
template Wrapped1<unsigned long>;
|
||||
|
||||
template Wrapped2<int, int>;
|
||||
template Wrapped2<int, signed char>;
|
||||
template Wrapped2<long, signed char>;
|
||||
template Wrapped2<long, int>;
|
||||
template Wrapped2<long, long>;
|
||||
template Wrapped2<unsigned int, unsigned int>;
|
||||
template Wrapped2<unsigned int, unsigned char>;
|
||||
template Wrapped2<unsigned long, unsigned int>;
|
||||
template Wrapped2<unsigned long, unsigned char>;
|
||||
template Wrapped2<unsigned long, unsigned long>;
|
||||
#endif
|
||||
|
||||
#define PRIVATE_EXPR_TEST(e, t) BOOST_TEST( ((e), (t)) )
|
||||
|
||||
|
||||
int
|
||||
test_main( int , char * [] )
|
||||
{
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
// Regression test.
|
||||
Point x;
|
||||
x = x + Point(3, 4);
|
||||
x = x - Point(3, 4);
|
||||
|
||||
cout << "Created point, and operated on it." << endl;
|
||||
|
||||
for (int n = 0; n < 10000; ++n)
|
||||
{
|
||||
boost::minstd_rand r;
|
||||
tester<long, int>()(r);
|
||||
tester<long, signed char>()(r);
|
||||
tester<long, long>()(r);
|
||||
tester<int, int>()(r);
|
||||
tester<int, signed char>()(r);
|
||||
|
||||
tester<unsigned long, unsigned int>()(r);
|
||||
tester<unsigned long, unsigned char>()(r);
|
||||
tester<unsigned long, unsigned long>()(r);
|
||||
tester<unsigned int, unsigned int>()(r);
|
||||
tester<unsigned int, unsigned char>()(r);
|
||||
}
|
||||
|
||||
cout << "Did random tester loop." << endl;
|
||||
|
||||
MyInt i1(1);
|
||||
MyInt i2(2);
|
||||
MyInt i;
|
||||
|
||||
BOOST_TEST( i1.value() == 1 );
|
||||
BOOST_TEST( i2.value() == 2 );
|
||||
BOOST_TEST( i.value() == 0 );
|
||||
|
||||
cout << "Created MyInt objects.\n";
|
||||
|
||||
PRIVATE_EXPR_TEST( (i = i2), (i.value() == 2) );
|
||||
|
||||
BOOST_TEST( i2 == i );
|
||||
BOOST_TEST( i1 != i2 );
|
||||
BOOST_TEST( i1 < i2 );
|
||||
BOOST_TEST( i1 <= i2 );
|
||||
BOOST_TEST( i <= i2 );
|
||||
BOOST_TEST( i2 > i1 );
|
||||
BOOST_TEST( i2 >= i1 );
|
||||
BOOST_TEST( i2 >= i );
|
||||
|
||||
PRIVATE_EXPR_TEST( (i = i1 + i2), (i.value() == 3) );
|
||||
PRIVATE_EXPR_TEST( (i = i + i2), (i.value() == 5) );
|
||||
PRIVATE_EXPR_TEST( (i = i - i1), (i.value() == 4) );
|
||||
PRIVATE_EXPR_TEST( (i = i * i2), (i.value() == 8) );
|
||||
PRIVATE_EXPR_TEST( (i = i / i2), (i.value() == 4) );
|
||||
PRIVATE_EXPR_TEST( (i = i % ( i - i1 )), (i.value() == 1) );
|
||||
PRIVATE_EXPR_TEST( (i = i2 + i2), (i.value() == 4) );
|
||||
PRIVATE_EXPR_TEST( (i = i1 | i2 | i), (i.value() == 7) );
|
||||
PRIVATE_EXPR_TEST( (i = i & i2), (i.value() == 2) );
|
||||
PRIVATE_EXPR_TEST( (i = i + i1), (i.value() == 3) );
|
||||
PRIVATE_EXPR_TEST( (i = i ^ i1), (i.value() == 2) );
|
||||
PRIVATE_EXPR_TEST( (i = ( i + i1 ) * ( i2 | i1 )), (i.value() == 9) );
|
||||
|
||||
PRIVATE_EXPR_TEST( (i = i1 << i2), (i.value() == 4) );
|
||||
PRIVATE_EXPR_TEST( (i = i2 >> i1), (i.value() == 1) );
|
||||
|
||||
cout << "Performed tests on MyInt objects.\n";
|
||||
|
||||
MyLong j1(1);
|
||||
MyLong j2(2);
|
||||
MyLong j;
|
||||
|
||||
BOOST_TEST( j1.value() == 1 );
|
||||
BOOST_TEST( j2.value() == 2 );
|
||||
BOOST_TEST( j.value() == 0 );
|
||||
|
||||
cout << "Created MyLong objects.\n";
|
||||
|
||||
PRIVATE_EXPR_TEST( (j = j2), (j.value() == 2) );
|
||||
|
||||
BOOST_TEST( j2 == j );
|
||||
BOOST_TEST( 2 == j );
|
||||
BOOST_TEST( j2 == 2 );
|
||||
BOOST_TEST( j == j2 );
|
||||
BOOST_TEST( j1 != j2 );
|
||||
BOOST_TEST( j1 != 2 );
|
||||
BOOST_TEST( 1 != j2 );
|
||||
BOOST_TEST( j1 < j2 );
|
||||
BOOST_TEST( 1 < j2 );
|
||||
BOOST_TEST( j1 < 2 );
|
||||
BOOST_TEST( j1 <= j2 );
|
||||
BOOST_TEST( 1 <= j2 );
|
||||
BOOST_TEST( j1 <= j );
|
||||
BOOST_TEST( j <= j2 );
|
||||
BOOST_TEST( 2 <= j2 );
|
||||
BOOST_TEST( j <= 2 );
|
||||
BOOST_TEST( j2 > j1 );
|
||||
BOOST_TEST( 2 > j1 );
|
||||
BOOST_TEST( j2 > 1 );
|
||||
BOOST_TEST( j2 >= j1 );
|
||||
BOOST_TEST( 2 >= j1 );
|
||||
BOOST_TEST( j2 >= 1 );
|
||||
BOOST_TEST( j2 >= j );
|
||||
BOOST_TEST( 2 >= j );
|
||||
BOOST_TEST( j2 >= 2 );
|
||||
|
||||
BOOST_TEST( (j1 + 2) == 3 );
|
||||
BOOST_TEST( (1 + j2) == 3 );
|
||||
PRIVATE_EXPR_TEST( (j = j1 + j2), (j.value() == 3) );
|
||||
|
||||
BOOST_TEST( (j + 2) == 5 );
|
||||
BOOST_TEST( (3 + j2) == 5 );
|
||||
PRIVATE_EXPR_TEST( (j = j + j2), (j.value() == 5) );
|
||||
|
||||
BOOST_TEST( (j - 1) == 4 );
|
||||
PRIVATE_EXPR_TEST( (j = j - j1), (j.value() == 4) );
|
||||
|
||||
BOOST_TEST( (j * 2) == 8 );
|
||||
BOOST_TEST( (4 * j2) == 8 );
|
||||
PRIVATE_EXPR_TEST( (j = j * j2), (j.value() == 8) );
|
||||
|
||||
BOOST_TEST( (j / 2) == 4 );
|
||||
PRIVATE_EXPR_TEST( (j = j / j2), (j.value() == 4) );
|
||||
|
||||
BOOST_TEST( (j % 3) == 1 );
|
||||
PRIVATE_EXPR_TEST( (j = j % ( j - j1 )), (j.value() == 1) );
|
||||
|
||||
PRIVATE_EXPR_TEST( (j = j2 + j2), (j.value() == 4) );
|
||||
|
||||
BOOST_TEST( (1 | j2 | j) == 7 );
|
||||
BOOST_TEST( (j1 | 2 | j) == 7 );
|
||||
BOOST_TEST( (j1 | j2 | 4) == 7 );
|
||||
PRIVATE_EXPR_TEST( (j = j1 | j2 | j), (j.value() == 7) );
|
||||
|
||||
BOOST_TEST( (7 & j2) == 2 );
|
||||
BOOST_TEST( (j & 2) == 2 );
|
||||
PRIVATE_EXPR_TEST( (j = j & j2), (j.value() == 2) );
|
||||
|
||||
PRIVATE_EXPR_TEST( (j = j | j1), (j.value() == 3) );
|
||||
|
||||
BOOST_TEST( (3 ^ j1) == 2 );
|
||||
BOOST_TEST( (j ^ 1) == 2 );
|
||||
PRIVATE_EXPR_TEST( (j = j ^ j1), (j.value() == 2) );
|
||||
|
||||
PRIVATE_EXPR_TEST( (j = ( j + j1 ) * ( j2 | j1 )), (j.value() == 9) );
|
||||
|
||||
BOOST_TEST( (j1 << 2) == 4 );
|
||||
BOOST_TEST( (j2 << 1) == 4 );
|
||||
PRIVATE_EXPR_TEST( (j = j1 << j2), (j.value() == 4) );
|
||||
|
||||
BOOST_TEST( (j >> 2) == 1 );
|
||||
BOOST_TEST( (j2 >> 1) == 1 );
|
||||
PRIVATE_EXPR_TEST( (j = j2 >> j1), (j.value() == 1) );
|
||||
|
||||
cout << "Performed tests on MyLong objects.\n";
|
||||
|
||||
MyChar k1(1);
|
||||
MyChar k2(2);
|
||||
MyChar k;
|
||||
|
||||
BOOST_TEST( k1.value() == 1 );
|
||||
BOOST_TEST( k2.value() == 2 );
|
||||
BOOST_TEST( k.value() == 0 );
|
||||
|
||||
cout << "Created MyChar objects.\n";
|
||||
|
||||
PRIVATE_EXPR_TEST( (k = k2), (k.value() == 2) );
|
||||
|
||||
BOOST_TEST( k2 == k );
|
||||
BOOST_TEST( k1 != k2 );
|
||||
BOOST_TEST( k1 < k2 );
|
||||
BOOST_TEST( k1 <= k2 );
|
||||
BOOST_TEST( k <= k2 );
|
||||
BOOST_TEST( k2 > k1 );
|
||||
BOOST_TEST( k2 >= k1 );
|
||||
BOOST_TEST( k2 >= k );
|
||||
|
||||
cout << "Performed tests on MyChar objects.\n";
|
||||
|
||||
MyShort l1(1);
|
||||
MyShort l2(2);
|
||||
MyShort l;
|
||||
|
||||
BOOST_TEST( l1.value() == 1 );
|
||||
BOOST_TEST( l2.value() == 2 );
|
||||
BOOST_TEST( l.value() == 0 );
|
||||
|
||||
cout << "Created MyShort objects.\n";
|
||||
|
||||
PRIVATE_EXPR_TEST( (l = l2), (l.value() == 2) );
|
||||
|
||||
BOOST_TEST( l2 == l );
|
||||
BOOST_TEST( 2 == l );
|
||||
BOOST_TEST( l2 == 2 );
|
||||
BOOST_TEST( l == l2 );
|
||||
BOOST_TEST( l1 != l2 );
|
||||
BOOST_TEST( l1 != 2 );
|
||||
BOOST_TEST( 1 != l2 );
|
||||
BOOST_TEST( l1 < l2 );
|
||||
BOOST_TEST( 1 < l2 );
|
||||
BOOST_TEST( l1 < 2 );
|
||||
BOOST_TEST( l1 <= l2 );
|
||||
BOOST_TEST( 1 <= l2 );
|
||||
BOOST_TEST( l1 <= l );
|
||||
BOOST_TEST( l <= l2 );
|
||||
BOOST_TEST( 2 <= l2 );
|
||||
BOOST_TEST( l <= 2 );
|
||||
BOOST_TEST( l2 > l1 );
|
||||
BOOST_TEST( 2 > l1 );
|
||||
BOOST_TEST( l2 > 1 );
|
||||
BOOST_TEST( l2 >= l1 );
|
||||
BOOST_TEST( 2 >= l1 );
|
||||
BOOST_TEST( l2 >= 1 );
|
||||
BOOST_TEST( l2 >= l );
|
||||
BOOST_TEST( 2 >= l );
|
||||
BOOST_TEST( l2 >= 2 );
|
||||
|
||||
cout << "Performed tests on MyShort objects.\n";
|
||||
|
||||
return boost::exit_success;
|
||||
}
|
@ -1,391 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<title>Projection Iterator Adaptor Documentation</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
|
||||
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)"
|
||||
align="center" width="277" height="86">
|
||||
|
||||
<h1>Projection Iterator Adaptor</h1>
|
||||
|
||||
Defined in header
|
||||
<a href="../../boost/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a>
|
||||
|
||||
<p>
|
||||
The projection iterator adaptor is similar to the <a
|
||||
href="./transform_iterator.htm">transform iterator adaptor</a> in that
|
||||
its <tt>operator*()</tt> applies some function to the result of
|
||||
dereferencing the base iterator and then returns the result. The
|
||||
difference is that the function must return a reference to some
|
||||
existing object (for example, a data member within the
|
||||
<tt>value_type</tt> of the base iterator). The following
|
||||
<b>pseudo-code</b> gives the basic idea. The data member <tt>p</tt> is
|
||||
the function object.
|
||||
|
||||
<pre>
|
||||
reference projection_iterator::operator*() const {
|
||||
return this->p(*this->base_iterator);
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h2>Synopsis</h2>
|
||||
|
||||
<pre>
|
||||
namespace boost {
|
||||
template <class <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>, class BaseIterator>
|
||||
struct projection_iterator_generator;
|
||||
|
||||
template <class <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>,
|
||||
class BaseIterator, class ConstBaseIterator>
|
||||
struct projection_iterator_pair_generator;
|
||||
|
||||
template <class <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>, class BaseIterator>
|
||||
typename projection_iterator_generator<AdaptableUnaryFunction, BaseIterator>::type
|
||||
make_projection_iterator(BaseIterator base,
|
||||
const AdaptableUnaryFunction& p = AdaptableUnaryFunction())
|
||||
|
||||
template <class <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>, class ConstBaseIterator>
|
||||
typename projection_iterator_generator<AdaptableUnaryFunction, ConstBaseIterator>::type
|
||||
make_const_projection_iterator(ConstBaseIterator base,
|
||||
const AdaptableUnaryFunction& p = AdaptableUnaryFunction())
|
||||
}
|
||||
</pre>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2><a name="projection_iterator_generator">The Projection Iterator Type
|
||||
Generator</a></h2>
|
||||
|
||||
The class <tt>projection_iterator_generator</tt> is a helper class
|
||||
whose purpose is to construct an projection iterator type. The main
|
||||
template parameter for this class is the <a
|
||||
href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html"><tt>AdaptableUnaryFunction</tt></a>
|
||||
function object type and the <tt>BaseIterator</tt> type that is being
|
||||
wrapped.
|
||||
|
||||
<pre>
|
||||
template <class <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>, class BaseIterator>
|
||||
class projection_iterator_generator
|
||||
{
|
||||
public:
|
||||
typedef <tt><a href="./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a><...></tt> type; // the resulting projection iterator type
|
||||
};
|
||||
</pre>
|
||||
|
||||
<h3>Example</h3>
|
||||
|
||||
In the following example we have a list of personnel records. Each
|
||||
record has an employee's name and ID number. We want to be able to
|
||||
traverse through the list accessing either the name or the ID numbers
|
||||
of the employees using the projection iterator so we create the
|
||||
function object classes <tt>select_name</tt> and
|
||||
<tt>select_ID</tt>. We then use the
|
||||
<tt>projection_iterator_generator</tt> class to create a projection
|
||||
iterator and use it to print out the names of the employees.
|
||||
|
||||
<pre>
|
||||
#include <boost/config.hpp>
|
||||
#include <list>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <boost/iterator_adaptors.hpp>
|
||||
|
||||
struct personnel_record {
|
||||
personnel_record(std::string n, int id) : m_name(n), m_ID(id) { }
|
||||
std::string m_name;
|
||||
int m_ID;
|
||||
};
|
||||
|
||||
struct select_name {
|
||||
typedef personnel_record argument_type;
|
||||
typedef std::string result_type;
|
||||
const std::string& operator()(const personnel_record& r) const {
|
||||
return r.m_name;
|
||||
}
|
||||
std::string& operator()(personnel_record& r) const {
|
||||
return r.m_name;
|
||||
}
|
||||
};
|
||||
|
||||
struct select_ID {
|
||||
typedef personnel_record argument_type;
|
||||
typedef int result_type;
|
||||
const int& operator()(const personnel_record& r) const {
|
||||
return r.m_ID;
|
||||
}
|
||||
int& operator()(personnel_record& r) const {
|
||||
return r.m_ID;
|
||||
}
|
||||
};
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
std::list<personnel_record> personnel_list;
|
||||
|
||||
personnel_list.push_back(personnel_record("Barney", 13423));
|
||||
personnel_list.push_back(personnel_record("Fred", 12343));
|
||||
personnel_list.push_back(personnel_record("Wilma", 62454));
|
||||
personnel_list.push_back(personnel_record("Betty", 20490));
|
||||
|
||||
// Example of using projection_iterator_generator
|
||||
// to print out the names in the personnel list.
|
||||
|
||||
boost::projection_iterator_generator<select_name,
|
||||
std::list<personnel_record>::iterator>::type
|
||||
personnel_first(personnel_list.begin()),
|
||||
personnel_last(personnel_list.end());
|
||||
|
||||
std::copy(personnel_first, personnel_last,
|
||||
std::ostream_iterator<std::string>(std::cout, "\n"));
|
||||
std::cout << std::endl;
|
||||
|
||||
// to be continued...
|
||||
</pre>
|
||||
The output for this part is:
|
||||
<pre>
|
||||
Barney
|
||||
Fred
|
||||
Wilma
|
||||
Betty
|
||||
</pre>
|
||||
|
||||
<h3>Template Parameters</h3>
|
||||
|
||||
<Table border>
|
||||
<TR>
|
||||
<TH>Parameter</TH><TH>Description</TH>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD><a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html"><tt>AdaptableUnaryFunction</tt></a></TD>
|
||||
<TD>The type of the function object. The <tt>argument_type</tt> of the
|
||||
function must match the value type of the base iterator. The function
|
||||
should return a reference to the function's <tt>result_type</tt>.
|
||||
The <tt>result_type</tt> will be the resulting iterator's <tt>value_type</tt>.
|
||||
</TD>
|
||||
</TD>
|
||||
|
||||
<TR>
|
||||
<TD><tt>BaseIterator</tt></TD>
|
||||
<TD>The iterator type being wrapped.</TD>
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
</Table>
|
||||
|
||||
<h3>Model of</h3>
|
||||
|
||||
If the base iterator is a model of <a
|
||||
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
|
||||
Access Iterator</a> then so is the resulting projection iterator. If
|
||||
the base iterator supports less functionality than this the resulting
|
||||
projection iterator will also support less functionality.
|
||||
|
||||
<h3>Members</h3>
|
||||
|
||||
The projection iterator type implements the member functions and
|
||||
operators required of the <a
|
||||
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
|
||||
Access Iterator</a> concept.
|
||||
In addition it has the following constructor:
|
||||
|
||||
<pre>
|
||||
projection_iterator_generator::type(const BaseIterator& it,
|
||||
const AdaptableUnaryFunction& p = AdaptableUnaryFunction())
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
<hr>
|
||||
<p>
|
||||
|
||||
<h2><a name="projection_iterator_pair_generator">The Projection Iterator Pair
|
||||
Generator</a></h2>
|
||||
|
||||
Sometimes a mutable/const pair of iterator types is needed, such as
|
||||
when implementing a container type. The
|
||||
<tt>projection_iterator_pair_generator</tt> class makes it more
|
||||
convenient to create this pair of iterator types.
|
||||
|
||||
<pre>
|
||||
template <class <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>, class BaseIterator, class ConstBaseIterator>
|
||||
class projection_iterator_pair_generator
|
||||
{
|
||||
public:
|
||||
typedef <tt><a href="./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a><...></tt> iterator; // the mutable projection iterator type
|
||||
typedef <tt><a href="./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a><...></tt> const_iterator; // the immutable projection iterator type
|
||||
};
|
||||
</pre>
|
||||
|
||||
<h3>Example</h3>
|
||||
|
||||
In this part of the example we use the
|
||||
<tt>projection_iterator_pair_generator</tt> to create a mutable/const
|
||||
pair of projection iterators that access the ID numbers of the
|
||||
personnel. We use the mutable iterator to re-index the ID numbers from
|
||||
zero. We then use the constant iterator to print the ID numbers out.
|
||||
|
||||
<pre>
|
||||
// continuing from the last example...
|
||||
|
||||
typedef boost::projection_iterator_pair_generator<select_ID,
|
||||
std::list<personnel_record>::iterator,
|
||||
std::list<personnel_record>::const_iterator> PairGen;
|
||||
|
||||
PairGen::iterator ID_first(personnel_list.begin()),
|
||||
ID_last(personnel_list.end());
|
||||
|
||||
int new_id = 0;
|
||||
while (ID_first != ID_last) {
|
||||
*ID_first = new_id++;
|
||||
++ID_first;
|
||||
}
|
||||
|
||||
PairGen::const_iterator const_ID_first(personnel_list.begin()),
|
||||
const_ID_last(personnel_list.end());
|
||||
|
||||
std::copy(const_ID_first, const_ID_last,
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
std::cout << std::endl;
|
||||
|
||||
// to be continued...
|
||||
</pre>
|
||||
The output is:
|
||||
<pre>
|
||||
0 1 2 3
|
||||
</pre>
|
||||
|
||||
<h3>Template Parameters</h3>
|
||||
|
||||
<Table border>
|
||||
<TR>
|
||||
<TH>Parameter</TH><TH>Description</TH>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD><a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html"><tt>AdaptableUnaryFunction</tt></a></TD>
|
||||
<TD>The type of the function object. The <tt>argument_type</tt> of the
|
||||
function must match the value type of the base iterator. The function
|
||||
should return a true reference to the function's <tt>result_type</tt>.
|
||||
The <tt>result_type</tt> will be the resulting iterator's <tt>value_type</tt>.
|
||||
</TD>
|
||||
</TD>
|
||||
|
||||
<TR>
|
||||
<TD><tt>BaseIterator</tt></TD>
|
||||
<TD>The mutable iterator type being wrapped.</TD>
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD><tt>ConstBaseIterator</tt></TD>
|
||||
<TD>The constant iterator type being wrapped.</TD>
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
</Table>
|
||||
|
||||
<h3>Model of</h3>
|
||||
|
||||
If the base iterator types model the <a
|
||||
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
|
||||
Access Iterator</a> then so do the resulting projection iterator
|
||||
types. If the base iterators support less functionality the
|
||||
resulting projection iterator types will also support less
|
||||
functionality. The resulting <tt>iterator</tt> type is mutable, and
|
||||
the resulting <tt>const_iterator</tt> type is constant.
|
||||
|
||||
<h3>Members</h3>
|
||||
|
||||
The resulting <tt>iterator</tt> and <tt>const_iterator</tt> types
|
||||
implements the member functions and operators required of the <a
|
||||
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
|
||||
Access Iterator</a> concept. In addition they support the following
|
||||
constructors:
|
||||
|
||||
<pre>
|
||||
projection_iterator_pair_generator::iterator(const BaseIterator& it,
|
||||
const AdaptableUnaryFunction& p = AdaptableUnaryFunction())</pre>
|
||||
|
||||
<pre>
|
||||
projection_iterator_pair_generator::const_iterator(const BaseIterator& it,
|
||||
const AdaptableUnaryFunction& p = AdaptableUnaryFunction())
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
<hr>
|
||||
<p>
|
||||
|
||||
<h2><a name="make_projection_iterator">The Projection Iterator Object Generators</a></h2>
|
||||
|
||||
The <tt>make_projection_iterator()</tt> and
|
||||
<tt>make_const_projection_iterator()</tt> functions provide a more
|
||||
convenient way to create projection iterator objects. The functions
|
||||
save the user the trouble of explicitly writing out the iterator
|
||||
types.
|
||||
|
||||
<pre>
|
||||
template <class <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>, class BaseIterator>
|
||||
typename projection_iterator_generator<AdaptableUnaryFunction, BaseIterator>::type
|
||||
make_projection_iterator(BaseIterator base,
|
||||
const AdaptableUnaryFunction& p = AdaptableUnaryFunction())
|
||||
|
||||
template <class <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>, class ConstBaseIterator>
|
||||
typename projection_iterator_generator<AdaptableUnaryFunction, ConstBaseIterator>::type
|
||||
make_const_projection_iterator(ConstBaseIterator base,
|
||||
const AdaptableUnaryFunction& p = AdaptableUnaryFunction())
|
||||
</pre>
|
||||
|
||||
|
||||
<h3>Example</h3>
|
||||
|
||||
In this part of the example, we again print out the names of the
|
||||
personnel, but this time we use the
|
||||
<tt>make_const_projection_iterator()</tt> function to save some typing.
|
||||
|
||||
<pre>
|
||||
// continuing from the last example...
|
||||
|
||||
std::copy
|
||||
(boost::make_const_projection_iterator<select_name>(personnel_list.begin()),
|
||||
boost::make_const_projection_iterator<select_name>(personnel_list.end()),
|
||||
std::ostream_iterator<std::string>(std::cout, "\n"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
The output is:
|
||||
<pre>
|
||||
Barney
|
||||
Fred
|
||||
Wilma
|
||||
Betty
|
||||
</pre>
|
||||
|
||||
<hr>
|
||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->08 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14892" --></p>
|
||||
<p><EFBFBD> Copyright Jeremy Siek 2000. Permission to copy, use,
|
||||
modify, sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided "as is"
|
||||
without express or implied warranty, and with no claim as to its suitability for
|
||||
any purpose.</p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
<!-- LocalWords: html charset alt gif hpp BaseIterator const namespace struct
|
||||
-->
|
||||
<!-- LocalWords: ConstPointer ConstReference typename iostream int abcdefg
|
||||
-->
|
||||
<!-- LocalWords: sizeof PairGen pre Siek htm AdaptableUnaryFunction
|
||||
-->
|
||||
<!-- LocalWords: ConstBaseIterator
|
||||
-->
|
@ -1,96 +0,0 @@
|
||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <list>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <boost/iterator_adaptors.hpp>
|
||||
|
||||
struct personnel_record {
|
||||
personnel_record(std::string n, int id) : m_name(n), m_ID(id) { }
|
||||
std::string m_name;
|
||||
int m_ID;
|
||||
};
|
||||
|
||||
struct select_name {
|
||||
typedef personnel_record argument_type;
|
||||
typedef std::string result_type;
|
||||
const std::string& operator()(const personnel_record& r) const {
|
||||
return r.m_name;
|
||||
}
|
||||
std::string& operator()(personnel_record& r) const {
|
||||
return r.m_name;
|
||||
}
|
||||
};
|
||||
|
||||
struct select_ID {
|
||||
typedef personnel_record argument_type;
|
||||
typedef int result_type;
|
||||
const int& operator()(const personnel_record& r) const {
|
||||
return r.m_ID;
|
||||
}
|
||||
int& operator()(personnel_record& r) const {
|
||||
return r.m_ID;
|
||||
}
|
||||
};
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
std::list<personnel_record> personnel_list;
|
||||
|
||||
personnel_list.push_back(personnel_record("Barney", 13423));
|
||||
personnel_list.push_back(personnel_record("Fred", 12343));
|
||||
personnel_list.push_back(personnel_record("Wilma", 62454));
|
||||
personnel_list.push_back(personnel_record("Betty", 20490));
|
||||
|
||||
// Example of using projection_iterator_generator
|
||||
// to print out the names in the personnel list.
|
||||
|
||||
boost::projection_iterator_generator<select_name,
|
||||
std::list<personnel_record>::iterator>::type
|
||||
personnel_first(personnel_list.begin()),
|
||||
personnel_last(personnel_list.end());
|
||||
|
||||
std::copy(personnel_first, personnel_last,
|
||||
std::ostream_iterator<std::string>(std::cout, "\n"));
|
||||
std::cout << std::endl;
|
||||
|
||||
// Example of using projection_iterator_pair_generator
|
||||
// to assign new ID numbers to the personnel.
|
||||
|
||||
typedef boost::projection_iterator_pair_generator<select_ID,
|
||||
std::list<personnel_record>::iterator,
|
||||
std::list<personnel_record>::const_iterator> PairGen;
|
||||
|
||||
PairGen::iterator ID_first(personnel_list.begin()),
|
||||
ID_last(personnel_list.end());
|
||||
|
||||
int new_id = 0;
|
||||
while (ID_first != ID_last) {
|
||||
*ID_first = new_id++;
|
||||
++ID_first;
|
||||
}
|
||||
|
||||
PairGen::const_iterator const_ID_first(personnel_list.begin()),
|
||||
const_ID_last(personnel_list.end());
|
||||
|
||||
std::copy(const_ID_first, const_ID_last,
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
std::cout << std::endl;
|
||||
|
||||
// Example of using make_const_projection_iterator()
|
||||
// to print out the names in the personnel list again.
|
||||
|
||||
std::copy
|
||||
(boost::make_const_projection_iterator<select_name>(personnel_list.begin()),
|
||||
boost::make_const_projection_iterator<select_name>(personnel_list.end()),
|
||||
std::ostream_iterator<std::string>(std::cout, "\n"));
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,331 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta name="generator" content="HTML Tidy, see www.w3.org">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
|
||||
<title>Reverse Iterator Adaptor Documentation</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align=
|
||||
"center" width="277" height="86">
|
||||
|
||||
<h1>Reverse Iterator Adaptor</h1>
|
||||
Defined in header <a href=
|
||||
"../../boost/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a>
|
||||
|
||||
<p>The reverse iterator adaptor flips the direction of a base iterator's
|
||||
motion. Invoking <tt>operator++()</tt> moves the base iterator backward and
|
||||
invoking <tt>operator--()</tt> moves the base iterator forward. The Boost
|
||||
reverse iterator adaptor is better to use than the
|
||||
<tt>std::reverse_iterator</tt> class in situations where pairs of
|
||||
mutable/constant iterators are needed (e.g., in containers) because
|
||||
comparisons and conversions between the mutable and const versions are
|
||||
implemented correctly.
|
||||
|
||||
<h2>Synopsis</h2>
|
||||
<pre>
|
||||
namespace boost {
|
||||
template <class <a href=
|
||||
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterator</a>,
|
||||
class Value, class Reference, class Pointer, class Category, class Distance>
|
||||
struct reverse_iterator_generator;
|
||||
|
||||
template <class <a href=
|
||||
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterator</a>>
|
||||
typename reverse_iterator_generator<BidirectionalIterator>::type
|
||||
make_reverse_iterator(BidirectionalIterator base)
|
||||
}
|
||||
</pre>
|
||||
<hr>
|
||||
|
||||
<h2><a name="reverse_iterator_generator">The Reverse Iterator Type
|
||||
Generator</a></h2>
|
||||
The <tt>reverse_iterator_generator</tt> template is a <a href=
|
||||
"../../more/generic_programming.html#type_generator">generator</a> of
|
||||
reverse iterator types. The main template parameter for this class is the
|
||||
base <tt>BidirectionalIterator</tt> type that is being adapted. In most
|
||||
cases the associated types of the base iterator can be deduced using
|
||||
<tt>std::iterator_traits</tt>, but in some situations the user may want to
|
||||
override these types, so there are also template parameters for the base
|
||||
iterator's associated types.
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
template <class <a href=
|
||||
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterator</a>,
|
||||
class Value, class Reference, class Pointer, class Category, class Distance>
|
||||
class reverse_iterator_generator
|
||||
{
|
||||
public:
|
||||
typedef <tt><a href=
|
||||
"./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a><...></tt> type; // the resulting reverse iterator type
|
||||
};
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<h3>Example</h3>
|
||||
In this example we sort a sequence of letters and then output the sequence
|
||||
in descending order using reverse iterators.
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
#include <boost/config.hpp>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <boost/iterator_adaptors.hpp>
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
char letters[] = "hello world!";
|
||||
const int N = sizeof(letters)/sizeof(char) - 1;
|
||||
std::cout << "original sequence of letters:\t"
|
||||
<< letters << std::endl;
|
||||
|
||||
std::sort(letters, letters + N);
|
||||
|
||||
// Use reverse_iterator_generator to print a sequence
|
||||
// of letters in reverse order.
|
||||
|
||||
boost::reverse_iterator_generator<char*>::type
|
||||
reverse_letters_first(letters + N),
|
||||
reverse_letters_last(letters);
|
||||
|
||||
std::cout << "letters in descending order:\t";
|
||||
std::copy(reverse_letters_first, reverse_letters_last,
|
||||
std::ostream_iterator<char>(std::cout));
|
||||
std::cout << std::endl;
|
||||
|
||||
// to be continued...
|
||||
</pre>
|
||||
</blockquote>
|
||||
The output is:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
original sequence of letters: hello world!
|
||||
letters in descending order: wroolllhed!
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<h3>Template Parameters</h3>
|
||||
|
||||
<table border>
|
||||
<tr>
|
||||
<th>Parameter
|
||||
|
||||
<th>Description
|
||||
|
||||
<tr>
|
||||
<td><tt><a href=
|
||||
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterator</a></tt>
|
||||
|
||||
|
||||
<td>The iterator type being wrapped.
|
||||
|
||||
<tr>
|
||||
<td><tt>Value</tt>
|
||||
|
||||
<td>The value-type of the base iterator and the resulting reverse
|
||||
iterator.<br>
|
||||
<b>Default:</b><tt>std::iterator_traits<BidirectionalIterator>::value_type</tt>
|
||||
|
||||
|
||||
<tr>
|
||||
<td><tt>Reference</tt>
|
||||
|
||||
<td>The <tt>reference</tt> type of the resulting iterator, and in
|
||||
particular, the result type of <tt>operator*()</tt>.<br>
|
||||
<b>Default:</b> If <tt>Value</tt> is supplied, <tt>Value&</tt> is
|
||||
used. Otherwise
|
||||
<tt>std::iterator_traits<BidirectionalIterator>::reference</tt>
|
||||
is used.
|
||||
|
||||
<tr>
|
||||
<td><tt>Pointer</tt>
|
||||
|
||||
<td>The <tt>pointer</tt> type of the resulting iterator, and in
|
||||
particular, the result type of <tt>operator->()</tt>.<br>
|
||||
<b>Default:</b> If <tt>Value</tt> was supplied, then <tt>Value*</tt>,
|
||||
otherwise
|
||||
<tt>std::iterator_traits<BidirectionalIterator>::pointer</tt>.
|
||||
|
||||
<tr>
|
||||
<td><tt>Category</tt>
|
||||
|
||||
<td>The <tt>iterator_category</tt> type for the resulting iterator.<br>
|
||||
<b>Default:</b>
|
||||
<tt>std::iterator_traits<BidirectionalIterator>::iterator_category</tt>
|
||||
|
||||
|
||||
<tr>
|
||||
<td><tt>Distance</tt>
|
||||
|
||||
<td>The <tt>difference_type</tt> for the resulting iterator.<br>
|
||||
<b>Default:</b>
|
||||
<tt>std::iterator_traits<BidirectionalIterator&gt::difference_type</tt>
|
||||
|
||||
</table>
|
||||
|
||||
<h3>Concept Model</h3>
|
||||
The indirect iterator will model whichever <a href=
|
||||
"http://www.sgi.com/tech/stl/Iterators.html">standard iterator concept
|
||||
category</a> is modeled by the base iterator. Thus, if the base iterator is
|
||||
a model of <a href=
|
||||
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access
|
||||
Iterator</a> then so is the resulting indirect iterator. If the base
|
||||
iterator models a more restrictive concept, the resulting indirect iterator
|
||||
will model the same concept. The base iterator must be at least a <a href=
|
||||
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">Bidirectional
|
||||
Iterator</a>
|
||||
|
||||
<h3>Members</h3>
|
||||
The reverse iterator type implements the member functions and operators
|
||||
required of the <a href=
|
||||
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access
|
||||
Iterator</a> concept. In addition it has the following constructor:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
reverse_iterator_generator::type(const BidirectionalIterator& it)
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
|
||||
<br>
|
||||
<br>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>
|
||||
|
||||
<h2><a name="make_reverse_iterator">The Reverse Iterator Object
|
||||
Generator</a></h2>
|
||||
The <tt>make_reverse_iterator()</tt> function provides a more convenient
|
||||
way to create reverse iterator objects. The function saves the user the
|
||||
trouble of explicitly writing out the iterator types.
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
template <class BidirectionalIterator>
|
||||
typename reverse_iterator_generator<BidirectionalIterator>::type
|
||||
make_reverse_iterator(BidirectionalIterator base);
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<h3>Example</h3>
|
||||
In this part of the example we use <tt>make_reverse_iterator()</tt> to
|
||||
print the sequence of letters in reverse-reverse order, which is the
|
||||
original order.
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
// continuing from the previous example...
|
||||
|
||||
std::cout << "letters in ascending order:\t";
|
||||
std::copy(boost::make_reverse_iterator(reverse_letters_last),
|
||||
boost::make_reverse_iterator(reverse_letters_first),
|
||||
std::ostream_iterator<char>(std::cout));
|
||||
std::cout << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
The output is:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
letters in ascending order: !dehllloorw
|
||||
</pre>
|
||||
</blockquote>
|
||||
<hr>
|
||||
|
||||
<h2><a name="interactions">Constant/Mutable Iterator Interactions</a></h2>
|
||||
|
||||
<p>One failing of the standard <tt><a
|
||||
href="http://www.sgi.com/tech/stl/ReverseIterator.html">reverse_iterator</a></tt>
|
||||
adaptor is that it doesn't properly support interactions between adapted
|
||||
<tt>const</tt> and non-<tt>const</tt> iterators. For example:
|
||||
<blockquote>
|
||||
<pre>
|
||||
#include <vector>
|
||||
|
||||
template <class T> void convert(T x) {}
|
||||
|
||||
// Test interactions of a matched pair of random access iterators
|
||||
template <class Iterator, class ConstIterator>
|
||||
void test_interactions(Iterator i, ConstIterator ci)
|
||||
{
|
||||
bool eq = i == ci; // comparisons
|
||||
bool ne = i != ci;
|
||||
bool lt = i < ci;
|
||||
bool le = i <= ci;
|
||||
bool gt = i > ci;
|
||||
bool ge = i >= ci;
|
||||
std::size_t distance = i - ci; // difference
|
||||
ci = i; // assignment
|
||||
ConstIterator ci2(i); // construction
|
||||
convert<ConstIterator>(i); // implicit conversion
|
||||
}
|
||||
|
||||
void f()
|
||||
{
|
||||
typedef std::vector<int> vec;
|
||||
vec v;
|
||||
const vec& cv;
|
||||
|
||||
test_interactions(v.begin(), cv.begin()); // <font color="#007F00">OK</font>
|
||||
test_interactions(v.rbegin(), cv.rbegin()); // <font color="#FF0000">ERRORS ON EVERY TEST!!</font>
|
||||
</pre>
|
||||
</blockquote>
|
||||
Reverse iterators created with <tt>boost::reverse_iterator_generator</tt> don't have this problem, though:
|
||||
<blockquote>
|
||||
<pre>
|
||||
typedef boost::reverse_iterator_generator<vec::iterator>::type ri;
|
||||
typedef boost::reverse_iterator_generator<vec::const_iterator>::type cri;
|
||||
test_interactions(ri(v.begin()), cri(cv.begin())); // <font color="#007F00">OK!!</font>
|
||||
</pre>
|
||||
</blockquote>
|
||||
Or, more simply,
|
||||
<blockquote>
|
||||
<pre>
|
||||
test_interactions(
|
||||
boost::make_reverse_iterator(v.begin()),
|
||||
boost::make_reverse_iterator(cv.begin())); // <font color="#007F00">OK!!</font>
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>If you are wondering why there is no
|
||||
<tt>reverse_iterator_pair_generator</tt> in the manner of <tt><a
|
||||
href="projection_iterator.htm#projection_iterator_pair_generator">projection_iterator_pair_generator</a></tt>,
|
||||
the answer is simple: we tried it, but found that in practice it took
|
||||
<i>more</i> typing to use <tt>reverse_iterator_pair_generator</tt> than to
|
||||
simply use <tt>reverse_iterator_generator</tt> twice!<br><br>
|
||||
|
||||
<hr>
|
||||
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->08 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14892" -->
|
||||
|
||||
|
||||
<p>© Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell
|
||||
and distribute this document is granted provided this copyright notice
|
||||
appears in all copies. This document is provided "as is" without express or
|
||||
implied warranty, and with no claim as to its suitability for any purpose.
|
||||
<!-- LocalWords: html charset alt gif hpp BidirectionalIterator const namespace struct
|
||||
-->
|
||||
|
||||
<!-- LocalWords: ConstPointer ConstReference typename iostream int abcdefg
|
||||
-->
|
||||
<!-- LocalWords: sizeof PairGen pre Siek wroolllhed dehllloorw
|
||||
-->
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,42 +0,0 @@
|
||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <boost/iterator_adaptors.hpp>
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
char letters[] = "hello world!";
|
||||
const int N = sizeof(letters)/sizeof(char) - 1;
|
||||
std::cout << "original sequence of letters:\t"
|
||||
<< letters << std::endl;
|
||||
|
||||
std::sort(letters, letters + N);
|
||||
|
||||
// Use reverse_iterator_generator to print a sequence
|
||||
// of letters in reverse order.
|
||||
|
||||
boost::reverse_iterator_generator<char*>::type
|
||||
reverse_letters_first(letters + N),
|
||||
reverse_letters_last(letters);
|
||||
|
||||
std::cout << "letters in descending order:\t";
|
||||
std::copy(reverse_letters_first, reverse_letters_last,
|
||||
std::ostream_iterator<char>(std::cout));
|
||||
std::cout << std::endl;
|
||||
|
||||
// Use make_reverse_iterator() to print the sequence
|
||||
// of letters in reverse-reverse order.
|
||||
|
||||
std::cout << "letters in ascending order:\t";
|
||||
std::copy(boost::make_reverse_iterator(reverse_letters_last),
|
||||
boost::make_reverse_iterator(reverse_letters_first),
|
||||
std::ostream_iterator<char>(std::cout));
|
||||
std::cout << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user