summaryrefslogtreecommitdiff
path: root/libs/optional/doc/16_optional_bool.qbk
blob: 6f3664fe71b78405a33963544f433f7320f73897 (plain)
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

[section A note about optional<bool>]

`optional<bool>` should be used with special caution and consideration.

First, it is functionally similar to a tristate boolean (false, maybe, true)
—such as __BOOST_TRIBOOL__— except that in a tristate boolean, the maybe state
[_represents a valid value], unlike the corresponding state of an uninitialized
`optional<bool>`.
It should be carefully considered if an `optional<bool>` instead of a `tribool`
is really needed.

Second, although `optional<>` provides a contextual conversion to `bool` in C++11,
 this falls back to an implicit conversion on older compilers. This conversion refers
 to the initialization state and not to the contained value. Using `optional<bool>`
 can lead to subtle errors due to the implicit `bool` conversion:

    void foo ( bool v ) ;
    void bar()
    {
        optional<bool> v = try();

        // The following intended to pass the value of 'v' to foo():
        foo(v);
        // But instead, the initialization state is passed
        // due to a typo: it should have been foo(*v).
    }

The only implicit conversion is to `bool`, and it is safe in the sense that
typical integral promotions don't apply (i.e. if `foo()` takes an `int`
instead, it won't compile).

Third, mixed comparisons with `bool` work differently than similar mixed comparisons between pointers and `bool`, so the results might surprise you:

    optional<bool> oEmpty(none), oTrue(true), oFalse(false);
    
    if (oEmpty == none);  // renders true
    if (oEmpty == false); // renders false!
    if (oEmpty == true);  // renders false!
     
    if (oFalse == none);  // renders false
    if (oFalse == false); // renders true!
    if (oFalse == true);  // renders false
    
    if (oTrue == none);   // renders false
    if (oTrue == false);  // renders false
    if (oTrue == true);   // renders true

In other words, for `optional<>`, the following assertion does not hold:

    assert((opt == false) == (!opt));
[endsect]