summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/convert/example/algorithms.cpp
blob: 6235fbfb3540efda62ac4d78e333f72b71ed5543 (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
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
// Copyright (c) 2009-2016 Vladimir Batov.
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.

#include <boost/convert.hpp>
#include <boost/convert/stream.hpp>
#include <boost/convert/lexical_cast.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <vector>

using std::string;

static
void
introduction()
{
//[algorithm_introduction

   /*`The following code demonstrates conversion of an array of integers from their textual ['hexadecimal]
      representation. It assigns -1 to those which fail to convert:
   */

    boost::array<char const*, 3> strs = {{ " 5", "0XF", "not an int" }};
    std::vector<int>             ints;
    boost::cnv::cstream           cnv;

    // Configure converter to read hexadecimal, skip (leading) white spaces.
    cnv(std::hex)(std::skipws);

    std::transform(strs.begin(), strs.end(), std::back_inserter(ints),
        boost::cnv::apply<int>(boost::cref(cnv)).value_or(-1));

    BOOST_TEST(ints.size() == 3); // Number of values processed.
    BOOST_TEST(ints[0] ==  5);    // " 5"
    BOOST_TEST(ints[1] == 15);    // "0XF"
    BOOST_TEST(ints[2] == -1);    // "not an int"
//]
}

static
void
example1()
{
//[algorithm_example1
    /*`The following code demonstrates a failed attempt (and one of the reasons ['Boost.Convert]
       has been developed) to convert a few `string`s to `int`s with `boost::lexical_cast`:
    */

    boost::array<char const*, 3> strs = {{ " 5", "0XF", "not an int" }};
    std::vector<int>             ints;

    try
    {
        std::transform(strs.begin(), strs.end(), std::back_inserter(ints),
            boost::bind(boost::lexical_cast<int, string>, _1));

        BOOST_TEST(0 && "Never reached!");
    }
    catch (std::exception&)
    {
        BOOST_TEST(ints.size() == 0); // No strings converted.
    }
//]
}

static
void
example2()
{
//[algorithm_example2
    /*`If the exception-throwing behavior is the desired behavior, then ['Boost.Convert] supports that.
      In addition, it also supports a non-throwing process-flow:
    */
    boost::array<char const*, 3> strs = {{ " 5", "0XF", "not an int" }};
    std::vector<int>             ints;

    std::transform(strs.begin(), strs.end(), std::back_inserter(ints),
        boost::cnv::apply<int>(boost::cnv::lexical_cast()).value_or(-1));

    BOOST_TEST(ints.size() == 3);
    BOOST_TEST(ints[0] == -1); // Failed conversion does not throw.
    BOOST_TEST(ints[1] == -1); // Failed conversion does not throw.
    BOOST_TEST(ints[2] == -1); // Failed conversion does not throw.
//]
}

static
void
example3()
{
//[algorithm_example3
    /*`Deploying `boost::cnv::cstream` with better formatting capabilities yields
       better results with exception-throwing and non-throwing process-flows still supported:
    */

    boost::array<char const*, 3> strs = {{ " 5", "0XF", "not an int" }};
    std::vector<int>             ints;
    boost::cnv::cstream           cnv;

    try
    {
        std::transform(strs.begin(), strs.end(), std::back_inserter(ints),
            boost::cnv::apply<int>(boost::cref(cnv(std::hex)(std::skipws))));

        BOOST_TEST(0 && "Never reached!");
    }
    catch (boost::bad_optional_access const&)
    {
        BOOST_TEST(ints.size() == 2); // Only the first two strings converted.
        BOOST_TEST(ints[0] ==  5);    // " 5"
        BOOST_TEST(ints[1] == 15);    // "0XF"

        // "not an int" causes the exception thrown.
    }
//]
}

static
void
example4()
{
    boost::array<char const*, 3> strs = {{ " 5", "0XF", "not an int" }};
    std::vector<int>             ints;
    boost::cnv::cstream           cnv;

//[algorithm_example4

    std::transform(strs.begin(), strs.end(), std::back_inserter(ints),
        boost::cnv::apply<int>(boost::cref(cnv(std::hex)(std::skipws))).value_or(-1));

    BOOST_TEST(ints.size() == 3);
    BOOST_TEST(ints[0] ==  5);
    BOOST_TEST(ints[1] == 15);
    BOOST_TEST(ints[2] == -1); // Failed conversion

    /*`[important One notable difference in the deployment of `boost::cnv::cstream` with algorithms is
       the use of `boost::cref` (or `std::cref` in C++11).

       It needs to be remembered that with standard algorithms the deployed converter needs to be
       [@http://en.cppreference.com/w/cpp/named_req/TriviallyCopyable copyable] or
       [@http://en.cppreference.com/w/cpp/named_req/MoveAssignable movable (C++11)]
       and is, in fact, copied or moved by the respective algorithm before being used.
       Given that `std::cstringstream` is not copyable, `boost::cnv::cstream` is not copyable either.
       That limitation is routinely worked-around using `boost::ref` or `boost::cref`.]
    */
//]
}

static
void
example5()
{
//[algorithm_example5
    /*`And now an example of algorithm-based integer-to-string formatted conversion with
       `std::hex`, `std::uppercase` and `std::showbase` formatting applied:
    */
    boost::array<int, 3>     ints = {{ 15, 16, 17 }};
    std::vector<std::string> strs;
    boost::cnv::cstream       cnv;

    cnv(std::hex)(std::uppercase)(std::showbase);

    std::transform(ints.begin(), ints.end(), std::back_inserter(strs),
        boost::cnv::apply<string>(boost::cref(cnv)));

    BOOST_TEST(strs.size() == 3);
    BOOST_TEST(strs[0] ==  "0XF"); // 15
    BOOST_TEST(strs[1] == "0X10"); // 16
    BOOST_TEST(strs[2] == "0X11"); // 17
//]
}

int
main(int, char const* [])
{
    introduction();
    example1();
    example2();
    example3();
    example4();
    example5();

    return boost::report_errors();
}