Boost
C++ Libraries
...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
This version of Boost is under active development. You are currently in the master branch. The current version is 1.91.0.
The purpose of the converter is to provide conversion-related formatting
and locale support not available with boost::lexical_cast.
Advantages of deploying a std::stream-based
conversion engine are:
std::hex,
std::setprecision, std::skipws,
etc.);
The converter might be deployed as follows:
#include <boost/convert.hpp> #include <boost/convert/stream.hpp> #include <boost/detail/lightweight_test.hpp> using std::string; using boost::convert; struct boost::cnv::by_default : boost::cnv::cstream {};
int i2 = convert<int>("123").value(); // Throws when fails. int i3 = convert<int>("uhm").value_or(-1); // Returns -1 when fails. string s2 = convert<string>(123).value(); BOOST_TEST(i2 == 123); BOOST_TEST(i3 == -1); BOOST_TEST(s2 == "123");
Formatting support is provided by the underlying std::stringstream.
Consequently, the API heavily borrows formatting metaphors from this underlying
component. One such metaphor is the manipulator represented
by std::hex, std::dec,
std::uppercase, std::scientific,
etc.
The following code demonstrates how char
and wchar_t strings can be
read in the std::hex or std::dec
format:
boost::cnv::cstream ccnv; boost::cnv::wstream wcnv; int v01 = convert<int>(" FF", ccnv(std::hex)(std::skipws)).value_or(0); int v02 = convert<int>(L" F", wcnv(std::hex)(std::skipws)).value_or(0); int v03 = convert<int>(" FF", ccnv(std::dec)(std::skipws)).value_or(-5); int v04 = convert<int>(L" F", wcnv(std::dec)(std::skipws)).value_or(-5); BOOST_TEST(v01 == 255); // "FF" BOOST_TEST(v02 == 15); // L"F" BOOST_TEST(v03 == -5); // Failed to convert "FF" as decimal. BOOST_TEST(v04 == -5); // Failed to convert L"F" as decimal.
For batch-processing it might be more efficient to configure the converter once:
ccnv(std::showbase)(std::uppercase)(std::hex); BOOST_TEST(convert<string>(255, ccnv, "bad") == "0XFF"); BOOST_TEST(convert<string>( 15, ccnv, "bad") == "0XF");
An alternative (generic) formatting interface is currently being extended and explored:
namespace cnv = boost::cnv; namespace arg = boost::cnv::parameter;
ccnv(arg::base = cnv::base::dec) (arg::uppercase = true) (arg::notation = cnv::notation::scientific);
is equivalent to the following std::manipulator-based variant:
ccnv(std::dec)(std::uppercase)(std::scientific);
using std::string; using std::wstring; using boost::convert;
The following example demonstrates the deployment of std::dec,
std::oct std::hex
manipulators:
boost::cnv::cstream ccnv; BOOST_TEST(convert<int>( "11", ccnv(std::hex)).value_or(0) == 17); // 11(16) = 17(10) BOOST_TEST(convert<int>( "11", ccnv(std::oct)).value_or(0) == 9); // 11(8) = 9(10) BOOST_TEST(convert<int>( "11", ccnv(std::dec)).value_or(0) == 11); BOOST_TEST(convert<string>( 18, ccnv(std::hex)).value_or("bad") == "12"); // 18(10) = 12(16) BOOST_TEST(convert<string>( 10, ccnv(std::oct)).value_or("bad") == "12"); // 10(10) = 12(8) BOOST_TEST(convert<string>( 12, ccnv(std::dec)).value_or("bad") == "12"); BOOST_TEST(convert<string>(255, ccnv(arg::base = boost::cnv::base::oct)).value_or("bad") == "377"); BOOST_TEST(convert<string>(255, ccnv(arg::base = boost::cnv::base::hex)).value_or("bad") == "ff"); BOOST_TEST(convert<string>(255, ccnv(arg::base = boost::cnv::base::dec)).value_or("bad") == "255"); ccnv(std::showbase); BOOST_TEST(convert<string>(18, ccnv(std::hex)).value_or("bad") == "0x12"); BOOST_TEST(convert<string>(10, ccnv(std::oct)).value_or("bad") == "012"); ccnv(std::uppercase); BOOST_TEST(convert<string>(18, ccnv(std::hex)).value_or("bad") == "0X12");
A more generic interface is also supported:
namespace cnv = boost::cnv; namespace arg = boost::cnv::parameter;
BOOST_TEST(convert<int>("11", ccnv(arg::base = cnv::base::hex)).value_or(0) == 17); BOOST_TEST(convert<int>("11", ccnv(arg::base = cnv::base::oct)).value_or(0) == 9); BOOST_TEST(convert<int>("11", ccnv(arg::base = cnv::base::dec)).value_or(0) == 11);
boost::cnv::cstream cnv; boost::optional<string> s01 = convert<string>(12, cnv(std::setw(4))); boost::optional<string> s02 = convert<string>(12, cnv(std::setw(5))(std::setfill('*'))); boost::optional<string> s03 = convert<string>(12, cnv(std::setw(5))(std::setfill('*'))(std::left)); BOOST_TEST(s01 && s01.value() == " 12"); // Field width = 4. BOOST_TEST(s02 && s02.value() == "***12"); // Field width = 5, filler = '*'. BOOST_TEST(s03 && s03.value() == "12***"); // Field width = 5, filler = '*', left adjustment
It needs to be remembered that boost::cnv::stream
converter uses std::stream as its underlying conversion
engine. Consequently, formatting-related behavior are driven by the
std::stream. Namely, after every operation
is performed, the default field width is restored.
The values of the fill character and the adjustment remain unchanged
until they are modified explicitly.
// The fill and adjustment remain '*' and 'left'. boost::optional<string> s11 = convert<string>(12, cnv(arg::width = 4)); boost::optional<string> s12 = convert<string>(12, cnv(arg::width = 5) (arg::fill = ' ') (arg::adjust = cnv::adjust::right)); BOOST_TEST(s11 && s11.value() == "12**"); // Field width was set to 4. BOOST_TEST(s12 && s12.value() == " 12"); // Field width was set to 5 with the ' ' filler.
using std::string; using std::wstring; using boost::convert;
boost::cnv::cstream ccnv; char const* const cstr_good = " 123"; char const* const cstr_bad = " 123 "; // std::skipws only affects leading spaces. ccnv(std::skipws); // Ignore leading whitespaces // ccnv(arg::skipws = true); // Ignore leading whitespaces. Alternative interface BOOST_TEST(convert<int>(cstr_good, ccnv).value_or(0) == 123); BOOST_TEST(convert<string>(" 123", ccnv).value_or("bad") == "123"); BOOST_TEST(!convert<int>(cstr_bad, ccnv)); ccnv(std::noskipws); // Do not ignore leading whitespaces // ccnv(arg::skipws = false); // Do not ignore leading whitespaces. Alternative interface // All conversions fail. BOOST_TEST(!convert<int>(cstr_good, ccnv)); BOOST_TEST(!convert<int>( cstr_bad, ccnv));
using std::string; using std::wstring; using boost::convert;
BOOST_TEST(convert<string>( true, cnv(std::boolalpha)).value_or("bad") == "true"); BOOST_TEST(convert<string>(false, cnv(std::boolalpha)).value_or("bad") == "false"); BOOST_TEST(convert<bool>( "true", cnv(std::boolalpha)).value_or(false) == true); BOOST_TEST(convert<bool>("false", cnv(std::boolalpha)).value_or( true) == false); BOOST_TEST(convert<string>( true, cnv(std::noboolalpha)).value_or("bad") == "1"); BOOST_TEST(convert<string>(false, cnv(std::noboolalpha)).value_or("bad") == "0"); BOOST_TEST(convert<bool>("1", cnv(std::noboolalpha)).value_or(false) == true); BOOST_TEST(convert<bool>("0", cnv(std::noboolalpha)).value_or( true) == false);