mirror of
https://github.com/boostorg/conversion.git
synced 2026-08-09 15:02:09 +02:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c35f326490 | ||
|
|
175c00ea3e |
@@ -1,11 +0,0 @@
|
|||||||
# To get started with Dependabot version updates, you'll need to specify which
|
|
||||||
# package ecosystems to update and where the package manifests are located.
|
|
||||||
# Please see the documentation for all configuration options:
|
|
||||||
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
|
|
||||||
|
|
||||||
version: 2
|
|
||||||
updates:
|
|
||||||
- package-ecosystem: "github-actions" # See documentation for possible values
|
|
||||||
directory: "/" # Location of package manifests
|
|
||||||
schedule:
|
|
||||||
interval: "weekly"
|
|
||||||
@@ -1,182 +0,0 @@
|
|||||||
name: CI
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
- develop
|
|
||||||
- feature/**
|
|
||||||
|
|
||||||
env:
|
|
||||||
UBSAN_OPTIONS: print_stacktrace=1
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
posix:
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- toolset: gcc-14 # Do not remove! It is the only toolset that tests CMake tests down below
|
|
||||||
cxxstd: "03,11,14,17,20"
|
|
||||||
os: ubuntu-24.04
|
|
||||||
- toolset: gcc-12
|
|
||||||
cxxstd: "03,11,14,17,2a"
|
|
||||||
os: ubuntu-22.04
|
|
||||||
cxxflags: "cxxflags=--coverage -fsanitize=address,leak,undefined -fno-sanitize-recover=undefined"
|
|
||||||
linkflags: "linkflags=--coverage -lasan -lubsan"
|
|
||||||
gcov_tool: "gcov-12"
|
|
||||||
- toolset: clang
|
|
||||||
compiler: clang++-14
|
|
||||||
cxxstd: "03,11,14,17,2a"
|
|
||||||
os: ubuntu-22.04
|
|
||||||
|
|
||||||
runs-on: ${{matrix.os}}
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
|
|
||||||
- name: Install packages
|
|
||||||
if: matrix.install
|
|
||||||
run: sudo apt install ${{matrix.install}}
|
|
||||||
|
|
||||||
- name: Setup Boost
|
|
||||||
run: |
|
|
||||||
echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY
|
|
||||||
LIBRARY=${GITHUB_REPOSITORY#*/}
|
|
||||||
echo LIBRARY: $LIBRARY
|
|
||||||
echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV
|
|
||||||
echo GITHUB_BASE_REF: $GITHUB_BASE_REF
|
|
||||||
echo GITHUB_REF: $GITHUB_REF
|
|
||||||
REF=${GITHUB_BASE_REF:-$GITHUB_REF}
|
|
||||||
REF=${REF#refs/heads/}
|
|
||||||
echo REF: $REF
|
|
||||||
BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true
|
|
||||||
echo BOOST_BRANCH: $BOOST_BRANCH
|
|
||||||
cd ..
|
|
||||||
git clone -b $BOOST_BRANCH --depth 10 https://github.com/boostorg/boost.git boost-root
|
|
||||||
cd boost-root
|
|
||||||
git submodule update --init --depth 10 --jobs 2 tools/boostdep tools/inspect libs/filesystem
|
|
||||||
python tools/boostdep/depinst/depinst.py --git_args "--depth 10 --jobs 3" filesystem
|
|
||||||
rm -rf libs/$LIBRARY/*
|
|
||||||
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
|
|
||||||
python tools/boostdep/depinst/depinst.py --include benchmark --include example --include examples --include tools --git_args "--depth 10 --jobs 3" $LIBRARY
|
|
||||||
./bootstrap.sh
|
|
||||||
./b2 -j4 variant=debug tools/inspect
|
|
||||||
|
|
||||||
- name: Run CMake tests
|
|
||||||
if: ${{matrix.toolset == 'gcc-14'}}
|
|
||||||
run: |
|
|
||||||
cd ../boost-root/
|
|
||||||
mkdir __build
|
|
||||||
cd __build
|
|
||||||
cmake -DBUILD_TESTING=1 -DBOOST_INCLUDE_LIBRARIES=conversion -DCMAKE_CXX_COMPILER=g++-14 -DCMAKE_C_COMPILER=gcc-14 ..
|
|
||||||
cmake --build . --target tests
|
|
||||||
ctest --output-on-failure --no-tests=error
|
|
||||||
cd ..
|
|
||||||
rm -rf __build
|
|
||||||
|
|
||||||
- name: Run tests
|
|
||||||
run: |
|
|
||||||
cd ../boost-root
|
|
||||||
./b2 -j3 libs/$LIBRARY/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} variant=debug,release "${{matrix.cxxflags}}" "${{matrix.linkflags}}" "${{matrix.launcher}}"
|
|
||||||
dist/bin/inspect libs/$LIBRARY
|
|
||||||
|
|
||||||
- name: Prepare coverage data
|
|
||||||
if: matrix.gcov_tool
|
|
||||||
run: |
|
|
||||||
mkdir -p $GITHUB_WORKSPACE/coveralls
|
|
||||||
|
|
||||||
echo -e "#!/bin/bash\nexec ${{matrix.gcov_tool}} \"\$@\"" > $GITHUB_WORKSPACE/coveralls/gcov_wrapper.sh
|
|
||||||
chmod +x $GITHUB_WORKSPACE/coveralls/gcov_wrapper.sh
|
|
||||||
wget https://github.com/linux-test-project/lcov/archive/v1.16.zip
|
|
||||||
unzip v1.16.zip
|
|
||||||
LCOV="`pwd`/lcov-1.16/bin/lcov --gcov-tool $GITHUB_WORKSPACE/coveralls/gcov_wrapper.sh"
|
|
||||||
|
|
||||||
echo "$LCOV --directory ../boost-root/bin.v2/libs/$LIBRARY/ --base-directory `pwd`/libs/$LIBRARY/test --capture --output-file $GITHUB_WORKSPACE/coveralls/coverage.info"
|
|
||||||
$LCOV --directory ../boost-root/bin.v2/libs/$LIBRARY/ --base-directory ../boost-root/ --capture --output-file $GITHUB_WORKSPACE/coveralls/coverage.info
|
|
||||||
$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
|
|
||||||
|
|
||||||
cd ../boost-root
|
|
||||||
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'`
|
|
||||||
echo $OTHER_LIBS
|
|
||||||
eval "$LCOV --remove $GITHUB_WORKSPACE/coveralls/coverage.info $OTHER_LIBS -o $GITHUB_WORKSPACE/coveralls/coverage.info"
|
|
||||||
|
|
||||||
- name: Coveralls
|
|
||||||
uses: coverallsapp/github-action@master
|
|
||||||
if: matrix.gcov_tool
|
|
||||||
with:
|
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
path-to-lcov: ./coveralls/coverage.info
|
|
||||||
parallel: true
|
|
||||||
|
|
||||||
windows:
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- toolset: msvc-14.3
|
|
||||||
cxxstd: "14,17,latest"
|
|
||||||
addrmd: 32,64
|
|
||||||
os: windows-2025
|
|
||||||
- toolset: gcc
|
|
||||||
cxxstd: "03,11,14,17,2a"
|
|
||||||
addrmd: 64
|
|
||||||
os: windows-2025
|
|
||||||
|
|
||||||
runs-on: ${{matrix.os}}
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
|
|
||||||
- name: Setup Boost
|
|
||||||
shell: cmd
|
|
||||||
run: |
|
|
||||||
echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY%
|
|
||||||
for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi
|
|
||||||
echo LIBRARY: %LIBRARY%
|
|
||||||
echo LIBRARY=%LIBRARY%>>%GITHUB_ENV%
|
|
||||||
echo GITHUB_BASE_REF: %GITHUB_BASE_REF%
|
|
||||||
echo GITHUB_REF: %GITHUB_REF%
|
|
||||||
if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF%
|
|
||||||
set BOOST_BRANCH=develop
|
|
||||||
for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master
|
|
||||||
echo BOOST_BRANCH: %BOOST_BRANCH%
|
|
||||||
cd ..
|
|
||||||
git clone -b %BOOST_BRANCH% --depth 10 https://github.com/boostorg/boost.git boost-root
|
|
||||||
cd boost-root
|
|
||||||
xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\
|
|
||||||
git submodule update --init tools/boostdep
|
|
||||||
python tools/boostdep/depinst/depinst.py --include benchmark --include example --include examples --include tools --git_args "--jobs 3" %LIBRARY%
|
|
||||||
cmd /c bootstrap
|
|
||||||
|
|
||||||
- name: Run CMake tests
|
|
||||||
if: ${{matrix.toolset == 'msvc-14.3'}}
|
|
||||||
shell: cmd
|
|
||||||
run: |
|
|
||||||
choco install --no-progress ninja
|
|
||||||
call "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvarsall.bat" x64
|
|
||||||
cd ../boost-root/
|
|
||||||
mkdir __build
|
|
||||||
cd __build
|
|
||||||
cmake -DBUILD_TESTING=1 -DBOOST_INCLUDE_LIBRARIES=conversion ..
|
|
||||||
cmake --build . --target tests --config Debug
|
|
||||||
ctest --output-on-failure --no-tests=error -C Debug
|
|
||||||
cd ..
|
|
||||||
rm -rf __build
|
|
||||||
|
|
||||||
- name: Run tests
|
|
||||||
shell: cmd
|
|
||||||
run: |
|
|
||||||
cd ../boost-root
|
|
||||||
b2 -j3 libs/%LIBRARY%/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release
|
|
||||||
|
|
||||||
finish:
|
|
||||||
needs: posix
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Coveralls Finished
|
|
||||||
uses: coverallsapp/github-action@master
|
|
||||||
with:
|
|
||||||
github-token: ${{ secrets.github_token }}
|
|
||||||
parallel-finished: true
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
# Copyright 2019 Mike Dev
|
|
||||||
# Distributed under the Boost Software License, Version 1.0.
|
|
||||||
# See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
|
|
||||||
|
|
||||||
cmake_minimum_required( VERSION 3.5...4.20 )
|
|
||||||
project( boost_conversion VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX )
|
|
||||||
|
|
||||||
add_library( boost_conversion INTERFACE )
|
|
||||||
add_library( Boost::conversion ALIAS boost_conversion )
|
|
||||||
|
|
||||||
target_include_directories( boost_conversion INTERFACE include )
|
|
||||||
|
|
||||||
target_link_libraries( boost_conversion
|
|
||||||
INTERFACE
|
|
||||||
Boost::assert
|
|
||||||
Boost::config
|
|
||||||
Boost::throw_exception
|
|
||||||
)
|
|
||||||
|
|
||||||
if(BUILD_TESTING)
|
|
||||||
add_subdirectory(test)
|
|
||||||
endif()
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
# [Boost.Conversion](https://boost.org/libs/conversion)
|
|
||||||
Boost.Conversion is one of the [Boost C++ Libraries](https://github.com/boostorg). This library improves program safety and clarity by performing otherwise messy conversions.
|
|
||||||
|
|
||||||
### Test results
|
|
||||||
|
|
||||||
@ | Build | Tests coverage | More info
|
|
||||||
----------------|-------------- | -------------- |-----------
|
|
||||||
Develop branch: | [](https://github.com/boostorg/conversion/actions/workflows/ci.yml) [](https://ci.appveyor.com/project/apolukhin/conversion/branch/develop) | [](https://coveralls.io/github/boostorg/conversion?branch=develop) | [details...](https://regression.boost.io/develop/developer/conversion.html)
|
|
||||||
Master branch: | [](https://github.com/boostorg/conversion/actions/workflows/ci.yml) [](https://ci.appveyor.com/project/apolukhin/conversion/branch/master) | [](https://coveralls.io/github/boostorg/conversion?branch=master) | [details...](https://regression.boost.io/master/developer/conversion.html)
|
|
||||||
|
|
||||||
[Latest developer documentation](https://www.boost.org/doc/libs/develop/doc/html/conversion.html)
|
|
||||||
|
|
||||||
### License
|
|
||||||
|
|
||||||
Distributed under the [Boost Software License, Version 1.0](https://boost.org/LICENSE_1_0.txt).
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
# Copyright René Ferdinand Rivera Morell 2023-2024
|
|
||||||
# Distributed under the Boost Software License, Version 1.0.
|
|
||||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
|
||||||
# http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
|
|
||||||
require-b2 5.2 ;
|
|
||||||
|
|
||||||
constant boost_dependencies :
|
|
||||||
/boost/assert//boost_assert
|
|
||||||
/boost/config//boost_config
|
|
||||||
/boost/throw_exception//boost_throw_exception ;
|
|
||||||
|
|
||||||
project /boost/conversion
|
|
||||||
: common-requirements
|
|
||||||
<include>include
|
|
||||||
;
|
|
||||||
|
|
||||||
explicit
|
|
||||||
[ alias boost_conversion : : : : <library>$(boost_dependencies) ]
|
|
||||||
[ alias all : boost_conversion test ]
|
|
||||||
;
|
|
||||||
|
|
||||||
call-if : boost-library conversion
|
|
||||||
;
|
|
||||||
|
|
||||||
@@ -0,0 +1,150 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||||
|
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||||
|
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||||
|
<title>Header boost/cast.hpp Documentation</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body bgcolor="#FFFFFF" text="#000000">
|
||||||
|
|
||||||
|
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="middle" width="277" height="86">Header
|
||||||
|
<a href="../../boost/cast.hpp">boost/cast.hpp</a></h1>
|
||||||
|
|
||||||
|
<h2><a name="Cast Functions">Cast Functions</a></h2>
|
||||||
|
|
||||||
|
<p>The header <a href="../../boost/cast.hpp">boost/cast.hpp</a>
|
||||||
|
provides <a href="#Polymorphic_cast"><b>polymorphic_cast</b></a>, <a href="#Polymorphic_cast"><b>polymorphic_downcast</b></a>,
|
||||||
|
and <a href="#numeric_cast"><b>numeric_cast</b></a> function templates designed
|
||||||
|
to complement the C++ built-in casts.</p>
|
||||||
|
|
||||||
|
<p>The program <a href="cast_test.cpp">cast_test.cpp</a> can be used to
|
||||||
|
verify these function templates work as expected.</p>
|
||||||
|
<h3><a name="Polymorphic_cast">Polymorphic casts</a></h3>
|
||||||
|
<p>Pointers to polymorphic objects (objects of classes which define at least one
|
||||||
|
virtual function) are sometimes downcast or crosscast. Downcasting means
|
||||||
|
casting from a base class to a derived class. Crosscasting means casting
|
||||||
|
across an inheritance hierarchy diagram, such as from one base to the other in a
|
||||||
|
<b>Y</b> diagram hierarchy.</p>
|
||||||
|
<p>Such casts can be done with old-style casts, but this approach is never to be
|
||||||
|
recommended. Old-style casts are sorely lacking in type safety, suffer
|
||||||
|
poor readability, and are difficult to locate with search tools.</p>
|
||||||
|
<p>The C++ built-in <b>static_cast</b> can be used for efficiently downcasting
|
||||||
|
pointers to polymorphic objects, but provides no error detection for the case
|
||||||
|
where the pointer being cast actually points to the wrong derived class. The <b>polymorphic_downcast</b>
|
||||||
|
template retains the efficiency of <b>static_cast</b> for non-debug
|
||||||
|
compilations, but for debug compilations adds safety via an assert() that a <b>dynamic_cast</b>
|
||||||
|
succeeds.</p>
|
||||||
|
<p>The C++ built-in <b>dynamic_cast</b> can be used for downcasts and crosscasts
|
||||||
|
of pointers to polymorphic objects, but error notification in the form of a
|
||||||
|
returned value of 0 is inconvenient to test, or worse yet, easy to forget to
|
||||||
|
test. The <b>polymorphic_cast</b> template performs a <b>dynamic_cast</b>,
|
||||||
|
and throws an exception if the <b>dynamic_cast</b> returns 0.</p>
|
||||||
|
<p>A <b>polymorphic_downcast</b> is preferred when debug-mode tests will cover
|
||||||
|
100% of the object types possibly cast and when non-debug-mode efficiency is an
|
||||||
|
issue. If these two conditions are not present, <b>polymorphic_cast</b> is
|
||||||
|
preferred. It must also be used for crosscasts. It does an assert(
|
||||||
|
dynamic_cast<Derived>(x) == x ) where x is the base pointer, ensuring that
|
||||||
|
not only is a non-zero pointer returned, but also that it correct in the
|
||||||
|
presence of multiple inheritance.<b> Warning:</b>: Because <b>polymorphic_downcast</b>
|
||||||
|
uses assert(), it violates the one definition rule (ODR) if NDEBUG is inconsistently
|
||||||
|
defined across translation units. [See ISO Std 3.2]</p>
|
||||||
|
<p>The C++ built-in <b>dynamic_cast</b> must be used to cast references rather
|
||||||
|
than pointers. It is also the only cast that can be used to check whether
|
||||||
|
a given interface is supported; in that case a return of 0 isn't an error
|
||||||
|
condition.</p>
|
||||||
|
<h3>polymorphic_cast and polymorphic_downcast synopsis</h3>
|
||||||
|
<blockquote>
|
||||||
|
<pre>namespace boost {
|
||||||
|
|
||||||
|
template <class Derived, class Base>
|
||||||
|
inline Derived polymorphic_cast(Base* x);
|
||||||
|
// Throws: std::bad_cast if ( dynamic_cast<Derived>(x) == 0 )
|
||||||
|
// Returns: dynamic_cast<Derived>(x)
|
||||||
|
|
||||||
|
template <class Derived, class Base>
|
||||||
|
inline Derived polymorphic_downcast(Base* x);
|
||||||
|
// Effects: assert( dynamic_cast<Derived>(x) == x );
|
||||||
|
// Returns: static_cast<Derived>(x)
|
||||||
|
|
||||||
|
}</pre>
|
||||||
|
</blockquote>
|
||||||
|
<h3>polymorphic_downcast example</h3>
|
||||||
|
<blockquote>
|
||||||
|
<pre>#include <boost/cast.hpp>
|
||||||
|
...
|
||||||
|
class Fruit { public: virtual ~Fruit(){}; ... };
|
||||||
|
class Banana : public Fruit { ... };
|
||||||
|
...
|
||||||
|
void f( Fruit * fruit ) {
|
||||||
|
// ... logic which leads us to believe it is a Banana
|
||||||
|
Banana * banana = boost::polymorphic_downcast<Banana*>(fruit);
|
||||||
|
...</pre>
|
||||||
|
</blockquote>
|
||||||
|
<h3><a name="numeric_cast">numeric_cast</a></h3>
|
||||||
|
<p>A <b>static_cast</b> or implicit conversion will not
|
||||||
|
detect failure to preserve range for numeric casts. The <b>numeric_cast</b> function
|
||||||
|
templates are similar to <b>static_cast</b> and certain (dubious)
|
||||||
|
implicit conversions in this respect, except that they detect loss of numeric
|
||||||
|
range. An exception is thrown when a runtime value-preservation check fails.</p>
|
||||||
|
<p>The requirements on the argument and result types are:</p>
|
||||||
|
<blockquote>
|
||||||
|
<ul>
|
||||||
|
<li>Both argument and result types are CopyConstructible [ISO Std 20.1.3].</li>
|
||||||
|
<li>Both argument and result types are Numeric, defined by <code>std::numeric_limits<>::is_specialized</code>
|
||||||
|
being true.</li>
|
||||||
|
<li>The argument can be converted to the result type using <b>static_cast</b>.</li>
|
||||||
|
</ul>
|
||||||
|
</blockquote>
|
||||||
|
<h3>numeric_cast synopsis</h3>
|
||||||
|
<blockquote>
|
||||||
|
<pre>namespace boost {
|
||||||
|
|
||||||
|
class bad_numeric_cast : public std::bad_cast {...};
|
||||||
|
|
||||||
|
template<typename Target, typename Source>
|
||||||
|
inline Target numeric_cast(Source arg);
|
||||||
|
// Throws: bad_numeric_cast unless, in converting arg from Source to Target,
|
||||||
|
// there is no loss of negative range, and no underflow, and no
|
||||||
|
// overflow, as determined by std::numeric_limits
|
||||||
|
// Returns: static_cast<Target>(arg)
|
||||||
|
|
||||||
|
}</pre>
|
||||||
|
</blockquote>
|
||||||
|
<h3>numeric_cast example</h3>
|
||||||
|
<blockquote>
|
||||||
|
<pre>#include <boost/cast.hpp>
|
||||||
|
using namespace boost::cast;
|
||||||
|
|
||||||
|
void ariane(double vx)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
unsigned short dx = numeric_cast<unsigned short>(vx);
|
||||||
|
...
|
||||||
|
}</pre>
|
||||||
|
</blockquote>
|
||||||
|
<h3>numeric_cast rationale</h3>
|
||||||
|
<p>The form of the throws condition is specified so that != is not a required
|
||||||
|
operation.</p>
|
||||||
|
<h3>History</h3>
|
||||||
|
<p><b>polymorphic_cast</b> was suggested by Bjarne Stroustrup in "The C++
|
||||||
|
Programming Language".<br>
|
||||||
|
<b>polymorphic_downcast</b> was contributed by <a href="../../people/dave_abrahams.htm">Dave
|
||||||
|
Abrahams</a>.<b><br>
|
||||||
|
numeric_cast</b> was contributed by <a href="../../people/kevlin_henney.htm">Kevlin
|
||||||
|
Henney</a>.</p>
|
||||||
|
<hr>
|
||||||
|
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan
|
||||||
|
-->06 January, 2001<!--webbot bot="Timestamp" endspan i-checksum="38320"
|
||||||
|
--></p>
|
||||||
|
<p>© Copyright boost.org 1999. Permission to copy, use, modify, sell and
|
||||||
|
distribute this document is granted provided this copyright notice appears in
|
||||||
|
all copies. This document is provided "as is" without express or
|
||||||
|
implied warranty, and with no claim as to its suitability for any purpose.</p>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
+154
@@ -0,0 +1,154 @@
|
|||||||
|
// boost utility cast test program -----------------------------------------//
|
||||||
|
|
||||||
|
// (C) Copyright boost.org 1999. Permission to copy, use, modify, sell
|
||||||
|
// and distribute this software is granted provided this copyright
|
||||||
|
// notice appears in all copies. This software is provided "as is" without
|
||||||
|
// express or implied warranty, and with no claim as to its suitability for
|
||||||
|
// any purpose.
|
||||||
|
|
||||||
|
// See http://www.boost.org for most recent version including documentation.
|
||||||
|
|
||||||
|
// Revision History
|
||||||
|
// 20 Jan 01 removed use of <limits> for portability to raw GCC (David Abrahams)
|
||||||
|
// 28 Jun 00 implicit_cast removed (Beman Dawes)
|
||||||
|
// 30 Aug 99 value_cast replaced by numeric_cast
|
||||||
|
// 3 Aug 99 Initial Version
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <climits>
|
||||||
|
#include <cfloat> // for DBL_MAX (Peter Schmid)
|
||||||
|
#include <boost/cast.hpp>
|
||||||
|
|
||||||
|
# if SCHAR_MAX == LONG_MAX
|
||||||
|
# error "This test program doesn't work if SCHAR_MAX == LONG_MAX"
|
||||||
|
# endif
|
||||||
|
|
||||||
|
using namespace boost;
|
||||||
|
using std::cout;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
struct Base
|
||||||
|
{
|
||||||
|
virtual char kind() { return 'B'; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Base2
|
||||||
|
{
|
||||||
|
virtual char kind2() { return '2'; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Derived : public Base, Base2
|
||||||
|
{
|
||||||
|
virtual char kind() { return 'D'; }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main( int argc, char * argv[] )
|
||||||
|
{
|
||||||
|
cout << "Usage: test_casts [n], where n omitted or is:\n"
|
||||||
|
" 1 = execute #1 assert failure (#ifndef NDEBUG)\n"
|
||||||
|
" 2 = execute #2 assert failure (#ifndef NDEBUG)\n"
|
||||||
|
"Example: test_casts 2\n\n";
|
||||||
|
|
||||||
|
# ifdef NDEBUG
|
||||||
|
cout << "NDEBUG is defined\n";
|
||||||
|
# else
|
||||||
|
cout << "NDEBUG is not defined\n";
|
||||||
|
# endif
|
||||||
|
|
||||||
|
cout << "\nBeginning tests...\n";
|
||||||
|
|
||||||
|
// test polymorphic_cast ---------------------------------------------------//
|
||||||
|
|
||||||
|
// tests which should succeed
|
||||||
|
Base * base = new Derived;
|
||||||
|
Base2 * base2 = 0;
|
||||||
|
Derived * derived = 0;
|
||||||
|
derived = polymorphic_downcast<Derived*>( base ); // downcast
|
||||||
|
assert( derived->kind() == 'D' );
|
||||||
|
|
||||||
|
derived = 0;
|
||||||
|
derived = polymorphic_cast<Derived*>( base ); // downcast, throw on error
|
||||||
|
assert( derived->kind() == 'D' );
|
||||||
|
|
||||||
|
base2 = polymorphic_cast<Base2*>( base ); // crosscast
|
||||||
|
assert( base2->kind2() == '2' );
|
||||||
|
|
||||||
|
// tests which should result in errors being detected
|
||||||
|
int err_count = 0;
|
||||||
|
base = new Base;
|
||||||
|
|
||||||
|
if ( argc > 1 && *argv[1] == '1' )
|
||||||
|
{ derived = polymorphic_downcast<Derived*>( base ); } // #1 assert failure
|
||||||
|
|
||||||
|
bool caught_exception = false;
|
||||||
|
try { derived = polymorphic_cast<Derived*>( base ); }
|
||||||
|
catch (std::bad_cast)
|
||||||
|
{ cout<<"caught bad_cast\n"; caught_exception = true; }
|
||||||
|
if ( !caught_exception ) ++err_count;
|
||||||
|
// the following is just so generated code can be inspected
|
||||||
|
if ( derived->kind() == 'B' ) ++err_count;
|
||||||
|
|
||||||
|
// test implicit_cast and numeric_cast -------------------------------------//
|
||||||
|
|
||||||
|
// tests which should succeed
|
||||||
|
long small_value = 1;
|
||||||
|
long small_negative_value = -1;
|
||||||
|
long large_value = LONG_MAX;
|
||||||
|
long large_negative_value = LONG_MIN;
|
||||||
|
signed char c = 0;
|
||||||
|
|
||||||
|
c = large_value; // see if compiler generates warning
|
||||||
|
|
||||||
|
c = numeric_cast<signed char>( small_value );
|
||||||
|
assert( c == 1 );
|
||||||
|
c = 0;
|
||||||
|
c = numeric_cast<signed char>( small_value );
|
||||||
|
assert( c == 1 );
|
||||||
|
c = 0;
|
||||||
|
c = numeric_cast<signed char>( small_negative_value );
|
||||||
|
assert( c == -1 );
|
||||||
|
|
||||||
|
// These tests courtesy of Joe R NWP Swatosh<joe.r.swatosh@usace.army.mil>
|
||||||
|
assert( 0.0f == numeric_cast<float>( 0.0 ) );
|
||||||
|
assert( 0.0 == numeric_cast<double>( 0.0 ) );
|
||||||
|
|
||||||
|
// tests which should result in errors being detected
|
||||||
|
|
||||||
|
caught_exception = false;
|
||||||
|
try { c = numeric_cast<signed char>( large_value ); }
|
||||||
|
catch (bad_numeric_cast)
|
||||||
|
{ cout<<"caught bad_numeric_cast #1\n"; caught_exception = true; }
|
||||||
|
if ( !caught_exception ) ++err_count;
|
||||||
|
|
||||||
|
caught_exception = false;
|
||||||
|
try { c = numeric_cast<signed char>( large_negative_value ); }
|
||||||
|
catch (bad_numeric_cast)
|
||||||
|
{ cout<<"caught bad_numeric_cast #2\n"; caught_exception = true; }
|
||||||
|
if ( !caught_exception ) ++err_count;
|
||||||
|
|
||||||
|
unsigned long ul;
|
||||||
|
caught_exception = false;
|
||||||
|
try { ul = numeric_cast<unsigned long>( large_negative_value ); }
|
||||||
|
catch (bad_numeric_cast)
|
||||||
|
{ cout<<"caught bad_numeric_cast #3\n"; caught_exception = true; }
|
||||||
|
if ( !caught_exception ) ++err_count;
|
||||||
|
|
||||||
|
caught_exception = false;
|
||||||
|
try { ul = numeric_cast<unsigned long>( small_negative_value ); }
|
||||||
|
catch (bad_numeric_cast)
|
||||||
|
{ cout<<"caught bad_numeric_cast #4\n"; caught_exception = true; }
|
||||||
|
if ( !caught_exception ) ++err_count;
|
||||||
|
|
||||||
|
caught_exception = false;
|
||||||
|
try { numeric_cast<int>( DBL_MAX ); }
|
||||||
|
catch (bad_numeric_cast)
|
||||||
|
{ cout<<"caught bad_numeric_cast #5\n"; caught_exception = true; }
|
||||||
|
if ( !caught_exception ) ++err_count;
|
||||||
|
|
||||||
|
cout << err_count << " errors detected\nTest "
|
||||||
|
<< (err_count==0 ? "passed\n" : "failed\n");
|
||||||
|
return err_count;
|
||||||
|
} // main
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
# Copyright (c) 2016 Mikhail Maximov <vigorous.activity -at- gmail.com>
|
|
||||||
|
|
||||||
# Distributed under the Boost Software License, Version 1.0.
|
|
||||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
|
||||||
# http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
|
|
||||||
project doc/conversion ;
|
|
||||||
|
|
||||||
using quickbook ;
|
|
||||||
import boostbook ;
|
|
||||||
|
|
||||||
xml conversion : conversion.qbk ;
|
|
||||||
boostbook standalone
|
|
||||||
:
|
|
||||||
conversion
|
|
||||||
:
|
|
||||||
<xsl:param>boost.root=../../../..
|
|
||||||
# File name of HTML output:
|
|
||||||
<xsl:param>root.filename=conversion
|
|
||||||
# How far down we chunk nested sections, basically all of them:
|
|
||||||
<xsl:param>chunk.section.depth=0
|
|
||||||
# Don't put the first section on the same page as the TOC:
|
|
||||||
<xsl:param>chunk.first.sections=0
|
|
||||||
# How far down sections get TOC's
|
|
||||||
<xsl:param>toc.section.depth=2
|
|
||||||
# Max depth in each TOC:
|
|
||||||
<xsl:param>toc.max.depth=2
|
|
||||||
# How far down we go with TOC's
|
|
||||||
<xsl:param>generate.section.toc.level=0
|
|
||||||
|
|
||||||
<xsl:param>generate.manifest=0
|
|
||||||
;
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
alias boostdoc : conversion ;
|
|
||||||
explicit boostdoc ;
|
|
||||||
alias boostrelease ;
|
|
||||||
explicit boostrelease ;
|
|
||||||
@@ -1,215 +0,0 @@
|
|||||||
[/
|
|
||||||
Copyright 2016 Mikhail Maximov.
|
|
||||||
Copyright Antony Polukhin, 2020-2026.
|
|
||||||
|
|
||||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)
|
|
||||||
]
|
|
||||||
|
|
||||||
[article The Conversion Library
|
|
||||||
[quickbook 1.6]
|
|
||||||
[compatibility-mode 1.5]
|
|
||||||
[id conversion]
|
|
||||||
[version 1.7]
|
|
||||||
[authors [Stroustrup, Bjarne], [Abrahams, Dave], [Rasin, Boris], [Polukhin, Antony]]
|
|
||||||
[copyright 2001 Beman Dawes, 2014-2026 Antony Polukhin]
|
|
||||||
[license
|
|
||||||
Distributed under the Boost Software License, Version 1.0.
|
|
||||||
(See accompanying file LICENSE_1_0.txt or copy at
|
|
||||||
[@http://www.boost.org/LICENSE_1_0.txt])
|
|
||||||
]
|
|
||||||
[source-mode c++]
|
|
||||||
]
|
|
||||||
|
|
||||||
[/ QuickBook Document version 1.5 ]
|
|
||||||
[/ Dec, 2016 ]
|
|
||||||
|
|
||||||
[section Description]
|
|
||||||
|
|
||||||
The Conversion Library improves program safety and clarity by performing
|
|
||||||
otherwise messy conversions. It includes cast-style function templates designed
|
|
||||||
to complement the C++ Standard's built-in casts.
|
|
||||||
|
|
||||||
To reduce coupling, the Boost Conversion Library is supplied by several headers:
|
|
||||||
|
|
||||||
# The [@boost:boost/polymorphic_cast.hpp boost/polymorphic_cast.hpp] header
|
|
||||||
provides [link polymorphic_cast `polymorphic_cast<>`] and
|
|
||||||
[link polymorphic_downcast `polymorphic_downcast<>`]
|
|
||||||
to perform safe casting between polymorphic types.
|
|
||||||
# The [@boost:boost/polymorphic_pointer_cast.hpp boost/polymorphic_pointer_cast.hpp] header
|
|
||||||
provides [link polymorphic_pointer_cast `polymorphic_pointer_cast<>`] and
|
|
||||||
[link polymorphic_pointer_cast `polymorphic_pointer_downcast<>`]
|
|
||||||
# The [@boost:boost/implicit_cast.hpp boost/implicit_cast.hpp] header provides `implicit_cast<>`
|
|
||||||
to perform implicit casts only (no down-cast, no void*->T*, no U->T if T has only explicit constructors for U).
|
|
||||||
|
|
||||||
[endsect]
|
|
||||||
|
|
||||||
[section Polymorphic casts]
|
|
||||||
Pointers to polymorphic objects (objects of classes which define at
|
|
||||||
least one virtual function) are sometimes downcast or crosscast.
|
|
||||||
Downcasting means casting from a base class to a derived class.
|
|
||||||
Crosscasting means casting across an inheritance hierarchy diagram, such
|
|
||||||
as from one base to the other in a [^Y] diagram hierarchy.
|
|
||||||
|
|
||||||
Such casts can be done with old-style casts, but this approach is
|
|
||||||
never to be recommended. Old-style casts are sorely lacking in type
|
|
||||||
safety, suffer poor readability, and are difficult to locate with search
|
|
||||||
tools.
|
|
||||||
|
|
||||||
[#polymorphic_downcast]
|
|
||||||
[section polymorphic_downcast]
|
|
||||||
|
|
||||||
The C++ built-in `static_cast` can be used for efficiently
|
|
||||||
downcasting pointers to polymorphic objects, but provides no error
|
|
||||||
detection for the case where the pointer being cast actually points to
|
|
||||||
the wrong derived class. The `polymorphic_downcast` template retains
|
|
||||||
the efficiency of `static_cast` for non-debug compilations, but for
|
|
||||||
debug compilations adds safety via an `assert()` that a `dynamic_cast`
|
|
||||||
succeeds.
|
|
||||||
|
|
||||||
A `polymorphic_downcast` should be used for
|
|
||||||
downcasts that you are certain should succeed. Error checking is
|
|
||||||
only performed in translation units where `NDEBUG` is
|
|
||||||
not defined, via
|
|
||||||
```
|
|
||||||
assert( dynamic_cast<Derived>(x) == x )
|
|
||||||
```
|
|
||||||
where `x` is the source pointer. This approach
|
|
||||||
ensures that not only is a non-zero pointer returned, but also
|
|
||||||
that it is correct in the presence of multiple inheritance.
|
|
||||||
Attempts to crosscast using `polymorphic_downcast` will
|
|
||||||
fail to compile.
|
|
||||||
|
|
||||||
[warning Because `polymorphic_downcast` uses `assert()`, it
|
|
||||||
violates the One Definition Rule (ODR) if `NDEBUG` is inconsistently
|
|
||||||
defined across translation units. See ISO Std 3.2]
|
|
||||||
|
|
||||||
[h4 Example:]
|
|
||||||
```
|
|
||||||
#include <boost/polymorphic_cast.hpp>
|
|
||||||
...
|
|
||||||
class Fruit { public: virtual ~Fruit(){}; ... };
|
|
||||||
class Banana : public Fruit { ... };
|
|
||||||
...
|
|
||||||
void f( Fruit * fruit ) {
|
|
||||||
// ... logic which leads us to believe it is a Banana
|
|
||||||
Banana * banana = boost::polymorphic_downcast<Banana*>(fruit);
|
|
||||||
...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
[endsect]
|
|
||||||
|
|
||||||
[#polymorphic_cast]
|
|
||||||
[section polymorphic_cast]
|
|
||||||
|
|
||||||
The C++ built-in `dynamic_cast` can be used for downcasts and
|
|
||||||
crosscasts of pointers to polymorphic objects, but error notification in
|
|
||||||
the form of a returned value of 0 is inconvenient to test, or worse yet,
|
|
||||||
easy to forget to test. The throwing form of `dynamic_cast`, which
|
|
||||||
works on references, can be used on pointers through the ugly expression
|
|
||||||
`&dynamic_cast<T&>(*p)`, which causes undefined
|
|
||||||
behavior if `p` is `0`. The `polymorphic_cast`
|
|
||||||
template performs a `dynamic_cast` on a pointer, and throws an
|
|
||||||
exception if the `dynamic_cast` returns 0.
|
|
||||||
|
|
||||||
For crosscasts, or when the success of a cast can only be known at runtime,
|
|
||||||
or when efficiency is not important, `polymorphic_cast` is preferred.
|
|
||||||
|
|
||||||
The C++ built-in `dynamic_cast` must be used to cast references rather than pointers.
|
|
||||||
It is also the only cast that can be used to check whether a given interface is supported; in that case a return of 0 isn't an error condition.
|
|
||||||
|
|
||||||
[endsect]
|
|
||||||
|
|
||||||
|
|
||||||
[#polymorphic_pointer_cast]
|
|
||||||
[section polymorphic_pointer_cast]
|
|
||||||
While `polymorphic_downcast` and `polymorphic_cast` work with built-in pointer types only,
|
|
||||||
`polymorphic_pointer_downcast` and `polymorphic_pointer_cast` are more generic versions
|
|
||||||
with support for any pointer type for which the following expressions would be valid:
|
|
||||||
|
|
||||||
For `polymorphic_pointer_downcast`:
|
|
||||||
```
|
|
||||||
static_pointer_cast<Derived>(p);
|
|
||||||
dynamic_pointer_cast<Derived>(p);
|
|
||||||
```
|
|
||||||
For `polymorphic_pointer_cast`:
|
|
||||||
```
|
|
||||||
dynamic_pointer_cast<Derived>(p);
|
|
||||||
!p; // conversion to bool with negation
|
|
||||||
```
|
|
||||||
|
|
||||||
This includes C++ built-in pointers, `std::shared_ptr`,
|
|
||||||
`boost::shared_ptr`, `boost::intrusive_ptr`, etc.
|
|
||||||
|
|
||||||
|
|
||||||
[h4 Example:]
|
|
||||||
```
|
|
||||||
#include <boost/polymorphic_pointer_cast.hpp>
|
|
||||||
|
|
||||||
class Fruit { public: virtual ~Fruit(){} };
|
|
||||||
class Banana : public Fruit {};
|
|
||||||
|
|
||||||
// Use one of these:
|
|
||||||
using FruitPtr = Fruit*;
|
|
||||||
using FruitPtr = std::shared_ptr<Fruit>;
|
|
||||||
using FruitPtr = boost::shared_ptr<Fruit>;
|
|
||||||
using FruitPtr = boost::intrusive_ptr<Fruit>;
|
|
||||||
|
|
||||||
void f(FruitPtr fruit) {
|
|
||||||
// ... logic which leads us to believe it is a banana
|
|
||||||
auto banana = boost::polymorphic_pointer_downcast<Banana>(fruit);
|
|
||||||
...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
[endsect]
|
|
||||||
|
|
||||||
[endsect]
|
|
||||||
|
|
||||||
[section Synopsis]
|
|
||||||
```
|
|
||||||
namespace boost {
|
|
||||||
|
|
||||||
// Throws: std::bad_cast if ( dynamic_cast<Derived>(x) == 0 )
|
|
||||||
// Returns: dynamic_cast<Derived>(x)
|
|
||||||
template <class Derived, class Base>
|
|
||||||
constexpr Derived polymorphic_cast(Base* x);
|
|
||||||
|
|
||||||
// Effects: assert( dynamic_cast<Derived>(x) == x );
|
|
||||||
// Returns: static_cast<Derived>(x)
|
|
||||||
template <class Derived, class Base>
|
|
||||||
constexpr Derived polymorphic_downcast(Base* x);
|
|
||||||
|
|
||||||
// Effects: assert( dynamic_cast<Derived>(&x) == &x );
|
|
||||||
// Returns: static_cast<Derived>(x)
|
|
||||||
template <class Derived, class Base>
|
|
||||||
constexpr Derived polymorphic_downcast(Base& x);
|
|
||||||
|
|
||||||
// Throws: std::bad_cast if ( dynamic_pointer_cast<Derived>(x) == 0 )
|
|
||||||
// Returns: dynamic_pointer_cast<Derived>(x)
|
|
||||||
template <class Derived, class Base>
|
|
||||||
inline auto polymorphic_pointer_cast(Base x);
|
|
||||||
|
|
||||||
// Effects: assert( dynamic_pointer_cast<Derived>(x) == x );
|
|
||||||
// Returns: static_pointer_cast<Derived>(x)
|
|
||||||
template <class Derived, class Base>
|
|
||||||
inline auto polymorphic_pointer_downcast(Base x);
|
|
||||||
|
|
||||||
}
|
|
||||||
```
|
|
||||||
[endsect]
|
|
||||||
|
|
||||||
|
|
||||||
[section History]
|
|
||||||
`polymorphic_cast` was suggested by Bjarne Stroustrup in "The C++ Programming Language".
|
|
||||||
|
|
||||||
`polymorphic_downcast` was contributed by [@http://www.boost.org/people/dave_abrahams.htm Dave Abrahams].
|
|
||||||
|
|
||||||
`polymorphic_pointer_downcast` was contributed by [@http://www.boost.org/people/boris_rasin.htm Boris Rasin]
|
|
||||||
and `polymorphic_pointer_cast` by Antony Polukhin.
|
|
||||||
|
|
||||||
`polymorphic_downcast` overload for references was contributed by Julien Delacroix.
|
|
||||||
|
|
||||||
An old `numeric_cast` that was contributed by [@http://www.boost.org/people/kevlin_henney.htm Kevlin Henney]
|
|
||||||
is now superseded by the [@boost:numeric_conversion/doc/html/html/boost_numericconversion/improved_numeric_cast__.html Boost Numeric Conversion Library]
|
|
||||||
[endsect]
|
|
||||||
@@ -0,0 +1,340 @@
|
|||||||
|
// boost cast.hpp header file ----------------------------------------------//
|
||||||
|
|
||||||
|
// (C) Copyright boost.org 1999. Permission to copy, use, modify, sell
|
||||||
|
// and distribute this software is granted provided this copyright
|
||||||
|
// notice appears in all copies. This software is provided "as is" without
|
||||||
|
// express or implied warranty, and with no claim as to its suitability for
|
||||||
|
// any purpose.
|
||||||
|
|
||||||
|
// See http://www.boost.org for most recent version including documentation.
|
||||||
|
|
||||||
|
// Revision History
|
||||||
|
// 02 Apr 01 Removed BOOST_NO_LIMITS workarounds and included
|
||||||
|
// <boost/limits.hpp> instead (the workaround did not
|
||||||
|
// actually compile when BOOST_NO_LIMITS was defined in
|
||||||
|
// any case, so we loose nothing). (John Maddock)
|
||||||
|
// 21 Jan 01 Undid a bug I introduced yesterday. numeric_cast<> never
|
||||||
|
// worked with stock GCC; trying to get it to do that broke
|
||||||
|
// vc-stlport.
|
||||||
|
// 20 Jan 01 Moved BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS to config.hpp.
|
||||||
|
// Removed unused BOOST_EXPLICIT_TARGET macro. Moved
|
||||||
|
// boost::detail::type to boost/type.hpp. Made it compile with
|
||||||
|
// stock gcc again (Dave Abrahams)
|
||||||
|
// 29 Nov 00 Remove nested namespace cast, cleanup spacing before Formal
|
||||||
|
// Review (Beman Dawes)
|
||||||
|
// 19 Oct 00 Fix numeric_cast for floating-point types (Dave Abrahams)
|
||||||
|
// 15 Jul 00 Suppress numeric_cast warnings for GCC, Borland and MSVC
|
||||||
|
// (Dave Abrahams)
|
||||||
|
// 30 Jun 00 More MSVC6 wordarounds. See comments below. (Dave Abrahams)
|
||||||
|
// 28 Jun 00 Removed implicit_cast<>. See comment below. (Beman Dawes)
|
||||||
|
// 27 Jun 00 More MSVC6 workarounds
|
||||||
|
// 15 Jun 00 Add workarounds for MSVC6
|
||||||
|
// 2 Feb 00 Remove bad_numeric_cast ";" syntax error (Doncho Angelov)
|
||||||
|
// 26 Jan 00 Add missing throw() to bad_numeric_cast::what(0 (Adam Levar)
|
||||||
|
// 29 Dec 99 Change using declarations so usages in other namespaces work
|
||||||
|
// correctly (Dave Abrahams)
|
||||||
|
// 23 Sep 99 Change polymorphic_downcast assert to also detect M.I. errors
|
||||||
|
// as suggested Darin Adler and improved by Valentin Bonnard.
|
||||||
|
// 2 Sep 99 Remove controversial asserts, simplify, rename.
|
||||||
|
// 30 Aug 99 Move to cast.hpp, replace value_cast with numeric_cast,
|
||||||
|
// place in nested namespace.
|
||||||
|
// 3 Aug 99 Initial version
|
||||||
|
|
||||||
|
#ifndef BOOST_CAST_HPP
|
||||||
|
#define BOOST_CAST_HPP
|
||||||
|
|
||||||
|
# include <boost/config.hpp>
|
||||||
|
# include <cassert>
|
||||||
|
# include <typeinfo>
|
||||||
|
# include <boost/type.hpp>
|
||||||
|
# include <boost/limits.hpp>
|
||||||
|
|
||||||
|
// It has been demonstrated numerous times that MSVC 6.0 fails silently at link
|
||||||
|
// time if you use a template function which has template parameters that don't
|
||||||
|
// appear in the function's argument list.
|
||||||
|
//
|
||||||
|
// TODO: Add this to config.hpp?
|
||||||
|
# if defined(BOOST_MSVC) && BOOST_MSVC <= 1200 // 1200 = VC6
|
||||||
|
# define BOOST_EXPLICIT_DEFAULT_TARGET , ::boost::type<Target>* = 0
|
||||||
|
# else
|
||||||
|
# define BOOST_EXPLICIT_DEFAULT_TARGET
|
||||||
|
# endif
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
// See the documentation for descriptions of how to choose between
|
||||||
|
// static_cast<>, dynamic_cast<>, polymorphic_cast<> and polymorphic_downcast<>
|
||||||
|
|
||||||
|
// polymorphic_cast --------------------------------------------------------//
|
||||||
|
|
||||||
|
// Runtime checked polymorphic downcasts and crosscasts.
|
||||||
|
// Suggested in The C++ Programming Language, 3rd Ed, Bjarne Stroustrup,
|
||||||
|
// section 15.8 exercise 1, page 425.
|
||||||
|
|
||||||
|
template <class Target, class Source>
|
||||||
|
inline Target polymorphic_cast(Source* x BOOST_EXPLICIT_DEFAULT_TARGET)
|
||||||
|
{
|
||||||
|
Target tmp = dynamic_cast<Target>(x);
|
||||||
|
if ( tmp == 0 ) throw std::bad_cast();
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// polymorphic_downcast ----------------------------------------------------//
|
||||||
|
|
||||||
|
// assert() checked polymorphic downcast. Crosscasts prohibited.
|
||||||
|
|
||||||
|
// WARNING: Because this cast uses assert(), it violates the One Definition
|
||||||
|
// Rule if NDEBUG is inconsistently defined across translation units.
|
||||||
|
|
||||||
|
// Contributed by Dave Abrahams
|
||||||
|
|
||||||
|
template <class Target, class Source>
|
||||||
|
inline Target polymorphic_downcast(Source* x BOOST_EXPLICIT_DEFAULT_TARGET)
|
||||||
|
{
|
||||||
|
assert( dynamic_cast<Target>(x) == x ); // detect logic error
|
||||||
|
return static_cast<Target>(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
// implicit_cast -----------------------------------------------------------//
|
||||||
|
//
|
||||||
|
// Removed due to uncertain purpose. Use either numeric_cast (see below)
|
||||||
|
// or static_cast according to the need.
|
||||||
|
|
||||||
|
// numeric_cast and related exception --------------------------------------//
|
||||||
|
|
||||||
|
// Contributed by Kevlin Henney
|
||||||
|
|
||||||
|
// bad_numeric_cast --------------------------------------------------------//
|
||||||
|
|
||||||
|
// exception used to indicate runtime numeric_cast failure
|
||||||
|
class bad_numeric_cast : public std::bad_cast
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructors, destructors and assignment operator defaulted
|
||||||
|
|
||||||
|
// function inlined for brevity and consistency with rest of library
|
||||||
|
virtual const char *what() const throw()
|
||||||
|
{
|
||||||
|
return "bad numeric cast: loss of range in numeric_cast";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// numeric_cast ------------------------------------------------------------//
|
||||||
|
|
||||||
|
#if !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) || defined(BOOST_SGI_CPP_LIMITS)
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template <bool is_signed> struct numeric_min_select;
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct numeric_min_select<true>
|
||||||
|
{
|
||||||
|
template <class T>
|
||||||
|
struct limits : std::numeric_limits<T>
|
||||||
|
{
|
||||||
|
static inline T min()
|
||||||
|
# ifndef __GNUC__ // bug workaround courtesy Jens Maurer
|
||||||
|
{
|
||||||
|
return std::numeric_limits<T>::min() >= 0
|
||||||
|
// unary minus causes integral promotion, thus the static_cast<>
|
||||||
|
? static_cast<T>(-std::numeric_limits<T>::max())
|
||||||
|
: std::numeric_limits<T>::min();
|
||||||
|
}
|
||||||
|
# else
|
||||||
|
;
|
||||||
|
# endif
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# ifdef __GNUC__ // bug workaround courtesy Jens Maurer
|
||||||
|
template<> template<class T>
|
||||||
|
inline T numeric_min_select<true>::limits<T>::min()
|
||||||
|
{
|
||||||
|
return std::numeric_limits<T>::min() >= 0
|
||||||
|
// unary minus causes integral promotion, thus the static_cast<>
|
||||||
|
? static_cast<T>(-std::numeric_limits<T>::max())
|
||||||
|
: std::numeric_limits<T>::min();
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct numeric_min_select<false>
|
||||||
|
{
|
||||||
|
template <class T>
|
||||||
|
struct limits : std::numeric_limits<T> {};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Move to namespace boost in utility.hpp?
|
||||||
|
template <class T>
|
||||||
|
struct fixed_numeric_limits
|
||||||
|
: public numeric_min_select<
|
||||||
|
std::numeric_limits<T>::is_signed
|
||||||
|
>::template limits<T>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
// less_than_type_min -
|
||||||
|
// x_is_signed should be numeric_limits<X>::is_signed
|
||||||
|
// y_is_signed should be numeric_limits<Y>::is_signed
|
||||||
|
// y_min should be numeric_limits<Y>::min()
|
||||||
|
//
|
||||||
|
// check(x, y_min) returns true iff x < y_min without invoking comparisons
|
||||||
|
// between signed and unsigned values.
|
||||||
|
//
|
||||||
|
// "poor man's partial specialization" is in use here.
|
||||||
|
template <bool x_is_signed, bool y_is_signed>
|
||||||
|
struct less_than_type_min
|
||||||
|
{
|
||||||
|
template <class X, class Y>
|
||||||
|
static bool check(X x, Y y_min)
|
||||||
|
{ return x < y_min; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct less_than_type_min<false, true>
|
||||||
|
{
|
||||||
|
template <class X, class Y>
|
||||||
|
static bool check(X, Y)
|
||||||
|
{ return false; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct less_than_type_min<true, false>
|
||||||
|
{
|
||||||
|
template <class X, class Y>
|
||||||
|
static bool check(X x, Y)
|
||||||
|
{ return x < 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// greater_than_type_max -
|
||||||
|
// same_sign should be:
|
||||||
|
// numeric_limits<X>::is_signed == numeric_limits<Y>::is_signed
|
||||||
|
// y_max should be numeric_limits<Y>::max()
|
||||||
|
//
|
||||||
|
// check(x, y_max) returns true iff x > y_max without invoking comparisons
|
||||||
|
// between signed and unsigned values.
|
||||||
|
//
|
||||||
|
// "poor man's partial specialization" is in use here.
|
||||||
|
template <bool same_sign, bool x_is_signed>
|
||||||
|
struct greater_than_type_max;
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct greater_than_type_max<true, true>
|
||||||
|
{
|
||||||
|
template <class X, class Y>
|
||||||
|
static inline bool check(X x, Y y_max)
|
||||||
|
{ return x > y_max; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct greater_than_type_max<false, true>
|
||||||
|
{
|
||||||
|
// What does the standard say about this? I think it's right, and it
|
||||||
|
// will work with every compiler I know of.
|
||||||
|
template <class X, class Y>
|
||||||
|
static inline bool check(X x, Y)
|
||||||
|
{ return x >= 0 && static_cast<X>(static_cast<Y>(x)) != x; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct greater_than_type_max<true, false>
|
||||||
|
{
|
||||||
|
template <class X, class Y>
|
||||||
|
static inline bool check(X x, Y y_max)
|
||||||
|
{ return x > y_max; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct greater_than_type_max<false, false>
|
||||||
|
{
|
||||||
|
// What does the standard say about this? I think it's right, and it
|
||||||
|
// will work with every compiler I know of.
|
||||||
|
template <class X, class Y>
|
||||||
|
static inline bool check(X x, Y)
|
||||||
|
{ return static_cast<X>(static_cast<Y>(x)) != x; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#else // use #pragma hacks if available
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
# if BOOST_MSVC
|
||||||
|
# pragma warning(push)
|
||||||
|
# pragma warning(disable : 4018)
|
||||||
|
# pragma warning(disable : 4146)
|
||||||
|
#elif defined(__BORLANDC__)
|
||||||
|
# pragma option push -w-8041
|
||||||
|
# endif
|
||||||
|
|
||||||
|
// Move to namespace boost in utility.hpp?
|
||||||
|
template <class T>
|
||||||
|
struct fixed_numeric_limits : public std::numeric_limits<T>
|
||||||
|
{
|
||||||
|
static inline T min()
|
||||||
|
{
|
||||||
|
return std::numeric_limits<T>::is_signed && std::numeric_limits<T>::min() >= 0
|
||||||
|
? T(-std::numeric_limits<T>::max()) : std::numeric_limits<T>::min();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
# if BOOST_MSVC
|
||||||
|
# pragma warning(pop)
|
||||||
|
#elif defined(__BORLANDC__)
|
||||||
|
# pragma option pop
|
||||||
|
# endif
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template<typename Target, typename Source>
|
||||||
|
inline Target numeric_cast(Source arg BOOST_EXPLICIT_DEFAULT_TARGET)
|
||||||
|
{
|
||||||
|
// typedefs abbreviating respective trait classes
|
||||||
|
typedef std::numeric_limits<Source> arg_traits;
|
||||||
|
typedef detail::fixed_numeric_limits<Target> result_traits;
|
||||||
|
|
||||||
|
#if !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) || defined(BOOST_SGI_CPP_LIMITS)
|
||||||
|
// typedefs that act as compile time assertions
|
||||||
|
// (to be replaced by boost compile time assertions
|
||||||
|
// as and when they become available and are stable)
|
||||||
|
typedef bool argument_must_be_numeric[arg_traits::is_specialized];
|
||||||
|
typedef bool result_must_be_numeric[result_traits::is_specialized];
|
||||||
|
|
||||||
|
const bool arg_is_signed = arg_traits::is_signed;
|
||||||
|
const bool result_is_signed = result_traits::is_signed;
|
||||||
|
const bool same_sign = arg_is_signed == result_is_signed;
|
||||||
|
|
||||||
|
if (less_than_type_min<arg_is_signed, result_is_signed>::check(arg, result_traits::min())
|
||||||
|
|| greater_than_type_max<same_sign, arg_is_signed>::check(arg, result_traits::max())
|
||||||
|
)
|
||||||
|
|
||||||
|
#else // We need to use #pragma hacks if available
|
||||||
|
|
||||||
|
# if BOOST_MSVC
|
||||||
|
# pragma warning(push)
|
||||||
|
# pragma warning(disable : 4018)
|
||||||
|
#elif defined(__BORLANDC__)
|
||||||
|
#pragma option push -w-8012
|
||||||
|
# endif
|
||||||
|
if ((arg < 0 && !result_traits::is_signed) // loss of negative range
|
||||||
|
|| (arg_traits::is_signed && arg < result_traits::min()) // underflow
|
||||||
|
|| arg > result_traits::max()) // overflow
|
||||||
|
# if BOOST_MSVC
|
||||||
|
# pragma warning(pop)
|
||||||
|
#elif defined(__BORLANDC__)
|
||||||
|
#pragma option pop
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
throw bad_numeric_cast();
|
||||||
|
}
|
||||||
|
return static_cast<Target>(arg);
|
||||||
|
} // numeric_cast
|
||||||
|
|
||||||
|
# undef BOOST_EXPLICIT_DEFAULT_TARGET
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif // BOOST_CAST_HPP
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
// Copyright David Abrahams 2003.
|
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See
|
|
||||||
// accompanying file LICENSE_1_0.txt or copy at
|
|
||||||
// http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
|
|
||||||
#ifndef BOOST_IMPLICIT_CAST_DWA200356_HPP
|
|
||||||
#define BOOST_IMPLICIT_CAST_DWA200356_HPP
|
|
||||||
|
|
||||||
#include <boost/config.hpp>
|
|
||||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
|
||||||
# pragma once
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template<class T> struct icast_identity
|
|
||||||
{
|
|
||||||
using type = T;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
// implementation originally suggested by C. Green in
|
|
||||||
// http://lists.boost.org/MailArchives/boost/msg00886.php
|
|
||||||
|
|
||||||
// The use of identity creates a non-deduced form, so that the
|
|
||||||
// explicit template argument must be supplied
|
|
||||||
template <typename T>
|
|
||||||
constexpr T implicit_cast (typename boost::detail::icast_identity<T>::type x) {
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace boost
|
|
||||||
|
|
||||||
|
|
||||||
#endif // BOOST_IMPLICIT_CAST_DWA200356_HPP
|
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
// boost lexical_cast.hpp header -------------------------------------------//
|
||||||
|
|
||||||
|
// See http://www.boost.org for most recent version including documentation.
|
||||||
|
|
||||||
|
#ifndef BOOST_LEXICAL_CAST_INCLUDED
|
||||||
|
#define BOOST_LEXICAL_CAST_INCLUDED
|
||||||
|
|
||||||
|
// what: lexical_cast custom keyword cast
|
||||||
|
// who: contributed by Kevlin Henney, with alternative naming, behaviors
|
||||||
|
// and fixes contributed by Dave Abrahams, Daryle Walker and other
|
||||||
|
// Boosters on the list
|
||||||
|
// when: November 2000
|
||||||
|
// where: tested with MSVC 6.0, BCC 5.5, and g++ 2.91
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
|
||||||
|
// Some sstream implementations are broken for the purposes of lexical cast.
|
||||||
|
# if defined(BOOST_NO_STRINGSTREAM)
|
||||||
|
# define BOOST_LEXICAL_CAST_USE_STRSTREAM
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#ifdef BOOST_LEXICAL_CAST_USE_STRSTREAM
|
||||||
|
# include <strstream>
|
||||||
|
#else
|
||||||
|
# include <sstream>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <typeinfo>
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
// exception used to indicate runtime lexical_cast failure
|
||||||
|
class bad_lexical_cast : public std::bad_cast
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructors, destructors, and assignment operator defaulted
|
||||||
|
|
||||||
|
// function inlined for brevity and consistency with rest of library
|
||||||
|
virtual const char * what() const throw()
|
||||||
|
{
|
||||||
|
return "bad lexical cast: "
|
||||||
|
"source type value could not be interpreted as target";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Target, typename Source>
|
||||||
|
Target lexical_cast(Source arg)
|
||||||
|
{
|
||||||
|
# ifdef BOOST_LEXICAL_CAST_USE_STRSTREAM
|
||||||
|
std::strstream interpreter; // for out-of-the-box g++ 2.95.2
|
||||||
|
# else
|
||||||
|
std::stringstream interpreter;
|
||||||
|
# endif
|
||||||
|
Target result;
|
||||||
|
|
||||||
|
if(!(interpreter << arg) || !(interpreter >> result) ||
|
||||||
|
!(interpreter >> std::ws).eof())
|
||||||
|
throw bad_lexical_cast();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved.
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
|
// purpose is hereby granted without fee, provided that this copyright and
|
||||||
|
// permissions notice appear in all copies and derivatives.
|
||||||
|
//
|
||||||
|
// This software is provided "as is" without express or implied warranty.
|
||||||
|
|
||||||
|
#ifdef BOOST_LEXICAL_CAST_USE_STRSTREAM
|
||||||
|
# undef BOOST_LEXICAL_CAST_USE_STRSTREAM
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,132 +0,0 @@
|
|||||||
// boost polymorphic_cast.hpp header file ----------------------------------------------//
|
|
||||||
|
|
||||||
// (C) Copyright Kevlin Henney and Dave Abrahams 1999.
|
|
||||||
// (C) Copyright Boris Rasin 2014.
|
|
||||||
// Distributed under the Boost
|
|
||||||
// Software License, Version 1.0. (See accompanying file
|
|
||||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
|
|
||||||
// See http://www.boost.org/libs/conversion for Documentation.
|
|
||||||
|
|
||||||
// Revision History
|
|
||||||
// 10 Nov 14 polymorphic_pointer_downcast moved to a separate header,
|
|
||||||
// minor improvements to stisfy latest Boost coding style
|
|
||||||
// 08 Nov 14 Add polymorphic_pointer_downcast (Boris Rasin)
|
|
||||||
// 09 Jun 14 "cast.hpp" was renamed to "polymorphic_cast.hpp" and
|
|
||||||
// inclusion of numeric_cast was removed (Antony Polukhin)
|
|
||||||
// 23 Jun 05 numeric_cast removed and redirected to the new version (Fernando Cacciola)
|
|
||||||
// 02 Apr 01 Removed BOOST_NO_LIMITS workarounds and included
|
|
||||||
// <boost/limits.hpp> instead (the workaround did not
|
|
||||||
// actually compile when BOOST_NO_LIMITS was defined in
|
|
||||||
// any case, so we loose nothing). (John Maddock)
|
|
||||||
// 21 Jan 01 Undid a bug I introduced yesterday. numeric_cast<> never
|
|
||||||
// worked with stock GCC; trying to get it to do that broke
|
|
||||||
// vc-stlport.
|
|
||||||
// 20 Jan 01 Moved BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS to config.hpp.
|
|
||||||
// Removed unused BOOST_EXPLICIT_TARGET macro. Moved
|
|
||||||
// boost::detail::type to boost/type.hpp. Made it compile with
|
|
||||||
// stock gcc again (Dave Abrahams)
|
|
||||||
// 29 Nov 00 Remove nested namespace cast, cleanup spacing before Formal
|
|
||||||
// Review (Beman Dawes)
|
|
||||||
// 19 Oct 00 Fix numeric_cast for floating-point types (Dave Abrahams)
|
|
||||||
// 15 Jul 00 Suppress numeric_cast warnings for GCC, Borland and MSVC
|
|
||||||
// (Dave Abrahams)
|
|
||||||
// 30 Jun 00 More MSVC6 workarounds. See comments below. (Dave Abrahams)
|
|
||||||
// 28 Jun 00 Removed implicit_cast<>. See comment below. (Beman Dawes)
|
|
||||||
// 27 Jun 00 More MSVC6 workarounds
|
|
||||||
// 15 Jun 00 Add workarounds for MSVC6
|
|
||||||
// 2 Feb 00 Remove bad_numeric_cast ";" syntax error (Doncho Angelov)
|
|
||||||
// 26 Jan 00 Add missing throw() to bad_numeric_cast::what(0 (Adam Levar)
|
|
||||||
// 29 Dec 99 Change using declarations so usages in other namespaces work
|
|
||||||
// correctly (Dave Abrahams)
|
|
||||||
// 23 Sep 99 Change polymorphic_downcast assert to also detect M.I. errors
|
|
||||||
// as suggested Darin Adler and improved by Valentin Bonnard.
|
|
||||||
// 2 Sep 99 Remove controversial asserts, simplify, rename.
|
|
||||||
// 30 Aug 99 Move to cast.hpp, replace value_cast with numeric_cast,
|
|
||||||
// place in nested namespace.
|
|
||||||
// 3 Aug 99 Initial version
|
|
||||||
|
|
||||||
#ifndef BOOST_POLYMORPHIC_CAST_HPP
|
|
||||||
#define BOOST_POLYMORPHIC_CAST_HPP
|
|
||||||
|
|
||||||
#include <boost/config.hpp>
|
|
||||||
|
|
||||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
|
||||||
# pragma once
|
|
||||||
#endif
|
|
||||||
|
|
||||||
# include <boost/assert.hpp>
|
|
||||||
# include <boost/throw_exception.hpp>
|
|
||||||
|
|
||||||
# include <memory> // std::addressof
|
|
||||||
# include <typeinfo>
|
|
||||||
# include <type_traits>
|
|
||||||
|
|
||||||
#if defined(__cpp_constexpr) && __cpp_constexpr >= 201907L
|
|
||||||
#define BOOST_CONVERSION_IMPL_CONSTEXPR_DYN_CAST constexpr
|
|
||||||
#else
|
|
||||||
#define BOOST_CONVERSION_IMPL_CONSTEXPR_DYN_CAST inline
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace boost
|
|
||||||
{
|
|
||||||
// See the documentation for descriptions of how to choose between
|
|
||||||
// static_cast<>, dynamic_cast<>, polymorphic_cast<> and polymorphic_downcast<>
|
|
||||||
|
|
||||||
// polymorphic_cast --------------------------------------------------------//
|
|
||||||
|
|
||||||
// Runtime checked polymorphic downcasts and crosscasts.
|
|
||||||
// Suggested in The C++ Programming Language, 3rd Ed, Bjarne Stroustrup,
|
|
||||||
// section 15.8 exercise 1, page 425.
|
|
||||||
|
|
||||||
template <class Target, class Source>
|
|
||||||
BOOST_CONVERSION_IMPL_CONSTEXPR_DYN_CAST Target polymorphic_cast(Source* x)
|
|
||||||
{
|
|
||||||
Target tmp = dynamic_cast<Target>(x);
|
|
||||||
if ( tmp == 0 ) boost::throw_exception( std::bad_cast() );
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// polymorphic_downcast ----------------------------------------------------//
|
|
||||||
|
|
||||||
// BOOST_ASSERT() checked raw pointer polymorphic downcast. Crosscasts prohibited.
|
|
||||||
|
|
||||||
// WARNING: Because this cast uses BOOST_ASSERT(), it violates
|
|
||||||
// the One Definition Rule if used in multiple translation units
|
|
||||||
// where BOOST_DISABLE_ASSERTS, BOOST_ENABLE_ASSERT_HANDLER
|
|
||||||
// NDEBUG are defined inconsistently.
|
|
||||||
|
|
||||||
// Contributed by Dave Abrahams
|
|
||||||
|
|
||||||
template <class Target, class Source>
|
|
||||||
BOOST_CONVERSION_IMPL_CONSTEXPR_DYN_CAST Target polymorphic_downcast(Source* x)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT( dynamic_cast<Target>(x) == x ); // detect logic error
|
|
||||||
return static_cast<Target>(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
// BOOST_ASSERT() checked reference polymorphic downcast. Crosscasts prohibited.
|
|
||||||
|
|
||||||
// WARNING: Because this cast uses BOOST_ASSERT(), it violates
|
|
||||||
// the One Definition Rule if used in multiple translation units
|
|
||||||
// where BOOST_DISABLE_ASSERTS, BOOST_ENABLE_ASSERT_HANDLER
|
|
||||||
// NDEBUG are defined inconsistently.
|
|
||||||
|
|
||||||
// Contributed by Julien Delacroix
|
|
||||||
|
|
||||||
template <class Target, class Source>
|
|
||||||
BOOST_CONVERSION_IMPL_CONSTEXPR_DYN_CAST typename std::enable_if<
|
|
||||||
std::is_reference<Target>::value, Target
|
|
||||||
>::type polymorphic_downcast(Source& x)
|
|
||||||
{
|
|
||||||
using target_pointer_type = typename std::remove_reference<Target>::type*;
|
|
||||||
return *boost::polymorphic_downcast<target_pointer_type>(
|
|
||||||
std::addressof(x)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace boost
|
|
||||||
|
|
||||||
#undef BOOST_CONVERSION_IMPL_CONSTEXPR_DYN_CAST
|
|
||||||
|
|
||||||
#endif // BOOST_POLYMORPHIC_CAST_HPP
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
// boost polymorphic_pointer_cast.hpp header file ----------------------------------------------//
|
|
||||||
// (C) Copyright Boris Rasin, 2014-2021.
|
|
||||||
// (C) Copyright Antony Polukhin, 2014-2026.
|
|
||||||
// Distributed under the Boost
|
|
||||||
// Software License, Version 1.0. (See accompanying file
|
|
||||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
|
|
||||||
// See http://www.boost.org/libs/conversion for Documentation.
|
|
||||||
|
|
||||||
#ifndef BOOST_CONVERSION_POLYMORPHIC_POINTER_CAST_HPP
|
|
||||||
#define BOOST_CONVERSION_POLYMORPHIC_POINTER_CAST_HPP
|
|
||||||
|
|
||||||
#include <boost/config.hpp>
|
|
||||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
|
||||||
# pragma once
|
|
||||||
#endif
|
|
||||||
|
|
||||||
# include <boost/assert.hpp>
|
|
||||||
# include <boost/pointer_cast.hpp>
|
|
||||||
# include <boost/throw_exception.hpp>
|
|
||||||
|
|
||||||
|
|
||||||
namespace boost
|
|
||||||
{
|
|
||||||
// See the documentation for descriptions of how to choose between
|
|
||||||
// static_pointer_cast<>, dynamic_pointer_cast<>, polymorphic_pointer_cast<> and polymorphic_pointer_downcast<>
|
|
||||||
|
|
||||||
// polymorphic_pointer_downcast --------------------------------------------//
|
|
||||||
|
|
||||||
// BOOST_ASSERT() checked polymorphic downcast. Crosscasts prohibited.
|
|
||||||
// Supports any type with static_pointer_cast/dynamic_pointer_cast functions:
|
|
||||||
// built-in pointers, std::shared_ptr, boost::shared_ptr, boost::intrusive_ptr, etc.
|
|
||||||
|
|
||||||
// WARNING: Because this cast uses BOOST_ASSERT(), it violates
|
|
||||||
// the One Definition Rule if used in multiple translation units
|
|
||||||
// where BOOST_DISABLE_ASSERTS, BOOST_ENABLE_ASSERT_HANDLER
|
|
||||||
// NDEBUG are defined inconsistently.
|
|
||||||
|
|
||||||
// Contributed by Boris Rasin
|
|
||||||
|
|
||||||
template <typename Target, typename Source>
|
|
||||||
inline auto polymorphic_pointer_downcast (const Source& x)
|
|
||||||
-> decltype(static_pointer_cast<Target>(x))
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(dynamic_pointer_cast<Target> (x) == x);
|
|
||||||
return static_pointer_cast<Target> (x);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Target, typename Source>
|
|
||||||
inline auto polymorphic_pointer_cast (const Source& x)
|
|
||||||
-> decltype(dynamic_pointer_cast<Target>(x))
|
|
||||||
{
|
|
||||||
auto tmp = dynamic_pointer_cast<Target> (x);
|
|
||||||
if ( !tmp ) boost::throw_exception( std::bad_cast() );
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace boost
|
|
||||||
|
|
||||||
#endif // BOOST_CONVERSION_POLYMORPHIC_POINTER_CAST_HPP
|
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Language" content="en-us">
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||||
|
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||||
|
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||||
|
<title>Boost Conversion Library</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body bgcolor="#FFFFFF" text="#000000">
|
||||||
|
|
||||||
|
<h1><img border="0" src="../../c++boost.gif" align="center" width="277" height="86">Boost
|
||||||
|
Conversion Library</h1>
|
||||||
|
|
||||||
|
<p>The Conversion Library improves program safety and clarity by performing
|
||||||
|
otherwise messy conversions. It includes cast-style function templates designed to complement the C++
|
||||||
|
Standard's built-in casts.</p>
|
||||||
|
<p>To reduce coupling, particularly to standard library IOStreams, the Boost
|
||||||
|
Conversion Library is
|
||||||
|
supplied by several headers:</p>
|
||||||
|
<ul>
|
||||||
|
<li>The <a href="cast.htm">boost/cast</a> header provides <b>polymorphic_cast<></b>
|
||||||
|
and <b>polymorphic_downcast<></b> to perform safe casting between
|
||||||
|
polymorphic types, and <b> numeric_cast</b><i><></i> to perform safe casting
|
||||||
|
between numeric types.<br>
|
||||||
|
</li>
|
||||||
|
<li>The <a href="lexical_cast.htm">boost/lexical_cast</a> header provides <b>lexical_cast<></b>
|
||||||
|
general literal text conversions, such as an <code>int</code> represented as
|
||||||
|
a <code>string</code>, or vice-versa.</li>
|
||||||
|
</ul>
|
||||||
|
<hr>
|
||||||
|
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED"
|
||||||
|
S-Format="%d %B, %Y" startspan -->06 January, 2001<!--webbot bot="Timestamp" endspan i-checksum="38320" -->
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
-39
@@ -1,39 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<!--
|
|
||||||
Copyright (c) 2016 Mikhail Maximov
|
|
||||||
vigorous.activity at gmail dot com
|
|
||||||
|
|
||||||
Copyright (c) Antony Polukhin, 2021-2026
|
|
||||||
|
|
||||||
Distributed under the Boost Software License,
|
|
||||||
Version 1.0. (See accompanying file LICENSE_1_0.txt
|
|
||||||
or copy at http://boost.org/LICENSE_1_0.txt)
|
|
||||||
|
|
||||||
boost-no-inspect
|
|
||||||
-->
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta http-equiv="refresh" content="0; url=../../doc/html/conversion.html">
|
|
||||||
<title>Boost.Conversion</title>
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
background: #fff;
|
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
a {
|
|
||||||
color: #00f;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<p>
|
|
||||||
Automatic redirection failed, please go to
|
|
||||||
<a href="../../doc/html/conversion.html">../../doc/html/conversion.html</a>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
© Antony Polukhin, 2014-2024
|
|
||||||
</p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -0,0 +1,242 @@
|
|||||||
|
<!doctype html public "-//W3C//DTD HTML Transitional 4.0//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>lexical_cast</title>
|
||||||
|
<meta name="author" content="Kevlin Henney, mailto:kevlin@curbralan.com">
|
||||||
|
<meta name="generator" content="Microsoft FrontPage 4.0">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body bgcolor="#FFFFFF" text="#000000">
|
||||||
|
|
||||||
|
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">Header
|
||||||
|
<a href="../../boost/lexical_cast.hpp">boost/lexical_cast.hpp</a></h1>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="#motivation">Motivation</a></li>
|
||||||
|
<li><a href="#examples">Examples</a></li>
|
||||||
|
<li><a href="#synopsis">Synopsis</a></li>
|
||||||
|
<li><a href="#lexical_cast"><code>lexical_cast</code></a></li>
|
||||||
|
<li><a href="#bad_lexical_cast"><code>bad_lexical_cast</code></a></li>
|
||||||
|
<li><a href="#portability">Portability</a></li>
|
||||||
|
<li><a href="#future">Future directions</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h2><a name="motivation">Motivation</a></h2>
|
||||||
|
|
||||||
|
Sometimes a value must be converted to a literal text form, such as an
|
||||||
|
<code>int</code> represented as a <code>string</code>, or vice-versa, when
|
||||||
|
a <code>string</code> is interpreted as an <code>int</code>. Such examples
|
||||||
|
are common when converting between data types internal to a program and
|
||||||
|
representation external to a program, such as windows and configuration files.
|
||||||
|
<p>
|
||||||
|
The standard C and C++ libraries offer a number of facilities for performing
|
||||||
|
such conversions. However, they vary with their ease of use, extensibility,
|
||||||
|
and safety.
|
||||||
|
<p>
|
||||||
|
For instance, there are a number of limitations with the family of standard C
|
||||||
|
functions typified by <code>atoi</code>:
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
Conversion is supported in one direction only: from text to
|
||||||
|
internal data type. Converting the other way using the C library
|
||||||
|
requires either the inconvenience and compromised safety of the
|
||||||
|
<code>sprintf</code> function, or the loss of portability associated
|
||||||
|
with non-standard functions such as <code>itoa</code>.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
The range of types supported is only a subset of the built-in numeric
|
||||||
|
types, namely <code>int</code>, <code>long</code>,
|
||||||
|
and <code>double</code>.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
The range of types cannot be extended in a uniform manner. For
|
||||||
|
instance, conversion from string representation to
|
||||||
|
<code>complex</code> or <code>rational</code>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
The standard C functions typified by <code>strtol</code> have the same basic
|
||||||
|
limitations, but offer finer control over the conversion process. However, for
|
||||||
|
the common case such control is often either not required or not used. The
|
||||||
|
<code>scanf</code> family of functions offer even greater control, but also
|
||||||
|
lack safety and ease of use.
|
||||||
|
<p>
|
||||||
|
The standard C++ library offers <code>stringstream</code> for the kind of
|
||||||
|
in-core formatting being discussed. It offers a great deal of control over the
|
||||||
|
formatting and conversion of I/O to and from arbitrary types through text.
|
||||||
|
However, for simple conversions direct use of <code>stringstream</code> can be
|
||||||
|
either clumsy (with the introduction of extra local variables and the loss of
|
||||||
|
infix-expression convenience) or obscure (where <code>stringstream</code>
|
||||||
|
objects are created as temporary objects in an expression). Facets provide a
|
||||||
|
comprehensive concept and facility for controlling textual representation, but
|
||||||
|
their relatively high entry level requires an extreme degree of involvement
|
||||||
|
for simple conversions.
|
||||||
|
<p>
|
||||||
|
The <code>lexical_cast</code> template function offers a convenient and consistent
|
||||||
|
form for supporting common conversions to and from arbitrary types when they are
|
||||||
|
represented as text. The simplification it offers is in expression-level
|
||||||
|
convenience for such conversions. For more involved conversions, such as where
|
||||||
|
precision or formatting need tighter control than is offered by the default
|
||||||
|
behavior of <code>lexical_cast</code>, the conventional
|
||||||
|
<code>stringstream</code> approach is recommended. Where the conversions are
|
||||||
|
numeric to numeric, <code><a href="cast.htm#numeric_cast">numeric_cast</a></code> may offer more reasonable
|
||||||
|
behavior than <code>lexical_cast</code>.
|
||||||
|
<p>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h2><a name="examples">Examples</a></h2>
|
||||||
|
|
||||||
|
The following example treats command line arguments as a sequence of numeric data:
|
||||||
|
<blockquote>
|
||||||
|
<pre>
|
||||||
|
int main(int argc, char * argv[])
|
||||||
|
{
|
||||||
|
using boost::lexical_cast;
|
||||||
|
using boost::bad_lexical_cast;
|
||||||
|
|
||||||
|
std::vector<short> args;
|
||||||
|
|
||||||
|
while(*++argv)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
args.push_back(lexical_cast<short>(*argv));
|
||||||
|
}
|
||||||
|
catch(bad_lexical_cast &)
|
||||||
|
{
|
||||||
|
args.push_back(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
...
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
The following example uses numeric data in a string expression:
|
||||||
|
<blockquote>
|
||||||
|
<pre>
|
||||||
|
void log_message(const std::string &);
|
||||||
|
|
||||||
|
void log_errno(int yoko)
|
||||||
|
{
|
||||||
|
log_message("Error " + boost::lexical_cast<std::string>(yoko) + ": " + strerror(yoko));
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h2><a name="synopsis">Synopsis</a></h2>
|
||||||
|
|
||||||
|
Library features defined in <a href="../../boost/lexical_cast.hpp"><code>"boost/lexical_cast.hpp"</code></a>:
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
<pre>
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
class <a href="#bad_lexical_cast">bad_lexical_cast</a>;
|
||||||
|
template<typename Target, typename Source>
|
||||||
|
Target <a href="#lexical_cast">lexical_cast</a>(Source arg);
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
Test harness defined in <a href="lexical_cast_test.cpp"><code>"lexical_cast_test.cpp"</code></a>.
|
||||||
|
<p>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h2><a name="lexical_cast"><code>lexical_cast</code></a></h2>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
<pre>
|
||||||
|
template<typename Target, typename Source>
|
||||||
|
Target lexical_cast(Source arg);
|
||||||
|
</pre>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
Returns the result of streaming <code>arg</code> into a <code>std::stringstream</code> and then
|
||||||
|
out as a <code>Target</code> object. The conversion is parameterized by the current
|
||||||
|
<a href="#lexical_context"><code>lexical_context</code></a>, if set. If the conversion is
|
||||||
|
unsuccessful, a <a href="#bad_lexical_cast"><code>bad_lexical_cast</code></a> exception is thrown
|
||||||
|
if the current <a href="#lexical_context"><code>lexical_context</code></a> is set for throwing or
|
||||||
|
if there is no current <a href="#lexical_context"><code>lexical_context</code></a> set, otherwise a
|
||||||
|
<code>Target()</code> is returned.
|
||||||
|
<p>
|
||||||
|
The requirements on the argument and result types are:
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<code>Source</code> is <i>OutputStreamable</i>, meaning that an
|
||||||
|
<code>operator<<</code> is defined that takes a
|
||||||
|
<code>std::ostream</code> object on the left hand side and an instance
|
||||||
|
of the argument type on the right.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Both <code>Source</code> and <code>Target</code> are <i>CopyConstructible</i> [20.1.3].
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<code>Target</code> is <i>InputStreamable</i>, meaning that an
|
||||||
|
<code>operator>></code> is defined that takes a
|
||||||
|
<code>std::istream</code> object on the left hand side and an instance
|
||||||
|
of the result type on the right.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<code>Target</code> is <i>DefaultConstructible</i>, meaning that it is
|
||||||
|
possible to <i>default-initialize</i> an object of that type [8.5, 20.1.3].
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<code>Target</code> is <i>Assignable</i> [23.1].
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h2><a name="bad_lexical_cast"><code>bad_lexical_cast</code></a></h2>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
<pre>
|
||||||
|
class bad_lexical_cast : public std::bad_cast
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual const char * what() const throw();
|
||||||
|
};
|
||||||
|
</pre>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
Exception used to indicate runtime <a href="#lexical_cast"><code>lexical_cast</code></a> failure.
|
||||||
|
<p>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h2><a name="portability">Portability</a></h2>
|
||||||
|
|
||||||
|
To date the code and test harness have been compiled successfully using
|
||||||
|
Microsoft Visual C++ 6.0, Borland C++ 5.5, and GNU g++ 2.91. Tests have run successfully for
|
||||||
|
Microsoft Visual C++ 6.0 and Borland C++ 5.5. For g++ streams interpret any integer, rather than
|
||||||
|
just <code>0</code> and <code>1</code>, as valid for <code>bool</code>; the other tests pass
|
||||||
|
without problem. The deprecated standard header <code><strstream></code> is used in
|
||||||
|
preference to the standard <code><sstream></code> header for out-of-the-box g++ support.
|
||||||
|
<p>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h2><a name="future">Future directions</a></h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
A mechanism for providing quality-of-service control is needed, e.g. formatting and exception
|
||||||
|
behavior. In the name of simplicity (and release), the current version strips out an earlier
|
||||||
|
experimental version.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Wide character and incompatible <code>std::basic_string</code> issues need to be catered for.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
An <code>interpret_cast</code> that performs a <i>do-something-reasonable</i> conversion between
|
||||||
|
types. It would, for instance, select between <code>numeric_cast</code> and <code>lexical_cast</code>
|
||||||
|
based on <code>std::numeric_limits<>::is_specialized</code>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div align="right"><small><i>© Copyright Kevlin Henney, 2000</i></small></div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,149 @@
|
|||||||
|
// boost lexical_cast_test.cpp program -------------------------------------//
|
||||||
|
|
||||||
|
// See http://www.boost.org for most recent version including documentation.
|
||||||
|
|
||||||
|
// what: lexical_cast custom keyword cast tests
|
||||||
|
// who: contributed by Kevlin Henney
|
||||||
|
// when: October 2000
|
||||||
|
// where: tested with MSVC 6.0 and BCC 5.5
|
||||||
|
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
|
#include "test.hpp"
|
||||||
|
#include <complex>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
using namespace boost;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
typedef test::test<const char *, void (*)()> test_case;
|
||||||
|
typedef const test_case * test_case_iterator;
|
||||||
|
|
||||||
|
extern const test_case_iterator begin, end;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
test::tester<test_case_iterator> test_suite(begin, end);
|
||||||
|
return test_suite() ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_to_string()
|
||||||
|
{
|
||||||
|
test::check_equal(
|
||||||
|
lexical_cast<string>(2001), "2001",
|
||||||
|
"2001 -> \"2001\"");
|
||||||
|
test::check_equal(
|
||||||
|
lexical_cast<string>(2001.0), "2001",
|
||||||
|
"2001.0 ->\"2001\"");
|
||||||
|
test::check_equal(
|
||||||
|
lexical_cast<string>(complex<double>(2000,1)), "(2000,1)",
|
||||||
|
"complex<double>(2000,1) -> \"(2000,1)\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_to_int()
|
||||||
|
{
|
||||||
|
test::check_equal(
|
||||||
|
lexical_cast<int>("2001"), 2001,
|
||||||
|
"\"2001\" -> 2001");
|
||||||
|
test::check_equal(
|
||||||
|
lexical_cast<int>(" 2001"), 2001,
|
||||||
|
"\" 2001\" -> 2001");
|
||||||
|
test::check_equal(
|
||||||
|
lexical_cast<int>("2001 "), 2001,
|
||||||
|
"\"2001 \" -> 2001");
|
||||||
|
TEST_CHECK_THROW(
|
||||||
|
lexical_cast<int>("Two thousand and one"),
|
||||||
|
bad_lexical_cast,
|
||||||
|
"\"Two thousand and one\"");
|
||||||
|
TEST_CHECK_THROW(
|
||||||
|
lexical_cast<int>("2001: A Space Odyssey"),
|
||||||
|
bad_lexical_cast,
|
||||||
|
"\"2001: A Space Odyssey\"");
|
||||||
|
TEST_CHECK_THROW(
|
||||||
|
lexical_cast<int>(200.1),
|
||||||
|
bad_lexical_cast,
|
||||||
|
"200.1");
|
||||||
|
TEST_CHECK_THROW(
|
||||||
|
lexical_cast<int>("200e1"),
|
||||||
|
bad_lexical_cast,
|
||||||
|
"\"200e1\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_to_char()
|
||||||
|
{
|
||||||
|
test::check_equal(
|
||||||
|
lexical_cast<char>("2"), '2',
|
||||||
|
"\"2\" -> '2'");
|
||||||
|
test::check_equal(
|
||||||
|
lexical_cast<char>(" 2"), '2',
|
||||||
|
"\" 2\" -> '2'");
|
||||||
|
test::check_equal(
|
||||||
|
lexical_cast<char>("2 "), '2',
|
||||||
|
"\"2 \" -> '2'");
|
||||||
|
test::check_equal(
|
||||||
|
lexical_cast<char>(2), '2',
|
||||||
|
"2 -> '2'");
|
||||||
|
TEST_CHECK_THROW(
|
||||||
|
lexical_cast<char>("2001"),
|
||||||
|
bad_lexical_cast,
|
||||||
|
"\"2001\"");
|
||||||
|
TEST_CHECK_THROW(
|
||||||
|
lexical_cast<char>(2001),
|
||||||
|
bad_lexical_cast,
|
||||||
|
"2001");
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_to_double()
|
||||||
|
{
|
||||||
|
test::check_equal(
|
||||||
|
lexical_cast<double>("1e6"), 1e6,
|
||||||
|
"\"1e6\" -> 1e6");
|
||||||
|
test::check_equal(
|
||||||
|
lexical_cast<double>("1e-2"), 1e-2,
|
||||||
|
"\"1e-2\" -> 1e-2");
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_to_bool()
|
||||||
|
{
|
||||||
|
test::check_equal(
|
||||||
|
lexical_cast<bool>(1), true,
|
||||||
|
"1 -> true");
|
||||||
|
test::check_equal(
|
||||||
|
lexical_cast<bool>('0'), false,
|
||||||
|
"'0' -> false");
|
||||||
|
TEST_CHECK_THROW(
|
||||||
|
lexical_cast<bool>(2001),
|
||||||
|
bad_lexical_cast,
|
||||||
|
"2001");
|
||||||
|
TEST_CHECK_THROW(
|
||||||
|
lexical_cast<bool>(2),
|
||||||
|
bad_lexical_cast,
|
||||||
|
"2");
|
||||||
|
TEST_CHECK_THROW(
|
||||||
|
lexical_cast<bool>("true thousand and one"),
|
||||||
|
bad_lexical_cast,
|
||||||
|
"\"true thousand and one\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
const test_case test_cases[] =
|
||||||
|
{
|
||||||
|
{ "lexical_cast<std::string>", test_to_string },
|
||||||
|
{ "lexical_cast<int>", test_to_int },
|
||||||
|
{ "lexical_cast<char>", test_to_char },
|
||||||
|
{ "lexical_cast<double>", test_to_double },
|
||||||
|
{ "lexical_cast<bool>", test_to_bool }
|
||||||
|
};
|
||||||
|
|
||||||
|
const test_case_iterator begin = test_cases;
|
||||||
|
const test_case_iterator end =
|
||||||
|
test_cases + (sizeof test_cases / sizeof *test_cases);
|
||||||
|
|
||||||
|
// Copyright Kevlin Henney, 2000. All rights reserved.
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
|
// purpose is hereby granted without fee, provided that this copyright and
|
||||||
|
// permissions notice appear in all copies and derivatives, and that no
|
||||||
|
// charge may be made for the software and its documentation except to cover
|
||||||
|
// cost of distribution.
|
||||||
|
//
|
||||||
|
// This software is provided "as is" without express or implied warranty.
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
"key": "conversion",
|
|
||||||
"name": "Conversion",
|
|
||||||
"authors": [
|
|
||||||
"Dave Abrahams",
|
|
||||||
"Kevlin Henney"
|
|
||||||
],
|
|
||||||
"description": "Polymorphic casts.",
|
|
||||||
"category": [
|
|
||||||
"Miscellaneous"
|
|
||||||
],
|
|
||||||
"maintainers": [
|
|
||||||
"Antony Polukhin <antoshkka -at- gmail.com>"
|
|
||||||
],
|
|
||||||
"cxxstd": "11"
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,312 @@
|
|||||||
|
// what: simple unit test framework
|
||||||
|
// who: developed by Kevlin Henney
|
||||||
|
// when: November 2000
|
||||||
|
// where: tested with BCC 5.5, MSVC 6.0, and g++ 2.91
|
||||||
|
//
|
||||||
|
// ChangeLog:
|
||||||
|
// 20 Jan 2001 - Fixed a warning for MSVC (Dave Abrahams)
|
||||||
|
|
||||||
|
#ifndef TEST_INCLUDED
|
||||||
|
#define TEST_INCLUDED
|
||||||
|
|
||||||
|
#include <exception>
|
||||||
|
#include <iostream>
|
||||||
|
#include <strstream> // for out-of-the-box g++
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace test // test tuple comprises name and nullary function (object)
|
||||||
|
{
|
||||||
|
template<typename string_type, typename function_type>
|
||||||
|
struct test
|
||||||
|
{
|
||||||
|
string_type name;
|
||||||
|
function_type action;
|
||||||
|
|
||||||
|
static test make(string_type name, function_type action)
|
||||||
|
{
|
||||||
|
test result; // MSVC aggreggate initializer bugs
|
||||||
|
result.name = name;
|
||||||
|
result.action = action;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test // failure exception used to indicate checked test failures
|
||||||
|
{
|
||||||
|
class failure : public std::exception
|
||||||
|
{
|
||||||
|
public: // struction (default cases are OK)
|
||||||
|
|
||||||
|
failure(const std::string & why)
|
||||||
|
: reason(why)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// std::~string has no exception-specification (could throw anything),
|
||||||
|
// but we need to be compatible with std::~exception's empty one
|
||||||
|
// see std::15.4p13 and std::15.4p3
|
||||||
|
~failure() throw()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public: // usage
|
||||||
|
|
||||||
|
virtual const char * what() const throw()
|
||||||
|
{
|
||||||
|
return reason.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
private: // representation
|
||||||
|
|
||||||
|
std::string reason;
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test // not_implemented exception used to mark unimplemented tests
|
||||||
|
{
|
||||||
|
class not_implemented : public std::exception
|
||||||
|
{
|
||||||
|
public: // usage (default ctor and dtor are OK)
|
||||||
|
|
||||||
|
virtual const char * what() const throw()
|
||||||
|
{
|
||||||
|
return "not implemented";
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test // test utilities
|
||||||
|
{
|
||||||
|
inline void check(bool condition, const std::string & description)
|
||||||
|
{
|
||||||
|
if(!condition)
|
||||||
|
{
|
||||||
|
throw failure(description);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void check_true(bool value, const std::string & description)
|
||||||
|
{
|
||||||
|
check(value, "expected true: " + description);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void check_false(bool value, const std::string & description)
|
||||||
|
{
|
||||||
|
check(!value, "expected false: " + description);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename lhs_type, typename rhs_type>
|
||||||
|
void check_equal(
|
||||||
|
const lhs_type & lhs, const rhs_type & rhs,
|
||||||
|
const std::string & description)
|
||||||
|
{
|
||||||
|
check(lhs == rhs, "expected equal values: " + description);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename lhs_type, typename rhs_type>
|
||||||
|
void check_unequal(
|
||||||
|
const lhs_type & lhs, const rhs_type & rhs,
|
||||||
|
const std::string & description)
|
||||||
|
{
|
||||||
|
check(lhs != rhs, "expected unequal values: " + description);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void check_null(const void* ptr, const std::string & description)
|
||||||
|
{
|
||||||
|
check(!ptr, "expected null pointer: " + description);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void check_non_null(const void* ptr, const std::string & description)
|
||||||
|
{
|
||||||
|
check(ptr != 0, "expected non-null pointer: " + description);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TEST_CHECK_THROW(expression, exception, description) \
|
||||||
|
try \
|
||||||
|
{ \
|
||||||
|
expression; \
|
||||||
|
throw ::test::failure(description); \
|
||||||
|
} \
|
||||||
|
catch(exception &) \
|
||||||
|
{ \
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test // memory tracking (enabled if test new and delete linked in)
|
||||||
|
{
|
||||||
|
class allocations
|
||||||
|
{
|
||||||
|
public: // singleton access
|
||||||
|
|
||||||
|
static allocations & instance()
|
||||||
|
{
|
||||||
|
static allocations singleton;
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
public: // logging
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
alloc_count = dealloc_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void allocation()
|
||||||
|
{
|
||||||
|
++alloc_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void deallocation()
|
||||||
|
{
|
||||||
|
++dealloc_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public: // reporting
|
||||||
|
|
||||||
|
unsigned long allocated() const
|
||||||
|
{
|
||||||
|
return alloc_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long deallocated() const
|
||||||
|
{
|
||||||
|
return dealloc_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool balanced() const
|
||||||
|
{
|
||||||
|
return alloc_count == dealloc_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
private: // structors (default dtor is fine)
|
||||||
|
|
||||||
|
allocations()
|
||||||
|
: alloc_count(0), dealloc_count(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private: // prevention
|
||||||
|
|
||||||
|
allocations(const allocations &);
|
||||||
|
allocations & operator=(const allocations &);
|
||||||
|
|
||||||
|
private: // state
|
||||||
|
|
||||||
|
unsigned long alloc_count, dealloc_count;
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test // tester is the driver class for a sequence of tests
|
||||||
|
{
|
||||||
|
template<typename test_iterator>
|
||||||
|
class tester
|
||||||
|
{
|
||||||
|
public: // structors (default destructor is OK)
|
||||||
|
|
||||||
|
tester(test_iterator first_test, test_iterator after_last_test)
|
||||||
|
: begin(first_test), end(after_last_test)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public: // usage
|
||||||
|
|
||||||
|
bool operator()(); // returns true if all tests passed
|
||||||
|
|
||||||
|
private: // representation
|
||||||
|
|
||||||
|
test_iterator begin, end;
|
||||||
|
|
||||||
|
private: // prevention
|
||||||
|
|
||||||
|
tester(const tester &);
|
||||||
|
tester &operator=(const tester &);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename test_iterator>
|
||||||
|
bool tester<test_iterator>::operator()()
|
||||||
|
{
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
unsigned long passed = 0, failed = 0, unimplemented = 0;
|
||||||
|
|
||||||
|
for(test_iterator current = begin; current != end; ++current)
|
||||||
|
{
|
||||||
|
cerr << "[" << current->name << "] " << flush;
|
||||||
|
string result = "passed"; // optimistic
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
allocations::instance().clear();
|
||||||
|
current->action();
|
||||||
|
|
||||||
|
if(!allocations::instance().balanced())
|
||||||
|
{
|
||||||
|
unsigned long allocated = allocations::instance().allocated();
|
||||||
|
unsigned long deallocated = allocations::instance().deallocated();
|
||||||
|
ostrstream report;
|
||||||
|
report << "new/delete ("
|
||||||
|
<< allocated << " allocated, "
|
||||||
|
<< deallocated << " deallocated)"
|
||||||
|
<< ends;
|
||||||
|
const char * text = report.str();
|
||||||
|
report.freeze(false);
|
||||||
|
throw failure(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
++passed;
|
||||||
|
}
|
||||||
|
catch(const failure & caught)
|
||||||
|
{
|
||||||
|
(result = "failed: ") += caught.what();
|
||||||
|
++failed;
|
||||||
|
}
|
||||||
|
catch(const not_implemented &)
|
||||||
|
{
|
||||||
|
result = "not implemented";
|
||||||
|
++unimplemented;
|
||||||
|
}
|
||||||
|
catch(const exception & caught)
|
||||||
|
{
|
||||||
|
(result = "exception: ") += caught.what();
|
||||||
|
++failed;
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
result = "failed with unknown exception";
|
||||||
|
++failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
cerr << result << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
cerr << passed + failed << " tests: "
|
||||||
|
<< passed << " passed, "
|
||||||
|
<< failed << " failed";
|
||||||
|
|
||||||
|
if(unimplemented)
|
||||||
|
{
|
||||||
|
cerr << " (" << unimplemented << " not implemented)";
|
||||||
|
}
|
||||||
|
|
||||||
|
cerr << endl;
|
||||||
|
|
||||||
|
return failed == 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Copyright Kevlin Henney, 2000. All rights reserved.
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
|
// purpose is hereby granted without fee, provided that this copyright and
|
||||||
|
// permissions notice appear in all copies and derivatives, and that no
|
||||||
|
// charge may be made for the software and its documentation except to cover
|
||||||
|
// cost of distribution.
|
||||||
|
//
|
||||||
|
// This software is provided "as is" without express or implied warranty.
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
# Copyright (c) 2016-2026 Antony Polukhin
|
|
||||||
# Distributed under the Boost Software License, Version 1.0.
|
|
||||||
# See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt
|
|
||||||
|
|
||||||
include(BoostTest OPTIONAL RESULT_VARIABLE HAVE_BOOST_TEST)
|
|
||||||
|
|
||||||
if(NOT HAVE_BOOST_TEST)
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(BOOST_TEST_LINK_LIBRARIES Boost::conversion Boost::core)
|
|
||||||
|
|
||||||
boost_test(TYPE run SOURCES cast_test.cpp)
|
|
||||||
boost_test(TYPE run SOURCES implicit_cast.cpp)
|
|
||||||
boost_test(TYPE compile-fail SOURCES implicit_cast_fail.cpp)
|
|
||||||
boost_test(TYPE compile-fail SOURCES implicit_cast_fail2.cpp)
|
|
||||||
boost_test(TYPE run SOURCES polymorphic_cast_test.cpp LINK_LIBRARIES Boost::smart_ptr)
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
# Copyright (C) 2001-2003 Douglas Gregor
|
|
||||||
# Copyright (C) Antony Polukhin, 2011-2024
|
|
||||||
#
|
|
||||||
# Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
#
|
|
||||||
|
|
||||||
require-b2 5.0.1 ;
|
|
||||||
import-search /boost/config/checks ;
|
|
||||||
import config : requires ;
|
|
||||||
import testing ;
|
|
||||||
import feature ;
|
|
||||||
|
|
||||||
project
|
|
||||||
: requirements
|
|
||||||
<library>/boost/conversion//boost_conversion
|
|
||||||
[ requires cxx11_decltype ]
|
|
||||||
# default to all warnings on:
|
|
||||||
<warnings>all
|
|
||||||
# set warnings as errors for those compilers we know we get warning free:
|
|
||||||
<toolset>gcc:<cxxflags>-Wextra
|
|
||||||
<toolset>gcc:<cxxflags>-Wno-uninitialized
|
|
||||||
;
|
|
||||||
|
|
||||||
test-suite conversion
|
|
||||||
: [ run implicit_cast.cpp ]
|
|
||||||
[ compile-fail implicit_cast_fail.cpp ]
|
|
||||||
[ run cast_test.cpp ]
|
|
||||||
[ run polymorphic_cast_test.cpp : : : <library>/boost/smart_ptr//boost_smart_ptr ]
|
|
||||||
[ compile-fail implicit_cast_fail2.cpp ]
|
|
||||||
;
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
# Use, modification, and distribution are
|
|
||||||
# subject to the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
#
|
|
||||||
# Copyright Antony Polukhin, 2016-2025.
|
|
||||||
|
|
||||||
#
|
|
||||||
# See https://svn.boost.org/trac/boost/wiki/TravisCoverals for description of this file
|
|
||||||
# and how it can be used with Boost libraries.
|
|
||||||
#
|
|
||||||
# File revision #6
|
|
||||||
|
|
||||||
init:
|
|
||||||
# boost-local/libs/ folder to put this library into. This may be useful, if you're for example running Travis
|
|
||||||
# from `Boost.DLL` repo while Boost already has `dll` and with to replace `dll` with content of`Boost.DLL`.
|
|
||||||
#
|
|
||||||
# Otherwise just leave the default value - set BOOST_LIBS_FOLDER=%APPVEYOR_PROJECT_NAME%
|
|
||||||
- set BOOST_LIBS_FOLDER=%APPVEYOR_PROJECT_NAME%
|
|
||||||
|
|
||||||
###############################################################################################################
|
|
||||||
# From this point and below code is same for all the Boost libs
|
|
||||||
###############################################################################################################
|
|
||||||
|
|
||||||
version: 1.84.{build}-{branch}
|
|
||||||
|
|
||||||
# branches to build
|
|
||||||
branches:
|
|
||||||
except:
|
|
||||||
- gh-pages
|
|
||||||
|
|
||||||
skip_tags: true
|
|
||||||
|
|
||||||
environment:
|
|
||||||
matrix:
|
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
|
||||||
TOOLSET: msvc-14.1,clang-win
|
|
||||||
CXXSTD: 14,17
|
|
||||||
ADDRMD: 32,64
|
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
|
||||||
ADDPATH: C:\cygwin\bin;
|
|
||||||
TOOLSET: gcc
|
|
||||||
CXXSTD: 03,11,14,1z
|
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
|
||||||
ADDPATH: C:\cygwin64\bin;
|
|
||||||
TOOLSET: gcc
|
|
||||||
CXXSTD: 03,11,14,1z
|
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
|
||||||
ADDPATH: C:\mingw\bin;
|
|
||||||
TOOLSET: gcc
|
|
||||||
CXXSTD: 03,11,14,1z
|
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
|
||||||
ADDPATH: C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin;
|
|
||||||
TOOLSET: gcc
|
|
||||||
CXXSTD: 03,11,14,1z
|
|
||||||
|
|
||||||
before_build:
|
|
||||||
- set BOOST_BRANCH=develop
|
|
||||||
- if "%APPVEYOR_REPO_BRANCH%" == "master" set BOOST_BRANCH=master
|
|
||||||
- echo "Testing %APPVEYOR_PROJECT_NAME%"
|
|
||||||
# Cloning Boost libraries (fast nondeep cloning)
|
|
||||||
- set BOOST=C:/boost-local
|
|
||||||
- git clone -b %BOOST_BRANCH% --depth 10 https://github.com/boostorg/boost.git %BOOST%
|
|
||||||
- cd %BOOST%
|
|
||||||
- git submodule update --init --depth 10 tools/build tools/boostdep
|
|
||||||
|
|
||||||
- rm -rf %BOOST%/libs/%BOOST_LIBS_FOLDER%
|
|
||||||
- mv -f %APPVEYOR_BUILD_FOLDER% %BOOST%/libs/%BOOST_LIBS_FOLDER%
|
|
||||||
- python tools/boostdep/depinst/depinst.py --git_args "--depth 10 --jobs 2" %BOOST_LIBS_FOLDER%
|
|
||||||
|
|
||||||
build_script:
|
|
||||||
- cmd /c bootstrap
|
|
||||||
- b2.exe headers
|
|
||||||
- cd %BOOST%/libs/%BOOST_LIBS_FOLDER%/test
|
|
||||||
|
|
||||||
after_build:
|
|
||||||
before_test:
|
|
||||||
test_script:
|
|
||||||
- PATH=%ADDPATH%%PATH%
|
|
||||||
- if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD%
|
|
||||||
- if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD%
|
|
||||||
- echo "Running command ..\..\..\b2 -j3 toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release"
|
|
||||||
- ..\..\..\b2.exe -j3 toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release cxxflags="-DBOOST_TRAVISCI_BUILD"
|
|
||||||
|
|
||||||
after_test:
|
|
||||||
on_success:
|
|
||||||
on_failure:
|
|
||||||
on_finish:
|
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
// boost utility cast test program -----------------------------------------//
|
|
||||||
|
|
||||||
// (C) Copyright Beman Dawes, Dave Abrahams 1999. Distributed under the Boost
|
|
||||||
// Software License, Version 1.0. (See accompanying file
|
|
||||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
|
|
||||||
// See http://www.boost.org for most recent version including documentation.
|
|
||||||
|
|
||||||
// Revision History
|
|
||||||
// 28 Set 04 factored out numeric_cast<> test (Fernando Cacciola)
|
|
||||||
// 20 Jan 01 removed use of <limits> for portability to raw GCC (David Abrahams)
|
|
||||||
// 28 Jun 00 implicit_cast removed (Beman Dawes)
|
|
||||||
// 30 Aug 99 value_cast replaced by numeric_cast
|
|
||||||
// 3 Aug 99 Initial Version
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <boost/polymorphic_cast.hpp>
|
|
||||||
#include <boost/core/lightweight_test.hpp>
|
|
||||||
|
|
||||||
using namespace boost;
|
|
||||||
using std::cout;
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
struct Base
|
|
||||||
{
|
|
||||||
virtual char kind() { return 'B'; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Base2
|
|
||||||
{
|
|
||||||
virtual char kind2() { return '2'; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Derived : public Base, Base2
|
|
||||||
{
|
|
||||||
virtual char kind() { return 'D'; }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool compile_time_polymorphic_cast_check() {
|
|
||||||
#if defined(__cpp_constexpr) && __cpp_constexpr >= 201907L
|
|
||||||
Derived derived;
|
|
||||||
Base* base = &derived;
|
|
||||||
return polymorphic_cast<Derived*>(base) != nullptr;
|
|
||||||
#endif
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static_assert(
|
|
||||||
compile_time_polymorphic_cast_check(),
|
|
||||||
"polymorphic_cast does not work at compile time"
|
|
||||||
);
|
|
||||||
|
|
||||||
constexpr bool compile_time_polymorphic_downcast_check() {
|
|
||||||
#if defined(__cpp_constexpr) && __cpp_constexpr >= 201907L
|
|
||||||
Derived derived;
|
|
||||||
Base* base = &derived;
|
|
||||||
return polymorphic_downcast<Derived*>(base) != nullptr;
|
|
||||||
#endif
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static_assert(
|
|
||||||
compile_time_polymorphic_downcast_check(),
|
|
||||||
"polymorphic_downcast does not work at compile time"
|
|
||||||
);
|
|
||||||
|
|
||||||
constexpr bool compile_time_polymorphic_downcast2_check() {
|
|
||||||
#if defined(__cpp_constexpr) && __cpp_constexpr >= 201907L
|
|
||||||
Derived derived;
|
|
||||||
Base& base = derived;
|
|
||||||
Derived& derived_again = polymorphic_downcast<Derived&>(base);
|
|
||||||
(void)derived_again;
|
|
||||||
#endif
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static_assert(
|
|
||||||
compile_time_polymorphic_downcast2_check(),
|
|
||||||
"polymorphic_downcast does not work at compile time"
|
|
||||||
);
|
|
||||||
|
|
||||||
int main( int argc, char * argv[] )
|
|
||||||
{
|
|
||||||
# ifdef NDEBUG
|
|
||||||
cout << "NDEBUG is defined\n";
|
|
||||||
# else
|
|
||||||
cout << "NDEBUG is not defined\n";
|
|
||||||
# endif
|
|
||||||
|
|
||||||
cout << "\nBeginning tests...\n";
|
|
||||||
|
|
||||||
// test polymorphic_cast ---------------------------------------------------//
|
|
||||||
|
|
||||||
// tests which should succeed
|
|
||||||
Derived derived_instance;
|
|
||||||
Base * base = &derived_instance;
|
|
||||||
Derived * derived = polymorphic_downcast<Derived*>( base ); // downcast
|
|
||||||
BOOST_TEST( derived->kind() == 'D' );
|
|
||||||
|
|
||||||
derived = polymorphic_cast<Derived*>( base ); // downcast, throw on error
|
|
||||||
BOOST_TEST( derived->kind() == 'D' );
|
|
||||||
|
|
||||||
Base2 * base2 = polymorphic_cast<Base2*>( base ); // crosscast
|
|
||||||
BOOST_TEST( base2->kind2() == '2' );
|
|
||||||
|
|
||||||
// tests which should result in errors being detected
|
|
||||||
Base base_instance;
|
|
||||||
base = &base_instance;
|
|
||||||
|
|
||||||
if ( argc > 1 && *argv[1] == '1' )
|
|
||||||
{ derived = polymorphic_downcast<Derived*>( base ); } // #1 assert failure
|
|
||||||
|
|
||||||
bool caught_exception = false;
|
|
||||||
try { derived = polymorphic_cast<Derived*>( base ); }
|
|
||||||
catch (const std::bad_cast&)
|
|
||||||
{ cout<<"caught bad_cast\n"; caught_exception = true; }
|
|
||||||
BOOST_TEST( caught_exception );
|
|
||||||
// the following is just so generated code can be inspected
|
|
||||||
BOOST_TEST( derived->kind() != 'B' );
|
|
||||||
|
|
||||||
return boost::report_errors();
|
|
||||||
} // main
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
// Copyright David Abrahams 2003.
|
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See
|
|
||||||
// accompanying file LICENSE_1_0.txt or copy at
|
|
||||||
// http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
|
|
||||||
#include <boost/implicit_cast.hpp>
|
|
||||||
#include <boost/core/lightweight_test.hpp>
|
|
||||||
#include <boost/type.hpp>
|
|
||||||
|
|
||||||
using boost::implicit_cast;
|
|
||||||
using boost::type;
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
type<T> check_return(T) { return type<T>(); }
|
|
||||||
|
|
||||||
struct foo
|
|
||||||
{
|
|
||||||
foo(char const*) {}
|
|
||||||
operator long() const { return 0; }
|
|
||||||
};
|
|
||||||
|
|
||||||
using long_type = type<long>;
|
|
||||||
using foo_type = type<foo>;
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
type<long> x = check_return(boost::implicit_cast<long>(1));
|
|
||||||
BOOST_TEST(boost::implicit_cast<long>(1) == 1L);
|
|
||||||
|
|
||||||
type<foo> f = check_return(boost::implicit_cast<foo>("hello"));
|
|
||||||
type<long> z = check_return(boost::implicit_cast<long>(foo("hello")));
|
|
||||||
|
|
||||||
// warning suppression:
|
|
||||||
(void)x;
|
|
||||||
(void)f;
|
|
||||||
(void)z;
|
|
||||||
|
|
||||||
|
|
||||||
constexpr long value = boost::implicit_cast<long>(42);
|
|
||||||
BOOST_TEST(value == 42L);
|
|
||||||
|
|
||||||
return boost::report_errors();
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
// Copyright David Abrahams 2003.
|
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See
|
|
||||||
// accompanying file LICENSE_1_0.txt or copy at
|
|
||||||
// http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
|
|
||||||
#include <boost/implicit_cast.hpp>
|
|
||||||
|
|
||||||
using boost::implicit_cast;
|
|
||||||
|
|
||||||
struct foo
|
|
||||||
{
|
|
||||||
explicit foo(char const*) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
foo x = implicit_cast<foo>("foobar");
|
|
||||||
(void)x; // warning suppression.
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
//
|
|
||||||
// Test that implicit_cast requires a template argument
|
|
||||||
//
|
|
||||||
// Copyright 2014 Peter Dimov
|
|
||||||
//
|
|
||||||
// Distributed under the Boost Software License, Version 1.0.
|
|
||||||
//
|
|
||||||
// See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <boost/implicit_cast.hpp>
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
int x = boost::implicit_cast( 1 );
|
|
||||||
(void)x;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,383 +0,0 @@
|
|||||||
//
|
|
||||||
// Test boost::polymorphic_cast, boost::polymorphic_downcast and
|
|
||||||
// boost::polymorphic_pointer_cast, boost::polymorphic_pointer_downcast
|
|
||||||
//
|
|
||||||
// Copyright 1999 Beman Dawes
|
|
||||||
// Copyright 1999 Dave Abrahams
|
|
||||||
// Copyright 2014 Peter Dimov
|
|
||||||
// Copyright 2014 Boris Rasin, Antony Polukhin
|
|
||||||
// Copyright 2023 Antony Polukhin
|
|
||||||
//
|
|
||||||
// Distributed under the Boost Software License, Version 1.0.
|
|
||||||
//
|
|
||||||
// See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt
|
|
||||||
//
|
|
||||||
|
|
||||||
#define BOOST_ENABLE_ASSERT_HANDLER
|
|
||||||
#include <boost/polymorphic_cast.hpp>
|
|
||||||
#include <boost/polymorphic_pointer_cast.hpp>
|
|
||||||
#include <boost/smart_ptr/shared_ptr.hpp>
|
|
||||||
#include <boost/smart_ptr/intrusive_ptr.hpp>
|
|
||||||
#include <boost/smart_ptr/intrusive_ref_counter.hpp>
|
|
||||||
#include <boost/core/lightweight_test.hpp>
|
|
||||||
#include <string>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
static bool expect_assertion = false;
|
|
||||||
static int assertion_failed_count = 0;
|
|
||||||
|
|
||||||
//assertion handler throws it to exit like assert, but to be able to catch it and stop
|
|
||||||
//usage: BOOST_TEST_THROWS( function_with_assert(), expected_assertion );
|
|
||||||
struct expected_assertion {};
|
|
||||||
|
|
||||||
// BOOST_ASSERT custom handler
|
|
||||||
void boost::assertion_failed( char const * expr, char const * function, char const * file, long line )
|
|
||||||
{
|
|
||||||
if( expect_assertion )
|
|
||||||
{
|
|
||||||
++assertion_failed_count;
|
|
||||||
throw expected_assertion();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
BOOST_ERROR( "unexpected assertion" );
|
|
||||||
|
|
||||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM
|
|
||||||
<< file << "(" << line << "): assertion '" << expr << "' failed in function '"
|
|
||||||
<< function << "'" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
struct Base : boost::intrusive_ref_counter<Base>
|
|
||||||
{
|
|
||||||
virtual ~Base() {}
|
|
||||||
virtual std::string kind() { return "Base"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Base2
|
|
||||||
{
|
|
||||||
virtual ~Base2() {}
|
|
||||||
virtual std::string kind2() { return "Base2"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Derived : public Base, Base2
|
|
||||||
{
|
|
||||||
virtual std::string kind() { return "Derived"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
static void test_polymorphic_cast()
|
|
||||||
{
|
|
||||||
Base * base = new Derived;
|
|
||||||
|
|
||||||
Derived * derived;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
derived = boost::polymorphic_cast<Derived*>( base );
|
|
||||||
|
|
||||||
BOOST_TEST( derived != 0 );
|
|
||||||
|
|
||||||
if( derived != 0 )
|
|
||||||
{
|
|
||||||
BOOST_TEST_EQ( derived->kind(), "Derived" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch( std::bad_cast const& )
|
|
||||||
{
|
|
||||||
BOOST_ERROR( "boost::polymorphic_cast<Derived*>( base ) threw std::bad_cast" );
|
|
||||||
}
|
|
||||||
|
|
||||||
Base2 * base2;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
base2 = boost::polymorphic_cast<Base2*>( base ); // crosscast
|
|
||||||
|
|
||||||
BOOST_TEST( base2 != 0 );
|
|
||||||
|
|
||||||
if( base2 != 0 )
|
|
||||||
{
|
|
||||||
BOOST_TEST_EQ( base2->kind2(), "Base2" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch( std::bad_cast const& )
|
|
||||||
{
|
|
||||||
BOOST_ERROR( "boost::polymorphic_cast<Base2*>( base ) threw std::bad_cast" );
|
|
||||||
}
|
|
||||||
|
|
||||||
delete base;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_polymorphic_pointer_cast()
|
|
||||||
{
|
|
||||||
Base * base = new Derived;
|
|
||||||
|
|
||||||
Derived * derived;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
derived = boost::polymorphic_pointer_cast<Derived>( base );
|
|
||||||
|
|
||||||
BOOST_TEST( derived != 0 );
|
|
||||||
|
|
||||||
if( derived != 0 )
|
|
||||||
{
|
|
||||||
BOOST_TEST_EQ( derived->kind(), "Derived" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch( std::bad_cast const& )
|
|
||||||
{
|
|
||||||
BOOST_ERROR( "boost::polymorphic_pointer_cast<Derived>( base ) threw std::bad_cast" );
|
|
||||||
}
|
|
||||||
|
|
||||||
Base2 * base2;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
base2 = boost::polymorphic_pointer_cast<Base2>( base ); // crosscast
|
|
||||||
|
|
||||||
BOOST_TEST( base2 != 0 );
|
|
||||||
|
|
||||||
if( base2 != 0 )
|
|
||||||
{
|
|
||||||
BOOST_TEST_EQ( base2->kind2(), "Base2" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch( std::bad_cast const& )
|
|
||||||
{
|
|
||||||
BOOST_ERROR( "boost::polymorphic_pointer_cast<Base2>( base ) threw std::bad_cast" );
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::shared_ptr<Base> sp_base( base );
|
|
||||||
boost::shared_ptr<Base2> sp_base2;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
sp_base2 = boost::polymorphic_pointer_cast<Base2>( sp_base ); // crosscast
|
|
||||||
|
|
||||||
BOOST_TEST( sp_base2 != 0 );
|
|
||||||
|
|
||||||
if( sp_base2 != 0 )
|
|
||||||
{
|
|
||||||
BOOST_TEST_EQ( sp_base2->kind2(), "Base2" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch( std::bad_cast const& )
|
|
||||||
{
|
|
||||||
BOOST_ERROR( "boost::polymorphic_pointer_cast<Base2>( sp_base ) threw std::bad_cast" );
|
|
||||||
}
|
|
||||||
|
|
||||||
// we do not `delete base;` because sahred_ptr is holding base
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_polymorphic_downcast()
|
|
||||||
{
|
|
||||||
Base *base_pointer = new Derived;
|
|
||||||
|
|
||||||
// test raw pointer cast
|
|
||||||
Derived *derived_pointer = boost::polymorphic_downcast<Derived *>(base_pointer);
|
|
||||||
|
|
||||||
BOOST_TEST(derived_pointer != 0);
|
|
||||||
|
|
||||||
if (derived_pointer != 0)
|
|
||||||
{
|
|
||||||
BOOST_TEST_EQ(derived_pointer->kind(), "Derived");
|
|
||||||
}
|
|
||||||
|
|
||||||
// test reference cast
|
|
||||||
Derived& derived_ref = boost::polymorphic_downcast<Derived&>(*base_pointer);
|
|
||||||
BOOST_TEST_EQ(derived_ref.kind(), "Derived");
|
|
||||||
|
|
||||||
delete base_pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_polymorphic_pointer_downcast_builtin()
|
|
||||||
{
|
|
||||||
Base * base = new Derived;
|
|
||||||
|
|
||||||
Derived * derived = boost::polymorphic_pointer_downcast<Derived>( base );
|
|
||||||
|
|
||||||
BOOST_TEST( derived != 0 );
|
|
||||||
|
|
||||||
if( derived != 0 )
|
|
||||||
{
|
|
||||||
BOOST_TEST_EQ( derived->kind(), "Derived" );
|
|
||||||
}
|
|
||||||
|
|
||||||
// polymorphic_pointer_downcast can't do crosscasts
|
|
||||||
|
|
||||||
delete base;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_polymorphic_pointer_downcast_boost_shared()
|
|
||||||
{
|
|
||||||
boost::shared_ptr<Base> base (new Derived);
|
|
||||||
|
|
||||||
boost::shared_ptr<Derived> derived = boost::polymorphic_pointer_downcast<Derived>( base );
|
|
||||||
|
|
||||||
BOOST_TEST( derived != 0 );
|
|
||||||
|
|
||||||
if( derived != 0 )
|
|
||||||
{
|
|
||||||
BOOST_TEST_EQ( derived->kind(), "Derived" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_polymorphic_pointer_downcast_intrusive()
|
|
||||||
{
|
|
||||||
boost::intrusive_ptr<Base> base (new Derived);
|
|
||||||
|
|
||||||
boost::intrusive_ptr<Derived> derived = boost::polymorphic_pointer_downcast<Derived>( base );
|
|
||||||
|
|
||||||
BOOST_TEST( derived != 0 );
|
|
||||||
|
|
||||||
if( derived != 0 )
|
|
||||||
{
|
|
||||||
BOOST_TEST_EQ( derived->kind(), "Derived" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_polymorphic_pointer_downcast_std_shared()
|
|
||||||
{
|
|
||||||
std::shared_ptr<Base> base (new Derived);
|
|
||||||
|
|
||||||
std::shared_ptr<Derived> derived = boost::polymorphic_pointer_downcast<Derived>( base );
|
|
||||||
|
|
||||||
BOOST_TEST( derived != 0 );
|
|
||||||
|
|
||||||
if( derived != 0 )
|
|
||||||
{
|
|
||||||
BOOST_TEST_EQ( derived->kind(), "Derived" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_polymorphic_cast_fail()
|
|
||||||
{
|
|
||||||
Base * base = new Base;
|
|
||||||
|
|
||||||
BOOST_TEST_THROWS( boost::polymorphic_cast<Derived*>( base ), std::bad_cast );
|
|
||||||
|
|
||||||
delete base;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_polymorphic_pointer_cast_fail()
|
|
||||||
{
|
|
||||||
Base * base = new Base;
|
|
||||||
BOOST_TEST_THROWS( boost::polymorphic_pointer_cast<Derived>( base ), std::bad_cast );
|
|
||||||
delete base;
|
|
||||||
|
|
||||||
BOOST_TEST_THROWS( boost::polymorphic_pointer_cast<Derived>( boost::shared_ptr<Base>(new Base) ), std::bad_cast );
|
|
||||||
|
|
||||||
BOOST_TEST_THROWS( boost::polymorphic_pointer_cast<Derived>( std::shared_ptr<Base>(new Base) ), std::bad_cast );
|
|
||||||
|
|
||||||
BOOST_TEST_THROWS( boost::polymorphic_pointer_cast<Derived>( boost::intrusive_ptr<Base>(new Base) ), std::bad_cast );
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_polymorphic_downcast_fail()
|
|
||||||
{
|
|
||||||
Base * base_pointer = new Base;
|
|
||||||
|
|
||||||
{
|
|
||||||
// test raw pointer cast
|
|
||||||
|
|
||||||
int old_count = assertion_failed_count;
|
|
||||||
expect_assertion = true;
|
|
||||||
|
|
||||||
BOOST_TEST_THROWS(boost::polymorphic_downcast<Derived *>(base_pointer), expected_assertion); // should assert
|
|
||||||
|
|
||||||
BOOST_TEST_EQ(assertion_failed_count, old_count + 1);
|
|
||||||
expect_assertion = false;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
// test reference cast
|
|
||||||
|
|
||||||
int old_count = assertion_failed_count;
|
|
||||||
expect_assertion = true;
|
|
||||||
|
|
||||||
BOOST_TEST_THROWS(boost::polymorphic_downcast<Derived &>(*base_pointer), expected_assertion); // should assert
|
|
||||||
|
|
||||||
BOOST_TEST_EQ(assertion_failed_count, old_count + 1);
|
|
||||||
expect_assertion = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete base_pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_polymorphic_pointer_downcast_builtin_fail()
|
|
||||||
{
|
|
||||||
Base * base = new Base;
|
|
||||||
|
|
||||||
int old_count = assertion_failed_count;
|
|
||||||
expect_assertion = true;
|
|
||||||
|
|
||||||
BOOST_TEST_THROWS( boost::polymorphic_pointer_downcast<Derived>( base ), expected_assertion ); // should assert
|
|
||||||
|
|
||||||
BOOST_TEST_EQ( assertion_failed_count, old_count + 1 );
|
|
||||||
expect_assertion = false;
|
|
||||||
|
|
||||||
delete base;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_polymorphic_pointer_downcast_boost_shared_fail()
|
|
||||||
{
|
|
||||||
boost::shared_ptr<Base> base (new Base);
|
|
||||||
|
|
||||||
int old_count = assertion_failed_count;
|
|
||||||
expect_assertion = true;
|
|
||||||
|
|
||||||
BOOST_TEST_THROWS( boost::polymorphic_pointer_downcast<Derived>( base ), expected_assertion ); // should assert
|
|
||||||
|
|
||||||
BOOST_TEST_EQ( assertion_failed_count, old_count + 1 );
|
|
||||||
expect_assertion = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void test_polymorphic_pointer_downcast_std_shared_fail()
|
|
||||||
{
|
|
||||||
std::shared_ptr<Base> base (new Base);
|
|
||||||
|
|
||||||
int old_count = assertion_failed_count;
|
|
||||||
expect_assertion = true;
|
|
||||||
|
|
||||||
BOOST_TEST_THROWS( boost::polymorphic_pointer_downcast<Derived>( base ), expected_assertion ); // should assert
|
|
||||||
|
|
||||||
BOOST_TEST_EQ( assertion_failed_count, old_count + 1 );
|
|
||||||
expect_assertion = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void test_polymorphic_pointer_downcast_intrusive_fail()
|
|
||||||
{
|
|
||||||
boost::intrusive_ptr<Base> base (new Base);
|
|
||||||
|
|
||||||
int old_count = assertion_failed_count;
|
|
||||||
expect_assertion = true;
|
|
||||||
|
|
||||||
BOOST_TEST_THROWS( boost::polymorphic_pointer_downcast<Derived>( base ), expected_assertion); // should assert
|
|
||||||
|
|
||||||
BOOST_TEST_EQ( assertion_failed_count, old_count + 1 );
|
|
||||||
expect_assertion = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
test_polymorphic_cast();
|
|
||||||
test_polymorphic_pointer_cast();
|
|
||||||
test_polymorphic_downcast();
|
|
||||||
test_polymorphic_pointer_downcast_builtin();
|
|
||||||
test_polymorphic_pointer_downcast_boost_shared();
|
|
||||||
test_polymorphic_pointer_downcast_intrusive();
|
|
||||||
test_polymorphic_cast_fail();
|
|
||||||
test_polymorphic_pointer_cast_fail();
|
|
||||||
test_polymorphic_downcast_fail();
|
|
||||||
test_polymorphic_pointer_downcast_builtin_fail();
|
|
||||||
test_polymorphic_pointer_downcast_boost_shared_fail();
|
|
||||||
test_polymorphic_pointer_downcast_intrusive_fail();
|
|
||||||
|
|
||||||
test_polymorphic_pointer_downcast_std_shared();
|
|
||||||
test_polymorphic_pointer_downcast_std_shared_fail();
|
|
||||||
|
|
||||||
|
|
||||||
return boost::report_errors();
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user