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();
}
|