Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r85901 - in branches/release/libs/conversion: . doc example test
From: antoshkka_at_[hidden]
Date: 2013-09-25 09:27:07


Author: apolukhin
Date: 2013-09-25 09:27:07 EDT (Wed, 25 Sep 2013)
New Revision: 85901
URL: http://svn.boost.org/trac/boost/changeset/85901

Log:
Merge lexical_casts documentation and tests to release branch (refs #9046)

Added:
   branches/release/libs/conversion/example/
      - copied from r85899, trunk/libs/conversion/example/
Replaced:
   branches/release/libs/conversion/example/args_to_numbers.cpp
      - copied unchanged from r85899, trunk/libs/conversion/example/args_to_numbers.cpp
   branches/release/libs/conversion/example/generic_stringize.cpp
      - copied unchanged from r85899, trunk/libs/conversion/example/generic_stringize.cpp
   branches/release/libs/conversion/example/small_examples.cpp
      - copied unchanged from r85899, trunk/libs/conversion/example/small_examples.cpp
   branches/release/libs/conversion/example/variant_to_long_double.cpp
      - copied unchanged from r85899, trunk/libs/conversion/example/variant_to_long_double.cpp
Properties modified:
   branches/release/libs/conversion/ (props changed)
Text files modified:
   branches/release/libs/conversion/doc/lexical_cast.qbk | 113 ++++++---------------------------------
   branches/release/libs/conversion/example/args_to_numbers.cpp | 35 ++++++++++++
   branches/release/libs/conversion/example/generic_stringize.cpp | 61 +++++++++++++++++++++
   branches/release/libs/conversion/example/small_examples.cpp | 52 ++++++++++++++++++
   branches/release/libs/conversion/example/variant_to_long_double.cpp | 39 +++++++++++++
   branches/release/libs/conversion/test/Jamfile.v2 | 9 ++
   branches/release/libs/conversion/test/lexical_cast_float_types_test.cpp | 6 +
   7 files changed, 218 insertions(+), 97 deletions(-)

Modified: branches/release/libs/conversion/doc/lexical_cast.qbk
==============================================================================
--- branches/release/libs/conversion/doc/lexical_cast.qbk Wed Sep 25 09:23:57 2013 (r85900)
+++ branches/release/libs/conversion/doc/lexical_cast.qbk 2013-09-25 09:27:07 EDT (Wed, 25 Sep 2013) (r85901)
@@ -38,54 +38,22 @@
 [endsect]
 
 [section Examples]
-The following example treats command line arguments as a sequence of numeric data:
-``
- int main(int argc, char * argv[])
- {
- using boost::lexical_cast;
- using boost::bad_lexical_cast;
 
- std::vector<short> args;
+[import ../example/args_to_numbers.cpp]
 
- while(*++argv)
- {
- try
- {
- args.push_back(lexical_cast<short>(*argv));
- }
- catch(bad_lexical_cast &)
- {
- args.push_back(0);
- }
- }
- ...
- }
-``
-The following example uses numeric data in a string expression:
-``
- void log_message(const std::string &);
+[section Strings to numbers conversion] [lexical_cast_args_example] [endsect]
+
+[import ../example/small_examples.cpp]
+[section Numbers to strings conversion] [lexical_cast_log_errno] [endsect]
+[section Converting to string without dynamic memory allocation] [lexical_cast_fixed_buffer] [endsect]
+[section Converting part of the string] [lexical_cast_substring_conversion] [endsect]
+
+[import ../example/generic_stringize.cpp]
+[section Generic programming (Boost.Fusion)] [lexical_cast_stringize] [endsect]
+
+[import ../example/variant_to_long_double.cpp]
+[section Generic programming (Boost.Variant)] [lexical_cast_variant_to_long_double] [endsect]
 
- void log_errno(int yoko)
- {
- log_message("Error " + boost::lexical_cast<std::string>(yoko) + ": " + strerror(yoko));
- }
-``
-Following example converts some number and puts it to file:
-``
- int i;
- FILE* file;
- ...
- typedef boost::array<char, 50> buf_t; // You can use std::array if your compiler supports it
- buf_t buffer = boost::lexical_cast<buf_t>(i); // No dynamic memory allocation
- puts(buffer.begin(), file);
-``
-Following example takes part of the string and converts it to `int`:
-``
-int convert_strings_part(const std::string& s, std::size_t pos, std::size_t n)
-{
- return boost::lexical_cast<int>(s.data() + pos, n);
-}
-``
 [endsect]
 
 [section Synopsis]
@@ -156,56 +124,6 @@
 
 [endsect]
 
-[/ Commenting out bad advise (this will break the ability to get correct function pointers via &lexical_cast<Target, Source>)
-[section Tuning classes for fast lexical conversions]
-Because of `boost::lexical_cast` optimizations for `boost::iterator_range<character_type*>`, it is possibile to make very fast lexical conversions for non zero terminated strings, substrings and user-defined classes.
-
-Consider the following example:
-``
- class example_class {
- char non_zero_terminated_data[10];
- std::size_t data_length;
-
- public:
- example_class();
- void fill_data();
-
- const char* data() const {
- return non_zero_terminated_data;
- }
-
- std::size_t size() const {
- return data_length;
- }
- };
-
- inline std::ostream& operator << (std::ostream& ostr, const example_class& rhs) {
- return ostr << boost::make_iterator_range(rhs.data(), rhs.data() + rhs.size());
- }
-``
-
-This is a good generic solution for most use cases.
-But we can make it even faster for some performance critical applications. During conversion, we loose speed at:
-
- * `std::ostream` construction (it makes some heap allocations)
- * `operator <<` (it copyies one by one all the symbols to an instance of `std::ostream`)
- * `std::ostream` destruction (it makes some heap deallocations)
-
-We can avoid all of this, by specifieng an overload for `boost::lexical_cast`:
-``
-namespace boost {
- template <class OutT>
- OutT lexical_cast(const example_class& rhs) {
- return boost::lexical_cast<OutT>(
- boost::make_iterator_range(rhs.data(), rhs.data() + rhs.size())
- );
- }
-}
-``
-Now `boost::lexical_cast<some_type>(example_class_instance)` conversions won't copy data and construct heavy STL stream objects. See [link boost_lexical_cast.performance Performance] section for info on `boost::iterator_range` conversion performance.
-[endsect]
-]
-
 [section Frequently Asked Questions]
 
 * [*Question:] Why does `lexical_cast<int8_t>("127")` throw `bad_lexical_cast`?
@@ -278,6 +196,11 @@
 
 * [*boost 1.54.0 :]
 
+ * Fix some issues with `boost::int128_type` and `boost::uint128_type` conversions. Notify user at compile time
+ if the `std::numeric_limits` are not specialized for 128bit types and `boost::lexical_cast` can not make conversions.
+
+* [*boost 1.54.0 :]
+
     * Added code to convert `boost::int128_type` and `boost::uint128_type` types (requires GCC 4.7 or higher).
     * Conversions to pointers will now fail to compile, instead of throwing at runtime.
     * Restored ability to get pointers to `lexical_cast` function (was broken in 1.53.0).

Copied: branches/release/libs/conversion/example/args_to_numbers.cpp (from r85899, trunk/libs/conversion/example/args_to_numbers.cpp)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/libs/conversion/example/args_to_numbers.cpp 2013-09-25 09:27:07 EDT (Wed, 25 Sep 2013) (r85901, copy of r85899, trunk/libs/conversion/example/args_to_numbers.cpp)
@@ -0,0 +1,35 @@
+// Copyright 2013 Antony Polukhin
+
+// Distributed under the Boost Software License, Version 1.0.
+// (See the accompanying file LICENSE_1_0.txt
+// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
+
+//[lexical_cast_args_example
+//`The following example treats command line arguments as a sequence of numeric data
+
+#include <boost/lexical_cast.hpp>
+#include <vector>
+
+int main(int /*argc*/, char * argv[])
+{
+ using boost::lexical_cast;
+ using boost::bad_lexical_cast;
+
+ std::vector<short> args;
+
+ while (*++argv)
+ {
+ try
+ {
+ args.push_back(lexical_cast<short>(*argv));
+ }
+ catch(const bad_lexical_cast &)
+ {
+ args.push_back(0);
+ }
+ }
+
+ // ...
+}
+
+//] [/lexical_cast_args_example]

Copied: branches/release/libs/conversion/example/generic_stringize.cpp (from r85899, trunk/libs/conversion/example/generic_stringize.cpp)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/libs/conversion/example/generic_stringize.cpp 2013-09-25 09:27:07 EDT (Wed, 25 Sep 2013) (r85901, copy of r85899, trunk/libs/conversion/example/generic_stringize.cpp)
@@ -0,0 +1,61 @@
+// Copyright 2013 Antony Polukhin
+
+// Distributed under the Boost Software License, Version 1.0.
+// (See the accompanying file LICENSE_1_0.txt
+// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
+
+
+//[lexical_cast_stringize
+/*`
+ In this example we'll make a `stringize` method that accepts a sequence, converts
+ each element of the sequence into string and appends that string to the result.
+
+ Example is based on the example from the [@http://www.packtpub.com/boost-cplusplus-application-development-cookbook/book Boost C++ Application Development Cookbook]
+ by Antony Polukhin, ISBN 9781849514880.
+
+ Step 1: Making a functor that converts any type to a string and remembers result:
+*/
+
+#include <boost/lexical_cast.hpp>
+
+struct stringize_functor {
+private:
+ std::string& result;
+
+public:
+ explicit stringize_functor(std::string& res)
+ : result(res)
+ {}
+
+ template <class T>
+ void operator()(const T& v) const {
+ result += boost::lexical_cast<std::string>(v);
+ }
+};
+
+//` Step 2: Applying `stringize_functor` to each element in sequence:
+#include <boost/fusion/include/for_each.hpp>
+template <class Sequence>
+std::string stringize(const Sequence& seq) {
+ std::string result;
+ boost::fusion::for_each(seq, stringize_functor(result));
+ return result;
+}
+
+//` Step 3: Using the `stringize` with different types:
+#include <cassert>
+#include <boost/fusion/adapted/boost_tuple.hpp>
+#include <boost/fusion/adapted/std_pair.hpp>
+
+int main() {
+ boost::tuple<char, int, char, int> decim('-', 10, 'e', 5);
+ assert(stringize(decim) == "-10e5");
+
+ std::pair<short, std::string> value_and_type(270, "Kelvin");
+ assert(stringize(value_and_type) == "270Kelvin");
+}
+
+//] [/lexical_cast_stringize]
+
+
+

Copied: branches/release/libs/conversion/example/small_examples.cpp (from r85899, trunk/libs/conversion/example/small_examples.cpp)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/libs/conversion/example/small_examples.cpp 2013-09-25 09:27:07 EDT (Wed, 25 Sep 2013) (r85901, copy of r85899, trunk/libs/conversion/example/small_examples.cpp)
@@ -0,0 +1,52 @@
+// Copyright 2013 Antony Polukhin
+
+// Distributed under the Boost Software License, Version 1.0.
+// (See the accompanying file LICENSE_1_0.txt
+// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
+
+#include <boost/lexical_cast.hpp>
+#include <string>
+#include <cstdio>
+
+//[lexical_cast_log_errno
+//`The following example uses numeric data in a string expression:
+
+void log_message(const std::string &);
+
+void log_errno(int yoko)
+{
+ log_message("Error " + boost::lexical_cast<std::string>(yoko) + ": " + strerror(yoko));
+}
+
+//] [/lexical_cast_log_errno]
+
+
+//[lexical_cast_fixed_buffer
+//`The following example converts some number and puts it to file:
+
+void number_to_file(int number, FILE* file)
+{
+ typedef boost::array<char, 50> buf_t; // You can use std::array if your compiler supports it
+ buf_t buffer = boost::lexical_cast<buf_t>(number); // No dynamic memory allocation
+ fputs(buffer.begin(), file);
+}
+
+//] [/lexical_cast_fixed_buffer]
+
+//[lexical_cast_substring_conversion
+//`The following example takes part of the string and converts it to `int`:
+
+int convert_strings_part(const std::string& s, std::size_t pos, std::size_t n)
+{
+ return boost::lexical_cast<int>(s.data() + pos, n);
+}
+
+//] [/lexical_cast_substring_conversion]
+
+void log_message(const std::string &) {}
+
+int main()
+{
+ return 0;
+}
+

Copied: branches/release/libs/conversion/example/variant_to_long_double.cpp (from r85899, trunk/libs/conversion/example/variant_to_long_double.cpp)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/libs/conversion/example/variant_to_long_double.cpp 2013-09-25 09:27:07 EDT (Wed, 25 Sep 2013) (r85901, copy of r85899, trunk/libs/conversion/example/variant_to_long_double.cpp)
@@ -0,0 +1,39 @@
+// Copyright 2013 Antony Polukhin
+
+// Distributed under the Boost Software License, Version 1.0.
+// (See the accompanying file LICENSE_1_0.txt
+// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
+
+
+//[lexical_cast_variant_to_long_double
+/*`
+ In this example we'll make a `to_long_double` method that converts value of the Boost.Variant to `long double`.
+*/
+
+#include <boost/lexical_cast.hpp>
+#include <boost/variant.hpp>
+#include <cassert>
+
+struct to_long_double_functor: boost::static_visitor<long double> {
+ template <class T>
+ long double operator()(const T& v) const {
+ // Lexical cast has many optimizations including optimizations for situations that usually
+ // occur in generic programming, like std::string to std::string or arithmetic type to arithmetic type conversion.
+ return boost::lexical_cast<long double>(v);
+ }
+};
+
+// Throws `boost::bad_lexical_cast` if value of the variant is not convertible to `long double`
+template <class Variant>
+long double to_long_double(const Variant& v) {
+ return boost::apply_visitor(to_long_double_functor(), v);
+}
+
+int main() {
+ boost::variant<char, int, std::string> v1('0'), v2("10.0001"), v3(1);
+
+ long double sum = to_long_double(v1) + to_long_double(v2) + to_long_double(v3);
+ assert(sum > 11 && sum < 11.1);
+}
+
+//] [/lexical_cast_variant_to_long_double]

Modified: branches/release/libs/conversion/test/Jamfile.v2
==============================================================================
--- branches/release/libs/conversion/test/Jamfile.v2 Wed Sep 25 09:23:57 2013 (r85900)
+++ branches/release/libs/conversion/test/Jamfile.v2 2013-09-25 09:27:07 EDT (Wed, 25 Sep 2013) (r85901)
@@ -40,7 +40,7 @@
     [ run lexical_cast_wchars_test.cpp ]
     [ run lexical_cast_float_types_test.cpp ]
     [ run lexical_cast_inf_nan_test.cpp ]
- [ run lexical_cast_containers_test.cpp ]
+ [ run lexical_cast_containers_test.cpp : : : <toolset>gcc:<cxxflags>-Wno-long-long <toolset>clang:<cxxflags>-Wno-long-long ]
     [ run lexical_cast_empty_input_test.cpp ]
     [ run lexical_cast_pointers_test.cpp ]
     [ compile lexical_cast_typedefed_wchar_test.cpp : <toolset>msvc:<nowchar>on ]
@@ -64,3 +64,10 @@
     [ run lexical_cast_filesystem_test.cpp ../../filesystem/build//boost_filesystem/<link>static ]
   ;
 
+# Assuring that examples compile and run. Adding sources from `example` directory to the `conversion` test suite.
+for local p in [ glob ../example/*.cpp ]
+{
+ conversion += [ run $(p) ] ;
+}
+
+

Modified: branches/release/libs/conversion/test/lexical_cast_float_types_test.cpp
==============================================================================
--- branches/release/libs/conversion/test/lexical_cast_float_types_test.cpp Wed Sep 25 09:23:57 2013 (r85900)
+++ branches/release/libs/conversion/test/lexical_cast_float_types_test.cpp 2013-09-25 09:27:07 EDT (Wed, 25 Sep 2013) (r85901)
@@ -297,12 +297,16 @@
     BOOST_CHECK_CLOSE_FRACTION(maxvalue, lexical_cast<test_t>(maxvalue), (std::numeric_limits<test_t>::epsilon()));
     BOOST_CHECK_CLOSE_FRACTION(maxvalue, lexical_cast<test_t>(s_max_value), (std::numeric_limits<test_t>::epsilon()));
 
+#ifndef _LIBCPP_VERSION
+ // libc++ had a bug in implementation of stream conversions for values that must be represented as infinity.
+ // http://llvm.org/bugs/show_bug.cgi?id=15723#c4
     BOOST_CHECK_THROW(lexical_cast<test_t>(s_max_value+"1"), bad_lexical_cast);
     BOOST_CHECK_THROW(lexical_cast<test_t>(s_max_value+"9"), bad_lexical_cast);
 
- // VC9 can fail the fllowing tests on floats and doubles when using stingstream...
+ // VC9 can fail the following tests on floats and doubles when using stingstream...
     BOOST_CHECK_THROW(lexical_cast<test_t>("1"+s_max_value), bad_lexical_cast);
     BOOST_CHECK_THROW(lexical_cast<test_t>("9"+s_max_value), bad_lexical_cast);
+#endif
 
     if ( is_same<test_t,float>::value )
     {


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk