├── .gitattributes ├── .github └── workflows │ └── ci.yml ├── CMakeLists.txt ├── README.md ├── build.jam ├── doc ├── Jamfile.v2 └── lexical_cast.qbk ├── example ├── args_to_numbers.cpp ├── generic_stringize.cpp ├── small_examples.cpp └── variant_to_long_double.cpp ├── include └── boost │ ├── detail │ ├── basic_pointerbuf.hpp │ └── lcast_precision.hpp │ ├── lexical_cast.hpp │ └── lexical_cast │ ├── bad_lexical_cast.hpp │ ├── detail │ ├── buffer_view.hpp │ ├── converter_lexical.hpp │ ├── converter_lexical_streams.hpp │ ├── converter_numeric.hpp │ ├── inf_nan.hpp │ ├── is_character.hpp │ ├── lcast_basic_unlockedbuf.hpp │ ├── lcast_char_constants.hpp │ ├── lcast_unsigned_converters.hpp │ └── widest_char.hpp │ └── try_lexical_convert.hpp ├── index.html ├── meta └── libraries.json ├── perf ├── Jamfile.v2 └── performance_test.cpp └── test ├── Jamfile.v2 ├── abstract_test.cpp ├── appveyor.yml ├── arrays_test.cpp ├── containers_test.cpp ├── empty_input_test.cpp ├── escape_struct.hpp ├── filesystem_test.cpp ├── float_types_test.cpp ├── from_volatile.cpp ├── implicit_convert.cpp ├── inf_nan_test.cpp ├── integral_types_test.cpp ├── iterator_range_test.cpp ├── lexical_cast_old.hpp ├── lexical_cast_test.cpp ├── loopback_test.cpp ├── no_exceptions_test.cpp ├── no_locale_test.cpp ├── noncopyable_test.cpp ├── pointers_test.cpp ├── stream_detection_test.cpp ├── stream_traits_test.cpp ├── string_view_test.cpp ├── to_pointer_test.cpp ├── try_lexical_convert.cpp ├── typedefed_wchar_test.cpp ├── typedefed_wchar_test_runtime.cpp ├── vc8_bug_test.cpp └── wchars_test.cpp /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto !eol svneol=native#text/plain 2 | *.gitattributes text svneol=native#text/plain 3 | 4 | # Scriptish formats 5 | *.bat text svneol=native#text/plain 6 | *.bsh text svneol=native#text/x-beanshell 7 | *.cgi text svneol=native#text/plain 8 | *.cmd text svneol=native#text/plain 9 | *.js text svneol=native#text/javascript 10 | *.php text svneol=native#text/x-php 11 | *.pl text svneol=native#text/x-perl 12 | *.pm text svneol=native#text/x-perl 13 | *.py text svneol=native#text/x-python 14 | *.sh eol=lf svneol=LF#text/x-sh 15 | configure eol=lf svneol=LF#text/x-sh 16 | 17 | # Image formats 18 | *.bmp binary svneol=unset#image/bmp 19 | *.gif binary svneol=unset#image/gif 20 | *.ico binary svneol=unset#image/ico 21 | *.jpeg binary svneol=unset#image/jpeg 22 | *.jpg binary svneol=unset#image/jpeg 23 | *.png binary svneol=unset#image/png 24 | *.tif binary svneol=unset#image/tiff 25 | *.tiff binary svneol=unset#image/tiff 26 | *.svg text svneol=native#image/svg%2Bxml 27 | 28 | # Data formats 29 | *.pdf binary svneol=unset#application/pdf 30 | *.avi binary svneol=unset#video/avi 31 | *.doc binary svneol=unset#application/msword 32 | *.dsp text svneol=crlf#text/plain 33 | *.dsw text svneol=crlf#text/plain 34 | *.eps binary svneol=unset#application/postscript 35 | *.gz binary svneol=unset#application/gzip 36 | *.mov binary svneol=unset#video/quicktime 37 | *.mp3 binary svneol=unset#audio/mpeg 38 | *.ppt binary svneol=unset#application/vnd.ms-powerpoint 39 | *.ps binary svneol=unset#application/postscript 40 | *.psd binary svneol=unset#application/photoshop 41 | *.rdf binary svneol=unset#text/rdf 42 | *.rss text svneol=unset#text/xml 43 | *.rtf binary svneol=unset#text/rtf 44 | *.sln text svneol=native#text/plain 45 | *.swf binary svneol=unset#application/x-shockwave-flash 46 | *.tgz binary svneol=unset#application/gzip 47 | *.vcproj text svneol=native#text/xml 48 | *.vcxproj text svneol=native#text/xml 49 | *.vsprops text svneol=native#text/xml 50 | *.wav binary svneol=unset#audio/wav 51 | *.xls binary svneol=unset#application/vnd.ms-excel 52 | *.zip binary svneol=unset#application/zip 53 | 54 | # Text formats 55 | .htaccess text svneol=native#text/plain 56 | *.bbk text svneol=native#text/xml 57 | *.cmake text svneol=native#text/plain 58 | *.css text svneol=native#text/css 59 | *.dtd text svneol=native#text/xml 60 | *.htm text svneol=native#text/html 61 | *.html text svneol=native#text/html 62 | *.ini text svneol=native#text/plain 63 | *.log text svneol=native#text/plain 64 | *.mak text svneol=native#text/plain 65 | *.qbk text svneol=native#text/plain 66 | *.rst text svneol=native#text/plain 67 | *.sql text svneol=native#text/x-sql 68 | *.txt text svneol=native#text/plain 69 | *.xhtml text svneol=native#text/xhtml%2Bxml 70 | *.xml text svneol=native#text/xml 71 | *.xsd text svneol=native#text/xml 72 | *.xsl text svneol=native#text/xml 73 | *.xslt text svneol=native#text/xml 74 | *.xul text svneol=native#text/xul 75 | *.yml text svneol=native#text/plain 76 | boost-no-inspect text svneol=native#text/plain 77 | CHANGES text svneol=native#text/plain 78 | COPYING text svneol=native#text/plain 79 | INSTALL text svneol=native#text/plain 80 | Jamfile text svneol=native#text/plain 81 | Jamroot text svneol=native#text/plain 82 | Jamfile.v2 text svneol=native#text/plain 83 | Jamrules text svneol=native#text/plain 84 | Makefile* text svneol=native#text/plain 85 | README text svneol=native#text/plain 86 | TODO text svneol=native#text/plain 87 | 88 | # Code formats 89 | *.c text svneol=native#text/plain 90 | *.cpp text svneol=native#text/plain 91 | *.h text svneol=native#text/plain 92 | *.hpp text svneol=native#text/plain 93 | *.ipp text svneol=native#text/plain 94 | *.tpp text svneol=native#text/plain 95 | *.jam text svneol=native#text/plain 96 | *.java text svneol=native#text/plain 97 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: 7 | - master 8 | - develop 9 | - feature/** 10 | 11 | env: 12 | UBSAN_OPTIONS: print_stacktrace=1 13 | 14 | jobs: 15 | posix: 16 | strategy: 17 | fail-fast: false 18 | matrix: 19 | include: 20 | - toolset: gcc-12 21 | cxxstd: "03,11,14,17,2a" 22 | os: ubuntu-22.04 23 | cxxflags: "cxxflags=--coverage -fsanitize=address,leak,undefined -fno-sanitize-recover=undefined" 24 | linkflags: "linkflags=--coverage -lasan -lubsan" 25 | gcov_tool: "gcov-12" 26 | launcher: "testing.launcher=LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libasan.so.8" 27 | - toolset: gcc-9 28 | cxxstd: "03,11,14,17,2a" 29 | os: ubuntu-22.04 30 | - toolset: clang 31 | compiler: clang++-14 32 | cxxstd: "03,11,14,17,2a" 33 | os: ubuntu-22.04 34 | - toolset: clang 35 | cxxstd: "11,14,17,20" 36 | os: macos-13 37 | 38 | runs-on: ${{matrix.os}} 39 | 40 | steps: 41 | - uses: actions/checkout@v2 42 | 43 | - name: Install packages 44 | if: matrix.install 45 | run: sudo apt install ${{matrix.install}} 46 | 47 | - name: Setup Boost 48 | run: | 49 | echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY 50 | LIBRARY=${GITHUB_REPOSITORY#*/} 51 | echo LIBRARY: $LIBRARY 52 | echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV 53 | echo GITHUB_BASE_REF: $GITHUB_BASE_REF 54 | echo GITHUB_REF: $GITHUB_REF 55 | REF=${GITHUB_BASE_REF:-$GITHUB_REF} 56 | REF=${REF#refs/heads/} 57 | echo REF: $REF 58 | BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true 59 | echo BOOST_BRANCH: $BOOST_BRANCH 60 | cd .. 61 | git clone -b $BOOST_BRANCH --depth 10 https://github.com/boostorg/boost.git boost-root 62 | cd boost-root 63 | git submodule update --init --depth 10 --jobs 2 tools/boostdep tools/inspect libs/filesystem 64 | python tools/boostdep/depinst/depinst.py --git_args "--depth 10 --jobs 3" filesystem 65 | rm -rf libs/$LIBRARY/* 66 | cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY 67 | python tools/boostdep/depinst/depinst.py --include benchmark --include example --include examples --include tools --git_args "--depth 10 --jobs 3" $LIBRARY 68 | ./bootstrap.sh 69 | ./b2 -d0 headers 70 | ./b2 -j4 variant=debug tools/inspect 71 | 72 | - name: Run tests 73 | run: | 74 | cd ../boost-root 75 | ./b2 -j3 libs/$LIBRARY/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} variant=debug,release "${{matrix.cxxflags}}" "${{matrix.linkflags}}" "${{matrix.launcher}}" 76 | dist/bin/inspect libs/$LIBRARY 77 | 78 | - name: Prepare coverage data 79 | if: matrix.gcov_tool 80 | run: | 81 | mkdir -p $GITHUB_WORKSPACE/coveralls 82 | 83 | echo -e "#!/bin/bash\nexec ${{matrix.gcov_tool}} \"\$@\"" > $GITHUB_WORKSPACE/coveralls/gcov_wrapper.sh 84 | chmod +x $GITHUB_WORKSPACE/coveralls/gcov_wrapper.sh 85 | wget https://github.com/linux-test-project/lcov/archive/v1.16.zip 86 | unzip v1.16.zip 87 | LCOV="`pwd`/lcov-1.16/bin/lcov --gcov-tool $GITHUB_WORKSPACE/coveralls/gcov_wrapper.sh" 88 | 89 | echo "$LCOV --directory ../boost-root/bin.v2/libs/$LIBRARY/ --base-directory `pwd`/libs/$LIBRARY/test --capture --output-file $GITHUB_WORKSPACE/coveralls/coverage.info" 90 | $LCOV --directory ../boost-root/bin.v2/libs/$LIBRARY/ --base-directory ../boost-root/ --capture --output-file $GITHUB_WORKSPACE/coveralls/coverage.info 91 | $LCOV --remove $GITHUB_WORKSPACE/coveralls/coverage.info "/usr*" "*/$LIBRARY/test/*" ${{matrix.ignore_coverage}} "*/$LIBRARY/tests/*" "*/$LIBRARY/examples/*" "*/$LIBRARY/example/*" -o $GITHUB_WORKSPACE/coveralls/coverage.info 92 | 93 | cd ../boost-root 94 | OTHER_LIBS=`grep "submodule .*" .gitmodules | sed 's/\[submodule\ "\(.*\)"\]/"\*\/boost\/\1\.hpp" "\*\/boost\/\1\/\*"/g'| sed "/\"\*\/boost\/$LIBRARY\/\*\"/d" | sed ':a;N;$!ba;s/\n/ /g'` 95 | echo $OTHER_LIBS 96 | eval "$LCOV --remove $GITHUB_WORKSPACE/coveralls/coverage.info $OTHER_LIBS -o $GITHUB_WORKSPACE/coveralls/coverage.info" 97 | 98 | - name: Coveralls 99 | uses: coverallsapp/github-action@master 100 | if: matrix.gcov_tool 101 | with: 102 | github-token: ${{ secrets.GITHUB_TOKEN }} 103 | path-to-lcov: ./coveralls/coverage.info 104 | parallel: true 105 | 106 | windows: 107 | strategy: 108 | fail-fast: false 109 | matrix: 110 | include: 111 | - toolset: msvc 112 | cxxstd: "14,17,latest" 113 | addrmd: 32,64 114 | os: windows-2022 115 | - toolset: msvc-14.2 116 | cxxstd: "14,17,latest" 117 | addrmd: 32,64 118 | os: windows-2019 119 | - toolset: gcc 120 | cxxstd: "03,11,14,17,2a" 121 | addrmd: 64 122 | os: windows-2019 123 | 124 | runs-on: ${{matrix.os}} 125 | 126 | steps: 127 | - uses: actions/checkout@v2 128 | 129 | - name: Setup Boost 130 | shell: cmd 131 | run: | 132 | echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY% 133 | for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi 134 | echo LIBRARY: %LIBRARY% 135 | echo LIBRARY=%LIBRARY%>>%GITHUB_ENV% 136 | echo GITHUB_BASE_REF: %GITHUB_BASE_REF% 137 | echo GITHUB_REF: %GITHUB_REF% 138 | if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF% 139 | set BOOST_BRANCH=develop 140 | for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master 141 | echo BOOST_BRANCH: %BOOST_BRANCH% 142 | cd .. 143 | git clone -b %BOOST_BRANCH% --depth 10 https://github.com/boostorg/boost.git boost-root 144 | cd boost-root 145 | xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\ 146 | git submodule update --init tools/boostdep 147 | python tools/boostdep/depinst/depinst.py --include benchmark --include example --include examples --include tools --git_args "--jobs 3" %LIBRARY% 148 | cmd /c bootstrap 149 | b2 -d0 headers 150 | 151 | - name: Run tests 152 | shell: cmd 153 | run: | 154 | cd ../boost-root 155 | b2 -j3 libs/%LIBRARY%/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release 156 | 157 | finish: 158 | if: false 159 | needs: posix 160 | runs-on: ubuntu-latest 161 | steps: 162 | - name: Coveralls Finished 163 | uses: coverallsapp/github-action@master 164 | with: 165 | github-token: ${{ secrets.github_token }} 166 | parallel-finished: true 167 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Generated by `boostdep --cmake lexical_cast` 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_lexical_cast VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX) 9 | 10 | add_library(boost_lexical_cast INTERFACE) 11 | add_library(Boost::lexical_cast ALIAS boost_lexical_cast) 12 | 13 | target_include_directories(boost_lexical_cast INTERFACE include) 14 | 15 | target_link_libraries(boost_lexical_cast 16 | INTERFACE 17 | Boost::config 18 | Boost::container 19 | Boost::core 20 | Boost::throw_exception 21 | Boost::type_traits 22 | ) 23 | 24 | if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt") 25 | 26 | add_subdirectory(test) 27 | 28 | endif() 29 | 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [Boost.LexicalCast](https://boost.org/libs/lexical_cast) 2 | Boost.LexicalCast is one of the [Boost C++ Libraries](https://github.com/boostorg). This library is meant for general literal text conversions, such as an int represented a string, or vice-versa. 3 | 4 | ### Test results 5 | 6 | @ | Build | Tests coverage | More info 7 | ----------------|-------------- | -------------- |----------- 8 | Develop branch: | [![CI](https://github.com/boostorg/lexical_cast/actions/workflows/ci.yml/badge.svg?branch=develop)](https://github.com/boostorg/lexical_cast/actions/workflows/ci.yml) [![Build status](https://ci.appveyor.com/api/projects/status/mwwanh1bpsnuv38h/branch/develop?svg=true)](https://ci.appveyor.com/project/apolukhin/lexical-cast/branch/develop) | [![Coverage Status](https://coveralls.io/repos/boostorg/lexical_cast/badge.png?branch=develop)](https://coveralls.io/r/boostorg/lexical_cast?branch=develop) | [details...](https://www.boost.org/development/tests/develop/developer/lexical_cast.html) 9 | Master branch: | [![CI](https://github.com/boostorg/lexical_cast/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/boostorg/lexical_cast/actions/workflows/ci.yml) [![Build status](https://ci.appveyor.com/api/projects/status/mwwanh1bpsnuv38h/branch/master?svg=true)](https://ci.appveyor.com/project/apolukhin/lexical-cast/branch/master) | [![Coverage Status](https://coveralls.io/repos/boostorg/lexical_cast/badge.png?branch=master)](https://coveralls.io/r/boostorg/lexical_cast?branch=master) | [details...](https://www.boost.org/development/tests/master/developer/lexical_cast.html) 10 | 11 | [Latest developer documentation](https://www.boost.org/doc/libs/develop/doc/html/boost_lexical_cast.html) 12 | 13 | ### License 14 | 15 | Distributed under the [Boost Software License, Version 1.0](https://boost.org/LICENSE_1_0.txt). 16 | -------------------------------------------------------------------------------- /build.jam: -------------------------------------------------------------------------------- 1 | # Copyright René Ferdinand Rivera Morell 2023-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/container//boost_container 11 | /boost/core//boost_core 12 | /boost/throw_exception//boost_throw_exception 13 | /boost/type_traits//boost_type_traits ; 14 | 15 | project /boost/lexical_cast 16 | : common-requirements 17 | include 18 | ; 19 | 20 | explicit 21 | [ alias boost_lexical_cast : : : : $(boost_dependencies) ] 22 | [ alias all : boost_lexical_cast test ] 23 | ; 24 | 25 | call-if : boost-library lexical_cast 26 | ; 27 | 28 | -------------------------------------------------------------------------------- /doc/Jamfile.v2: -------------------------------------------------------------------------------- 1 | # Copyright Antony Polukhin, 2011-2025. 2 | # 3 | # Use, modification, and distribution are 4 | # subject to the Boost Software License, Version 1.0. (See accompanying 5 | # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | 7 | using quickbook ; 8 | import boostbook : boostbook ; 9 | 10 | xml lexical_cast : lexical_cast.qbk ; 11 | boostbook standalone 12 | : 13 | lexical_cast 14 | : 15 | boost.root=../../../.. 16 | pdf:boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html 17 | ; 18 | 19 | ############################################################################### 20 | alias boostdoc 21 | : lexical_cast 22 | : 23 | : 24 | : ; 25 | explicit boostdoc ; 26 | alias boostrelease ; 27 | explicit boostrelease ; 28 | -------------------------------------------------------------------------------- /example/args_to_numbers.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Antony Polukhin, 2013-2025. 2 | 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // (See the accompanying file LICENSE_1_0.txt 5 | // or a copy at .) 6 | 7 | //[lexical_cast_args_example 8 | //`The following example treats command line arguments as a sequence of numeric data 9 | 10 | #include 11 | #include 12 | 13 | int main(int /*argc*/, char * argv[]) 14 | { 15 | using boost::lexical_cast; 16 | using boost::bad_lexical_cast; 17 | 18 | std::vector args; 19 | 20 | while (*++argv) 21 | { 22 | try 23 | { 24 | args.push_back(lexical_cast(*argv)); 25 | } 26 | catch(const bad_lexical_cast &) 27 | { 28 | args.push_back(0); 29 | } 30 | } 31 | 32 | // ... 33 | } 34 | 35 | //] [/lexical_cast_args_example] 36 | -------------------------------------------------------------------------------- /example/generic_stringize.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Antony Polukhin, 2013-2025. 2 | 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // (See the accompanying file LICENSE_1_0.txt 5 | // or a copy at .) 6 | 7 | #include 8 | #ifdef BOOST_MSVC 9 | # pragma warning(disable: 4512) // generic_stringize.cpp(37) : warning C4512: 'stringize_functor' : assignment operator could not be generated 10 | #endif 11 | 12 | //[lexical_cast_stringize 13 | /*` 14 | In this example we'll make a `stringize` method that accepts a sequence, converts 15 | each element of the sequence into string and appends that string to the result. 16 | 17 | Example is based on the example from the [@http://www.packtpub.com/boost-cplusplus-application-development-cookbook/book Boost C++ Application Development Cookbook] 18 | by Antony Polukhin, ISBN 9781849514880. Russian translation: [@https://dmkpress.com/catalog/computer/programming/c/978-5-97060-868-5/ ISBN: 9785970608685]. 19 | 20 | Step 1: Making a functor that converts any type to a string and remembers result: 21 | */ 22 | 23 | #include 24 | 25 | struct stringize_functor { 26 | private: 27 | std::string& result; 28 | 29 | public: 30 | explicit stringize_functor(std::string& res) 31 | : result(res) 32 | {} 33 | 34 | template 35 | void operator()(const T& v) const { 36 | result += boost::lexical_cast(v); 37 | } 38 | }; 39 | 40 | //` Step 2: Applying `stringize_functor` to each element in sequence: 41 | #include 42 | template 43 | std::string stringize(const Sequence& seq) { 44 | std::string result; 45 | boost::fusion::for_each(seq, stringize_functor(result)); 46 | return result; 47 | } 48 | 49 | //` Step 3: Using the `stringize` with different types: 50 | #include 51 | #include 52 | 53 | int main() { 54 | std::tuple decim('-', 10, 'e', 5); 55 | if (stringize(decim) != "-10e5") { 56 | return 1; 57 | } 58 | 59 | std::pair value_and_type(270, "Kelvin"); 60 | if (stringize(value_and_type) != "270Kelvin") { 61 | return 2; 62 | } 63 | 64 | return 0; 65 | } 66 | 67 | //] [/lexical_cast_stringize] 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /example/small_examples.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Antony Polukhin, 2013-2025. 2 | 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // (See the accompanying file LICENSE_1_0.txt 5 | // or a copy at .) 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #ifdef BOOST_MSVC 14 | # pragma warning(disable: 4996) // `strerror` is not safe 15 | #endif 16 | 17 | //[lexical_cast_log_errno 18 | //`The following example uses numeric data in a string expression: 19 | 20 | void log_message(const std::string &); 21 | 22 | void log_errno(int yoko) 23 | { 24 | log_message("Error " + boost::lexical_cast(yoko) + ": " + strerror(yoko)); 25 | } 26 | 27 | //] [/lexical_cast_log_errno] 28 | 29 | 30 | //[lexical_cast_fixed_buffer 31 | //`The following example converts some number and puts it to file: 32 | 33 | void number_to_file(int number, std::FILE* file) 34 | { 35 | using buf_t = std::array; 36 | buf_t buffer = boost::lexical_cast(number); // No dynamic memory allocation 37 | std::fputs(buffer.data(), file); 38 | } 39 | 40 | //] [/lexical_cast_fixed_buffer] 41 | 42 | //[lexical_cast_substring_conversion 43 | //`The following example takes part of the string and converts it to `int`: 44 | 45 | int convert_strings_part(const std::string& s, std::size_t pos, std::size_t n) 46 | { 47 | return boost::lexical_cast(s.data() + pos, n); 48 | } 49 | 50 | //] [/lexical_cast_substring_conversion] 51 | 52 | void log_message(const std::string &) {} 53 | 54 | int main() 55 | { 56 | return 0; 57 | } 58 | 59 | -------------------------------------------------------------------------------- /example/variant_to_long_double.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Antony Polukhin, 2013-2025. 2 | 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // (See the accompanying file LICENSE_1_0.txt 5 | // or a copy at .) 6 | 7 | 8 | //[lexical_cast_variant_to_long_double 9 | /*` 10 | In this example we'll make a `to_long_double` method that converts value of the Boost.Variant to `long double`. 11 | */ 12 | 13 | #include 14 | #include 15 | 16 | struct to_long_double_functor: boost::static_visitor { 17 | template 18 | long double operator()(const T& v) const { 19 | // Lexical cast has many optimizations including optimizations for situations that usually 20 | // occur in generic programming, like std::string to std::string or arithmetic type to arithmetic type conversion. 21 | return boost::lexical_cast(v); 22 | } 23 | }; 24 | 25 | // Throws `boost::bad_lexical_cast` if value of the variant is not convertible to `long double` 26 | template 27 | long double to_long_double(const Variant& v) { 28 | return boost::apply_visitor(to_long_double_functor(), v); 29 | } 30 | 31 | int main() { 32 | boost::variant v1('0'), v2("10.0001"), v3(1); 33 | 34 | const long double sum = to_long_double(v1) + to_long_double(v2) + to_long_double(v3); 35 | if (11 < sum && sum < 11.1) { 36 | return 0; // OK, as expected 37 | }; 38 | 39 | return 1; // FAIL 40 | } 41 | 42 | //] [/lexical_cast_variant_to_long_double] 43 | -------------------------------------------------------------------------------- /include/boost/detail/basic_pointerbuf.hpp: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // boost detail/templated_streams.hpp header file 3 | // See http://www.boost.org for updates, documentation, and revision history. 4 | //----------------------------------------------------------------------------- 5 | // 6 | // Copyright (c) 2013 John Maddock, Antony Polukhin 7 | // 8 | // 9 | // Distributed under the Boost Software License, Version 1.0. (See 10 | // accompanying file LICENSE_1_0.txt or copy at 11 | // http://www.boost.org/LICENSE_1_0.txt) 12 | 13 | #ifndef BOOST_DETAIL_BASIC_POINTERBUF_HPP 14 | #define BOOST_DETAIL_BASIC_POINTERBUF_HPP 15 | 16 | // MS compatible compilers support #pragma once 17 | #if defined(_MSC_VER) 18 | # pragma once 19 | #endif 20 | 21 | #include 22 | 23 | #include 24 | 25 | namespace boost { namespace detail { 26 | 27 | // 28 | // class basic_pointerbuf: 29 | // acts as a stream buffer which wraps around a pair of pointers: 30 | // 31 | template 32 | class basic_pointerbuf : public BufferT { 33 | protected: 34 | typedef BufferT base_type; 35 | typedef basic_pointerbuf this_type; 36 | typedef typename base_type::int_type int_type; 37 | typedef typename base_type::char_type char_type; 38 | typedef typename base_type::pos_type pos_type; 39 | typedef ::std::streamsize streamsize; 40 | typedef typename base_type::off_type off_type; 41 | 42 | public: 43 | basic_pointerbuf() : base_type() { this_type::setbuf(0, 0); } 44 | const charT* getnext() { return this->gptr(); } 45 | 46 | using base_type::pptr; 47 | using base_type::pbase; 48 | 49 | protected: 50 | // VC mistakenly assumes that `setbuf` and other functions are not referenced. 51 | // Marking those functions with `inline` suppresses the warnings. 52 | // There must be no harm from marking virtual functions as inline: inline virtual 53 | // call can be inlined ONLY when the compiler knows the "exact class". 54 | inline base_type* setbuf(char_type* s, streamsize n) BOOST_OVERRIDE; 55 | inline typename this_type::pos_type seekpos(pos_type sp, ::std::ios_base::openmode which) BOOST_OVERRIDE; 56 | inline typename this_type::pos_type seekoff(off_type off, ::std::ios_base::seekdir way, ::std::ios_base::openmode which) BOOST_OVERRIDE; 57 | 58 | private: 59 | basic_pointerbuf& operator=(const basic_pointerbuf&); 60 | basic_pointerbuf(const basic_pointerbuf&); 61 | }; 62 | 63 | template 64 | BufferT* 65 | basic_pointerbuf::setbuf(char_type* s, streamsize n) 66 | { 67 | this->setg(s, s, s + n); 68 | return this; 69 | } 70 | 71 | template 72 | typename basic_pointerbuf::pos_type 73 | basic_pointerbuf::seekoff(off_type off, ::std::ios_base::seekdir way, ::std::ios_base::openmode which) 74 | { 75 | typedef ::std::ios_base::seekdir cast_type; 76 | 77 | if(which & ::std::ios_base::out) 78 | return pos_type(off_type(-1)); 79 | std::ptrdiff_t size = this->egptr() - this->eback(); 80 | std::ptrdiff_t pos = this->gptr() - this->eback(); 81 | charT* g = this->eback(); 82 | switch(static_cast(way)) 83 | { 84 | case ::std::ios_base::beg: 85 | if((off < 0) || (off > size)) 86 | return pos_type(off_type(-1)); 87 | else 88 | this->setg(g, g + off, g + size); 89 | break; 90 | case ::std::ios_base::end: 91 | if((off < 0) || (off > size)) 92 | return pos_type(off_type(-1)); 93 | else 94 | this->setg(g, g + size - off, g + size); 95 | break; 96 | case ::std::ios_base::cur: 97 | { 98 | std::ptrdiff_t newpos = static_cast(pos + off); 99 | if((newpos < 0) || (newpos > size)) 100 | return pos_type(off_type(-1)); 101 | else 102 | this->setg(g, g + newpos, g + size); 103 | break; 104 | } 105 | default: ; 106 | } 107 | #ifdef BOOST_MSVC 108 | #pragma warning(push) 109 | #pragma warning(disable:4244) 110 | #endif 111 | return static_cast(this->gptr() - this->eback()); 112 | #ifdef BOOST_MSVC 113 | #pragma warning(pop) 114 | #endif 115 | } 116 | 117 | template 118 | typename basic_pointerbuf::pos_type 119 | basic_pointerbuf::seekpos(pos_type sp, ::std::ios_base::openmode which) 120 | { 121 | if(which & ::std::ios_base::out) 122 | return pos_type(off_type(-1)); 123 | off_type size = static_cast(this->egptr() - this->eback()); 124 | charT* g = this->eback(); 125 | if(off_type(sp) <= size) 126 | { 127 | this->setg(g, g + off_type(sp), g + size); 128 | } 129 | return pos_type(off_type(-1)); 130 | } 131 | 132 | }} // namespace boost::detail 133 | 134 | #endif // BOOST_DETAIL_BASIC_POINTERBUF_HPP 135 | -------------------------------------------------------------------------------- /include/boost/detail/lcast_precision.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Alexander Nasonov & Paul A. Bristow 2006. 2 | 3 | // Use, modification and distribution are subject to the 4 | // Boost Software License, Version 1.0. 5 | // (See accompanying file LICENSE_1_0.txt 6 | // or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #ifndef BOOST_DETAIL_LCAST_PRECISION_HPP_INCLUDED 9 | #define BOOST_DETAIL_LCAST_PRECISION_HPP_INCLUDED 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | namespace boost { namespace detail { 18 | 19 | // Calculate an argument to pass to std::ios_base::precision from 20 | // lexical_cast. 21 | template 22 | struct lcast_precision 23 | { 24 | using limits = std::numeric_limits; 25 | 26 | static constexpr bool use_default_precision = 27 | !limits::is_specialized || limits::is_exact 28 | ; 29 | 30 | static constexpr bool is_specialized_bin = 31 | !use_default_precision && 32 | limits::radix == 2 && limits::digits > 0 33 | ; 34 | 35 | static constexpr bool is_specialized_dec = 36 | !use_default_precision && 37 | limits::radix == 10 && limits::digits10 > 0 38 | ; 39 | 40 | static constexpr std::streamsize streamsize_max = 41 | (std::numeric_limits::max)() 42 | ; 43 | 44 | static constexpr unsigned int precision_dec = limits::digits10 + 1U; 45 | 46 | static_assert(!is_specialized_dec || 47 | precision_dec <= streamsize_max + 0UL 48 | , ""); 49 | 50 | static constexpr unsigned long precision_bin = 51 | 2UL + limits::digits * 30103UL / 100000UL 52 | ; 53 | 54 | static_assert(!is_specialized_bin || 55 | (limits::digits + 0UL < ULONG_MAX / 30103UL && 56 | precision_bin > limits::digits10 + 0UL && 57 | precision_bin <= streamsize_max + 0UL) 58 | , ""); 59 | 60 | static constexpr std::streamsize value = 61 | is_specialized_bin ? precision_bin 62 | : is_specialized_dec ? precision_dec : 6 63 | ; 64 | }; 65 | 66 | template 67 | inline void lcast_set_precision(std::ios_base& stream, T*) 68 | { 69 | stream.precision(lcast_precision::value); 70 | } 71 | 72 | template 73 | inline void lcast_set_precision(std::ios_base& stream, Source*, Target*) 74 | { 75 | std::streamsize const s = lcast_precision::value; 76 | std::streamsize const t = lcast_precision::value; 77 | stream.precision(s > t ? s : t); 78 | } 79 | 80 | }} 81 | 82 | #endif // BOOST_DETAIL_LCAST_PRECISION_HPP_INCLUDED 83 | 84 | -------------------------------------------------------------------------------- /include/boost/lexical_cast.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Kevlin Henney, 2000-2005. 2 | // Copyright Alexander Nasonov, 2006-2010. 3 | // Copyright Antony Polukhin, 2011-2025. 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See 6 | // accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt) 8 | // 9 | // what: lexical_cast custom keyword cast 10 | // who: contributed by Kevlin Henney, 11 | // enhanced with contributions from Terje Slettebo, 12 | // with additional fixes and suggestions from Gennaro Prota, 13 | // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, 14 | // Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann, 15 | // Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters 16 | // when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2014 17 | 18 | #ifndef BOOST_LEXICAL_CAST_INCLUDED 19 | #define BOOST_LEXICAL_CAST_INCLUDED 20 | 21 | #include 22 | #ifdef BOOST_HAS_PRAGMA_ONCE 23 | # pragma once 24 | #endif 25 | 26 | #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING) 27 | #define BOOST_LCAST_NO_WCHAR_T 28 | #endif 29 | 30 | #include 31 | 32 | #include 33 | #include 34 | 35 | namespace boost 36 | { 37 | template 38 | inline Target lexical_cast(const Source &arg) 39 | { 40 | Target result = Target(); 41 | 42 | if (!boost::conversion::detail::try_lexical_convert(arg, result)) { 43 | boost::conversion::detail::throw_bad_cast(); 44 | } 45 | 46 | return result; 47 | } 48 | 49 | template 50 | inline Target lexical_cast(const char* chars, std::size_t count) 51 | { 52 | return ::boost::lexical_cast( 53 | ::boost::conversion::detail::make_buffer_view(chars, chars + count) 54 | ); 55 | } 56 | 57 | template 58 | inline Target lexical_cast(const unsigned char* chars, std::size_t count) 59 | { 60 | return ::boost::lexical_cast( 61 | ::boost::conversion::detail::make_buffer_view(chars, chars + count) 62 | ); 63 | } 64 | 65 | template 66 | inline Target lexical_cast(const signed char* chars, std::size_t count) 67 | { 68 | return ::boost::lexical_cast( 69 | ::boost::conversion::detail::make_buffer_view(chars, chars + count) 70 | ); 71 | } 72 | 73 | #ifndef BOOST_LCAST_NO_WCHAR_T 74 | template 75 | inline Target lexical_cast(const wchar_t* chars, std::size_t count) 76 | { 77 | return ::boost::lexical_cast( 78 | ::boost::conversion::detail::make_buffer_view(chars, chars + count) 79 | ); 80 | } 81 | #endif 82 | template 83 | inline Target lexical_cast(const char16_t* chars, std::size_t count) 84 | { 85 | return ::boost::lexical_cast( 86 | ::boost::conversion::detail::make_buffer_view(chars, chars + count) 87 | ); 88 | } 89 | template 90 | inline Target lexical_cast(const char32_t* chars, std::size_t count) 91 | { 92 | return ::boost::lexical_cast( 93 | ::boost::conversion::detail::make_buffer_view(chars, chars + count) 94 | ); 95 | } 96 | 97 | } // namespace boost 98 | 99 | #undef BOOST_LCAST_NO_WCHAR_T 100 | 101 | #endif // BOOST_LEXICAL_CAST_INCLUDED 102 | 103 | -------------------------------------------------------------------------------- /include/boost/lexical_cast/bad_lexical_cast.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Kevlin Henney, 2000-2005. 2 | // Copyright Alexander Nasonov, 2006-2010. 3 | // Copyright Antony Polukhin, 2011-2025. 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See 6 | // accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt) 8 | // 9 | // what: lexical_cast custom keyword cast 10 | // who: contributed by Kevlin Henney, 11 | // enhanced with contributions from Terje Slettebo, 12 | // with additional fixes and suggestions from Gennaro Prota, 13 | // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, 14 | // Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann, 15 | // Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters 16 | // when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2014 17 | 18 | #ifndef BOOST_LEXICAL_CAST_BAD_LEXICAL_CAST_HPP 19 | #define BOOST_LEXICAL_CAST_BAD_LEXICAL_CAST_HPP 20 | 21 | #include 22 | #ifdef BOOST_HAS_PRAGMA_ONCE 23 | # pragma once 24 | #endif 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | namespace boost 31 | { 32 | // exception used to indicate runtime lexical_cast failure 33 | class BOOST_SYMBOL_VISIBLE bad_lexical_cast : 34 | // workaround MSVC bug with std::bad_cast when _HAS_EXCEPTIONS == 0 35 | #if defined(BOOST_MSVC) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS 36 | public std::exception 37 | #else 38 | public std::bad_cast 39 | #endif 40 | { 41 | public: 42 | bad_lexical_cast() noexcept 43 | #ifndef BOOST_NO_TYPEID 44 | : source(&typeid(void)), target(&typeid(void)) 45 | #endif 46 | {} 47 | 48 | const char *what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE { 49 | return "bad lexical cast: " 50 | "source type value could not be interpreted as target"; 51 | } 52 | 53 | bad_lexical_cast(const bad_lexical_cast&) = default; 54 | bad_lexical_cast& operator=(const bad_lexical_cast&) = default; 55 | 56 | #ifndef BOOST_NO_TYPEID 57 | private: 58 | #ifdef BOOST_NO_STD_TYPEINFO 59 | typedef ::type_info type_info_t; 60 | #else 61 | typedef ::std::type_info type_info_t; 62 | #endif 63 | public: 64 | bad_lexical_cast( 65 | const type_info_t &source_type_arg, 66 | const type_info_t &target_type_arg) noexcept 67 | : source(&source_type_arg), target(&target_type_arg) 68 | {} 69 | 70 | const type_info_t &source_type() const noexcept { 71 | return *source; 72 | } 73 | 74 | const type_info_t &target_type() const noexcept { 75 | return *target; 76 | } 77 | 78 | private: 79 | const type_info_t *source; 80 | const type_info_t *target; 81 | #endif 82 | }; 83 | 84 | namespace conversion { namespace detail { 85 | #ifdef BOOST_NO_TYPEID 86 | template 87 | inline void throw_bad_cast() { 88 | boost::throw_exception(bad_lexical_cast()); 89 | } 90 | #else 91 | template 92 | inline void throw_bad_cast() { 93 | boost::throw_exception(bad_lexical_cast(typeid(S), typeid(T))); 94 | } 95 | #endif 96 | }} // namespace conversion::detail 97 | 98 | } // namespace boost 99 | 100 | #endif // BOOST_LEXICAL_CAST_BAD_LEXICAL_CAST_HPP 101 | -------------------------------------------------------------------------------- /include/boost/lexical_cast/detail/buffer_view.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Antony Polukhin, 2011-2025. 2 | // 3 | // Distributed under the Boost Software License, Version 1.0. (See 4 | // accompanying file LICENSE_1_0.txt or copy at 5 | // http://www.boost.org/LICENSE_1_0.txt) 6 | 7 | #ifndef BOOST_LEXICAL_CAST_DETAIL_BUFFER_VIEW_HPP 8 | #define BOOST_LEXICAL_CAST_DETAIL_BUFFER_VIEW_HPP 9 | 10 | #include 11 | #ifdef BOOST_HAS_PRAGMA_ONCE 12 | # pragma once 13 | #endif 14 | 15 | #include 16 | 17 | namespace boost { namespace conversion { namespace detail { 18 | 19 | template < typename CharT > 20 | struct buffer_view { 21 | const CharT* begin; 22 | const CharT* end; 23 | }; 24 | 25 | template < typename CharT > 26 | buffer_view make_buffer_view(const CharT* begin, const CharT* end) { 27 | return buffer_view{begin, end}; 28 | } 29 | 30 | inline buffer_view make_buffer_view(const signed char* begin, const signed char* end) { 31 | return buffer_view{ 32 | reinterpret_cast(begin), 33 | reinterpret_cast(end) 34 | }; 35 | } 36 | 37 | inline buffer_view make_buffer_view(const unsigned char* begin, const unsigned char* end) { 38 | return buffer_view{ 39 | reinterpret_cast(begin), 40 | reinterpret_cast(end) 41 | }; 42 | } 43 | 44 | template< typename CharT, typename Elem, typename Traits > 45 | std::basic_ostream& operator<<( 46 | std::basic_ostream& os, 47 | buffer_view r) 48 | { 49 | while (r.begin != r.end) { 50 | os << r.begin[0]; 51 | ++r.begin; 52 | } 53 | return os; 54 | } 55 | 56 | }}} // namespace boost::conversion::detail 57 | 58 | #endif // BOOST_LEXICAL_CAST_DETAIL_BUFFER_VIEW_HPP 59 | 60 | -------------------------------------------------------------------------------- /include/boost/lexical_cast/detail/converter_lexical.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Kevlin Henney, 2000-2005. 2 | // Copyright Alexander Nasonov, 2006-2010. 3 | // Copyright Antony Polukhin, 2011-2025. 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See 6 | // accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt) 8 | // 9 | // what: lexical_cast custom keyword cast 10 | // who: contributed by Kevlin Henney, 11 | // enhanced with contributions from Terje Slettebo, 12 | // with additional fixes and suggestions from Gennaro Prota, 13 | // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, 14 | // Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann, 15 | // Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters 16 | // when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2014 17 | 18 | #ifndef BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_HPP 19 | #define BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_HPP 20 | 21 | #include 22 | #ifdef BOOST_HAS_PRAGMA_ONCE 23 | # pragma once 24 | #endif 25 | 26 | #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING) 27 | #define BOOST_LCAST_NO_WCHAR_T 28 | #endif 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #include 41 | #include 42 | 43 | #include 44 | 45 | #ifndef BOOST_NO_CXX17_HDR_STRING_VIEW 46 | #include 47 | #endif 48 | 49 | #include 50 | #include 51 | 52 | #include 53 | 54 | namespace boost { 55 | 56 | // Forward declaration 57 | template 58 | class array; 59 | template 60 | class iterator_range; 61 | 62 | // Forward declaration of boost::basic_string_view from Utility 63 | template class basic_string_view; 64 | 65 | namespace detail // normalize_single_byte_char 66 | { 67 | // Converts signed/unsigned char to char 68 | template < class Char > 69 | struct normalize_single_byte_char 70 | { 71 | typedef Char type; 72 | }; 73 | 74 | template <> 75 | struct normalize_single_byte_char< signed char > 76 | { 77 | typedef char type; 78 | }; 79 | 80 | template <> 81 | struct normalize_single_byte_char< unsigned char > 82 | { 83 | typedef char type; 84 | }; 85 | } 86 | 87 | namespace detail // deduce_character_type_later 88 | { 89 | // Helper type, meaning that stram character for T must be deduced 90 | // at Stage 2 (See deduce_source_char and deduce_target_char) 91 | template < class T > struct deduce_character_type_later {}; 92 | } 93 | 94 | namespace detail // stream_char_common 95 | { 96 | // Selectors to choose stream character type (common for Source and Target) 97 | // Returns one of char, wchar_t, char16_t, char32_t or deduce_character_type_later types 98 | // Executed on Stage 1 (See deduce_source_char and deduce_target_char) 99 | template < typename Type > 100 | struct stream_char_common: public boost::conditional< 101 | boost::detail::is_character< Type >::value, 102 | Type, 103 | boost::detail::deduce_character_type_later< Type > 104 | > {}; 105 | 106 | template < typename Char > 107 | struct stream_char_common< Char* >: public boost::conditional< 108 | boost::detail::is_character< Char >::value, 109 | Char, 110 | boost::detail::deduce_character_type_later< Char* > 111 | > {}; 112 | 113 | template < typename Char > 114 | struct stream_char_common< const Char* >: public boost::conditional< 115 | boost::detail::is_character< Char >::value, 116 | Char, 117 | boost::detail::deduce_character_type_later< const Char* > 118 | > {}; 119 | 120 | template < typename Char > 121 | struct stream_char_common< boost::conversion::detail::buffer_view< Char > > 122 | { 123 | typedef Char type; 124 | }; 125 | 126 | template < typename Char > 127 | struct stream_char_common< boost::iterator_range< Char* > >: public boost::conditional< 128 | boost::detail::is_character< Char >::value, 129 | Char, 130 | boost::detail::deduce_character_type_later< boost::iterator_range< Char* > > 131 | > {}; 132 | 133 | template < typename Char > 134 | struct stream_char_common< boost::iterator_range< const Char* > >: public boost::conditional< 135 | boost::detail::is_character< Char >::value, 136 | Char, 137 | boost::detail::deduce_character_type_later< boost::iterator_range< const Char* > > 138 | > {}; 139 | 140 | template < class Char, class Traits, class Alloc > 141 | struct stream_char_common< std::basic_string< Char, Traits, Alloc > > 142 | { 143 | typedef Char type; 144 | }; 145 | 146 | template < class Char, class Traits, class Alloc > 147 | struct stream_char_common< boost::container::basic_string< Char, Traits, Alloc > > 148 | { 149 | typedef Char type; 150 | }; 151 | 152 | template < typename Char, std::size_t N > 153 | struct stream_char_common< boost::array< Char, N > >: public boost::conditional< 154 | boost::detail::is_character< Char >::value, 155 | Char, 156 | boost::detail::deduce_character_type_later< boost::array< Char, N > > 157 | > {}; 158 | 159 | template < typename Char, std::size_t N > 160 | struct stream_char_common< boost::array< const Char, N > >: public boost::conditional< 161 | boost::detail::is_character< Char >::value, 162 | Char, 163 | boost::detail::deduce_character_type_later< boost::array< const Char, N > > 164 | > {}; 165 | 166 | #ifndef BOOST_NO_CXX11_HDR_ARRAY 167 | template < typename Char, std::size_t N > 168 | struct stream_char_common< std::array >: public boost::conditional< 169 | boost::detail::is_character< Char >::value, 170 | Char, 171 | boost::detail::deduce_character_type_later< std::array< Char, N > > 172 | > {}; 173 | 174 | template < typename Char, std::size_t N > 175 | struct stream_char_common< std::array< const Char, N > >: public boost::conditional< 176 | boost::detail::is_character< Char >::value, 177 | Char, 178 | boost::detail::deduce_character_type_later< std::array< const Char, N > > 179 | > {}; 180 | #endif 181 | 182 | #ifndef BOOST_NO_CXX17_HDR_STRING_VIEW 183 | template < class Char, class Traits > 184 | struct stream_char_common< std::basic_string_view< Char, Traits > > 185 | { 186 | typedef Char type; 187 | }; 188 | #endif 189 | template < class Char, class Traits > 190 | struct stream_char_common< boost::basic_string_view< Char, Traits > > 191 | { 192 | typedef Char type; 193 | }; 194 | 195 | #ifdef BOOST_HAS_INT128 196 | template <> struct stream_char_common< boost::int128_type >: public boost::type_identity< char > {}; 197 | template <> struct stream_char_common< boost::uint128_type >: public boost::type_identity< char > {}; 198 | #endif 199 | 200 | #if !defined(BOOST_LCAST_NO_WCHAR_T) && defined(BOOST_NO_INTRINSIC_WCHAR_T) 201 | template <> 202 | struct stream_char_common< wchar_t > 203 | { 204 | typedef char type; 205 | }; 206 | #endif 207 | } 208 | 209 | namespace detail // deduce_source_char_impl 210 | { 211 | // If type T is `deduce_character_type_later` type, then tries to deduce 212 | // character type using streaming metafunctions. 213 | // Otherwise supplied type T is a character type, that must be normalized 214 | // using normalize_single_byte_char. 215 | // Executed at Stage 2 (See deduce_source_char and deduce_target_char) 216 | template < class Char > 217 | struct deduce_source_char_impl 218 | { 219 | typedef typename boost::detail::normalize_single_byte_char< Char >::type type; 220 | }; 221 | 222 | template < class T > 223 | struct deduce_source_char_impl< deduce_character_type_later< T > > 224 | { 225 | template 226 | static auto left_shift_type(long) 227 | -> decltype( std::declval&>() << std::declval(), char{}); 228 | 229 | #if !defined(BOOST_LCAST_NO_WCHAR_T) 230 | template 231 | static auto left_shift_type(int) 232 | -> decltype( std::declval&>() << std::declval(), wchar_t{}); 233 | #endif 234 | 235 | template 236 | static void left_shift_type(...); 237 | 238 | using type = decltype(left_shift_type(1L)); 239 | 240 | static_assert(!std::is_same::value, 241 | #if defined(BOOST_LCAST_NO_WCHAR_T) 242 | "Source type is not std::ostream`able and std::wostream`s are " 243 | "not supported by your STL implementation" 244 | #else 245 | "Source type is neither std::ostream`able nor std::wostream`able" 246 | #endif 247 | ); 248 | }; 249 | } 250 | 251 | namespace detail // deduce_target_char_impl 252 | { 253 | // If type T is `deduce_character_type_later` type, then tries to deduce 254 | // character type using boost::has_right_shift metafunction. 255 | // Otherwise supplied type T is a character type, that must be normalized 256 | // using normalize_single_byte_char. 257 | // Executed at Stage 2 (See deduce_source_char and deduce_target_char) 258 | template < class Char > 259 | struct deduce_target_char_impl 260 | { 261 | typedef typename normalize_single_byte_char< Char >::type type; 262 | }; 263 | 264 | template < class T > 265 | struct deduce_target_char_impl< deduce_character_type_later > 266 | { 267 | template 268 | static auto right_shift_type(long) 269 | -> decltype( std::declval&>() >> std::declval(), char{}); 270 | 271 | #if !defined(BOOST_LCAST_NO_WCHAR_T) 272 | template 273 | static auto right_shift_type(int) 274 | -> decltype( std::declval&>() >> std::declval(), wchar_t{}); 275 | #endif 276 | 277 | template 278 | static void right_shift_type(...); 279 | 280 | using type = decltype(right_shift_type(1L)); 281 | 282 | static_assert(!std::is_same::value, 283 | #if defined(BOOST_LCAST_NO_WCHAR_T) 284 | "Target type is not std::istream`able and std::wistream`s are " 285 | "not supported by your STL implementation" 286 | #else 287 | "Target type is neither std::istream`able nor std::wistream`able" 288 | #endif 289 | ); 290 | }; 291 | } 292 | 293 | namespace detail // deduce_target_char and deduce_source_char 294 | { 295 | // We deduce stream character types in two stages. 296 | // 297 | // Stage 1 is common for Target and Source. At Stage 1 we get 298 | // non normalized character type (may contain unsigned/signed char) 299 | // or deduce_character_type_later where T is the original type. 300 | // Stage 1 is executed by stream_char_common 301 | // 302 | // At Stage 2 we normalize character types or try to deduce character 303 | // type using metafunctions. 304 | // Stage 2 is executed by deduce_target_char_impl and 305 | // deduce_source_char_impl 306 | // 307 | // deduce_target_char and deduce_source_char functions combine 308 | // both stages 309 | 310 | template < class T > 311 | struct deduce_target_char 312 | { 313 | typedef typename stream_char_common< T >::type stage1_type; 314 | typedef typename deduce_target_char_impl< stage1_type >::type type; 315 | }; 316 | 317 | template < class T > 318 | struct deduce_source_char 319 | { 320 | typedef typename stream_char_common< T >::type stage1_type; 321 | typedef typename deduce_source_char_impl< stage1_type >::type type; 322 | }; 323 | } 324 | 325 | namespace detail // array_to_pointer_decay 326 | { 327 | template 328 | struct array_to_pointer_decay 329 | { 330 | typedef T type; 331 | }; 332 | 333 | template 334 | struct array_to_pointer_decay 335 | { 336 | typedef const T * type; 337 | }; 338 | } 339 | 340 | namespace detail // lcast_src_length 341 | { 342 | // Return max. length of string representation of Source; 343 | template< class Source, // Source type of lexical_cast. 344 | class Enable = void // helper type 345 | > 346 | struct lcast_src_length 347 | { 348 | BOOST_STATIC_CONSTANT(std::size_t, value = 1); 349 | }; 350 | 351 | // Helper for integral types. 352 | // Notes on length calculation: 353 | // Max length for 32bit int with grouping "\1" and thousands_sep ',': 354 | // "-2,1,4,7,4,8,3,6,4,7" 355 | // ^ - is_signed 356 | // ^ - 1 digit not counted by digits10 357 | // ^^^^^^^^^^^^^^^^^^ - digits10 * 2 358 | // 359 | // Constant is_specialized is used instead of constant 1 360 | // to prevent buffer overflow in a rare case when 361 | // doesn't add missing specialization for 362 | // numeric_limits for some integral type T. 363 | // When is_specialized is false, the whole expression is 0. 364 | template 365 | struct lcast_src_length< 366 | Source, typename boost::enable_if >::type 367 | > 368 | { 369 | BOOST_STATIC_CONSTANT(std::size_t, value = 370 | std::numeric_limits::is_signed + 371 | std::numeric_limits::is_specialized + /* == 1 */ 372 | std::numeric_limits::digits10 * 2 373 | ); 374 | }; 375 | 376 | // Helper for floating point types. 377 | // -1.23456789e-123456 378 | // ^ sign 379 | // ^ leading digit 380 | // ^ decimal point 381 | // ^^^^^^^^ lcast_precision::value 382 | // ^ "e" 383 | // ^ exponent sign 384 | // ^^^^^^ exponent (assumed 6 or less digits) 385 | // sign + leading digit + decimal point + "e" + exponent sign == 5 386 | template 387 | struct lcast_src_length< 388 | Source, typename boost::enable_if >::type 389 | > 390 | { 391 | static_assert( 392 | std::numeric_limits::max_exponent10 <= 999999L && 393 | std::numeric_limits::min_exponent10 >= -999999L 394 | , ""); 395 | 396 | BOOST_STATIC_CONSTANT(std::size_t, value = 397 | 5 + lcast_precision::value + 6 398 | ); 399 | }; 400 | } 401 | 402 | namespace detail // lexical_cast_stream_traits 403 | { 404 | template 405 | struct lexical_cast_stream_traits { 406 | typedef typename boost::detail::array_to_pointer_decay::type src; 407 | typedef typename boost::remove_cv::type no_cv_src; 408 | 409 | typedef boost::detail::deduce_source_char deduce_src_char_metafunc; 410 | typedef typename deduce_src_char_metafunc::type src_char_t; 411 | typedef typename boost::detail::deduce_target_char::type target_char_t; 412 | 413 | typedef typename boost::detail::widest_char< 414 | target_char_t, src_char_t 415 | >::type char_type; 416 | 417 | #if !defined(BOOST_NO_CXX11_CHAR16_T) && defined(BOOST_NO_CXX11_UNICODE_LITERALS) 418 | static_assert(!boost::is_same::value 419 | && !boost::is_same::value, 420 | "Your compiler does not have full support for char16_t" ); 421 | #endif 422 | #if !defined(BOOST_NO_CXX11_CHAR32_T) && defined(BOOST_NO_CXX11_UNICODE_LITERALS) 423 | static_assert(!boost::is_same::value 424 | && !boost::is_same::value, 425 | "Your compiler does not have full support for char32_t" ); 426 | #endif 427 | 428 | typedef std::char_traits traits; 429 | 430 | typedef boost::detail::lcast_src_length len_t; 431 | }; 432 | } 433 | 434 | namespace detail 435 | { 436 | template 437 | struct lexical_converter_impl 438 | { 439 | typedef lexical_cast_stream_traits stream_trait; 440 | 441 | typedef detail::lcast::optimized_src_stream< 442 | typename stream_trait::char_type, 443 | typename stream_trait::traits, 444 | stream_trait::len_t::value + 1 445 | > optimized_src_stream; 446 | 447 | template 448 | static auto detect_type(int) 449 | -> decltype(std::declval().stream_in(std::declval>()), optimized_src_stream{}); 450 | 451 | template 452 | static lcast::ios_src_stream detect_type(...); 453 | 454 | using from_src_stream = decltype(detect_type(1)); 455 | 456 | typedef detail::lcast::to_target_stream< 457 | typename stream_trait::char_type, 458 | typename stream_trait::traits 459 | > to_target_stream; 460 | 461 | static inline bool try_convert(const Source& arg, Target& result) { 462 | from_src_stream src_stream; 463 | if (!src_stream.stream_in(lcast::exact{arg})) 464 | return false; 465 | 466 | to_target_stream out(src_stream.cbegin(), src_stream.cend()); 467 | if (!out.stream_out(result)) 468 | return false; 469 | 470 | return true; 471 | } 472 | }; 473 | } 474 | 475 | } // namespace boost 476 | 477 | #undef BOOST_LCAST_NO_WCHAR_T 478 | 479 | #endif // BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_HPP 480 | 481 | -------------------------------------------------------------------------------- /include/boost/lexical_cast/detail/converter_numeric.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Kevlin Henney, 2000-2005. 2 | // Copyright Alexander Nasonov, 2006-2010. 3 | // Copyright Antony Polukhin, 2011-2025. 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See 6 | // accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt) 8 | // 9 | // what: lexical_cast custom keyword cast 10 | // who: contributed by Kevlin Henney, 11 | // enhanced with contributions from Terje Slettebo, 12 | // with additional fixes and suggestions from Gennaro Prota, 13 | // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, 14 | // Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann, 15 | // Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters 16 | // when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2016 17 | 18 | #ifndef BOOST_LEXICAL_CAST_DETAIL_CONVERTER_NUMERIC_HPP 19 | #define BOOST_LEXICAL_CAST_DETAIL_CONVERTER_NUMERIC_HPP 20 | 21 | #include 22 | #ifdef BOOST_HAS_PRAGMA_ONCE 23 | # pragma once 24 | #endif 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | namespace boost { namespace detail { 37 | 38 | template 39 | bool ios_numeric_comparer_float(Source x, Source y) noexcept { 40 | return x == y 41 | || (boost::core::isnan(x) && boost::core::isnan(y)) 42 | || (x < (std::numeric_limits::min)()) 43 | ; 44 | } 45 | 46 | template 47 | constexpr bool is_out_of_range_for(T value) noexcept { 48 | return value > static_cast((std::numeric_limits::max)()) 49 | || value < static_cast((std::numeric_limits::min)()); 50 | } 51 | 52 | 53 | // integral -> integral 54 | template 55 | typename boost::enable_if_c< 56 | !boost::is_floating_point::value && !boost::is_floating_point::value, bool 57 | >::type noexcept_numeric_convert(Source arg, Target& result) noexcept { 58 | const Target target_tmp = static_cast(arg); 59 | const Source arg_restored = static_cast(target_tmp); 60 | if (arg == arg_restored) { 61 | result = target_tmp; 62 | return true; 63 | } 64 | return false; 65 | } 66 | 67 | // integral -> floating point 68 | template 69 | typename boost::enable_if_c< 70 | !boost::is_floating_point::value && boost::is_floating_point::value, bool 71 | >::type noexcept_numeric_convert(Source arg, Target& result) noexcept { 72 | const Target target_tmp = static_cast(arg); 73 | result = target_tmp; 74 | return true; 75 | } 76 | 77 | 78 | // floating point -> floating point 79 | template 80 | typename boost::enable_if_c< 81 | boost::is_floating_point::value && boost::is_floating_point::value, bool 82 | >::type noexcept_numeric_convert(Source arg, Target& result) noexcept { 83 | const Target target_tmp = static_cast(arg); 84 | const Source arg_restored = static_cast(target_tmp); 85 | if (detail::ios_numeric_comparer_float(arg, arg_restored)) { 86 | result = target_tmp; 87 | return true; 88 | } 89 | 90 | return false; 91 | } 92 | 93 | // floating point -> integral 94 | template 95 | typename boost::enable_if_c< 96 | boost::is_floating_point::value && !boost::is_floating_point::value, bool 97 | >::type noexcept_numeric_convert(Source arg, Target& result) noexcept { 98 | if (detail::is_out_of_range_for(arg)) { 99 | return false; 100 | } 101 | 102 | const Target target_tmp = static_cast(arg); 103 | const Source arg_restored = static_cast(target_tmp); 104 | if (detail::ios_numeric_comparer_float(arg, arg_restored)) { 105 | result = target_tmp; 106 | return true; 107 | } 108 | 109 | return false; 110 | } 111 | 112 | struct lexical_cast_dynamic_num_not_ignoring_minus 113 | { 114 | template 115 | static inline bool try_convert(Source arg, Target& result) noexcept { 116 | return boost::detail::noexcept_numeric_convert(arg, result); 117 | } 118 | }; 119 | 120 | struct lexical_cast_dynamic_num_ignoring_minus 121 | { 122 | template 123 | #if defined(__clang__) && (__clang_major__ > 3 || __clang_minor__ > 6) 124 | __attribute__((no_sanitize("unsigned-integer-overflow"))) 125 | #endif 126 | static inline bool try_convert(Source arg, Target& result) noexcept { 127 | typedef typename boost::conditional< 128 | boost::is_float::value, 129 | boost::type_identity, 130 | boost::make_unsigned 131 | >::type usource_lazy_t; 132 | typedef typename usource_lazy_t::type usource_t; 133 | 134 | if (arg < 0) { 135 | const bool res = boost::detail::noexcept_numeric_convert( 136 | static_cast(0u - static_cast(arg)), result 137 | ); 138 | result = static_cast(0u - result); 139 | return res; 140 | } else { 141 | return boost::detail::noexcept_numeric_convert(arg, result); 142 | } 143 | } 144 | }; 145 | 146 | /* 147 | * dynamic_num_converter_impl follows the rules: 148 | * 1) If Source can be converted to Target without precision loss and 149 | * without overflows, then assign Source to Target and return 150 | * 151 | * 2) If Source is less than 0 and Target is an unsigned integer, 152 | * then negate Source, check the requirements of rule 1) and if 153 | * successful, assign static_casted Source to Target and return 154 | * 155 | * 3) Otherwise throw a bad_lexical_cast exception 156 | * 157 | * 158 | * Rule 2) required because boost::lexical_cast has the behavior of 159 | * stringstream, which uses the rules of scanf for conversions. And 160 | * in the C99 standard for unsigned input value minus sign is 161 | * optional, so if a negative number is read, no errors will arise 162 | * and the result will be the two's complement. 163 | */ 164 | template 165 | struct dynamic_num_converter_impl 166 | { 167 | static inline bool try_convert(Source arg, Target& result) noexcept { 168 | typedef typename boost::conditional< 169 | boost::is_unsigned::value && 170 | (boost::is_signed::value || boost::is_float::value) && 171 | !(boost::is_same::value) && 172 | !(boost::is_same::value), 173 | lexical_cast_dynamic_num_ignoring_minus, 174 | lexical_cast_dynamic_num_not_ignoring_minus 175 | >::type caster_type; 176 | 177 | return caster_type::try_convert(arg, result); 178 | } 179 | }; 180 | 181 | }} // namespace boost::detail 182 | 183 | #endif // BOOST_LEXICAL_CAST_DETAIL_CONVERTER_NUMERIC_HPP 184 | 185 | -------------------------------------------------------------------------------- /include/boost/lexical_cast/detail/inf_nan.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Kevlin Henney, 2000-2005. 2 | // Copyright Alexander Nasonov, 2006-2010. 3 | // Copyright Antony Polukhin, 2011-2025. 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See 6 | // accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt) 8 | // 9 | // what: lexical_cast custom keyword cast 10 | // who: contributed by Kevlin Henney, 11 | // enhanced with contributions from Terje Slettebo, 12 | // with additional fixes and suggestions from Gennaro Prota, 13 | // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, 14 | // Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann, 15 | // Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters 16 | // when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2014 17 | 18 | #ifndef BOOST_LEXICAL_CAST_DETAIL_INF_NAN_HPP 19 | #define BOOST_LEXICAL_CAST_DETAIL_INF_NAN_HPP 20 | 21 | #include 22 | #ifdef BOOST_HAS_PRAGMA_ONCE 23 | # pragma once 24 | #endif 25 | 26 | #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING) 27 | #define BOOST_LCAST_NO_WCHAR_T 28 | #endif 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include 37 | 38 | namespace boost { 39 | namespace detail 40 | { 41 | template 42 | bool lc_iequal(const CharT* val, const CharT* lcase, const CharT* ucase, unsigned int len) noexcept { 43 | for( unsigned int i=0; i < len; ++i ) { 44 | if ( val[i] != lcase[i] && val[i] != ucase[i] ) return false; 45 | } 46 | 47 | return true; 48 | } 49 | 50 | /* Returns true and sets the correct value if found NaN or Inf. */ 51 | template 52 | inline bool parse_inf_nan_impl(const CharT* begin, const CharT* end, T& value 53 | , const CharT* lc_NAN, const CharT* lc_nan 54 | , const CharT* lc_INFINITY, const CharT* lc_infinity 55 | , const CharT opening_brace, const CharT closing_brace) noexcept 56 | { 57 | if (begin == end) return false; 58 | const CharT minus = lcast_char_constants::minus; 59 | const CharT plus = lcast_char_constants::plus; 60 | const int inifinity_size = 8; // == sizeof("infinity") - 1 61 | 62 | /* Parsing +/- */ 63 | bool const has_minus = (*begin == minus); 64 | if (has_minus || *begin == plus) { 65 | ++ begin; 66 | } 67 | 68 | if (end - begin < 3) return false; 69 | if (lc_iequal(begin, lc_nan, lc_NAN, 3)) { 70 | begin += 3; 71 | if (end != begin) { 72 | /* It is 'nan(...)' or some bad input*/ 73 | 74 | if (end - begin < 2) return false; // bad input 75 | -- end; 76 | if (*begin != opening_brace || *end != closing_brace) return false; // bad input 77 | } 78 | 79 | if( !has_minus ) value = std::numeric_limits::quiet_NaN(); 80 | else value = boost::core::copysign(std::numeric_limits::quiet_NaN(), static_cast(-1)); 81 | return true; 82 | } else if ( 83 | ( /* 'INF' or 'inf' */ 84 | end - begin == 3 // 3 == sizeof('inf') - 1 85 | && lc_iequal(begin, lc_infinity, lc_INFINITY, 3) 86 | ) 87 | || 88 | ( /* 'INFINITY' or 'infinity' */ 89 | end - begin == inifinity_size 90 | && lc_iequal(begin, lc_infinity, lc_INFINITY, inifinity_size) 91 | ) 92 | ) 93 | { 94 | if( !has_minus ) value = std::numeric_limits::infinity(); 95 | else value = -std::numeric_limits::infinity(); 96 | return true; 97 | } 98 | 99 | return false; 100 | } 101 | 102 | template 103 | const CharT* get_inf_nan_impl(T value 104 | , const CharT* lc_nan 105 | , const CharT* lc_minus_nan 106 | , const CharT* lc_infinity 107 | , const CharT* lc_minus_infinity) noexcept 108 | { 109 | if (boost::core::isnan(value)) { 110 | if (boost::core::signbit(value)) { 111 | return lc_minus_nan; 112 | } 113 | return lc_nan; 114 | } else if (boost::core::isinf(value)) { 115 | if (boost::core::signbit(value)) { 116 | return lc_minus_infinity; 117 | } 118 | return lc_infinity; 119 | } 120 | 121 | return nullptr; 122 | } 123 | 124 | 125 | #ifndef BOOST_LCAST_NO_WCHAR_T 126 | template 127 | bool parse_inf_nan(const wchar_t* begin, const wchar_t* end, T& value) noexcept { 128 | return parse_inf_nan_impl(begin, end, value 129 | , L"NAN", L"nan" 130 | , L"INFINITY", L"infinity" 131 | , L'(', L')'); 132 | } 133 | 134 | template 135 | const wchar_t* get_inf_nan(T value, wchar_t) noexcept { 136 | return detail::get_inf_nan_impl(value, L"nan", L"-nan", L"inf", L"-inf"); 137 | } 138 | 139 | #endif 140 | #if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) 141 | template 142 | bool parse_inf_nan(const char16_t* begin, const char16_t* end, T& value) noexcept { 143 | return parse_inf_nan_impl(begin, end, value 144 | , u"NAN", u"nan" 145 | , u"INFINITY", u"infinity" 146 | , u'(', u')'); 147 | } 148 | 149 | template 150 | const char16_t* get_inf_nan(T value, char16_t) noexcept { 151 | return detail::get_inf_nan_impl(value, u"nan", u"-nan", u"inf", u"-inf"); 152 | } 153 | #endif 154 | #if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) 155 | template 156 | bool parse_inf_nan(const char32_t* begin, const char32_t* end, T& value) noexcept { 157 | return parse_inf_nan_impl(begin, end, value 158 | , U"NAN", U"nan" 159 | , U"INFINITY", U"infinity" 160 | , U'(', U')'); 161 | } 162 | 163 | template 164 | const char32_t* get_inf_nan(T value, char32_t) noexcept { 165 | return detail::get_inf_nan_impl(value, U"nan", U"-nan", U"inf", U"-inf"); 166 | } 167 | #endif 168 | 169 | template 170 | bool parse_inf_nan(const CharT* begin, const CharT* end, T& value) noexcept { 171 | return parse_inf_nan_impl(begin, end, value 172 | , "NAN", "nan" 173 | , "INFINITY", "infinity" 174 | , '(', ')'); 175 | } 176 | 177 | template 178 | const char* get_inf_nan(T value, char) noexcept { 179 | return detail::get_inf_nan_impl(value, "nan", "-nan", "inf", "-inf"); 180 | } 181 | } 182 | } // namespace boost 183 | 184 | #undef BOOST_LCAST_NO_WCHAR_T 185 | 186 | #endif // BOOST_LEXICAL_CAST_DETAIL_INF_NAN_HPP 187 | 188 | -------------------------------------------------------------------------------- /include/boost/lexical_cast/detail/is_character.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Kevlin Henney, 2000-2005. 2 | // Copyright Alexander Nasonov, 2006-2010. 3 | // Copyright Antony Polukhin, 2011-2025. 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See 6 | // accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt) 8 | // 9 | // what: lexical_cast custom keyword cast 10 | // who: contributed by Kevlin Henney, 11 | // enhanced with contributions from Terje Slettebo, 12 | // with additional fixes and suggestions from Gennaro Prota, 13 | // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, 14 | // Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann, 15 | // Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters 16 | // when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2014 17 | 18 | #ifndef BOOST_LEXICAL_CAST_DETAIL_IS_CHARACTER_HPP 19 | #define BOOST_LEXICAL_CAST_DETAIL_IS_CHARACTER_HPP 20 | 21 | #include 22 | #ifdef BOOST_HAS_PRAGMA_ONCE 23 | # pragma once 24 | #endif 25 | 26 | #include 27 | #include 28 | 29 | namespace boost { namespace detail { 30 | 31 | // returns true, if T is one of the character types 32 | template < typename T > 33 | using is_character = boost::integral_constant< 34 | bool, 35 | boost::is_same< T, char >::value || 36 | #if !defined(BOOST_NO_STRINGSTREAM) && !defined(BOOST_NO_STD_WSTRING) 37 | boost::is_same< T, wchar_t >::value || 38 | #endif 39 | #ifndef BOOST_NO_CXX11_CHAR16_T 40 | boost::is_same< T, char16_t >::value || 41 | #endif 42 | #ifndef BOOST_NO_CXX11_CHAR32_T 43 | boost::is_same< T, char32_t >::value || 44 | #endif 45 | boost::is_same< T, unsigned char >::value || 46 | boost::is_same< T, signed char >::value 47 | >; 48 | 49 | }} 50 | 51 | #endif // BOOST_LEXICAL_CAST_DETAIL_IS_CHARACTER_HPP 52 | 53 | -------------------------------------------------------------------------------- /include/boost/lexical_cast/detail/lcast_basic_unlockedbuf.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Kevlin Henney, 2000-2005. 2 | // Copyright Alexander Nasonov, 2006-2010. 3 | // Copyright Antony Polukhin, 2011-2025. 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See 6 | // accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | #ifndef BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_BASIC_UNLOCKEDBUF_HPP 10 | #define BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_BASIC_UNLOCKEDBUF_HPP 11 | 12 | #include 13 | #ifdef BOOST_HAS_PRAGMA_ONCE 14 | # pragma once 15 | #endif 16 | 17 | 18 | #ifdef BOOST_NO_STRINGSTREAM 19 | #include 20 | #else 21 | #include 22 | #endif 23 | 24 | #include 25 | #ifndef BOOST_NO_CWCHAR 26 | # include 27 | #endif 28 | 29 | namespace boost { namespace detail { namespace lcast { 30 | 31 | // acts as a stream buffer which wraps around a pair of pointers 32 | // and gives acces to internals 33 | template 34 | class basic_unlockedbuf : public basic_pointerbuf { 35 | public: 36 | typedef basic_pointerbuf base_type; 37 | typedef typename base_type::streamsize streamsize; 38 | 39 | using base_type::pptr; 40 | using base_type::pbase; 41 | using base_type::setbuf; 42 | }; 43 | 44 | #if defined(BOOST_NO_STRINGSTREAM) 45 | template 46 | using out_stream_t = std::ostream; 47 | 48 | template 49 | using stringbuffer_t = basic_unlockedbuf; 50 | #elif defined(BOOST_NO_STD_LOCALE) 51 | template 52 | using out_stream_t = std::ostream; 53 | 54 | template 55 | using stringbuffer_t = basic_unlockedbuf; 56 | 57 | template 58 | using buffer_t = basic_unlockedbuf; 59 | #else 60 | template 61 | using out_stream_t = std::basic_ostream; 62 | 63 | template 64 | using stringbuffer_t = basic_unlockedbuf, CharT>; 65 | 66 | template 67 | using buffer_t = basic_unlockedbuf, CharT>; 68 | #endif 69 | 70 | }}} // namespace boost::detail::lcast 71 | 72 | #endif // BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_BASIC_UNLOCKEDBUF_HPP 73 | 74 | -------------------------------------------------------------------------------- /include/boost/lexical_cast/detail/lcast_char_constants.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Kevlin Henney, 2000-2005. 2 | // Copyright Alexander Nasonov, 2006-2010. 3 | // Copyright Antony Polukhin, 2011-2025. 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See 6 | // accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt) 8 | // 9 | // what: lexical_cast custom keyword cast 10 | // who: contributed by Kevlin Henney, 11 | // enhanced with contributions from Terje Slettebo, 12 | // with additional fixes and suggestions from Gennaro Prota, 13 | // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, 14 | // Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann, 15 | // Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters 16 | // when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2014 17 | 18 | #ifndef BOOST_LEXICAL_CAST_DETAIL_LCAST_CHAR_CONSTANTS_HPP 19 | #define BOOST_LEXICAL_CAST_DETAIL_LCAST_CHAR_CONSTANTS_HPP 20 | 21 | #include 22 | #ifdef BOOST_HAS_PRAGMA_ONCE 23 | # pragma once 24 | #endif 25 | 26 | namespace boost 27 | { 28 | namespace detail // '0', '-', '+', 'e', 'E' and '.' constants 29 | { 30 | template < typename Char > 31 | struct lcast_char_constants { 32 | // We check in tests assumption that static casted character is 33 | // equal to correctly written C++ literal: U'0' == static_cast('0') 34 | BOOST_STATIC_CONSTANT(Char, zero = static_cast('0')); 35 | BOOST_STATIC_CONSTANT(Char, minus = static_cast('-')); 36 | BOOST_STATIC_CONSTANT(Char, plus = static_cast('+')); 37 | BOOST_STATIC_CONSTANT(Char, lowercase_e = static_cast('e')); 38 | BOOST_STATIC_CONSTANT(Char, capital_e = static_cast('E')); 39 | BOOST_STATIC_CONSTANT(Char, c_decimal_separator = static_cast('.')); 40 | }; 41 | } 42 | } // namespace boost 43 | 44 | 45 | #endif // BOOST_LEXICAL_CAST_DETAIL_LCAST_CHAR_CONSTANTS_HPP 46 | 47 | -------------------------------------------------------------------------------- /include/boost/lexical_cast/detail/lcast_unsigned_converters.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Kevlin Henney, 2000-2005. 2 | // Copyright Alexander Nasonov, 2006-2010. 3 | // Copyright Antony Polukhin, 2011-2025. 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See 6 | // accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt) 8 | // 9 | // what: lexical_cast custom keyword cast 10 | // who: contributed by Kevlin Henney, 11 | // enhanced with contributions from Terje Slettebo, 12 | // with additional fixes and suggestions from Gennaro Prota, 13 | // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, 14 | // Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann, 15 | // Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters 16 | // when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2014 17 | 18 | #ifndef BOOST_LEXICAL_CAST_DETAIL_LCAST_UNSIGNED_CONVERTERS_HPP 19 | #define BOOST_LEXICAL_CAST_DETAIL_LCAST_UNSIGNED_CONVERTERS_HPP 20 | 21 | #include 22 | #ifdef BOOST_HAS_PRAGMA_ONCE 23 | # pragma once 24 | #endif 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | 36 | #ifndef BOOST_NO_STD_LOCALE 37 | # include 38 | #else 39 | # ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE 40 | // Getting error at this point means, that your STL library is old/lame/misconfigured. 41 | // If nothing can be done with STL library, define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE, 42 | // but beware: lexical_cast will understand only 'C' locale delimeters and thousands 43 | // separators. 44 | # error "Unable to use header. Define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE to force " 45 | # error "boost::lexical_cast to use only 'C' locale during conversions." 46 | # endif 47 | #endif 48 | 49 | #include 50 | #include 51 | #include 52 | #include 53 | 54 | namespace boost 55 | { 56 | namespace detail // lcast_to_unsigned 57 | { 58 | template 59 | #if defined(__clang__) && (__clang_major__ > 3 || __clang_minor__ > 6) 60 | __attribute__((no_sanitize("unsigned-integer-overflow"))) 61 | #endif 62 | inline 63 | typename boost::make_unsigned::type lcast_to_unsigned(const T value) noexcept { 64 | typedef typename boost::make_unsigned::type result_type; 65 | return value < 0 66 | ? static_cast(0u - static_cast(value)) 67 | : static_cast(value); 68 | } 69 | } 70 | 71 | namespace detail // lcast_put_unsigned 72 | { 73 | template 74 | class lcast_put_unsigned: boost::noncopyable { 75 | typedef typename Traits::int_type int_type; 76 | typename boost::conditional< 77 | (sizeof(unsigned) > sizeof(T)) 78 | , unsigned 79 | , T 80 | >::type m_value; 81 | CharT* m_finish; 82 | CharT const m_czero; 83 | int_type const m_zero; 84 | 85 | public: 86 | lcast_put_unsigned(const T n_param, CharT* finish) noexcept 87 | : m_value(n_param), m_finish(finish) 88 | , m_czero(lcast_char_constants::zero), m_zero(Traits::to_int_type(m_czero)) 89 | { 90 | #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS 91 | static_assert(!std::numeric_limits::is_signed, ""); 92 | #endif 93 | } 94 | 95 | CharT* convert() { 96 | #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE 97 | std::locale loc; 98 | if (loc == std::locale::classic()) { 99 | return main_convert_loop(); 100 | } 101 | 102 | typedef std::numpunct numpunct; 103 | numpunct const& np = BOOST_USE_FACET(numpunct, loc); 104 | std::string const grouping = np.grouping(); 105 | std::string::size_type const grouping_size = grouping.size(); 106 | 107 | if (!grouping_size || grouping[0] <= 0) { 108 | return main_convert_loop(); 109 | } 110 | 111 | #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS 112 | // Check that ulimited group is unreachable: 113 | static_assert(std::numeric_limits::digits10 < CHAR_MAX, ""); 114 | #endif 115 | CharT const thousands_sep = np.thousands_sep(); 116 | std::string::size_type group = 0; // current group number 117 | char last_grp_size = grouping[0]; 118 | char left = last_grp_size; 119 | 120 | do { 121 | if (left == 0) { 122 | ++group; 123 | if (group < grouping_size) { 124 | char const grp_size = grouping[group]; 125 | last_grp_size = (grp_size <= 0 ? static_cast(CHAR_MAX) : grp_size); 126 | } 127 | 128 | left = last_grp_size; 129 | --m_finish; 130 | Traits::assign(*m_finish, thousands_sep); 131 | } 132 | 133 | --left; 134 | } while (main_convert_iteration()); 135 | 136 | return m_finish; 137 | #else 138 | return main_convert_loop(); 139 | #endif 140 | } 141 | 142 | private: 143 | inline bool main_convert_iteration() noexcept { 144 | --m_finish; 145 | int_type const digit = static_cast(m_value % 10U); 146 | Traits::assign(*m_finish, Traits::to_char_type(m_zero + digit)); 147 | m_value /= 10; 148 | return !!m_value; // suppressing warnings 149 | } 150 | 151 | inline CharT* main_convert_loop() noexcept { 152 | while (main_convert_iteration()); 153 | return m_finish; 154 | } 155 | }; 156 | } 157 | 158 | namespace detail // lcast_ret_unsigned 159 | { 160 | template 161 | class lcast_ret_unsigned: boost::noncopyable { 162 | bool m_multiplier_overflowed; 163 | T m_multiplier; 164 | T& m_value; 165 | const CharT* const m_begin; 166 | const CharT* m_end; 167 | 168 | public: 169 | lcast_ret_unsigned(T& value, const CharT* const begin, const CharT* end) noexcept 170 | : m_multiplier_overflowed(false), m_multiplier(1), m_value(value), m_begin(begin), m_end(end) 171 | { 172 | #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS 173 | static_assert(!std::numeric_limits::is_signed, ""); 174 | 175 | // GCC when used with flag -std=c++0x may not have std::numeric_limits 176 | // specializations for __int128 and unsigned __int128 types. 177 | // Try compilation with -std=gnu++0x or -std=gnu++11. 178 | // 179 | // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40856 180 | static_assert(std::numeric_limits::is_specialized, 181 | "std::numeric_limits are not specialized for integral type passed to boost::lexical_cast" 182 | ); 183 | #endif 184 | } 185 | 186 | inline bool convert() { 187 | CharT const czero = lcast_char_constants::zero; 188 | --m_end; 189 | m_value = static_cast(0); 190 | 191 | if (m_begin > m_end || *m_end < czero || *m_end >= czero + 10) 192 | return false; 193 | m_value = static_cast(*m_end - czero); 194 | --m_end; 195 | 196 | #ifdef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE 197 | return main_convert_loop(); 198 | #else 199 | std::locale loc; 200 | if (loc == std::locale::classic()) { 201 | return main_convert_loop(); 202 | } 203 | 204 | typedef std::numpunct numpunct; 205 | numpunct const& np = BOOST_USE_FACET(numpunct, loc); 206 | std::string const& grouping = np.grouping(); 207 | std::string::size_type const grouping_size = grouping.size(); 208 | 209 | /* According to Programming languages - C++ 210 | * we MUST check for correct grouping 211 | */ 212 | if (!grouping_size || grouping[0] <= 0) { 213 | return main_convert_loop(); 214 | } 215 | 216 | unsigned char current_grouping = 0; 217 | CharT const thousands_sep = np.thousands_sep(); 218 | char remained = static_cast(grouping[current_grouping] - 1); 219 | 220 | for (;m_end >= m_begin; --m_end) 221 | { 222 | if (remained) { 223 | if (!main_convert_iteration()) { 224 | return false; 225 | } 226 | --remained; 227 | } else { 228 | if ( !Traits::eq(*m_end, thousands_sep) ) //|| begin == end ) return false; 229 | { 230 | /* 231 | * According to Programming languages - C++ 232 | * Digit grouping is checked. That is, the positions of discarded 233 | * separators is examined for consistency with 234 | * use_facet >(loc ).grouping() 235 | * 236 | * BUT what if there is no separators at all and grouping() 237 | * is not empty? Well, we have no extraced separators, so we 238 | * won`t check them for consistency. This will allow us to 239 | * work with "C" locale from other locales 240 | */ 241 | return main_convert_loop(); 242 | } else { 243 | if (m_begin == m_end) return false; 244 | if (current_grouping < grouping_size - 1) ++current_grouping; 245 | remained = grouping[current_grouping]; 246 | } 247 | } 248 | } /*for*/ 249 | 250 | return true; 251 | #endif 252 | } 253 | 254 | private: 255 | // Iteration that does not care about grouping/separators and assumes that all 256 | // input characters are digits 257 | #if defined(__clang__) && (__clang_major__ > 3 || __clang_minor__ > 6) 258 | __attribute__((no_sanitize("unsigned-integer-overflow"))) 259 | #endif 260 | inline bool main_convert_iteration() noexcept { 261 | CharT const czero = lcast_char_constants::zero; 262 | T const maxv = (std::numeric_limits::max)(); 263 | 264 | m_multiplier_overflowed = m_multiplier_overflowed || (maxv/10 < m_multiplier); 265 | m_multiplier = static_cast(m_multiplier * 10); 266 | 267 | T const dig_value = static_cast(*m_end - czero); 268 | T const new_sub_value = static_cast(m_multiplier * dig_value); 269 | 270 | // We must correctly handle situations like `000000000000000000000000000001`. 271 | // So we take care of overflow only if `dig_value` is not '0'. 272 | if (*m_end < czero || *m_end >= czero + 10 // checking for correct digit 273 | || (dig_value && ( // checking for overflow of ... 274 | m_multiplier_overflowed // ... multiplier 275 | || static_cast(maxv / dig_value) < m_multiplier // ... subvalue 276 | || static_cast(maxv - new_sub_value) < m_value // ... whole expression 277 | )) 278 | ) return false; 279 | 280 | m_value = static_cast(m_value + new_sub_value); 281 | 282 | return true; 283 | } 284 | 285 | bool main_convert_loop() noexcept { 286 | for ( ; m_end >= m_begin; --m_end) { 287 | if (!main_convert_iteration()) { 288 | return false; 289 | } 290 | } 291 | 292 | return true; 293 | } 294 | }; 295 | } 296 | } // namespace boost 297 | 298 | #endif // BOOST_LEXICAL_CAST_DETAIL_LCAST_UNSIGNED_CONVERTERS_HPP 299 | 300 | -------------------------------------------------------------------------------- /include/boost/lexical_cast/detail/widest_char.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Kevlin Henney, 2000-2005. 2 | // Copyright Alexander Nasonov, 2006-2010. 3 | // Copyright Antony Polukhin, 2011-2025. 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See 6 | // accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt) 8 | // 9 | // what: lexical_cast custom keyword cast 10 | // who: contributed by Kevlin Henney, 11 | // enhanced with contributions from Terje Slettebo, 12 | // with additional fixes and suggestions from Gennaro Prota, 13 | // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, 14 | // Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann, 15 | // Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters 16 | // when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2014 17 | 18 | #ifndef BOOST_LEXICAL_CAST_DETAIL_WIDEST_CHAR_HPP 19 | #define BOOST_LEXICAL_CAST_DETAIL_WIDEST_CHAR_HPP 20 | 21 | #include 22 | #ifdef BOOST_HAS_PRAGMA_ONCE 23 | # pragma once 24 | #endif 25 | 26 | 27 | #include 28 | 29 | namespace boost { namespace detail { 30 | 31 | template 32 | using widest_char = boost::conditional< 33 | (sizeof(TargetChar) > sizeof(SourceChar)) 34 | , TargetChar 35 | , SourceChar 36 | >; 37 | 38 | }} // namespace boost::detail 39 | 40 | #endif // BOOST_LEXICAL_CAST_DETAIL_WIDEST_CHAR_HPP 41 | 42 | -------------------------------------------------------------------------------- /include/boost/lexical_cast/try_lexical_convert.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Kevlin Henney, 2000-2005. 2 | // Copyright Alexander Nasonov, 2006-2010. 3 | // Copyright Antony Polukhin, 2011-2025. 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See 6 | // accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt) 8 | // 9 | // what: lexical_cast custom keyword cast 10 | // who: contributed by Kevlin Henney, 11 | // enhanced with contributions from Terje Slettebo, 12 | // with additional fixes and suggestions from Gennaro Prota, 13 | // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, 14 | // Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann, 15 | // Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters 16 | // when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2014 17 | 18 | #ifndef BOOST_LEXICAL_CAST_TRY_LEXICAL_CONVERT_HPP 19 | #define BOOST_LEXICAL_CAST_TRY_LEXICAL_CONVERT_HPP 20 | 21 | #include 22 | #ifdef BOOST_HAS_PRAGMA_ONCE 23 | # pragma once 24 | #endif 25 | 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | namespace boost { 35 | namespace detail 36 | { 37 | template 38 | using is_arithmetic_and_not_xchars = boost::integral_constant< 39 | bool, 40 | !(boost::detail::is_character::value) && 41 | !(boost::detail::is_character::value) && 42 | boost::is_arithmetic::value && 43 | boost::is_arithmetic::value 44 | >; 45 | } 46 | 47 | namespace conversion { namespace detail { 48 | 49 | template 50 | inline bool try_lexical_convert(const Source& arg, Target& result) 51 | { 52 | static_assert( 53 | !boost::is_volatile::value, 54 | "Boost.LexicalCast does not support volatile input"); 55 | 56 | typedef typename boost::detail::array_to_pointer_decay::type src; 57 | 58 | typedef boost::detail::is_arithmetic_and_not_xchars 59 | shall_we_copy_with_dynamic_check_t; 60 | 61 | typedef typename boost::conditional< 62 | shall_we_copy_with_dynamic_check_t::value, 63 | boost::detail::dynamic_num_converter_impl, 64 | boost::detail::lexical_converter_impl 65 | >::type caster_type; 66 | 67 | return caster_type::try_convert(arg, result); 68 | } 69 | 70 | template 71 | inline bool try_lexical_convert(const CharacterT* chars, std::size_t count, Target& result) 72 | { 73 | static_assert( 74 | boost::detail::is_character::value, 75 | "This overload of try_lexical_convert is meant to be used only with arrays of characters." 76 | ); 77 | return ::boost::conversion::detail::try_lexical_convert( 78 | ::boost::conversion::detail::make_buffer_view(chars, chars + count), 79 | result 80 | ); 81 | } 82 | 83 | }} // namespace conversion::detail 84 | 85 | namespace conversion { 86 | // ADL barrier 87 | using ::boost::conversion::detail::try_lexical_convert; 88 | } 89 | 90 | } // namespace boost 91 | 92 | #endif // BOOST_LEXICAL_CAST_TRY_LEXICAL_CONVERT_HPP 93 | 94 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | Automatic redirection failed, please go to 14 | ../../doc/html/boost_lexical_cast.html 15 | 16 | 17 | -------------------------------------------------------------------------------- /meta/libraries.json: -------------------------------------------------------------------------------- 1 | { 2 | "key": "lexical_cast", 3 | "name": "Lexical Cast", 4 | "authors": [ 5 | "Kevlin Henney" 6 | ], 7 | "description": "General literal text conversions, such as an int represented a string, or vice-versa.", 8 | "category": [ 9 | "Miscellaneous", 10 | "String" 11 | ], 12 | "maintainers": [ 13 | "Antony Polukhin " 14 | ], 15 | "cxxstd": "11" 16 | } 17 | -------------------------------------------------------------------------------- /perf/Jamfile.v2: -------------------------------------------------------------------------------- 1 | #============================================================================== 2 | # Copyright (c) Antony Polukhin, 2012-2024. 3 | # 4 | # Distributed under the Boost Software License, Version 1.0. (See accompanying 5 | # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | #============================================================================== 7 | 8 | # performance tests 9 | import testing ; 10 | import path ; 11 | 12 | path-constant TEST_DIR : . ; 13 | 14 | project performance/test 15 | : source-location ./ 16 | : requirements 17 | # /boost/chrono//boost_chrono 18 | # /boost/system//boost_system 19 | static 20 | freebsd:"-lrt" 21 | linux:"-lrt" 22 | gcc:-fvisibility=hidden 23 | intel-linux:-fvisibility=hidden 24 | sun:-xldscope=hidden 25 | : default-build release 26 | ; 27 | 28 | run performance_test.cpp : $(TEST_DIR) ; 29 | 30 | -------------------------------------------------------------------------------- /perf/performance_test.cpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright Antony Polukhin, 2012-2025. 2 | // Use, modification and distribution are subject to the 3 | // Boost Software License, Version 1.0. (See accompanying file 4 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | // See http://www.boost.org/libs/config for most recent version. 7 | 8 | // 9 | // Testing lexical_cast<> performance 10 | // 11 | 12 | #define BOOST_ERROR_CODE_HEADER_ONLY 13 | #define BOOST_CHRONO_HEADER_ONLY 14 | 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | // File to output data 27 | std::fstream fout; 28 | 29 | namespace boost { 30 | inline std::istream& operator>> (std::istream& in, boost::array& res) { 31 | in >> res.begin(); 32 | return in; 33 | } 34 | } 35 | 36 | template 37 | static inline void test_lexical(const InT& in_val) { 38 | OutT out_val = boost::lexical_cast(in_val); 39 | (void)out_val; 40 | } 41 | 42 | template 43 | static inline void test_ss_constr(const InT& in_val) { 44 | OutT out_val; 45 | std::stringstream ss; 46 | ss << in_val; 47 | if (ss.fail()) throw std::logic_error("descr"); 48 | ss >> out_val; 49 | if (ss.fail()) throw std::logic_error("descr"); 50 | } 51 | 52 | template 53 | static inline void test_ss_constr(const boost::array& in_val) { 54 | OutT out_val; 55 | std::stringstream ss; 56 | ss << in_val.begin(); 57 | if (ss.fail()) throw std::logic_error("descr"); 58 | ss >> out_val; 59 | if (ss.fail()) throw std::logic_error("descr"); 60 | } 61 | 62 | template 63 | static inline void test_ss_noconstr(StringStreamT& ss, const boost::array& in_val) { 64 | OutT out_val; 65 | ss << in_val.begin(); // ss is an instance of std::stringstream 66 | if (ss.fail()) throw std::logic_error("descr"); 67 | ss >> out_val; 68 | if (ss.fail()) throw std::logic_error("descr"); 69 | /* reseting std::stringstream to use it again */ 70 | ss.str(std::string()); 71 | ss.clear(); 72 | } 73 | 74 | template 75 | static inline void test_ss_noconstr(StringStreamT& ss, const InT& in_val) { 76 | OutT out_val; 77 | ss << in_val; // ss is an instance of std::stringstream 78 | if (ss.fail()) throw std::logic_error("descr"); 79 | ss >> out_val; 80 | if (ss.fail()) throw std::logic_error("descr"); 81 | /* reseting std::stringstream to use it again */ 82 | ss.str(std::string()); 83 | ss.clear(); 84 | } 85 | 86 | struct structure_sprintf { 87 | template 88 | static inline void test(BufferT* buffer, const InT& in_val, const char* const conv) { 89 | sprintf(buffer, conv, in_val); 90 | OutT out_val(buffer); 91 | } 92 | 93 | template 94 | static inline void test(BufferT* buffer, const std::string& in_val, const char* const conv) { 95 | sprintf(buffer, conv, in_val.c_str()); 96 | OutT out_val(buffer); 97 | } 98 | 99 | template 100 | static inline void test(BufferT* buffer, std::string_view in_val, const char* const conv) { 101 | sprintf(buffer, conv, in_val.data()); // in_val is zero terminated in this program 102 | OutT out_val(buffer); 103 | } 104 | }; 105 | 106 | struct structure_sscanf { 107 | template 108 | static inline void test(BufferT* /*buffer*/, const boost::array& in_val, const char* const conv) { 109 | OutT out_val; 110 | sscanf(in_val.cbegin(), conv, &out_val); 111 | } 112 | 113 | template 114 | static inline void test(BufferT* /*buffer*/, const InT& in_val, const char* const conv) { 115 | OutT out_val; 116 | sscanf(reinterpret_cast(in_val), conv, &out_val); 117 | } 118 | 119 | template 120 | static inline void test(BufferT* /*buffer*/, const std::string& in_val, const char* const conv) { 121 | OutT out_val; 122 | sscanf(in_val.c_str(), conv, &out_val); 123 | } 124 | 125 | template 126 | static inline void test(BufferT* /*buffer*/, const boost::iterator_range& in_val, const char* const conv) { 127 | OutT out_val; 128 | sscanf(in_val.begin(), conv, &out_val); 129 | } 130 | 131 | template 132 | static inline void test(BufferT* /*buffer*/, std::string_view in_val, const char* const conv) { 133 | OutT out_val; 134 | sscanf(in_val.data(), conv, &out_val); // in_val is zero terminated in this program 135 | } 136 | }; 137 | 138 | struct structure_fake { 139 | template 140 | static inline void test(BufferT* /*buffer*/, const InT& /*in_val*/, const char* const /*conv*/) {} 141 | }; 142 | 143 | static const int fake_test_value = 9999; 144 | 145 | template 146 | static inline void min_fancy_output(T v1, T v2, T v3, T v4) { 147 | const char beg_mark[] = "!!! *"; 148 | const char end_mark[] = "* !!!"; 149 | const char no_mark[] = ""; 150 | 151 | unsigned int res = 4; 152 | if (v1 < v2 && v1 < v3 && v1 < v4) res = 1; 153 | if (v2 < v1 && v2 < v3 && v2 < v4) res = 2; 154 | if (v3 < v1 && v3 < v2 && v3 < v4) res = 3; 155 | 156 | fout << "[ " 157 | << (res == 1 ? beg_mark : no_mark) 158 | ; 159 | 160 | if (v1) fout << v1; 161 | else fout << "<1"; 162 | 163 | fout << (res == 1 ? end_mark : no_mark) 164 | << " ][ " 165 | << (res == 2 ? beg_mark : no_mark) 166 | ; 167 | 168 | if (v2) fout << v2; 169 | else fout << "<1"; 170 | 171 | fout << (res == 2 ? end_mark : no_mark) 172 | << " ][ " 173 | << (res == 3 ? beg_mark : no_mark) 174 | ; 175 | 176 | if (v3) fout << v3; 177 | else fout << "<1"; 178 | 179 | fout << (res == 3 ? end_mark : no_mark) 180 | << " ][ " 181 | << (res == 4 ? beg_mark : no_mark) 182 | ; 183 | 184 | if (!v4) fout << "<1"; 185 | else if (v4 == fake_test_value) fout << "---"; 186 | else fout << v4; 187 | 188 | fout 189 | << (res == 4 ? end_mark : no_mark) 190 | << " ]"; 191 | } 192 | 193 | template 194 | static inline void perf_test_impl(const FromT& in_val, const char* const conv) { 195 | 196 | typedef boost::chrono::steady_clock test_clock; 197 | test_clock::time_point start; 198 | typedef boost::chrono::milliseconds duration_t; 199 | duration_t lexical_cast_time, ss_constr_time, ss_noconstr_time, printf_time; 200 | 201 | start = test_clock::now(); 202 | for (unsigned int i = 0; i < IetartionsCountV; ++i) { 203 | test_lexical(in_val); 204 | test_lexical(in_val); 205 | test_lexical(in_val); 206 | test_lexical(in_val); 207 | } 208 | lexical_cast_time = boost::chrono::duration_cast(test_clock::now() - start); 209 | 210 | 211 | start = test_clock::now(); 212 | for (unsigned int i = 0; i < IetartionsCountV; ++i) { 213 | test_ss_constr(in_val); 214 | test_ss_constr(in_val); 215 | test_ss_constr(in_val); 216 | test_ss_constr(in_val); 217 | } 218 | ss_constr_time = boost::chrono::duration_cast(test_clock::now() - start); 219 | 220 | std::stringstream ss; 221 | start = test_clock::now(); 222 | for (unsigned int i = 0; i < IetartionsCountV; ++i) { 223 | test_ss_noconstr(ss, in_val); 224 | test_ss_noconstr(ss, in_val); 225 | test_ss_noconstr(ss, in_val); 226 | test_ss_noconstr(ss, in_val); 227 | } 228 | ss_noconstr_time = boost::chrono::duration_cast(test_clock::now() - start); 229 | 230 | 231 | char buffer[128]; 232 | start = test_clock::now(); 233 | for (unsigned int i = 0; i < IetartionsCountV; ++i) { 234 | SprintfT::template test(buffer, in_val, conv); 235 | SprintfT::template test(buffer, in_val, conv); 236 | SprintfT::template test(buffer, in_val, conv); 237 | SprintfT::template test(buffer, in_val, conv); 238 | } 239 | printf_time = boost::chrono::duration_cast(test_clock::now() - start); 240 | 241 | min_fancy_output( 242 | lexical_cast_time.count(), 243 | ss_constr_time.count(), 244 | ss_noconstr_time.count(), 245 | boost::is_same::value ? fake_test_value : printf_time.count() 246 | ); 247 | } 248 | 249 | template 250 | static inline void perf_test(const std::string& test_name, const FromT& in_val, const char* const conv) { 251 | const unsigned int ITERATIONSCOUNT = 100000; 252 | fout << " [[ " << test_name << " ]"; 253 | 254 | perf_test_impl(in_val, conv); 255 | 256 | fout << "]\n"; 257 | } 258 | 259 | 260 | template 261 | void string_like_test_set(const std::string& from) { 262 | typedef structure_sscanf ssc_t; 263 | ConverterT conv; 264 | 265 | perf_test(from + "->char", conv("c"), "%c"); 266 | perf_test(from + "->signed char", conv("c"), "%hhd"); 267 | perf_test(from + "->unsigned char", conv("c"), "%hhu"); 268 | 269 | perf_test(from + "->int", conv("100"), "%d"); 270 | perf_test(from + "->short", conv("100"), "%hd"); 271 | perf_test(from + "->long int", conv("100"), "%ld"); 272 | perf_test(from + "->long long", conv("100"), "%lld"); 273 | 274 | perf_test(from + "->unsigned int", conv("100"), "%u"); 275 | perf_test(from + "->unsigned short", conv("100"), "%hu"); 276 | perf_test(from + "->unsigned long int", conv("100"), "%lu"); 277 | perf_test(from + "->unsigned long long", conv("100"), "%llu"); 278 | 279 | // perf_test(from + "->bool", conv("1"), "%"); 280 | 281 | perf_test(from + "->float", conv("1.123"), "%f"); 282 | perf_test(from + "->double", conv("1.123"), "%lf"); 283 | perf_test(from + "->long double", conv("1.123"), "%Lf"); 284 | perf_test, ssc_t>(from + "->array", conv("1.123"), "%s"); 285 | 286 | perf_test(from + "->string", conv("string"), "%Lf"); 287 | perf_test(from + "->container::string" 288 | , conv("string"), "%Lf"); 289 | 290 | } 291 | 292 | struct to_string_conv { 293 | std::string operator()(const char* const c) const { 294 | return c; 295 | } 296 | }; 297 | 298 | struct to_char_conv { 299 | const char* operator()(const char* const c) const { 300 | return c; 301 | } 302 | }; 303 | 304 | struct to_uchar_conv { 305 | const unsigned char* operator()(const char* const c) const { 306 | return reinterpret_cast(c); 307 | } 308 | }; 309 | 310 | 311 | struct to_schar_conv { 312 | const signed char* operator()(const char* const c) const { 313 | return reinterpret_cast(c); 314 | } 315 | }; 316 | 317 | struct to_iterator_range { 318 | boost::iterator_range operator()(const char* const c) const { 319 | return boost::make_iterator_range(c, c + std::strlen(c)); 320 | } 321 | }; 322 | 323 | struct to_array_50 { 324 | boost::array operator()(const char* const c) const { 325 | boost::array ret; 326 | std::strcpy(ret.begin(), c); 327 | return ret; 328 | } 329 | }; 330 | 331 | struct to_string_view { 332 | std::string_view operator()(const char* const c) const { 333 | return std::string_view{c}; 334 | } 335 | }; 336 | 337 | int main(int argc, char** argv) { 338 | BOOST_ASSERT(argc >= 2); 339 | std::string output_path(argv[1]); 340 | output_path += "/results.txt"; 341 | fout.open(output_path.c_str(), std::fstream::in | std::fstream::out | std::fstream::app); 342 | BOOST_ASSERT(fout); 343 | 344 | fout << "[section " << BOOST_COMPILER << "]\n" 345 | << "[table:id Performance Table ( "<< BOOST_COMPILER << ")\n" 346 | << "[[From->To] [lexical_cast] [std::stringstream with construction] " 347 | << "[std::stringstream without construction][scanf/printf]]\n"; 348 | 349 | 350 | // From std::string to ... 351 | string_like_test_set("string"); 352 | 353 | // From ... to std::string 354 | perf_test("string->char", 'c', "%c"); 355 | perf_test("string->signed char", static_cast('c'), "%hhd"); 356 | perf_test("string->unsigned char", static_cast('c'), "%hhu"); 357 | 358 | perf_test("int->string", 100, "%d"); 359 | perf_test("short->string", static_cast(100), "%hd"); 360 | perf_test("long int->string", 100l, "%ld"); 361 | perf_test("long long->string", 100ll, "%lld"); 362 | 363 | perf_test("unsigned int->string", static_cast(100u), "%u"); 364 | perf_test("unsigned short->string", 100u, "%hu"); 365 | perf_test("unsigned long int->string", 100ul, "%lu"); 366 | perf_test("unsigned long long->string", static_cast(100), "%llu"); 367 | 368 | // perf_test("bool->string", std::string("1"), "%"); 369 | 370 | perf_test("float->string", 1.123f, "%f"); 371 | perf_test("double->string", 1.123, "%lf"); 372 | perf_test("long double->string", 1.123L, "%Lf"); 373 | 374 | 375 | string_like_test_set("char*"); 376 | string_like_test_set("unsigned char*"); 377 | string_like_test_set("signed char*"); 378 | string_like_test_set("iterator_range"); 379 | string_like_test_set("std::string_view"); 380 | string_like_test_set("array"); 381 | 382 | perf_test("int->int", 100, ""); 383 | perf_test("float->double", 100.0f, ""); 384 | perf_test("char->signed char", 'c', ""); 385 | 386 | 387 | fout << "]\n" 388 | << "[endsect]\n\n"; 389 | return 0; 390 | } 391 | 392 | 393 | -------------------------------------------------------------------------------- /test/Jamfile.v2: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2001-2003 Douglas Gregor 2 | # Copyright (C) Antony Polukhin, 2011-2024 3 | # 4 | # Distributed under the Boost Software License, Version 1.0. (See accompanying 5 | # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | # 7 | 8 | require-b2 5.0.1 ; 9 | import-search /boost/config/checks ; 10 | import config : requires ; 11 | import testing ; 12 | import feature ; 13 | 14 | project 15 | : requirements 16 | /boost/lexical_cast//boost_lexical_cast 17 | [ requires cxx11_rvalue_references cxx11_static_assert cxx11_template_aliases ] 18 | static 19 | gcc-4.7:-ftrapv 20 | gcc-4.6:-ftrapv 21 | clang:-ftrapv 22 | # default to all warnings on: 23 | all 24 | # set warnings as errors for those compilers we know we get warning free: 25 | gcc:-Wextra 26 | 27 | # Not a lexical_cast related warning: boost/preprocessor/variadic/elem.hpp:29:46: warning: variadic macros are a C99 feature 28 | clang:-Wno-variadic-macros 29 | gcc:-Wno-variadic-macros 30 | 31 | # Not a lexical_cast related warning: boost/mpl/aux_/preprocessed/gcc/greater_equal.hpp:78:1: warning: empty macro arguments are a C99 feature [-Wc99-extensions] 32 | # boost/mpl/iter_fold.hpp:45:1: warning: empty macro arguments are a C99 feature [-Wc99-extensions] 33 | clang:-Wno-c99-extensions 34 | 35 | /boost/array//boost_array 36 | /boost/range//boost_range 37 | /boost/utility//boost_utility 38 | ; 39 | 40 | # Thanks to Steven Watanabe for helping with feature 41 | feature.feature nowchar : on : 42 | composite optional propagated link-incompatible ; 43 | feature.compose on : "/Zc:wchar_t-" ; 44 | 45 | test-suite conversion 46 | : [ run lexical_cast_test.cpp ] 47 | [ run loopback_test.cpp ] 48 | [ run abstract_test.cpp ] 49 | [ run noncopyable_test.cpp ] 50 | [ run vc8_bug_test.cpp ] 51 | [ run implicit_convert.cpp ] 52 | [ run wchars_test.cpp ] 53 | [ run float_types_test.cpp ] 54 | 55 | # Make sure that LexicalCast works the same way as some of the C++ Standard Libraries 56 | [ run float_types_test.cpp : : : BOOST_LEXICAL_CAST_DETAIL_TEST_ON_OLD 57 | msvc:no # could have outdated behavior in some border cases 58 | darwin:no # may have outdated behavior in some border cases 59 | : float_types_non_opt 60 | ] 61 | 62 | [ run inf_nan_test.cpp ] 63 | [ run containers_test.cpp : : : gcc:-Wno-long-long clang:-Wno-long-long ] 64 | [ run empty_input_test.cpp ] 65 | [ run pointers_test.cpp ] 66 | [ compile typedefed_wchar_test.cpp : msvc:on /boost/date_time//boost_date_time ] 67 | [ run typedefed_wchar_test_runtime.cpp : : : msvc:on msvc,stlport:no ] 68 | [ run no_locale_test.cpp : : : BOOST_NO_STD_LOCALE BOOST_LEXICAL_CAST_ASSUME_C_LOCALE ] 69 | [ run no_exceptions_test.cpp : : : off 70 | _HAS_EXCEPTIONS=0 # MSVC stdlib 71 | _STLP_NO_EXCEPTIONS # STLPort 72 | ] 73 | [ run iterator_range_test.cpp ] 74 | [ run string_view_test.cpp ] 75 | [ run arrays_test.cpp : : : 76 | msvc:/wd4512 # assignment operator could not be generated 77 | ] 78 | [ run integral_types_test.cpp ] 79 | [ run stream_detection_test.cpp ] 80 | [ run stream_traits_test.cpp ] 81 | [ compile-fail to_pointer_test.cpp ] 82 | [ compile-fail from_volatile.cpp ] 83 | [ run filesystem_test.cpp /boost/filesystem//boost_filesystem/static ] 84 | [ run try_lexical_convert.cpp ] 85 | ; 86 | 87 | # Assuring that examples compile and run. Adding sources from `example` directory to the `conversion` test suite. 88 | for local p in [ glob ../example/*.cpp ] 89 | { 90 | conversion += [ run $(p) : : : /boost/variant//boost_variant /boost/date_time//boost_date_time ] ; 91 | } 92 | 93 | 94 | -------------------------------------------------------------------------------- /test/abstract_test.cpp: -------------------------------------------------------------------------------- 1 | // Unit test for boost::lexical_cast. 2 | // 3 | // See http://www.boost.org for most recent version, including documentation. 4 | // 5 | // Copyright Sergey Shandar 2005, Alexander Nasonov, 2007. 6 | // Copyright Antony Polukhin, 2023-2025. 7 | // 8 | // Distributed under the Boost 9 | // Software License, Version 1.0. (See accompanying file 10 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 11 | // 12 | // Test abstract class. Bug 1358600: 13 | // http://sf.net/tracker/?func=detail&aid=1358600&group_id=7586&atid=107586 14 | 15 | #include 16 | 17 | #include 18 | 19 | class A 20 | { 21 | public: 22 | virtual void out(std::ostream &) const = 0; 23 | virtual ~A() {} 24 | }; 25 | 26 | class B: public A 27 | { 28 | public: 29 | virtual void out(std::ostream &O) const { O << "B"; } 30 | }; 31 | 32 | std::ostream &operator<<(std::ostream &O, const A &a) 33 | { 34 | a.out(O); 35 | return O; 36 | } 37 | 38 | void test_abstract() 39 | { 40 | const A &a = B(); 41 | BOOST_TEST(boost::lexical_cast(a) == "B"); 42 | } 43 | 44 | int main() 45 | { 46 | test_abstract(); 47 | return boost::report_errors(); 48 | } 49 | 50 | -------------------------------------------------------------------------------- /test/appveyor.yml: -------------------------------------------------------------------------------- 1 | # Use, modification, and distribution are 2 | # subject to the Boost Software License, Version 1.0. (See accompanying 3 | # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 4 | # 5 | # Copyright Antony Polukhin, 2016-2025. 6 | 7 | # 8 | # See https://svn.boost.org/trac/boost/wiki/TravisCoverals for description of this file 9 | # and how it can be used with Boost libraries. 10 | # 11 | # File revision #6 12 | 13 | init: 14 | # boost-local/libs/ folder to put this library into. This may be useful, if you're for example running Travis 15 | # from `Boost.DLL` repo while Boost already has `dll` and with to replace `dll` with content of`Boost.DLL`. 16 | # 17 | # Otherwise just leave the default value - set BOOST_LIBS_FOLDER=%APPVEYOR_PROJECT_NAME% 18 | - set BOOST_LIBS_FOLDER=%APPVEYOR_PROJECT_NAME% 19 | 20 | ############################################################################################################### 21 | # From this point and below code is same for all the Boost libs 22 | ############################################################################################################### 23 | 24 | version: 1.74.{build}-{branch} 25 | 26 | # branches to build 27 | branches: 28 | except: 29 | - gh-pages 30 | 31 | skip_tags: true 32 | 33 | environment: 34 | matrix: 35 | # - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 36 | # TOOLSET: msvc # TODO: clang-win ??? 37 | # ADDRMD: 32,64 38 | # CXXSTD: 17,latest 39 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 40 | TOOLSET: msvc # clang-win has problems with structured bindings - it can not correclty use std::tuple_size 41 | ADDRMD: 32,64 42 | CXXSTD: 17,latest 43 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 44 | TOOLSET: msvc # clang-win has problems with structured bindings - it can not correclty use std::tuple_size 45 | ADDRMD: 32,64 46 | CXXSTD: 17,latest 47 | CXXFLAGS: /permissive- 48 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 49 | TOOLSET: msvc # clang-win has problems with structured bindings - it can not correclty use std::tuple_size 50 | ADDRMD: 32,64 51 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 52 | ADDPATH: C:\cygwin\bin; 53 | TOOLSET: gcc 54 | CXXSTD: 14,1z 55 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 56 | ADDPATH: C:\cygwin64\bin; 57 | TOOLSET: gcc 58 | CXXSTD: 14,1z 59 | # - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 60 | # ADDPATH: C:\mingw\bin; 61 | # TOOLSET: gcc 62 | # CXXSTD: 14,1z 63 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 64 | ADDPATH: C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin; 65 | TOOLSET: gcc 66 | CXXSTD: 14,1z 67 | 68 | before_build: 69 | - set BOOST_BRANCH=develop 70 | - if "%APPVEYOR_REPO_BRANCH%" == "master" set BOOST_BRANCH=master 71 | - echo "Testing %BOOST_LIBS_FOLDER%" 72 | # Cloning Boost libraries (fast nondeep cloning) 73 | - set BOOST=C:/boost-local 74 | - git clone -b %BOOST_BRANCH% --depth 10 https://github.com/boostorg/boost.git %BOOST% 75 | - cd %BOOST% 76 | - git submodule update --init --depth 10 tools/build tools/boostdep 77 | 78 | - echo "rm -rf %BOOST%/libs/%BOOST_LIBS_FOLDER%" 79 | - rm -rf %BOOST%/libs/%BOOST_LIBS_FOLDER% 80 | - mv %APPVEYOR_BUILD_FOLDER% %BOOST%/libs/%BOOST_LIBS_FOLDER% 81 | - python tools/boostdep/depinst/depinst.py --git_args "--depth 10 --jobs 2" -I example -I examples %BOOST_LIBS_FOLDER% 82 | 83 | build_script: 84 | - cmd /c bootstrap 85 | - b2.exe headers 86 | - cd %BOOST%/libs/%BOOST_LIBS_FOLDER%/test 87 | 88 | after_build: 89 | before_test: 90 | test_script: 91 | - PATH=%ADDPATH%%PATH% 92 | - if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD% 93 | - if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD% 94 | - echo "Running command ..\..\..\b2 -j3 toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release" 95 | - ..\..\..\b2.exe -j3 toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release cxxflags="-DBOOST_TRAVISCI_BUILD %CXXFLAGS%" 96 | 97 | after_test: 98 | on_success: 99 | on_failure: 100 | on_finish: 101 | -------------------------------------------------------------------------------- /test/arrays_test.cpp: -------------------------------------------------------------------------------- 1 | // Testing boost::lexical_cast with boost::container::string. 2 | // 3 | // See http://www.boost.org for most recent version, including documentation. 4 | // 5 | // Copyright Antony Polukhin, 2012-2025. 6 | // 7 | // Distributed under the Boost 8 | // Software License, Version 1.0. (See accompanying file 9 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 10 | 11 | #include 12 | 13 | #include 14 | 15 | #include 16 | 17 | using namespace boost; 18 | 19 | #if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) && !defined(_LIBCPP_VERSION) && !defined(BOOST_MSVC) 20 | #define BOOST_LC_RUNU16 21 | #endif 22 | 23 | #if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) && !defined(_LIBCPP_VERSION) && !defined(BOOST_MSVC) 24 | #define BOOST_LC_RUNU32 25 | #endif 26 | 27 | template