mirror of
https://github.com/boostorg/lexical_cast.git
synced 2025-05-09 23:03:55 +00:00
Make a separate folder for lexical_casts examples, use those examples in documenation and assure that they successfully build and run (refs #9046)
[SVN r85828]
This commit is contained in:
parent
6f656adea3
commit
c2c4b884fe
@ -38,54 +38,22 @@ For a good discussion of the options and issues involved in string-based formatt
|
||||
[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 @@ Exception used to indicate runtime lexical_cast failure.
|
||||
|
||||
[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`?
|
||||
@ -276,6 +194,11 @@ limitation of compiler options that you use.
|
||||
|
||||
[section Changes]
|
||||
|
||||
* [*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).
|
||||
|
35
example/args_to_numbers.cpp
Normal file
35
example/args_to_numbers.cpp
Normal file
@ -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]
|
59
example/generic_stringize.cpp
Normal file
59
example/generic_stringize.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
// 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>
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
struct stringize_functor: boost::noncopyable {
|
||||
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 <iostream>
|
||||
#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);
|
||||
std::pair<short, std::string> value_and_type(270, "Kelvin");
|
||||
|
||||
std::cout << stringize(decim) << '\n' // outputs '-10e5'
|
||||
<< stringize(value_and_type); // outputs '270Kelvin'
|
||||
}
|
||||
|
||||
//] [/lexical_cast_stringize]
|
52
example/small_examples.cpp
Normal file
52
example/small_examples.cpp
Normal file
@ -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;
|
||||
}
|
||||
|
39
example/variant_to_long_double.cpp
Normal file
39
example/variant_to_long_double.cpp
Normal file
@ -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]
|
@ -64,3 +64,10 @@ test-suite conversion
|
||||
[ 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) ] ;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user