| 1 | // Boost.Convert test and usage example |
| 2 | // Copyright (c) 2009-2020 Vladimir Batov. |
| 3 | // Use, modification and distribution are subject to the Boost Software License, |
| 4 | // Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. |
| 5 | |
| 6 | #include "./test.hpp" |
| 7 | |
| 8 | #if !defined(BOOST_CONVERT_CXX14) |
| 9 | int main(int, char const* []) { return 0; } |
| 10 | #else |
| 11 | |
| 12 | #include <boost/convert.hpp> |
| 13 | #include <boost/convert/lexical_cast.hpp> |
| 14 | #include <functional> |
| 15 | |
| 16 | using std::string; |
| 17 | using boost::convert; |
| 18 | using boost::lexical_cast; |
| 19 | |
| 20 | //[callable_example1 |
| 21 | void plain_old_func(string const& value_in, boost::optional<int>& value_out) |
| 22 | //] |
| 23 | { |
| 24 | try |
| 25 | { |
| 26 | value_out = lexical_cast<int>(value_in); |
| 27 | } |
| 28 | catch (...) |
| 29 | { |
| 30 | } |
| 31 | } |
| 32 | |
| 33 | template<typename TypeIn, typename TypeOut> |
| 34 | void |
| 35 | convert_all(TypeIn const&, boost::optional<TypeOut>&) |
| 36 | { |
| 37 | } |
| 38 | |
| 39 | template<typename Type> |
| 40 | void |
| 41 | assign(boost::optional<Type>& value_out, Type const& value_in) |
| 42 | { |
| 43 | value_out = value_in; |
| 44 | } |
| 45 | |
| 46 | struct converter1 |
| 47 | { |
| 48 | template<typename TypeIn, typename TypeOut> |
| 49 | void |
| 50 | operator()(TypeIn const&, boost::optional<TypeOut>&) const |
| 51 | { |
| 52 | } |
| 53 | }; |
| 54 | |
| 55 | //[callable_example4 |
| 56 | struct take_double { void operator()(double, boost::optional<string>&) const {}}; |
| 57 | struct take_int { void operator()(int, boost::optional<string>&) const {}}; |
| 58 | //] |
| 59 | |
| 60 | //[callable_example6 |
| 61 | struct double_only |
| 62 | { |
| 63 | // Declared for all types. |
| 64 | template<typename TypeIn> void operator()(TypeIn, boost::optional<string>&) const; |
| 65 | }; |
| 66 | |
| 67 | // Defined only for certain types. |
| 68 | template<> void double_only::operator()<double>(double, boost::optional<string>&) const {} |
| 69 | //] |
| 70 | |
| 71 | int |
| 72 | main(int, char const* []) |
| 73 | { |
| 74 | using func_type = std::function<void (string const& value_in, boost::optional<int>&)>; |
| 75 | |
| 76 | char const* const str = "-12" ; |
| 77 | |
| 78 | // Testing old-function-based converter. |
| 79 | //[callable_example2 |
| 80 | int v01 = convert<int>(str, plain_old_func).value_or(-1); |
| 81 | //] |
| 82 | // Testing std::function-based converter. |
| 83 | int v02 = convert<int>(str, func_type(plain_old_func)).value_or(-1); |
| 84 | // Testing crazy std::bind-based converter. |
| 85 | //[callable_example3 |
| 86 | int v03 = convert<int>(str, |
| 87 | std::bind(assign<int>, std::placeholders::_2, |
| 88 | std::bind(boost::lexical_cast<int, string>, std::placeholders::_1))).value_or(-1); |
| 89 | //] |
| 90 | BOOST_TEST(v01 == -12); |
| 91 | BOOST_TEST(v02 == -12); |
| 92 | BOOST_TEST(v03 == -12); |
| 93 | |
| 94 | convert<int>(str, convert_all<string, int>); |
| 95 | convert<string>(11, convert_all<int, string>); |
| 96 | convert< int>(str, converter1()); |
| 97 | convert<string>(11, converter1()); |
| 98 | convert<string>(11.23, take_double()); |
| 99 | convert<string>(11, take_int()); |
| 100 | //[callable_example5 |
| 101 | convert<string>(11, take_double()); // Compiler applies int-to-double promotion to call the converter. |
| 102 | convert<string>(11.23, take_int()); // Compiler applies double-to-int implicit truncation. |
| 103 | //] |
| 104 | //[callable_example7 |
| 105 | convert<string>(11.23, double_only()); // Fine. |
| 106 | // convert<string>(11, double_only()); // Fails: undefined reference to double_only::operator()<int> |
| 107 | //] |
| 108 | |
| 109 | return boost::report_errors(); |
| 110 | } |
| 111 | |
| 112 | #endif |
| 113 | |