├── .drone.star ├── .drone └── drone.sh ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── README.md ├── build.jam ├── doc ├── 00_main.qbk ├── acknowledgments.qbk ├── algorithms.qbk ├── charconv_converter.qbk ├── converters.qbk ├── converters_detail.qbk ├── default_converter.qbk ├── design_notes.qbk ├── generate-html.sh ├── getting_serious.qbk ├── getting_started.qbk ├── html │ ├── BOOST_CNV_PARAM_S_idm12086.html │ ├── BOOST_CNV_PARAM_S_idm12432.html │ ├── BOOST_CNV_PARAM_T_idm12088.html │ ├── BOOST_CNV_PARAM_T_idm12434.html │ ├── BOOST_CNV_STRING_ENABLE.html │ ├── BOOST_CNV_STRING_TO.html │ ├── BOOST_CNV_TO_STRING.html │ ├── boost │ │ ├── cnv │ │ │ ├── apply_idm11741.html │ │ │ ├── basic_stream.html │ │ │ ├── basic_stream │ │ │ │ ├── ibuffer_type.html │ │ │ │ └── obuffer_type.html │ │ │ ├── charconv.html │ │ │ ├── cnvbase.html │ │ │ ├── lexical_cast.html │ │ │ ├── printf.html │ │ │ ├── reference.html │ │ │ ├── reference_Convert_idm11712.html │ │ │ ├── spirit.html │ │ │ └── strtol.html │ │ ├── convert_idm11767.html │ │ ├── convert_idm11787.html │ │ ├── make_default.html │ │ └── throw_on_failure.html │ ├── boost_convert │ │ ├── acknowledgements.html │ │ ├── algorithms.html │ │ ├── alternative_interface.html │ │ ├── converters.html │ │ ├── converters_detail.html │ │ ├── converters_detail │ │ │ ├── charconv_converter.html │ │ │ ├── charconv_converter │ │ │ │ ├── formatting_support.html │ │ │ │ ├── formatting_support │ │ │ │ │ ├── field_width__fill_character_and_adjustment.html │ │ │ │ │ ├── floating_point_notation.html │ │ │ │ │ ├── floating_point_precision.html │ │ │ │ │ └── leading_whitespace_characters.html │ │ │ │ └── supported_string_types.html │ │ │ ├── stream_converter.html │ │ │ ├── stream_converter │ │ │ │ ├── locale_support.html │ │ │ │ ├── supported_string_types.html │ │ │ │ ├── supported_string_types │ │ │ │ │ └── custom_string_types.html │ │ │ │ └── the___default_constructible__type_requirement.html │ │ │ ├── strtol_converter.html │ │ │ └── strtol_converter │ │ │ │ ├── formatting_support.html │ │ │ │ ├── formatting_support │ │ │ │ ├── field_width__fill_character_and_adjustment.html │ │ │ │ ├── floating_point_precision.html │ │ │ │ └── leading_whitespace_characters.html │ │ │ │ ├── supported_string_types.html │ │ │ │ └── supported_string_types │ │ │ │ └── custom_string_types.html │ │ ├── default_converter.html │ │ ├── design_notes.html │ │ ├── design_notes │ │ │ ├── converter_signature.html │ │ │ └── user_interface_signature.html │ │ ├── error_detection.html │ │ ├── getting_started.html │ │ ├── getting_started │ │ │ ├── basic_conversion_failure_detection.html │ │ │ └── flexibility_and_adaptability_to_change.html │ │ ├── integration_of_user_types.html │ │ ├── introduction.html │ │ ├── other_conversions.html │ │ ├── performance.html │ │ ├── performance │ │ │ ├── boost_convert_overhead.html │ │ │ └── the_bigger_picture.html │ │ ├── supported_compilers.html │ │ ├── supporting_tools.html │ │ └── supporting_tools │ │ │ ├── boost__cnv__is_range.html │ │ │ ├── boost_declare_has_member.html │ │ │ └── boost_declare_is_callable.html │ ├── boost_convert_c___reference.html │ ├── header │ │ └── boost │ │ │ ├── convert │ │ │ ├── base_hpp.html │ │ │ ├── charconv_hpp.html │ │ │ ├── lexical_cast_hpp.html │ │ │ ├── parameters_hpp.html │ │ │ ├── printf_hpp.html │ │ │ ├── spirit_hpp.html │ │ │ ├── stream_hpp.html │ │ │ └── strtol_hpp.html │ │ │ └── make_default_hpp.html │ ├── images │ │ ├── home.png │ │ ├── important.png │ │ ├── next.png │ │ ├── note.png │ │ ├── prev.png │ │ ├── up.png │ │ └── warning.png │ ├── index.html │ ├── index │ │ └── s18.html │ └── standalone_HTML.manifest ├── index.idx ├── introduction.qbk ├── jamfile.v2 ├── lexcast_converter.qbk ├── limitations.qbk ├── no_optional_interface.qbk ├── other.qbk ├── performance.qbk ├── rationale.qbk ├── section-end.qbk ├── stream_converter.qbk ├── strtol_converter.qbk ├── tools.qbk └── user_types.qbk ├── example ├── algorithms.cpp ├── default_converter.cpp ├── default_converter_fail.cpp ├── getting_serious.cpp ├── getting_started.cpp ├── jamfile.v2 ├── lexical_cast.cpp └── stream.cpp ├── include └── boost │ ├── convert.hpp │ ├── convert │ ├── base.hpp │ ├── charconv.hpp │ ├── detail │ │ ├── char.hpp │ │ ├── config.hpp │ │ ├── has_member.hpp │ │ ├── is_callable.hpp │ │ ├── is_fun.hpp │ │ ├── is_string.hpp │ │ └── range.hpp │ ├── lexical_cast.hpp │ ├── parameters.hpp │ ├── printf.hpp │ ├── spirit.hpp │ ├── stream.hpp │ └── strtol.hpp │ └── make_default.hpp ├── index.html ├── makefile ├── meta └── libraries.json ├── test ├── CMakeLists.txt ├── callable.cpp ├── charconv_converter.cpp ├── encryption.cpp ├── fallbacks.cpp ├── has_member.cpp ├── issue-63.cpp ├── jamfile.v2 ├── lcast_converter.cpp ├── performance.cpp ├── performance_spirit.cpp ├── prepare.hpp ├── printf_converter.cpp ├── sfinae.cpp ├── spirit_converter.cpp ├── str_to_int.cpp ├── stream_converter.cpp ├── strtol_converter.cpp ├── test.hpp └── user_type.cpp └── todo.txt /.drone/drone.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2020 Rene Rivera, Sam Darwin 4 | # Distributed under the Boost Software License, Version 1.0. 5 | # (See accompanying file LICENSE.txt or copy at http://boost.org/LICENSE_1_0.txt) 6 | 7 | set -e 8 | export TRAVIS_BUILD_DIR=$(pwd) 9 | export DRONE_BUILD_DIR=$(pwd) 10 | export TRAVIS_BRANCH=$DRONE_BRANCH 11 | export VCS_COMMIT_ID=$DRONE_COMMIT 12 | export GIT_COMMIT=$DRONE_COMMIT 13 | export REPO_NAME=$DRONE_REPO 14 | export PATH=~/.local/bin:/usr/local/bin:$PATH 15 | 16 | if [ "$DRONE_JOB_BUILDTYPE" == "boost" ]; then 17 | 18 | echo '==================================> INSTALL' 19 | 20 | BOOST_BRANCH=develop && [ "$TRAVIS_BRANCH" == "master" ] && BOOST_BRANCH=master || true 21 | cd .. 22 | git clone -b $TRAVIS_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root 23 | cd boost-root 24 | git submodule update --init tools/boost_install 25 | git submodule update --init libs/headers 26 | git submodule update --init tools/build 27 | git submodule update --init libs/config 28 | git submodule update --init tools/boostdep 29 | cp -r $TRAVIS_BUILD_DIR/* libs/convert 30 | python tools/boostdep/depinst/depinst.py convert 31 | ./bootstrap.sh 32 | ./b2 headers 33 | 34 | echo '==================================> SCRIPT' 35 | 36 | echo "using $TOOLSET : : $COMPILER ;" > ~/user-config.jam 37 | ./b2 --verbose-test libs/config/test//config_info toolset=$TOOLSET cxxstd=$CXXSTD || true 38 | cd libs/convert/test 39 | ../../../b2 -j`(nproc || sysctl -n hw.ncpu) 2> /dev/null` toolset=$TOOLSET cxxstd=$CXXSTD $CXXSTD_DIALECT 40 | cd ../../.. 41 | 42 | fi 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *~ 3 | bin.v2/ 4 | bin/ 5 | doc/bin/ 6 | doc/doxygen/ 7 | doc/inspect.txt 8 | convert.pdf 9 | *.log 10 | *.bat 11 | 12 | ################# 13 | ## Eclipse 14 | ################# 15 | 16 | .project 17 | .settings/ 18 | .cproject 19 | 20 | Debug/ 21 | Release/ 22 | *.vcxproj* 23 | *.sln 24 | *.suo 25 | *.sdf 26 | *.opensdf 27 | a.out 28 | Jamroot.jam 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Generated by `boostdep --cmake convert` 2 | # Copyright 2020 Peter Dimov 3 | # Distributed under the Boost Software License, Version 1.0. 4 | # https://www.boost.org/LICENSE_1_0.txt 5 | 6 | cmake_minimum_required(VERSION 3.5...3.16) 7 | 8 | project(boost_convert VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX) 9 | 10 | add_library(boost_convert INTERFACE) 11 | add_library(Boost::convert ALIAS boost_convert) 12 | 13 | target_include_directories(boost_convert INTERFACE include) 14 | 15 | target_link_libraries(boost_convert 16 | INTERFACE 17 | Boost::config 18 | Boost::core 19 | Boost::function_types 20 | Boost::lexical_cast 21 | Boost::math 22 | Boost::mpl 23 | Boost::optional 24 | Boost::parameter 25 | Boost::range 26 | Boost::spirit 27 | Boost::type_traits 28 | ) 29 | 30 | if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt") 31 | 32 | add_subdirectory(test) 33 | 34 | endif() 35 | 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | The library builds on the `boost::lexical_cast` experience and takes those type conversion/transformation-related ideas further 2 | 3 | * to be useful and applicable in a wider range of deployment scenarios, 4 | * to provide a flexible, extendible and configurable type-conversion framework. 5 | 6 | **HTML documentation is available [here](http://yet-another-user.github.io/convert).** 7 | 8 | -------------------------------------------------------------------------------- /build.jam: -------------------------------------------------------------------------------- 1 | # Copyright René Ferdinand Rivera Morell 2024 2 | # Distributed under the Boost Software License, Version 1.0. 3 | # (See accompanying file LICENSE_1_0.txt or copy at 4 | # http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | require-b2 5.2 ; 7 | 8 | constant boost_dependencies : 9 | /boost/config//boost_config 10 | /boost/core//boost_core 11 | /boost/function_types//boost_function_types 12 | /boost/lexical_cast//boost_lexical_cast 13 | /boost/math//boost_math_tr1 14 | /boost/mpl//boost_mpl 15 | /boost/optional//boost_optional 16 | /boost/parameter//boost_parameter 17 | /boost/range//boost_range 18 | /boost/spirit//boost_spirit 19 | /boost/type_traits//boost_type_traits ; 20 | 21 | project /boost/convert 22 | : common-requirements 23 | include 24 | ; 25 | 26 | explicit 27 | [ alias boost_convert : : : : $(boost_dependencies) ] 28 | [ alias all : boost_convert example test ] 29 | ; 30 | 31 | call-if : boost-library convert 32 | ; 33 | 34 | -------------------------------------------------------------------------------- /doc/00_main.qbk: -------------------------------------------------------------------------------- 1 | [/============================================================================== 2 | Copyright (C) 2009-2022 Vladimir Batov 3 | 4 | Use, modification and distribution is subject to the Boost Software 5 | License, Version 1.0. (See a copy at http://www.boost.org/LICENSE_1_0.txt) 6 | ===============================================================================/] 7 | 8 | [library Boost.Convert 9 | [quickbook 1.5] 10 | [version 2.0] 11 | [id convert] 12 | [dirname convert] 13 | [copyright 2009-2022 Vladimir Batov] 14 | [purpose Conversions Beyond boost::lexical_cast] 15 | [category generic] 16 | [authors [Batov, Vladimir]] 17 | [source-mode c++] 18 | [license 19 | Distributed under the Boost Software License, Version 1.0. 20 | See copy at [@http://www.boost.org/LICENSE_1_0.txt]. 21 | ] 22 | ] 23 | 24 | [important Requires C++11 and up.] 25 | 26 | [import ../test/test.hpp] 27 | [import ../example/stream.cpp] 28 | [import ../test/stream_converter.cpp] 29 | [import ../test/performance.cpp] 30 | [import ../test/sfinae.cpp] 31 | [import ../test/user_type.cpp] 32 | [import ../test/has_member.cpp] 33 | 34 | [include rationale.qbk] 35 | [include introduction.qbk] 36 | [include getting_started.qbk] 37 | [include getting_serious.qbk] 38 | [include default_converter.qbk] 39 | [include no_optional_interface.qbk] 40 | [include converters.qbk] 41 | [include user_types.qbk] 42 | [include algorithms.qbk] 43 | [include performance.qbk] 44 | [include other.qbk] 45 | [include converters_detail.qbk] 46 | [include lexcast_converter.qbk] 47 | [include stream_converter.qbk] 48 | [include strtol_converter.qbk] 49 | [include charconv_converter.qbk] 50 | [include section-end.qbk] 51 | [include design_notes.qbk] 52 | [include tools.qbk] 53 | [include limitations.qbk] 54 | [include acknowledgments.qbk] 55 | [xinclude convert_reference.xml] 56 | '''''' 57 | 58 | 59 | -------------------------------------------------------------------------------- /doc/acknowledgments.qbk: -------------------------------------------------------------------------------- 1 | [/ 2 | Copyright (c) Vladimir Batov 2009-2022 3 | Distributed under the Boost Software License, Version 1.0. 4 | See copy at http://www.boost.org/LICENSE_1_0.txt. 5 | ] 6 | 7 | [section Acknowledgements] 8 | 9 | Many thanks to Julian Gonggrijp, Rob Stewart, Andrzej Krzemienski, Matus Chochlik, Jeroen Habraken, Hartmut Kaiser, Joel De Guzman, Thijs (M.A.) van den Berg, Roland Bock, Gavin Lambert, Paul Bristow, Alex Hagen-Zanker, Christopher Kormanyos for taking part in the ['Boost.Convert] review and their valuable input. 10 | 11 | Special thanks to: 12 | 13 | * Alex Hagen-Zanker, Roland Bock, Rob Stewart for their considerable and continuous contributions to the design and implementation of the library; 14 | * Andrzej Krzemienski for helping to partition responsibilities and to ultimately pave the way for the `boost::optional` and `std::tr2::optional` deployment; 15 | * Edward Diener the Boost Review Manager for helping with the converters' design, his continuous involvement, technical and administrative help, guidance and advice; 16 | * Joel De Guzman, Rob Stewart and Alex Hagen-Zanker for making sure the performance tests work as they should; 17 | * Paul Bristow for helping great deal with the documentation; 18 | * Kevlin Henney and Dave Abrahams for their lexical_cast-related insights and explanations. 19 | 20 | [endsect] 21 | 22 | -------------------------------------------------------------------------------- /doc/algorithms.qbk: -------------------------------------------------------------------------------- 1 | [/ 2 | Copyright (c) Vladimir Batov 2009-2022 3 | Distributed under the Boost Software License, Version 1.0. 4 | See copy at http://www.boost.org/LICENSE_1_0.txt. 5 | ] 6 | 7 | [section:algorithms Boost.Convert with Standard Algorithms] 8 | 9 | [algorithm_example1] 10 | [algorithm_example2] 11 | [algorithm_example3] 12 | [algorithm_example4] 13 | [algorithm_example5] 14 | 15 | [heading Forced ['TypeIn] vs. Deduced] 16 | 17 | So far it was sufficient to explicitly specify only one type to `boost::cnv::apply` -- the target ['TypeOut] type. The source ['TypeIn] type was 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`. 18 | 19 | The following example demonstrates an interesting issue related to the ['`change`] class introduced in [link boost_convert.integration_of_user_types 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`). 20 | 21 | [algorithm_example6] 22 | 23 | The `boost::cnv::apply` 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`): 24 | 25 | [algorithm_example7] 26 | 27 | [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 representative) 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.] 28 | 29 | [endsect] [/section:algorithms Boost.Convert with Standard Algorithms] 30 | 31 | -------------------------------------------------------------------------------- /doc/charconv_converter.qbk: -------------------------------------------------------------------------------- 1 | [/ 2 | Copyright (c) Dvir Yitzchaki 2022. 3 | Distributed under the Boost Software License, Version 1.0. 4 | See copy at http://www.boost.org/LICENSE_1_0.txt. 5 | ] 6 | 7 | [import ../test/charconv_converter.cpp] 8 | 9 | [section:charconv_converter ['boost::cnv::charconv] Converter] 10 | 11 | [important Requires C++17 and up.] 12 | 13 | The converter is a wrapper around `std::to_chars` and `std::from_chars` and offers great performance with some formatting support. The converter only supports `char`-based strings. Written by Dvir Yitzchaki. 14 | 15 | [section Basic Deployment] 16 | [charconv_basic_deployment_header] 17 | [charconv_basic_deployment] 18 | [endsect] 19 | 20 | [section Formatting Support] 21 | 22 | [section Numeric Base (bin, oct, dec, hex)] 23 | [charconv_numeric_base] 24 | [endsect] 25 | 26 | [section Field Width, Fill Character and Adjustment] 27 | [charconv_width] 28 | [endsect] 29 | 30 | [section Leading Whitespace Characters] 31 | [charconv_skipws] 32 | [endsect] 33 | 34 | [section Floating-Point Precision] 35 | [charconv_precision] 36 | [endsect] 37 | 38 | [section Floating-Point Notation] 39 | [charconv_notation] 40 | [endsect] 41 | [endsect] 42 | 43 | [section Supported String Types] 44 | 45 | [section Custom String Types] 46 | [my_string_declaration] 47 | [charconv_user_string] 48 | [endsect] 49 | 50 | [endsect] 51 | [endsect] 52 | 53 | -------------------------------------------------------------------------------- /doc/converters.qbk: -------------------------------------------------------------------------------- 1 | [/ 2 | Copyright (c) Vladimir Batov 2009-2022 3 | Distributed under the Boost Software License, Version 1.0. 4 | See copy at http://www.boost.org/LICENSE_1_0.txt. 5 | ] 6 | 7 | [section:converters Converters] 8 | 9 | [import ../test/callable.cpp] 10 | 11 | The `boost::convert()` API plays its role by providing a ['uniform interface] and ensuring ['consistent behavior]. However, it is the respective converter which does the hard work of actual type conversion\/transformation. 12 | 13 | ['Boost.Convert] design reflects the fact that no one converter is to satisfy all imaginable conversion\/transformation-related user requirements. Consequently, ['extendibility] and ['converter pluggability] are important properties of ['Boost.Convert]. The library provides several converters for common type conversions with varying degrees of formatting support and performance. However, it is an expectation that more generic-purpose and custom-specific converters are to be written and deployed with ['Boost.Convert]. 14 | 15 | For a converter to be plugged in to the ['Boost.Convert] framework it needs to be a ['callable] with one of the signatures: 16 | 17 | template 18 | void operator()(TypeIn const& value_in, boost::optional& result_out) const; 19 | 20 | template 21 | void operator()(TypeIn value_in, boost::optional& result_out) const; 22 | 23 | if that is a general-purpose converter capable of handling many types (like string-to-type and type-to-string conversions). Alternatively, a purpose-built custom converter might only care to provide 24 | 25 | void operator()(TypeIn const&, boost::optional&) const; 26 | 27 | if its sole purpose is to handle one specific conversion\/transformation of ['TypeIn] to ['TypeOut]. For example, a converter from the operating-system-specific MBCS string format to the UCS-2 or UCS-4 (depending on `wchar_t` size) might be one such example: 28 | 29 | void operator()(std::string const&, boost::optional&) const; 30 | 31 | Alternatively again, an ad-hoc in-place ['callable] might be provided as a converter. For example, 32 | 33 | [getting_started_using] 34 | [callable_example3] 35 | 36 | or an old-fashioned function: 37 | 38 | [callable_example1] 39 | [callable_example2] 40 | 41 | With regard to converters the ['Boost.Convert] framework has been designed with the following requirement in mind: 42 | 43 | [note Converters shall be independent from and must not rely on the ['Boost.Convert] infrastructure.] 44 | 45 | [heading Implicit ['TypeIn] Promotions and Conversions] 46 | 47 | It is worth remembering that ['TypeIn] in the signature should be interpreted in the context of the potential implicit type promotions and conversions allowed ['by the language]. For example, depending on the context the `take_double` and `take_int` converters below might not do what is expected of them due to implicit ['int-to-double] promotion and value-destroying ['double-to-int] conversion applied ['by the compiler]: 48 | 49 | [callable_example4] 50 | [callable_example5] 51 | 52 | `boost::convert()` API does not modify ['TypeIn] or interpret it in any way. The passed-in value and its type are delivered to the underlying converter as-is. Consequently, if potential implicit type promotions and conversions are not desirable, then it is the converter's responsibility to address that issue. For example, one way to disable implicit conversions might be: 53 | 54 | [callable_example6] 55 | [callable_example7] 56 | 57 | [endsect] 58 | 59 | -------------------------------------------------------------------------------- /doc/converters_detail.qbk: -------------------------------------------------------------------------------- 1 | [/ 2 | Copyright (c) Vladimir Batov 2009-2022 3 | Distributed under the Boost Software License, Version 1.0. 4 | See copy at http://www.boost.org/LICENSE_1_0.txt. 5 | ] 6 | 7 | [section:converters_detail Converters in Detail] 8 | 9 | 10 | -------------------------------------------------------------------------------- /doc/default_converter.qbk: -------------------------------------------------------------------------------- 1 | [/ 2 | Copyright (c) Vladimir Batov 2009-2022 3 | Distributed under the Boost Software License, Version 1.0. 4 | See copy at http://www.boost.org/LICENSE_1_0.txt. 5 | ] 6 | 7 | [section Default Converter] 8 | 9 | [import ../example/default_converter.cpp] 10 | 11 | The explicit converter as in 12 | 13 | int i = boost::convert("123", converter).value(); 14 | 15 | provides considerable flexibility, configurability and efficiency. However, in certain contexts that might be not that important or even counter-productive if, for example, an application relies on certain consistent behavior associated with one particular converter type and configuration. To accommodate such a scenario ['Boost.Convert] introduces the concept of the ['default converter] implemented as `boost::cnv::by_default`. 16 | 17 | [important There is no default converter set by default.] 18 | 19 | Consequently, without additional configuration steps the following call will fail to compile: 20 | 21 | int i = boost::convert("123").value(); // No converter provided 22 | 23 | However, after `boost::cnv::by_default` is defined simply as: 24 | 25 | [default_converter_declaration_simple] 26 | 27 | or potentially configured with additional formatting: 28 | 29 | [default_converter_declaration_formatted] 30 | 31 | the code compiles and deploys `boost::cnv::cstream` when `boost::convert()` is called without an explicitly supplied converter: 32 | 33 | [default_converter_example1] 34 | 35 | The trade-off for the convenience is the rigid converter configuration (which in certain contexts might be the desired behavior) and a potential performance impact. When a converter is not provided explicitly, the default converter is created, potentially configured, deployed and destroyed for every `boost::convert()` call. Consequently, if efficiency of this particular component is important, then the implementation of `boost::cnv::by_default` will need to take that into account and to make sure those operations are cheap. 36 | 37 | [endsect] 38 | 39 | -------------------------------------------------------------------------------- /doc/generate-html.sh: -------------------------------------------------------------------------------- 1 | # boost-no-inspect 2 | 3 | if [[ -d "$BOOST_ROOT" ]] 4 | then 5 | echo Using BOOST_ROOT=$BOOST_ROOT 6 | else 7 | export BOOST_ROOT=$HOME/dev/boost 8 | fi 9 | 10 | $BOOST_ROOT/b2 --toolset=gcc --enable-index 11 | 12 | rm -rf convert_reference.xml 13 | rm -rf bin 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /doc/getting_serious.qbk: -------------------------------------------------------------------------------- 1 | [/ 2 | Copyright (c) Vladimir Batov 2009-2022 3 | Distributed under the Boost Software License, Version 1.0. 4 | See copy at http://www.boost.org/LICENSE_1_0.txt. 5 | ] 6 | 7 | [section:error_detection Better Error Detection] 8 | 9 | [:[*['"Detection is, or ought to be, an exact science, ..." Sir Arthur Conan Doyle]]] 10 | 11 | [import ../example/getting_serious.cpp] 12 | 13 | [getting_serious_example1] 14 | 15 | The code above is straightforward and self-explanatory but, strictly speaking, is not entirely correct as -1 might be the result of a conversion failure or the successful conversion of the "-1" string. Still, in reality "spare" values (outside the valid\/sensible range) are often available to indicate conversion failures. If so, such straightorward deployment might be adequate. Alternatively, it might be not that uncommon to ignore conversion failures altogether and to simply log the event and to proceed with the supplied fallback value. 16 | 17 | Applications outside these mentioned categories still require conversion failure reliably detected and processed accordingly. The `boost::lexical_cast`'s (only) answer is to throw on failure and ['Boost.Convert] supports that behavior as well: 18 | 19 | [getting_serious_example2] 20 | 21 | However, to cater for a wider range of program-flow variations, ['Boost.Convert] adds the flexibility of 22 | 23 | * delaying the moment when the conversion-failure exception is actually thrown or 24 | * avoiding the exception altogether. 25 | 26 | [getting_serious_example3] 27 | 28 | Here [@boost:/libs/optional/index.html `boost::optional`] steps forward as the actual type returned by `boost::convert()` which until now we avoided by immediately calling its value-accessor methods: 29 | 30 | int i1 = boost::convert(str1, cnv).value(); 31 | int i2 = boost::convert(str2, cnv).value_or(fallback_value); 32 | int i3 = boost::convert(str3, cnv).value_or_eval(fallback_function); 33 | 34 | [note One notable advantage of `value_or_eval()` over `value_or()` is that the actual calculation of the `fallback_value` is potentially delayed and conditional on the success or failure of the conversion.] 35 | 36 | From the user perspective, `boost::lexical_cast` processes failure in a somewhat one-dimensional non-negotiable manner. `boost::convert` takes a more flexible approach. It provides choice and leaves the decision to the user. It is not unimaginable that, on the library level, propagating the conversion-failure exception might be the only available option. On the application level though, in my personal experience, the choice has overwhelmingly been to handle conversion failures ['locally], i.e. avoiding conversion-failure exception propagation or, better still, avoiding exceptions altogether with program flows similar to: 37 | 38 | [getting_serious_example4] 39 | 40 | and 41 | 42 | [getting_serious_example5] 43 | [getting_serious_example6] 44 | 45 | [endsect] [/section:error_detection Better Error Detection] 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /doc/getting_started.qbk: -------------------------------------------------------------------------------- 1 | [/ 2 | Copyright (c) Vladimir Batov 2009-2022 3 | Distributed under the Boost Software License, Version 1.0. 4 | See copy at http://www.boost.org/LICENSE_1_0.txt. 5 | ] 6 | 7 | [section Getting Started] 8 | 9 | [note Given the ubiquity of `boost::lexical_cast` and the familiarity of the programming community with it, here and further in the documentation `boost::lexical_cast` is often mentioned as a reference.] 10 | 11 | [import ../example/getting_started.cpp] 12 | 13 | [section Basic Deployment] 14 | 15 | For die-hard `boost::lexical_cast` users or as a transitional path to `boost::convert`, one of `boost::convert` deployments is not that different from `boost::lexical_cast`. In fact, the original `boost::lexical_cast` functionality is easily deployed through `boost::convert` interface: 16 | 17 | [getting_started_headers1] 18 | [getting_started_using] 19 | [getting_started_default_converter] 20 | [getting_started_example1] 21 | 22 | [important As we explore `boost::convert` behavior and interface further, at first they might appear unduly complex, verbose, etc... nothing like `atoi()`... so famous for all the wrong reasons. :-) It is important to remember that a conversion request is only a ['request] which may succeed but may also fail... which might not be as rare or as exceptional as one might hope. `boost::convert` (as well as `boost::lexical_cast`) behavior and interfaces reflect that reality.] 23 | 24 | [endsect] 25 | [section Flexibility and Adaptability to Change] 26 | 27 | [:[*['"There is nothing more constant than change" Heraclitus]]] 28 | 29 | Sooner or later (during initial development or in the maintenance phase) flexibility and adaptability become important. Deployment of ['Boost.Convert] helps to adjust and to change in line with the evolution of the requirements. For example, if the program flow would benefit from the non-throwing behavior, then: 30 | 31 | [getting_started_using] 32 | [getting_started_example2] 33 | 34 | Or, if the component is identified as too slow, then the performance could be improved with minimal effort by replacing the converter: 35 | 36 | [getting_started_headers3] 37 | [getting_started_example3] 38 | 39 | If, instead, the requirements change to support more input formats or to require a certain output format, then, again, that could be accommodated with: 40 | 41 | [getting_started_headers4] 42 | [getting_started_example4] 43 | 44 | [endsect] 45 | [section Basic Conversion-Failure Detection] 46 | 47 | [getting_started_using] 48 | [getting_started_example5] 49 | 50 | The above is translated to English as 51 | 52 | * "['convert a string to int]" for `i1` and `i2` and 53 | * "['convert a string to int and return -1 if the conversion fails]" for `i3`. 54 | 55 | The `i1` and `i2` deployments look sufficiently close and behave identically. Namely, with the user instructions silent about the conversion failure, those are treated as "exceptional" and throw. 56 | 57 | The `i3` specification, on the other hand, is explicit about conversion failures. The supplied fallback value is returned if the requested conversion fails. 58 | 59 | That basic error detection and processing might be sufficient for a variety of conversion deployments. For example: 60 | 61 | [getting_started_example6] 62 | 63 | Or 64 | 65 | [getting_started_example9_func] 66 | [getting_started_example9] 67 | 68 | Or, if we do not care about logging conversion failures: 69 | 70 | [getting_started_example7] 71 | 72 | So far the deployment of `boost::convert` seems more flexible, more compact and natural (your mileage may vary) and potentially more efficient compared to `boost::lexical_cast` which achieves somewhat similar results with: 73 | 74 | [getting_started_example8] 75 | 76 | By design, this is `boost::lexical_cast`'s only behavior -- straightforward and comprehensible, but limited. 77 | It makes quite a few legitimate process\/program flows difficult and awkward to implement. 78 | ['Boost.Convert] addresses that with additional functionality, flexibility and convenience. 79 | 80 | [endsect] 81 | [endsect] 82 | -------------------------------------------------------------------------------- /doc/html/BOOST_CNV_PARAM_S_idm12086.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Macro BOOST_CNV_PARAM_SET 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | PrevUpHomeNext 15 |
16 |
17 |
18 |
19 |

Macro BOOST_CNV_PARAM_SET

20 |

BOOST_CNV_PARAM_SET

21 |
22 |

Synopsis

23 |
// In header: <boost/convert/base.hpp>
24 | 
25 | BOOST_CNV_PARAM_SET(param_name)
26 |
27 | 28 | 29 | 34 |
35 |
36 |
37 | PrevUpHomeNext 38 |
39 | 40 | 41 | -------------------------------------------------------------------------------- /doc/html/BOOST_CNV_PARAM_S_idm12432.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Macro BOOST_CNV_PARAM_SET 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | PrevUpHomeNext 15 |
16 |
17 |
18 |
19 |

Macro BOOST_CNV_PARAM_SET

20 |

BOOST_CNV_PARAM_SET

21 |
22 |

Synopsis

23 |
// In header: <boost/convert/stream.hpp>
24 | 
25 | BOOST_CNV_PARAM_SET(param_name)
26 |
27 | 28 | 29 | 34 |
35 |
36 |
37 | PrevUpHomeNext 38 |
39 | 40 | 41 | -------------------------------------------------------------------------------- /doc/html/BOOST_CNV_PARAM_T_idm12088.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Macro BOOST_CNV_PARAM_TRY 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | PrevUpHomeNext 15 |
16 |
17 |
18 |
19 |

Macro BOOST_CNV_PARAM_TRY

20 |

BOOST_CNV_PARAM_TRY

21 |
22 |

Synopsis

23 |
// In header: <boost/convert/base.hpp>
24 | 
25 | BOOST_CNV_PARAM_TRY(param_name)
26 |
27 | 28 | 29 | 34 |
35 |
36 |
37 | PrevUpHomeNext 38 |
39 | 40 | 41 | -------------------------------------------------------------------------------- /doc/html/BOOST_CNV_PARAM_T_idm12434.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Macro BOOST_CNV_PARAM_TRY 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | PrevUpHomeNext 15 |
16 |
17 |
18 |
19 |

Macro BOOST_CNV_PARAM_TRY

20 |

BOOST_CNV_PARAM_TRY

21 |
22 |

Synopsis

23 |
// In header: <boost/convert/stream.hpp>
24 | 
25 | BOOST_CNV_PARAM_TRY(param_name)
26 |
27 | 28 | 29 | 34 |
35 |
36 |
37 | PrevUpHomeNext 38 |
39 | 40 | 41 | -------------------------------------------------------------------------------- /doc/html/BOOST_CNV_STRING_ENABLE.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Macro BOOST_CNV_STRING_ENABLE 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | PrevUpHomeNext 15 |
16 |
17 |
18 |
19 |

Macro BOOST_CNV_STRING_ENABLE

20 |

BOOST_CNV_STRING_ENABLE

21 |
22 |

Synopsis

23 |
// In header: <boost/convert/stream.hpp>
24 | 
25 | BOOST_CNV_STRING_ENABLE
26 |
27 | 28 | 29 | 34 |
35 |
36 |
37 | PrevUpHomeNext 38 |
39 | 40 | 41 | -------------------------------------------------------------------------------- /doc/html/BOOST_CNV_STRING_TO.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Macro BOOST_CNV_STRING_TO 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | PrevUpHomeNext 15 |
16 |
17 |
18 |
19 |

Macro BOOST_CNV_STRING_TO

20 |

BOOST_CNV_STRING_TO

21 |
22 |

Synopsis

23 |
// In header: <boost/convert/base.hpp>
24 | 
25 | BOOST_CNV_STRING_TO
26 |
27 | 28 | 29 | 34 |
35 |
36 |
37 | PrevUpHomeNext 38 |
39 | 40 | 41 | -------------------------------------------------------------------------------- /doc/html/BOOST_CNV_TO_STRING.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Macro BOOST_CNV_TO_STRING 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | PrevUpHomeNext 15 |
16 |
17 |
18 |
19 |

Macro BOOST_CNV_TO_STRING

20 |

BOOST_CNV_TO_STRING

21 |
22 |

Synopsis

23 |
// In header: <boost/convert/base.hpp>
24 | 
25 | BOOST_CNV_TO_STRING
26 |
27 | 28 | 29 | 34 |
35 |
36 |
37 | PrevUpHomeNext 38 |
39 | 40 | 41 | -------------------------------------------------------------------------------- /doc/html/boost/cnv/basic_stream/ibuffer_type.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Struct ibuffer_type 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | PrevUpHomeNext 15 |
16 |
17 |
18 |
19 |

Struct ibuffer_type

20 |

boost::cnv::basic_stream::ibuffer_type

21 |
22 |

Synopsis

23 |
// In header: <boost/convert/stream.hpp>
24 | 
25 | 
26 | 
27 | struct ibuffer_type : public buffer_type {
28 |   // construct/copy/destruct
29 |   ibuffer_type(char_type const *, std::size_t);
30 | };
31 |
32 |

Description

33 |
34 |

35 | ibuffer_type 36 | public 37 | construct/copy/destruct

38 |
  1. ibuffer_type(char_type const * beg, std::size_t sz);
39 |
40 |
41 |
42 | 43 | 44 | 49 |
50 |
51 |
52 | PrevUpHomeNext 53 |
54 | 55 | 56 | -------------------------------------------------------------------------------- /doc/html/boost/cnv/basic_stream/obuffer_type.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Struct obuffer_type 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | PrevUpHomeNext 15 |
16 |
17 |
18 |
19 |

Struct obuffer_type

20 |

boost::cnv::basic_stream::obuffer_type

21 |
22 |

Synopsis

23 |
// In header: <boost/convert/stream.hpp>
24 | 
25 | 
26 | 
27 | struct obuffer_type : public buffer_type {
28 | };
29 |
30 | 31 | 32 | 37 |
38 |
39 |
40 | PrevUpHomeNext 41 |
42 | 43 | 44 | -------------------------------------------------------------------------------- /doc/html/boost/make_default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Function template make_default 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | PrevUpHomeNext 15 |
16 |
17 |
18 |
19 |

Function template make_default

20 |

boost::make_default

21 |
22 |

Synopsis

23 |
// In header: <boost/make_default.hpp>
24 | 
25 | 
26 | template<typename T> T make_default();
27 |
28 |

Description

29 |

A considerable number of libraries require an instance of a class provided (storage created and initialized). For example,

30 |
Type result;
31 | ...
32 | istream >> result;
33 | 
34 |

In generic code that results in the Default Constructibility requirement imposed on every type 'Type' to be used with the respective code. Inevitably, that requirement a) either excludes all the classes that for various reasons do not meet that requirement or b) imposes certain (not necessarily desirable) design/implementation onto respective classes.

35 |

Deployment of boost::make_default() eliminates the Default Constructibility requirement with

36 |
Type result = boost::make_default<Type>();
37 | ...
38 | istream >> result;
39 | 
40 |

Classes with no default constructor can now be included via a boost::make_default() specialization:

41 |
namespace boost
42 | {
43 |     template<> inline Type make_default<Type>() { return Type(parameters); }
44 | }
45 | 
46 |

47 |
48 |
49 | 50 | 51 | 56 |
57 |
58 |
59 | PrevUpHomeNext 60 |
61 | 62 | 63 | -------------------------------------------------------------------------------- /doc/html/boost/throw_on_failure.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Global throw_on_failure 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | PrevUpHomeNext 15 |
16 |
17 |
18 |
19 |

Global throw_on_failure

20 |

boost::throw_on_failure

21 |
22 |

Synopsis

23 |
// In header: <boost/convert.hpp>
24 | 
25 | unspecified throw_on_failure;
26 |
27 |

Description

28 |

boost::throw_on_failure is the 'tag' object to request the exception-throwing behavior.

29 |
30 |
31 | 32 | 33 | 38 |
39 |
40 |
41 | PrevUpHomeNext 42 |
43 | 44 | 45 | -------------------------------------------------------------------------------- /doc/html/boost_convert/acknowledgements.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Acknowledgements 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | PrevUpHomeNext 15 |
16 |
17 |

18 | Acknowledgements 19 |

20 |

21 | Many thanks to Julian Gonggrijp, Rob Stewart, Andrzej Krzemienski, Matus Chochlik, 22 | Jeroen Habraken, Hartmut Kaiser, Joel De Guzman, Thijs (M.A.) van den Berg, 23 | Roland Bock, Gavin Lambert, Paul Bristow, Alex Hagen-Zanker, Christopher Kormanyos 24 | for taking part in the Boost.Convert review and their 25 | valuable input. 26 |

27 |

28 | Special thanks to: 29 |

30 |
    31 |
  • 32 | Alex Hagen-Zanker, Roland Bock, Rob Stewart for their considerable and 33 | continuous contributions to the design and implementation of the library; 34 |
  • 35 |
  • 36 | Andrzej Krzemienski for helping to partition responsibilities and to ultimately 37 | pave the way for the boost::optional 38 | and std::tr2::optional deployment; 39 |
  • 40 |
  • 41 | Edward Diener the Boost Review Manager for helping with the converters' 42 | design, his continuous involvement, technical and administrative help, 43 | guidance and advice; 44 |
  • 45 |
  • 46 | Joel De Guzman, Rob Stewart and Alex Hagen-Zanker for making sure the performance 47 | tests work as they should; 48 |
  • 49 |
  • 50 | Paul Bristow for helping great deal with the documentation; 51 |
  • 52 |
  • 53 | Kevlin Henney and Dave Abrahams for their lexical_cast-related insights 54 | and explanations. 55 |
  • 56 |
57 |
58 | 59 | 60 | 65 |
66 |
67 |
68 | PrevUpHomeNext 69 |
70 | 71 | 72 | -------------------------------------------------------------------------------- /doc/html/boost_convert/converters_detail/charconv_converter/formatting_support/leading_whitespace_characters.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Leading Whitespace Characters 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | PrevUpHomeNext 15 |
16 |
17 | 21 |

22 |

23 |
boost::cnv::charconv cnv;
24 | 
25 | BOOST_TEST(-1 == convert<int>( " 12", cnv(arg::skipws = false)).value_or(-1));
26 | BOOST_TEST(12 == convert<int>( " 12", cnv(arg::skipws =  true)).value_or(-1));
27 | 
28 |

29 |

30 |
31 | 32 | 33 | 38 |
39 |
40 |
41 | PrevUpHomeNext 42 |
43 | 44 | 45 | -------------------------------------------------------------------------------- /doc/html/boost_convert/supported_compilers.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Supported Compilers 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | PrevUpHomeNext 15 |
16 |
17 | 20 |

21 | Boost.Convert makes use of SFINAE for correct boost::convert() deployment depending on the context. Unfortunately, 22 | the correctness and the completeness of SFINAE support varies with different 23 | compilers and different versions of those compilers. Consequently, some compilers 24 | fail to compile Boost.Convert API (although the actual 25 | functionality provided by the converters themselves is probably availabable 26 | via other non-standard means). Boost.Convert has been 27 | tested through the Boost regression-testing framework with the following results: 28 |

29 |
    30 |
  • 31 | CLANG. Successfully tested with versions from 2.9 to 3.6; 32 |
  • 33 |
  • 34 | GCC. Successfully tested with versions from 4.2.1 through to 5.0. Earlier 35 | versions were not tested; 36 |
  • 37 |
  • 38 | Intel C++ compiler. Successfully tested with versions from 12.1 forward. 39 | Earlier versions fail to compile Boost.Convert due 40 | to lacking full SFINAE support; 41 |
  • 42 |
  • 43 | MSVC. Successfully tested from MSVC 2013 (msvc-12.0) forward. Earlier versions 44 | had some components disabled due to lacking full SFINAE support; 45 |
  • 46 |
47 |

48 | Please visit Boost.Convert 49 | regression test summary for the latest available report. 50 |

51 |
52 | 53 | 54 | 59 |
60 |
61 |
62 | PrevUpHomeNext 63 |
64 | 65 | 66 | -------------------------------------------------------------------------------- /doc/html/boost_convert/supporting_tools.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Supporting Tools 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | PrevUpHomeNext 15 |
16 |
17 |

18 | Supporting Tools 19 |

20 | 26 |

27 | This section describes a few supporting tools written as part of Boost.Convert 28 | but which might be useful in their own rights. 29 |

30 |
31 |

32 | boost::cnv::range 33 |

34 |

35 | boost::cnv::range is a consolidation of the [begin, 36 | end)-based ranges (such as std::string) and the sentry-based 37 | ranges (such as null-terminated C-style strings). It allows universal traversal 38 | of both types of ranges with 39 |

40 |
for (auto s = range.begin(); s != range.sentry(); ++s)
41 | 
42 |

43 | without the penalty or the need for an extra traversal of the sentry-based 44 | ranges in order to find the end. 45 |

46 |

47 | TODO 48 |

49 |
50 |
51 | 52 | 53 | 58 |
59 |
60 |
61 | PrevUpHomeNext 62 |
63 | 64 | 65 | -------------------------------------------------------------------------------- /doc/html/boost_convert/supporting_tools/boost__cnv__is_range.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | boost::cnv::is_range 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | PrevUpHomeNext 15 |
16 |
17 | 20 |

21 | TODO 22 |

23 |
24 | 25 | 26 | 31 |
32 |
33 |
34 | PrevUpHomeNext 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /doc/html/header/boost/convert/base_hpp.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Header <boost/convert/base.hpp> 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | PrevUpHomeNext 15 |
16 |
17 |

18 | Header <boost/convert/base.hpp>

19 |
20 | 
21 | BOOST_CNV_TO_STRING
22 | BOOST_CNV_STRING_TO
23 | BOOST_CNV_PARAM_SET(param_name)
24 | BOOST_CNV_PARAM_TRY(param_name)
25 |
namespace boost {
26 |   namespace cnv {
27 |     template<typename derived_type> struct cnvbase;
28 |   }
29 | }
30 |
31 | 32 | 33 | 38 |
39 |
40 |
41 | PrevUpHomeNext 42 |
43 | 44 | 45 | -------------------------------------------------------------------------------- /doc/html/header/boost/convert/charconv_hpp.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Header <boost/convert/charconv.hpp> 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | PrevUpHomeNext 15 |
16 |
17 | 19 |
namespace boost {
20 |   namespace cnv {
21 |     struct charconv;
22 |   }
23 | }
24 |
25 | 26 | 27 | 32 |
33 |
34 |
35 | PrevUpHomeNext 36 |
37 | 38 | 39 | -------------------------------------------------------------------------------- /doc/html/header/boost/convert/lexical_cast_hpp.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Header <boost/convert/lexical_cast.hpp> 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | PrevUpHomeNext 15 |
16 |
17 | 19 |
namespace boost {
20 |   namespace cnv {
21 |     struct lexical_cast;
22 |   }
23 | }
24 |
25 | 26 | 27 | 32 |
33 |
34 |
35 | PrevUpHomeNext 36 |
37 | 38 | 39 | -------------------------------------------------------------------------------- /doc/html/header/boost/convert/parameters_hpp.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Header <boost/convert/parameters.hpp> 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | PrevUpHomeNext 15 |
16 |
17 | 19 |
namespace boost {
20 |   namespace cnv {
21 | 
22 |     enum adjust { left, right, center };
23 | 
24 |     enum base { bin = =2, oct = =8, dec = =10, hex = =16 };
25 | 
26 |     enum notation { fixed, scientific, hex };
27 |     namespace parameter {
28 |     }
29 |   }
30 | }
31 |
32 | 33 | 34 | 39 |
40 |
41 |
42 | PrevUpHomeNext 43 |
44 | 45 | 46 | -------------------------------------------------------------------------------- /doc/html/header/boost/convert/printf_hpp.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Header <boost/convert/printf.hpp> 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | PrevUpHomeNext 15 |
16 |
17 | 19 |
namespace boost {
20 |   namespace cnv {
21 |     struct printf;
22 |   }
23 | }
24 |
25 | 26 | 27 | 32 |
33 |
34 |
35 | PrevUpHomeNext 36 |
37 | 38 | 39 | -------------------------------------------------------------------------------- /doc/html/header/boost/convert/spirit_hpp.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Header <boost/convert/spirit.hpp> 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | PrevUpHomeNext 15 |
16 |
17 | 19 |
namespace boost {
20 |   namespace cnv {
21 |     struct spirit;
22 |   }
23 | }
24 |
25 | 26 | 27 | 32 |
33 |
34 |
35 | PrevUpHomeNext 36 |
37 | 38 | 39 | -------------------------------------------------------------------------------- /doc/html/header/boost/convert/stream_hpp.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Header <boost/convert/stream.hpp> 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | PrevUpHomeNext 15 |
16 |
17 | 19 |
20 | 
21 | BOOST_CNV_STRING_ENABLE
22 | BOOST_CNV_PARAM_SET(param_name)
23 | BOOST_CNV_PARAM_TRY(param_name)
24 |
namespace boost {
25 |   namespace cnv {
26 |     template<typename Char> struct basic_stream;
27 | 
28 |     typedef boost::cnv::basic_stream< char > cstream;
29 |     typedef boost::cnv::basic_stream< wchar_t > wstream;
30 |   }
31 | }
32 |
33 | 34 | 35 | 40 |
41 |
42 |
43 | PrevUpHomeNext 44 |
45 | 46 | 47 | -------------------------------------------------------------------------------- /doc/html/header/boost/convert/strtol_hpp.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Header <boost/convert/strtol.hpp> 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | PrevUpHomeNext 15 |
16 |
17 | 19 |
namespace boost {
20 |   namespace cnv {
21 |     struct strtol;
22 |   }
23 | }
24 |
25 | 26 | 27 | 32 |
33 |
34 |
35 | PrevUpHomeNext 36 |
37 | 38 | 39 | -------------------------------------------------------------------------------- /doc/html/header/boost/make_default_hpp.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Header <boost/make_default.hpp> 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | PrevUpHomeNext 15 |
16 |
17 |

18 | Header <boost/make_default.hpp>

19 |
namespace boost {
20 |   template<typename T> T make_default();
21 | }
22 |
23 | 24 | 25 | 30 |
31 |
32 |
33 | PrevUpHomeNext 34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /doc/html/images/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boostorg/convert/6e2419c007b998c087d703e41931141ea555a8e1/doc/html/images/home.png -------------------------------------------------------------------------------- /doc/html/images/important.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boostorg/convert/6e2419c007b998c087d703e41931141ea555a8e1/doc/html/images/important.png -------------------------------------------------------------------------------- /doc/html/images/next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boostorg/convert/6e2419c007b998c087d703e41931141ea555a8e1/doc/html/images/next.png -------------------------------------------------------------------------------- /doc/html/images/note.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boostorg/convert/6e2419c007b998c087d703e41931141ea555a8e1/doc/html/images/note.png -------------------------------------------------------------------------------- /doc/html/images/prev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boostorg/convert/6e2419c007b998c087d703e41931141ea555a8e1/doc/html/images/prev.png -------------------------------------------------------------------------------- /doc/html/images/up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boostorg/convert/6e2419c007b998c087d703e41931141ea555a8e1/doc/html/images/up.png -------------------------------------------------------------------------------- /doc/html/images/warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boostorg/convert/6e2419c007b998c087d703e41931141ea555a8e1/doc/html/images/warning.png -------------------------------------------------------------------------------- /doc/html/standalone_HTML.manifest: -------------------------------------------------------------------------------- 1 | index.html 2 | boost_convert/introduction.html 3 | boost_convert/getting_started.html 4 | boost_convert/getting_started/flexibility_and_adaptability_to_change.html 5 | boost_convert/getting_started/basic_conversion_failure_detection.html 6 | boost_convert/error_detection.html 7 | boost_convert/default_converter.html 8 | boost_convert/alternative_interface.html 9 | boost_convert/converters.html 10 | boost_convert/integration_of_user_types.html 11 | boost_convert/algorithms.html 12 | boost_convert/performance.html 13 | boost_convert/performance/boost_convert_overhead.html 14 | boost_convert/performance/the_bigger_picture.html 15 | boost_convert/other_conversions.html 16 | boost_convert/converters_detail.html 17 | boost_convert/converters_detail/stream_converter.html 18 | boost_convert/converters_detail/stream_converter/locale_support.html 19 | boost_convert/converters_detail/stream_converter/supported_string_types.html 20 | boost_convert/converters_detail/stream_converter/supported_string_types/custom_string_types.html 21 | boost_convert/converters_detail/stream_converter/the___default_constructible__type_requirement.html 22 | boost_convert/converters_detail/strtol_converter.html 23 | boost_convert/converters_detail/strtol_converter/formatting_support.html 24 | boost_convert/converters_detail/strtol_converter/formatting_support/field_width__fill_character_and_adjustment.html 25 | boost_convert/converters_detail/strtol_converter/formatting_support/leading_whitespace_characters.html 26 | boost_convert/converters_detail/strtol_converter/formatting_support/floating_point_precision.html 27 | boost_convert/converters_detail/strtol_converter/supported_string_types.html 28 | boost_convert/converters_detail/strtol_converter/supported_string_types/custom_string_types.html 29 | boost_convert/converters_detail/charconv_converter.html 30 | boost_convert/converters_detail/charconv_converter/formatting_support.html 31 | boost_convert/converters_detail/charconv_converter/formatting_support/field_width__fill_character_and_adjustment.html 32 | boost_convert/converters_detail/charconv_converter/formatting_support/leading_whitespace_characters.html 33 | boost_convert/converters_detail/charconv_converter/formatting_support/floating_point_precision.html 34 | boost_convert/converters_detail/charconv_converter/formatting_support/floating_point_notation.html 35 | boost_convert/converters_detail/charconv_converter/supported_string_types.html 36 | boost_convert/design_notes.html 37 | boost_convert/design_notes/converter_signature.html 38 | boost_convert/design_notes/user_interface_signature.html 39 | boost_convert/supporting_tools.html 40 | boost_convert/supporting_tools/boost__cnv__is_range.html 41 | boost_convert/supporting_tools/boost_declare_has_member.html 42 | boost_convert/supporting_tools/boost_declare_is_callable.html 43 | boost_convert/supported_compilers.html 44 | boost_convert/acknowledgements.html 45 | boost_convert_c___reference.html 46 | boost/cnv/reference.html 47 | boost/cnv/reference_Convert_idm11712.html 48 | boost/cnv/apply_idm11741.html 49 | boost/throw_on_failure.html 50 | boost/convert_idm11767.html 51 | boost/convert_idm11787.html 52 | header/boost/convert/base_hpp.html 53 | boost/cnv/cnvbase.html 54 | BOOST_CNV_TO_STRING.html 55 | BOOST_CNV_STRING_TO.html 56 | BOOST_CNV_PARAM_S_idm12086.html 57 | BOOST_CNV_PARAM_T_idm12088.html 58 | header/boost/convert/charconv_hpp.html 59 | boost/cnv/charconv.html 60 | header/boost/convert/lexical_cast_hpp.html 61 | boost/cnv/lexical_cast.html 62 | header/boost/convert/parameters_hpp.html 63 | header/boost/convert/printf_hpp.html 64 | boost/cnv/printf.html 65 | header/boost/convert/spirit_hpp.html 66 | boost/cnv/spirit.html 67 | header/boost/convert/stream_hpp.html 68 | boost/cnv/basic_stream.html 69 | boost/cnv/basic_stream/ibuffer_type.html 70 | boost/cnv/basic_stream/obuffer_type.html 71 | BOOST_CNV_STRING_ENABLE.html 72 | BOOST_CNV_PARAM_S_idm12432.html 73 | BOOST_CNV_PARAM_T_idm12434.html 74 | header/boost/convert/strtol_hpp.html 75 | boost/cnv/strtol.html 76 | header/boost/make_default_hpp.html 77 | boost/make_default.html 78 | index/s18.html 79 | -------------------------------------------------------------------------------- /doc/index.idx: -------------------------------------------------------------------------------- 1 | #index.idx for Convert Quickbook, Doxygen and Auto-index. 2 | # Copyright (c) Vladimir Batov 2009-2022 3 | # Distributed under the Boost Software License, Version 1.0. 4 | # See copy at http://www.boost.org/LICENSE_1_0.txt. 5 | 6 | !scan ../include/boost/convert/lexical_cast.hpp 7 | !scan ../include/boost/convert/parameters.hpp 8 | !scan ../include/boost/convert/printf.hpp 9 | !scan ../include/boost/convert/spirit.hpp 10 | !scan ../include/boost/convert/stream.hpp 11 | !scan ../include/boost/convert/strtol.hpp 12 | !scan ../include/boost/convert/charconv.hpp 13 | !scan ../include/boost/make_default.hpp 14 | !scan ../include/boost/convert.hpp 15 | 16 | #!scan "../example" ".*.cpp" true 17 | 18 | !scan ../example/algorithms.cpp 19 | !scan ../example/default_converter.cpp 20 | !scan ../example/default_converter_fail.cpp 21 | !scan ../example/getting_started.cpp 22 | !scan ../example/getting_serious.cpp 23 | !scan ../example/lexical_cast.cpp 24 | !scan ../example/stream.cpp 25 | 26 | # Might be useful to Doxygen document everything for maintenance? 27 | #!scan "../include/boost/detail/" "*.hpp" true 28 | 29 | base \<\w*\base\w*\> 30 | boolalpha \<\w*boolalpha\w*\> 31 | fixed \<\w*fixed\w*\> 32 | floating-point \<\w*float\w*\> 33 | dec 34 | encryption \<\w*(encryption|decryption)\w*\> 35 | hex 36 | leading 37 | locale \<\w*\locale\w*\> 38 | precision 39 | oct 40 | scientific 41 | skipws \ 42 | transformation \ 43 | user-defined types (UDT) \<\w*user\w*\> 44 | whitespace \ 45 | 46 | -------------------------------------------------------------------------------- /doc/introduction.qbk: -------------------------------------------------------------------------------- 1 | [/ 2 | Copyright (c) Vladimir Batov 2009-2022 3 | Distributed under the Boost Software License, Version 1.0. 4 | See copy at http://www.boost.org/LICENSE_1_0.txt. 5 | ] 6 | 7 | [section Introduction] 8 | 9 | ['Boost.Convert] builds on the `boost::lexical_cast` experience and takes those type conversion\/transformation-related ideas further 10 | 11 | * to be applicable to a wider range of conversion-related deployment scenarios, 12 | * to provide a more flexible, configurable and extendible type-conversion framework, 13 | * to provide generic consistent behavior, 14 | * to ['unify and to uniformly deploy] various conversion facilities ['through one consistent interface]. 15 | 16 | ['Boost.Convert] provides new and familiar conversion\/transformation-related functionality such as: 17 | 18 | * means to deploy types that do not meet the [@http://en.cppreference.com/w/cpp/named_req/DefaultConstructible ['Default Constructibility]] requirement; 19 | * four types of the conversion-failure ['detection]: 20 | * as part of the same process flow -- basic and generic; 21 | * as a branched process flow -- exception-based and function-based; 22 | * the choice of immediate or delayed exception-throwing and non-throwing conversion-failure ['processing]; 23 | * flexibility of conversion-failure ['processing] via: 24 | * an exception thrown; 25 | * the fallback value returned; 26 | * the fallback function called; 27 | * support for standard algorithms. 28 | 29 | ['Boost.Convert] consists of two components: 30 | 31 | * the `boost::convert()` interface; 32 | * an extendible collection of pluggable converters. 33 | 34 | The `boost::convert()` interface 35 | 36 | * advertises, provides and ensures certain ['consistent behavior]; 37 | * unifies and provides ['one consistent interface] to various conversion facilities. 38 | 39 | The collection of pluggable converters is independent of the `boost::convert()` API facade and is designed to be ['extendible] and extended over time. Currently the following converters are provided: 40 | 41 | * `boost::lexical_cast`-based, 42 | * `printf/scanf`-based, 43 | * `strtol`-inspired, 44 | * `std::stringstream`-based, 45 | * `boost::spirit`-based. 46 | 47 | The converters provide new and familiar functionality and demonstrate how existing and independent conversion facilities might be incorporated in to the ['Boost.Convert] framework. For example, the `std::stream`-based converter draws on the standard `std::streams` functionality and provides: 48 | 49 | * string-to-type and type-to-string conversions; 50 | * formatting support (`std::ios`-based precision, base, upper/lower-case, scientific, etc.); 51 | * support for different `locale`s; 52 | * `char` and `wchar_t` support. 53 | 54 | [import ../example/algorithms.cpp] 55 | 56 | [algorithm_introduction] 57 | 58 | [endsect] [/section Introduction] 59 | 60 | -------------------------------------------------------------------------------- /doc/jamfile.v2: -------------------------------------------------------------------------------- 1 | # Convert documentation Jamfile 2 | 3 | # Copyright (c) Vladimir Batov 2009-2022 4 | # Distributed under the Boost Software License, Version 1.0. 5 | # See copy at http://www.boost.org/LICENSE_1_0.txt. 6 | 7 | using quickbook ; 8 | using doxygen ; 9 | using boostbook ; 10 | 11 | path-constant here : . ; # convenient to refer to files in the same directory as this jamfile.v2 12 | path-constant boost-images : ../../../doc/src/images ; 13 | 14 | import modules ; 15 | 16 | if --enable-index in [ modules.peek : ARGV ] 17 | { 18 | ECHO "Building the convert docs with automatic index generation enabled." ; 19 | using auto-index ; 20 | project convert_doc : requirements 21 | on 22 | index.idx 23 | . 24 | on 25 | html:on 26 | html:generate.index=0 27 | pdf:on 28 | pdf:index.on.type=1 29 | enable_index ; 30 | } 31 | else 32 | { 33 | project convert_doc ; 34 | ECHO "Building the convert docs with automatic index generation disabled. Try building with --enable-index." ; 35 | } 36 | 37 | doxygen convert_reference 38 | : 39 | [ glob $(here)/../include/boost/convert.hpp $(here)/../include/boost/make_default.hpp $(here)/../include/boost/convert/*.hpp ] 40 | : 41 | PROJECT_NAME="CONVERT" 42 | PROJECT_NUMBER=3 43 | SORT_MEMBER_DOCS=NO 44 | SHOW_INCLUDE_FILES=NO 45 | MAX_INITIALIZER_LINES=0 46 | VERBATIM_HEADERS=NO 47 | WARNINGS=NO # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings for undocumented members. 48 | # If EXTRACT_ALL is set to YES then this flag will automatically be disabled. 49 | WARN_IF_UNDOCUMENTED=NO # If WARN_IF_UNDOCUMENTED is set to YES, 50 | # then doxygen will generate warnings for undocumented members. 51 | WARN_IF_DOC_ERROR=YES # If WARN_IF_DOC_ERROR is set to YES, Doxygen will generate warnings for 52 | # potential errors in the documentation. 53 | 54 | #"Reference" 55 | "boost.doxygen.reftitle=Boost.Convert C++ Reference" 56 | ; 57 | 58 | xml convert 59 | : 60 | 00_main.qbk 61 | : 62 | convert_reference 63 | ; 64 | 65 | boostbook standalone 66 | : 67 | convert 68 | : 69 | boost.root=../../../.. 70 | chunk.section.depth=8 71 | toc.section.depth=8 # How far down sections get TOCs. 72 | toc.max.depth=4 # Max depth in each TOC. 73 | 74 | # PDF Options: 75 | # TOC Generation: this is needed for FOP-0.9 and later: 76 | fop1.extensions=0 77 | xep.extensions=1 78 | # TOC generation: this is needed for FOP 0.2, but must not be set to zero for FOP-0.9! 79 | fop.extensions=1 80 | # No indent on body text: 81 | body.start.indent=0pt 82 | # Margin size: 83 | page.margin.inner=0.5in 84 | # Margin size: 85 | page.margin.outer=0.5in 86 | # Paper type = A4 87 | paper.type=A4 88 | # Yes, we want graphics for admonishments: 89 | admon.graphics=1 90 | # Set this one for PDF generation *only*: 91 | # default pnd graphics are awful in PDF form, 92 | # better use SVG's instead: 93 | pdf:admon.graphics.extension=".svg" 94 | pdf:admon.graphics.path=$(boost-images)/ 95 | ; 96 | 97 | install pdfinstall 98 | : standalone 99 | : .. PDF convert.pdf 100 | ; 101 | explicit css ; 102 | explicit images ; 103 | 104 | ############################################################################### 105 | alias boostdoc ; 106 | explicit boostdoc ; 107 | alias boostrelease : standalone ; 108 | explicit boostrelease ; 109 | -------------------------------------------------------------------------------- /doc/lexcast_converter.qbk: -------------------------------------------------------------------------------- 1 | [/ 2 | Copyright (c) Vladimir Batov 2009-2022 3 | Distributed under the Boost Software License, Version 1.0. 4 | See copy at http://www.boost.org/LICENSE_1_0.txt. 5 | ] 6 | 7 | [import ../example/lexical_cast.cpp] 8 | 9 | [section:lexical_cast_converter ['boost::cnv::lexical_cast] Converter] 10 | 11 | The purpose of the converter is to 12 | 13 | * Make use of the `boost::lexical_cast` functionality and performance that many people have become accustomed to and comfortable with; 14 | * Demonstrate how existing independent conversion\/transformation-related facilities might be incorporated in to the ['Boost.Convert] framework. 15 | 16 | The converter can easily replace `boost::lexical_cast`, adding flexibility and convenience: 17 | 18 | [lexical_cast_headers1] 19 | [lexical_cast_example1] 20 | 21 | See the [classref boost::cnv::lexical_cast `boost::cnv::lexical_cast` implementation] for details. 22 | 23 | In order for a user-defined type to be integrated into the `boost::lexical_cast` framework and, consequently, deployed with the `boost::cnv::lexical_cast` converter: 24 | 25 | * ['TypeOut] needs to be [@http://en.cppreference.com/w/cpp/named_req/CopyConstructible ['Copy Constructible]]; 26 | * ['TypeOut] needs to be [@http://en.cppreference.com/w/cpp/named_req/DefaultConstructible ['Default Constructible]]; 27 | * ['TypeOut] needs to be ['Input Streamable]; 28 | * ['TypeIn] needs to be ['Output Streamable]. 29 | 30 | The first two requirements are imposed by the `boost::lexical_cast` design and implementation and the last two requirements by the underlying `std::stringstream` engine. 31 | 32 | [endsect] 33 | 34 | -------------------------------------------------------------------------------- /doc/limitations.qbk: -------------------------------------------------------------------------------- 1 | [/ 2 | Copyright (c) Vladimir Batov 2009-2022 3 | Distributed under the Boost Software License, Version 1.0. 4 | See copy at http://www.boost.org/LICENSE_1_0.txt. 5 | ] 6 | 7 | [section Supported Compilers] 8 | 9 | ['Boost.Convert] makes use of SFINAE for correct `boost::convert()` deployment depending on the context. Unfortunately, the correctness and the completeness of SFINAE support varies with different compilers and different versions of those compilers. Consequently, some compilers fail to compile ['Boost.Convert] API (although the actual functionality provided by the converters themselves is probably availabable via other non-standard means). ['Boost.Convert] has been tested through the Boost regression-testing framework with the following results: 10 | 11 | * CLANG. Successfully tested with versions from 2.9 to 3.6; 12 | 13 | * GCC. Successfully tested with versions from 4.2.1 through to 5.0. Earlier versions were not tested; 14 | 15 | * Intel C++ compiler. Successfully tested with versions from 12.1 forward. Earlier versions fail to compile ['Boost.Convert] due to lacking full SFINAE support; 16 | 17 | * MSVC. Successfully tested from MSVC 2013 (msvc-12.0) forward. Earlier versions had some components disabled due to lacking full SFINAE support; 18 | 19 | Please visit [@http://www.boost.org/development/tests/develop/developer/convert.html ['Boost.Convert] regression test summary] for the latest available report. 20 | 21 | [endsect] 22 | 23 | -------------------------------------------------------------------------------- /doc/no_optional_interface.qbk: -------------------------------------------------------------------------------- 1 | [/ 2 | Copyright (c) Vladimir Batov 2009-2022 3 | Distributed under the Boost Software License, Version 1.0. 4 | See copy at http://www.boost.org/LICENSE_1_0.txt. 5 | ] 6 | 7 | [section Alternative Interface] 8 | 9 | [:[*['"It's not a question of happiness, it's a requirement. Consider the alternative” Doug Horton]]] 10 | 11 | As it was indicated previously [@boost:/libs/optional/index.html `boost::optional`] is the actual type returned by the `boost::convert()` main interface: 12 | 13 | boost::optional boost::convert(TypeIn const&, Converter const&); 14 | 15 | The signature is ['functionally-complete] and routinely elided during compilation. Still, the following alternative (and arguably more traditional) interface might be potentially more suitable for certain deployment scenarios (or due to personal preferences): 16 | 17 | TypeOut convert(TypeIn const&, Converter const&, TypeOut const& fallback_value); 18 | TypeOut convert(TypeIn const&, Converter const&, Functor const& fallback_func); 19 | TypeOut convert(TypeIn const&, Converter const&, boost::throw_on_failure); 20 | 21 | The interface still provides unambiguous behavior and readability, full support for various program flows and various degrees of conversion-failure detection and processing. It can be deployed in a similar fashion as follows: 22 | 23 | [getting_serious_example5] 24 | [getting_serious_example7] 25 | 26 | Still, the described interfaces are convenience wrappers around the main interface which provides the described behavior with: 27 | 28 | [getting_serious_example8] 29 | 30 | [endsect] [/section Return Value] 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /doc/other.qbk: -------------------------------------------------------------------------------- 1 | [/ 2 | Copyright (c) Vladimir Batov 2009-2022 3 | Distributed under the Boost Software License, Version 1.0. 4 | See copy at http://www.boost.org/LICENSE_1_0.txt. 5 | ] 6 | 7 | [section:other_conversions Beyond Basic Conversions] 8 | 9 | An interesting (and yet to be fully explored) property of the described design is that ['Boost.Convert] is not limited to string-to-type and type-to-string conversions. The `boost::convert()` interface is type-agnostic and the plugged-in converter ultimately dictates what type transformations are available. Consequently, a wide range of conversion\/transformation-related tasks can be addressed and ['deployed uniformly] by plugging-in special-purpose converters. 10 | 11 | As an experiment, the code below (taken from ['test/encryption.cpp]) does not do type conversion. Instead, it applies a string transformation: 12 | 13 | string encrypted = boost::convert("ABC", my_cypher).value(); 14 | string decrypted = boost::convert(encrypted, my_cypher).value(); 15 | 16 | BOOST_ASSERT(encrypted == "123"); 17 | BOOST_ASSERT(decrypted == "ABC"); 18 | 19 | The original "ABC" string is "encrypted" as "123" first and then "123" is "decrypted" back to its original "ABC" form. 20 | 21 | Similarly, I personally do not immediately see as objectionable string-transformations like: 22 | 23 | std::u8string utf8 = boost::convert(utf32_str, cnv); 24 | std::u8string utf8 = boost::convert(mbcs_str, cnv); 25 | 26 | [endsect] 27 | -------------------------------------------------------------------------------- /doc/rationale.qbk: -------------------------------------------------------------------------------- 1 | [/ 2 | Copyright (c) Vladimir Batov 2009-2022 3 | Distributed under the Boost Software License, Version 1.0. 4 | See copy at http://www.boost.org/LICENSE_1_0.txt. 5 | ] 6 | 7 | [section Rationale] 8 | 9 | I was using textual configuration files extensively and was also processing and preparing considerable amounts of data in XML. Consequently, I had a need for an ['extendible] library that would provide a ['uniform] interface to convert various data between their internal binary representations and external (predominantly textual) representations. 10 | 11 | The `boost::lexical_cast` library (with its orthogonal and extendible design) looked very promising compared to others (see [@http://www.gotw.ca/publications/mill19.htm The String Formatters of Manor Farm] by H. Sutter for the discussion of alternatives). Unfortunately, 12 | 13 | * many deployed user types simply did not meet `boost::lexical_cast` requirements (namely, [@http://en.cppreference.com/w/cpp/named_req/DefaultConstructible ['Default Constructibility]]); 14 | * failure to convert a user-provided configuration parameter was not that rare or exceptional to justify the hassle and the overhead of exception processing; consequently, additional flexibility (['if], ['when] and ['how]) in handling conversion failures was needed; 15 | * additional conversion-related functionality (such as formatting and locale support) were needed. 16 | 17 | The original hope was to see `boost::lexical_cast` extended to be applicable to a wider range of deployment scenarios. However, after discussions with Kevlin Henney (the `boost::lexical_cast` author) and in the Boost Developers forum it was collectively decided that the desired extensions were not compatible with the original design and the idea of what `boost::lexical_cast` embodied and, therefore, a new component with richer interface and functionality was needed. That decision resulted in the development of ['Boost.Convert] described in this document. 18 | 19 | [endsect] 20 | -------------------------------------------------------------------------------- /doc/section-end.qbk: -------------------------------------------------------------------------------- 1 | [endsect] 2 | 3 | [/ 4 | Copyright (c) Vladimir Batov 2009-2022 5 | Distributed under the Boost Software License, Version 1.0. 6 | See copy at http://www.boost.org/LICENSE_1_0.txt. 7 | ] 8 | -------------------------------------------------------------------------------- /doc/strtol_converter.qbk: -------------------------------------------------------------------------------- 1 | [/ 2 | Copyright (c) Vladimir Batov 2009-2022 3 | Distributed under the Boost Software License, Version 1.0. 4 | See copy at http://www.boost.org/LICENSE_1_0.txt. 5 | ] 6 | 7 | [section:strtol_converter ['boost::cnv::strtol] Converter] 8 | 9 | The converter started as a deployment example (with the `std::strtol` family of functions as its conversion engine) and a part of the performance-test set. Surprisingly, the converter showed fairly decent all-around performance (see [link boost_convert.performance.converters_compared Converters Compared]) and, consequently, has been rewritten and extended to provide additional conversion support and formatting. At the moment it seems to be a good choice with moderate formatting facilities and adequate performance. 10 | 11 | It should be noted though that the converter is nowhere as mature as `boost::cnv::lexical_cast` or `boost::cnv::stream` and, therefore, bugs are to be expected. 12 | 13 | [section Basic Deployment] 14 | [strtol_basic_deployment_header] 15 | [strtol_basic_deployment] 16 | [endsect] 17 | 18 | [section Formatting Support] 19 | 20 | [section Numeric Base (bin, oct, dec, hex)] 21 | [strtol_numeric_base_header] 22 | [strtol_numeric_base] 23 | [wide_strtol_numeric_base] 24 | [endsect] 25 | 26 | [section Field Width, Fill Character and Adjustment] 27 | [strtol_width] 28 | [endsect] 29 | 30 | [section Leading Whitespace Characters] 31 | [strtol_skipws] 32 | [wide_strtol_skipws] 33 | [endsect] 34 | 35 | [section Floating-Point Precision] 36 | [strtol_precision] 37 | [endsect] 38 | [endsect] 39 | 40 | [section Supported String Types] 41 | 42 | [section Wide String] 43 | [wide_strtol_numeric_base] 44 | [wide_strtol_skipws] 45 | [endsect] 46 | 47 | [section Custom String Types] 48 | [my_string_declaration] 49 | [strtol_user_string] 50 | [endsect] 51 | 52 | [endsect] 53 | [endsect] 54 | 55 | -------------------------------------------------------------------------------- /doc/tools.qbk: -------------------------------------------------------------------------------- 1 | [/ 2 | Copyright (c) Vladimir Batov 2009-2022 3 | Distributed under the Boost Software License, Version 1.0. 4 | See copy at http://www.boost.org/LICENSE_1_0.txt. 5 | ] 6 | 7 | [section:supporting_tools Supporting Tools] 8 | 9 | This section describes a few supporting tools written as part of ['Boost.Convert] but which might be useful in their own rights. 10 | 11 | [section boost::cnv::range] 12 | 13 | ['boost::cnv::range] is a consolidation of the [begin, end)-based ranges (such as ['std::string]) and the sentry-based ranges (such as null-terminated C-style strings). It allows universal traversal of both types of ranges with 14 | 15 | for (auto s = range.begin(); s != range.sentry(); ++s) 16 | 17 | without the penalty or the need for an extra traversal of the sentry-based ranges in order to find the end. 18 | 19 | TODO 20 | 21 | [endsect] 22 | [section boost::cnv::is_range] 23 | 24 | TODO 25 | 26 | [endsect] 27 | [section BOOST_DECLARE_HAS_MEMBER] 28 | 29 | The BOOST_DECLARE_HAS_MEMBER macro allows to declare a trait which would then let introspect the existence of a class member (a data member or a member function) with the specified name. 30 | 31 | For example, the following declarations introduce `local::has_begin` and `local::has_funop` traits which then allow to test if the supplied class has respectively `begin` and `operator()` members: 32 | 33 | [has_member_declaration] 34 | 35 | Now these traits can be used as follows: 36 | 37 | [has_member_classes_tested] 38 | [has_member_usage] 39 | 40 | As it can be seen from the example the traits only check for the existence of a member (be that a data member or a member function) with the specified name. 41 | 42 | [endsect] 43 | [section BOOST_DECLARE_IS_CALLABLE] 44 | 45 | The BOOST_DECLARE_IS_CALLABLE macro extends the functionality provided by BOOST_DECLARE_HAS_MEMBER and allows to declare a trait which would then let introspect the existence of a named class member function ['callable with the supplied signature]. 46 | 47 | For example, the following declarations introduce `local::can_call_funop` and `local::can_call_func` traits: 48 | 49 | [is_callable_declaration] 50 | 51 | The traits allow to test if the supplied class has respectively `operator()` and `func()` member functions callable with the specified signature: 52 | 53 | [is_callable_classes_tested] 54 | [is_callable_usage1] 55 | [is_callable_usage2] 56 | 57 | As it can be seen from the example the traits check for the existence of a ['callable] member function but ['not necessarily of the specified signature]. Please check the ['Boost.TTI] library for the latter. 58 | 59 | [endsect] 60 | [endsect] 61 | 62 | -------------------------------------------------------------------------------- /doc/user_types.qbk: -------------------------------------------------------------------------------- 1 | [/ 2 | Copyright (c) Vladimir Batov 2009-2022 3 | Distributed under the Boost Software License, Version 1.0. 4 | See copy at http://www.boost.org/LICENSE_1_0.txt. 5 | ] 6 | 7 | [import ../test/strtol_converter.cpp] 8 | 9 | [section:integration_of_user_types Integration of User-Defined Types] 10 | 11 | Probably the most obvious way to support a new type is to write a converter (potentially by inheriting from an existing converter) that understands the type and implements whatever transformation functionality is required. That said, conversions to certain types are very common (for example, string\/text-related conversions) and, consequently, an ability to ['extend] support of an ['existing] converter onto a user-defined type might be the preferred option. The obvious example of such design might be the ['`std::iostream`] library and its type-integration mechanism based on 12 | 13 | std::istream& operator>>(std::istream&, Type&); // For input 14 | std::ostream& operator<<(std::ostream&, Type const&); // For output 15 | 16 | Within the ['Boost.Convert] framework the integration and support of user-defined types is every converter's private business. Every converter is free to implement its own (or re-use an existing) user-type-integration mechanism. 17 | 18 | [heading ['boost::cnv::stream et al.]] 19 | 20 | Unsurprisingly, the converters based on the ['`std::iostream`] library use the mechanism introduced and supported by that library. That is, 21 | 22 | * for output ['Type] needs to be ['Output Streamable]; 23 | * for input ['Type] needs to be ['Input Streamable]. 24 | 25 | which in practical terms means that the type needs to have the following operators defined: 26 | 27 | std::istream& operator>>(std::istream&, Type&); // For input 28 | std::ostream& operator<<(std::ostream&, Type const&); // For output 29 | 30 | For example, 31 | 32 | [change_declaration] 33 | [change_stream_operators] 34 | 35 | That allows handling conversions of user-defined types with ['`std::iostream`]-based converters: 36 | 37 | [stream_example6] 38 | 39 | [heading ['boost::cnv::strtol et al.]] 40 | 41 | Other converters (based on `boost::cnv::cnvbase`) implement support for user types similarly but without the ['`std::iostream`]-related overhead (see [link boost_convert.performance.converters_compared Converters Compared]). Namely, new types are supported by the converters after the following is defined: 42 | 43 | void operator>>(TypeIn const&, boost::optional&); 44 | 45 | For example, the mentioned ['`change`] class is deployed with `boost::cnv::strol` after the following ['change-to-string] and ['string-to-change] conversions are defined: 46 | 47 | [change_convert_operators] 48 | 49 | which are not that dissimilar to (but considerably more efficient than) previously shown: 50 | 51 | std::istream& operator>>(std::istream&, change&); 52 | std::ostream& operator<<(std::ostream&, change const&); 53 | 54 | That allows handling conversions of user-defined types with `boost::cnv::strtol`: 55 | 56 | [strtol_user_type] 57 | 58 | [endsect] 59 | 60 | -------------------------------------------------------------------------------- /example/default_converter.cpp: -------------------------------------------------------------------------------- 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 7 | #include 8 | #include 9 | 10 | #ifdef ONLY_FOR_DEMONSTRATION_PURPOSES 11 | //[default_converter_declaration_simple 12 | struct boost::cnv::by_default : boost::cnv::cstream {}; 13 | //] 14 | #endif 15 | //[default_converter_declaration_formatted 16 | struct boost::cnv::by_default : boost::cnv::cstream 17 | { 18 | by_default() { (*this)(std::uppercase)(std::hex); } 19 | }; 20 | //] 21 | 22 | int 23 | main(int, char const* []) 24 | { 25 | //[default_converter_example1 26 | // No explicit converter provided. boost::cnv::by_default is used. 27 | int i = boost::convert("F").value_or(-1); 28 | std::string s = boost::convert(255).value_or("bad"); 29 | 30 | // 'i' and 's' are converted using boost::cnv::cstream 31 | // with std::uppercase and std::hex formatting applied. 32 | 33 | BOOST_TEST(i == 15); // 15(10) = F(16) 34 | BOOST_TEST(s == "FF"); // 255(10) = FF(16) 35 | //] 36 | 37 | return boost::report_errors(); 38 | } 39 | 40 | -------------------------------------------------------------------------------- /example/default_converter_fail.cpp: -------------------------------------------------------------------------------- 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 7 | 8 | using std::string; 9 | using boost::convert; 10 | 11 | // This is expected to fail to compile: 12 | //'boost::cnv::by_default' : class has no constructors. 13 | 14 | int 15 | main(int, char const* []) 16 | { 17 | int i = convert("123").value(); 18 | string s = convert(123).value(); 19 | } 20 | 21 | -------------------------------------------------------------------------------- /example/getting_serious.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009-2020 Vladimir Batov. 2 | // Use, modification and distribution are subject to the Boost Software License, 3 | // Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. 4 | 5 | #ifdef BOOST_MSVC 6 | # pragma warning(disable : 4127) // conditional expression is constant. 7 | # pragma warning(disable : 4189) // local variable is initialized but not referenced. 8 | #endif 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | using std::string; 15 | using boost::convert; 16 | using boost::lexical_cast; 17 | using boost::optional; 18 | 19 | static void process_failure() {} 20 | static void log(...) {} 21 | static int fallback_function() { return -1; } 22 | 23 | //[getting_serious_default_converter 24 | struct boost::cnv::by_default : boost::cnv::cstream {}; 25 | //] 26 | static 27 | void 28 | example1() 29 | { 30 | boost::cnv::cstream cnv; 31 | std::string const str = "123"; 32 | std::string const str1 = "123"; 33 | std::string const str2 = "123"; 34 | std::string const str3 = "123"; 35 | int const fallback_value = -1; 36 | 37 | { 38 | //[getting_serious_example1 39 | int i2 = convert("not an int", cnv).value_or(-1); // after the call i2==-1 40 | 41 | if (i2 == -1) process_failure(); 42 | //] 43 | } 44 | { 45 | //[getting_serious_example2 46 | try 47 | { 48 | int i1 = lexical_cast(str); // Throws if the conversion fails. 49 | int i2 = convert(str, cnv).value(); // Throws if the conversion fails. 50 | } 51 | catch (...) 52 | { 53 | process_failure(); 54 | } 55 | //] 56 | } 57 | { 58 | //[getting_serious_example3 59 | optional r1 = convert(str1, cnv); // Does not throw on conversion failure. 60 | optional r2 = convert(str2, cnv); // Does not throw on conversion failure. 61 | // ... 62 | try // Delayed processing of potential exceptions. 63 | { 64 | int i1 = r1.value(); // Will throw if conversion failed. 65 | int i2 = r2.value(); // Will throw if conversion failed. 66 | } 67 | catch (boost::bad_optional_access const&) 68 | { 69 | // Handle failed conversion. 70 | } 71 | 72 | // Exceptions are avoided altogether. 73 | int i1 = r1 ? r1.value() : fallback_value; 74 | int i2 = r2.value_or(fallback_value); 75 | int i3 = convert(str3, cnv).value_or(fallback_value); 76 | int i4 = convert(str3, cnv).value_or_eval(fallback_function); 77 | //] 78 | } 79 | } 80 | 81 | //[getting_serious_example5 82 | struct fallback_func 83 | { 84 | int operator()() const { log("Failed to convert"); return 42; } 85 | }; 86 | //] 87 | 88 | static 89 | void 90 | example4() 91 | { 92 | boost::cnv::cstream cnv; 93 | std::string const str = "123"; 94 | int const fallback_value = -1; 95 | //[getting_serious_example4 96 | boost::optional res = boost::convert(str, cnv); 97 | 98 | if (!res) log("str conversion failed!"); 99 | 100 | int i1 = res.value_or(fallback_value); 101 | 102 | // ...proceed 103 | //] 104 | //[getting_serious_example6 105 | // Fallback function is called when failed 106 | int i2 = convert(str, cnv).value_or_eval(fallback_func()); 107 | int i3 = convert(str, cnv, fallback_func()); // Same as above. Alternative API. 108 | //] 109 | } 110 | 111 | static 112 | void 113 | example7() 114 | { 115 | boost::cnv::cstream cnv; 116 | std::string const str = "123"; 117 | int const fallback_value = -1; 118 | //[getting_serious_example7 119 | // Error-processing behavior are specified unambiguously and uniformly. 120 | // a) i1: Returns the provided fallback value; 121 | // b) i2: Calls the provided failure-processing function; 122 | // c) i3: Throws an exception. 123 | 124 | int i1 = convert(str, cnv, fallback_value); 125 | int i2 = convert(str, cnv, fallback_func()); 126 | 127 | try 128 | { 129 | // Throwing behavior specified explicitly rather than implied. 130 | int i3 = convert(str, cnv, boost::throw_on_failure); 131 | } 132 | catch (boost::bad_optional_access const&) 133 | { 134 | // Handle failed conversion. 135 | } 136 | //] 137 | //[getting_serious_example8 138 | int m1 = convert(str, cnv).value_or(fallback_value); 139 | int m2 = convert(str, cnv).value_or_eval(fallback_func()); 140 | int m3 = convert(str, cnv).value(); 141 | //] 142 | //[getting_serious_example9 143 | int n1 = convert(str).value_or(fallback_value); 144 | int n2 = convert(str).value_or_eval(fallback_func()); 145 | int n3 = convert(str).value(); 146 | //] 147 | } 148 | 149 | int 150 | main(int, char const* []) 151 | { 152 | example1(); 153 | example4(); 154 | example7(); 155 | } 156 | -------------------------------------------------------------------------------- /example/jamfile.v2: -------------------------------------------------------------------------------- 1 | # Convert Jamfile 2 | # Copyright (c) Vladimir Batov 2009-2014 3 | # Distributed under the Boost Software License, Version 1.0. 4 | # See copy at http://www.boost.org/LICENSE_1_0.txt. 5 | 6 | # bring in the rules for testing 7 | import testing ; 8 | 9 | project convert_examples 10 | : requirements 11 | /boost/convert//boost_convert 12 | on 13 | gcc:all 14 | msvc:all 15 | gcc:"-Wno-unused-local-typedefs -Wno-unused-variable -Wno-long-long" 16 | msvc:"/wd4996 /wd4512 /wd4610 /wd4510 /wd4127 /wd4701 /wd4127 /wd4305 /wd4100 /wd4512 /wd4714" 17 | msvc:on 18 | msvc:_CRT_SECURE_NO_DEPRECATE 19 | msvc:_SCL_SECURE_NO_DEPRECATE 20 | msvc:_SCL_SECURE_NO_WARNINGS 21 | msvc:_CRT_SECURE_NO_WARNINGS 22 | ../include 23 | ; 24 | 25 | run algorithms.cpp : : : : convert_example_algorithms ; 26 | run default_converter.cpp : : : : convert_example_default_converter ; 27 | run getting_serious.cpp : : : : convert_example_getting_started ; 28 | run getting_started.cpp : : : : convert_example_getting_serious ; 29 | run lexical_cast.cpp : : : : convert_example_lexical_cast_converter ; 30 | run stream.cpp : : : : convert_example_stream_converter ; 31 | 32 | compile-fail default_converter_fail.cpp : off "-w" ; 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /example/lexical_cast.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009-2020 Vladimir Batov. 2 | // Use, modification and distribution are subject to the Boost Software License, 3 | // Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. 4 | 5 | //[lexical_cast_headers1 6 | #include 7 | #include 8 | #include 9 | 10 | using std::string; 11 | using boost::convert; 12 | using boost::lexical_cast; 13 | 14 | struct boost::cnv::by_default : boost::cnv::lexical_cast {}; 15 | //] 16 | 17 | int 18 | main(int, char const* []) 19 | { 20 | //[lexical_cast_example1 21 | int i1 = lexical_cast("123"); // Throws if the conversion fails. 22 | int i2 = convert("123").value(); // Throws if the conversion fails. 23 | int i3 = convert("uhm").value_or(-1); // Returns -1 if the conversion fails. 24 | string s1 = lexical_cast(123); 25 | string s2 = convert(123).value(); 26 | 27 | BOOST_TEST(i1 == 123); 28 | BOOST_TEST(i2 == 123); 29 | BOOST_TEST(i3 == -1); 30 | BOOST_TEST(s1 == "123"); 31 | BOOST_TEST(s2 == "123"); 32 | //] 33 | 34 | return boost::report_errors(); 35 | } 36 | -------------------------------------------------------------------------------- /example/stream.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009-2020 Vladimir Batov. 2 | // Use, modification and distribution are subject to the Boost Software License, 3 | // Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. 4 | 5 | #include "../test/test.hpp" 6 | 7 | #if !defined(BOOST_CONVERT_CXX14) 8 | int main(int, char const* []) { return 0; } 9 | #else 10 | 11 | #include 12 | #include 13 | 14 | //[stream_headers1 15 | #include 16 | #include 17 | #include 18 | 19 | using std::string; 20 | using boost::convert; 21 | 22 | struct boost::cnv::by_default : boost::cnv::cstream {}; 23 | //] 24 | //[stream_headers2 25 | namespace cnv = boost::cnv; 26 | namespace arg = boost::cnv::parameter; 27 | //] 28 | 29 | static 30 | void 31 | example1() 32 | { 33 | //[stream_example1 34 | int i2 = convert("123").value(); // Throws when fails. 35 | int i3 = convert("uhm").value_or(-1); // Returns -1 when fails. 36 | string s2 = convert(123).value(); 37 | 38 | BOOST_TEST(i2 == 123); 39 | BOOST_TEST(i3 == -1); 40 | BOOST_TEST(s2 == "123"); 41 | //] 42 | } 43 | 44 | static 45 | void 46 | example2() 47 | { 48 | //[stream_example2 49 | boost::cnv::cstream ccnv; 50 | boost::cnv::wstream wcnv; 51 | 52 | int v01 = convert(" FF", ccnv(std::hex)(std::skipws)).value_or(0); 53 | int v02 = convert(L" F", wcnv(std::hex)(std::skipws)).value_or(0); 54 | int v03 = convert(" FF", ccnv(std::dec)(std::skipws)).value_or(-5); 55 | int v04 = convert(L" F", wcnv(std::dec)(std::skipws)).value_or(-5); 56 | 57 | BOOST_TEST(v01 == 255); // "FF" 58 | BOOST_TEST(v02 == 15); // L"F" 59 | BOOST_TEST(v03 == -5); // Failed to convert "FF" as decimal. 60 | BOOST_TEST(v04 == -5); // Failed to convert L"F" as decimal. 61 | //] 62 | //[stream_example3 63 | ccnv(std::showbase)(std::uppercase)(std::hex); 64 | 65 | BOOST_TEST(convert(255, ccnv, "bad") == "0XFF"); 66 | BOOST_TEST(convert( 15, ccnv, "bad") == "0XF"); 67 | //] 68 | //[stream_example4 69 | ccnv(arg::base = cnv::base::dec) 70 | (arg::uppercase = true) 71 | (arg::notation = cnv::notation::scientific); 72 | //] 73 | //[stream_example5 74 | ccnv(std::dec)(std::uppercase)(std::scientific); 75 | //] 76 | } 77 | 78 | static 79 | void 80 | example6() 81 | { 82 | //[stream_example6 83 | boost::cnv::cstream cnv1; 84 | boost::cnv::lexical_cast cnv2; 85 | 86 | change chg = change::up; 87 | string s1 = convert(chg, cnv1, "bad"); // Input type (change) deduced 88 | string s2 = convert(change::dn, cnv1, "bad"); // Input type (change) enforced 89 | 90 | BOOST_TEST(convert("up", cnv1, change::no) == change::up); 91 | BOOST_TEST(convert("up", cnv2, change::no) == change::up); 92 | BOOST_TEST(s1 == "up"); 93 | BOOST_TEST(s2 == "dn"); 94 | //] 95 | } 96 | 97 | int 98 | main(int, char const* []) 99 | { 100 | example1(); 101 | example2(); 102 | example6(); 103 | 104 | return boost::report_errors(); 105 | } 106 | 107 | #endif 108 | -------------------------------------------------------------------------------- /include/boost/convert/charconv.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Dvir Yitzchaki. 2 | // Use, modification and distribution are subject to the Boost Software License, 3 | // Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. 4 | 5 | #ifndef BOOST_CONVERT_CHARCONV_BASED_CONVERTER_HPP 6 | #define BOOST_CONVERT_CHARCONV_BASED_CONVERTER_HPP 7 | 8 | #ifdef BOOST_NO_CXX17_HDR_CHARCONV 9 | #error "This header requires which is unavailable" 10 | #endif // BOOST_NO_CXX17_HDR_CHARCONV 11 | 12 | #ifdef BOOST_NO_CXX17_STRUCTURED_BINDINGS 13 | #error "This header requires structured bindings which is unavailable" 14 | #endif // BOOST_NO_CXX17_STRUCTURED_BINDINGS 15 | 16 | #ifdef BOOST_NO_CXX17_IF_CONSTEXPR 17 | #error "This header requires constexpr if which is unavailable" 18 | #endif // BOOST_NO_CXX17_IF_CONSTEXPR 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | namespace boost::cnv { struct charconv; } 26 | 27 | /// @brief std::to/from_chars-based extended converter 28 | /// @details Good overall performance and moderate formatting facilities. 29 | struct boost::cnv::charconv : public boost::cnv::cnvbase 30 | { 31 | using this_type = boost::cnv::charconv; 32 | using base_type = boost::cnv::cnvbase; 33 | 34 | template 35 | cnv::range 36 | to_str(in_type value_in, char* buf) const 37 | { 38 | auto [ptr, err] = [&] 39 | { 40 | if constexpr (std::is_integral_v) 41 | return std::to_chars(buf, buf + bufsize_, value_in, int(base_)); 42 | else 43 | return std::to_chars(buf, buf + bufsize_, value_in, chars_format(), precision_); 44 | }(); 45 | return cnv::range(buf, err == std::errc{} ? ptr : buf); 46 | } 47 | template 48 | void 49 | str_to(cnv::range range, optional& result_out) const 50 | { 51 | out_type result = boost::make_default(); 52 | auto [ptr, err] = [&] 53 | { 54 | char_cptr beg = &*range.begin(); 55 | char_cptr end = beg + range.size(); 56 | 57 | if constexpr (std::is_integral_v) 58 | return std::from_chars(beg, end, result, int(base_)); 59 | else 60 | return std::from_chars(beg, end, result, chars_format()); 61 | }(); 62 | if (err == std::errc{}) 63 | result_out = result; 64 | } 65 | std::chars_format chars_format() const 66 | { 67 | static constexpr std::chars_format format[] = 68 | { 69 | std::chars_format::fixed, 70 | std::chars_format::scientific, 71 | std::chars_format::hex 72 | }; 73 | return format[int(notation_)]; 74 | } 75 | }; 76 | 77 | #endif // BOOST_CONVERT_CHARCONV_BASED_CONVERTER_HPP 78 | -------------------------------------------------------------------------------- /include/boost/convert/detail/char.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009-2020 Vladimir Batov. 2 | // Use, modification and distribution are subject to the Boost Software License, 3 | // Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. 4 | 5 | #ifndef BOOST_CONVERT_DETAIL_IS_CHAR_HPP 6 | #define BOOST_CONVERT_DETAIL_IS_CHAR_HPP 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | namespace boost { namespace cnv 13 | { 14 | using char_type = char; 15 | using uchar_type = unsigned char; 16 | using wchar_type = wchar_t; 17 | using char_cptr = char const*; 18 | 19 | namespace detail 20 | { 21 | template struct is_char : std::false_type {}; 22 | template<> struct is_char< char_type> : std:: true_type {}; 23 | template<> struct is_char : std:: true_type {}; 24 | } 25 | template struct is_char : detail::is_char::type> {}; 26 | 27 | template inline bool is_space(char_type); 28 | template inline char_type to_upper(char_type); 29 | 30 | template<> inline bool is_space ( char_type c) { return bool(std::isspace(static_cast(c))); } 31 | template<> inline bool is_space (uchar_type c) { return bool(std::isspace(c)); } 32 | template<> inline bool is_space (wchar_type c) { return bool(std::iswspace(c)); } 33 | template<> inline char_type to_upper ( char_type c) { return std::toupper(static_cast(c)); } 34 | template<> inline uchar_type to_upper (uchar_type c) { return std::toupper(c); } 35 | template<> inline wchar_type to_upper (wchar_type c) { return std::towupper(c); } 36 | }} 37 | 38 | #endif // BOOST_CONVERT_DETAIL_IS_CHAR_HPP 39 | 40 | -------------------------------------------------------------------------------- /include/boost/convert/detail/config.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009-2020 Vladimir Batov. 2 | // Use, modification and distribution are subject to the Boost Software License, 3 | // Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. 4 | 5 | #ifndef BOOST_CONVERT_FORWARD_HPP 6 | #define BOOST_CONVERT_FORWARD_HPP 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #if defined(BOOST_NO_CXX14) 14 | #undef BOOST_CONVERT_CXX14 15 | #else 16 | #define BOOST_CONVERT_CXX14 17 | #endif 18 | 19 | // Intel 12.0 and lower have broken SFINAE 20 | #if defined(BOOST_INTEL) && (BOOST_INTEL <= 1200) 21 | #undef BOOST_CONVERT_CXX14 22 | #endif 23 | 24 | // No C++11 support 25 | #if defined(__GNUC__) && (__GNUC__ < 6) 26 | #undef BOOST_CONVERT_CXX14 27 | #endif 28 | 29 | // MSVC-11 and lower have broken SFINAE 30 | #if defined(_MSVC_VER) && (_MSVC_VER < 1800) 31 | #undef BOOST_CONVERT_CXX14 32 | #endif 33 | 34 | #if defined(_MSC_VER) 35 | 36 | //MSVC++ 7.0 _MSC_VER == 1300 37 | //MSVC++ 7.1 _MSC_VER == 1310 (Visual Studio 2003) 38 | //MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005) 39 | //MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008) 40 | //MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010) 41 | //MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012) 42 | //MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013) 43 | //MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015) 44 | //MSVC++ 15.0 _MSC_VER == 1910 (Visual Studio 2017) 45 | 46 | # pragma warning(disable: 4100) // unreferenced formal parameter 47 | # pragma warning(disable: 4146) // unary minus operator applied to unsigned type 48 | # pragma warning(disable: 4180) // qualifier applied to function type has no meaning 49 | # pragma warning(disable: 4224) 50 | # pragma warning(disable: 4244) 51 | # pragma warning(disable: 4800) // forcing value to bool 52 | # pragma warning(disable: 4996) 53 | 54 | #if _MSC_VER < 1900 /* MSVC-14 defines real snprintf()... just about time! */ 55 | # define snprintf _snprintf 56 | #endif 57 | 58 | #endif 59 | 60 | #endif // BOOST_CONVERT_FORWARD_HPP 61 | -------------------------------------------------------------------------------- /include/boost/convert/detail/has_member.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009-2020 Vladimir Batov. 2 | // Use, modification and distribution are subject to the Boost Software License, 3 | // Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. 4 | 5 | #ifndef BOOST_CONVERT_HAS_MEMBER_HPP 6 | #define BOOST_CONVERT_HAS_MEMBER_HPP 7 | 8 | #include 9 | 10 | // This macro allows to check if a type has a member named "__member_name__"... 11 | // ... regardless of the signature. If takes advantage of the following behavior related to 12 | // function resolution. Say, both, foo and base, declare a method with the same name "func": 13 | // 14 | // struct foo { int func (int, int) { return 0; } }; 15 | // struct base { void func () {} }; 16 | // struct mixin : public foo, public base {}; 17 | // 18 | // Now, if we inherit from both -- foo and base -- classes, then the following calls will fail 19 | // mixin_ptr(0)->func(); 20 | // mixin_ptr(0)->func(5, 5); 21 | // with the error message (gcc): request for member func is ambiguous 22 | // regardless if we provide any arguments or not even though one might expect that 23 | // arg-based signature resolution might kick in. The only way to deploy those methods is: 24 | // 25 | // mixin_ptr(0)->foo::func(); 26 | // mixin_ptr(0)->base::func(5, 5); 27 | // 28 | // C2. The actual signature of __member_name__ is not taken into account. If 29 | // __T__::__member_name__(any-signature) exists, then the introduced base::__member_name__ 30 | // will cause mixin->__member_name__() call to fail to compile (due to ambiguity). 31 | // C3. &U::__member_name__ (a.k.a. &mixin::__member_name__) 32 | // has the type of func_type only if __T__::__member_name__ does not exist. 33 | // If __T__::member_name does exist, then mixin::__member_name__ is ambiguous 34 | // and "yes_type test (...)" kicks in instead. 35 | // C4. Need to find some unique/ugly name so that it does not clash if this macro is 36 | // used inside some other template class; 37 | 38 | #define BOOST_DECLARE_HAS_MEMBER(__trait_name__, __member_name__) \ 39 | \ 40 | template /*C4*/ \ 41 | class __trait_name__ \ 42 | { \ 43 | using check_type = typename boost::remove_const<__boost_has_member_T__>::type; \ 44 | using yes_type = ::boost::type_traits::yes_type; \ 45 | using no_type = ::boost::type_traits:: no_type; \ 46 | \ 47 | struct base { void __member_name__(/*C2*/) {}}; \ 48 | struct mixin : public base, public check_type {}; \ 49 | \ 50 | template struct aux {}; \ 51 | \ 52 | template static no_type test(aux<&U::__member_name__>*); /*C3*/ \ 53 | template static yes_type test(...); \ 54 | \ 55 | public: \ 56 | \ 57 | BOOST_STATIC_CONSTANT(bool, value = (sizeof(yes_type) == sizeof(test(0)))); \ 58 | } 59 | 60 | #endif // BOOST_CONVERT_HAS_MEMBER_HPP 61 | -------------------------------------------------------------------------------- /include/boost/convert/detail/is_fun.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009-2020 Vladimir Batov. 2 | // Use, modification and distribution are subject to the Boost Software License, 3 | // Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. 4 | 5 | #ifndef BOOST_CONVERT_IS_FUNCTION_HPP 6 | #define BOOST_CONVERT_IS_FUNCTION_HPP 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | namespace boost { namespace cnv 15 | { 16 | using yes_type = ::boost::type_traits::yes_type; 17 | using no_type = ::boost::type_traits:: no_type; 18 | 19 | template 20 | struct check_functor { BOOST_STATIC_CONSTANT(bool, value = false); }; 21 | 22 | template 23 | struct is_fun { BOOST_STATIC_CONSTANT(bool, value = false); }; 24 | 25 | template 26 | struct check_functor 27 | { 28 | static yes_type test (TypeOut const&); 29 | static no_type test (...); 30 | 31 | static bool BOOST_CONSTEXPR_OR_CONST value = sizeof(yes_type) == sizeof(test(((Functor*) 0)->operator()())); 32 | }; 33 | template 34 | struct is_fun::value && !is_convertible::value, void>::type> 36 | { 37 | BOOST_DECLARE_HAS_MEMBER(has_funop, operator()); 38 | 39 | BOOST_STATIC_CONSTANT(bool, value = (check_functor::value, Functor, TypeOut>::value)); 40 | }; 41 | template 42 | struct is_fun::value && 45 | function_types::function_arity::value == 0 && 46 | !is_same::value, 47 | void>::type> 48 | { 49 | using out_type = TypeOut; 50 | using func_type = typename function_types::result_type::type; 51 | 52 | BOOST_STATIC_CONSTANT(bool, value = (is_convertible::value)); 53 | }; 54 | }} 55 | 56 | #endif // BOOST_CONVERT_IS_FUNCTION_HPP 57 | 58 | -------------------------------------------------------------------------------- /include/boost/convert/detail/is_string.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009-2020 Vladimir Batov. 2 | // Use, modification and distribution are subject to the Boost Software License, 3 | // Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. 4 | 5 | #ifndef BOOST_CONVERT_DETAIL_IS_STRING_HPP 6 | #define BOOST_CONVERT_DETAIL_IS_STRING_HPP 7 | 8 | #include 9 | 10 | namespace boost { namespace cnv 11 | { 12 | namespace detail 13 | { 14 | template struct is_string : std::false_type {}; 15 | 16 | template struct is_string 17 | { 18 | static bool BOOST_CONSTEXPR_OR_CONST value = cnv::is_char::value; 19 | }; 20 | template struct is_string 21 | { 22 | static bool BOOST_CONSTEXPR_OR_CONST value = cnv::is_char::value; 23 | }; 24 | template struct is_string 25 | { 26 | static bool BOOST_CONSTEXPR_OR_CONST value = cnv::is_char::value; 27 | }; 28 | } 29 | template 30 | struct is_string : detail::is_string< 31 | typename std::remove_const::type, 32 | std::is_class::value && cnv::is_range::value> 33 | {}; 34 | }} 35 | 36 | #endif // BOOST_CONVERT_DETAIL_IS_STRING_HPP 37 | -------------------------------------------------------------------------------- /include/boost/convert/detail/range.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009-2020 Vladimir Batov. 2 | // Use, modification and distribution are subject to the Boost Software License, 3 | // Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. 4 | 5 | #ifndef BOOST_CONVERT_DETAIL_RANGE_HPP 6 | #define BOOST_CONVERT_DETAIL_RANGE_HPP 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | namespace boost { namespace cnv 13 | { 14 | namespace detail 15 | { 16 | template struct is_range : std::false_type {}; 17 | 18 | template struct is_range 19 | { 20 | BOOST_DECLARE_HAS_MEMBER(has_begin, begin); 21 | BOOST_DECLARE_HAS_MEMBER( has_end, end); 22 | 23 | static bool BOOST_CONSTEXPR_OR_CONST value = has_begin::value && has_end::value; 24 | }; 25 | } 26 | template struct is_range : detail::is_range::type, boost::is_class::value> {}; 27 | template struct range; 28 | template struct iterator; 29 | 30 | template 31 | struct iterator::value>::type> 32 | { 33 | using type = typename boost::range_iterator::type; 34 | using const_type = typename boost::range_iterator::type; 35 | using value_type = typename boost::iterator_value::type; 36 | }; 37 | template 38 | struct iterator 39 | { 40 | using value_type = typename boost::remove_const::type; 41 | using type = T*; 42 | using const_type = value_type const*; 43 | }; 44 | template 45 | struct range_base 46 | { 47 | using value_type = typename cnv::iterator::value_type; 48 | using iterator = typename cnv::iterator::type; 49 | using const_iterator = typename cnv::iterator::const_type; 50 | using sentry_type = const_iterator; 51 | 52 | iterator begin () { return begin_; } 53 | const_iterator begin () const { return begin_; } 54 | void operator++ () { ++begin_; } 55 | // void operator-- () { --end_; } 56 | 57 | protected: 58 | 59 | range_base (iterator b, iterator e) : begin_(b), end_(e) {} 60 | 61 | iterator begin_; 62 | iterator mutable end_; 63 | }; 64 | 65 | template 66 | struct range::value>::type> : public range_base 67 | { 68 | using this_type = range; 69 | using base_type = range_base; 70 | using iterator = typename base_type::iterator; 71 | using const_iterator = typename base_type::const_iterator; 72 | using sentry_type = const_iterator; 73 | 74 | range (T& r) : base_type(r.begin(), r.end()) {} 75 | 76 | iterator end () { return base_type::end_; } 77 | const_iterator end () const { return base_type::end_; } 78 | sentry_type sentry () const { return base_type::end_; } 79 | std::size_t size () const { return base_type::end_ - base_type::begin_; } 80 | bool empty () const { return base_type::begin_ == base_type::end_; } 81 | }; 82 | 83 | template 84 | struct range::value>::type> : public range_base 85 | { 86 | using this_type = range; 87 | using base_type = range_base; 88 | using value_type = typename boost::remove_const::type; 89 | using iterator = T*; 90 | using const_iterator = value_type const*; 91 | 92 | struct sentry_type 93 | { 94 | friend bool operator!=(iterator it, sentry_type) { return !!*it; } 95 | }; 96 | 97 | range (iterator b, iterator e =0) : base_type(b, e) {} 98 | 99 | iterator end () { return base_type::end_ ? base_type::end_ : (base_type::end_ = base_type::begin_ + size()); } 100 | const_iterator end () const { return base_type::end_ ? base_type::end_ : (base_type::end_ = base_type::begin_ + size()); } 101 | sentry_type sentry () const { return sentry_type(); } 102 | std::size_t size () const { return std::char_traits::length(base_type::begin_); } 103 | bool empty () const { return !*base_type::begin_; } 104 | }; 105 | template 106 | struct range : public range 107 | { 108 | range (T* b, T* e =0) : range(b, e) {} 109 | }; 110 | template 111 | struct range : public range 112 | { 113 | range (T* b, T* e =0) : range(b, e) {} 114 | }; 115 | }} 116 | 117 | #endif // BOOST_CONVERT_DETAIL_RANGE_HPP 118 | -------------------------------------------------------------------------------- /include/boost/convert/lexical_cast.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009-2020 Vladimir Batov. 2 | // Use, modification and distribution are subject to the Boost Software License, 3 | // Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. 4 | 5 | #ifndef BOOST_CONVERT_LEXICAL_CAST_HPP 6 | #define BOOST_CONVERT_LEXICAL_CAST_HPP 7 | 8 | #include 9 | 10 | namespace boost { namespace cnv { struct lexical_cast; }} 11 | 12 | /// @brief boost::lexical_cast-based converter 13 | /// @details The purpose of the converter is to 14 | /// * Make use of the boost::lexical_cast functionality and performance that many people have become 15 | /// accustomed to and comfortable with; 16 | /// * Demonstrate how existing independent conversion/transformation-related facilities might be 17 | // incorporated in to the Boost.Convert framework. 18 | /// 19 | /// The converter can easily replace boost::lexical_cast, adding flexibility and convenience. 20 | 21 | struct boost::cnv::lexical_cast 22 | { 23 | template 24 | void 25 | operator()(TypeIn const& value_in, boost::optional& result_out) const 26 | { 27 | try 28 | { 29 | result_out = boost::lexical_cast(value_in); 30 | } 31 | catch (boost::bad_lexical_cast const&) 32 | { 33 | } 34 | } 35 | }; 36 | 37 | #endif // BOOST_CONVERT_LEXICAL_CAST_HPP 38 | -------------------------------------------------------------------------------- /include/boost/convert/parameters.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009-2020 Vladimir Batov. 2 | // Use, modification and distribution are subject to the Boost Software License, 3 | // Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. 4 | 5 | #ifndef BOOST_CONVERT_PARAMETERS_HPP 6 | #define BOOST_CONVERT_PARAMETERS_HPP 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | namespace boost { namespace cnv 13 | { 14 | enum class adjust : uint8_t { left, right, center }; 15 | enum class base : uint8_t { bin =2, oct =8, dec =10, hex =16 }; 16 | enum class notation : uint8_t { fixed, scientific, hex }; 17 | 18 | namespace parameter 19 | { 20 | BOOST_PARAMETER_NAME(( adjust, type) adjust) 21 | BOOST_PARAMETER_NAME(( base, type) base) 22 | BOOST_PARAMETER_NAME(( fill, type) fill) 23 | BOOST_PARAMETER_NAME(( locale, type) locale) 24 | BOOST_PARAMETER_NAME(( notation, type) notation) 25 | BOOST_PARAMETER_NAME((precision, type) precision) 26 | BOOST_PARAMETER_NAME(( skipws, type) skipws) 27 | BOOST_PARAMETER_NAME((uppercase, type) uppercase) 28 | BOOST_PARAMETER_NAME((lowercase, type) lowercase) 29 | BOOST_PARAMETER_NAME(( width, type) width) 30 | } 31 | }} 32 | 33 | #endif // BOOST_CONVERT_PARAMETERS_HPP 34 | -------------------------------------------------------------------------------- /include/boost/convert/printf.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009-2020 Vladimir Batov. 2 | // Use, modification and distribution are subject to the Boost Software License, 3 | // Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. 4 | 5 | #ifndef BOOST_CONVERT_PRINTF_HPP 6 | #define BOOST_CONVERT_PRINTF_HPP 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | namespace boost { namespace cnv { struct printf; }} 16 | 17 | struct boost::cnv::printf : boost::cnv::cnvbase 18 | { 19 | using this_type = boost::cnv::printf; 20 | using base_type = boost::cnv::cnvbase; 21 | 22 | using base_type::operator(); 23 | 24 | template 25 | cnv::range 26 | to_str(in_type value_in, char* buf) const 27 | { 28 | char_cptr fmt = printf_format(pos()); 29 | int num_chars = snprintf(buf, bufsize_, fmt, precision_, value_in); 30 | bool success = num_chars < bufsize_; 31 | 32 | return cnv::range(buf, success ? (buf + num_chars) : buf); 33 | } 34 | template 35 | void 36 | str_to(cnv::range range, optional& result_out) const 37 | { 38 | out_type result = boost::make_default(); 39 | char_cptr fmt = sscanf_format(pos()); 40 | int num_read = sscanf(&*range.begin(), fmt, &result); 41 | 42 | if (num_read == 1) 43 | result_out = result; 44 | } 45 | 46 | private: 47 | 48 | template int pos() const 49 | { 50 | // C1. The orders of types and formats must match. 51 | 52 | using types = boost::mpl::vector< 53 | double, float, int, unsigned int, short int, 54 | unsigned short int, long int, unsigned long int>; 55 | using found = typename boost::mpl::find::type; 56 | using pos = typename found::pos; 57 | 58 | return pos::value; 59 | } 60 | char_cptr printf_format(int type_pos) const 61 | { 62 | char_cptr BOOST_CONSTEXPR_OR_CONST d_fmt[3][8] = 63 | { 64 | { "%.*f", "%.*f", "%.*d", "%.*u", "%.*hd", "%.*hu", "%.*ld", "%.*lu" }, //C1. fxd 65 | { "%.*e", "%.*e", "%.*d", "%.*u", "%.*hd", "%.*hu", "%.*ld", "%.*lu" }, //C1. sci 66 | { "%.*a", "%.*a", "%.*d", "%.*u", "%.*hd", "%.*hu", "%.*ld", "%.*lu" } //C1. hex 67 | }; 68 | char_cptr BOOST_CONSTEXPR_OR_CONST x_fmt[3][8] = 69 | { 70 | { "%.*f", "%.*f", "%.*x", "%.*x", "%.*hx", "%.*hx", "%.*lx", "%.*lx" }, //C1. fxd 71 | { "%.*e", "%.*e", "%.*x", "%.*x", "%.*hx", "%.*hx", "%.*lx", "%.*lx" }, //C1. sci 72 | { "%.*a", "%.*a", "%.*x", "%.*x", "%.*hx", "%.*hx", "%.*lx", "%.*lx" } //C1. hex 73 | }; 74 | char_cptr BOOST_CONSTEXPR_OR_CONST o_fmt[3][8] = 75 | { 76 | { "%.*f", "%.*f", "%.*o", "%.*o", "%.*ho", "%.*ho", "%.*lo", "%.*lo" }, //C1. fxd 77 | { "%.*e", "%.*e", "%.*o", "%.*o", "%.*ho", "%.*ho", "%.*lo", "%.*lo" }, //C1. sci 78 | { "%.*a", "%.*a", "%.*o", "%.*o", "%.*ho", "%.*ho", "%.*lo", "%.*lo" } //C1. hex 79 | }; 80 | return base_ == base::dec ? d_fmt[int(notation_)][type_pos] 81 | : base_ == base::hex ? x_fmt[int(notation_)][type_pos] 82 | : base_ == base::oct ? o_fmt[int(notation_)][type_pos] 83 | : (BOOST_ASSERT(0), nullptr); 84 | } 85 | char_cptr sscanf_format(int type_pos) const 86 | { 87 | char_cptr BOOST_CONSTEXPR_OR_CONST d_fmt[3][8] = 88 | { 89 | { "%lf", "%f", "%d", "%u", "%hd", "%hu", "%ld", "%lu" }, //C1. fxd 90 | { "%le", "%e", "%d", "%u", "%hd", "%hu", "%ld", "%lu" }, //C1. sci 91 | { "%la", "%a", "%d", "%u", "%hd", "%hu", "%ld", "%lu" } //C1. hex 92 | }; 93 | char_cptr BOOST_CONSTEXPR_OR_CONST x_fmt[3][8] = 94 | { 95 | { "%lf", "%f", "%x", "%x", "%hx", "%hx", "%lx", "%lx" }, //C1. fxd 96 | { "%le", "%e", "%x", "%x", "%hx", "%hx", "%lx", "%lx" }, //C1. sci 97 | { "%la", "%a", "%x", "%x", "%hx", "%hx", "%lx", "%lx" } //C1. hex 98 | }; 99 | char_cptr BOOST_CONSTEXPR_OR_CONST o_fmt[3][8] = 100 | { 101 | { "%lf", "%f", "%o", "%o", "%ho", "%ho", "%lo", "%lo" }, //C1. fxd 102 | { "%le", "%e", "%o", "%o", "%ho", "%ho", "%lo", "%lo" }, //C1. sci 103 | { "%la", "%a", "%o", "%o", "%ho", "%ho", "%lo", "%lo" } //C1. hex 104 | }; 105 | return base_ == base::dec ? d_fmt[int(notation_)][type_pos] 106 | : base_ == base::hex ? x_fmt[int(notation_)][type_pos] 107 | : base_ == base::oct ? o_fmt[int(notation_)][type_pos] 108 | : (BOOST_ASSERT(0), nullptr); 109 | } 110 | }; 111 | 112 | #endif // BOOST_CONVERT_PRINTF_HPP 113 | -------------------------------------------------------------------------------- /include/boost/convert/spirit.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009-2020 Vladimir Batov. 2 | // Use, modification and distribution are subject to the Boost Software License, 3 | // Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. 4 | 5 | #ifndef BOOST_CONVERT_SPIRIT_BASED_CONVERTER_HPP 6 | #define BOOST_CONVERT_SPIRIT_BASED_CONVERTER_HPP 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace boost { namespace cnv { struct spirit; }} 14 | 15 | struct boost::cnv::spirit : boost::cnv::cnvbase 16 | { 17 | using this_type = boost::cnv::spirit; 18 | using base_type = boost::cnv::cnvbase; 19 | 20 | using base_type::operator(); 21 | 22 | template 23 | void 24 | str_to(cnv::range range, optional& result_out) const 25 | { 26 | using parser = typename boost::spirit::traits::create_parser::type; 27 | 28 | auto beg = range.begin(); 29 | auto end = range.end(); 30 | auto result = out_type(); 31 | 32 | if (boost::spirit::qi::parse(beg, end, parser(), result)) 33 | if (beg == end) // ensure the whole string has been parsed 34 | result_out = result; 35 | } 36 | template 37 | cnv::range 38 | to_str(in_type value_in, char_type* beg) const 39 | { 40 | using generator = typename boost::spirit::traits::create_generator::type; 41 | 42 | auto end = beg; 43 | bool good = boost::spirit::karma::generate(end, generator(), value_in); 44 | 45 | return cnv::range(beg, good ? end : beg); 46 | } 47 | }; 48 | 49 | #endif // BOOST_CONVERT_SPIRIT_BASED_CONVERTER_HPP 50 | 51 | -------------------------------------------------------------------------------- /include/boost/make_default.hpp: -------------------------------------------------------------------------------- 1 | /// @file 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 | #ifndef BOOST_MAKE_DEFAULT_HPP 7 | #define BOOST_MAKE_DEFAULT_HPP 8 | 9 | namespace boost 10 | { 11 | /// @details A considerable number of libraries require an instance of a class 12 | /// provided (storage created and initialized). For example, 13 | /// @code 14 | /// Type result; 15 | /// ... 16 | /// istream >> result; 17 | /// @endcode 18 | /// In generic code that results in the Default Constructibility requirement imposed 19 | /// on every type 'Type' to be used with the respective code. Inevitably, that requirement 20 | /// a) either excludes all the classes that for various reasons do not meet that requirement or 21 | /// b) imposes certain (not necessarily desirable) design/implementation onto respective classes. 22 | /// 23 | /// Deployment of boost::make_default() eliminates the Default Constructibility requirement with 24 | /// @code 25 | /// Type result = boost::make_default(); 26 | /// ... 27 | /// istream >> result; 28 | /// @endcode 29 | /// Classes with no default constructor can now be included via a boost::make_default() specialization: 30 | /// @code 31 | /// namespace boost 32 | /// { 33 | /// template<> inline Type make_default() { return Type(parameters); } 34 | /// } 35 | /// @endcode 36 | 37 | template T make_default() { return T(); } 38 | } 39 | 40 | #endif // BOOST_MAKE_DEFAULT_HPP 41 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Boost.Convert 5 | 6 | 7 | 17 | 18 | 19 |

20 | Automatic redirection failed, please go to doc/html/index.html 21 |

22 |

Copyright Vladimir Batov 2009-2020

23 |

Distributed under the Boost Software License, Version 1.0. (See accompanying file 24 | LICENSE_1_0.txt or copy at 25 | www.boost.org/LICENSE_1_0.txt). 26 |

27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | BOOST_ROOT = $(PRJROOT)/boost 2 | 3 | cflags := -O3 -I./include -I$(BOOST_ROOT) -Wno-unused-variable -Wno-uninitialized -Wno-deprecated-declarations -Wno-stringop-overflow 4 | lflags := -L$(BOOST_ROOT)/stage/lib -lboost_timer -lboost_chrono -lboost_system 5 | 6 | target_1 = convert-test-callable test/callable.cpp 7 | target_3 = convert-test-fallbacks test/fallbacks.cpp 8 | target_4 = convert-test-spirit-converter test/spirit_converter.cpp 9 | target_5 = convert-test-stream-converter test/stream_converter.cpp 10 | target_6 = convert-test-lcast-converter test/lcast_converter.cpp 11 | target_7 = convert-test-printf-converter test/printf_converter.cpp 12 | target_8 = convert-test-strtol-converter test/strtol_converter.cpp 13 | target_9 = convert-test-encryption test/encryption.cpp 14 | target_10 = convert-test-user-type test/user_type.cpp 15 | target_11 = convert-test-str-to-int test/str_to_int.cpp 16 | target_12 = convert-test-sfinae test/sfinae.cpp 17 | target_13 = convert-test-has-member test/has_member.cpp 18 | target_14 = convert-test-performance test/performance.cpp 19 | target_15 = convert-test-performance-spirit test/performance_spirit.cpp 20 | target_16 = convert-test-charconv-converter test/charconv_converter.cpp 21 | target_17 = convert-test-63 test/issue-63.cpp 22 | 23 | target_21 = convert-example-algorithms example/algorithms.cpp 24 | target_22 = convert-example-default_converter example/default_converter.cpp 25 | target_23 = convert-example-getting_serious example/getting_serious.cpp 26 | target_24 = convert-example-getting_started example/getting_started.cpp 27 | target_25 = convert-example-lexical_cast example/lexical_cast.cpp 28 | target_26 = convert-example-stream example/stream.cpp 29 | 30 | include $(PRJROOT)/make/makefile 31 | -------------------------------------------------------------------------------- /meta/libraries.json: -------------------------------------------------------------------------------- 1 | { 2 | "key": "convert", 3 | "name": "Convert", 4 | "authors": [ "Vladimir Batov" ], 5 | "maintainers": [ "Vladimir Batov " ], 6 | "description": "An extendible and configurable type-conversion framework.", 7 | "category": [ 8 | "Miscellaneous", 9 | "String" 10 | ], 11 | "cxxstd": "11" 12 | } 13 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(BoostTest OPTIONAL RESULT_VARIABLE HAVE_BOOST_TEST) 2 | 3 | if(HAVE_BOOST_TEST) 4 | boost_test(TYPE run NAME convert_test_callable SOURCES callable.cpp LINK_LIBRARIES Boost::convert) 5 | boost_test(TYPE run NAME convert_test_fallbacks SOURCES fallbacks.cpp LINK_LIBRARIES Boost::convert) 6 | boost_test(TYPE run NAME convert_test_spirit_converter SOURCES spirit_converter.cpp LINK_LIBRARIES Boost::convert) 7 | boost_test(TYPE run NAME convert_test_stream_converter SOURCES stream_converter.cpp LINK_LIBRARIES Boost::convert Boost::included_unit_test_framework) 8 | boost_test(TYPE run NAME convert_test_printf_converter SOURCES printf_converter.cpp LINK_LIBRARIES Boost::convert Boost::included_unit_test_framework) 9 | boost_test(TYPE run NAME convert_test_strtol_converter SOURCES strtol_converter.cpp LINK_LIBRARIES Boost::convert) 10 | boost_test(TYPE run NAME convert_test_lcast_converter SOURCES lcast_converter.cpp LINK_LIBRARIES Boost::convert) 11 | boost_test(TYPE run NAME convert_test_encryption SOURCES encryption.cpp LINK_LIBRARIES Boost::convert) 12 | boost_test(TYPE run NAME convert_test_user_type SOURCES user_type.cpp LINK_LIBRARIES Boost::convert) 13 | boost_test(TYPE run NAME convert_test_str_to_int SOURCES str_to_int.cpp LINK_LIBRARIES Boost::convert) 14 | boost_test(TYPE run NAME convert_test_sfinae SOURCES sfinae.cpp LINK_LIBRARIES Boost::convert) 15 | boost_test(TYPE run NAME convert_test_has_member SOURCES has_member.cpp LINK_LIBRARIES Boost::convert) 16 | 17 | # these tests require C++17 18 | boost_test(TYPE run NAME convert_test_charconv_converter SOURCES charconv_converter.cpp LINK_LIBRARIES Boost::convert Boost::included_unit_test_framework COMPILE_FEATURES cxx_std_17) 19 | endif() 20 | 21 | function(boost_exe) 22 | cmake_parse_arguments("BOOST_EXE" "" "NAME" "SOURCES;LINK_LIBRARIES;COMPILE_DEFINITIONS;COMPILE_OPTIONS;COMPILE_FEATURES;INCLUDE_DIRECTORIES" ${ARGN}) 23 | 24 | add_executable(${BOOST_EXE_NAME} EXCLUDE_FROM_ALL ${BOOST_EXE_SOURCES}) 25 | target_link_libraries(${BOOST_EXE_NAME} PRIVATE ${BOOST_EXE_LINK_LIBRARIES}) 26 | target_include_directories(${BOOST_EXE_NAME} PRIVATE ${BOOST_EXE_INCLUDE_DIRECTORIES}) 27 | target_compile_definitions(${BOOST_EXE_NAME} PRIVATE ${BOOST_EXE_COMPILE_DEFINITIONS}) 28 | target_compile_options(${BOOST_EXE_NAME} PRIVATE ${BOOST_EXE_COMPILE_OPTIONS}) 29 | target_compile_features(${BOOST_EXE_NAME} PRIVATE ${BOOST_EXE_COMPILE_FEATURES}) 30 | endfunction() 31 | 32 | boost_exe(NAME convert_test_performance SOURCES performance.cpp LINK_LIBRARIES Boost::convert Boost::timer Boost::chrono) 33 | boost_exe(NAME convert_test_performance_spirit SOURCES performance_spirit.cpp LINK_LIBRARIES Boost::convert INCLUDE_DIRECTORIES ${Boost_SOURCE_DIR} COMPILE_FEATURES cxx_std_17) 34 | -------------------------------------------------------------------------------- /test/callable.cpp: -------------------------------------------------------------------------------- 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 13 | #include 14 | #include 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& value_out) 22 | //] 23 | { 24 | try 25 | { 26 | value_out = lexical_cast(value_in); 27 | } 28 | catch (...) 29 | { 30 | } 31 | } 32 | 33 | template 34 | void 35 | convert_all(TypeIn const&, boost::optional&) 36 | { 37 | } 38 | 39 | template 40 | void 41 | assign(boost::optional& value_out, Type const& value_in) 42 | { 43 | value_out = value_in; 44 | } 45 | 46 | struct converter1 47 | { 48 | template 49 | void 50 | operator()(TypeIn const&, boost::optional&) const 51 | { 52 | } 53 | }; 54 | 55 | //[callable_example4 56 | struct take_double { void operator()(double, boost::optional&) const {}}; 57 | struct take_int { void operator()(int, boost::optional&) const {}}; 58 | //] 59 | 60 | //[callable_example6 61 | struct double_only 62 | { 63 | // Declared for all types. 64 | template void operator()(TypeIn, boost::optional&) const; 65 | }; 66 | 67 | // Defined only for certain types. 68 | template<> void double_only::operator()(double, boost::optional&) const {} 69 | //] 70 | 71 | int 72 | main(int, char const* []) 73 | { 74 | using func_type = std::function&)>; 75 | 76 | char const* const str = "-12"; 77 | 78 | // Testing old-function-based converter. 79 | //[callable_example2 80 | int v01 = convert(str, plain_old_func).value_or(-1); 81 | //] 82 | // Testing std::function-based converter. 83 | int v02 = convert(str, func_type(plain_old_func)).value_or(-1); 84 | // Testing crazy std::bind-based converter. 85 | //[callable_example3 86 | int v03 = convert(str, 87 | std::bind(assign, std::placeholders::_2, 88 | std::bind(boost::lexical_cast, 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(str, convert_all); 95 | convert(11, convert_all); 96 | convert< int>(str, converter1()); 97 | convert(11, converter1()); 98 | convert(11.23, take_double()); 99 | convert(11, take_int()); 100 | //[callable_example5 101 | convert(11, take_double()); // Compiler applies int-to-double promotion to call the converter. 102 | convert(11.23, take_int()); // Compiler applies double-to-int implicit truncation. 103 | //] 104 | //[callable_example7 105 | convert(11.23, double_only()); // Fine. 106 | // convert(11, double_only()); // Fails: undefined reference to double_only::operator() 107 | //] 108 | 109 | return boost::report_errors(); 110 | } 111 | 112 | #endif 113 | -------------------------------------------------------------------------------- /test/encryption.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009-2020 Vladimir Batov. 2 | // Use, modification and distribution are subject to the Boost Software License, 3 | // Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. 4 | 5 | #include "./test.hpp" 6 | 7 | #if !defined(BOOST_CONVERT_CXX14) 8 | int main(int, char const* []) { return 0; } 9 | #else 10 | 11 | #include 12 | 13 | static 14 | bool 15 | my_cypher(std::string const& value_in, boost::optional& value_out) 16 | { 17 | size_t const cypher = 'A' - '1'; 18 | 19 | value_out = value_in; 20 | 21 | for (std::string::iterator it = value_out->begin(); it != value_out->end(); ++it) 22 | (*it < 'A') ? (*it += cypher) : (*it -= cypher); 23 | 24 | return true; 25 | } 26 | 27 | int 28 | main(int, char const* []) 29 | { 30 | //////////////////////////////////////////////////////////////////////////// 31 | // Testing custom converter. 32 | //////////////////////////////////////////////////////////////////////////// 33 | 34 | std::string encrypted = boost::convert("ABC", my_cypher).value(); 35 | std::string decrypted = boost::convert(encrypted, my_cypher).value(); 36 | 37 | BOOST_TEST(encrypted == "123"); 38 | BOOST_TEST(decrypted == "ABC"); 39 | 40 | return boost::report_errors(); 41 | } 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /test/fallbacks.cpp: -------------------------------------------------------------------------------- 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 13 | #include 14 | #include 15 | 16 | namespace { namespace local 17 | { 18 | bool called_functor_int; 19 | bool called_functor_double; 20 | bool called_functor_foo; 21 | bool called_function_int; 22 | bool called_function_long; 23 | }} 24 | 25 | struct functor_int { int operator() () const { local:: called_functor_int = true; return INT_MAX; }}; 26 | struct functor_double { double operator() () const { local::called_functor_double = true; return INT_MAX; }}; 27 | struct functor_foo { int func (int) const { local:: called_functor_foo = true; return INT_MAX; }}; 28 | 29 | int function_int () { local:: called_function_int = true; return INT_MAX; } 30 | long function_long () { local::called_function_long = true; return INT_MAX; } 31 | 32 | int 33 | main(int, char const* []) 34 | { 35 | auto cnv = boost::cnv::cstream(); 36 | auto foo = functor_foo(); 37 | 38 | int i01 = boost::convert("uhm", cnv).value_or_eval(functor_int()); 39 | int i02 = boost::convert("uhm", cnv).value_or_eval(functor_double()); 40 | int i03 = boost::convert("uhm", cnv).value_or_eval(std::bind(&functor_foo::func, foo, 0)); 41 | int i04 = boost::convert("uhm", cnv).value_or_eval(function_int); 42 | int i05 = boost::convert("uhm", cnv).value_or_eval(function_long); 43 | 44 | BOOST_TEST(local:: called_functor_int && i01 == INT_MAX); 45 | BOOST_TEST(local::called_functor_double && i02 == INT_MAX); 46 | BOOST_TEST(local:: called_functor_foo && i03 == INT_MAX); 47 | BOOST_TEST(local:: called_function_int && i04 == INT_MAX); 48 | BOOST_TEST(local:: called_function_long && i05 == INT_MAX); 49 | 50 | local:: called_functor_int = false; 51 | local::called_functor_double = false; 52 | local:: called_functor_foo = false; 53 | local:: called_function_int = false; 54 | local:: called_function_long = false; 55 | 56 | boost::convert("uhm", cnv, functor_int()); 57 | boost::convert("uhm", cnv, functor_double()); 58 | boost::convert("uhm", cnv, std::bind(&functor_foo::func, foo, 0)); 59 | boost::convert("uhm", cnv, function_int); 60 | boost::convert("uhm", cnv, function_long); 61 | 62 | BOOST_TEST(local:: called_functor_int && i01 == INT_MAX); 63 | BOOST_TEST(local::called_functor_double && i02 == INT_MAX); 64 | BOOST_TEST(local:: called_functor_foo && i03 == INT_MAX); 65 | BOOST_TEST(local:: called_function_int && i04 == INT_MAX); 66 | BOOST_TEST(local:: called_function_long && i05 == INT_MAX); 67 | 68 | try 69 | { 70 | boost::convert("uhm", cnv, boost::throw_on_failure); 71 | BOOST_TEST(0); 72 | } 73 | catch (boost::bad_optional_access const&) 74 | { 75 | } 76 | return boost::report_errors(); 77 | } 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /test/has_member.cpp: -------------------------------------------------------------------------------- 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 13 | #include 14 | #include 15 | 16 | //[has_member_declaration 17 | namespace { namespace local 18 | { 19 | BOOST_DECLARE_HAS_MEMBER(has_begin, begin); 20 | BOOST_DECLARE_HAS_MEMBER(has_funop, operator()); 21 | }} 22 | //] 23 | //[has_member_classes_tested 24 | namespace { namespace local 25 | { 26 | struct test01 { int begin; }; 27 | struct test02 { char* begin() { return 0; } }; 28 | struct test22 { void operator()() {} }; 29 | }} 30 | //] 31 | 32 | namespace { namespace local 33 | { 34 | struct test03 35 | { 36 | void begin(int) {} 37 | int begin(int, int) { return 0; } 38 | }; 39 | struct test04 40 | { 41 | virtual ~test04() {} 42 | 43 | private: virtual char* begin() { return 0; } 44 | }; 45 | struct test05 46 | { 47 | virtual char* begin() { return 0; } 48 | virtual ~test05() {} 49 | }; 50 | struct test06 : public test04 {}; 51 | struct test07 : private test04 {}; 52 | struct test08 : public test05 {}; 53 | struct test09 : private test05 {}; 54 | 55 | struct test11 { int no_begin; }; 56 | struct test12 { char* no_begin() { return 0; } }; 57 | }} 58 | 59 | namespace { namespace local 60 | { 61 | struct test21 { void zoo () {} }; 62 | struct test23 { void operator() () const {} }; 63 | struct test24 { int operator() (int) { return 0; } }; 64 | struct test25 { int operator() (int) const { return 0; } }; 65 | struct test26 { int operator() (int) const { return 0; } void operator() () const {} }; 66 | }} 67 | 68 | int 69 | main(int, char const* []) 70 | { 71 | BOOST_TEST(local::has_begin::value == true); 72 | BOOST_TEST(local::has_begin::value == true); 73 | BOOST_TEST(local::has_begin::value == true); 74 | BOOST_TEST(local::has_begin::value == true); 75 | BOOST_TEST(local::has_begin::value == true); 76 | BOOST_TEST(local::has_begin::value == true); 77 | BOOST_TEST(local::has_begin::value == true); 78 | BOOST_TEST(local::has_begin::value == true); 79 | BOOST_TEST(local::has_begin::value == true); 80 | BOOST_TEST(local::has_begin::value == true); 81 | BOOST_TEST(local::has_begin >::value == true); 82 | 83 | BOOST_TEST(local::has_begin::value == false); 84 | BOOST_TEST(local::has_begin::value == false); 85 | BOOST_TEST(local::has_begin::value == false); 86 | 87 | //[has_member_usage 88 | BOOST_TEST(local::has_begin::value == true); 89 | BOOST_TEST(local::has_begin::value == true); 90 | BOOST_TEST(local::has_funop::value == true); 91 | //] 92 | 93 | BOOST_TEST(local::has_funop::value == false); 94 | BOOST_TEST(local::has_funop::value == true); 95 | BOOST_TEST(local::has_funop::value == true); 96 | BOOST_TEST(local::has_funop::value == true); 97 | BOOST_TEST(local::has_funop::value == true); 98 | BOOST_TEST(local::has_funop::value == true); 99 | 100 | return boost::report_errors(); 101 | } 102 | 103 | #endif 104 | -------------------------------------------------------------------------------- /test/issue-63.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | auto cnv4 = boost::cnv::charconv(); 8 | std::string PuNum = "2"; 9 | auto optPuNum = boost::convert(PuNum, cnv4); 10 | 11 | if (optPuNum) 12 | std::cout << *optPuNum << "\n"; 13 | else 14 | std::cout << "nullopt\n"; 15 | 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /test/jamfile.v2: -------------------------------------------------------------------------------- 1 | # Convert Jamfile 2 | # Copyright (c) Vladimir Batov 2009-2014 3 | # Distributed under the Boost Software License, Version 1.0. 4 | # See copy at http://www.boost.org/LICENSE_1_0.txt. 5 | 6 | require-b2 5.0.1 ; 7 | 8 | import-search /boost/config/checks ; 9 | 10 | # bring in the rules for testing 11 | import testing ; 12 | import config : requires ; 13 | 14 | project convert_test 15 | : requirements 16 | /boost/convert//boost_convert 17 | on 18 | icpc:"-std=c++11" 19 | clang:"-std=c++11" 20 | gcc:all 21 | gcc:"-O3 -std=c++0x -Wno-unused-variable -Wno-long-long" 22 | msvc:all 23 | msvc:"/wd4996 /wd4512 /wd4610 /wd4510 /wd4127 /wd4701 /wd4127 /wd4305 /wd4244 /wd4714 /wd4189" 24 | msvc:on 25 | msvc:_CRT_SECURE_NO_DEPRECATE 26 | msvc:_SCL_SECURE_NO_DEPRECATE 27 | msvc:_SCL_SECURE_NO_WARNINGS 28 | msvc:_CRT_SECURE_NO_WARNINGS 29 | ../include 30 | ; 31 | 32 | exe convert_test_performance : performance.cpp /boost/timer//boost_timer /boost/chrono//boost_chrono 33 | : [ requires cxx17_hdr_charconv cxx17_structured_bindings cxx17_if_constexpr ] ; 34 | exe convert_test_performance_spirit : performance_spirit.cpp ; 35 | 36 | run callable.cpp : : : : convert_test_callable ; 37 | run fallbacks.cpp : : : : convert_test_fallbacks ; 38 | run spirit_converter.cpp : : : : convert_test_spirit_converter ; 39 | run strtol_converter.cpp : : : : convert_test_strtol_converter ; 40 | run lcast_converter.cpp : : : : convert_test_lcast_converter ; 41 | run encryption.cpp : : : : convert_test_encryption ; 42 | run user_type.cpp : : : : convert_test_user_type ; 43 | run str_to_int.cpp : : : : convert_test_str_to_int ; 44 | run sfinae.cpp : : : : convert_test_sfinae ; 45 | run has_member.cpp : : : : convert_test_has_member ; 46 | run printf_converter.cpp : 47 | /boost/test/included_unit_test_framework : : : convert_test_printf_converter ; 48 | run stream_converter.cpp : 49 | /boost/test/included_unit_test_framework : : : convert_test_stream_converter ; 50 | 51 | # these tests require C++17 52 | run charconv_converter.cpp 53 | : /boost/test//included_unit_test_framework 54 | : 55 | : [ requires cxx17_hdr_charconv cxx17_structured_bindings cxx17_if_constexpr ] 56 | gcc:"-O3 -std=c++17 -Wno-unused-variable -Wno-long-long" 57 | : convert_test_charconv_converter ; 58 | -------------------------------------------------------------------------------- /test/lcast_converter.cpp: -------------------------------------------------------------------------------- 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 13 | #include 14 | 15 | using std::string; 16 | using boost::convert; 17 | 18 | struct boost::cnv::by_default : boost::cnv::lexical_cast {}; 19 | 20 | static 21 | void 22 | test_invalid() 23 | { 24 | char const* str[] = { "not", "1 2", " 33", "44 ", "0x11", "7 + 5" }; 25 | int const size = sizeof(str) / sizeof(str[0]); 26 | 27 | for (int k = 0; k < size; ++k) 28 | { 29 | boost::optional const res = convert(str[k]); 30 | bool const failed = !res; 31 | 32 | if (!failed) 33 | { 34 | printf("test::cnv::invalid() failed for: <%s><%d>\n", str[k], res.value()); 35 | } 36 | BOOST_TEST(failed); 37 | } 38 | } 39 | 40 | static 41 | void 42 | test_dbl_to_str() 43 | { 44 | // printf("100.00 %s\n", convert( 99.999).value().c_str()); 45 | // printf( "99.95 %s\n", convert( 99.949).value().c_str()); 46 | // printf("-99.95 %s\n", convert(-99.949).value().c_str()); 47 | // printf( "99.9 %s\n", convert( 99.949).value().c_str()); 48 | // printf( "1.00 %s\n", convert( 0.999).value().c_str()); 49 | // printf( "-1.00 %s\n", convert( -0.999).value().c_str()); 50 | // printf( "0.95 %s\n", convert( 0.949).value().c_str()); 51 | // printf( "-0.95 %s\n", convert( -0.949).value().c_str()); 52 | // printf( "1.9 %s\n", convert( 1.949).value().c_str()); 53 | // printf( "-1.9 %s\n", convert( -1.949).value().c_str()); 54 | } 55 | 56 | int 57 | main(int, char const* []) 58 | { 59 | string const not_int_str = "not an int"; 60 | string const std_str = "-11"; 61 | char const* const c_str = "-12"; 62 | int const v00 = convert(not_int_str).value_or(-1); 63 | int const v01 = convert( std_str).value_or(-1); 64 | int const v02 = convert( c_str).value_or(-1); 65 | 66 | BOOST_TEST(v00 == -1); // Failed conversion. No throw 67 | BOOST_TEST(v01 == -11); 68 | BOOST_TEST(v02 == -12); 69 | 70 | test_invalid(); 71 | test_dbl_to_str(); 72 | 73 | return boost::report_errors(); 74 | } 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /test/performance_spirit.cpp: -------------------------------------------------------------------------------- 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 | // This code has been adapted from libs/spirit/optimization/qi/int_parser.cpp. 7 | // This code uses the performance testing framework from libs/spirit/optimization/measure.cpp. 8 | // See these mentioned files for the copyright notice. 9 | 10 | #include "./test.hpp" 11 | 12 | #if !defined(BOOST_CONVERT_CXX14) 13 | int main(int, char const* []) { return 0; } 14 | #else 15 | 16 | #include "./prepare.hpp" 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | #include 24 | 25 | namespace 26 | { 27 | namespace local 28 | { 29 | struct base : test::base 30 | { 31 | base() : strings_(local::get_strs()) {} 32 | 33 | // Test strings are created as part of the object, i.e. on the stack to make sure 34 | // they are easily accessed. 35 | local::strings strings_; 36 | }; 37 | } 38 | struct raw_lxcast_str_to_int_test : local::base 39 | { 40 | void benchmark() 41 | { 42 | for (size_t i = 0; i < strings_.size(); ++i) 43 | this->val += boost::lexical_cast(strings_[i].c_str()); 44 | } 45 | }; 46 | struct cnv_lxcast_str_to_int_test : local::base 47 | { 48 | void benchmark() 49 | { 50 | for (size_t i = 0; i < strings_.size(); ++i) 51 | this->val += boost::convert(strings_[i].c_str(), cnv).value(); 52 | } 53 | boost::cnv::lexical_cast cnv; 54 | }; 55 | struct raw_spirit_str_to_int_test : local::base 56 | { 57 | static int parse(char const* str) 58 | { 59 | char const* beg = str; 60 | char const* end = beg + strlen(str); 61 | int n; 62 | 63 | if (boost::spirit::qi::parse(beg, end, boost::spirit::qi::int_, n)) 64 | if (beg == end) 65 | return n; 66 | 67 | return (BOOST_ASSERT(0), 0); 68 | } 69 | void benchmark() 70 | { 71 | for (size_t i = 0; i < strings_.size(); ++i) 72 | this->val += parse(strings_[i].c_str()); 73 | } 74 | }; 75 | struct cnv_spirit_str_to_int_test : local::base 76 | { 77 | void benchmark() 78 | { 79 | for (size_t i = 0; i < strings_.size(); ++i) 80 | this->val += boost::convert(strings_[i].c_str(), cnv).value(); 81 | } 82 | boost::cnv::spirit cnv; 83 | }; 84 | } 85 | 86 | int 87 | main(int, char const* []) 88 | { 89 | // This code has been adapted from libs/spirit/optimization/qi/int_parser.cpp. 90 | // This code uses the performance testing framework from libs/spirit/optimization/measure.cpp. 91 | // See these mentioned files for the copyright notice. 92 | 93 | BOOST_SPIRIT_TEST_BENCHMARK( 94 | 10000000, // This is the maximum repetitions to execute 95 | (raw_lxcast_str_to_int_test) 96 | (cnv_lxcast_str_to_int_test) 97 | (raw_spirit_str_to_int_test) 98 | (cnv_spirit_str_to_int_test) 99 | ) 100 | 101 | // This is ultimately responsible for preventing all the test code 102 | // from being optimized away. Change this to return 0 and you 103 | // unplug the whole test's life support system. 104 | return test::live_code != 0; 105 | } 106 | 107 | #endif 108 | -------------------------------------------------------------------------------- /test/prepare.hpp: -------------------------------------------------------------------------------- 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 | #ifndef BOOST_CONVERT_TEST_PREPARE_HPP 7 | #define BOOST_CONVERT_TEST_PREPARE_HPP 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | // boostinspect:nounnamed 14 | namespace { namespace local 15 | { 16 | // C1. 18 = 9 positive + 9 negative numbers with the number of digits from 1 to 9. 17 | // Even though INT_MAX(32) = 2147483647, i.e. 10 digits (not to mention long int) 18 | // we only test up to 9 digits as Spirit does not handle more than 9. 19 | 20 | using strings = std::array; //C1 21 | 22 | // Generate a random number string with N digits 23 | std::string 24 | gen_int(int digits, bool negative) 25 | { 26 | std::string result; 27 | 28 | if (negative) // Prepend a '-' 29 | result += '-'; 30 | 31 | result += '1' + (std::rand() % 9); // The first digit cannot be '0' 32 | 33 | for (int i = 1; i < digits; ++i) // Generate the remaining digits 34 | result += '0' + (std::rand()%10); 35 | 36 | return result; 37 | } 38 | 39 | local::strings const& 40 | get_strs() 41 | { 42 | static auto strings = local::strings(); 43 | static bool filled = false; 44 | static bool negative = true; 45 | 46 | if (!filled) 47 | { 48 | // Seed the random generator 49 | std::srand(std::time(0)); 50 | 51 | for (size_t k = 0; k < strings.size(); ++k) 52 | strings[k] = local::gen_int(k/2 + 1, negative = !negative).c_str(); 53 | 54 | filled = true; 55 | } 56 | return strings; 57 | } 58 | }} 59 | 60 | #endif // BOOST_CONVERT_TEST_PREPARE_HPP 61 | -------------------------------------------------------------------------------- /test/printf_converter.cpp: -------------------------------------------------------------------------------- 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 13 | #include 14 | #include 15 | 16 | using std::string; 17 | using boost::convert; 18 | 19 | namespace cnv = boost::cnv; 20 | namespace arg = boost::cnv::parameter; 21 | 22 | static 23 | void 24 | test_notation() 25 | { 26 | //[printf_notation 27 | boost::cnv::printf cnv; 28 | 29 | BOOST_TEST( "-3.14159" == convert(-3.14159, cnv(arg::notation = cnv::notation::fixed)(arg::precision = 5)).value()); 30 | BOOST_TEST( "-3.142e+00" == convert(-3.14159, cnv(arg::notation = cnv::notation::scientific)(arg::precision = 3)).value()); 31 | BOOST_TEST("-0x1.9220p+1" == convert(-3.14159, cnv(arg::notation = cnv::notation::hex)(arg::precision = 4)).value()); 32 | 33 | const auto close = boost::math::fpc::close_at_tolerance(1); 34 | 35 | BOOST_TEST_WITH(-3.14159, convert("-3.14159", cnv(arg::notation = cnv::notation::fixed)).value(), close); 36 | BOOST_TEST_WITH(-3.14159, convert("-3.142e+00", cnv(arg::notation = cnv::notation::scientific)).value(), close); 37 | BOOST_TEST_WITH(-3.14159, convert("-0x1.9220p+1", cnv(arg::notation = cnv::notation::hex)).value(), close); 38 | //] 39 | } 40 | 41 | int 42 | main(int, char const* []) 43 | { 44 | boost::cnv::printf cnv; 45 | 46 | string const not_int_str = "not an int"; 47 | string const std_str = "-11"; 48 | char const* const c_str = "-12"; 49 | 50 | BOOST_TEST( -1 == convert(not_int_str, cnv).value_or(-1)); 51 | BOOST_TEST(-11 == convert(std_str, cnv).value_or(-1)); 52 | BOOST_TEST(-12 == convert(c_str, cnv).value_or(-1)); 53 | 54 | BOOST_TEST( float(3.14) == convert< float>("3.14", cnv(arg::precision = 2)).value_or(-1)); 55 | BOOST_TEST(double(3.14) == convert("3.14", cnv(arg::precision = 2)).value_or(-1)); 56 | 57 | BOOST_TEST("255" == convert(255, cnv(arg::base = boost::cnv::base::dec)).value()); 58 | BOOST_TEST( "ff" == convert(255, cnv(arg::base = boost::cnv::base::hex)).value()); 59 | BOOST_TEST("377" == convert(255, cnv(arg::base = boost::cnv::base::oct)).value()); 60 | 61 | string s01 = convert(12.3456, cnv(arg::precision = 6)).value(); 62 | string s02 = convert(12.3456, cnv(arg::precision = 3)).value(); 63 | 64 | BOOST_TEST(s01 == "12.345600"); 65 | BOOST_TEST(s02 == "12.346"); 66 | 67 | test_notation(); 68 | 69 | return boost::report_errors(); 70 | } 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /test/spirit_converter.cpp: -------------------------------------------------------------------------------- 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 13 | #include 14 | 15 | using std::string; 16 | using std::wstring; 17 | using boost::convert; 18 | 19 | namespace cnv = boost::cnv; 20 | namespace arg = boost::cnv::parameter; 21 | 22 | struct boost::cnv::by_default : boost::cnv::spirit {}; 23 | 24 | int 25 | main(int, char const* []) 26 | { 27 | char const* const c_stri ("12345"); 28 | char const* const c_strd ("123.45"); 29 | wchar_t const* const c_wstri (L"12345"); 30 | wchar_t const* const c_wstrd (L"123.45"); 31 | std::string const std_stri (c_stri); 32 | std::string const std_strd (c_strd); 33 | std::wstring const std_wstri (c_wstri); 34 | std::wstring const std_wstrd (c_wstrd); 35 | my_string const my_stri (c_stri, c_stri + strlen(c_stri)); 36 | my_string const my_strd (c_strd, c_strd + strlen(c_strd)); 37 | 38 | boost::cnv::spirit cnv; 39 | 40 | BOOST_TEST( 12345 == convert< int>( c_stri).value()); 41 | BOOST_TEST( 12345 == convert< int>( c_wstri).value()); 42 | BOOST_TEST( 12345 == convert< int>( std_stri).value()); 43 | BOOST_TEST( 12345 == convert< int>(std_wstri).value()); 44 | BOOST_TEST( 12345 == convert< int>( my_stri).value()); 45 | BOOST_TEST( 12345 == convert(c_stri).value()); 46 | BOOST_TEST( 12345 == convert( c_stri).value()); 47 | BOOST_TEST( 12345 == convert( c_wstri).value()); 48 | BOOST_TEST( 12345 == convert( std_stri).value()); 49 | BOOST_TEST( 12345 == convert(std_wstri).value()); 50 | BOOST_TEST( 12345 == convert( my_stri).value()); 51 | BOOST_TEST( 12345 == convert(c_stri).value()); 52 | BOOST_TEST( 12345 == convert(c_stri).value()); 53 | BOOST_TEST( 12345 == convert(c_stri).value()); 54 | BOOST_TEST(123.45 == convert< double>( c_strd).value()); 55 | BOOST_TEST(123.45 == convert< double>( c_wstrd).value()); 56 | // BOOST_TEST(123.45 == convert< double>( std_strd).value()); 57 | // BOOST_TEST(123.45 == convert< double>(std_wstrd).value()); 58 | BOOST_TEST(123.45 == convert< double>( my_strd).value()); 59 | 60 | BOOST_TEST(!convert< int>("uhm")); 61 | BOOST_TEST(!convert< int>(L"uhm")); 62 | BOOST_TEST(!convert("12.uhm")); 63 | BOOST_TEST(!convert("L12.uhm")); 64 | 65 | BOOST_TEST( "1234" == convert(1234).value()); 66 | BOOST_TEST( "1234" == convert(1234u).value()); 67 | BOOST_TEST( "1234" == convert(1234ll).value()); 68 | BOOST_TEST( "1234" == convert(1234ull).value()); 69 | BOOST_TEST( L"1234" == convert(1234).value()); 70 | BOOST_TEST( "12xxx" == convert(12, cnv(arg::width = 5) 71 | (arg::fill = 'x') 72 | (arg::adjust = cnv::adjust::left)).value()); 73 | BOOST_TEST(L"12xxx" == convert(12, cnv(arg::width = 5) 74 | (arg::fill = 'x') 75 | (arg::adjust = cnv::adjust::left)).value()); 76 | BOOST_TEST( "x12xx" == convert(12, cnv(arg::adjust = cnv::adjust::center)).value()); 77 | BOOST_TEST(L"x12xx" == convert(12, cnv(arg::adjust = cnv::adjust::center)).value()); 78 | 79 | // BOOST_TEST("12.34" == convert(12.34).value()); 80 | // printf("%s\n", convert(12.34).value().c_str()); 81 | 82 | return boost::report_errors(); 83 | } 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /test/user_type.cpp: -------------------------------------------------------------------------------- 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 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | using std::string; 19 | using std::wstring; 20 | 21 | static 22 | void 23 | test_user_type() 24 | { 25 | boost::cnv::cstream cnv; // stringstream-based char converter 26 | 27 | direction const up_dir1 = direction::up; 28 | direction const dn_dir1 = direction::dn; 29 | // string const up_dir0_str = boost::convert(direction::up, cnv).value(); 30 | // string const dn_dir0_str = boost::convert(direction::dn, cnv).value(); 31 | string const up_dir1_str = boost::convert(up_dir1, cnv).value(); 32 | string const dn_dir1_str = boost::convert(dn_dir1, cnv).value(); 33 | direction const up_dir2 = boost::convert(up_dir1_str, cnv).value(); 34 | direction const dn_dir2 = boost::convert(dn_dir1_str, cnv).value(); 35 | direction const up_dir3 = boost::convert(up_dir1_str, cnv).value(); 36 | direction const dn_dir3 = boost::convert(dn_dir1_str, cnv).value(); 37 | direction const dn_dir4 = boost::convert("junk", cnv).value_or(direction::dn); 38 | boost::optional up_dir4 = boost::convert("junk", cnv); 39 | 40 | // BOOST_TEST(up_dir0_str == "up"); 41 | // BOOST_TEST(dn_dir0_str == "dn"); 42 | BOOST_TEST(up_dir1_str == "up"); 43 | BOOST_TEST(dn_dir1_str == "dn"); 44 | BOOST_TEST(up_dir2 == up_dir1); 45 | BOOST_TEST(dn_dir2 == dn_dir1); 46 | BOOST_TEST(up_dir3 == direction::up); 47 | BOOST_TEST(dn_dir3 == direction::dn); 48 | BOOST_TEST(dn_dir4 == direction::dn); 49 | BOOST_TEST(!up_dir4); // Failed conversion 50 | } 51 | 52 | static 53 | void 54 | test_algorithms() 55 | { 56 | //[algorithm_example6 57 | std::array chgs1 = {{ change::no, change::up, change::dn }}; 58 | std::array chgs2 = {{ change::no, change::up, change::dn }}; 59 | 60 | auto strs1 = std::vector(); 61 | auto strs2 = std::vector(); 62 | auto strs3 = std::vector(); 63 | auto cnv = boost::cnv::cstream(); 64 | 65 | std::transform(chgs1.begin(), chgs1.end(), std::back_inserter(strs1), 66 | boost::cnv::apply(std::cref(cnv))); // Deduced TypeIn is 'change' 67 | 68 | std::transform(chgs2.begin(), chgs2.end(), std::back_inserter(strs2), 69 | boost::cnv::apply(std::cref(cnv))); // Deduced TypeIn is 'change::value_type' 70 | 71 | BOOST_TEST(strs1.size() == 3); 72 | BOOST_TEST(strs1[0] == "no"); 73 | BOOST_TEST(strs1[1] == "up"); 74 | BOOST_TEST(strs1[2] == "dn"); 75 | 76 | BOOST_TEST(strs2.size() == 3); 77 | BOOST_TEST(strs2[0] == "0"); 78 | BOOST_TEST(strs2[1] == "1"); 79 | BOOST_TEST(strs2[2] == "2"); 80 | //] 81 | //[algorithm_example7 82 | 83 | std::transform(chgs2.begin(), chgs2.end(), std::back_inserter(strs3), 84 | boost::cnv::apply(std::cref(cnv))); 85 | 86 | BOOST_TEST(strs3.size() == 3); 87 | BOOST_TEST(strs3[0] == "no"); 88 | BOOST_TEST(strs3[1] == "up"); 89 | BOOST_TEST(strs3[2] == "dn"); 90 | //] 91 | } 92 | 93 | int 94 | main(int, char const* []) 95 | { 96 | test_user_type(); 97 | test_algorithms(); 98 | 99 | return boost::report_errors(); 100 | } 101 | 102 | #endif 103 | -------------------------------------------------------------------------------- /todo.txt: -------------------------------------------------------------------------------- 1 | boost-no-inspect 2 | 3 | * Adding Doxygen comments to describe briefly the files, functions etc (so users can find which include files may be needed?) 4 | * I don't understand the timing figures given in Performance section. Some items refer to MSVC express 10, other detailed tables in Boost 1.55 to 11? No Clang results? 5 | 6 | * You are not using links to take from the text to the appropriate functions etc 7 | in the reference section. Users will find this helpful too. 8 | 9 | * The reference section could be much improved by adding brief Doxygen comments to 10 | the files, functions etc. 11 | 12 | 13 | --------------------------------------------------------------------------------