1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803
|
<!DOCTYPE HTML PUBLIC "-//SoftQuad Software//DTD HoTMetaL PRO 5.0::19981217::extensions to HTML 4.0//EN" "hmpro5.dtd">
<HTML>
<HEAD>
<meta http-equiv="Content-Language" content="en-us">
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252">
<LINK REL="stylesheet" TYPE="text/css" HREF="../../../boost.css">
<TITLE>Header </TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#800080">
<H2><IMG SRC="../../../boost.png" WIDTH="276" HEIGHT="86">Header <<A
HREF="../../../boost/optional/optional.hpp">boost/optional/optional.hpp</A>> </H2>
<H2>Contents</H2>
<DL CLASS="page-index">
<DT><A HREF="#mot">Motivation</A></DT>
<DT><A HREF="#dev">Development</A></DT>
<DT><A HREF="#synopsis">Synopsis</A></DT>
<DT><A HREF="#semantics">Semantics</A></DT>
<DT><A HREF="#examples">Examples</A></DT>
<DT><A HREF="#ref">Optional references</A></DT>
<DT><A HREF="#refassign">Rebinding semantics for assignment of optional references</A></DT>
<DT><A HREF="#none">none_t and none</A></DT>
<DT><A HREF="#inplace">In-Place Factories</A></DT>
<DT><A HREF="#bool">A note about optional<bool></A></DT>
<DT><A HREF="#exsafety">Exception Safety Guarantees</A></DT>
<DT><A HREF="#requirements">Type requirements</A></DT>
<DT><A HREF="#impl">Implementation Notes</A></DT>
<DT><A HREF="#porta">Dependencies and Portability</A></DT>
<DT><A HREF="#credits">Acknowledgment</A></DT>
</DL>
<HR>
<H2><A NAME="mot"></A>Motivation</H2>
<P>Consider these functions which should return a value but which might not have
a value to return:</P>
<pre>(A) double sqrt(double n );
(B) char get_async_input();
(C) point polygon::get_any_point_effectively_inside();</pre>
<P>There are different approaches to the issue of not having a value to return.</P>
<P>A typical approach is to consider the existence of a valid return value as
a postcondition, so that if the function cannot compute the value to return,
it has either undefined behavior (and can use assert in a debug build)
or uses a runtime check and throws an exception if the postcondition is violated.
This is a reasonable choice for example, for function (A), because the
lack of a proper return value is directly related to an invalid parameter (out
of domain argument), so it is appropriate to require the callee to supply only
parameters in a valid domain for execution to continue normally.</P>
<P>However, function (B), because of its asynchronous nature, does not fail just
because it can't find a value to return; so it is incorrect to consider
such a situation an error and assert or throw an exception. This function must
return, and somehow, must tell the callee that it is not returning a meaningful
value.</P>
<P>A similar situation occurs with function (C): it is conceptually an error to
ask a <i>null-area</i> polygon to return a point inside itself, but in many
applications, it is just impractical for performance reasons to treat this as
an error (because detecting that the polygon has no area might be too expensive
to be required to be tested previously), and either an arbitrary point (typically
at infinity) is returned, or some efficient way to tell the callee that there
is no such point is used.</P>
<P>There are various mechanisms to let functions communicate that the returned
value is not valid. One such mechanism, which is quite common since it has zero
or negligible overhead, is to use a special value which is reserved to communicate
this. Classical examples of such special values are EOF, string::npos, points
at infinity, etc...</P>
<P>When those values exist, i.e. the return type can hold all meaningful values
<i>plus</i> the <i>signal</i> value, this mechanism is quite appropriate and
well known. Unfortunately, there are cases when such values do not exist. In
these cases, the usual alternative is either to use a wider type, such as 'int'
in place of 'char'; or a compound type, such as std::pair<point,bool>.
</P>
<P>Returning a std::pair<T,bool>, thus attaching a boolean flag to the result
which indicates if the result is meaningful, has the advantage that can be turned
into a consistent idiom since the first element of the pair can be whatever
the function would conceptually return. For example, the last two functions
could have the following interface:</P>
<pre>std::pair<char,bool> get_async_input();
std::pair<point,bool> polygon::get_any_point_effectively_inside();</pre>
<p>These functions use a consistent interface for dealing with possibly inexistent
results:</p>
<pre>std::pair<point,bool> p = poly.get_any_point_effectively_inside();
if ( p.second )
flood_fill(p.first);
</pre>
<P>However, not only is this quite a burden syntactically, it is also error
prone since the user can easily use the function result (first element of the
pair) without ever checking if it has a valid value.</P>
<P>Clearly, we need a better idiom.</P>
<H2><A NAME="dev"></A>Development</H2>
<h3><u>The models:</u></h3>
<P>In C++, we can <i>declare</i> an object (a variable) of type T, and we can give this variable
an <i>initial value</i> (through an <i>initializer</i>. (c.f. 8.5)).<br>
When a declaration includes a non-empty initializer (an initial value is given), it is said that
the object has been <i><b>initialized</b></i>.<br>
If the declaration uses an empty initializer (no initial value is given),
and neither default nor value initialization applies, it is said that the object is
<i><b>uninitialized</b></i>. Its actual value exist but has an
<i>indeterminate initial value</i> (c.f. 8.5.9).<br>
<code>optional<T></code> intends to formalize the notion of initialization
(or lack of it)
allowing a program to test whether an object has been initialized and stating that access to
the value of an uninitialized object is undefined behavior. That is,
when a variable is declared as optional<T> and no initial value is given,
the variable is <i>formally</i> uninitialized. A formally uninitialized optional object has conceptually
no value at all and this situation can be tested at runtime. It is formally <i>
undefined behavior</i>
to try to access the value of an uninitialized optional. An uninitialized optional can be <i>assigned</i> a value, in which case its initialization state changes to initialized. Furthermore, given the formal
treatment of initialization states in optional objects, it is even possible to reset an optional to <i>uninitialized</i>.</P>
<P>In C++ there is no formal notion of uninitialized objects, which
means that objects always have an initial value even if indeterminate.<br>
As discussed on the previous section, this has a drawback because you need additional
information to tell if an object has been effectively initialized.<br>
One of the typical ways in which this has been historically
dealt with is via a special value: EOF,npos,-1, etc... This is equivalent to adding
the special value to the set of possible values of a given type. This super set of
T plus some <i>nil_t</i>—were nil_t is some stateless POD-can be modeled in modern
languages as a <b>discriminated union</b> of <code>T</code> and <code>nil_t</code>.
Discriminated unions are often called <i>variants</i>. A variant has a <i>current type</i>,
which in our case is either <code>T</code> or <code>nil_t</code>.<br>
Using the <a href="../../../doc/html/variant.html">Boost.Variant</a> library, this model can be implemented
in terms of <code>boost::variant<T,nil_t></code>.<br>
There is precedent for a discriminated union as a model for an optional value: the
<a href="http://www.haskell.org/"><u>Haskell</u></a> <b>Maybe</b> built-in type constructor.
Thus, a discriminated union <code>T+nil_t</code> serves as a conceptual foundation.</p>
<p>A <code>variant<T,nil_t></code> follows naturally from the traditional idiom of extending
the range of possible values adding an additional sentinel value with the special meaning of <i>Nothing. </i>
However, this additional <i>Nothing</i> value is largely irrelevant for our purpose
since our goal is to formalize the notion of uninitialized objects and, while a special extended value <i>can</i> be used to convey that meaning, it is not strictly
necessary in order to do so.</p>
<p>The observation made in the last paragraph about the irrelevant nature of the additional <code>nil_t</code> with respect to
<u>purpose</u> of optional<T> suggests
an alternative model: a <i>container</i> that either has a value of T or nothing.
</p>
<p>As of this writing I don't know of any precedent for a variable-size fixed-capacity (of 1)
stack-based container model for optional values, yet I believe this is the consequence of
the lack of practical implementations of such a container rather than an inherent shortcoming
of the container model.</p>
<p>In any event, both the discriminated-union or the single-element container models serve as a conceptual
ground for a class representing optional—i.e. possibly uninitialized—objects.<br>
For instance, these models show the <i>exact</i> semantics required for a wrapper of optional values:</p>
<p>Discriminated-union:</p>
<blockquote>
<li><b>deep-copy</b> semantics: copies of the variant implies copies of the value.</li>
<li><b>deep-relational</b> semantics: comparisons between variants matches both current types and values</li>
<li>If the variant's current type is T, it is modeling an <i>initialized</i> optional.</li>
<li>If the variant's current type is not T, it is modeling an <i>uninitialized</i> optional.</li>
<li>Testing if the variant's current type is T models testing if the optional is initialized</li>
<li>Trying to extract a T from a variant when its current type is not T, models the undefined
behavior
of trying to access the value of an uninitialized optional</li>
</blockquote>
<p>Single-element container:</p>
<blockquote>
<li><b>deep-copy</b> semantics: copies of the container implies copies of the value.</li>
<li><b>deep-relational</b> semantics: comparisons between containers compare container size and if match, contained value</li>
<li>If the container is not empty (contains an object of type T), it is modeling an <i>initialized</i> optional.</li>
<li>If the container is empty, it is modeling an <i>uninitialized</i> optional.</li>
<li>Testing if the container is empty models testing if the optional is initialized</li>
<li>Trying to extract a T from an empty container models the undefined behavior
of trying to access the value of an uninitialized optional</li>
</blockquote>
<h3><u>The semantics:</u></h3>
<p>Objects of type <code>optional<T></code> are intended to be used in places where objects of type T would
but which might be uninitialized. Hence, <code>optional<T></code>'s purpose is to formalize the
additional possibly uninitialized state.<br>
From the perspective of this role, <code>optional<T></code> can have the same operational semantics of T
plus the additional semantics corresponding to this special state.<br>
As such, <code>optional<T></code> could be thought of as a <i>supertype</i> of T. Of course,
we can't do that in C++, so we need to compose the desired semantics using a different mechanism.<br>
Doing it the other way around, that is, making <code>optional<T></code> a <i>subtype</i> of T is not only
conceptually wrong but also impractical: it is not allowed to derive from a non-class type, such as a
built-in type.</p>
<p>We can draw from the purpose of optional<T> the required basic semantics:</p>
<blockquote>
<p><b>Default Construction:</b> To introduce a formally uninitialized wrapped
object.</p>
<p><b>Direct Value Construction via copy:</b> To introduce a formally
initialized wrapped object whose value is obtained as a copy of some object.</p>
<p><b>Deep Copy Construction:</b> To obtain a new yet equivalent wrapped
object.</p>
<p><b>Direct Value Assignment (upon initialized):</b> To assign a value to the wrapped object.</p>
<p><b>Direct Value Assignment (upon uninitialized):</b> To initialize the wrapped object
with a value obtained
as a copy of some object.</p>
<p><b>Assignment (upon initialized):</b> To assign to the wrapped object the value
of another wrapped object.</p>
<p><b>Assignment (upon uninitialized):</b> To initialize the wrapped object
with value of another wrapped object.</p>
<p><b>Deep Relational Operations (when supported by the type T):</b> To compare
wrapped object values taking into account the presence of uninitialized
states.</p>
<p><b>Value access:</b> To unwrap the wrapped object.</p>
<p><b>Initialization state query:</b> To determine if the object is formally
initialized or not.</p>
<p><b>Swap:</b> To exchange wrapped objects. (with whatever exception safety
guarantees are provided by T's swap).</p>
<p><b>De-initialization:</b> To release the wrapped object (if any) and leave
the wrapper in the uninitialized state.</p>
</blockquote>
<p>Additional operations are useful, such as converting constructors and
converting assignments, in-place construction and assignment, and safe value
access via a pointer to the wrapped object or null.</p>
<h3><u>The Interface:</u></h3>
<p>Since the purpose of optional is to allow us to use objects with a formal
uninitialized additional state, the interface could try to follow the interface
of the underlying T type as much as possible. In order to choose the proper
degree of adoption of the native T interface, the following must be noted: <br>
Even if all the operations supported by an instance of type T are defined for
the entire range of values for such a type, an optional<T> extends such a set of
values with a new value for which most (otherwise valid) operations are not
defined in terms of T.<br>
Furthermore, since optional<T> itself is merely a T wrapper (modeling a T
supertype), any attempt to define such operations upon uninitialized optionals
will be totally artificial w.r.t. T.<br>
This library chooses an interface which follows from T's interface only for
those operations which are well defined (w.r.t the type T) even if any of the
operands are uninitialized. These operations include: construction,
copy-construction, assignment, swap and relational operations.<br>
For the value access operations, which are undefined (w.r.t the type T) when the
operand is uninitialized, a different interface is chosen (which will be
explained next).<br>
Also, the presence of the possibly uninitialized state requires additional
operations not provided by T itself which are supported by a special interface.</p>
<h3>Lexically-hinted Value Access in the presence of possibly untitialized
optional objects: The operators * and -></h3>
<p>A relevant feature of a pointer is that it can have a <b>null
pointer value</b>. This is a <i>special</i> value which is used to indicate that the
pointer is not referring to any object at all. In other words, null pointer
values convey the notion of inexistent objects.</P>
<P>This meaning of the null pointer value allowed pointers to became a <i>de facto</i> standard
for handling optional objects because all you have to do to refer to a value which you
don't really have is to use a null pointer value of the appropriate type.
Pointers have been used for decades—from the days of C APIs to modern C++ libraries—to
<i>refer</i> to optional (that is, possibly inexistent) objects; particularly
as optional arguments to a function, but also quite often as optional data members.</P>
<P>The possible presence of a null pointer value makes the operations that access the
pointee's value possibly undefined, therefore, expressions which use dereference
and access operators, such as: <code>( *p = 2 )</code> and <code>( p->foo())</code>,
implicitly convey the notion of optionality, and this information is tied to
the <i>syntax</i> of the expressions. That is, the presence of operators * and -> tell by
themselves—without any additional context—that the expression will be undefined unless
the implied pointee actually exist.</P>
<P>Such a <i>de facto</i> idiom for referring to optional objects can be formalized in the form of a
concept: the <a href="../../utility/OptionalPointee.html">OptionalPointee</a> concept.<br>
This concept captures the syntactic usage of operators *, -> and conversion to bool to convey
the notion of optionality.</P>
<P>However, pointers are good to <u>refer</u> to optional objects, but not particularly good
to handle the optional objects in all other respects, such as initializing or moving/copying
them. The problem resides in the shallow-copy of pointer semantics: if you need to
effectively move or copy the object, pointers alone are not enough. The problem
is that copies of pointers do not imply copies of pointees. For example, as
was discussed in the motivation, pointers alone cannot be used to return optional
objects from a function because the object must move outside from the function and
into the caller's context.<br>
A solution to the shallow-copy problem that is often used is to resort to dynamic
allocation and use a smart pointer to automatically handle the details of this.
For example, if a function is to optionally return an object X, it can use shared_ptr<X>
as the return value. However, this requires dynamic allocation of X. If X is
a built-in or small POD, this technique is very poor in terms of required resources.
Optional objects are essentially values so it is very convenient to be able to use automatic
storage and deep-copy semantics to manipulate optional values just as we do with ordinary
values. Pointers do not have this semantics, so are inappropriate for the initialization and
transport of optional values, yet are quite convenient for handling the access to the
possible undefined value because of the idiomatic aid present in the OptionalPointee
concept incarnated by pointers.
</p>
<h4>Optional<T> as a model of OptionalPointee</h4>
<P>For value access operations optional<> uses operators * and -> to lexically
warn about the possibly uninitialized state appealing to the familiar pointer
semantics w.r.t. to null pointers.<br>
<u><b>However, it is particularly important to note that optional<> objects are not pointers. optional<>
is not, and does not model, a pointer</b></u><b>.</b>
<P>For instance, optional<> does not have shallow-copy so does not alias: two different optionals
never refer to the <i>same</i> value unless T itself is a reference (but may have <i>equivalent</i> values).<br>
The difference between an optional<T> and a pointer must be kept in mind, particularly
because the semantics of relational operators are different: since optional<T>
is a value-wrapper, relational operators are deep: they compare optional values;
but relational operators for pointers are shallow: they do not compare pointee values.<br>
As a result, you might be able to replace optional<T> by T* on some situations but
not always. Specifically, on generic code written for both, you cannot use relational
operators directly, and must use the template functions
<a href="../../utility/OptionalPointee.html#equal">equal_pointees()</a> and
<a href="../../utility/OptionalPointee.html#less">less_pointees()</a> instead.
<HR>
<H2><A NAME="synopsis">Synopsis</A></H2>
<PRE>namespace boost {
template<class T>
class optional
{
public :
<i><u>(If T is of reference type, the parameters and results by reference are by value)</u></i>
optional () ;
optional ( none_t ) ;
optional ( T const& v ) ;
optional ( bool condition, T const& v ) ; <u><i>[new in 1.34]</u></i>
optional ( optional const& rhs ) ;
template<class U> explicit optional ( optional<U> const& rhs ) ;
template<class InPlaceFactory> explicit optional ( InPlaceFactory const& f ) ;
template<class TypedInPlaceFactory> explicit optional ( TypedInPlaceFactory const& f ) ;
optional& operator = ( none_t ) ;
optional& operator = ( T const& v ) ;
optional& operator = ( optional const& rhs ) ;
template<class U> optional& operator = ( optional<U> const& rhs ) ;
template<class InPlaceFactory> optional& operator = ( InPlaceFactory const& f ) ;
template<class TypedInPlaceFactory> optional& operator = ( TypedInPlaceFactory const& f ) ;
T const& get() const ;
T& get() ;
T const& get_value_or( T const& default ) const ; <u><i>[new in 1.34]</u></i>
T const* operator ->() const ;
T* operator ->() ;
T const& operator *() const ;
T& operator *() ;
T const* get_ptr() const ;
T* get_ptr() ;
operator <i>unspecified-bool-type</i>() const ;
bool operator!() const ;
<i><u>deprecated methods</u></i>
void reset() ; (deprecated)
void reset ( T const& ) ; (deprecated)
bool is_initialized() const ; (deprecated)
} ;
template<class T> inline bool operator == ( optional<T> const& x, optional<T> const& y ) ;
template<class T> inline bool operator != ( optional<T> const& x, optional<T> const& y ) ;
template<class T> inline bool operator < ( optional<T> const& x, optional<T> const& y ) ;
template<class T> inline bool operator > ( optional<T> const& x, optional<T> const& y ) ;
template<class T> inline bool operator <= ( optional<T> const& x, optional<T> const& y ) ;
template<class T> inline bool operator >= ( optional<T> const& x, optional<T> const& y ) ;
template<class T> inline bool operator == ( optional<T> const& x, T const& n ) ; <u><i>[new in 1.34]</u></i>
template<class T> inline bool operator != ( optional<T> const& x, T const& n ) ; <u><i>[new in 1.34]</u></i>
template<class T> inline bool operator < ( optional<T> const& x, T const& n ) ; <u><i>[new in 1.34]</u></i>
template<class T> inline bool operator > ( optional<T> const& x, T const& n ) ; <u><i>[new in 1.34]</u></i>
template<class T> inline bool operator <= ( optional<T> const& x, T const& n ) ; <u><i>[new in 1.34]</u></i>
template<class T> inline bool operator >= ( optional<T> const& x, T const& n ) ; <u><i>[new in 1.34]</u></i>
template<class T> inline bool operator == ( T const& n, optional<T> const& y ) ; <u><i>[new in 1.34]</u></i>
template<class T> inline bool operator != ( T const& n, optional<T> const& y ) ; <u><i>[new in 1.34]</u></i>
template<class T> inline bool operator < ( T const& n, optional<T> const& y ) ; <u><i>[new in 1.34]</u></i>
template<class T> inline bool operator > ( T const& n, optional<T> const& y ) ; <u><i>[new in 1.34]</u></i>
template<class T> inline bool operator <= ( T const& n, optional<T> const& y ) ; <u><i>[new in 1.34]</u></i>
template<class T> inline bool operator >= ( T const& n, optional<T> const& y ) ; <u><i>[new in 1.34]</u></i>
template<class T> inline bool operator == ( optional<T> const& x, none_t n ) ; <u><i>[new in 1.34]</u></i>
template<class T> inline bool operator != ( optional<T> const& x, none_t n ) ; <u><i>[new in 1.34]</u></i>
template<class T> inline bool operator < ( optional<T> const& x, none_t n ) ; <u><i>[new in 1.34]</u></i>
template<class T> inline bool operator > ( optional<T> const& x, none_t n ) ; <u><i>[new in 1.34]</u></i>
template<class T> inline bool operator <= ( optional<T> const& x, none_t n ) ; <u><i>[new in 1.34]</u></i>
template<class T> inline bool operator >= ( optional<T> const& x, none_t n ) ; <u><i>[new in 1.34]</u></i>
template<class T> inline bool operator == ( none_t n, optional<T> const& y ) ; <u><i>[new in 1.34]</u></i>
template<class T> inline bool operator != ( none_t n, optional<T> const& y ) ; <u><i>[new in 1.34]</u></i>
template<class T> inline bool operator < ( none_t n, optional<T> const& y ) ; <u><i>[new in 1.34]</u></i>
template<class T> inline bool operator > ( none_t n, optional<T> const& y ) ; <u><i>[new in 1.34]</u></i>
template<class T> inline bool operator <= ( none_t n, optional<T> const& y ) ; <u><i>[new in 1.34]</u></i>
template<class T> inline bool operator >= ( none_t n, optional<T> const& y ) ; <u><i>[new in 1.34]</u></i>
template<class T> inline optional<T> make_optional ( T const& v ) ; <u><i>[new in 1.34]</u></i>
template<class T> inline optional<T> make_optional ( bool condition, T const& v ) ; <u><i>[new in 1.34]</u></i>
template<class T> inline T const& get_optional_value_or ( optional<T> const& opt, T const& default ) ; <u><i>[new in 1.34]</u></i>
template<class T> inline T const& get ( optional<T> const& opt ) ;
template<class T> inline T& get ( optional<T> & opt ) ;
template<class T> inline T const* get ( optional<T> const* opt ) ;
template<class T> inline T* get ( optional<T>* opt ) ;
template<class T> inline T const* get_pointer ( optional<T> const& opt ) ;
template<class T> inline T* get_pointer ( optional<T> & opt ) ;
template<class T> inline void swap( optional<T>& x, optional<T>& y ) ;
} // namespace boost
</PRE>
<HR>
<h2><A NAME="semantics">Detailed Semantics</a></h2>
<p><b><u>NOTES: </u></b></p>
<p><b>Because T might be of reference type, in the sequel, those entries whose
semantic depends on T being of reference type or not will be distinguished using
the following convention:<br>
If the entry reads: optional<T (not a ref)>, the description corresponds only to
the case where T is not of reference type.<br>
If the entry reads: optional<T&>, the description corresponds only to the case
where T is of reference type. <br>
If the entry reads: optional<T>, the description is the same for both cases.</b></p>
<p><i>The following section contains various assert() which are used only to
show the postconditions as sample code. It is not implied that the type T must
support each particular expression but that if the expression is supported, the
implied condition holds.</i></p>
<hr>
<pre>optional<T>::optional();</pre>
<blockquote>
<p><b>Effect:</b> Default-Constructs an <b>optional</b>.</p>
<p><b>Postconditions:</b> <b>*this</b> is <u>uninitialized</u>.</p>
<p><b>Throws:</b> Nothing.</p>
<p><b>Notes:</b> T's default constructor <u><i>is not</i></u> called.</p>
<p><b>Example:</b></p>
<blockquote>
<pre>optional<T> def ;
assert ( !def ) ;</pre>
</blockquote>
</blockquote>
<HR>
<pre>optional<T>::optional( none_t );</pre>
<blockquote>
<p><b>Effect:</b> Constructs an <b>optional</b> uninitialized.</p>
<p><b>Postconditions:</b> <b>*this</b> is <u>uninitialized</u>.</p>
<p><b>Throws:</b> Nothing.</p>
<p><b>Notes:</b></p>
<blockquote>
<p>T's default constructor <u><i>is not</i></u> called.<br>
The
expression <code>boost::none</code> denotes an instance of <code>boost::none_t</code> that can be
used as the parameter.</p>
</blockquote>
<p><b>Example:</b></p>
<blockquote>
<pre>
#include <boost/none.hpp>
optional<int> n(boost::none) ;
assert ( !n ) ;
</pre>
</blockquote>
</blockquote>
<HR>
<pre>optional<T <i>(not a ref)</i>>::optional( T const& v )</pre>
<blockquote>
<p><b>Effect:</b> Directly-Constructs an <b>optional</b>.</p>
<p><b>Postconditions:</b> <b>*this</b> is <u>initialized</u> and its value is a <i>copy</i> of 'v'.</p>
<p><b>Throws:</b> Whatever T::T( T const& ) throws.</p>
<p><b>Notes: </b> T::T( T const& ) is called.</p>
<p><b>Exception Safety:</b> Exceptions can only be thrown during T::T( T const& );
in that case, this constructor has no effect.
</p>
<p><b>Example:</b></p>
<blockquote>
<pre>
T v;
optional<T> opt(v);
assert ( *opt == v ) ;
</pre>
</blockquote>
</blockquote>
<HR>
<pre>optional<T&>::optional( T& ref )</pre>
<blockquote>
<p><b>Effect:</b> Directly-Constructs an <b>optional</b>.</p>
<p><b>Postconditions:</b> <b>*this</b> is <u>initialized</u> and its value is an
instance of an internal type wrapping the reference 'ref'.</p>
<p><b>Throws:</b> Nothing.</p>
<p><b>Example:</b></p>
<blockquote>
<pre>
T v;
T& vref = v ;
optional<T&> opt(vref);
assert ( *opt == v ) ;
++ v ; // mutate referee
assert (*opt == v);
</pre>
</blockquote>
</blockquote>
<HR>
<pre>optional<T <i>(not a ref)</i>>::optional( bool condition, T const& v ) ;
optional<T&> ::optional( bool condition, T& v ) ;
</pre>
<blockquote>
<p>If <i>condition</i> is <code>true</code>, same as:</p>
<pre>optional<T <i>(not a ref)</i>>::optional( T const& v )
optional<T&> ::optional( T& v )
</pre>
<p>otherwise, same as:</p>
<pre>
optional<T <i>(not a ref)</i>>::optional()
optional<T&> ::optional()
</pre>
</blockquote>
<HR>
<pre>optional<T <i>(not a ref)</i>>::optional( optional const& rhs );</pre>
<blockquote>
<p><b>Effect:</b> Copy-Constructs an <b>optional</b>.</p>
<p><b>Postconditions:</b> If <b>rhs</b> is initialized, <b>*this</b> is initialized
and its value is a <i>copy</i> of the value of <b>rhs</b>; else <b>*this</b>
is uninitialized.</p>
<p><b>Throws:</b> Whatever T::T( T const& ) throws.</p>
<p><b>Notes:</b> If <b>rhs</b> is initialized, T::T(T const& ) is called.</p>
<p><b>Exception Safety:</b> Exceptions can only be thrown during T::T( T const& );
in that case, this constructor has no effect.
</p>
<p><b>Example:</b></p>
<blockquote>
<pre>
optional<T> uninit ;
assert (!uninit);
optional<T> uinit2 ( uninit ) ;
assert ( uninit2 == uninit );
optional<T> init( T(2) );
assert ( *init == T(2) ) ;
optional<T> init2 ( init ) ;
assert ( init2 == init ) ;
</pre>
</blockquote>
</blockquote>
<HR>
<pre>optional<T&>::optional( optional const& rhs );</pre>
<blockquote>
<p><b>Effect:</b> Copy-Constructs an <b>optional</b>.</p>
<p><b>Postconditions:</b> If <b>rhs</b> is initialized, <b>*this</b> is initialized
and its value is another reference to the same object referenced by <b>*rhs</b>; else <b>*this</b>
is uninitialized.</p>
<p><b>Throws:</b> Nothing.</p>
<p><b>Notes:</b> If <b>rhs</b> is initialized, both <b>*this</b> and <b>*rhs</b> will
reefer to the same object<b> </b>(they alias).</p>
<p><b>Example:</b></p>
<blockquote>
<pre>
optional<T&> uninit ;
assert (!uninit);
optional<T&> uinit2 ( uninit ) ;
assert ( uninit2 == uninit );
T v = 2 ; T& ref = v ;
optional<T> init(ref);
assert ( *init == v ) ;
optional<T> init2 ( init ) ;
assert ( *init2 == v ) ;
v = 3 ;
assert ( *init == 3 ) ;
assert ( *init2 == 3 ) ;
</pre>
</blockquote>
</blockquote>
<HR>
<pre>template<U> explicit optional<T <i>(not a ref)</i>>::optional( optional<U> const& rhs );</pre>
<blockquote>
<p><b>Effect:</b> Copy-Constructs an <b>optional</b>.</p>
<p><b>Postconditions:</b> If <b>rhs</b> is initialized, <b>*this</b> is initialized
and its value is a <i>copy</i> of the value of <b>rhs</b> <i>converted</i>
to type T; else <b>*this</b> is uninitialized.
</p>
<p><b>Throws:</b> Whatever T::T( U const& ) throws.</p>
<p><b>Notes:</b> T::T( U const& ) is called if <b>rhs</b> is initialized, which requires
a valid conversion from U to T.
</p>
<p><b>Exception Safety:</b> Exceptions can only be thrown during T::T( U const& );
in that case, this constructor has no effect.
</p>
<p><b>Example:</b></p>
<blockquote>
<pre>
optional<double> x(123.4);
assert ( *x == 123.4 ) ;
optional<int> y(x) ;
assert( *y == 123 ) ;
</pre>
</blockquote>
</blockquote>
<HR>
<pre>template<<i>InPlaceFactory</i>> explicit optional<T <i>(not a ref)</i>>::optional( <i>InPlaceFactory</i> const& f );</pre>
<pre>template<<i>TypedInPlaceFactory</i>> explicit optional<T <i>(not a ref)</i>>::optional( <i>TypedInPlaceFactory</i> const& f );</pre>
<blockquote>
<p><b>Effect:</b> Constructs an <b>optional</b> with a value of T obtained from
the factory.</p>
<p><b>Postconditions:</b> <b>*this</b> is <u>initialized</u> and its value is
<i>directly given</i> from the factory 'f' (i.e., the value<u> is not copied</u>).</p>
<p><b>Throws:</b> Whatever the T constructor called by the factory throws.</p>
<p><b>Notes:</b> See <A HREF="#inplace">In-Place Factories</A></p>
<p><b>Exception Safety:</b> Exceptions can only be thrown during the call to the
T constructor used by the factory;
in that case, this constructor has no effect.
</p>
<p><b>Example:</b></p>
<blockquote>
<pre>
class C { C ( char, double, std::string ) ; } ;
C v('A',123.4,"hello");
optional<C> x( in_place ('A', 123.4, "hello") ); // InPlaceFactory used
optional<C> y( in_place<C>('A', 123.4, "hello") ); // TypedInPlaceFactory used
assert ( *x == v ) ;
assert ( *y == v ) ;
</pre>
</blockquote>
</blockquote>
<HR>
<pre>optional& optional<T</i>>::operator= ( none_t n ) ;</pre>
<blockquote>
<p><b>Effect:</b> Same as opeator=(optional const& rhs), when rhs is default-constructed (uninitialized).</p>
<p><b>Postconditions:</b> <b>*this</b> is uninitialized</p>
<p><b>Example:</b></p>
<blockquote>
<pre>
#include <boost/none.hpp>
optional<int> def ;
optional<int> opt(123) ;
opt = boost::none ;
assert ( opt == def ) ;
</pre>
</blockquote>
</blockquote>
<HR>
<pre>optional& optional<T <i>(not a ref)</i>>::operator= ( T const& rhs ) ;</pre>
<blockquote>
<p><b>Effect:</b> Assigns the value 'rhs' to an <b>optional</b>.</p>
<p><b>Postconditions:</b> <b>*this</b> is initialized
and its value is a <i>copy</i> of <b>rhs.</b></p>
<p><b>Throws:</b> Whatever T::operator=( T const& ) or T::T(T const&) throws.</p>
<p><b>Notes:</b> If <b>*this</b> was initialized, T's assignment operator is
used, otherwise, its copy-constructor is used.</p>
<p><b>Exception Safety:</b> In the event of an exception, the initialization
state of <b>*this</b> is unchanged and its value unspecified as far as optional
is concerned (it is up to T's operator=()) [If <b>*this</b> is initially
uninitialized and T's <i>copy constructor</i> fails, <b>*this</b> is left
properly uninitialized]</p>
<p><b>Example:</b></p>
<blockquote>
<pre>
T x;
optional<T> def ;
optional<T> opt(x) ;
T y;
def = y ;
assert ( *def == y ) ;
opt = y ;
assert ( *opt == y ) ;</pre>
</blockquote>
</blockquote>
<HR>
<pre>optional<T&>& optional<T&>::operator= ( T& const& rhs ) ;</pre>
<blockquote>
<p><b>Effect:</b> (Re)binds thee wrapped reference.</p>
<p><b>Postconditions:</b> <b>*this</b> is initialized
and it references the same object referenced by <b>rhs.</b></p>
<p><b>Notes:</b> If <b>*this</b> was initialized, is is <i>rebound</i> to the
new object. See <A HREF="#refassign">here</a> for details on this behavior.</p>
<p><b>Example:</b></p>
<blockquote>
<pre>
int a = 1 ;
int b = 2 ;
T& ra = a ;
T& rb = b ;
optional<int&> def ;
optional<int&> opt(ra) ;
def = rb ; // binds 'def' to 'b' through 'rb'
assert ( *def == b ) ;
*def = a ; // changes the value of 'b' to a copy of the value of 'a'
assert ( b == a ) ;
int c = 3;
int& rc = c ;
opt = rc ; // REBINDS to 'c' through 'rc'
c = 4 ;
assert ( *opt == 4 ) ;
</pre>
</blockquote>
</blockquote>
<HR>
<pre>optional& optional<T <i>(not a ref)</i>>::operator= ( optional const& rhs ) ;</pre>
<blockquote>
<p><b>Effect:</b> Assigns another <b>optional</b> to an <b>optional</b>.</p>
<p><b>Postconditions:</b> If <b>rhs</b> is initialized, <b>*this</b> is initialized
and its value is a <i>copy</i> of the value of <b>rhs</b>; else <b>*this</b>
is uninitialized.
</p>
<p><b>Throws:</b> Whatever T::operator( T const&) or T::T( T const& ) throws.</p>
<p><b>Notes:</b> If both<b> *this</b> and <b>rhs</b> are initially initialized,
T's <i>assignment</i> <i>operator</i> is used. If <b>*this</b> is initially initialized but <b>
rhs</b> is uninitialized, T's <i>destructor</i> is called. If <b>*this</b> is initially
uninitialized but rhs is initialized, T's <i>copy constructor</i> is called.
</p>
<p><b>Exception Safety:</b> In the event of an exception, the initialization
state of <b>*this</b> is unchanged and its value unspecified as far as optional
is concerned (it is up to T's operator=()) [If <b>*this</b> is initially
uninitialized and T's <i>copy constructor</i> fails, <b>*this</b> is left
properly uninitialized]</p>
<p><b>Example:</b></p>
<blockquote>
<pre>T v;
optional<T> opt(v);
optional<T> def ;
opt = def ;
assert ( !def ) ;
// previous value (copy of 'v') destroyed from within 'opt'.
</pre>
</blockquote>
</blockquote>
<HR>
<pre>optional<T&> & optional<T&>::operator= ( optional<T&> const& rhs ) ;</pre>
<blockquote>
<p><b>Effect:</b> (Re)binds thee wrapped reference.</p>
<p><b>Postconditions:</b> If <b>*rhs</b> is initialized, *<b>this</b> is initialized
and it references the same object referenced by <b>*rhs</b>; otherwise, <b>*this</b>
is uninitialized (and references no object).</p>
<p><b>Notes:</b> If <b>*this</b> was initialized and so is <b>*rhs</b>, <b>this</b>
is is <i>rebound</i> to the new object. See <A HREF="#refassign">here</a> for details on this
behavior.</p>
<p><b>Example:</b></p>
<blockquote>
<pre>int a = 1 ;
int b = 2 ;
T& ra = a ;
T& rb = b ;
optional<int&> def ;
optional<int&> ora(ra) ;
optional<int&> orb(rb) ;
def = orb ; // binds 'def' to 'b' through 'rb' wrapped within 'orb'
assert ( *def == b ) ;
*def = ora ; // changes the value of 'b' to a copy of the value of 'a'
assert ( b == a ) ;
int c = 3;
int& rc = c ;
optional<int&> orc(rc) ;
ora = orc ; // REBINDS ora to 'c' through 'rc'
c = 4 ;
assert ( *ora == 4 ) ;
</pre>
</blockquote>
</blockquote>
<HR>
<pre>template<U> optional& optional<T <i>(not a ref)</i>>::operator= ( optional<U> const& rhs ) ;</pre>
<blockquote>
<p><b>Effect:</b> Assigns another <i>convertible</i> <b>optional</b> to an <b>optional</b>.</p>
<p><b>Postconditions:</b> If <b>rhs</b> is initialized, <b>*this</b> is initialized
and its value is a <i>copy</i> of the value of <b>rhs</b> <i>converted</i>
to type T; else <b>*this</b> is uninitialized.
</p>
<p><b>Throws:</b> Whatever T::operator=( U const& ) or T::T( U const& ) throws.</p>
<p><b>Notes:</b> If both<b> *this</b> and <b>rhs</b> are initially initialized,
T's <i>assignment</i> <i>operator</i> (from U) is used. If <b>*this</b> is initially initialized but <b>
rhs</b> is uninitialized, T's <i>destructor</i> is called. If <b>*this</b> is initially
uninitialized but rhs is initialized, T's <i>converting constructor</i> (from U) is called.
</p>
<p><b>Exception Safety:</b> In the event of an exception, the initialization
state of <b>*this</b> is unchanged and its value unspecified as far as optional
is concerned (it is up to T's operator=()) [If <b>*this</b> is initially
uninitialized and T's <i>converting constructor</i> fails, <b>*this</b> is left
properly uninitialized]</p>
<p><b>Example:</b></p>
<blockquote>
<pre>T v;
optional<T> opt0(v);
optional<U> opt1;
opt1 = opt0 ;
assert ( *opt1 == static_cast<U>(v) ) ;
</pre>
</blockquote>
</blockquote>
<HR>
<pre>void optional<T <i>(not a ref)</i>>::reset( T const& v ) ;</pre>
<blockquote>
<p><b>Deprecated:</b> same as operator= ( T const& v) ;</p>
</blockquote>
<HR>
<pre>void optional<T>::reset() ;</pre>
<blockquote>
<p><b>Deprecated: </b>Same as operator=( none_t n);</p>
</blockquote>
<HR>
<pre>T const& optional<T <i>(not a ref)</i>>::operator*() const ;
T& optional<T<i> (not a ref)</i>>::operator*();</pre>
<pre>T const& optional<T <i>(not a ref)</i>>::get() const ;
T& optional<T <i>(not a ref)</i>>::get() ;
inline T const& get ( optional<T<i> (not a ref)</i>> const& ) ;
inline T& get ( optional<T <i>(not a ref)</i>> &) ;
</pre>
<blockquote>
<p><b>Requirements: *this</b> is initialized</p>
<p><b>Returns:</b> A reference to the contained value</p>
<p><b>Throws:</b> Nothing.</p>
<p><b>Notes:</b> The requirement is asserted via BOOST_ASSERT().</p>
<p><b>Example:</b></p>
<blockquote>
<pre>T v ;
optional<T> opt ( v );
T const& u = *opt;
assert ( u == v ) ;
T w ;
*opt = w ;
assert ( *opt == w ) ;
</pre>
</blockquote>
<pre></pre>
</blockquote>
<HR>
<pre>T const& optional<T&>::operator*() const ;
T & optional<T<i>&</i>>::operator*();</pre>
<pre>T const& optional<T&>::get() const ;
T& optional<T&>::get() ;
inline T const& get ( optional<T<i>&</i>> const& ) ;
inline T& get ( optional<T&> &) ;
</pre>
<blockquote>
<p><b>Requirements: *this</b> is initialized</p>
<p><b>Returns:</b> <u>The</u> reference contained.</p>
<p><b>Throws:</b> Nothing.</p>
<p><b>Notes:</b> The requirement is asserted via BOOST_ASSERT().</p>
<p><b>Example:</b></p>
<blockquote>
<pre>T v ;
T& vref = v ;
optional<T&> opt ( vref );
T const& vref2 = *opt;
assert ( vref2 == v ) ;
++ v ;
assert ( *opt == v ) ;</pre>
</blockquote>
</blockquote>
<HR>
<pre>T const& optional<T>::get_value_or( T const& default) const ;
T& optional<T>::get_value_or( T& default ) ;
inline T const& get_optional_value_or ( optional<T> const& o, T const& default ) ;
inline T& get_optional_value_or ( optional<T>& o, T& default ) ;
</pre>
<blockquote>
<p><b>Returns:</b> A reference to the contained value (which can be itself a reference), if any, or <code>default</code></p>
<p><b>Throws:</b> Nothing.</p>
<p><b>Example:</b></p>
<blockquote>
<pre>T v, z ;
optional<T> def;
T const& y = def.get_value_or(z);
assert ( y == z ) ;
optional<T> opt ( v );
T const& u = get_optional_value_or(opt,z);
assert ( u == v ) ;
assert ( u != z ) ;
</pre>
</blockquote>
<pre></pre>
</blockquote>
<HR>
<pre>T const* optional<T>::get_ptr() const ;
T* optional<T>::get_ptr() ;
inline T const* get_pointer ( optional<T> const& ) ;
inline T* get_pointer ( optional<T> &) ;
</pre>
<blockquote>
<p><b>Returns:</b> If <b>*this</b> is initialized, a pointer to the contained
value; else 0 (<i>null</i>).
</p>
<p><b>Throws:</b> Nothing.</p>
<p><b>Notes:</b> If T is a reference type, the pointer is to the referenced object</p>
<p><b>Notes:</b> The contained value is permanently stored within *this, so
you should not hold nor delete this pointer.
</p>
<p><b>Example:</b></p>
<blockquote>
<pre>int v=123;
optional<int> opt(v);
optional<int> const copt(v);
int* p = opt.get_ptr() ;
int const* cp = copt.get_ptr();
assert ( p == get_pointer(opt) );
assert ( cp == get_pointer(copt) ) ;
int& rv = v ;
optional<int&> optr(rv);
*(optr.get_ptr()) = 456 ;
assert ( v == 456 );
</pre>
</blockquote>
</blockquote>
<HR>
<pre>T const* optional<T>::operator ->() const ;
T* optional<T>::operator ->() ;
</pre>
<blockquote>
<p><b>Requirements: *this</b> is initialized.</p>
<p><b>Returns:</b> A pointer to the contained value.</p>
<p><b>Throws:</b> Nothing.</p>
<p><b>Notes:</b> If T is a reference type, the pointer is to the referenced object</p>
<p><b>Notes:</b> The requirement is asserted via BOOST_ASSERT().</p>
<p><b>Example:</b></p>
<blockquote>
<pre>struct X { int mdata ; } ;
X x ;
optional<X> opt (x);
opt->mdata = 2 ;
X& rx = x ;
optional<X&> optr (rx);
optr->mdata = 4 ;
assert ( x.mdata = 4 )
</pre>
</blockquote>
</blockquote>
<HR>
<pre>optional<T>::operator <i>unspecified-bool-type</i>() const ;</pre>
<blockquote>
<p><b>Returns:</b> An unspecified value which if used on a boolean context is equivalent to (get() != 0)</p>
<p><b>Throws:</b> Nothing.</p>
<blockquote>
<pre>optional<T> def ;
assert ( def == 0 );
optional<T> opt ( v ) ;
assert ( opt );
assert ( opt != 0 );
</pre>
</blockquote>
</blockquote>
<HR>
<pre> bool optional<T>::operator!() ;</pre>
<blockquote>
<p><b>Returns:</b> If <b>*this</b> is uninitialized, <code>true</code>; else <code>false.</code></p>
<p><b>Throws:</b> Nothing.</p>
<p><b>Notes:</b> This operator is provided for those compilers which can't use
the <i>unspecified-bool-type</i> operator in certain boolean contexts.
</p>
<p><b>Example:</b></p>
<blockquote>
<pre>optional<T> opt ;
assert ( !opt );
*opt = some_T ;
// Notice the "double-bang" idiom here.
assert ( !!opt ) ;
</pre>
</blockquote>
</blockquote>
<HR>
<pre>bool optional<T>::is_initialized() const ;</pre>
<blockquote>
<p><b>Returns:</b> <i>true</i> is the <b>optional</b> is initialized, <i>false</i>
otherwise.</p>
<p><b>Throws:</b> Nothing.</p>
<blockquote>
<pre>optional<T> def ;
assert ( !def.is_initialized() );
optional<T> opt ( v ) ;
assert ( opt.is_initialized() );</pre>
</blockquote>
</blockquote>
<HR>
<pre>optional<T <i>(not a ref)</i>> make_optional( T const& v )</pre>
<blockquote>
<p><b>Returns:</b> optional<T>(v) for the <i>deduced</i> type <code>T</code> of <code>v</code>.</p>
<p><b>Example:</b></p>
<blockquote>
<pre>template<class T> void foo ( optional<T> const& opt ) ;
foo ( make_optional(1+1) ) ; // Creates an optional<int>
</blockquote>
</blockquote>
<HR>
<pre>optional<T <i>(not a ref)</i>> make_optional( bool condition, T const& v )</pre>
<blockquote>
<p><b>Returns:</b> optional<T>(condition,v) for the <i>deduced</i> type <code>T</code> of <code>v</code>.</p>
<p><b>Example:</b></p>
<blockquote>
<pre>optional<double> calculate_foo()
{
double val = compute_foo();
return make_optional(is_not_nan_and_finite(val),val);
}
optional<double> v = calculate_foo();
if ( !v )
error("foo wasn't computed");
</blockquote>
</blockquote>
<HR>
<pre>bool operator == ( optional<T> const& x, optional<T> const& y );</pre>
<blockquote>
<p><b>Returns:</b> If both <b>x</b> and <b>y</b> are initialied, <code>(*x == *y)</code>.
If only x or y is initialized, <code>false</code>. If both are uninitialized, <code>true</code>. </p>
<p><b>Throws:</b> Nothing.</p>
<p><b>Notes:</b> Pointers have shallow relational operators while <b>optional</b> has
deep relational operators. Do not use operator == directly in generic code
which expect to be given either an optional<T> or a pointer;
use <a href="../../utility/OptionalPointee.html#equal">equal_pointees()</a> instead </p>
<p><b>Example:</b></p>
<blockquote>
<pre>T x(12);
T y(12);
T z(21);
optional<T> def0 ;
optional<T> def1 ;
optional<T> optX(x);
optional<T> optY(y);
optional<T> optZ(z);
// Identity always hold
assert ( def0 == def0 );
assert ( optX == optX );
// Both uninitialized compare equal
assert ( def0 == def1 );
// Only one initialized compare unequal.
assert ( def0 != optX );
// Both initialized compare as (*lhs == *rhs)
assert ( optX == optY ) ;
assert ( optX != optZ ) ;
</pre>
</blockquote>
</blockquote>
<HR>
<pre>bool operator < ( optional<T> const& x, optional<T> const& y );</pre>
<blockquote>
<p><b>Returns:</b> If <b>y</b> is not initialized, <code>false</code>.
If <b>y</b> is initialized and <b>x</b> is not initialized, <code>true</code>.
If both <b>x</b> and <b>y</b> are initialized, <code>(*x < *y)</code>. </p>
<p><b>Throws:</b> Nothing.</p>
<p><b>Notes:</b> Pointers have shallow relational operators while <b>optional</b> has
deep relational operators. Do not use operator < directly in generic code
which expect to be given either an optional<T> or a pointer;
use <a href="../../utility/OptionalPointee.html#less">less_pointees()</a> instead </p>
<p><b>Example:</b></p>
<blockquote>
<pre>T x(12);
T y(34);
optional<T> def ;
optional<T> optX(x);
optional<T> optY(y);
// Identity always hold
assert ( !(def < def) );
assert ( optX == optX );
// Both uninitialized compare equal
assert ( def0 == def1 );
// Only one initialized compare unequal.
assert ( def0 != optX );
// Both initialized compare as (*lhs == *rhs)
assert ( optX == optY ) ;
assert ( optX != optZ ) ;
</pre>
</blockquote>
</blockquote>
<HR>
<pre>bool operator != ( optional<T> const& x, optional<T> const& y );
</pre>
<blockquote>
<p><b>Returns:</b> !( x == y );</p>
<p><b>Throws:</b> Nothing.</p>
</blockquote>
<HR>
<pre>bool operator > ( optional<T> const& x, optional<T> const& y );
</pre>
<blockquote>
<p><b>Returns:</b> ( y < x );</p>
<p><b>Throws:</b> Nothing.</p>
</blockquote>
<HR>
<pre>bool operator <= ( optional<T> const& x, optional<T> const& y );
</pre>
<blockquote>
<p><b>Returns:</b> !( y<x );</p>
<p><b>Throws:</b> Nothing.</p>
</blockquote>
<HR>
<pre>bool operator >= ( optional<T> const& x, optional<T> const& y );
</pre>
<blockquote>
<p><b>Returns:</b> !( x<y );</p>
<p><b>Throws:</b> Nothing.</p>
</blockquote>
<HR>
<pre>
bool operator == ( optional<T> const& x, T const& n );
bool operator != ( optional<T> const& x, T const& n );
bool operator < ( optional<T> const& x, T const& n );
bool operator > ( optional<T> const& x, T const& n );
bool operator <= ( optional<T> const& x, T const& n );
bool operator >= ( optional<T> const& x, T const& n );
bool operator == ( T const& n, optional<T> const& y );
bool operator != ( T const& n, optional<T> const& y );
bool operator < ( T const& n, optional<T> const& y );
bool operator > ( T const& n, optional<T> const& y );
bool operator <= ( T const& n, optional<T> const& y );
bool operator >= ( T const& n, optional<T> const& y );
</pre>
<blockquote>
<p><b>Returns:</b> The result obtained by replacing the argument 'n' by optional<T>(n).</p>
</blockquote>
<HR>
<pre>
bool operator == ( optional<T> const& x, none_t n );
bool operator != ( optional<T> const& x, none_t n );
bool operator < ( optional<T> const& x, none_t n );
bool operator > ( optional<T> const& x, none_t n );
bool operator <= ( optional<T> const& x, none_t n );
bool operator >= ( optional<T> const& x, none_t n );
bool operator == ( none_t n, optional<T> const& y );
bool operator != ( none_t n, optional<T> const& y );
bool operator < ( none_t n, optional<T> const& y );
bool operator > ( none_t n, optional<T> const& y );
bool operator <= ( none_t n, optional<T> const& y );
bool operator >= ( none_t n, optional<T> const& y );
</pre>
<blockquote>
<p><b>Returns:</b> The result obtained by replacing the argument 'n' by optional<T>().</p>
</blockquote>
<HR>
<pre>void swap ( optional<T>& x, optional<T>& y );</pre>
<blockquote>
<p><b>Effect:</b> If both <b>x</b> and <b>y</b> are initialized, calls <code>swap(*x,*y)</code> using std::swap.<br>
If only one is initialized, say x, calls: <code>y = *x; x = boost:none;</code><br>
If none is initialized, does nothing. </p>
<p><b>Postconditions:</b> The states of x and y interchanged.</p>
<p><b>Throws:</b> If both are initialized, whatever swap(T&,T&) throws.
If only one is initialized, whatever T::T ( T const& ) throws. </p>
<p><b>Notes:</b> If both are initialized, swap(T&,T&) is used <i>unqualified</i> but with std::swap introduced in scope.<br>
If only one is initialized, T::~T() and T::T( T const& ) is called. </p>
<p><b>Exception Safety:</b> If both are initialized, this operation has the exception
safety guarantees of swap(T&,T&).<br>
If only one is initialized, it has the same <b>basic</b> guarantee as optional<T>::operator=( T const& ). </p>
<p><b>Example:</b></p>
<blockquote>
<pre>T x(12);
T y(21);
optional<T> def0 ;
optional<T> def1 ;
optional<T> optX(x);
optional<T> optY(y);
boost::swap(def0,def1); // no-op
boost::swap(def0,optX);
assert ( *def0 == x );
assert ( !optX );
boost::swap(def0,optX); // Get back to original values
boost::swap(optX,optY);
assert ( *optX == y );
assert ( *optY == x );
</pre>
</blockquote>
</blockquote>
<HR>
<H2><A NAME="examples">Examples</A></H2>
<h3>Optional return values</h3>
<PRE>optional<char> get_async_input()
{
if ( !queue.empty() )
return optional<char>(queue.top());
else return optional<char>(); // uninitialized
}
void receive_async_message()
{
optional<char> rcv ;
// The safe boolean conversion from 'rcv' is used here.
while ( (rcv = get_async_input()) && !timeout() )
output(*rcv);
}
</pre>
<h3>Optional local variables</h3>
<pre>optional<string> name ;
if ( database.open() )
{
name = database.lookup(employer_name) ;
}
else
{
if ( can_ask_user )
name = user.ask(employer_name) ;
}
if ( name )
print(*name);
else print("employer's name not found!");
</pre>
<h3>Optional data members</h3>
<pre>class figure
{
public:
figure()
{
// data member 'm_clipping_rect' is uninitialized at this point.
}
void clip_in_rect ( rect const& rect )
{
....
m_clipping_rect = rect ; // initialized here.
}
void draw ( canvas& cvs )
{
if ( m_clipping_rect )
do_clipping(*m_clipping_rect);
cvs.drawXXX(..);
}
// this can return NULL.
rect const* get_clipping_rect() { return get_pointer(m_clipping_rect); }
private :
optional<rect> m_clipping_rect ;
};
</pre>
<h3>Bypassing expensive unnecessary default construction</h3>
<pre>class ExpensiveCtor { ... } ;
class Fred
{
Fred() : mLargeVector(10000) {}
std::vector< optional<ExpensiveCtor> > mLargeVector ;
} ;
</pre>
<HR>
<H2><A NAME="ref">Optional references</A></H2>
<p>This library allows the template parameter T to be of reference type: T&, and
to some extent, T const&.</p>
<p>However, since references are not real objects some restrictions apply and
some operations are not available in this case:</p>
<ul>
<li>Converting constructors</li>
<li>Converting assignment</li>
<li>InPlace construction</li>
<li>InPlace assignment</li>
</ul>
<p>Also, even though optional<T&> treats it wrapped pseudo-object much as a real
value, a true real reference is stored, thus aliasing can ocurr: </p>
<ul>
<li>Copies of optional<T&> copies the reference, but all copied references
will nonetheless reefer to the same object.</li>
<li>Value-access provides access to the referenced object rather
than the reference itself.</li>
<li>Pointer-access provides a pointer to the referenced object rather
than a pointer to the reference itself.</li>
</ul>
<HR>
<h2><A NAME="refassign">Rebinding semantics for assignment of optional
references</a></h2>
<p>If you assign to an <i>uninitialized</i> optional<T&> the effect is to bind (for the first time) to the object.
Clearly, there is no other choice.</p>
<pre>int x = 1 ;
int& rx = x ;
optional<int&> ora ;
optional<int&> orb(rx) ;
ora = orb ; // now 'ora' is bound to 'x' through 'rx'
*ora = 2 ; // Changes value of 'x' through 'ora'
assert(x==2);
</pre>
<p>If you assign to a bare C++ reference, the assignment is forwarded to the
referenced object; it's value changes but the reference is never rebound.</p>
<pre>int a = 1 ;
int& ra = a ;
int b = 2 ;
int& rb = b ;
ra = rb ; // Changes the VALUE of 'a' to that of 'b'
assert(a==b);
b = 3 ;
assert(ra!=b); // 'ra' is not rebound to 'b'
</pre>
<p>Now, if you assign to an <i>initialized</i> optional<T&>, the effect is to <b>rebind</b> to the new object instead of assigning the referee. This is unlike
bare C++ references.</p>
<pre>int a = 1 ;
int b = 2 ;
int& ra = a ;
int& rb = b ;
optional<int&> ora(ra) ;
optional<int&> orb(rb) ;
ora = orb ; // 'ora' is <b>rebound</b> to 'b'
*ora = 3 ; // Changes value of 'b' (not 'a')
assert(a==1);
assert(b==3);
</pre>
<h3>Rationale:</h3>
<p>Rebinding semantics for the assignment of <i>initialized</i> optional
references has been chosen to provide<b><i> </i>consistency among initialization
states<i> </i></b>even at the expense of lack of consistency with the semantics of bare
C++ references.<br>
It is true that optional<U> strives to behave as much as possible as U does
whenever it is initialized; but in the case when U is T&, doing so would result
in inconsistent behavior w.r.t to the lvalue initialization state.</p>
<p>Consider the following code :</p>
<pre>
int x = 1 ;
int& rx = x ;
void foo ( optional<int&> & outer )
{
optional<int&> b(rx);
outer = b ;
}
</pre>
<p>What should the assignment to 'outer' do?<br>
If 'outer' is <i>uninitialized</i>, the answer is clear: it should bind to 'x' (so we now have
a second reference to 'x').<br>
But what if 'outer' is already <i>initialized?</i><br>
The assignment could change the value of the
referenced object (whatever that is), but doing that would be inconsistent with the uninitialized case
and then you wouldn't be able to reason at compile time about all the references to x since
the appearance of a new reference to it would depend on wheter the lvalue ('outer')
is initialized or not.</p>
<p>Arguably, if rebinding the reference to another object is wrong for your code, then is
likely that binding it for the fist time via assignment instead of intialization is also wrong.
In that case, you can always just assign the value to the referenced object directly via
the access operator <code>*opt=value</code>.</p>
<p>If rebinding is wrong but first-time binding
isn't (via assignment), you can always work around the rebinding semantics using a discriminator:</p>
<pre>
if ( !opt )
opt = value ; // first-time binding
else *opt = value ; // assign to referee without rebinding
</pre>
<HR>
<H2><A NAME="none">none_t and none</A></H2>
<p>optional<T> supports uninitialized states with a convenient syntax via a constant of
the <i>implementation-defined</i> type <code>boost::none_t</code>, identified as <code>boost::none</code>.</p>
<p>Starting with Boost version 1.34.0, both <code>boost::none_t</code> and <code>boost::none</code> are
included in <code>boost/none.hpp</code>, which is automatically included by <code>boost/optional/optional.hpp</code>
</p>
<p>This contant is similar in purpose to NULL, except that is not a <i>null pointer value</i>. You can use it to initialize
an optional<T> instance, which has the same effect of a default constructor, and you can assign it which has the
effect of reseting the optional<T> instance. You can also use it in relational operators to make the predicate expression
more clear.</p>
<p>Here are some typical examples:</p>
<pre>
#include "boost/optional/optional.hpp" // boost/none.hpp is included automatically
boost::optional<int> foo ( int a )
{
return some_condition(a) ? boost::make_optional(a) : boost::none ;
// NOTE: in real code you can just use this: make_optional(some_condition(a), a )
}
boost::optional<int> opt = boost::none ;
if ( opt == boost::none )
opt = foo(123);
opt = boost::none ;
</pre>
<HR>
<H2><A NAME="inplace">In-Place Factories</A></H2>
<p>
One of the typical problems with wrappers and containers is that their
interfaces usually provide an operation to initialize or assign the contained
object as a copy of some other object. This not only requires the underlying
type to be <a href="../../utility/CopyConstructible.html">Copy Constructible</a>, but also requires the existence of a fully
constructed object, often temporary, just to follow the copy from:</p>
<pre>struct X
{
X ( int, std:::string ) ;
} ;</pre>
<pre>class W
{
X wrapped_ ;
public:
W ( X const& x ) : wrapped_(x) {}
} ;</pre>
<pre>void foo()
{
// Temporary object created.
W ( X(123,"hello") ) ;
}
</pre>
<p>A solution to this problem is to support direct construction of the contained
object right in the container's storage.<br>
In this scheme, the user only needs to supply the arguments to the constructor
to use in the wrapped object construction.</p>
<pre>class W
{
X wrapped_ ;
public:
W ( X const& x ) : wrapped_(x) {}
W ( int a0, std::string a1) : wrapped_(a0,a1) {}
} ;</pre>
<pre>void foo()
{
// Wrapped object constructed in-place
// No temporary created.
W (123,"hello") ;
}
</pre>
<p>A limitation of this method is that it doesn't scale well to wrapped objects with multiple
constructors nor to generic code were the constructor overloads are unknown.</p>
<p>The solution presented in this library is the family of <b>InPlaceFactories</b> and <b>TypedInPlaceFactories</b>.<br>
These factories are a family of classes which encapsulate an increasing number of arbitrary
constructor parameters and supply a method to construct an object of a given type using those
parameters at an address specified by the user via placement new.</p>
<p> For example, one member of this family looks like:</p>
<pre>template<class T,class A0, class A1>
class TypedInPlaceFactory2
{
A0 m_a0 ; A1 m_a1 ;
public:
TypedInPlaceFactory2( A0 const& a0, A1 const& a1 ) : m_a0(a0), m_a1(a1) {}
void construct ( void* p ) { new (p) T(m_a0,m_a1) ; }
} ;
</pre>
<p>A wrapper class aware of this can use it as:</p>
<pre>class W
{
X wrapped_ ;
public:
W ( X const& x ) : wrapped_(x) {}
W ( TypedInPlaceFactory2 const& fac ) { fac.construct(&wrapped_) ; }
} ;</pre>
<pre>void foo()
{
// Wrapped object constructed in-place via a TypedInPlaceFactory.
// No temporary created.
W ( TypedInPlaceFactory2<X,int,std::string&rt;(123,"hello")) ;
}
</pre>
<p>The factories are divided in two groups:<ul>
<li><u>TypedInPlaceFactories</u>: those which take the target type as a primary template parameter.</li>
<li><u>InPlaceFactories</u>: those with a template <code>construct(void*)</code> member function taking the target type.</li>
</ul>
<p>Within each group, all the family members differ only in the number of parameters allowed.</p>
<p></p>
<p>This library provides an overloaded set of helper template functions to construct these factories
without requiring unnecessary template parameters:</p>
<pre>template<class A0,...,class AN>
InPlaceFactory<i>N </i><A0,...,AN> <b>in_place</b> ( A0 const& a0, ..., AN const& aN) ;
template<class T,class A0,...,class AN>
TypedInPlaceFactory<i>N </i><T,A0,...,AN> <b>in_place</b> ( T const& a0, A0 const& a0, ..., AN const& aN) ;</pre>
<p>In-place factories can be used generically by the wrapper and user as follows:</p>
<pre>class W
{
X wrapped_ ;
public:
W ( X const& x ) : wrapped_(x) {}
template<class InPlaceFactory></class>
W ( InPlaceFactory const& fac ) { fac.template <X>construct(&wrapped_) ; }
} ;</pre>
<pre>void foo()
{
// Wrapped object constructed in-place via a InPlaceFactory.
// No temporary created.
W ( in_place(123,"hello") ) ;
}
</pre>
<p>The factories are implemented in the headers: <a href="../../../boost/utility/in_place_factory.hpp">in_place_factory.hpp</a> and <a href="../../../boost/utility/typed_in_place_factory.hpp">typed_in_place_factory.hpp</a> </p>
<HR>
<H2><A NAME="bool">A note about optional<bool></A></H2>
<p><code>optional<bool></code> should be used with special caution and consideration.</p>
<p>First, it is functionally similar to a tristate boolean (false,maybe,true) —such as <a href="http://www.boost.org/doc/html/tribool.html">boost::tribool</a>—except that in a tristate boolean,
the <i>maybe</i> state <u>represents a valid value</u>, unlike the corresponding state
of an uninitialized optional<bool>.<br>
It should be carefully considered if an optional<bool> instead of a tribool is really needed</p>
<p>Second, optional<> provides a simple way to test initialization state: an implicit conversion to a type that evaluates as a 'bool' in a boolean context.<br>
Using optional<bool> can lead to subtle errors due to this implicit conversion:</p>
<pre>void foo ( bool v ) ;
void bar()
{
optional<bool> v = try();
// The following intended to pass the <b>value</b> of 'v' to foo():
foo(v);
// But instead, the <i>initialization state</i> is passed
// due to a typo: it should have been foo(<b>*</b>v).
}
</pre>
<p>The only implicit conversion is to bool, and it is <i>safe</i> in the sense that typical
integral promotions don't apply (i.e. if foo() takes an 'int' instead, it won't compile). <HR>
<H2><A NAME="exsafety">Exception Safety Guarantees</A></H2>
<H3><u>Assignment:</u></H3>
<p><i>IMPORTANT NOTE: This changed in 1.33.1 with respect to previous versions</i></p>
<p>Because of the current implementation (see <A HREF="#impl">Implementation Notes</A>), all
of the assignment methods:</p>
<ul>
<li> <code>optional<T>::operator= ( optional<T> const& ) </code>
</li>
<li> <code>optional<T>::operator= ( T const& ) </code></li>
<li> <code>template<class U> optional<T>::operator= ( optional<U> const& ) </code>
</li>
<li> <code>template<class InPlaceFactory> optional<T>::operator= (
InPlaceFactory const& ) </code></li>
<li> <code>template<class TypedInPlaceFactory> optional<T>::operator= (
TypedInPlaceFactory const& ) </code></li>
</ul>
<p>cannot offer any <i>exception safety guarantee</i> beyond that provided by <code>T::operator=( T const& )</code></p>
<p>On the other hand, the <i>uninitializing</i> methods:</p>
<ul>
<li><code>optional<T>::operator= ( detail::none_t ) </code></li>
</ul>
<p>Provides the no-throw guarantee (assuming a no-throw T::~T()) becuse it only destroys the stored object.</p>
<H3><u>Swap:</u></H3>
<p><code>void swap( optional<T>&, optional<T>& )</code> has the same exception guarantee as <code>swap(T&,T&)</code> when both optionals are initialized.<br>
If only one of the optionals is initialized, it gives the same exception guarantee as <code>T::operator=( T const& )</code> (since <code>optional<T>::operator=( none_t )</code> doesn't throw).<br>
If none of the optionals is initialized, it has no-throw guarantee since it is a no-op. </p>
<HR>
<H2><A NAME="requirements">Type requirements</A></H2>
<p>In general, T must be <a href="../../utility/CopyConstructible.html">Copy Constructible</a> and have a no-throw destructor. The copy-constructible requirement is not needed
if InPlaceFactories are used.<br>
T <u>is not</u> required to be <a href="http://www.sgi.com/tech/stl/DefaultConstructible.html">Default Constructible</a> </p>
<HR>
<H2><A NAME="impl">Implementation Notes</A></H2>
<p>optional<T> is currently implemented
using a custom aligned storage facility built from <code>alignment_of</code> and <code>type_with_alignment</code> (both from Type Traits).
It uses a separate boolean flag to indicate the initialization state.</p>
<p>Placement new with T's copy constructor and T's destructor
is explicitly used to initialize and destroy optional values. This allows T's default constructor to be effectively by-passed.</p>
<p>If assignment is used and the lvalue optional is uninitialized, T's copy constructor is used. However, if it is already initialized, T's assignment operator is used. This prevents optional from offering any exception guarantee stronger than the one offered by the type T itself</p>
<HR>
<H2><A NAME="porta">Dependencies and Portability</A></H2>
<p>The implementation uses <code>type_traits/alignment_of.hpp</code> and <code>type_traits/type_with_alignment.hpp</code></p>
<HR>
<H2><A NAME="credits">Acknowledgments</A></H2>
<p>Pre-formal review:</p>
<blockquote>
<p>Peter Dimov suggested the name 'optional', and was the first to point out the
need for aligned storage<br>
Douglas Gregor developed 'type_with_alignment', and later Eric Friedman coded
'aligned_storage', which are the core of the optional class implementation.<br>
Andrei Alexandrescu and Brian Parker also worked with aligned storage techniques
and their work influenced the current implementation.<br>
Gennadiy Rozental made extensive and important comments which shaped the design.<br>
Vesa Karvonen and Douglas Gregor made quite useful comparisons between optional,
variant and any; and made other relevant comments. Douglas Gregor and Peter
Dimov commented on comparisons and evaluation in boolean contexts.<br>
Eric Friedman helped understand the issues involved with aligned storage, move/copy
operations and exception safety.<br>
Many others have participated with useful comments: Aleksey Gurotov, Kevlin
Henney, David Abrahams, and others I can't recall. </p>
</blockquote>
<p>Post-formal review:</p>
<blockquote>
<p>William Kempf carefully considered the originally proposed interface and
suggested the new interface which is currently used. He also started and fueled
the discussion about the analogy optional<>/smart pointer and about
relational operators.<br>
Peter Dimov, Joel de Guzman, David Abrahams, Tanton Gibbs and Ian Hanson focused
on the relational semantics of optional (originally undefined); concluding
with the fact that the pointer-like interface doesn't make it a pointer so
it shall have deep relational operators.<br>
Augustus Saunders also explored the different relational semantics between
optional<> and a pointer and developed the OptionalPointee concept as
an aid against potential conflicts on generic code.<br>
Joel de Guzman noticed that optional<> can be seen as an API on top
of variant<T,nil_t>.<br>
Dave Gomboc explained the meaning and usage of the Haskell analog to optional<>:
the Maybe type constructor (analogy originally pointed out by David Sankel).<br>
Other comments were posted by Vincent Finn, Anthony Williams, Ed Brey, Rob
Stewart, and others.<br>
Joel de Guzman made the case for the support of references and helped with
the proper semantics.<br>
Mat Marcus shown the virtues of a value-oriented interface, influencing the
current design, and contributed the idea of "none".</p>
</blockquote>
<HR>
<P>Revised March 27, 2007</P>
<p> Copyright Fernando Luis Cacciola Carballal, 2003-2007</p>
<p> Use, modification, and distribution are subject to the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
<P>Developed by <A HREF="mailto:fernando_cacciola@hotmail.com">Fernando Cacciola</A>,
the latest version of this file can be found at <A
HREF="http://www.boost.org">www.boost.org</A>, and the boost <A HREF="http://www.boost.org/more/mailing_lists.htm#main">discussion lists</A></P>
</pre></BODY>
</HTML>
|