Целью конвертера является обеспечение форматирования, связанного с конверсией, и поддержки локализации, недоступной с<boost::lexical_cast
>. Преимущества развертывания конверсионного двигателя на основе<std::stream
>:
Оказание поддержки осуществляется с помощью основного<std::stringstream
>. Следовательно, API в значительной степени заимствует метафоры форматирования из этого базового компонента. Одной из таких метафор является манипулятор, представленный<std::hex
>,<std::dec
>,<std::uppercase
>,<std::scientific
>и т. д.
Следующий код показывает, как<char
>и<wchar_t
>строки могут быть прочитаны в<std::hex
>или<std::dec
>формате:
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);
BOOST_TEST(v02 == 15);
BOOST_TEST(v03 == -5);
BOOST_TEST(v04 == -5);
Для пакетной обработки может быть более эффективным настроить преобразователь один раз:
ccnv(std::showbase)(std::uppercase)(std::hex);
BOOST_TEST(convert<string>(255, ccnv, "bad") == "0XFF");
BOOST_TEST(convert<string>( 15, ccnv, "bad") == "0XF");
В настоящее время расширяется и изучается альтернативный (общий) интерфейс форматирования:
namespace cnv = boost::cnv;
namespace arg = boost::cnv::parameter;
ccnv(arg::base = cnv::base::dec)
(arg::uppercase = true)
(arg::notation = cnv::notation::scientific);
является эквивалентным следующемуstd::manipulator-based варианту:
ccnv(std::dec)(std::uppercase)(std::scientific);
using std::string;
using std::wstring;
using boost::convert;
Следующий пример демонстрирует развертывание<std::dec
>,<std::oct
><std::hex
>манипуляторов:
boost::cnv::cstream ccnv;
BOOST_TEST(convert<int>( "11", ccnv(std::hex)).value_or(0) == 17);
BOOST_TEST(convert<int>( "11", ccnv(std::oct)).value_or(0) == 9);
BOOST_TEST(convert<int>( "11", ccnv(std::dec)).value_or(0) == 11);
BOOST_TEST(convert<string>( 18, ccnv(std::hex)).value_or("bad") == "12");
BOOST_TEST(convert<string>( 10, ccnv(std::oct)).value_or("bad") == "12");
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");
Более общий интерфейс также поддерживается:
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");
BOOST_TEST(s02 && s02.value() == "***12");
BOOST_TEST(s03 && s03.value() == "12***");
Следует помнить, что<boost::cnv::stream
>преобразователь использует<std::stream
>в качестве основного двигателя преобразования. Следовательно, поведение, связанное с форматированием, обусловлено<std::stream
>. А именно, после каждой операции восстанавливается ширина поля по умолчанию. Значения заполнения и корректировки остаются неизменными до тех пор, пока они не будут явно изменены.
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**");
BOOST_TEST(s12 && s12.value() == " 12");
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 ";
ccnv(std::skipws);
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);
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);