|  | Home | Libraries | People | FAQ | More | 
      The following code demonstrates a failed attempt (and one of the reasons Boost.Convert
      has been developed) to convert a few strings
      to ints 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. }
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.
      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. }
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]](../../../../../doc/src/images/important.png) | Important | 
|---|---|
| 
        One notable difference in the deployment of  
        It needs to be remembered that with standard algorithms the deployed converter
        needs to be copyable
        or movable
        (C++11) and is, in fact, copied or moved by the respective algorithm
        before being used. Given that  | 
      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
      So far it was sufficient to explicitly specify only one type to boost::cnv::apply<TypeOut>
      -- the target TypeOut type. The source TypeIn
      type has been provided implicitly through the algorithm and often it all just
      works (as the examples above demonstrate). However, at times more control is
      needed regarding the TypeIn type and boost::cnv::apply() provides
      such control via explicit specification of TypeIn --
      boost::cnv::apply<TypeOut, TypeIn>.
    
      The following example demonstrates an interesting issue related to the change class introduced in Integration of User-Defined
      Types. The class is essentially a glorified enum, a user-friendly convenience
      wrapper around the actual enum
      value_type {
      no, up, dn
      }. In the example an array
      of change
      values (chgs1) is sensibly
      converted to readable "no", "up" and "dn" strings
      (strs1) when an array of change::value_type values (chgs2) converts to obscure "0",
      "1" and "2" (strs2).
    
boost::array<change, 3> chgs1 = {{ change::no, change::up, change::dn }}; boost::array<change::value_type, 3> chgs2 = {{ change::no, change::up, change::dn }}; std::vector<std::string> strs1; std::vector<std::string> strs2; std::vector<std::string> strs3; boost::cnv::cstream cnv; std::transform(chgs1.begin(), chgs1.end(), std::back_inserter(strs1), boost::cnv::apply<string>(boost::cref(cnv))); // Deduced TypeIn is 'change' std::transform(chgs2.begin(), chgs2.end(), std::back_inserter(strs2), boost::cnv::apply<string>(boost::cref(cnv))); // Deduced TypeIn is 'change::value_type' BOOST_TEST(strs1.size() == 3); BOOST_TEST(strs1[0] == "no"); BOOST_TEST(strs1[1] == "up"); BOOST_TEST(strs1[2] == "dn"); BOOST_TEST(strs2.size() == 3); BOOST_TEST(strs2[0] == "0"); BOOST_TEST(strs2[1] == "1"); BOOST_TEST(strs2[2] == "2");
      The boost::cnv::apply<TypeOut, TypeIn> with forced (rather than deduced) TypeIn
      comes to the rescue and converts the array of change::value_type
      values (chgs2) to sensible
      "no", "up" and "dn" (strs3):
    
std::transform(chgs2.begin(), chgs2.end(), std::back_inserter(strs3), boost::cnv::apply<string, change>(boost::cref(cnv))); BOOST_TEST(strs3.size() == 3); BOOST_TEST(strs3[0] == "no"); BOOST_TEST(strs3[1] == "up"); BOOST_TEST(strs3[2] == "dn");
| ![[Note]](../../../../../doc/src/images/note.png) | Note | 
|---|---|
| For demonstration purposes the example above is made as simple as possible and, consequently, the described "issue" could probably be addressed by other means. Still, do not let my inability to come up with a better (complex but short and succulent) example get in the way of appreciating the described functionality. I do not expect it to be used often but it is here when you need it. |