forked from boostorg/type_index
Compare commits
285 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
29ab3258a7 | ||
|
|
4a04bb5f46 | ||
|
|
34e6c165da | ||
|
|
034d105a48 | ||
|
|
62a3c9e89f | ||
|
|
b9815d397b | ||
|
|
7bde4f36af | ||
|
|
b66e6cf881 | ||
|
|
ad7e8f7e4b | ||
|
|
6fcb86f6cc | ||
|
|
b8e658c5bd | ||
|
|
9507b06b68 | ||
|
|
9f35fab4cf | ||
|
|
d4fe92e302 | ||
|
|
cca370a918 | ||
|
|
97fc5b9838 | ||
|
|
0cc169ecd6 | ||
|
|
a3c6a957ee | ||
|
|
04cc1734ef | ||
|
|
f395836779 | ||
|
|
4f51b1f4eb | ||
|
|
a2ef72c907 | ||
|
|
331c26760e | ||
|
|
d6d07a8ce8 | ||
|
|
4468903f8f | ||
|
|
88c5d9a998 | ||
|
|
f0b87ea7d3 | ||
|
|
03794d6144 | ||
|
|
62154d3b19 | ||
|
|
b4014f385d | ||
|
|
0dc42bab8f | ||
|
|
a4726d239f | ||
|
|
f40f4731e1 | ||
|
|
754fb0f348 | ||
|
|
6fa4f57e7d | ||
|
|
c79f1c8d5d | ||
|
|
843ee6848b | ||
|
|
6fc5b35b00 | ||
|
|
84d68f32e2 | ||
|
|
1dacdb561e | ||
|
|
9862011b6b | ||
|
|
321749796e | ||
|
|
f2e395a7f3 | ||
|
|
9936c31851 | ||
|
|
560c7d2ef6 | ||
|
|
bf33e63feb | ||
|
|
2152466531 | ||
|
|
389f621450 | ||
|
|
0b65c1a8d8 | ||
|
|
216c21b728 | ||
|
|
afd1b6cdc8 | ||
|
|
d69a8a211b | ||
|
|
ebe74ba4ba | ||
|
|
ac4fec435f | ||
|
|
f68d6dc073 | ||
|
|
85f43ece0d | ||
|
|
a2de6a56f3 | ||
|
|
c585d74669 | ||
|
|
32909cb25a | ||
|
|
7af1661709 | ||
|
|
351cedf404 | ||
|
|
098c84481e | ||
|
|
d9d13b9574 | ||
|
|
44ca756e32 | ||
|
|
acb536a67e | ||
|
|
7654c26594 | ||
|
|
075b3682ae | ||
|
|
a60e25a74d | ||
|
|
cd1c905f87 | ||
|
|
f3da852bca | ||
|
|
a8fafd93f9 | ||
|
|
01944bf377 | ||
|
|
09f0bc23c5 | ||
|
|
718af3e8dc | ||
|
|
c9c1412a05 | ||
|
|
c2caa340ab | ||
|
|
da0a181117 | ||
|
|
be9f5a4b9b | ||
|
|
bd19ed1a87 | ||
|
|
727cdadc86 | ||
|
|
5bc4f54183 | ||
|
|
918e59c109 | ||
|
|
cd659212aa | ||
|
|
70e51a62e9 | ||
|
|
05feacf14b | ||
|
|
82ed016577 | ||
|
|
1a7226bc0f | ||
|
|
be08eda196 | ||
|
|
baa5019c90 | ||
|
|
4585bab3c3 | ||
|
|
93e7b2458b | ||
|
|
09ac338acc | ||
|
|
b0737f4169 | ||
|
|
be74716251 | ||
|
|
f82eab8882 | ||
|
|
af61d6b8ed | ||
|
|
d3d4e8d18a | ||
|
|
7f8af2a6e9 | ||
|
|
342d835289 | ||
|
|
5cacb67510 | ||
|
|
f2616bcd17 | ||
|
|
8c582362d0 | ||
|
|
f71d9eb3f2 | ||
|
|
cfcdcd647d | ||
|
|
8bee2f6939 | ||
|
|
40985de221 | ||
|
|
d8bdbad2ec | ||
|
|
c52fdfe30c | ||
|
|
7f840c882e | ||
|
|
b669f0244e | ||
|
|
d656e1879a | ||
|
|
b1ed011b6e | ||
|
|
4d1cf425e0 | ||
|
|
d6ca24ff3c | ||
|
|
4459af9532 | ||
|
|
b61a7423b7 | ||
|
|
1a918009fd | ||
|
|
045ab1d779 | ||
|
|
6cf5288a8c | ||
|
|
4453acf867 | ||
|
|
b6b23bad3a | ||
|
|
3bb646d19b | ||
|
|
9cd218bbc4 | ||
|
|
ad26256d09 | ||
|
|
5af925602e | ||
|
|
2fb667a6a0 | ||
|
|
12751e0f83 | ||
|
|
0b006b6af6 | ||
|
|
76cae485cb | ||
|
|
ee7b15a493 | ||
|
|
1dc8310826 | ||
|
|
b230140529 | ||
|
|
31ec1d2524 | ||
|
|
40e9bd336a | ||
|
|
767c724983 | ||
|
|
24708cc109 | ||
|
|
57205874ae | ||
|
|
1b4a85764f | ||
|
|
1976355e8f | ||
|
|
0efc48e16c | ||
|
|
e96a6e8f80 | ||
|
|
8e3466ece5 | ||
|
|
8b6c3facb3 | ||
|
|
ffb98af0dd | ||
|
|
9122022faf | ||
|
|
18dbaea6ee | ||
|
|
6dabf11504 | ||
|
|
7bd788c5d7 | ||
|
|
2d87bc6194 | ||
|
|
36efa3969b | ||
|
|
551535f8cf | ||
|
|
3f004511a2 | ||
|
|
30bb93bd23 | ||
|
|
7f2b9fd31a | ||
|
|
c9f1370d0c | ||
|
|
1ec4460244 | ||
|
|
1ed55a2f12 | ||
|
|
1c685fa119 | ||
|
|
37484c19ec | ||
|
|
bb02f97414 | ||
|
|
b9db462091 | ||
|
|
cf4f09b520 | ||
|
|
5de7f5def6 | ||
|
|
1c8190cc62 | ||
|
|
6ff2a75da3 | ||
|
|
58b0f69e52 | ||
|
|
478da3512a | ||
|
|
a373a4c7ed | ||
|
|
34835b90e3 | ||
|
|
236fdc8dba | ||
|
|
1ff942f329 | ||
|
|
f58844637c | ||
|
|
9fede62a7c | ||
|
|
48d50ae178 | ||
|
|
743b2a8851 | ||
|
|
7e2a538eb5 | ||
|
|
e5e105013a | ||
|
|
d7ec25e56b | ||
|
|
c0f75c27fa | ||
|
|
3e6695971d | ||
|
|
8d3127935d | ||
|
|
d585fc3673 | ||
|
|
6b5d2743c5 | ||
|
|
8558fd66ef | ||
|
|
8ddc5feac4 | ||
|
|
8b7534889b | ||
|
|
697e09bda9 | ||
|
|
242d9a0bed | ||
|
|
99f58714d1 | ||
|
|
7b04caa160 | ||
|
|
4d221d4f71 | ||
|
|
806a192df1 | ||
|
|
1633adfee4 | ||
|
|
c3a26dff9a | ||
|
|
436ecd0b3e | ||
|
|
9fcbfd18ce | ||
|
|
1916e2b42f | ||
|
|
56bd9b401a | ||
|
|
e2c227d4aa | ||
|
|
80086cbc4f | ||
|
|
0f0902d11c | ||
|
|
6857f23e6f | ||
|
|
ce103443fd | ||
|
|
b34d4d466d | ||
|
|
441a71c3d1 | ||
|
|
ae946ee496 | ||
|
|
76dc3d1053 | ||
|
|
28c77f4036 | ||
|
|
631e592b7a | ||
|
|
fa2fa1805c | ||
|
|
0744f86a2c | ||
|
|
61594ba1da | ||
|
|
e2ceb6cf36 | ||
|
|
a397391b0e | ||
|
|
8c8d9c6c69 | ||
|
|
eac9c8af2f | ||
|
|
4cc0272bd2 | ||
|
|
ecac9ac83c | ||
|
|
8a8a3ec639 | ||
|
|
6931c1de4c | ||
|
|
7ba3f29da1 | ||
|
|
a184f3969f | ||
|
|
f7388d59b5 | ||
|
|
2602569bc4 | ||
|
|
172d4a25ca | ||
|
|
6af608a827 | ||
|
|
5ed8543025 | ||
|
|
a66ffcfa50 | ||
|
|
2e11dc75d4 | ||
|
|
a2a934dde8 | ||
|
|
3f51425f3c | ||
|
|
501a0a992e | ||
|
|
b8265cdb4f | ||
|
|
89398ac07c | ||
|
|
40f6ae1ede | ||
|
|
2ebd172f4e | ||
|
|
70fdaa633e | ||
|
|
7ddb306c65 | ||
|
|
7488e75a9c | ||
|
|
b44845b46d | ||
|
|
0d8c6f36ad | ||
|
|
98e5bbe6ac | ||
|
|
276101f1b3 | ||
|
|
ea2e5beabb | ||
|
|
c99b7b26da | ||
|
|
78824176ea | ||
|
|
de0d90eca1 | ||
|
|
2ef8924510 | ||
|
|
beaa53f460 | ||
|
|
0137b9b43f | ||
|
|
683dab93a2 | ||
|
|
496ab93589 | ||
|
|
c0871ef714 | ||
|
|
2f9c4b7834 | ||
|
|
c43f8c1cfa | ||
|
|
50d496288f | ||
|
|
3daeab38fa | ||
|
|
5f97225a18 | ||
|
|
5977f9ce6e | ||
|
|
9ea436c4d3 | ||
|
|
9e4e48a9b3 | ||
|
|
986ff55058 | ||
|
|
736bdd4e04 | ||
|
|
45649b44e5 | ||
|
|
477a7b0c2c | ||
|
|
9aef004abc | ||
|
|
2a086a81c5 | ||
|
|
c2910c18a8 | ||
|
|
860c454c93 | ||
|
|
a37c8ed87c | ||
|
|
19fef8ddab | ||
|
|
79fbd3ab5c | ||
|
|
868328d2f6 | ||
|
|
83e02d83c4 | ||
|
|
cadd22c74d | ||
|
|
1508e1d560 | ||
|
|
d0d30d56df | ||
|
|
8ab45702a0 | ||
|
|
8789bff181 | ||
|
|
2a45139fd3 | ||
|
|
5d71c723cc | ||
|
|
cf4096d317 | ||
|
|
3f48978268 | ||
|
|
69a4fddfb6 | ||
|
|
300001d7c7 |
192
.github/workflows/ci.yml
vendored
Normal file
192
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
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-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"
|
||||
launcher: "testing.launcher=LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libasan.so.8"
|
||||
- toolset: gcc-11
|
||||
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-11"
|
||||
launcher: "testing.launcher=LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libasan.so.6"
|
||||
- toolset: gcc-10
|
||||
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-10"
|
||||
launcher: "testing.launcher=LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libasan.so.6"
|
||||
- toolset: gcc-9
|
||||
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-9"
|
||||
launcher: "testing.launcher=LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libasan.so.5"
|
||||
- toolset: clang
|
||||
compiler: clang++-14
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-22.04
|
||||
- toolset: clang
|
||||
compiler: clang++-10
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-20.04
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- 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 -d0 headers
|
||||
./b2 -j4 variant=debug tools/inspect/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.15.zip
|
||||
unzip v1.15.zip
|
||||
LCOV="`pwd`/lcov-1.15/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.0
|
||||
cxxstd: "14,latest"
|
||||
addrmd: 32,64
|
||||
os: windows-2019
|
||||
- toolset: msvc-14.2
|
||||
cxxstd: "14,17,20,latest"
|
||||
addrmd: 32,64
|
||||
os: windows-2019
|
||||
- toolset: msvc-14.3
|
||||
cxxstd: "14,17,20,latest"
|
||||
addrmd: 32,64
|
||||
os: windows-2022
|
||||
- toolset: clang-win
|
||||
cxxstd: "14,17,latest"
|
||||
addrmd: 32,64
|
||||
os: windows-2022
|
||||
- toolset: gcc
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
addrmd: 64
|
||||
os: windows-2019
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- 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
|
||||
b2 -d0 headers
|
||||
|
||||
- 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 embed-manifest-via=linker
|
||||
|
||||
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
|
||||
378
.gitignore
vendored
378
.gitignore
vendored
@@ -1,376 +1,2 @@
|
||||
# Ignore docs/html directory, that is actually a `gh-pages` branch
|
||||
/libs/type_index/doc/autodoc.xml
|
||||
/libs/type_index/doc/html/
|
||||
|
||||
|
||||
# While testing I use this project inside the SVN's /boost/trunk folders
|
||||
# Follwoing rules ignore all the /boost's files, without ignorng the TypeIndex library
|
||||
|
||||
*~
|
||||
*.svn
|
||||
/boost/.svn/
|
||||
/boost/accumulators
|
||||
/boost/algorithm
|
||||
/boost/aligned_storage.hpp
|
||||
/boost/any.hpp
|
||||
/boost/any.hpp~
|
||||
/boost/archive
|
||||
/boost/array.hpp
|
||||
/boost/asio
|
||||
/boost/asio.hpp
|
||||
/boost/assert.hpp
|
||||
/boost/assign
|
||||
/boost/assign.hpp
|
||||
/boost/atomic
|
||||
/boost/atomic.hpp
|
||||
/boost/bimap
|
||||
/boost/bimap.hpp
|
||||
/boost/bind
|
||||
/boost/bind.hpp
|
||||
/boost/blank_fwd.hpp
|
||||
/boost/blank.hpp
|
||||
/boost/call_traits.hpp
|
||||
/boost/cast.hpp
|
||||
/boost/cerrno.hpp
|
||||
/boost/checked_delete.hpp
|
||||
/boost/chrono
|
||||
/boost/chrono.hpp
|
||||
/boost/circular_buffer
|
||||
/boost/circular_buffer_fwd.hpp
|
||||
/boost/circular_buffer.hpp
|
||||
/boost/compatibility
|
||||
/boost/compressed_pair.hpp
|
||||
/boost/concept
|
||||
/boost/concept_archetype.hpp
|
||||
/boost/concept_check
|
||||
/boost/concept_check.hpp
|
||||
/boost/config
|
||||
/boost/config.hpp
|
||||
/boost/container
|
||||
/boost/context
|
||||
/boost/coroutine
|
||||
/boost/crc.hpp
|
||||
/boost/cregex.hpp
|
||||
/boost/cstdint.hpp
|
||||
/boost/cstdlib.hpp
|
||||
/boost/current_function.hpp
|
||||
/boost/date_time
|
||||
/boost/date_time.hpp
|
||||
/boost/detail
|
||||
/boost/dynamic_bitset
|
||||
/boost/dynamic_bitset_fwd.hpp
|
||||
/boost/dynamic_bitset.hpp
|
||||
/boost/enable_shared_from_this.hpp
|
||||
/boost/exception
|
||||
/boost/exception_ptr.hpp
|
||||
/boost/filesystem
|
||||
/boost/filesystem.hpp
|
||||
/boost/flyweight
|
||||
/boost/flyweight.hpp
|
||||
/boost/foreach_fwd.hpp
|
||||
/boost/foreach.hpp
|
||||
/boost/format
|
||||
/boost/format.hpp
|
||||
/boost/function
|
||||
/boost/functional
|
||||
/boost/functional.hpp
|
||||
/boost/function_equal.hpp
|
||||
/boost/function.hpp
|
||||
/boost/function_output_iterator.hpp
|
||||
/boost/function_types
|
||||
/boost/fusion
|
||||
/boost/generator_iterator.hpp
|
||||
/boost/geometry
|
||||
/boost/geometry.hpp
|
||||
/boost/get_pointer.hpp
|
||||
/boost/gil
|
||||
/boost/graph
|
||||
/boost/heap
|
||||
/boost/icl
|
||||
/boost/implicit_cast.hpp
|
||||
/boost/indirect_reference.hpp
|
||||
/boost/integer
|
||||
/boost/integer_fwd.hpp
|
||||
/boost/integer.hpp
|
||||
/boost/integer_traits.hpp
|
||||
/boost/interprocess
|
||||
/boost/intrusive
|
||||
/boost/intrusive_ptr.hpp
|
||||
/boost/io
|
||||
/boost/io_fwd.hpp
|
||||
/boost/iostreams
|
||||
/boost/is_placeholder.hpp
|
||||
/boost/iterator
|
||||
/boost/iterator_adaptors.hpp
|
||||
/boost/iterator.hpp
|
||||
/boost/lambda
|
||||
/boost/last_value.hpp
|
||||
/boost/lexical_cast.hpp
|
||||
/boost/lexical_cast.hpp~
|
||||
/boost/limits.hpp
|
||||
/boost/locale
|
||||
/boost/locale.hpp
|
||||
/boost/local_function
|
||||
/boost/local_function.hpp
|
||||
/boost/lockfree
|
||||
/boost/log
|
||||
/boost/logic
|
||||
/boost/make_shared.hpp
|
||||
/boost/math
|
||||
/boost/math_fwd.hpp
|
||||
/boost/mem_fn.hpp
|
||||
/boost/memory_order.hpp
|
||||
/boost/move
|
||||
/boost/mpi
|
||||
/boost/mpi.hpp
|
||||
/boost/mpl
|
||||
/boost/msm
|
||||
/boost/multi_array
|
||||
/boost/multi_array.hpp
|
||||
/boost/multi_index
|
||||
/boost/multi_index_container_fwd.hpp
|
||||
/boost/multi_index_container.hpp
|
||||
/boost/multiprecision
|
||||
/boost/next_prior.hpp
|
||||
/boost/noncopyable.hpp
|
||||
/boost/nondet_random.hpp
|
||||
/boost/none.hpp
|
||||
/boost/none_t.hpp
|
||||
/boost/non_type.hpp
|
||||
/boost/numeric
|
||||
/boost/operators.hpp
|
||||
/boost/optional
|
||||
/boost/optional.hpp
|
||||
/boost/parameter
|
||||
/boost/parameter.hpp
|
||||
/boost/pending
|
||||
/boost/phoenix
|
||||
/boost/phoenix.hpp
|
||||
/boost/pointee.hpp
|
||||
/boost/pointer_cast.hpp
|
||||
/boost/pointer_to_other.hpp
|
||||
/boost/polygon
|
||||
/boost/pool
|
||||
/boost/predef
|
||||
/boost/predef.h
|
||||
/boost/preprocessor
|
||||
/boost/preprocessor.hpp
|
||||
/boost/program_options
|
||||
/boost/program_options.hpp
|
||||
/boost/progress.hpp
|
||||
/boost/progress.hpp~
|
||||
/boost/property_map
|
||||
/boost/property_tree
|
||||
/boost/proto
|
||||
/boost/ptr_container
|
||||
/boost/python
|
||||
/boost/python.hpp
|
||||
/boost/random
|
||||
/boost/random.hpp
|
||||
/boost/range
|
||||
/boost/range.hpp
|
||||
/boost/ratio
|
||||
/boost/ratio.hpp
|
||||
/boost/rational.hpp
|
||||
/boost/rational.hpp.htm
|
||||
/boost/ref.hpp
|
||||
/boost/regex
|
||||
/boost/regex_fwd.hpp
|
||||
/boost/regex.h
|
||||
/boost/regex.hpp
|
||||
/boost/scoped_array.hpp
|
||||
/boost/scoped_ptr.hpp
|
||||
/boost/scope_exit.hpp
|
||||
/boost/serialization
|
||||
/boost/shared_array.hpp
|
||||
/boost/shared_container_iterator.hpp
|
||||
/boost/shared_ptr.hpp
|
||||
/boost/signal.hpp
|
||||
/boost/signals
|
||||
/boost/signals2
|
||||
/boost/signals2.hpp
|
||||
/boost/signals.hpp
|
||||
/boost/smart_ptr
|
||||
/boost/smart_ptr.hpp
|
||||
/boost/spirit
|
||||
/boost/spirit.hpp
|
||||
/boost/statechart
|
||||
/boost/static_assert.hpp
|
||||
/boost/strong_typedef.hpp
|
||||
/boost/swap.hpp
|
||||
/boost/sync
|
||||
/boost/system
|
||||
/boost/test
|
||||
/boost/thread
|
||||
/boost/thread.hpp
|
||||
/boost/throw_exception.hpp
|
||||
/boost/timer
|
||||
/boost/timer.hpp
|
||||
/boost/token_functions.hpp
|
||||
/boost/token_iterator.hpp
|
||||
/boost/tokenizer.hpp
|
||||
/boost/tr1
|
||||
/boost/tti
|
||||
/boost/tuple
|
||||
/boost/type_erasure
|
||||
/boost/type.hpp
|
||||
/boost/typeof
|
||||
/boost/type_traits
|
||||
/boost/type_traits.hpp
|
||||
/boost/type_traits.hpp~
|
||||
/boost/units
|
||||
/boost/unordered
|
||||
/boost/unordered_map.hpp
|
||||
/boost/unordered_set.hpp
|
||||
/boost/utility
|
||||
/boost/utility.hpp
|
||||
/boost/uuid
|
||||
/boost/variant
|
||||
/boost/variant.hpp
|
||||
/boost/version.hpp
|
||||
/boost/visit_each.hpp
|
||||
/boost/wave
|
||||
/boost/wave.hpp
|
||||
/boost/weak_ptr.hpp
|
||||
/boost/xpressive
|
||||
|
||||
|
||||
/libs/accumulators
|
||||
/libs/algorithm
|
||||
/libs/any
|
||||
/libs/array
|
||||
/libs/asio
|
||||
/libs/assign
|
||||
/libs/atomic
|
||||
/libs/bimap
|
||||
/libs/bind
|
||||
/libs/chrono
|
||||
/libs/circular_buffer
|
||||
/libs/compatibility
|
||||
/libs/compose
|
||||
/libs/concept_check
|
||||
/libs/config
|
||||
/libs/container
|
||||
/libs/context
|
||||
/libs/conversion
|
||||
/libs/coroutine
|
||||
/libs/crc
|
||||
/libs/date_time
|
||||
/libs/detail
|
||||
/libs/disjoint_sets
|
||||
/libs/dynamic_bitset
|
||||
/libs/exception
|
||||
/libs/filesystem
|
||||
/libs/flyweight
|
||||
/libs/foreach
|
||||
/libs/format
|
||||
/libs/function
|
||||
/libs/functional
|
||||
/libs/function_types
|
||||
/libs/fusion
|
||||
/libs/geometry
|
||||
/libs/gil
|
||||
/libs/graph
|
||||
/libs/graph_parallel
|
||||
/libs/heap
|
||||
/libs/icl
|
||||
/libs/index.html
|
||||
/libs/integer
|
||||
/libs/interprocess
|
||||
/libs/intrusive
|
||||
/libs/io
|
||||
/libs/iostreams
|
||||
/libs/iterator
|
||||
/libs/lambda
|
||||
/libs/libraries.htm
|
||||
/libs/locale
|
||||
/libs/local_function
|
||||
/libs/lockfree
|
||||
/libs/log
|
||||
/libs/logic
|
||||
/libs/maintainers.txt
|
||||
/libs/math
|
||||
/libs/mem_fn
|
||||
/libs/move
|
||||
/libs/mpi
|
||||
/libs/mpl
|
||||
/libs/msm
|
||||
/libs/multi_array
|
||||
/libs/multi_index
|
||||
/libs/multiprecision
|
||||
/libs/numeric
|
||||
/libs/optional
|
||||
/libs/parameter
|
||||
/libs/phoenix
|
||||
/libs/platform_maintainers.txt
|
||||
/libs/polygon
|
||||
/libs/pool
|
||||
/libs/predef
|
||||
/libs/preprocessor
|
||||
/libs/program_options
|
||||
/libs/property_map
|
||||
/libs/property_tree
|
||||
/libs/proto
|
||||
/libs/ptr_container
|
||||
/libs/python
|
||||
/libs/random
|
||||
/libs/range
|
||||
/libs/ratio
|
||||
/libs/rational
|
||||
/libs/regex
|
||||
/libs/scope_exit
|
||||
/libs/serialization
|
||||
/libs/signals
|
||||
/libs/signals2
|
||||
/libs/smart_ptr
|
||||
/libs/spirit
|
||||
/libs/statechart
|
||||
/libs/static_assert
|
||||
/libs/sync
|
||||
/libs/system
|
||||
/libs/test
|
||||
/libs/thread
|
||||
/libs/timer
|
||||
/libs/tokenizer
|
||||
/libs/tr1
|
||||
/libs/tti
|
||||
/libs/tuple
|
||||
/libs/type_erasure
|
||||
/libs/typeof
|
||||
/libs/type_traits
|
||||
/libs/units
|
||||
/libs/unordered
|
||||
/libs/utility
|
||||
/libs/uuid
|
||||
/libs/variant
|
||||
/libs/wave
|
||||
/libs/xpressive
|
||||
/libs/Jamfile.v2
|
||||
|
||||
|
||||
/boost.css
|
||||
/b2
|
||||
/boost-build.jam
|
||||
/rst.css
|
||||
/boost.png
|
||||
/bootstrap.sh
|
||||
/project-config.jam
|
||||
/Jamroot
|
||||
/.gitignore~
|
||||
/index.htm
|
||||
/README.md
|
||||
/boostcpp.jam
|
||||
/INSTALL
|
||||
/LICENSE_1_0.txt
|
||||
/index.html
|
||||
/bjam
|
||||
/bootstrap.bat
|
||||
/bootstrap.log
|
||||
/boostcpp.py
|
||||
|
||||
|
||||
/bin.v2/
|
||||
/doc/
|
||||
/more/
|
||||
/status/
|
||||
/tools/
|
||||
doc/autodoc.xml
|
||||
doc/html
|
||||
|
||||
27
CMakeLists.txt
Normal file
27
CMakeLists.txt
Normal file
@@ -0,0 +1,27 @@
|
||||
# Generated by `boostdep --cmake type_index`
|
||||
# Copyright 2020, 2021 Peter Dimov
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
cmake_minimum_required(VERSION 3.5...3.20)
|
||||
|
||||
project(boost_type_index VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX)
|
||||
|
||||
add_library(boost_type_index INTERFACE)
|
||||
add_library(Boost::type_index ALIAS boost_type_index)
|
||||
|
||||
target_include_directories(boost_type_index INTERFACE include)
|
||||
|
||||
target_link_libraries(boost_type_index
|
||||
INTERFACE
|
||||
Boost::config
|
||||
Boost::container_hash
|
||||
Boost::core
|
||||
Boost::throw_exception
|
||||
)
|
||||
|
||||
if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt")
|
||||
|
||||
add_subdirectory(test)
|
||||
|
||||
endif()
|
||||
19
README.md
19
README.md
@@ -1,9 +1,16 @@
|
||||
type_index
|
||||
==========
|
||||
# [Boost.TypeIndex](https://boost.org/libs/type_index)
|
||||
Boost.TypeIndex is a part of the [Boost C++ Libraries](https://github.com/boostorg). It is a runtime/compile time copyable type info.
|
||||
|
||||
Runtime/Compile time copyable type info. Library is waiting for boost reiew.
|
||||
Documantation available at: http://apolukhin.github.com/type_index/index.html
|
||||
### Test results
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt).
|
||||
@ | Build | Tests coverage | More info
|
||||
----------------|-------------- | -------------- |-----------
|
||||
Develop branch: | [](https://github.com/boostorg/type_index/actions/workflows/ci.yml) [](https://ci.appveyor.com/project/apolukhin/type-index/branch/develop) | [](https://coveralls.io/r/apolukhin/type_index?branch=develop) | [details...](https://www.boost.org/development/tests/develop/developer/type_index.html)
|
||||
Master branch: | [](https://github.com/boostorg/type_index/actions/workflows/ci.yml) [](https://ci.appveyor.com/project/apolukhin/type-index/branch/master) | [](https://coveralls.io/r/apolukhin/type_index?branch=master) | [details...](https://www.boost.org/development/tests/master/developer/type_index.html)
|
||||
|
||||
While ticket #9228 is not solved, use boost_test_no_rtti.patch to make the tests compile.
|
||||
|
||||
[Latest developer documentation](https://www.boost.org/doc/libs/develop/doc/html/boost_typeindex.html)
|
||||
|
||||
### License
|
||||
|
||||
Distributed under the [Boost Software License, Version 1.0](https://boost.org/LICENSE_1_0.txt).
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
//
|
||||
// Copyright (c) Antony Polukhin, 2012-2013.
|
||||
//
|
||||
// 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_TYPE_INDEX_HPP
|
||||
#define BOOST_TYPE_INDEX_HPP
|
||||
|
||||
/// \file type_index.hpp
|
||||
/// \brief Includes all the headers of the Boost.TypeIndex library.
|
||||
///
|
||||
/// By inclusion of this file both classes (boost::type_index if RTTI is on and boost::template_index) will be available.
|
||||
///
|
||||
/// Consider including <boost/type_index/type_index_minimal.hpp> if you do not whant to include
|
||||
/// boost::template_index class while RTTI is available (this is recommended).
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
#if defined(_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/type_index/type_index_minimal.hpp>
|
||||
#include <boost/type_index/template_index_impl.hpp>
|
||||
|
||||
#endif // BOOST_TYPE_INDEX_HPP
|
||||
|
||||
@@ -1,311 +0,0 @@
|
||||
//
|
||||
// Copyright (c) Antony Polukhin, 2012-2013.
|
||||
//
|
||||
//
|
||||
// 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_TYPE_INDEX_TEMPLATE_INDEX_IMPL_HPP
|
||||
#define BOOST_TYPE_INDEX_TEMPLATE_INDEX_IMPL_HPP
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
#if defined(_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_TYPE_INDEX_TYPE_INDEX_MINIMAL_HPP
|
||||
#error "Header <boost/type_index/template_index_impl.hpp> must not be included directly."
|
||||
#error "Include <boost/type_index/type_index_minimal.hpp> or <boost/type_index.hpp> instead."
|
||||
#endif
|
||||
|
||||
/// \file template_index_impl.hpp
|
||||
/// \brief Contains implementation of boost::template_index class.
|
||||
///
|
||||
/// boost::template_index class is used instead of boost::type_index class in situations when RTTI is disabled.
|
||||
///
|
||||
/// Consider including <boost/type_index/type_index_minimal.hpp> or <boost/type_index.hpp> instead of this file.
|
||||
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_traits/is_arithmetic.hpp>
|
||||
#include <boost/type_traits/remove_cv.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/functional/hash_fwd.hpp>
|
||||
|
||||
#if !defined(BOOST_NO_IOSTREAM)
|
||||
#if !defined(BOOST_NO_IOSFWD)
|
||||
#include <iosfwd> // for std::basic_ostream
|
||||
#else
|
||||
#include <ostream>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
|
||||
|
||||
/// \def BOOST_TYPE_INDEX_FUNCTION_SIGNATURE
|
||||
/// BOOST_TYPE_INDEX_FUNCTION_SIGNATURE is used by boost::template_index class to
|
||||
/// deduce the name of a template parameter. If your compiler is not recognized
|
||||
/// by the TypeIndex library and you wish to work with boost::template_index, you may
|
||||
/// define this macro by yourself.
|
||||
///
|
||||
/// BOOST_TYPE_INDEX_FUNCTION_SIGNATURE must be defined to a compiler specific macro,
|
||||
/// that outputs the WHOLE function signature, including template parameters.
|
||||
///
|
||||
/// If your compiler is not recognised and BOOST_TYPE_INDEX_FUNCTION_SIGNATURE is not defined,
|
||||
/// then a compile-time error will arise at any attempt to use boost::template_index class.
|
||||
#define BOOST_TYPE_INDEX_FUNCTION_SIGNATURE BOOST_CURRENT_FUNCTION
|
||||
|
||||
#elif defined(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE)
|
||||
|
||||
template <class T>
|
||||
inline void lazy_function_signature_assert(){}
|
||||
|
||||
#elif defined(__FUNCSIG__)
|
||||
|
||||
template <class T>
|
||||
inline void lazy_function_signature_assert(){}
|
||||
#define BOOST_TYPE_INDEX_FUNCTION_SIGNATURE __FUNCSIG__
|
||||
|
||||
#elif defined(__PRETTY_FUNCTION__) \
|
||||
|| defined(__GNUC__) \
|
||||
|| (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) \
|
||||
|| (defined(__ICC) && (__ICC >= 600)) \
|
||||
|| defined(__ghs__) \
|
||||
|| defined(__DMC__)
|
||||
|
||||
template <class T>
|
||||
inline void lazy_function_signature_assert(){}
|
||||
#define BOOST_TYPE_INDEX_FUNCTION_SIGNATURE __PRETTY_FUNCTION__
|
||||
|
||||
#else
|
||||
|
||||
template <class T>
|
||||
inline void lazy_function_signature_assert() {
|
||||
BOOST_STATIC_ASSERT_MSG(
|
||||
sizeof(T) && false,
|
||||
"TypeIndex library could not detect your compiler. "
|
||||
"Please make the BOOST_TYPE_INDEX_FUNCTION_SIGNATURE macro use "
|
||||
"correct compiler macro for getting the whole function name. "
|
||||
"Do not forget to also define BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP and "
|
||||
"BOOST_TYPE_INDEX_CTTI_END_SKIP."
|
||||
);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP) && defined(BOOST_TYPE_INDEX_CTTI_END_SKIP)
|
||||
// skip user specified bytes count
|
||||
BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_begin = BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP);
|
||||
// skip user specified bytes count
|
||||
BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_end = BOOST_TYPE_INDEX_CTTI_END_SKIP);
|
||||
#elif defined _MSC_VER
|
||||
// sizeof("const char *__cdecl boost::detail::ctti<") - 1
|
||||
BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_begin = 40);
|
||||
|
||||
// sizeof(">::n(void)") - 1
|
||||
BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_end = 10);
|
||||
|
||||
#elif defined __clang__
|
||||
// sizeof("static const char *boost::detail::ctti<") - 1
|
||||
BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_begin = 39);
|
||||
|
||||
// == sizeof(">::n()") - 1
|
||||
BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_end = 6);
|
||||
#elif defined __GNUC__
|
||||
// sizeof("static const char* boost::detail::ctti<T>::n() [with T = ") - 1
|
||||
BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_begin = 57);
|
||||
|
||||
// == sizeof("]") - 1
|
||||
BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_end = 1);
|
||||
|
||||
#else
|
||||
// TODO: Code for other platforms
|
||||
BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_begin = 0); // skip nothing
|
||||
BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_end = 0); // skip nothing
|
||||
#endif
|
||||
|
||||
/// Noncopyable type_info that does not require RTTI
|
||||
/// CTTI == Compile Time Type Info
|
||||
/// This name must be as short as posible, to avoid code bloat
|
||||
template <class T>
|
||||
struct ctti {
|
||||
typedef T template_type;
|
||||
typedef ctti this_type;
|
||||
|
||||
/// Returns raw name. Must be as short, as possible, to avoid code bloat
|
||||
static const char* n() BOOST_NOEXCEPT {
|
||||
lazy_function_signature_assert<T>();
|
||||
return BOOST_TYPE_INDEX_FUNCTION_SIGNATURE + detail::ctti_skip_size_at_begin;
|
||||
}
|
||||
|
||||
/// Returns raw name
|
||||
static const char* name() BOOST_NOEXCEPT {
|
||||
return this_type::n();
|
||||
}
|
||||
|
||||
/// Returns true if the type precedes the type of rhs in the collation order.
|
||||
/// The collation order is just an internal order.
|
||||
template <class BefT>
|
||||
static bool before() BOOST_NOEXCEPT {
|
||||
return std::strcmp(this_type::n(), ctti<BefT>::n()) < 0;
|
||||
}
|
||||
|
||||
/// Returns length of demangled name
|
||||
static std::size_t name_length() BOOST_NOEXCEPT {
|
||||
return std::strlen(this_type::n() + detail::ctti_skip_size_at_end);
|
||||
}
|
||||
|
||||
/// Returns user-friendly name
|
||||
static std::string name_demangled() BOOST_NOEXCEPT {
|
||||
return std::string(this_type::n(), this_type::name_length());
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
/// Copyable type_info that does not require RTTI and could store const,
|
||||
/// volatile and references if constructed via construct_with_cvr()
|
||||
class template_index {
|
||||
private:
|
||||
const char* name_;
|
||||
|
||||
/// @cond
|
||||
explicit template_index(const char* name) BOOST_NOEXCEPT
|
||||
: name_(name)
|
||||
{}
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
/// Default constructor.
|
||||
template_index() BOOST_NOEXCEPT
|
||||
: name_(detail::ctti<void>::name())
|
||||
{}
|
||||
|
||||
/// Factory method for constructing template_index instance for type T.
|
||||
/// Strips const, volatile and & modifiers from T
|
||||
template <class T>
|
||||
static template_index construct(){
|
||||
typedef BOOST_DEDUCED_TYPENAME boost::remove_reference<T>::type no_ref_t;
|
||||
typedef BOOST_DEDUCED_TYPENAME boost::remove_cv<no_ref_t>::type no_cvr_t;
|
||||
|
||||
# if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \
|
||||
|| (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 744)
|
||||
BOOST_STATIC_ASSERT_MSG( !boost::is_arithmetic<no_cvr_t>::type::value
|
||||
, "Your EDG-based compiler seems to mistakenly distinguish 'int' from 'signed int', in typeid() expressions.");
|
||||
#endif
|
||||
|
||||
return template_index(detail::ctti<no_cvr_t>::name());
|
||||
}
|
||||
|
||||
/// Factory method for constructing template_index instance for type T.
|
||||
/// Does not strip const, volatile and & modifiers from T
|
||||
template <class T>
|
||||
static template_index construct_with_cvr() {
|
||||
# if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \
|
||||
|| (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 744)
|
||||
BOOST_STATIC_ASSERT_MSG( !boost::is_arithmetic<T>::type::value
|
||||
, "Your EDG-based compiler seems to mistakenly distinguish 'int' from 'signed int', in typeid() expressions.");
|
||||
#endif
|
||||
|
||||
return template_index(detail::ctti<T>::name());
|
||||
}
|
||||
|
||||
|
||||
/// Returns true if the type precedes the type of rhs in the collation order.
|
||||
/// The collation order is just an internal order.
|
||||
bool before(const template_index& rhs) const BOOST_NOEXCEPT {
|
||||
return std::strcmp(name(), rhs.name()) < 0;
|
||||
}
|
||||
|
||||
/// Returns raw name
|
||||
const char* name() const BOOST_NOEXCEPT {
|
||||
return name_;
|
||||
}
|
||||
|
||||
/// Returns user-friendly name
|
||||
std::string name_demangled() const {
|
||||
return std::string(name_, std::strlen(name_ + detail::ctti_skip_size_at_end));
|
||||
}
|
||||
|
||||
/// @cond
|
||||
bool operator == (const template_index& rhs) const BOOST_NOEXCEPT {
|
||||
return !std::strcmp(name_, rhs.name());
|
||||
}
|
||||
|
||||
bool operator != (const template_index& rhs) const BOOST_NOEXCEPT {
|
||||
return !!std::strcmp(name_, rhs.name());
|
||||
}
|
||||
|
||||
bool operator < (const template_index& rhs) const BOOST_NOEXCEPT {
|
||||
return std::strcmp(name_, rhs.name()) < 0;
|
||||
}
|
||||
|
||||
bool operator > (const template_index& rhs) const BOOST_NOEXCEPT {
|
||||
return std::strcmp(name_, rhs.name()) > 0;
|
||||
}
|
||||
|
||||
bool operator <= (const template_index& rhs) const BOOST_NOEXCEPT {
|
||||
return std::strcmp(name_, rhs.name()) <= 0;
|
||||
}
|
||||
|
||||
bool operator >= (const template_index& rhs) const BOOST_NOEXCEPT {
|
||||
return std::strcmp(name_, rhs.name()) >= 0;
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
/// Function for getting hash value
|
||||
std::size_t hash_code() const BOOST_NOEXCEPT {
|
||||
return boost::hash_range(name_, name_ + std::strlen(name_ + detail::ctti_skip_size_at_end));
|
||||
}
|
||||
};
|
||||
|
||||
/// Method for constructing template_index instance for type T.
|
||||
/// Strips const, volatile and & modifiers from T.
|
||||
template <class T>
|
||||
inline template_index template_id() BOOST_NOEXCEPT {
|
||||
return template_index::construct<T>();
|
||||
}
|
||||
|
||||
/// Factory method for constructing template_index instance for type T.
|
||||
/// Does not strip const, volatile and & modifiers from T.
|
||||
/// If T has no const, volatile, & and && modifiers, then returns exactly
|
||||
/// the same result as in case of calling `template_id<T>()`.
|
||||
template <class T>
|
||||
inline template_index template_id_with_cvr() BOOST_NOEXCEPT {
|
||||
return template_index::construct_with_cvr<T>();
|
||||
}
|
||||
|
||||
/* *************** template_index free functions ******************* */
|
||||
|
||||
#ifndef BOOST_NO_IOSTREAM
|
||||
#ifdef BOOST_NO_TEMPLATED_IOSTREAMS
|
||||
/// Ostream operator that will output demangled name
|
||||
inline std::ostream& operator<<(std::ostream& ostr, template_index const& ind) {
|
||||
ostr << ind.name_demangled();
|
||||
return ostr;
|
||||
}
|
||||
#else
|
||||
/// Ostream operator that will output demangled name
|
||||
template <class CharT, class TriatT>
|
||||
inline std::basic_ostream<CharT, TriatT>& operator<<(std::basic_ostream<CharT, TriatT>& ostr, template_index const& ind) {
|
||||
ostr << ind.name_demangled();
|
||||
return ostr;
|
||||
}
|
||||
#endif // BOOST_NO_TEMPLATED_IOSTREAMS
|
||||
#endif // BOOST_NO_IOSTREAM
|
||||
|
||||
/// hash_value function overload for template_index
|
||||
inline std::size_t hash_value(template_index const& v) BOOST_NOEXCEPT {
|
||||
return v.hash_code();
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_TYPE_INDEX_TEMPLATE_INDEX_IMPL_HPP
|
||||
|
||||
@@ -1,392 +0,0 @@
|
||||
//
|
||||
// Copyright (c) Antony Polukhin, 2012-2013.
|
||||
//
|
||||
// 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_TYPE_INDEX_TYPE_INDEX_IMPL_HPP
|
||||
#define BOOST_TYPE_INDEX_TYPE_INDEX_IMPL_HPP
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
#if defined(_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_TYPE_INDEX_TYPE_INDEX_MINIMAL_HPP
|
||||
#error "Header <boost/type_index/type_index_impl.hpp> must not be included directly."
|
||||
#error "Include <boost/type_index/type_index_minimal.hpp> or <boost/type_index.hpp> instead."
|
||||
#endif
|
||||
|
||||
/// \file type_index_impl.hpp
|
||||
/// \brief Contains implementation of boost::type_index class.
|
||||
///
|
||||
/// boost::type_index class is used in situations when RTTI is enabled.
|
||||
/// When RTTI is disabled or BOOST_TYPE_INDEX_FORCE_NORTTI_COMPATIBILITY macro is defined boost::template_index
|
||||
/// is used instead.
|
||||
///
|
||||
/// Consider including <boost/type_index/type_index_minimal.hpp> or <boost/type_index.hpp> instead of this file.
|
||||
|
||||
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_traits/is_arithmetic.hpp>
|
||||
#include <boost/type_traits/is_const.hpp>
|
||||
#include <boost/type_traits/is_reference.hpp>
|
||||
#include <boost/type_traits/is_volatile.hpp>
|
||||
#include <boost/type_traits/remove_cv.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/current_function.hpp>
|
||||
#include <boost/detail/no_exceptions_support.hpp>
|
||||
#include <boost/functional/hash_fwd.hpp>
|
||||
|
||||
#ifndef BOOST_NO_RTTI
|
||||
#include <typeinfo>
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_IOSTREAM)
|
||||
#if !defined(BOOST_NO_IOSFWD)
|
||||
#include <iosfwd> // for std::basic_ostream
|
||||
#else
|
||||
#include <ostream>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#include <cxxabi.h>
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
#ifndef BOOST_NO_RTTI
|
||||
|
||||
#ifndef BOOST_TYPE_INDEX_DOXYGEN_INVOKED
|
||||
|
||||
// for this compiler at least, cross-shared-library type_info
|
||||
// comparisons don't work, so use typeid(x).name() instead. It's not
|
||||
// yet clear what the best default strategy is.
|
||||
# if (defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5))) \
|
||||
|| defined(_AIX) \
|
||||
|| (defined(__sgi) && defined(__host_mips)) \
|
||||
|| (defined(__hpux) && defined(__HP_aCC)) \
|
||||
|| (defined(linux) && defined(__INTEL_COMPILER) && defined(__ICC))
|
||||
# define BOOST_CLASSINFO_COMPARE_BY_NAMES
|
||||
# endif
|
||||
|
||||
#endif // BOOST_TYPE_INDEX_DOXYGEN_INVOKED
|
||||
|
||||
namespace detail {
|
||||
template <class T> class cvr_saver{};
|
||||
}
|
||||
|
||||
/// Copyable type_info class that requires RTTI.
|
||||
class type_index {
|
||||
public:
|
||||
|
||||
#ifdef BOOST_NO_STD_TYPEINFO
|
||||
typedef type_info stl_type_info;
|
||||
#else
|
||||
typedef std::type_info stl_type_info;
|
||||
#endif
|
||||
|
||||
private:
|
||||
const stl_type_info* pinfo_;
|
||||
|
||||
public:
|
||||
/// Default constructor.
|
||||
type_index() BOOST_NOEXCEPT
|
||||
: pinfo_(&typeid(void))
|
||||
{}
|
||||
|
||||
/// Constructs type_index from an instance of std::type_info.
|
||||
explicit type_index(const stl_type_info& inf) BOOST_NOEXCEPT
|
||||
: pinfo_(&inf)
|
||||
{}
|
||||
|
||||
/// Factory method for constructing type_index instance for type T.
|
||||
/// Strips const, volatile and & modifiers from T.
|
||||
template <class T>
|
||||
static type_index construct() BOOST_NOEXCEPT {
|
||||
typedef BOOST_DEDUCED_TYPENAME boost::remove_reference<T>::type no_ref_t;
|
||||
typedef BOOST_DEDUCED_TYPENAME boost::remove_cv<no_ref_t>::type no_cvr_t;
|
||||
|
||||
# if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \
|
||||
|| (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 744)
|
||||
BOOST_STATIC_ASSERT_MSG( !boost::is_arithmetic<no_cvr_t>::type::value
|
||||
, "Your EDG-based compiler seems to mistakenly distinguish 'int' from 'signed int', in typeid() expressions.");
|
||||
#endif
|
||||
|
||||
return type_index(typeid(no_cvr_t));
|
||||
}
|
||||
|
||||
/// Factory method for constructing type_index instance for type T.
|
||||
/// Does not strip const, volatile, & and && modifiers from T.
|
||||
/// If T has no const, volatile, & and && modifiers, then returns exactly
|
||||
/// the same result as in case of calling `construct<T>()`.
|
||||
template <class T>
|
||||
static type_index construct_with_cvr() BOOST_NOEXCEPT {
|
||||
typedef typename boost::mpl::if_c<
|
||||
boost::is_reference<T>::value
|
||||
|| boost::is_const<T>::value
|
||||
|| boost::is_volatile<T>::value,
|
||||
detail::cvr_saver<T>,
|
||||
T
|
||||
>::type type;
|
||||
return construct<type>();
|
||||
}
|
||||
|
||||
/// Factory function, that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index.
|
||||
/// This method available only with RTTI enabled.
|
||||
template <class T>
|
||||
static type_index construct_rtti_only(T& rtti_val) {
|
||||
return type_index(typeid(rtti_val));
|
||||
}
|
||||
|
||||
/// Factory function, that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index.
|
||||
/// This method available only with RTTI enabled.
|
||||
template <class T>
|
||||
static type_index construct_rtti_only(T* rtti_val) {
|
||||
return type_index(typeid(rtti_val));
|
||||
}
|
||||
|
||||
/// Returns true if the type precedes the type of rhs in the collation order.
|
||||
/// The collation order is just an internal order.
|
||||
bool before(type_index const& rhs) const BOOST_NOEXCEPT {
|
||||
return !!pinfo_->before(*rhs.pinfo_);
|
||||
}
|
||||
|
||||
/// Returns raw name
|
||||
const char* name() const BOOST_NOEXCEPT {
|
||||
#ifdef _MSC_VER
|
||||
return pinfo_->raw_name();
|
||||
#else
|
||||
return pinfo_->name();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Returns user-friendly name
|
||||
std::string name_demangled() const {
|
||||
#if defined(__GNUC__)
|
||||
std::string ret;
|
||||
int status = 0;
|
||||
char* demang = abi::__cxa_demangle(pinfo_->name(), NULL, 0, &status);
|
||||
BOOST_ASSERT(!status);
|
||||
|
||||
BOOST_TRY {
|
||||
ret = demang; // may throw out of memory exception
|
||||
} BOOST_CATCH (...) {
|
||||
free(demang);
|
||||
BOOST_RETHROW;
|
||||
} BOOST_CATCH_END
|
||||
|
||||
free(demang);
|
||||
#else
|
||||
std::string ret = pinfo_->name();
|
||||
#endif
|
||||
std::string::size_type pos = ret.find("boost::detail::cvr_saver<");
|
||||
if (pos == std::string::npos) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
pos += sizeof("boost::detail::cvr_saver<") - 1;
|
||||
while (ret[pos] == ' ') {
|
||||
++ pos;
|
||||
}
|
||||
std::string::size_type end = ret.rfind(">");
|
||||
BOOST_ASSERT(end != std::string::npos);
|
||||
while (ret[end] == ' ') {
|
||||
-- end;
|
||||
}
|
||||
|
||||
return ret.substr(pos, end - pos);
|
||||
}
|
||||
|
||||
#ifndef BOOST_TYPE_INDEX_DOXYGEN_INVOKED
|
||||
bool operator == (type_index const& rhs) const BOOST_NOEXCEPT {
|
||||
#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES
|
||||
return !std::strcmp(pinfo_->name(), rhs.pinfo_->name());
|
||||
#else
|
||||
return *pinfo_ == *rhs.pinfo_;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool operator != (type_index const& rhs) const BOOST_NOEXCEPT {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
bool operator < (type_index const& rhs) const BOOST_NOEXCEPT {
|
||||
#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES
|
||||
return std::strcmp(pinfo_->name(), rhs.pinfo_->name()) < 0;
|
||||
#else
|
||||
return before(rhs);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool operator > (type_index const& rhs) const BOOST_NOEXCEPT {
|
||||
return (rhs < *this);
|
||||
}
|
||||
|
||||
bool operator <= (type_index const& rhs) const BOOST_NOEXCEPT {
|
||||
return !(*this > rhs);
|
||||
}
|
||||
|
||||
bool operator >= (type_index const& rhs) const BOOST_NOEXCEPT {
|
||||
return !(*this < rhs);
|
||||
}
|
||||
|
||||
bool operator == (stl_type_info const& rhs) const BOOST_NOEXCEPT {
|
||||
#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES
|
||||
return !std::strcmp(pinfo_->name(), rhs.name());
|
||||
#else
|
||||
return *pinfo_ == rhs;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool operator != (stl_type_info const& rhs) const BOOST_NOEXCEPT {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
bool operator < (stl_type_info const& rhs) const BOOST_NOEXCEPT {
|
||||
#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES
|
||||
return std::strcmp(pinfo_->name(), rhs.name()) < 0;
|
||||
#else
|
||||
return !!pinfo_->before(rhs);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool operator > (stl_type_info const& rhs) const BOOST_NOEXCEPT {
|
||||
#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES
|
||||
return std::strcmp(pinfo_->name(), rhs.name()) > 0;
|
||||
#else
|
||||
return !!rhs.before(*pinfo_);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool operator <= (stl_type_info const& rhs) const BOOST_NOEXCEPT {
|
||||
return !(*this > rhs);
|
||||
}
|
||||
|
||||
bool operator >= (stl_type_info const& rhs) const BOOST_NOEXCEPT {
|
||||
return !(*this < rhs);
|
||||
}
|
||||
#endif // BOOST_TYPE_INDEX_DOXYGEN_INVOKED
|
||||
|
||||
/// Function for getting hash value
|
||||
std::size_t hash_code() const BOOST_NOEXCEPT {
|
||||
#if _MSC_VER >= 1600 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5 && defined(__GXX_EXPERIMENTAL_CXX0X__))
|
||||
return pinfo_->hash_code();
|
||||
#else
|
||||
return boost::hash_range(name(), name() + std::strlen(name()));
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef BOOST_TYPE_INDEX_DOXYGEN_INVOKED
|
||||
|
||||
/* *************** type_index free functions ******************* */
|
||||
|
||||
inline bool operator == (type_index::stl_type_info const& lhs, type_index const& rhs) BOOST_NOEXCEPT {
|
||||
return rhs == lhs; // Operation is commutative
|
||||
}
|
||||
|
||||
inline bool operator != (type_index::stl_type_info const& lhs, type_index const& rhs) BOOST_NOEXCEPT {
|
||||
return rhs != lhs; // Operation is commutative
|
||||
}
|
||||
|
||||
inline bool operator < (type_index::stl_type_info const& lhs, type_index const& rhs) BOOST_NOEXCEPT {
|
||||
return rhs > lhs;
|
||||
}
|
||||
|
||||
inline bool operator > (type_index::stl_type_info const& lhs, type_index const& rhs) BOOST_NOEXCEPT {
|
||||
return rhs < lhs;
|
||||
}
|
||||
|
||||
inline bool operator <= (type_index::stl_type_info const& lhs, type_index const& rhs) BOOST_NOEXCEPT {
|
||||
return rhs >= lhs;
|
||||
}
|
||||
|
||||
inline bool operator >= (type_index::stl_type_info const& lhs, type_index const& rhs) BOOST_NOEXCEPT {
|
||||
return rhs <= lhs;
|
||||
}
|
||||
|
||||
#endif // BOOST_TYPE_INDEX_DOXYGEN_INVOKED
|
||||
|
||||
#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES
|
||||
#undef BOOST_CLASSINFO_COMPARE_BY_NAMES
|
||||
#endif
|
||||
|
||||
/// @endcond
|
||||
|
||||
/// Function, to get type_index for a type T. Strips const, volatile and & modifiers from T.
|
||||
template <class T>
|
||||
inline type_index type_id() BOOST_NOEXCEPT {
|
||||
return type_index::construct<T>();
|
||||
}
|
||||
|
||||
/// Function for constructing type_index instance for type T.
|
||||
/// Does not strip const, volatile, & and && modifiers from T.
|
||||
/// If T has no const, volatile, & and && modifiers, then returns exactly
|
||||
/// the same result as in case of calling `type_id<T>()`.
|
||||
template <class T>
|
||||
inline type_index type_id_with_cvr() BOOST_NOEXCEPT {
|
||||
return type_index::construct_with_cvr<T>();
|
||||
}
|
||||
|
||||
/// Function, that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index.
|
||||
/// This method available only with RTTI enabled. Without RTTI support it won't compile,
|
||||
/// producing a compile-time error with message: "boost::type_id_rtti_only(T&) requires RTTI"
|
||||
template <class T>
|
||||
inline type_index type_id_rtti_only(T& rtti_val) BOOST_NOEXCEPT {
|
||||
return type_index::construct_rtti_only(rtti_val);
|
||||
}
|
||||
|
||||
/// Function, that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index.
|
||||
/// This method available only with RTTI enabled. Without RTTI support it won't compile,
|
||||
/// producing a compile-time error with message: "boost::type_id_rtti_only(T*) requires RTTI"
|
||||
template <class T>
|
||||
inline type_index type_id_rtti_only(T* rtti_val) {
|
||||
return type_index::construct_rtti_only(rtti_val);
|
||||
}
|
||||
|
||||
/* *************** type_index free functions ******************* */
|
||||
|
||||
/// @cond
|
||||
|
||||
#ifndef BOOST_NO_IOSTREAM
|
||||
#ifdef BOOST_NO_TEMPLATED_IOSTREAMS
|
||||
|
||||
/// Ostream operator that will output demangled name.
|
||||
inline std::ostream& operator<<(std::ostream& ostr, type_index const& ind) {
|
||||
ostr << ind.name_demangled();
|
||||
return ostr;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/// Ostream operator that will output demangled name.
|
||||
template <class CharT, class TriatT>
|
||||
inline std::basic_ostream<CharT, TriatT>& operator<<(std::basic_ostream<CharT, TriatT>& ostr, type_index const& ind) {
|
||||
ostr << ind.name_demangled();
|
||||
return ostr;
|
||||
}
|
||||
|
||||
#endif // BOOST_NO_TEMPLATED_IOSTREAMS
|
||||
#endif // BOOST_NO_IOSTREAM
|
||||
|
||||
/// hash_value function overload for type_index.
|
||||
inline std::size_t hash_value(type_index const& v) BOOST_NOEXCEPT {
|
||||
return v.hash_code();
|
||||
}
|
||||
|
||||
/// @endcond
|
||||
|
||||
#endif // BOOST_NO_RTTI
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_TYPE_INDEX_TYPE_INDEX_IMPL_HPP
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
//
|
||||
// Copyright (c) Antony Polukhin, 2012-2013.
|
||||
//
|
||||
//
|
||||
// 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_TYPE_INDEX_TYPE_INDEX_MINIMAL_HPP
|
||||
#define BOOST_TYPE_INDEX_TYPE_INDEX_MINIMAL_HPP
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
#if defined(_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
/// \file type_index_minimal.hpp
|
||||
/// \brief This is the header that required for ussage of boost::type_index with/without RTTI.
|
||||
///
|
||||
/// It includes only the minamally required headers and does the 'typedef template_index type_index;'
|
||||
/// when RTTI is disabled.
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if !defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NORTTI_COMPATIBILITY)
|
||||
# include <boost/type_index/type_index_impl.hpp>
|
||||
#else
|
||||
# include <boost/type_index/template_index_impl.hpp>
|
||||
# include <boost/static_assert.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
typedef template_index type_index;
|
||||
|
||||
template <class T>
|
||||
inline type_index type_id() BOOST_NOEXCEPT {
|
||||
return template_index::construct<T>();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline type_index type_id_with_cvr() BOOST_NOEXCEPT {
|
||||
return template_index::construct_with_cvr<T>();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline type_index type_id_rtti_only(T& rtti_val) BOOST_NOEXCEPT {
|
||||
BOOST_STATIC_ASSERT_MSG(sizeof(T) && false, "boost::type_id_rtti_only(T&) requires RTTI");
|
||||
return type_index();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline type_index type_id_rtti_only(T* rtti_val) {
|
||||
BOOST_STATIC_ASSERT_MSG(sizeof(T) && false, "boost::type_id_rtti_only(T*) requires RTTI");
|
||||
return type_index();
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_NO_RTTI
|
||||
|
||||
#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
|
||||
/// \def BOOST_TYPE_INDEX_FORCE_NORTTI_COMPATIBILITY
|
||||
/// Define the BOOST_TYPE_INDEX_FORCE_NORTTI_COMPATIBILITY macro if you are mixing objects
|
||||
/// compiled with different RTTI flags. This will force the usage of boost::template_index
|
||||
/// class instead of boost::type_index.
|
||||
#define BOOST_TYPE_INDEX_FORCE_NORTTI_COMPATIBILITY
|
||||
#endif // BOOST_TYPE_INDEX_DOXYGEN_INVOKED
|
||||
|
||||
#endif // BOOST_TYPE_INDEX_TYPE_INDEX_MINIMAL_HPP
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
Index: trunk/boost/test/execution_monitor.hpp
|
||||
===================================================================
|
||||
--- trunk/boost/test/execution_monitor.hpp (revision 86235)
|
||||
+++ trunk/boost/test/execution_monitor.hpp (working copy)
|
||||
@@ -261,7 +261,7 @@
|
||||
template<typename ExceptionType>
|
||||
void erase_exception_translator( boost::type<ExceptionType>* = 0 )
|
||||
{
|
||||
- m_custom_translators = m_custom_translators->erase<ExceptionType>( m_custom_translators );
|
||||
+ m_custom_translators = m_custom_translators->template erase<ExceptionType>( m_custom_translators );
|
||||
}
|
||||
|
||||
private:
|
||||
Index: trunk/boost/test/tree/test_case_template.hpp
|
||||
===================================================================
|
||||
--- trunk/boost/test/tree/test_case_template.hpp (revision 86235)
|
||||
+++ trunk/boost/test/tree/test_case_template.hpp (working copy)
|
||||
@@ -34,8 +34,13 @@
|
||||
#include <boost/type_traits/is_const.hpp>
|
||||
#include <boost/function/function0.hpp>
|
||||
|
||||
+#ifndef BOOST_NO_RTTI
|
||||
+#include <typeinfo> // for typeid
|
||||
+#else
|
||||
+#include <boost/current_function.hpp>
|
||||
+#endif
|
||||
+
|
||||
// STL
|
||||
-#include <typeinfo> // for typeid
|
||||
#include <string> // for std::string
|
||||
#include <list> // for std::list
|
||||
|
||||
@@ -77,7 +82,11 @@
|
||||
std::string full_name;
|
||||
assign_op( full_name, m_test_case_name, 0 );
|
||||
full_name += '<';
|
||||
+#ifndef BOOST_NO_RTTI
|
||||
full_name += typeid(TestType).name();
|
||||
+#else
|
||||
+ full_name += BOOST_CURRENT_FUNCTION;
|
||||
+#endif
|
||||
if( boost::is_const<TestType>::value )
|
||||
full_name += " const";
|
||||
full_name += '>';
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright Antony Polukhin 2011.
|
||||
# Copyright 2011-2023 Antony Polukhin.
|
||||
# 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)
|
||||
@@ -10,7 +10,8 @@ import doxygen ;
|
||||
doxygen autodoc
|
||||
:
|
||||
[ glob ../../../boost/type_index.hpp ]
|
||||
[ glob ../../../boost/type_index/* ]
|
||||
[ glob ../../../boost/type_index/*.hpp ]
|
||||
[ glob ../../../boost/type_index/runtime_cast/*.hpp ]
|
||||
:
|
||||
<doxygen:param>EXTRACT_ALL=NO
|
||||
<doxygen:param>HIDE_UNDOC_MEMBERS=YES
|
||||
@@ -18,20 +19,14 @@ doxygen autodoc
|
||||
<doxygen:param>ENABLE_PREPROCESSING=YES
|
||||
<doxygen:param>EXPAND_ONLY_PREDEF=YES
|
||||
<doxygen:param>MACRO_EXPANSION=YES
|
||||
<doxygen:param>"PREDEFINED=\"insert_const_ref_type= const T&\" \\
|
||||
<doxygen:param>"PREDEFINED=\"stl_type_info=std::type_info\" \\
|
||||
\"BOOST_TYPE_INDEX_DOXYGEN_INVOKED\" \\
|
||||
\"BOOST_RV_REF(T)=T &&\" \\
|
||||
\"BOOST_RV_REF_BEG=\" \\
|
||||
\"BOOST_RV_REF_END=&&\" \\
|
||||
\"BOOST_CLASSINFO_COMPARISON_NOEXCEPT=\" \\
|
||||
\"BOOST_COPY_ASSIGN_REF(T)=const T &\" \\
|
||||
\"BOOST_RV_REF_2_TEMPL_ARGS(T,a,b)=T<a, b> &&\" \\
|
||||
\"BOOST_RV_REF_3_TEMPL_ARGS(T,a,b,c)=T<a,b,c>T<a,b,c> &&\" \\
|
||||
\"BOOST_FWD_REF(a)=a &&\""
|
||||
\"BOOST_CXX14_CONSTEXPR=constexpr\" \\
|
||||
\"detail::stl_type_info=std::type_info\""
|
||||
<xsl:param>"boost.doxygen.reftitle=Boost.TypeIndex Header Reference"
|
||||
;
|
||||
|
||||
xml type_index : type_index.qbk ;
|
||||
xml type_index : type_index.qbk : <dependency>autodoc ;
|
||||
boostbook standalone
|
||||
:
|
||||
type_index
|
||||
@@ -39,6 +34,14 @@ boostbook standalone
|
||||
<xsl:param>boost.root=http://www.boost.org/doc/libs/1_53_0
|
||||
# <xsl:param>boost.root=../../../..
|
||||
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html
|
||||
<dependency>autodoc
|
||||
;
|
||||
|
||||
###############################################################################
|
||||
alias boostdoc
|
||||
: type_index
|
||||
:
|
||||
: <dependency>autodoc
|
||||
: ;
|
||||
explicit boostdoc ;
|
||||
alias boostrelease ;
|
||||
explicit boostrelease ;
|
||||
483
doc/type_index.qbk
Normal file
483
doc/type_index.qbk
Normal file
@@ -0,0 +1,483 @@
|
||||
[library Boost.TypeIndex
|
||||
[quickbook 1.6]
|
||||
[version 4.1]
|
||||
[copyright 2012-2023 Antony Polukhin]
|
||||
[category Language Features Emulation]
|
||||
[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])
|
||||
]
|
||||
]
|
||||
|
||||
[section Motivation]
|
||||
Sometimes getting and storing information about a type at runtime is required. For such cases a construction like `&typeid(T)` or C++11 class `std::type_index` is usually used, which is where problems start:
|
||||
|
||||
* `typeid(T)` and `std::type_index` require Run Time Type Info (RTTI)
|
||||
* some implementations of `typeid(T)` erroneously do not strip const, volatile and references from type
|
||||
* some compilers have bugs and do not correctly compare `std::type_info` objects across shared libraries
|
||||
* only a few implementations of Standard Library currently provide `std::type_index`
|
||||
* no easy way to store type info without stripping const, volatile and references
|
||||
* no nice and portable way to get human readable type names
|
||||
* no way to easily make your own type info class
|
||||
|
||||
Boost.TypeIndex library was designed to work around all those issues.
|
||||
|
||||
[note `T` means type here. Think of it as of `T` in `template <class T>` ]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Getting started]
|
||||
|
||||
[classref boost::typeindex::type_info boost::typeindex::type_info] is a drop-in replacement for `std::type_info` and
|
||||
[classref boost::typeindex::type_index boost::typeindex::type_index]
|
||||
is a drop-in replacement for `std::type_index`. Unlike Standard Library versions those classes can work without RTTI.
|
||||
|
||||
`type_index` provides the full set of comparison operators, hashing functions and ostream
|
||||
operators, so it can be used with any container class.
|
||||
|
||||
[section How to use]
|
||||
|
||||
To start using Boost.TypeIndex:
|
||||
|
||||
[table:porting
|
||||
[[Replace this:][With the following:][More Info]]
|
||||
[[``
|
||||
#include <typeinfo>
|
||||
#include <typeindex>
|
||||
``][``
|
||||
#include <boost/type_index.hpp>
|
||||
``][
|
||||
[headerref boost/type_index.hpp more... ]
|
||||
]]
|
||||
|
||||
[[``
|
||||
std::type_index
|
||||
``][``
|
||||
boost::typeindex::type_index
|
||||
``][
|
||||
[classref boost::typeindex::type_index more... ]
|
||||
]]
|
||||
|
||||
[[``
|
||||
typeid(T)
|
||||
typeid(T).name() // not human readable
|
||||
typeid(variable)
|
||||
``][``
|
||||
boost::typeindex::type_id<T>()
|
||||
boost::typeindex::type_id<T>().pretty_name() // human readable
|
||||
boost::typeindex::type_id_runtime(variable)
|
||||
``][
|
||||
[funcref boost::typeindex::type_id more... ]
|
||||
|
||||
[classref boost::typeindex::type_index more... ]
|
||||
|
||||
[funcref boost::typeindex::type_id_runtime more... ]
|
||||
]]
|
||||
|
||||
[[``
|
||||
// attempt to save const, volatile, reference
|
||||
typeid(please_save_modifiers<T>)
|
||||
``][``
|
||||
// cvr = const, volatile, reference
|
||||
boost::typeindex::type_id_with_cvr<T>()
|
||||
``][
|
||||
[funcref boost::typeindex::type_id_with_cvr more... ]
|
||||
]]
|
||||
|
||||
[[``
|
||||
// when reference to `std::type_info` is required
|
||||
const std::type_info& v1 = typeid(int);
|
||||
|
||||
// other cases
|
||||
const std::type_info* v2 = &typeid(int);
|
||||
``][``
|
||||
const boost::typeindex::type_info& v1
|
||||
= boost::typeindex::type_id<int>().type_info();
|
||||
|
||||
boost::typeindex::type_index v2
|
||||
= boost::typeindex::type_id<int>();
|
||||
``][
|
||||
[classref boost::typeindex::type_index more... ]
|
||||
|
||||
[funcref boost::typeindex::type_id more... ]
|
||||
]]
|
||||
]
|
||||
|
||||
If you are using [funcref boost::typeindex::type_id_runtime type_id_runtime()] methods
|
||||
and RTTI is disabled, make sure that classes that are passed to
|
||||
`type_id_runtime()` are marked with
|
||||
[macroref BOOST_TYPE_INDEX_REGISTER_CLASS BOOST_TYPE_INDEX_REGISTER_CLASS] macro.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Example with Boost.Any]
|
||||
|
||||
Here is how TypeIndex could be used in `boost/any.hpp`:
|
||||
[table:any
|
||||
[[Before] [With TypeIndex]]
|
||||
[[``#include <typeinfo>``][``#include <boost/type_index.hpp>``]]
|
||||
[[``
|
||||
virtual const std::type_info & type() const BOOST_NOEXCEPT
|
||||
{
|
||||
// requires RTTI
|
||||
return typeid(ValueType);
|
||||
}
|
||||
``] [``
|
||||
virtual const boost::typeindex::type_info & type() const BOOST_NOEXCEPT
|
||||
{
|
||||
// now works even with RTTI disabled
|
||||
return boost::typeindex::type_id<ValueType>().type_info();
|
||||
}
|
||||
``]]
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[section Example with Boost.Variant]
|
||||
|
||||
Here is how TypeIndex could be used in `boost/variant/variant.hpp`:
|
||||
[table:variant
|
||||
[[Before] [With TypeIndex]]
|
||||
|
||||
[[``
|
||||
#if !defined(BOOST_NO_TYPEID)
|
||||
#include <typeinfo> // for typeid, std::type_info
|
||||
#endif // BOOST_NO_TYPEID
|
||||
``][``
|
||||
#include <boost/type_index.hpp>
|
||||
``]]
|
||||
[[``
|
||||
#if !defined(BOOST_NO_TYPEID)
|
||||
|
||||
class reflect
|
||||
: public static_visitor<const std::type_info&>
|
||||
{
|
||||
public: // visitor interfaces
|
||||
|
||||
template <typename T>
|
||||
const std::type_info& operator()(const T&) const BOOST_NOEXCEPT
|
||||
{
|
||||
return typeid(T);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // BOOST_NO_TYPEID
|
||||
``][``
|
||||
class reflect
|
||||
: public static_visitor<const boost::typeindex::type_info&>
|
||||
{
|
||||
public: // visitor interfaces
|
||||
|
||||
template <typename T>
|
||||
const boost::typeindex::type_info& operator()(const T&) const BOOST_NOEXCEPT
|
||||
{
|
||||
return boost::typeindex::type_id<T>().type_info();
|
||||
}
|
||||
|
||||
};
|
||||
``]]
|
||||
[[``
|
||||
#if !defined(BOOST_NO_TYPEID)
|
||||
const std::type_info& type() const
|
||||
{
|
||||
detail::variant::reflect visitor;
|
||||
return this->apply_visitor(visitor);
|
||||
}
|
||||
#endif
|
||||
``] [``
|
||||
const boost::typeindex::type_info& type() const
|
||||
{
|
||||
detail::variant::reflect visitor;
|
||||
return this->apply_visitor(visitor);
|
||||
}
|
||||
``]]
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[endsect]
|
||||
|
||||
[section:config Configuring and building the library]
|
||||
|
||||
TypeIndex is a header only library and it does not use Boost libraries that require
|
||||
building. You just need to `#include <boost/type_index.hpp>` to start using it.
|
||||
|
||||
The library supports a number of configuration macros, defining which require full
|
||||
rebuild of all the projects that use TypeIndex:
|
||||
|
||||
[table Configuration macros
|
||||
[[Macro name] [Short description]]
|
||||
[[[macroref BOOST_TYPE_INDEX_USER_TYPEINDEX]] [ Macro that allows you to use your
|
||||
own implementation of TypeIndex instead of the default all around the projects and libraries.]]
|
||||
|
||||
[[[macroref BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY]] [ Macro that must be defined
|
||||
if you are mixing RTTI-on and RTTI-off.]]
|
||||
|
||||
[[[macroref BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING] and
|
||||
[macroref BOOST_TYPE_INDEX_FUNCTION_SIGNATURE]] [ Macros that allow you to specify
|
||||
parsing options and type name generating macro for RTTI-off cases. ]]
|
||||
]
|
||||
|
||||
You can define configuration macros in the `bjam` command line using one of the following
|
||||
approaches:
|
||||
|
||||
[pre
|
||||
b2 variant=release define=BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY stage
|
||||
]
|
||||
|
||||
[pre
|
||||
b2 variant=release "define=BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING='(39, 1, true, \\"T = \\")'" stage
|
||||
]
|
||||
|
||||
However, it may be more convenient to define configuration macros in the "boost/config/user.hpp"
|
||||
file in order to automatically define them both for the library and user's projects.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section How it works]
|
||||
`type_index` is just a typedef for [classref boost::typeindex::stl_type_index]
|
||||
or [classref boost::typeindex::ctti_type_index].
|
||||
|
||||
Depending on the `typeid()` availability TypeIndex library will choose an optimal class for
|
||||
`type_index`. In cases when at least basic support for `typeid()` is available `stl_type_index` will be used.
|
||||
|
||||
[macroref BOOST_TYPE_INDEX_REGISTER_CLASS] macro is a helper macro that places some virtual helper functions or
|
||||
expands to nothing.
|
||||
|
||||
[macroref BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS] macro is a helper macro that places the same
|
||||
helpers as BOOST_TYPE_INDEX_REGISTER_CLASS plus some additional helpers for boost::typeindex::runtime_cast
|
||||
to function.
|
||||
|
||||
Issues with cross module type comparison on a bugged compilers are bypassed by directly comparing strings with type
|
||||
(latest versions of those compilers resolved that issue using exactly the same approach).
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Examples]
|
||||
|
||||
[import ../examples/demangled_names.cpp]
|
||||
[section Getting human readable and mangled type names] [type_index_names_example] [endsect]
|
||||
|
||||
[import ../examples/registry.cpp]
|
||||
[section Storing information about a type in container ] [type_index_registry_example] [endsect]
|
||||
|
||||
[import ../examples/inheritance.cpp]
|
||||
[section Getting through the inheritance to receive a real type name ] [type_index_derived_example] [endsect]
|
||||
|
||||
[import ../examples/runtime_cast.cpp]
|
||||
[section Using runtime_cast where RTTI is unavailable or undesirable ] [type_index_runtime_cast_example] [endsect]
|
||||
|
||||
[import ../examples/exact_types_match.cpp]
|
||||
[section Exact type matching: storing type with const, volatile and reference qualifiers] [type_index_exact_type_match_example] [endsect]
|
||||
|
||||
[import ../examples/table_of_names.cpp]
|
||||
[section Table of raw_name() and pretty_name() outputs with and without RTTI ] [type_index_names_table] [endsect]
|
||||
|
||||
[import ../examples/constexpr14_namespace_check.cpp]
|
||||
[section C++14: Checking namespace at compile time ] [type_index_constexpr14_namespace_example] [endsect]
|
||||
|
||||
[import ../examples/constexpr14_sort_check.cpp]
|
||||
[section C++14: Checking lexigraphical order of provided types ] [type_index_constexpr14_sort_check_example] [endsect]
|
||||
|
||||
[endsect]
|
||||
|
||||
[xinclude autodoc.xml]
|
||||
|
||||
[section Making a custom type_index]
|
||||
|
||||
Sometimes there may be a need to create your own type info system. This may be useful if you wish to store some more info about types (PODness, size of a type, pointers to common functions...) or if you have an idea of a more compact types representations.
|
||||
|
||||
[import ../examples/user_defined_typeinfo.hpp]
|
||||
[import ../examples/user_defined_typeinfo.cpp]
|
||||
|
||||
[section Basics]
|
||||
[type_index_userdefined_usertypes]
|
||||
[type_index_userdefined_enum]
|
||||
[type_index_my_type_index]
|
||||
[type_index_my_type_index_usage]
|
||||
[endsect]
|
||||
|
||||
[section Getting type infos at runtime]
|
||||
[type_index_my_type_index_register_class]
|
||||
[type_index_my_type_index_type_id_runtime_implmentation]
|
||||
[type_index_my_type_index_type_id_runtime_classes]
|
||||
[type_index_my_type_index_type_id_runtime_test]
|
||||
[endsect]
|
||||
|
||||
[section Using new type infos all around the code]
|
||||
[type_index_my_type_index_worldwide_macro]
|
||||
[type_index_my_type_index_worldwide_typedefs]
|
||||
[type_index_my_type_index_worldwide_usage]
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[section Space and Performance]
|
||||
|
||||
* `ctti_type_index` uses macro for getting full text representation of function name which could lead to code bloat,
|
||||
so prefer using `stl_type_index` type when possible.
|
||||
* All the type_index classes hold a single pointer and are fast to copy.
|
||||
* Calls to `const char* raw_name()` do not require dynamic memory allocation and usually just return a pointer to an array of chars in a read-only section of the binary image.
|
||||
* Comparison operators are optimized as much as possible and execute a single `std::strcmp` in worst case.
|
||||
* Calls to `std::string pretty_name()` usually require dynamic memory allocation and some computations, so they are not recommended for usage in performance critical sections.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Code bloat]
|
||||
|
||||
Without RTTI TypeIndex library will switch from using `boost::typeindex::stl_type_index` class to
|
||||
`boost::typeindex::ctti_type_index`. `boost::typeindex::ctti_type_index` uses macro for getting full
|
||||
text representation of function name for each type that is passed to `type_id()` and
|
||||
`type_id_with_cvr()` functions.
|
||||
|
||||
This leads to big strings in binary file:
|
||||
```
|
||||
static const char* boost::detail::ctti<T>::n() [with T = int]
|
||||
static const char* boost::detail::ctti<T>::n() [with T = user_defined_type]
|
||||
```
|
||||
While using RTTI, you'll get the following (more compact) string in binary file:
|
||||
|
||||
```
|
||||
i
|
||||
17user_defined_type
|
||||
```
|
||||
|
||||
[endsect]
|
||||
|
||||
[section RTTI emulation limitations]
|
||||
|
||||
TypeIndex has been tested and successfully work on many compilers.
|
||||
|
||||
[warning
|
||||
With RTTI off classes with exactly the same names defined in different modules in anonymous namespaces may collapse:
|
||||
```
|
||||
// In A.cpp
|
||||
namespace { struct user_defined{}; }
|
||||
type_index foo_a() { return type_id<user_defined>(); }
|
||||
|
||||
// In B.cpp
|
||||
namespace { struct user_defined{}; }
|
||||
type_index foo_b() { return type_id<user_defined>(); }
|
||||
|
||||
// In main.cpp
|
||||
assert(foo_a() != foo_b()); // will fail on some compilers
|
||||
```
|
||||
|
||||
*Compilers that have that limitation:* GCC, CLANG, Intel.
|
||||
|
||||
*Test:* you can test this issue by runing the `testing_crossmodule_anonymous_no_rtti` that can be build if you run `../../../b2` in `type_index/test/` folder.
|
||||
]
|
||||
|
||||
[section Define the BOOST_TYPE_INDEX_FUNCTION_SIGNATURE macro]
|
||||
|
||||
If you get the following error during compilation
|
||||
``
|
||||
TypeIndex library could not detect your compiler.
|
||||
Please make the BOOST_TYPE_INDEX_FUNCTION_SIGNATURE macro use
|
||||
correct compiler macro for getting the whole function name.
|
||||
Define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING to correct value after that.
|
||||
``
|
||||
then you are using a compiler that was not tested with this library.
|
||||
|
||||
[macroref BOOST_TYPE_INDEX_FUNCTION_SIGNATURE] must be defined to a compiler specific macro, that outputs the *whole*
|
||||
function signature including template parameters.
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Fixing pretty_name() output]
|
||||
|
||||
If the output of `boost::typeindex::ctti_type_index::type_id<int>().name()`
|
||||
* returns not just `int` but also a lot of text around the `int`
|
||||
* or does not return type at all
|
||||
then you are using a compiler that was not tested with this library and you need to setup the
|
||||
[macroref BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING] macro.
|
||||
|
||||
Here is a short instruction:
|
||||
|
||||
# get the output of `boost::typeindex::ctti_type_index::type_id<int>().name()`
|
||||
# define [macroref BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING] to
|
||||
`(skip_at_begin, skip_at_end, false, "")`, where
|
||||
* `skip_at_begin` is equal to characters count before the first occurrence of `int` in output
|
||||
* `skip_at_end` is equal to characters count after last occurrence of `int` in output
|
||||
# check that `boost::typeindex::ctti_type_index::type_id<int>().name_demangled()` returns "int"
|
||||
# if it does not return `int`, then define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING to
|
||||
`(skip_at_begin, skip_at_end, true, "T = ")`, where
|
||||
* `skip_at_begin` is equal to `skip_at_begin` at step 2
|
||||
* `skip_at_end` is equal to `skip_at_end` at step 2
|
||||
* `"T = "` is equal to characters that are right before the `int` in output
|
||||
# (optional, but highly recommended) [@http://www.boost.org/support/bugs.html create ticket] with
|
||||
feature request to add your compiler to supported compilers list. Include
|
||||
parameters provided to `BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING` macro.
|
||||
|
||||
|
||||
Consider the following example:
|
||||
|
||||
`boost::typeindex::ctti_type_index::type_id<int>().raw_name()` returns
|
||||
"const char *__cdecl boost::detail::ctti<int>::n(void)". Then you shall set
|
||||
`skip_at_begin` to `sizeof("const char *__cdecl boost::detail::ctti<") - 1`
|
||||
and `skip_at_end` to `sizeof(">::n(void)") - 1`.
|
||||
|
||||
``
|
||||
#define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING (39, 6, false, "")
|
||||
``
|
||||
|
||||
Another example:
|
||||
|
||||
`boost::typeindex::ctti_type_index::type_id<int>().raw_name()` returns
|
||||
"static const char *boost::detail::ctti<int>::n() [T = int]"". Then you shall set
|
||||
`skip_at_begin` to `sizeof("static const char *boost::detail::ctti<") - 1`
|
||||
and `skip_at_end` to `sizeof("]") - 1` and last parameter of macro to "T = ".
|
||||
|
||||
``
|
||||
#define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING (39, 1, true, "T = ")
|
||||
``
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Mixing sources with RTTI on and RTTI off]
|
||||
|
||||
Linking a binary from source files that were compiled with different RTTI flags is not a very good
|
||||
idea and may lead to a lot of surprises. However if there is a very strong need, TypeIndex library
|
||||
provides a solution for mixing sources: just define [macroref BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY]
|
||||
macro. This would lead to usage of same type_index class (`boost::typeindex::ctti_type_index` or
|
||||
`boost::typeindex::stl_type_index`) all around the project.
|
||||
|
||||
[note Do not forget to rebuild *all* the projects with `BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY` macro defined ]
|
||||
|
||||
You must know that linking RTTI on and RTTI off binaries may succeed even without defining the
|
||||
`BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY` macro, but that does not mean that you'll get a
|
||||
working binary. Such actions may break the One Definition Rule. Take a look at the table below,
|
||||
that shows how the `boost::type_index get_integer();` function will look like with different
|
||||
RTTI flags:
|
||||
|
||||
[table:diffs
|
||||
[[RTTI on] [RTTI off]]
|
||||
[[`boost::typeindex::stl_type_index get_integer();`] [`boost::typeindex::ctti_type_index get_integer();`]]
|
||||
]
|
||||
|
||||
Such differences are usually not detected by linker and lead to errors at runtime.
|
||||
|
||||
[warning
|
||||
Even with `BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY` defined there is no guarantee
|
||||
that everything will be OK. Libraries that use their own workarounds for disabled RTTI
|
||||
may fail to link or to work correctly.
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Acknowledgements]
|
||||
|
||||
In order of helping and advising:
|
||||
|
||||
* Peter Dimov for writing source codes in late 2007, that gave me an idea of how to emulate RTTI.
|
||||
* Agustín Bergé K-ballo for helping with docs and fixing a lot of typos.
|
||||
* Niall Douglas for generating a lot of great ideas, reviewing the sources and being the review manager for the library.
|
||||
* All the library reviewers, especially Andrey Semashev, for making good notes and proposing improvements to the library.
|
||||
|
||||
[endsect]
|
||||
99
examples/constexpr14_namespace_check.cpp
Normal file
99
examples/constexpr14_namespace_check.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
// Copyright 2013-2023 Antony Polukhin
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See the accompanying file LICENSE_1_0.txt
|
||||
// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
template <class T>
|
||||
void do_something(const T&) {}
|
||||
|
||||
|
||||
#if !defined(BOOST_NO_CXX14_CONSTEXPR) && !defined(BOOST_NO_CXX11_CONSTEXPR)
|
||||
// Implementation of this function is not essential for the example
|
||||
template <std::size_t N>
|
||||
constexpr bool starts_with(const char* name, const char (&ns)[N]) noexcept {
|
||||
for (std::size_t i = 0; i < N - 1; ++i)
|
||||
if (name[i] != ns[i])
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//[type_index_constexpr14_namespace_example
|
||||
/*`
|
||||
The following example shows that `boost::typeindex::ctti_type_index` is usable at compile time on
|
||||
a C++14 compatible compilers.
|
||||
|
||||
In this example we'll create and use a constexpr function that checks namespace of the provided type.
|
||||
*/
|
||||
|
||||
#include <boost/type_index/ctti_type_index.hpp>
|
||||
|
||||
// Helper function that returns true if `name` starts with `substr`
|
||||
template <std::size_t N>
|
||||
constexpr bool starts_with(const char* name, const char (&substr)[N]) noexcept;
|
||||
|
||||
|
||||
// Function that returns true if `T` declared in namespace `ns`
|
||||
template <class T, std::size_t N>
|
||||
constexpr bool in_namespace(const char (&ns)[N]) noexcept {
|
||||
const char* name = boost::typeindex::ctti_type_index::type_id<T>().raw_name();
|
||||
|
||||
// Some compilers add `class ` or `struct ` before the namespace, so we need to skip those words first
|
||||
if (starts_with(name, "class ")) {
|
||||
name += sizeof("class ") - 1;
|
||||
} else if (starts_with(name, "struct ")) {
|
||||
name += sizeof("struct ") - 1;
|
||||
}
|
||||
|
||||
return starts_with(name, ns) && starts_with(name + N - 1, "::");
|
||||
}
|
||||
|
||||
/*`
|
||||
Now when we have that wonderfull function, we can do static assertions and other compile-time validations:
|
||||
*/
|
||||
|
||||
namespace my_project {
|
||||
struct serializer {
|
||||
template <class T>
|
||||
void serialize(const T& value) {
|
||||
static_assert(
|
||||
in_namespace<T>("my_project::types") || in_namespace<T>("my_project::types_ext"),
|
||||
"Only types from namespaces `my_project::types` and `my_project::types_ext` are allowed to be serialized using `my_project::serializer`"
|
||||
);
|
||||
|
||||
// Actual implementation of the serialization goes below
|
||||
// ...
|
||||
do_something(value);
|
||||
}
|
||||
};
|
||||
|
||||
namespace types {
|
||||
struct foo{};
|
||||
struct bar{};
|
||||
}
|
||||
} // namespace my_project
|
||||
|
||||
int main() {
|
||||
my_project::serializer s;
|
||||
my_project::types::foo f;
|
||||
my_project::types::bar b;
|
||||
|
||||
s.serialize(f);
|
||||
s.serialize(b);
|
||||
|
||||
// short sh = 0;
|
||||
// s.serialize(sh); // Fails the static_assert!
|
||||
}
|
||||
//] [/type_index_constexpr14_namespace_example]
|
||||
|
||||
#else // #if !defined(BOOST_NO_CXX14_CONSTEXPR) && !defined(BOOST_NO_CXX11_CONSTEXPR)
|
||||
|
||||
int main() {}
|
||||
|
||||
#endif
|
||||
|
||||
76
examples/constexpr14_sort_check.cpp
Normal file
76
examples/constexpr14_sort_check.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
// Copyright 2013-2023 Antony Polukhin
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See the accompanying file LICENSE_1_0.txt
|
||||
// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if !defined(BOOST_NO_CXX14_CONSTEXPR) && !defined(BOOST_NO_CXX11_CONSTEXPR) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && (!defined(_MSC_VER) || (_MSC_VER > 1916))
|
||||
|
||||
//[type_index_constexpr14_sort_check_example
|
||||
/*`
|
||||
The following example shows that `boost::typeindex::ctti_type_index` is usable at compile time on
|
||||
a C++14 compatible compilers to check order of template parameters.
|
||||
|
||||
Consider the situation when we have a function that accepts std::tuple, boost::variant or some other class that uses variadic templates:
|
||||
*/
|
||||
|
||||
template <class... T> class types{};
|
||||
|
||||
template <class... T>
|
||||
void do_something(const types<T...>& t) noexcept;
|
||||
|
||||
/*`
|
||||
Such functions may be very usefull, however they may significantly increase the size of the resulting program. Each instantionation of such function with different templates order
|
||||
consumes space in the resulting program:
|
||||
|
||||
// Types are same, but different order leads to new instantionation of do_something function.
|
||||
types<bool, double, int>
|
||||
types<bool, int, double>
|
||||
types<int, bool, double>
|
||||
types<int, double, bool>
|
||||
types<double, int, bool>
|
||||
types<double, bool, int>
|
||||
|
||||
One of the ways to reduce instantinations count is to force the types to have some order:
|
||||
*/
|
||||
|
||||
|
||||
#include <boost/type_index/ctti_type_index.hpp>
|
||||
|
||||
// Implementing type trait that returns true if the types are sorted lexographicaly
|
||||
template <class... T>
|
||||
constexpr bool is_asc_sorted(types<T...>) noexcept {
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class Lhs, class Rhs, class... TN>
|
||||
constexpr bool is_asc_sorted(types<Lhs, Rhs, TN...>) noexcept {
|
||||
using namespace boost::typeindex;
|
||||
return ctti_type_index::type_id<Lhs>() <= ctti_type_index::type_id<Rhs>()
|
||||
&& is_asc_sorted(types<Rhs, TN...>());
|
||||
}
|
||||
|
||||
|
||||
// Using the newly created `is_asc_sorted` trait:
|
||||
template <class... T>
|
||||
void do_something(const types<T...>& /*value*/) noexcept {
|
||||
static_assert(
|
||||
is_asc_sorted( types<T...>() ),
|
||||
"T... for do_something(const types<T...>& t) must be sorted ascending"
|
||||
);
|
||||
}
|
||||
|
||||
int main() {
|
||||
do_something( types<bool, double, int>() );
|
||||
// do_something( types<bool, int, double>() ); // Fails the static_assert!
|
||||
}
|
||||
//] [/type_index_constexpr14_sort_check_example]
|
||||
|
||||
#else // #if !defined(BOOST_NO_CXX14_CONSTEXPR) && !defined(BOOST_NO_CXX11_CONSTEXPR) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && (!defined(_MSC_VER) || (_MSC_VER > 1916))
|
||||
|
||||
int main() {}
|
||||
|
||||
#endif
|
||||
|
||||
76
examples/demangled_names.cpp
Normal file
76
examples/demangled_names.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
// Copyright 2013-2023 Antony Polukhin
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See the accompanying file LICENSE_1_0.txt
|
||||
// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
|
||||
|
||||
|
||||
//[type_index_names_example
|
||||
/*`
|
||||
The following example shows how short (mangled) and human readable type names could be obtained from a type.
|
||||
Works with and without RTTI.
|
||||
*/
|
||||
|
||||
|
||||
#include <boost/type_index.hpp>
|
||||
#include <iostream>
|
||||
|
||||
template <class T>
|
||||
void foo(T) {
|
||||
std::cout << "\n Short name: " << boost::typeindex::type_id<T>().raw_name();
|
||||
std::cout << "\n Readable name: " << boost::typeindex::type_id<T>().pretty_name();
|
||||
}
|
||||
|
||||
struct user_defined_type{};
|
||||
|
||||
namespace ns1 { namespace ns2 {
|
||||
struct user_defined_type{};
|
||||
}} // namespace ns1::ns2
|
||||
|
||||
namespace {
|
||||
struct in_anon_type{};
|
||||
} // anonymous namespace
|
||||
|
||||
int main() {
|
||||
// Call to
|
||||
foo(1);
|
||||
// will output something like this:
|
||||
//
|
||||
// (RTTI on) (RTTI off)
|
||||
// Short name: i Short name: int]
|
||||
// Readable name: int Readable name: int
|
||||
|
||||
user_defined_type t;
|
||||
foo(t);
|
||||
// Will output:
|
||||
//
|
||||
// (RTTI on) (RTTI off)
|
||||
// Short name: 17user_defined_type user_defined_type]
|
||||
// Readable name: user_defined_type user_defined_type
|
||||
|
||||
ns1::ns2::user_defined_type t_in_ns;
|
||||
foo(t_in_ns);
|
||||
// Will output:
|
||||
//
|
||||
// (RTTI on) (RTTI off)
|
||||
// Short name: N3ns13ns217user_defined_typeE ns1::ns2::user_defined_type]
|
||||
// Readable name: ns1::ns2::user_defined_type ns1::ns2::user_defined_type
|
||||
|
||||
in_anon_type anon_t;
|
||||
foo(anon_t);
|
||||
// Will output:
|
||||
//
|
||||
// (RTTI on) (RTTI off)
|
||||
// Short name: N12_GLOBAL__N_112in_anon_typeE {anonymous}::in_anon_type]
|
||||
// Readable name: (anonymous namespace)::in_anon_type {anonymous}::in_anon_type
|
||||
}
|
||||
|
||||
/*`
|
||||
Short names are very compiler dependant: some compiler will output `.H`, others `i`.
|
||||
|
||||
Readable names may also differ between compilers: `struct user_defined_type`, `user_defined_type`.
|
||||
|
||||
[warning With RTTI off different classes with same names in anonymous namespace may collapse. See 'RTTI emulation limitations'. ]
|
||||
*/
|
||||
|
||||
//] [/type_index_names_example]
|
||||
76
examples/exact_types_match.cpp
Normal file
76
examples/exact_types_match.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
// Copyright 2013-2023 Antony Polukhin
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See the accompanying file LICENSE_1_0.txt
|
||||
// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
|
||||
|
||||
//[type_index_exact_type_match_example
|
||||
/*`
|
||||
The following example shows that `type_index` (and `type_info`) is able to store the exact type,
|
||||
without stripping const, volatile and references. Example works with and without RTTI.
|
||||
|
||||
In this example we'll create a class that stores a pointer to function and remembers the exact type of the
|
||||
parameter the function accepts. When the call to the bound function is made, he actual input parameter
|
||||
type is checked against the stored parameter type and an exception is thrown in case of mismatch.
|
||||
*/
|
||||
|
||||
#include <boost/type_index.hpp>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <cstdlib>
|
||||
|
||||
//<-
|
||||
// Making `#include <cassert>` visible in docs, while actually using hand-made check
|
||||
// instead of `assert`. This is required to verify correct behavior even if NDEBUG
|
||||
// is defined and to avoid `unused local variable` warnings with defined NDEBUG.
|
||||
//
|
||||
// boost-no-inspect
|
||||
#ifdef assert
|
||||
# undef assert
|
||||
#endif
|
||||
#define assert(X) if (!(X)) std::exit(__LINE__)
|
||||
/* !Comment block is not closed intentionaly!
|
||||
//->
|
||||
#include <cassert>
|
||||
//<-
|
||||
!Closing comment block! */
|
||||
//->
|
||||
|
||||
class type_erased_unary_function {
|
||||
void* function_ptr_;
|
||||
boost::typeindex::type_index exact_param_t_;
|
||||
|
||||
public:
|
||||
template <class ParamT>
|
||||
type_erased_unary_function(void(*ptr)(ParamT))
|
||||
: function_ptr_(reinterpret_cast<void*>(ptr)) // ptr - is a pointer to function returning `void` and accepting parameter of type `ParamT`
|
||||
, exact_param_t_(boost::typeindex::type_id_with_cvr<ParamT>())
|
||||
{}
|
||||
|
||||
template <class ParamT>
|
||||
void call(ParamT v) {
|
||||
if (exact_param_t_ != boost::typeindex::type_id_with_cvr<ParamT>()) {
|
||||
throw std::runtime_error("Incorrect `ParamT`");
|
||||
}
|
||||
|
||||
return (reinterpret_cast<void(*)(ParamT)>(function_ptr_))(v);
|
||||
}
|
||||
};
|
||||
|
||||
void foo(int){}
|
||||
|
||||
int main() {
|
||||
type_erased_unary_function func(&foo);
|
||||
func.call(100); // OK, `100` has type `int`
|
||||
|
||||
try {
|
||||
int i = 100;
|
||||
|
||||
// An attempt to convert stored function to a function accepting reference
|
||||
func.call<int&>(i); // Will throw, because types `int&` and `int` mismatch
|
||||
|
||||
assert(false);
|
||||
} catch (const std::runtime_error& /*e*/) {}
|
||||
}
|
||||
|
||||
//] [/type_index_exact_type_match_example]
|
||||
47
examples/inheritance.cpp
Normal file
47
examples/inheritance.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
// Copyright 2013-2023 Antony Polukhin
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See the accompanying file LICENSE_1_0.txt
|
||||
// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
|
||||
|
||||
//[type_index_derived_example
|
||||
/*`
|
||||
The following example shows that `type_info` is able to store the real type, successfully getting through
|
||||
all the inheritances.
|
||||
|
||||
Example works with and without RTTI."
|
||||
*/
|
||||
|
||||
#include <boost/type_index.hpp>
|
||||
#include <boost/type_index/runtime_cast/register_runtime_class.hpp>
|
||||
#include <iostream>
|
||||
|
||||
struct A {
|
||||
BOOST_TYPE_INDEX_REGISTER_CLASS
|
||||
virtual ~A(){}
|
||||
};
|
||||
struct B: public A { BOOST_TYPE_INDEX_REGISTER_CLASS };
|
||||
struct C: public B { BOOST_TYPE_INDEX_REGISTER_CLASS };
|
||||
struct D: public C { BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS() };
|
||||
|
||||
void print_real_type(const A& a) {
|
||||
std::cout << boost::typeindex::type_id_runtime(a).pretty_name() << '\n';
|
||||
}
|
||||
|
||||
int main() {
|
||||
C c;
|
||||
const A& c_as_a = c;
|
||||
print_real_type(c_as_a); // Outputs `struct C`
|
||||
print_real_type(B()); // Outputs `struct B`
|
||||
|
||||
/*`
|
||||
It's also possible to use type_id_runtime with the BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS, which adds additional
|
||||
information for runtime_cast to work.
|
||||
*/
|
||||
D d;
|
||||
const A& d_as_a = d;
|
||||
print_real_type(d_as_a); // Outputs `struct D`
|
||||
|
||||
}
|
||||
|
||||
//] [/type_index_derived_example]
|
||||
55
examples/registry.cpp
Normal file
55
examples/registry.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
// Copyright 2013-2023 Antony Polukhin
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See the accompanying file LICENSE_1_0.txt
|
||||
// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
|
||||
|
||||
//[type_index_registry_example
|
||||
/*`
|
||||
The following example shows how an information about a type could be stored.
|
||||
Example works with and without RTTI.
|
||||
*/
|
||||
|
||||
#include <boost/type_index.hpp>
|
||||
#include <boost/unordered/unordered_set.hpp>
|
||||
//<-
|
||||
// Making `#include <cassert>` visible in docs, while actually using `BOOST_TEST`
|
||||
// instead of `assert`. This is required to verify correct behavior even if NDEBUG
|
||||
// is defined and to avoid `unused local variable` warnings with defined NDEBUG.
|
||||
//
|
||||
// boost-no-inspect
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#ifdef assert
|
||||
# undef assert
|
||||
#endif
|
||||
#define assert(X) BOOST_TEST(X)
|
||||
/* !Comment block is not closed intentionaly!
|
||||
//->
|
||||
#include <cassert>
|
||||
//<-
|
||||
!Closing comment block! */
|
||||
//->
|
||||
|
||||
int main() {
|
||||
boost::unordered_set<boost::typeindex::type_index> types;
|
||||
|
||||
// Storing some `boost::type_info`s
|
||||
types.insert(boost::typeindex::type_id<int>());
|
||||
types.insert(boost::typeindex::type_id<float>());
|
||||
|
||||
// `types` variable contains two `boost::type_index`es:
|
||||
assert(types.size() == 2);
|
||||
|
||||
// Const, volatile and reference will be striped from the type:
|
||||
bool is_inserted = types.insert(boost::typeindex::type_id<const int>()).second;
|
||||
assert(!is_inserted);
|
||||
assert(types.erase(boost::typeindex::type_id<float&>()) == 1);
|
||||
|
||||
// We have erased the `float` type, only `int` remains
|
||||
assert(*types.begin() == boost::typeindex::type_id<int>());
|
||||
//<-
|
||||
return boost::report_errors();
|
||||
//->
|
||||
}
|
||||
|
||||
//] [/type_index_registry_example]
|
||||
90
examples/runtime_cast.cpp
Normal file
90
examples/runtime_cast.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
//
|
||||
// Copyright (c) Chris Glover, 2016.
|
||||
//
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
//[type_index_runtime_cast_example
|
||||
/*`
|
||||
The following example shows that `runtime_cast` is able to find a valid pointer
|
||||
in various class hierarchies regardless of inheritance or type relation.
|
||||
|
||||
Example works with and without RTTI."
|
||||
*/
|
||||
|
||||
#include <boost/type_index/runtime_cast.hpp>
|
||||
#include <iostream>
|
||||
|
||||
struct A {
|
||||
BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS()
|
||||
virtual ~A()
|
||||
{}
|
||||
};
|
||||
|
||||
struct B {
|
||||
BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS()
|
||||
virtual ~B()
|
||||
{}
|
||||
};
|
||||
|
||||
struct C : A {
|
||||
BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(A)
|
||||
};
|
||||
|
||||
struct D : B {
|
||||
BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(B)
|
||||
};
|
||||
|
||||
struct E : C, D {
|
||||
BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(C, D)
|
||||
};
|
||||
|
||||
int main() {
|
||||
C c;
|
||||
A* a = &c;
|
||||
|
||||
if(C* cp = boost::typeindex::runtime_cast<C*>(a)) {
|
||||
std::cout << "Yes, a points to a C: "
|
||||
<< a << "->" << cp << '\n';
|
||||
}
|
||||
else {
|
||||
std::cout << "Error: Expected a to point to a C" << '\n';
|
||||
}
|
||||
|
||||
if(E* ce = boost::typeindex::runtime_cast<E*>(a)) {
|
||||
std::cout << "Error: Expected a to not points to an E: "
|
||||
<< a << "->" << ce << '\n';
|
||||
}
|
||||
else {
|
||||
std::cout << "But, a does not point to an E" << '\n';
|
||||
}
|
||||
|
||||
E e;
|
||||
C* cp2 = &e;
|
||||
if(D* dp = boost::typeindex::runtime_cast<D*>(cp2)) {
|
||||
std::cout << "Yes, we can cross-cast from a C* to a D* when we actually have an E: "
|
||||
<< cp2 << "->" << dp << '\n';
|
||||
}
|
||||
else {
|
||||
std::cout << "Error: Expected cp to point to a D" << '\n';
|
||||
}
|
||||
|
||||
/*`
|
||||
Alternatively, we can use runtime_pointer_cast so we don't need to specity the target as a pointer.
|
||||
This works for smart_ptr types too.
|
||||
*/
|
||||
A* ap = &e;
|
||||
if(B* bp = boost::typeindex::runtime_pointer_cast<B>(ap)) {
|
||||
std::cout << "Yes, we can cross-cast and up-cast at the same time."
|
||||
<< ap << "->" << bp << '\n';
|
||||
}
|
||||
else {
|
||||
std::cout << "Error: Expected ap to point to a B" << '\n';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//] [/type_index_runtime_cast_example]
|
||||
90
examples/table_of_names.cpp
Normal file
90
examples/table_of_names.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
// Copyright 2013-2023 Antony Polukhin
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See the accompanying file LICENSE_1_0.txt
|
||||
// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
|
||||
|
||||
|
||||
//[type_index_names_table
|
||||
/*`
|
||||
The following example shows how different type names look when we explicitly use classes for RTTI and RTT off.
|
||||
|
||||
This example requires RTTI. For a more portable example see 'Getting human readable and mangled type names':
|
||||
*/
|
||||
|
||||
|
||||
#include <boost/type_index/stl_type_index.hpp>
|
||||
#include <boost/type_index/ctti_type_index.hpp>
|
||||
#include <iostream>
|
||||
|
||||
template <class T>
|
||||
void print(const char* name) {
|
||||
boost::typeindex::stl_type_index sti = boost::typeindex::stl_type_index::type_id<T>();
|
||||
boost::typeindex::ctti_type_index cti = boost::typeindex::ctti_type_index::type_id<T>();
|
||||
std::cout << "\t[" /* start of the row */
|
||||
<< "[" << name << "]"
|
||||
<< "[`" << sti.raw_name() << "`] "
|
||||
<< "[`" << sti.pretty_name() << "`] "
|
||||
<< "[`" << cti.raw_name() << "`] "
|
||||
<< "]\n" /* end of the row */ ;
|
||||
}
|
||||
|
||||
struct user_defined_type{};
|
||||
|
||||
namespace ns1 { namespace ns2 {
|
||||
struct user_defined_type{};
|
||||
}} // namespace ns1::ns2
|
||||
|
||||
namespace {
|
||||
struct in_anon_type{};
|
||||
} // anonymous namespace
|
||||
|
||||
namespace ns3 { namespace { namespace ns4 {
|
||||
struct in_anon_type{};
|
||||
}}} // namespace ns3::{anonymous}::ns4
|
||||
|
||||
|
||||
template <class T0, class T1>
|
||||
class templ {};
|
||||
|
||||
template <>
|
||||
class templ<int, int> {};
|
||||
|
||||
int main() {
|
||||
std::cout << "[table:id Table of names\n";
|
||||
std::cout << "\t[[Type] [RTTI & raw_name] [RTTI & pretty_name] [noRTTI & raw_name]]\n";
|
||||
|
||||
print<user_defined_type>("User defined type");
|
||||
print<in_anon_type>("In anonymous namespace");
|
||||
print<ns3::ns4::in_anon_type>("In ns3::{anonymous}::ns4 namespace");
|
||||
print<templ<short, int> >("Template class");
|
||||
print<templ<int, int> >("Template class (full specialization)");
|
||||
print<templ<
|
||||
templ<char, signed char>,
|
||||
templ<int, user_defined_type>
|
||||
> >("Template class with templae classes");
|
||||
|
||||
|
||||
std::cout << "]\n";
|
||||
}
|
||||
|
||||
/*`
|
||||
Code from the example will produce the following table:
|
||||
|
||||
[table:id Table of names
|
||||
[[Type] [RTTI & raw_name] [RTTI & pretty_name] [noRTTI & raw_name]]
|
||||
[[User defined type][`17user_defined_type`] [`user_defined_type`] [`user_defined_type]`] ]
|
||||
[[In anonymous namespace][`N12_GLOBAL__N_112in_anon_typeE`] [`(anonymous namespace)::in_anon_type`] [`{anonymous}::in_anon_type]`] ]
|
||||
[[In ns3::{anonymous}::ns4 namespace][`N3ns312_GLOBAL__N_13ns412in_anon_typeE`] [`ns3::(anonymous namespace)::ns4::in_anon_type`] [`ns3::{anonymous}::ns4::in_anon_type]`] ]
|
||||
[[Template class][`5templIsiE`] [`templ<short, int>`] [`templ<short int, int>]`] ]
|
||||
[[Template class (full specialization)][`5templIiiE`] [`templ<int, int>`] [`templ<int, int>]`] ]
|
||||
[[Template class with template classes][`5templIS_IcaES_Ii17user_defined_typeEE`] [`templ<templ<char, signed char>, templ<int, user_defined_type> >`] [`templ<templ<char, signed char>, templ<int, user_defined_type> >]`] ]
|
||||
]
|
||||
|
||||
We have not show the "noRTTI & pretty_name" column in the table because it is almost equal
|
||||
to "noRTTI & raw_name" column.
|
||||
|
||||
[warning With RTTI off different classes with same names in anonymous namespace may collapse. See 'RTTI emulation limitations'. ]
|
||||
*/
|
||||
|
||||
//] [/type_index_names_table]
|
||||
73
examples/user_defined_typeinfo.cpp
Normal file
73
examples/user_defined_typeinfo.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
// Copyright 2013-2023 Antony Polukhin
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See the accompanying file LICENSE_1_0.txt
|
||||
// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
|
||||
|
||||
|
||||
//[type_index_my_type_index_worldwide_macro
|
||||
/*`
|
||||
There is an easy way to force `boost::typeindex::type_id` to use your own type_index class.
|
||||
|
||||
All we need to do is just define `BOOST_TYPE_INDEX_USER_TYPEINDEX` to the full path to header file
|
||||
of your type index class:
|
||||
*/
|
||||
|
||||
// BOOST_TYPE_INDEX_USER_TYPEINDEX must be defined *BEFORE* first inclusion of <boost/type_index.hpp>
|
||||
#define BOOST_TYPE_INDEX_USER_TYPEINDEX <boost/../libs/type_index/examples/user_defined_typeinfo.hpp>
|
||||
#include <boost/type_index.hpp>
|
||||
//] [/type_index_my_type_index_worldwide_macro]
|
||||
|
||||
// boost-no-inspect
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#ifdef assert
|
||||
# undef assert
|
||||
#endif
|
||||
#define assert(X) BOOST_TEST(X)
|
||||
|
||||
|
||||
using namespace my_namespace;
|
||||
|
||||
int main() {
|
||||
//[type_index_my_type_index_usage
|
||||
/*`
|
||||
Finally we can use the my_type_index class for getting type indexes:
|
||||
*/
|
||||
|
||||
my_type_index
|
||||
cl1 = my_type_index::type_id<my_class>(),
|
||||
st1 = my_type_index::type_id<my_struct>(),
|
||||
st2 = my_type_index::type_id<my_struct>(),
|
||||
vec = my_type_index::type_id<my_classes>()
|
||||
;
|
||||
|
||||
assert(cl1 != st1);
|
||||
assert(st2 == st1);
|
||||
assert(vec.pretty_name() == "my_classes");
|
||||
assert(cl1.pretty_name() == "my_class");
|
||||
|
||||
//] [/type_index_my_type_index_usage]
|
||||
|
||||
//[type_index_my_type_index_type_id_runtime_test
|
||||
/*`
|
||||
Now the following example will compile and work.
|
||||
*/
|
||||
my_struct str;
|
||||
my_class& reference = str;
|
||||
assert(my_type_index::type_id<my_struct>() == my_type_index::type_id_runtime(reference));
|
||||
//][/type_index_my_type_index_type_id_runtime_test]
|
||||
|
||||
//[type_index_my_type_index_worldwide_usage
|
||||
/*`
|
||||
That's it! Now all TypeIndex global methods and typedefs will be using your class:
|
||||
*/
|
||||
boost::typeindex::type_index worldwide = boost::typeindex::type_id<my_classes>();
|
||||
assert(worldwide.pretty_name() == "my_classes");
|
||||
assert(worldwide == my_type_index::type_id<my_classes>());
|
||||
//][/type_index_my_type_index_worldwide_usage]
|
||||
//<-
|
||||
return boost::report_errors();
|
||||
//->
|
||||
}
|
||||
|
||||
|
||||
213
examples/user_defined_typeinfo.hpp
Normal file
213
examples/user_defined_typeinfo.hpp
Normal file
@@ -0,0 +1,213 @@
|
||||
// Copyright 2013-2023 Antony Polukhin
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See the accompanying file LICENSE_1_0.txt
|
||||
// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
|
||||
|
||||
#ifndef USER_DEFINED_TYPEINFO_HPP
|
||||
#define USER_DEFINED_TYPEINFO_HPP
|
||||
|
||||
//[type_index_userdefined_usertypes
|
||||
/*`
|
||||
The following example shows how a user defined type_info can be created and used.
|
||||
Example works with and without RTTI.
|
||||
|
||||
Consider situation when user uses only those types in `typeid()`:
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace my_namespace {
|
||||
|
||||
class my_class;
|
||||
struct my_struct;
|
||||
|
||||
typedef std::vector<my_class> my_classes;
|
||||
typedef std::string my_string;
|
||||
|
||||
} // namespace my_namespace
|
||||
|
||||
//] [/type_index_userdefined_usertypes]
|
||||
|
||||
|
||||
//[type_index_userdefined_enum
|
||||
/*`
|
||||
In that case user may wish to save space in binary and create it's own type system.
|
||||
For that case `detail::typenum<>` meta function is added. Depending on the input type T
|
||||
this function will return different numeric values.
|
||||
*/
|
||||
#include <boost/type_index/type_index_facade.hpp>
|
||||
|
||||
namespace my_namespace { namespace detail {
|
||||
template <class T> struct typenum;
|
||||
template <> struct typenum<void>{ enum {value = 0}; };
|
||||
template <> struct typenum<my_class>{ enum {value = 1}; };
|
||||
template <> struct typenum<my_struct>{ enum {value = 2}; };
|
||||
template <> struct typenum<my_classes>{ enum {value = 3}; };
|
||||
template <> struct typenum<my_string>{ enum {value = 4}; };
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4510 4512 4610) // non-copyable non-constructable type
|
||||
#endif
|
||||
|
||||
// my_typeinfo structure is used to save type number
|
||||
struct my_typeinfo {
|
||||
const char* const type_;
|
||||
};
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
const my_typeinfo infos[5] = {
|
||||
{"void"}, {"my_class"}, {"my_struct"}, {"my_classes"}, {"my_string"}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
inline const my_typeinfo& my_typeinfo_construct() {
|
||||
return infos[typenum<T>::value];
|
||||
}
|
||||
}} // my_namespace::detail
|
||||
|
||||
//] [/type_index_userdefined_usertypes]
|
||||
|
||||
|
||||
//[type_index_my_type_index
|
||||
/*`
|
||||
`my_type_index` is a user created type_index class. If in doubt during this phase, you can always
|
||||
take a look at the `<boost/type_index/ctti_type_index.hpp>` or `<boost/type_index/stl_type_index.hpp>`
|
||||
files. Documentation for `type_index_facade` could be also useful.
|
||||
*/
|
||||
|
||||
/*`
|
||||
Since we are not going to override `type_index_facade::hash_code()` we must additionally include
|
||||
`<boost/container_hash/hash.hpp>`.
|
||||
*/
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
|
||||
/*`
|
||||
See implementation of `my_type_index`:
|
||||
*/
|
||||
namespace my_namespace {
|
||||
|
||||
class my_type_index: public boost::typeindex::type_index_facade<my_type_index, detail::my_typeinfo> {
|
||||
const detail::my_typeinfo* data_;
|
||||
|
||||
public:
|
||||
typedef detail::my_typeinfo type_info_t;
|
||||
|
||||
inline my_type_index() BOOST_NOEXCEPT
|
||||
: data_(&detail::my_typeinfo_construct<void>())
|
||||
{}
|
||||
|
||||
inline my_type_index(const type_info_t& data) BOOST_NOEXCEPT
|
||||
: data_(&data)
|
||||
{}
|
||||
|
||||
inline const type_info_t& type_info() const BOOST_NOEXCEPT {
|
||||
return *data_;
|
||||
}
|
||||
|
||||
inline const char* raw_name() const BOOST_NOEXCEPT {
|
||||
return data_->type_;
|
||||
}
|
||||
|
||||
inline std::string pretty_name() const {
|
||||
return data_->type_;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline static my_type_index type_id() BOOST_NOEXCEPT {
|
||||
return detail::my_typeinfo_construct<T>();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline static my_type_index type_id_with_cvr() BOOST_NOEXCEPT {
|
||||
return detail::my_typeinfo_construct<T>();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline static my_type_index type_id_runtime(const T& variable) BOOST_NOEXCEPT;
|
||||
};
|
||||
|
||||
} // namespace my_namespace
|
||||
|
||||
/*`
|
||||
Note that we have used the boost::typeindex::type_index_facade class as base.
|
||||
That class took care about all the helper function and operators (comparison, hashing, ostreaming and others).
|
||||
*/
|
||||
|
||||
//] [/type_index_my_type_index]
|
||||
|
||||
//[type_index_my_type_index_register_class
|
||||
/*`
|
||||
Usually to allow runtime type info we need to register class with some macro.
|
||||
Let's see how a `MY_TYPEINDEX_REGISTER_CLASS` macro could be implemented for our `my_type_index` class:
|
||||
*/
|
||||
namespace my_namespace { namespace detail {
|
||||
|
||||
template <class T>
|
||||
inline const my_typeinfo& my_typeinfo_construct_ref(const T*) {
|
||||
return my_typeinfo_construct<T>();
|
||||
}
|
||||
|
||||
#define MY_TYPEINDEX_REGISTER_CLASS \
|
||||
virtual const my_namespace::detail::my_typeinfo& type_id_runtime() const { \
|
||||
return my_namespace::detail::my_typeinfo_construct_ref(this); \
|
||||
}
|
||||
|
||||
}} // namespace my_namespace::detail
|
||||
|
||||
//] [/type_index_my_type_index_register_class]
|
||||
|
||||
//[type_index_my_type_index_type_id_runtime_implmentation
|
||||
/*`
|
||||
Now when we have a MY_TYPEINDEX_REGISTER_CLASS, let's implement a `my_type_index::type_id_runtime` method:
|
||||
*/
|
||||
namespace my_namespace {
|
||||
template <class T>
|
||||
my_type_index my_type_index::type_id_runtime(const T& variable) BOOST_NOEXCEPT {
|
||||
// Classes that were marked with `MY_TYPEINDEX_REGISTER_CLASS` will have a
|
||||
// `type_id_runtime()` method.
|
||||
return variable.type_id_runtime();
|
||||
}
|
||||
}
|
||||
//] [/type_index_my_type_index_type_id_runtime_implmentation]
|
||||
|
||||
//[type_index_my_type_index_type_id_runtime_classes
|
||||
/*`
|
||||
Consider the situation, when `my_class` and `my_struct` are polymorphic classes:
|
||||
*/
|
||||
|
||||
namespace my_namespace {
|
||||
|
||||
class my_class {
|
||||
public:
|
||||
MY_TYPEINDEX_REGISTER_CLASS
|
||||
virtual ~my_class() {}
|
||||
};
|
||||
|
||||
struct my_struct: public my_class {
|
||||
MY_TYPEINDEX_REGISTER_CLASS
|
||||
};
|
||||
|
||||
} // namespace my_namespace
|
||||
|
||||
//] [/type_index_my_type_index_type_id_runtime_classes]
|
||||
|
||||
|
||||
//[type_index_my_type_index_worldwide_typedefs
|
||||
/*`
|
||||
You'll also need to add some typedefs and macro to your "user_defined_typeinfo.hpp" header file:
|
||||
*/
|
||||
#define BOOST_TYPE_INDEX_REGISTER_CLASS MY_TYPEINDEX_REGISTER_CLASS
|
||||
namespace boost { namespace typeindex {
|
||||
typedef my_namespace::my_type_index type_index;
|
||||
}}
|
||||
//] [/type_index_my_type_index_worldwide_typedefs]
|
||||
|
||||
|
||||
#endif // USER_DEFINED_TYPEINFO_HPP
|
||||
|
||||
265
include/boost/type_index.hpp
Normal file
265
include/boost/type_index.hpp
Normal file
@@ -0,0 +1,265 @@
|
||||
//
|
||||
// Copyright 2012-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)
|
||||
//
|
||||
|
||||
#ifndef BOOST_TYPE_INDEX_HPP
|
||||
#define BOOST_TYPE_INDEX_HPP
|
||||
|
||||
/// \file boost/type_index.hpp
|
||||
/// \brief Includes minimal set of headers required to use the Boost.TypeIndex library.
|
||||
///
|
||||
/// By inclusion of this file most optimal type index classes will be included and used
|
||||
/// as a boost::typeindex::type_index and boost::typeindex::type_info.
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_TYPE_INDEX_USER_TYPEINDEX)
|
||||
# include BOOST_TYPE_INDEX_USER_TYPEINDEX
|
||||
# ifdef BOOST_HAS_PRAGMA_DETECT_MISMATCH
|
||||
# pragma detect_mismatch( "boost__type_index__abi", "user defined type_index class is used: " BOOST_STRINGIZE(BOOST_TYPE_INDEX_USER_TYPEINDEX))
|
||||
# endif
|
||||
#elif (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined(BOOST_MSVC)
|
||||
# include <boost/type_index/stl_type_index.hpp>
|
||||
# if defined(BOOST_NO_RTTI) || defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)
|
||||
# include <boost/type_index/detail/stl_register_class.hpp>
|
||||
# ifdef BOOST_HAS_PRAGMA_DETECT_MISMATCH
|
||||
# pragma detect_mismatch( "boost__type_index__abi", "RTTI is off - typeid() is used only for templates")
|
||||
# endif
|
||||
# else
|
||||
# ifdef BOOST_HAS_PRAGMA_DETECT_MISMATCH
|
||||
# pragma detect_mismatch( "boost__type_index__abi", "RTTI is used")
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
# include <boost/type_index/ctti_type_index.hpp>
|
||||
# include <boost/type_index/detail/ctti_register_class.hpp>
|
||||
# ifdef BOOST_HAS_PRAGMA_DETECT_MISMATCH
|
||||
# pragma detect_mismatch( "boost__type_index__abi", "RTTI is off - using CTTI")
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_TYPE_INDEX_REGISTER_CLASS
|
||||
#define BOOST_TYPE_INDEX_REGISTER_CLASS
|
||||
#endif
|
||||
|
||||
namespace boost { namespace typeindex {
|
||||
|
||||
#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
|
||||
|
||||
/// \def BOOST_TYPE_INDEX_FUNCTION_SIGNATURE
|
||||
/// BOOST_TYPE_INDEX_FUNCTION_SIGNATURE is used by boost::typeindex::ctti_type_index class to
|
||||
/// deduce the name of a type. If your compiler is not recognized
|
||||
/// by the TypeIndex library and you wish to work with boost::typeindex::ctti_type_index, you may
|
||||
/// define this macro by yourself.
|
||||
///
|
||||
/// BOOST_TYPE_INDEX_FUNCTION_SIGNATURE must be defined to a compiler specific macro
|
||||
/// that outputs the \b whole function signature \b including \b template \b parameters.
|
||||
///
|
||||
/// If your compiler is not recognised and BOOST_TYPE_INDEX_FUNCTION_SIGNATURE is not defined,
|
||||
/// then a compile-time error will arise at any attempt to use boost::typeindex::ctti_type_index classes.
|
||||
///
|
||||
/// See BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS and BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING
|
||||
/// for an information of how to tune the implementation to make a nice pretty_name() output.
|
||||
#define BOOST_TYPE_INDEX_FUNCTION_SIGNATURE BOOST_CURRENT_FUNCTION
|
||||
|
||||
/// \def BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING
|
||||
/// This is a helper macro for making correct pretty_names() with RTTI off.
|
||||
///
|
||||
/// BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING macro may be defined to
|
||||
/// '(begin_skip, end_skip, runtime_skip, runtime_skip_until)' with parameters for adding a
|
||||
/// support for compilers, that by default are not recognized by TypeIndex library.
|
||||
///
|
||||
/// \b Example:
|
||||
///
|
||||
/// Imagine the situation when
|
||||
/// \code boost::typeindex::ctti_type_index::type_id<int>().pretty_name() \endcode
|
||||
/// returns the following string:
|
||||
/// \code "static const char *boost::detail::ctti<int>::n() [T = int]" \endcode
|
||||
/// and \code boost::typeindex::ctti_type_index::type_id<short>().pretty_name() \endcode returns the following:
|
||||
/// \code "static const char *boost::detail::ctti<short>::n() [T = short]" \endcode
|
||||
///
|
||||
/// As we may see first 39 characters are "static const char *boost::detail::ctti<" and they do not depend on
|
||||
/// the type T. After first 39 characters we have a human readable type name which is duplicated at the end
|
||||
/// of a string. String always ends on ']', which consumes 1 character.
|
||||
///
|
||||
/// Now if we define `BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING` to
|
||||
/// `(39, 1, false, "")` we'll be getting \code "int>::n() [T = int" \endcode
|
||||
/// for `boost::typeindex::ctti_type_index::type_id<int>().pretty_name()` and \code "short>::n() [T = short" \endcode
|
||||
/// for `boost::typeindex::ctti_type_index::type_id<short>().pretty_name()`.
|
||||
///
|
||||
/// Now we need to take additional care of the characters that go before the last mention of our type. We'll
|
||||
/// do that by telling the macro that we need to cut off everything that goes before the "T = " including the "T = "
|
||||
/// itself:
|
||||
///
|
||||
/// \code (39, 1, true, "T = ") \endcode
|
||||
///
|
||||
/// In case of GCC or Clang command line we need to add the following line while compiling all the sources:
|
||||
///
|
||||
/// \code
|
||||
/// -DBOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING='(39, 1, true, "T = ")'
|
||||
/// \endcode
|
||||
/// \param begin_skip How many characters must be skipped at the beginning of the type holding string.
|
||||
/// Must be a compile time constant.
|
||||
/// \param end_skip How many characters must be skipped at the end of the type holding string.
|
||||
/// Must be a compile time constant.
|
||||
/// \param runtime_skip Do we need additional checks at runtime to cut off the more characters.
|
||||
/// Must be `true` or `false`.
|
||||
/// \param runtime_skip_until Skip all the characters before the following string (including the string itself).
|
||||
/// Must be a compile time array of characters.
|
||||
///
|
||||
/// See [RTTI emulation limitations](boost_typeindex/rtti_emulation_limitations.html) for more info.
|
||||
#define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING (0, 0, false, "")
|
||||
|
||||
|
||||
/// Depending on a compiler flags, optimal implementation of type_index will be used
|
||||
/// as a default boost::typeindex::type_index.
|
||||
///
|
||||
/// Could be a boost::typeindex::stl_type_index, boost::typeindex::ctti_type_index or
|
||||
/// user defined type_index class.
|
||||
///
|
||||
/// \b See boost::typeindex::type_index_facade for a full description of type_index functions.
|
||||
typedef platform_specific type_index;
|
||||
#elif defined(BOOST_TYPE_INDEX_USER_TYPEINDEX)
|
||||
// Nothing to do
|
||||
#elif (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined(BOOST_MSVC)
|
||||
typedef boost::typeindex::stl_type_index type_index;
|
||||
#else
|
||||
typedef boost::typeindex::ctti_type_index type_index;
|
||||
#endif
|
||||
|
||||
/// Depending on a compiler flags, optimal implementation of type_info will be used
|
||||
/// as a default boost::typeindex::type_info.
|
||||
///
|
||||
/// Could be a std::type_info, boost::typeindex::detail::ctti_data or
|
||||
/// some user defined class.
|
||||
///
|
||||
/// type_info \b is \b not copyable or default constructible. It is \b not assignable too!
|
||||
typedef type_index::type_info_t type_info;
|
||||
|
||||
#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
|
||||
|
||||
/// \def BOOST_TYPE_INDEX_USER_TYPEINDEX
|
||||
/// BOOST_TYPE_INDEX_USER_TYPEINDEX can be defined to the path to header file
|
||||
/// with user provided implementation of type_index.
|
||||
///
|
||||
/// See [Making a custom type_index](boost_typeindex/making_a_custom_type_index.html) section
|
||||
/// of documentation for usage example.
|
||||
#define BOOST_TYPE_INDEX_USER_TYPEINDEX <full/absolute/path/to/header/with/type_index.hpp>
|
||||
|
||||
|
||||
/// \def BOOST_TYPE_INDEX_REGISTER_CLASS
|
||||
/// BOOST_TYPE_INDEX_REGISTER_CLASS is used to help to emulate RTTI.
|
||||
/// Put this macro into the public section of polymorphic class to allow runtime type detection.
|
||||
///
|
||||
/// Depending on the typeid() availability this macro will expand to nothing or to virtual helper function
|
||||
/// `virtual const type_info& boost_type_info_type_id_runtime_() const noexcept`.
|
||||
///
|
||||
/// \b Example:
|
||||
/// \code
|
||||
/// class A {
|
||||
/// public:
|
||||
/// BOOST_TYPE_INDEX_REGISTER_CLASS
|
||||
/// virtual ~A(){}
|
||||
/// };
|
||||
///
|
||||
/// struct B: public A {
|
||||
/// BOOST_TYPE_INDEX_REGISTER_CLASS
|
||||
/// };
|
||||
///
|
||||
/// struct C: public B {
|
||||
/// BOOST_TYPE_INDEX_REGISTER_CLASS
|
||||
/// };
|
||||
///
|
||||
/// ...
|
||||
///
|
||||
/// C c1;
|
||||
/// A* pc1 = &c1;
|
||||
/// assert(boost::typeindex::type_id<C>() == boost::typeindex::type_id_runtime(*pc1));
|
||||
/// \endcode
|
||||
#define BOOST_TYPE_INDEX_REGISTER_CLASS nothing-or-some-virtual-functions
|
||||
|
||||
/// \def BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY
|
||||
/// BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY is a helper macro that must be defined if mixing
|
||||
/// RTTI on/off modules. See
|
||||
/// [Mixing sources with RTTI on and RTTI off](boost_typeindex/mixing_sources_with_rtti_on_and_.html)
|
||||
/// section of documentation for more info.
|
||||
#define BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY
|
||||
|
||||
#endif // defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
|
||||
|
||||
|
||||
/// Function to get boost::typeindex::type_index for a type T.
|
||||
/// Removes const, volatile && and & modifiers from T.
|
||||
///
|
||||
/// \b Example:
|
||||
/// \code
|
||||
/// type_index ti = type_id<int&>();
|
||||
/// std::cout << ti.pretty_name(); // Outputs 'int'
|
||||
/// \endcode
|
||||
///
|
||||
/// \tparam T Type for which type_index must be created.
|
||||
/// \throw Nothing.
|
||||
/// \return boost::typeindex::type_index with information about the specified type T.
|
||||
template <class T>
|
||||
inline type_index type_id() noexcept {
|
||||
return type_index::type_id<T>();
|
||||
}
|
||||
|
||||
/// Function for constructing boost::typeindex::type_index instance for type T.
|
||||
/// Does not remove const, volatile, & and && modifiers from T.
|
||||
///
|
||||
/// If T has no const, volatile, & and && modifiers, then returns exactly
|
||||
/// the same result as in case of calling `type_id<T>()`.
|
||||
///
|
||||
/// \b Example:
|
||||
/// \code
|
||||
/// type_index ti = type_id_with_cvr<int&>();
|
||||
/// std::cout << ti.pretty_name(); // Outputs 'int&'
|
||||
/// \endcode
|
||||
///
|
||||
/// \tparam T Type for which type_index must be created.
|
||||
/// \throw Nothing.
|
||||
/// \return boost::typeindex::type_index with information about the specified type T.
|
||||
template <class T>
|
||||
inline type_index type_id_with_cvr() noexcept {
|
||||
return type_index::type_id_with_cvr<T>();
|
||||
}
|
||||
|
||||
/// Function that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index.
|
||||
///
|
||||
/// Returns runtime information about specified type.
|
||||
///
|
||||
/// \b Requirements: RTTI available or Base and Derived classes must be marked with BOOST_TYPE_INDEX_REGISTER_CLASS.
|
||||
///
|
||||
/// \b Example:
|
||||
/// \code
|
||||
/// struct Base { virtual ~Base(){} };
|
||||
/// struct Derived: public Base {};
|
||||
/// ...
|
||||
/// Derived d;
|
||||
/// Base& b = d;
|
||||
/// type_index ti = type_id_runtime(b);
|
||||
/// std::cout << ti.pretty_name(); // Outputs 'Derived'
|
||||
/// \endcode
|
||||
///
|
||||
/// \param runtime_val Variable which runtime type must be returned.
|
||||
/// \throw Nothing.
|
||||
/// \return boost::typeindex::type_index with information about the specified variable.
|
||||
template <class T>
|
||||
inline type_index type_id_runtime(const T& runtime_val) noexcept {
|
||||
return type_index::type_id_runtime(runtime_val);
|
||||
}
|
||||
|
||||
}} // namespace boost::typeindex
|
||||
|
||||
|
||||
|
||||
#endif // BOOST_TYPE_INDEX_HPP
|
||||
|
||||
204
include/boost/type_index/ctti_type_index.hpp
Normal file
204
include/boost/type_index/ctti_type_index.hpp
Normal file
@@ -0,0 +1,204 @@
|
||||
//
|
||||
// Copyright 2013-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)
|
||||
//
|
||||
|
||||
#ifndef BOOST_TYPE_INDEX_CTTI_TYPE_INDEX_HPP
|
||||
#define BOOST_TYPE_INDEX_CTTI_TYPE_INDEX_HPP
|
||||
|
||||
/// \file ctti_type_index.hpp
|
||||
/// \brief Contains boost::typeindex::ctti_type_index class that is constexpr if C++14 constexpr is supported by compiler.
|
||||
///
|
||||
/// boost::typeindex::ctti_type_index class can be used as a drop-in replacement
|
||||
/// for std::type_index.
|
||||
///
|
||||
/// It is used in situations when typeid() method is not available or
|
||||
/// BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY macro is defined.
|
||||
|
||||
#include <boost/type_index/type_index_facade.hpp>
|
||||
#include <boost/type_index/detail/compile_time_type_info.hpp>
|
||||
|
||||
#include <cstring>
|
||||
#include <type_traits>
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
namespace boost { namespace typeindex {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// That's the most trickiest part of the TypeIndex library:
|
||||
// 1) we do not want to give user ability to manually construct and compare `struct-that-represents-type`
|
||||
// 2) we need to distinguish between `struct-that-represents-type` and `const char*`
|
||||
// 3) we need a thread-safe way to have references to instances `struct-that-represents-type`
|
||||
// 4) we need a compile-time control to make sure that user does not copy or
|
||||
// default construct `struct-that-represents-type`
|
||||
//
|
||||
// Solution would be the following:
|
||||
|
||||
/// \class ctti_data
|
||||
/// Standard-layout class with private constructors and assignment operators.
|
||||
///
|
||||
/// You can not work with this class directly. The purpose of this class is to hold type info
|
||||
/// \b when \b RTTI \b is \b off and allow ctti_type_index construction from itself.
|
||||
///
|
||||
/// \b Example:
|
||||
/// \code
|
||||
/// const detail::ctti_data& foo();
|
||||
/// ...
|
||||
/// type_index ti = type_index(foo());
|
||||
/// std::cout << ti.pretty_name();
|
||||
/// \endcode
|
||||
class ctti_data {
|
||||
public:
|
||||
ctti_data() = delete;
|
||||
ctti_data(const ctti_data&) = delete;
|
||||
ctti_data& operator=(const ctti_data&) = delete;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Helper method for getting detail::ctti_data of a template parameter T.
|
||||
template <class T>
|
||||
inline const detail::ctti_data& ctti_construct() noexcept {
|
||||
// Standard C++11, 5.2.10 Reinterpret cast:
|
||||
// An object pointer can be explicitly converted to an object pointer of a different type. When a prvalue
|
||||
// v of type "pointer to T1" is converted to the type "pointer to cv T2", the result is static_cast<cv
|
||||
// T2*>(static_cast<cv void*>(v)) if both T1 and T2 are standard-layout types (3.9) and the alignment
|
||||
// requirements of T2 are no stricter than those of T1, or if either type is void. Converting a prvalue of type
|
||||
// "pointer to T1" to the type "pointer to T2" (where T1 and T2 are object types and where the alignment
|
||||
// requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer
|
||||
// value.
|
||||
//
|
||||
// Alignments are checked in `type_index_test_ctti_alignment.cpp` test.
|
||||
return *reinterpret_cast<const detail::ctti_data*>(boost::detail::ctti<T>::n());
|
||||
}
|
||||
|
||||
/// \class ctti_type_index
|
||||
/// This class is a wrapper that pretends to work exactly like stl_type_index, but does
|
||||
/// not require RTTI support. \b For \b description \b of \b functions \b see type_index_facade.
|
||||
///
|
||||
/// This class on C++14 compatible compilers has following functions marked as constexpr:
|
||||
/// * default constructor
|
||||
/// * copy constructors and assignemnt operations
|
||||
/// * class methods: name(), before(const ctti_type_index& rhs), equal(const ctti_type_index& rhs)
|
||||
/// * static methods type_id<T>(), type_id_with_cvr<T>()
|
||||
/// * comparison operators
|
||||
///
|
||||
/// This class produces slightly longer type names, so consider using stl_type_index
|
||||
/// in situations when typeid() is working.
|
||||
class ctti_type_index: public type_index_facade<ctti_type_index, detail::ctti_data> {
|
||||
const char* data_;
|
||||
|
||||
inline std::size_t get_raw_name_length() const noexcept;
|
||||
|
||||
BOOST_CXX14_CONSTEXPR inline explicit ctti_type_index(const char* data) noexcept
|
||||
: data_(data)
|
||||
{}
|
||||
|
||||
public:
|
||||
typedef detail::ctti_data type_info_t;
|
||||
|
||||
BOOST_CXX14_CONSTEXPR inline ctti_type_index() noexcept
|
||||
: data_(boost::detail::ctti<void>::n())
|
||||
{}
|
||||
|
||||
inline ctti_type_index(const type_info_t& data) noexcept
|
||||
: data_(reinterpret_cast<const char*>(&data))
|
||||
{}
|
||||
|
||||
inline const type_info_t& type_info() const noexcept;
|
||||
BOOST_CXX14_CONSTEXPR inline const char* raw_name() const noexcept;
|
||||
BOOST_CXX14_CONSTEXPR inline const char* name() const noexcept;
|
||||
inline std::string pretty_name() const;
|
||||
inline std::size_t hash_code() const noexcept;
|
||||
|
||||
BOOST_CXX14_CONSTEXPR inline bool equal(const ctti_type_index& rhs) const noexcept;
|
||||
BOOST_CXX14_CONSTEXPR inline bool before(const ctti_type_index& rhs) const noexcept;
|
||||
|
||||
template <class T>
|
||||
BOOST_CXX14_CONSTEXPR inline static ctti_type_index type_id() noexcept;
|
||||
|
||||
template <class T>
|
||||
BOOST_CXX14_CONSTEXPR inline static ctti_type_index type_id_with_cvr() noexcept;
|
||||
|
||||
template <class T>
|
||||
inline static ctti_type_index type_id_runtime(const T& variable) noexcept;
|
||||
};
|
||||
|
||||
|
||||
inline const ctti_type_index::type_info_t& ctti_type_index::type_info() const noexcept {
|
||||
return *reinterpret_cast<const detail::ctti_data*>(data_);
|
||||
}
|
||||
|
||||
|
||||
BOOST_CXX14_CONSTEXPR inline bool ctti_type_index::equal(const ctti_type_index& rhs) const noexcept {
|
||||
const char* const left = raw_name();
|
||||
const char* const right = rhs.raw_name();
|
||||
return /*left == right ||*/ !boost::typeindex::detail::constexpr_strcmp(left, right);
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR inline bool ctti_type_index::before(const ctti_type_index& rhs) const noexcept {
|
||||
const char* const left = raw_name();
|
||||
const char* const right = rhs.raw_name();
|
||||
return /*left != right &&*/ boost::typeindex::detail::constexpr_strcmp(left, right) < 0;
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
BOOST_CXX14_CONSTEXPR inline ctti_type_index ctti_type_index::type_id() noexcept {
|
||||
typedef typename std::remove_reference<T>::type no_ref_t;
|
||||
typedef typename std::remove_cv<no_ref_t>::type no_cvr_t;
|
||||
return ctti_type_index(boost::detail::ctti<no_cvr_t>::n());
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class T>
|
||||
BOOST_CXX14_CONSTEXPR inline ctti_type_index ctti_type_index::type_id_with_cvr() noexcept {
|
||||
return ctti_type_index(boost::detail::ctti<T>::n());
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
inline ctti_type_index ctti_type_index::type_id_runtime(const T& variable) noexcept {
|
||||
return variable.boost_type_index_type_id_runtime_();
|
||||
}
|
||||
|
||||
|
||||
BOOST_CXX14_CONSTEXPR inline const char* ctti_type_index::raw_name() const noexcept {
|
||||
return data_;
|
||||
}
|
||||
|
||||
|
||||
BOOST_CXX14_CONSTEXPR inline const char* ctti_type_index::name() const noexcept {
|
||||
return data_;
|
||||
}
|
||||
|
||||
inline std::size_t ctti_type_index::get_raw_name_length() const noexcept {
|
||||
return std::strlen(raw_name() + detail::skip().size_at_end);
|
||||
}
|
||||
|
||||
|
||||
inline std::string ctti_type_index::pretty_name() const {
|
||||
std::size_t len = get_raw_name_length();
|
||||
while (raw_name()[len - 1] == ' ') --len; // MSVC sometimes adds whitespaces
|
||||
return std::string(raw_name(), len);
|
||||
}
|
||||
|
||||
|
||||
inline std::size_t ctti_type_index::hash_code() const noexcept {
|
||||
return boost::hash_range(raw_name(), raw_name() + get_raw_name_length());
|
||||
}
|
||||
|
||||
|
||||
}} // namespace boost::typeindex
|
||||
|
||||
#endif // BOOST_TYPE_INDEX_CTTI_TYPE_INDEX_HPP
|
||||
|
||||
349
include/boost/type_index/detail/compile_time_type_info.hpp
Normal file
349
include/boost/type_index/detail/compile_time_type_info.hpp
Normal file
@@ -0,0 +1,349 @@
|
||||
//
|
||||
// Copyright 2012-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)
|
||||
//
|
||||
|
||||
#ifndef BOOST_TYPE_INDEX_DETAIL_COMPILE_TIME_TYPE_INFO_HPP
|
||||
#define BOOST_TYPE_INDEX_DETAIL_COMPILE_TIME_TYPE_INFO_HPP
|
||||
|
||||
/// \file compile_time_type_info.hpp
|
||||
/// \brief Contains helper macros and implementation details of boost::typeindex::ctti_type_index.
|
||||
/// Not intended for inclusion from user's code.
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <cstring>
|
||||
#include <type_traits>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
/// @cond
|
||||
#if defined(__has_builtin)
|
||||
#if __has_builtin(__builtin_constant_p)
|
||||
#define BOOST_TYPE_INDEX_DETAIL_IS_CONSTANT(x) __builtin_constant_p(x)
|
||||
#endif
|
||||
#if __has_builtin(__builtin_strcmp)
|
||||
#define BOOST_TYPE_INDEX_DETAIL_BUILTIN_STRCMP(str1, str2) __builtin_strcmp(str1, str2)
|
||||
#endif
|
||||
#elif defined(__GNUC__)
|
||||
#define BOOST_TYPE_INDEX_DETAIL_IS_CONSTANT(x) __builtin_constant_p(x)
|
||||
#define BOOST_TYPE_INDEX_DETAIL_BUILTIN_STRCMP(str1, str2) __builtin_strcmp(str1, str2)
|
||||
#endif
|
||||
|
||||
/// @endcond
|
||||
|
||||
|
||||
namespace boost { namespace typeindex { namespace detail {
|
||||
struct ctti_skip {
|
||||
std::size_t size_at_begin;
|
||||
std::size_t size_at_end;
|
||||
const char* until_runtime;
|
||||
std::size_t until_runtime_length;
|
||||
};
|
||||
|
||||
template <std::size_t N>
|
||||
constexpr ctti_skip make_ctti_skip(std::size_t size_at_begin,
|
||||
std::size_t size_at_end,
|
||||
bool more_at_runtime,
|
||||
const char (&until_runtime)[N])
|
||||
{
|
||||
return ctti_skip{size_at_begin, size_at_end, until_runtime, more_at_runtime ? N - 1 : 0};
|
||||
}
|
||||
|
||||
template <std::size_t N>
|
||||
constexpr ctti_skip make_ctti_skip(std::size_t size_at_begin,
|
||||
std::size_t size_at_end,
|
||||
const char (&until_runtime)[N])
|
||||
{
|
||||
return ctti_skip{size_at_begin, size_at_end, until_runtime, N - 1};
|
||||
}
|
||||
|
||||
#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
|
||||
/* Nothing to document. All the macro docs are moved to <boost/type_index.hpp> */
|
||||
#elif defined(BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING)
|
||||
constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING; }
|
||||
#elif defined(_MSC_VER) && !defined(__clang__) && defined (BOOST_NO_CXX11_NOEXCEPT)
|
||||
// sizeof("const char *__cdecl boost::detail::ctti<") - 1, sizeof(">::n(void)") - 1
|
||||
constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(40, 10, ""); }
|
||||
#elif defined(_MSC_VER) && !defined(__clang__) && !defined (BOOST_NO_CXX11_NOEXCEPT)
|
||||
// sizeof("const char *__cdecl boost::detail::ctti<") - 1, sizeof(">::n(void) noexcept") - 1
|
||||
constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(40, 19, ""); }
|
||||
#elif defined(__clang__) && defined(__APPLE__)
|
||||
// Someone made __clang_major__ equal to LLVM version rather than compiler version
|
||||
// on APPLE platform.
|
||||
//
|
||||
// Using less efficient solution because there is no good way to detect real version of Clang.
|
||||
// sizeof("static const char *boost::detail::ctti<") - 1, sizeof("]") - 1, true, "???????????>::n() [T = int"
|
||||
constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(39, 1, "T = "); }
|
||||
#elif defined(__clang__) && (__clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ == 0))
|
||||
// sizeof("static const char *boost::detail::ctti<") - 1, sizeof(">::n()") - 1
|
||||
// note: checked on 3.0
|
||||
constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(39, 6, ""); }
|
||||
#elif defined(__clang__) && (__clang_major__ >= 4 || (__clang_major__ == 3 && __clang_minor__ > 0))
|
||||
// sizeof("static const char *boost::detail::ctti<") - 1, sizeof("]") - 1, true, "int>::n() [T = int"
|
||||
// note: checked on 3.1, 3.4
|
||||
constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(39, 1, "T = "); }
|
||||
#elif defined(__EDG__) && !defined(BOOST_NO_CXX14_CONSTEXPR)
|
||||
// sizeof("static cha boost::detail::ctti<T>::s() [with I = 40U, T = ") - 1, sizeof("]") - 1
|
||||
// note: checked on 4.14
|
||||
constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(58, 1, ""); }
|
||||
#elif defined(__EDG__) && defined(BOOST_NO_CXX14_CONSTEXPR)
|
||||
// sizeof("static const char *boost::detail::ctti<T>::n() [with T = ") - 1, sizeof("]") - 1
|
||||
// note: checked on 4.14
|
||||
constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(57, 1, ""); }
|
||||
#elif defined(__GNUC__) && (__GNUC__ < 7) && !defined(BOOST_NO_CXX14_CONSTEXPR)
|
||||
// sizeof("static constexpr char boost::detail::ctti<T>::s() [with unsigned int I = 0u; } T = ") - 1, sizeof("]") - 1
|
||||
constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(81, 1, ""); }
|
||||
#elif defined(__GNUC__) && (__GNUC__ >= 7) && !defined(BOOST_NO_CXX14_CONSTEXPR)
|
||||
// sizeof("static constexpr char boost::detail::ctti<T>::s() [with unsigned int I = 0; } T = ") - 1, sizeof("]") - 1
|
||||
constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(80, 1, ""); }
|
||||
#elif defined(__GNUC__) && defined(BOOST_NO_CXX14_CONSTEXPR)
|
||||
// sizeof("static const char* boost::detail::ctti<T>::n() [with T = ") - 1, sizeof("]") - 1
|
||||
constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(57, 1, ""); }
|
||||
#elif defined(__ghs__)
|
||||
// sizeof("static const char *boost::detail::ctti<T>::n() [with T = ") - 1, sizeof("]") - 1
|
||||
constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(57, 1, ""); }
|
||||
#else
|
||||
// Deafult code for other platforms... Just skip nothing!
|
||||
constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(0, 0, ""); }
|
||||
#endif
|
||||
|
||||
template <bool Condition>
|
||||
BOOST_CXX14_CONSTEXPR inline void assert_compile_time_legths() noexcept {
|
||||
static_assert(
|
||||
Condition,
|
||||
"TypeIndex library is misconfigured for your compiler. "
|
||||
"Please define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING to correct values. See section "
|
||||
"'RTTI emulation limitations' of the documentation for more information."
|
||||
);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
BOOST_CXX14_CONSTEXPR inline void failed_to_get_function_name() noexcept {
|
||||
static_assert(
|
||||
sizeof(T) && false,
|
||||
"TypeIndex library could not detect your compiler. "
|
||||
"Please make the BOOST_TYPE_INDEX_FUNCTION_SIGNATURE macro use "
|
||||
"correct compiler macro for getting the whole function name. "
|
||||
"Define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING to correct value after that."
|
||||
);
|
||||
}
|
||||
|
||||
#if defined(BOOST_TYPE_INDEX_DETAIL_IS_CONSTANT)
|
||||
BOOST_CXX14_CONSTEXPR BOOST_FORCEINLINE bool is_constant_string(const char* str) noexcept {
|
||||
while (BOOST_TYPE_INDEX_DETAIL_IS_CONSTANT(*str)) {
|
||||
if (*str == '\0')
|
||||
return true;
|
||||
++str;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif // defined(BOOST_TYPE_INDEX_DETAIL_IS_CONSTANT)
|
||||
|
||||
template<class ForwardIterator1, class ForwardIterator2>
|
||||
BOOST_CXX14_CONSTEXPR inline ForwardIterator1 constexpr_search(
|
||||
ForwardIterator1 first1,
|
||||
ForwardIterator1 last1,
|
||||
ForwardIterator2 first2,
|
||||
ForwardIterator2 last2) noexcept
|
||||
{
|
||||
if (first2 == last2) {
|
||||
return first1; // specified in C++11
|
||||
}
|
||||
|
||||
while (first1 != last1) {
|
||||
ForwardIterator1 it1 = first1;
|
||||
ForwardIterator2 it2 = first2;
|
||||
|
||||
while (*it1 == *it2) {
|
||||
++it1;
|
||||
++it2;
|
||||
if (it2 == last2) return first1;
|
||||
if (it1 == last1) return last1;
|
||||
}
|
||||
|
||||
++first1;
|
||||
}
|
||||
|
||||
return last1;
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR inline int constexpr_strcmp_loop(const char *v1, const char *v2) noexcept {
|
||||
while (*v1 != '\0' && *v1 == *v2) {
|
||||
++v1;
|
||||
++v2;
|
||||
}
|
||||
|
||||
return static_cast<int>(*v1) - *v2;
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR inline int constexpr_strcmp(const char *v1, const char *v2) noexcept {
|
||||
#if !defined(BOOST_NO_CXX14_CONSTEXPR) && defined(BOOST_TYPE_INDEX_DETAIL_IS_CONSTANT) && defined(BOOST_TYPE_INDEX_DETAIL_BUILTIN_STRCMP)
|
||||
if (boost::typeindex::detail::is_constant_string(v1) && boost::typeindex::detail::is_constant_string(v2))
|
||||
return boost::typeindex::detail::constexpr_strcmp_loop(v1, v2);
|
||||
return BOOST_TYPE_INDEX_DETAIL_BUILTIN_STRCMP(v1, v2);
|
||||
#elif !defined(BOOST_NO_CXX14_CONSTEXPR)
|
||||
return boost::typeindex::detail::constexpr_strcmp_loop(v1, v2);
|
||||
#else
|
||||
return std::strcmp(v1, v2);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <unsigned int ArrayLength>
|
||||
BOOST_CXX14_CONSTEXPR inline const char* skip_begining_runtime(const char* begin) noexcept {
|
||||
const char* const it = detail::constexpr_search(
|
||||
begin, begin + ArrayLength,
|
||||
skip().until_runtime, skip().until_runtime + skip().until_runtime_length
|
||||
);
|
||||
return (it == begin + ArrayLength ? begin : it + skip().until_runtime_length);
|
||||
}
|
||||
|
||||
template <unsigned int ArrayLength>
|
||||
BOOST_CXX14_CONSTEXPR inline const char* skip_begining(const char* begin) noexcept {
|
||||
detail::assert_compile_time_legths<(ArrayLength > skip().size_at_begin + skip().size_at_end)>();
|
||||
return skip().until_runtime_length
|
||||
? detail::skip_begining_runtime<ArrayLength - skip().size_at_begin>(begin + skip().size_at_begin)
|
||||
: begin + skip().size_at_begin
|
||||
;
|
||||
}
|
||||
|
||||
#if !defined(__clang__) && defined(__GNUC__) && !defined(BOOST_NO_CXX14_CONSTEXPR)
|
||||
template <unsigned int... I>
|
||||
struct index_seq {};
|
||||
|
||||
template <typename Left, typename Right>
|
||||
struct make_index_sequence_join;
|
||||
|
||||
template <unsigned int... Left, unsigned int... Right>
|
||||
struct make_index_sequence_join<index_seq<Left...>, index_seq<Right...> > {
|
||||
typedef index_seq<Left..., Right...> type;
|
||||
};
|
||||
|
||||
template <unsigned int C, unsigned int D>
|
||||
struct make_index_seq_impl {
|
||||
typedef typename make_index_sequence_join<
|
||||
typename make_index_seq_impl<C, D / 2>::type,
|
||||
typename make_index_seq_impl<C + D / 2, (D + 1) / 2>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <unsigned int C>
|
||||
struct make_index_seq_impl<C, 0> {
|
||||
typedef index_seq<> type;
|
||||
};
|
||||
|
||||
template <unsigned int C>
|
||||
struct make_index_seq_impl<C, 1> {
|
||||
typedef index_seq<C> type;
|
||||
};
|
||||
|
||||
template <char... C>
|
||||
struct cstring {
|
||||
static constexpr unsigned int size_ = sizeof...(C);
|
||||
static constexpr char data_[size_] = { C... };
|
||||
};
|
||||
|
||||
template <char... C>
|
||||
constexpr char cstring<C...>::data_[];
|
||||
#endif
|
||||
|
||||
}}} // namespace boost::typeindex::detail
|
||||
|
||||
namespace boost { namespace detail {
|
||||
|
||||
/// Noncopyable type_info that does not require RTTI.
|
||||
/// CTTI == Compile Time Type Info.
|
||||
/// This name must be as short as possible, to avoid code bloat
|
||||
template <class T>
|
||||
struct ctti {
|
||||
|
||||
#if !defined(__clang__) && defined(__GNUC__) && !defined(BOOST_NO_CXX14_CONSTEXPR)
|
||||
//helper functions
|
||||
template <unsigned int I>
|
||||
constexpr static char s() noexcept { // step
|
||||
constexpr unsigned int offset =
|
||||
(I >= 10u ? 1u : 0u)
|
||||
+ (I >= 100u ? 1u : 0u)
|
||||
+ (I >= 1000u ? 1u : 0u)
|
||||
+ (I >= 10000u ? 1u : 0u)
|
||||
+ (I >= 100000u ? 1u : 0u)
|
||||
+ (I >= 1000000u ? 1u : 0u)
|
||||
;
|
||||
|
||||
#if defined(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE)
|
||||
return BOOST_TYPE_INDEX_FUNCTION_SIGNATURE[I + offset];
|
||||
#elif defined(__FUNCSIG__)
|
||||
return __FUNCSIG__[I + offset];
|
||||
#else
|
||||
return __PRETTY_FUNCTION__[I + offset];
|
||||
#endif
|
||||
}
|
||||
|
||||
template <unsigned int ...Indexes>
|
||||
constexpr static const char* impl(::boost::typeindex::detail::index_seq<Indexes...> ) noexcept {
|
||||
return ::boost::typeindex::detail::cstring<s<Indexes>()...>::data_;
|
||||
}
|
||||
|
||||
template <unsigned int D = 0> // `D` means `Dummy`
|
||||
constexpr static const char* n() noexcept {
|
||||
#if defined(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE)
|
||||
constexpr unsigned int size = sizeof(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE);
|
||||
#elif defined(__FUNCSIG__)
|
||||
constexpr unsigned int size = sizeof(__FUNCSIG__);
|
||||
#elif defined(__PRETTY_FUNCTION__) \
|
||||
|| defined(__GNUC__) \
|
||||
|| (defined(__SUNPRO_CC) && (__SUNPRO_CC >= 0x5130)) \
|
||||
|| (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) \
|
||||
|| (defined(__ICC) && (__ICC >= 600)) \
|
||||
|| defined(__ghs__) \
|
||||
|| defined(__DMC__)
|
||||
constexpr unsigned int size = sizeof(__PRETTY_FUNCTION__);
|
||||
#else
|
||||
boost::typeindex::detail::failed_to_get_function_name<T>();
|
||||
#endif
|
||||
|
||||
boost::typeindex::detail::assert_compile_time_legths<
|
||||
(size > boost::typeindex::detail::skip().size_at_begin + boost::typeindex::detail::skip().size_at_end + sizeof("const *") - 1)
|
||||
>();
|
||||
static_assert(!boost::typeindex::detail::skip().until_runtime_length, "Skipping for GCC in C++14 mode is unsupported");
|
||||
|
||||
typedef typename boost::typeindex::detail::make_index_seq_impl<
|
||||
boost::typeindex::detail::skip().size_at_begin,
|
||||
size - sizeof("const *") + 1 - boost::typeindex::detail::skip().size_at_begin
|
||||
>::type idx_seq;
|
||||
return impl(idx_seq());
|
||||
}
|
||||
#else
|
||||
/// Returns raw name. Must be as short, as possible, to avoid code bloat
|
||||
BOOST_CXX14_CONSTEXPR static const char* n() noexcept {
|
||||
#if defined(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE)
|
||||
return boost::typeindex::detail::skip_begining< sizeof(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE) >(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE);
|
||||
#elif defined(__FUNCSIG__)
|
||||
return boost::typeindex::detail::skip_begining< sizeof(__FUNCSIG__) >(__FUNCSIG__);
|
||||
#elif defined(__PRETTY_FUNCTION__) \
|
||||
|| defined(__GNUC__) \
|
||||
|| (defined(__SUNPRO_CC) && (__SUNPRO_CC >= 0x5130)) \
|
||||
|| (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) \
|
||||
|| (defined(__ICC) && (__ICC >= 600)) \
|
||||
|| defined(__ghs__) \
|
||||
|| defined(__DMC__) \
|
||||
|| defined(__clang__)
|
||||
return boost::typeindex::detail::skip_begining< sizeof(__PRETTY_FUNCTION__) >(__PRETTY_FUNCTION__);
|
||||
#else
|
||||
boost::typeindex::detail::failed_to_get_function_name<T>();
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
}} // namespace boost::detail
|
||||
|
||||
|
||||
|
||||
#endif // BOOST_TYPE_INDEX_DETAIL_COMPILE_TIME_TYPE_INFO_HPP
|
||||
40
include/boost/type_index/detail/ctti_register_class.hpp
Normal file
40
include/boost/type_index/detail/ctti_register_class.hpp
Normal file
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// Copyright 2013-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)
|
||||
//
|
||||
|
||||
#ifndef BOOST_TYPE_INDEX_CTTI_REGISTER_CLASS_HPP
|
||||
#define BOOST_TYPE_INDEX_CTTI_REGISTER_CLASS_HPP
|
||||
|
||||
/// \file ctti_register_class.hpp
|
||||
/// \brief Contains BOOST_TYPE_INDEX_REGISTER_CLASS macro implementation that uses boost::typeindex::ctti_type_index.
|
||||
/// Not intended for inclusion from user's code.
|
||||
|
||||
#include <boost/type_index/ctti_type_index.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
namespace boost { namespace typeindex { namespace detail {
|
||||
|
||||
template <class T>
|
||||
inline const ctti_data& ctti_construct_typeid_ref(const T*) noexcept {
|
||||
return boost::typeindex::ctti_construct<T>();
|
||||
}
|
||||
|
||||
}}} // namespace boost::typeindex::detail
|
||||
|
||||
/// @cond
|
||||
#define BOOST_TYPE_INDEX_REGISTER_CLASS \
|
||||
virtual const boost::typeindex::detail::ctti_data& boost_type_index_type_id_runtime_() const noexcept { \
|
||||
return boost::typeindex::detail::ctti_construct_typeid_ref(this); \
|
||||
} \
|
||||
/**/
|
||||
/// @endcond
|
||||
|
||||
#endif // BOOST_TYPE_INDEX_CTTI_REGISTER_CLASS_HPP
|
||||
|
||||
40
include/boost/type_index/detail/stl_register_class.hpp
Normal file
40
include/boost/type_index/detail/stl_register_class.hpp
Normal file
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// Copyright 2013-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)
|
||||
//
|
||||
|
||||
#ifndef BOOST_TYPE_INDEX_STL_REGISTER_CLASS_HPP
|
||||
#define BOOST_TYPE_INDEX_STL_REGISTER_CLASS_HPP
|
||||
|
||||
/// \file stl_register_class.hpp
|
||||
/// \brief Contains BOOST_TYPE_INDEX_REGISTER_CLASS macro implementation that uses boost::typeindex::stl_type_index.
|
||||
/// Not intended for inclusion from user's code.
|
||||
|
||||
#include <boost/type_index/stl_type_index.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
namespace boost { namespace typeindex { namespace detail {
|
||||
|
||||
template <class T>
|
||||
inline const stl_type_index::type_info_t& stl_construct_typeid_ref(const T*) noexcept {
|
||||
return typeid(T);
|
||||
}
|
||||
|
||||
}}} // namespace boost::typeindex::detail
|
||||
|
||||
/// @cond
|
||||
#define BOOST_TYPE_INDEX_REGISTER_CLASS \
|
||||
virtual const boost::typeindex::stl_type_index::type_info_t& boost_type_index_type_id_runtime_() const noexcept { \
|
||||
return boost::typeindex::detail::stl_construct_typeid_ref(this); \
|
||||
} \
|
||||
/**/
|
||||
/// @endcond
|
||||
|
||||
#endif // BOOST_TYPE_INDEX_STL_REGISTER_CLASS_HPP
|
||||
|
||||
28
include/boost/type_index/runtime_cast.hpp
Normal file
28
include/boost/type_index/runtime_cast.hpp
Normal file
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// Copyright (c) Chris Glover, 2016.
|
||||
//
|
||||
//
|
||||
// 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_TYPE_INDEX_RUNTIME_CAST_HPP
|
||||
#define BOOST_TYPE_INDEX_RUNTIME_CAST_HPP
|
||||
|
||||
/// \file runtime_cast.hpp
|
||||
/// \brief Contains the basic utilities necessary to fully emulate
|
||||
/// dynamic_cast for language level constructs (raw pointers and references).
|
||||
///
|
||||
/// boost::typeindex::runtime_cast is a drop in replacement for dynamic_cast
|
||||
/// that can be used in situations where traditional rtti is either unavailable
|
||||
/// or undesirable.
|
||||
|
||||
#include <boost/type_index/runtime_cast/register_runtime_class.hpp>
|
||||
#include <boost/type_index/runtime_cast/pointer_cast.hpp>
|
||||
#include <boost/type_index/runtime_cast/reference_cast.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#endif // BOOST_TYPE_INDEX_RUNTIME_CAST_HPP
|
||||
@@ -0,0 +1,50 @@
|
||||
//
|
||||
// Copyright (c) Chris Glover, 2016.
|
||||
//
|
||||
//
|
||||
// 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_TYPE_INDEX_RUNTIME_CAST_BOOST_SHARED_PTR_CAST_HPP
|
||||
#define BOOST_TYPE_INDEX_RUNTIME_CAST_BOOST_SHARED_PTR_CAST_HPP
|
||||
|
||||
/// \file boost_shared_ptr_cast.hpp
|
||||
/// \brief Contains the overload of boost::typeindex::runtime_pointer_cast for
|
||||
/// boost::shared_ptr types.
|
||||
|
||||
#include <boost/type_index/runtime_cast/detail/runtime_cast_impl.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
template<class T> class shared_ptr;
|
||||
}
|
||||
|
||||
namespace boost { namespace typeindex {
|
||||
|
||||
/// \brief Creates a new instance of std::shared_ptr whose stored pointer is obtained from u's
|
||||
/// stored pointer using a runtime_cast.
|
||||
///
|
||||
/// The new shared_ptr will share ownership with u, except that it is empty if the runtime_cast
|
||||
/// performed by runtime_pointer_cast returns a null pointer.
|
||||
/// \tparam T The desired target type to return a pointer of.
|
||||
/// \tparam U A complete class type of the source instance pointed to from u.
|
||||
/// \return If there exists a valid conversion from U* to T*, returns a boost::shared_ptr<T>
|
||||
/// that points to an address suitably offset from u.
|
||||
/// If no such conversion exists, returns boost::shared_ptr<T>();
|
||||
template<typename T, typename U>
|
||||
boost::shared_ptr<T> runtime_pointer_cast(boost::shared_ptr<U> const& u) {
|
||||
T* value = detail::runtime_cast_impl<T>(u.get(), std::is_base_of<T, U>());
|
||||
if(value)
|
||||
return boost::shared_ptr<T>(u, value);
|
||||
return boost::shared_ptr<T>();
|
||||
}
|
||||
|
||||
}} // namespace boost::typeindex
|
||||
|
||||
#endif // BOOST_TYPE_INDEX_RUNTIME_CAST_BOOST_SHARED_PTR_CAST_HPP
|
||||
@@ -0,0 +1,58 @@
|
||||
//
|
||||
// Copyright (c) Chris Glover, 2016.
|
||||
//
|
||||
//
|
||||
// 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_TYPE_INDEX_RUNTIME_CAST_DETAIL_RUNTIME_CAST_IMPL_HPP
|
||||
#define BOOST_TYPE_INDEX_RUNTIME_CAST_DETAIL_RUNTIME_CAST_IMPL_HPP
|
||||
|
||||
/// \file runtime_cast_impl.hpp
|
||||
/// \brief Contains the overload of boost::typeindex::runtime_cast for
|
||||
/// pointer types.
|
||||
///
|
||||
/// boost::typeindex::runtime_cast can be used to emulate dynamic_cast
|
||||
/// functionality on platorms that don't provide it or should the user
|
||||
/// desire opt in functionality instead of enabling it system wide.
|
||||
|
||||
#include <boost/type_index.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
namespace boost { namespace typeindex {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename T, typename U>
|
||||
T* runtime_cast_impl(U* u, std::integral_constant<bool, true>) noexcept {
|
||||
return u;
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
T const* runtime_cast_impl(U const* u, std::integral_constant<bool, true>) noexcept {
|
||||
return u;
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
T* runtime_cast_impl(U* u, std::integral_constant<bool, false>) noexcept {
|
||||
return const_cast<T*>(static_cast<T const*>(
|
||||
u->boost_type_index_find_instance_(boost::typeindex::type_id<T>())
|
||||
));
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
T const* runtime_cast_impl(U const* u, std::integral_constant<bool, false>) noexcept {
|
||||
return static_cast<T const*>(u->boost_type_index_find_instance_(boost::typeindex::type_id<T>()));
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
}} // namespace boost::typeindex
|
||||
|
||||
#endif // BOOST_TYPE_INDEX_RUNTIME_CAST_DETAIL_RUNTIME_CAST_IMPL_HPP
|
||||
73
include/boost/type_index/runtime_cast/pointer_cast.hpp
Normal file
73
include/boost/type_index/runtime_cast/pointer_cast.hpp
Normal file
@@ -0,0 +1,73 @@
|
||||
//
|
||||
// Copyright (c) Chris Glover, 2016.
|
||||
//
|
||||
//
|
||||
// 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_TYPE_INDEX_RUNTIME_CAST_POINTER_CAST_HPP
|
||||
#define BOOST_TYPE_INDEX_RUNTIME_CAST_POINTER_CAST_HPP
|
||||
|
||||
/// \file pointer_class.hpp
|
||||
/// \brief Contains the function overloads of boost::typeindex::runtime_cast for
|
||||
/// pointer types.
|
||||
#include <boost/type_index.hpp>
|
||||
#include <boost/type_index/runtime_cast/detail/runtime_cast_impl.hpp>
|
||||
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
namespace boost { namespace typeindex {
|
||||
|
||||
/// \brief Safely converts pointers to classes up, down, and sideways along the inheritance hierarchy.
|
||||
/// \tparam T The desired target type. Like dynamic_cast, must be a pointer to complete class type.
|
||||
/// \tparam U A complete class type of the source instance, u.
|
||||
/// \return If there exists a valid conversion from U* to T, returns a T that points to
|
||||
/// an address suitably offset from u. If no such conversion exists, returns nullptr.
|
||||
template<typename T, typename U>
|
||||
T runtime_cast(U* u) noexcept {
|
||||
typedef typename std::remove_pointer<T>::type impl_type;
|
||||
return detail::runtime_cast_impl<impl_type>(u, std::is_base_of<T, U>());
|
||||
}
|
||||
|
||||
/// \brief Safely converts pointers to classes up, down, and sideways along the inheritance hierarchy.
|
||||
/// \tparam T The desired target type. Like dynamic_cast, must be a pointer to complete class type.
|
||||
/// \tparam U A complete class type of the source instance, u.
|
||||
/// \return If there exists a valid conversion from U* to T, returns a T that points to
|
||||
/// an address suitably offset from u. If no such conversion exists, returns nullptr.
|
||||
template<typename T, typename U>
|
||||
T runtime_cast(U const* u) noexcept {
|
||||
typedef typename std::remove_pointer<T>::type impl_type;
|
||||
return detail::runtime_cast_impl<impl_type>(u, std::is_base_of<T, U>());
|
||||
}
|
||||
|
||||
/// \brief Safely converts pointers to classes up, down, and sideways along the inheritance
|
||||
/// hierarchy.
|
||||
/// \tparam T The desired target type to return a pointer to.
|
||||
/// \tparam U A complete class type of the source instance, u.
|
||||
/// \return If there exists a valid conversion from U const* to T*, returns a T*
|
||||
/// that points to an address suitably offset from u.
|
||||
/// If no such conversion exists, returns nullptr.
|
||||
template<typename T, typename U>
|
||||
T* runtime_pointer_cast(U* u) noexcept {
|
||||
return detail::runtime_cast_impl<T>(u, std::is_base_of<T, U>());
|
||||
}
|
||||
|
||||
/// \brief Safely converts pointers to classes up, down, and sideways along the inheritance
|
||||
/// hierarchy.
|
||||
/// \tparam T The desired target type to return a pointer to.
|
||||
/// \tparam U A complete class type of the source instance, u.
|
||||
/// \return If there exists a valid conversion from U const* to T const*, returns a T const*
|
||||
/// that points to an address suitably offset from u.
|
||||
/// If no such conversion exists, returns nullptr.
|
||||
template<typename T, typename U>
|
||||
T const* runtime_pointer_cast(U const* u) noexcept {
|
||||
return detail::runtime_cast_impl<T>(u, std::is_base_of<T, U>());
|
||||
}
|
||||
|
||||
}} // namespace boost::typeindex
|
||||
|
||||
#endif // BOOST_TYPE_INDEX_RUNTIME_CAST_POINTER_CAST_HPP
|
||||
65
include/boost/type_index/runtime_cast/reference_cast.hpp
Normal file
65
include/boost/type_index/runtime_cast/reference_cast.hpp
Normal file
@@ -0,0 +1,65 @@
|
||||
//
|
||||
// Copyright (c) Chris Glover, 2016.
|
||||
//
|
||||
//
|
||||
// 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_TYPE_INDEX_RUNTIME_CAST_REFERENCE_CAST_HPP
|
||||
#define BOOST_TYPE_INDEX_RUNTIME_CAST_REFERENCE_CAST_HPP
|
||||
|
||||
/// \file reference_cast.hpp
|
||||
/// \brief Contains the overload of boost::typeindex::runtime_cast for
|
||||
/// reference types.
|
||||
|
||||
#include <boost/type_index/runtime_cast/detail/runtime_cast_impl.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
namespace boost { namespace typeindex {
|
||||
|
||||
/// \brief Indicates that runtime_cast was unable to perform the desired cast operation
|
||||
/// because the source instance was not also an instance of the target type.
|
||||
struct BOOST_SYMBOL_VISIBLE bad_runtime_cast : std::exception
|
||||
{};
|
||||
|
||||
/// \brief Safely converts references to classes up, down, and sideways along the inheritance hierarchy.
|
||||
/// \tparam T The desired target type. Like dynamic_cast, must be a pointer to complete class type.
|
||||
/// \tparam U A complete class type of the source instance, u.
|
||||
/// \return If there exists a valid conversion from U& to T, returns a T that references an address
|
||||
/// suitably offset from u. If no such conversion exists, throws boost::typeindex::bad_runtime_cast.
|
||||
template<typename T, typename U>
|
||||
typename std::add_lvalue_reference<T>::type runtime_cast(U& u) {
|
||||
typedef typename std::remove_reference<T>::type impl_type;
|
||||
impl_type* value = detail::runtime_cast_impl<impl_type>(
|
||||
std::addressof(u), std::is_base_of<T, U>());
|
||||
if(!value)
|
||||
BOOST_THROW_EXCEPTION(bad_runtime_cast());
|
||||
return *value;
|
||||
}
|
||||
|
||||
/// \brief Safely converts references to classes up, down, and sideways along the inheritance hierarchy.
|
||||
/// \tparam T The desired target type. Like dynamic_cast, must be a pointer to complete class type.
|
||||
/// \tparam U A complete class type of the source instance, u.
|
||||
/// \return If there exists a valid conversion from U const& to T const, returns a T const that references an address
|
||||
/// suitably offset from u. If no such conversion exists, throws boost::typeindex::bad_runtime_cast.
|
||||
template<typename T, typename U>
|
||||
typename std::add_lvalue_reference<const T>::type runtime_cast(U const& u) {
|
||||
typedef typename std::remove_reference<T>::type impl_type;
|
||||
impl_type* value = detail::runtime_cast_impl<impl_type>(
|
||||
std::addressof(u), std::is_base_of<T, U>());
|
||||
if(!value)
|
||||
BOOST_THROW_EXCEPTION(bad_runtime_cast());
|
||||
return *value;
|
||||
}
|
||||
|
||||
}} // namespace boost::typeindex
|
||||
|
||||
#endif // BOOST_TYPE_INDEX_RUNTIME_CAST_REFERENCE_CAST_HPP
|
||||
141
include/boost/type_index/runtime_cast/register_runtime_class.hpp
Normal file
141
include/boost/type_index/runtime_cast/register_runtime_class.hpp
Normal file
@@ -0,0 +1,141 @@
|
||||
//
|
||||
// Copyright (c) Chris Glover, 2016.
|
||||
//
|
||||
//
|
||||
// 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_TYPE_INDEX_RUNTIME_CAST_REGISTER_RUNTIME_CLASS_HPP
|
||||
#define BOOST_TYPE_INDEX_RUNTIME_CAST_REGISTER_RUNTIME_CLASS_HPP
|
||||
|
||||
/// \file register_runtime_class.hpp
|
||||
/// \brief Contains the macros BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST and
|
||||
/// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS
|
||||
#include <boost/type_index.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
namespace boost { namespace typeindex { namespace detail {
|
||||
|
||||
template<typename T>
|
||||
inline type_index runtime_class_construct_type_id(T const*) {
|
||||
return boost::typeindex::type_id<T>();
|
||||
}
|
||||
|
||||
template <class Self>
|
||||
constexpr const void* find_instance(boost::typeindex::type_index const&, const Self*) noexcept {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <class Base, class... OtherBases, class Self>
|
||||
const void* find_instance(boost::typeindex::type_index const& idx, const Self* self) noexcept {
|
||||
if (const void* ptr = self->Base::boost_type_index_find_instance_(idx)) {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
return boost::typeindex::detail::find_instance<OtherBases...>(idx, self);
|
||||
}
|
||||
|
||||
}}} // namespace boost::typeindex::detail
|
||||
|
||||
|
||||
/// \def BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS
|
||||
/// \brief Macro used to make a class compatible with boost::typeindex::runtime_cast
|
||||
///
|
||||
/// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS generates a virtual function
|
||||
/// in the current class that, when combined with the supplied base class information, allows
|
||||
/// boost::typeindex::runtime_cast to accurately convert between dynamic types of instances of
|
||||
/// the current class.
|
||||
///
|
||||
/// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS also adds support for boost::typeindex::type_id_runtime
|
||||
/// by including BOOST_TYPE_INDEX_REGISTER_CLASS. It is typical that these features are used together,
|
||||
/// but in the event that BOOST_TYPE_INDEX_REGISTER_CLASS is undesirable in the current class,
|
||||
/// BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST is provided.
|
||||
///
|
||||
/// \b Example:
|
||||
/// \code
|
||||
/// struct base1 {
|
||||
/// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS()
|
||||
/// virtual ~base1();
|
||||
/// };
|
||||
///
|
||||
/// struct base2 {
|
||||
/// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS()
|
||||
/// virtual ~base2();
|
||||
/// };
|
||||
///
|
||||
/// struct derived1 : base1 {
|
||||
/// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(base1)
|
||||
/// };
|
||||
///
|
||||
/// struct derived2 : base1, base2 {
|
||||
/// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(base1, base2)
|
||||
/// };
|
||||
///
|
||||
/// ...
|
||||
///
|
||||
/// base1* pb1 = get_object();
|
||||
/// if(derived2* pb2 = boost::typeindex::runtime_cast<derived2*>(pb1)) {
|
||||
/// assert(boost::typeindex::type_id_runtime(*pb1)) == boost::typeindex::type_id<derived2>());
|
||||
/// }
|
||||
/// \endcode
|
||||
///
|
||||
/// \param base_class_seq A Boost.Preprocessor sequence of the current class' direct bases, or
|
||||
/// BOOST_TYPE_INDEX_NO_BASE_CLASS if this class has no direct base classes.
|
||||
#define BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(...) \
|
||||
BOOST_TYPE_INDEX_REGISTER_CLASS \
|
||||
BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(__VA_ARGS__)
|
||||
|
||||
/// \def BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST
|
||||
/// \brief Macro used to make a class compatible with boost::typeindex::runtime_cast without including
|
||||
/// support for boost::typeindex::type_id_runtime.
|
||||
///
|
||||
/// BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST is provided as an alternative to BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS
|
||||
/// in the event that support for boost::typeindex::type_id_runtime is undesirable.
|
||||
///
|
||||
/// \b Example:
|
||||
/// \code
|
||||
/// struct base1 {
|
||||
/// BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST()
|
||||
/// virtual ~base1();
|
||||
/// };
|
||||
///
|
||||
/// struct base2 {
|
||||
/// BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST()
|
||||
/// virtual ~base2();
|
||||
/// };
|
||||
///
|
||||
/// struct derived1 : base1 {
|
||||
/// BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(base1)
|
||||
/// };
|
||||
///
|
||||
/// struct derived2 : base1, base2 {
|
||||
/// BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(base1, base2)
|
||||
/// };
|
||||
///
|
||||
/// ...
|
||||
///
|
||||
/// base1* pb1 = get_object();
|
||||
/// if(derived2* pb2 = boost::typeindex::runtime_cast<derived2*>(pb1))
|
||||
/// { /* can't call boost::typeindex::type_id_runtime(*pb1) here */ }
|
||||
/// \endcode
|
||||
///
|
||||
/// \param base_class_seq A Boost.Preprocessor sequence of the current class' direct bases, or
|
||||
/// BOOST_TYPE_INDEX_NO_BASE_CLASS if this class has no direct base classes.
|
||||
#define BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(...) \
|
||||
virtual void const* boost_type_index_find_instance_(boost::typeindex::type_index const& idx) const noexcept { \
|
||||
if(idx == boost::typeindex::detail::runtime_class_construct_type_id(this)) \
|
||||
return this; \
|
||||
return boost::typeindex::detail::find_instance<__VA_ARGS__>(idx, this); \
|
||||
}
|
||||
|
||||
/// \def BOOST_TYPE_INDEX_NO_BASE_CLASS
|
||||
/// \brief Instructs BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS and BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST
|
||||
/// that this class has no base classes.
|
||||
/// \deprecated Just remove and use BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS() or BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST()
|
||||
#define BOOST_TYPE_INDEX_NO_BASE_CLASS /**/
|
||||
|
||||
#endif // BOOST_TYPE_INDEX_RUNTIME_CAST_REGISTER_RUNTIME_CLASS_HPP
|
||||
@@ -0,0 +1,45 @@
|
||||
//
|
||||
// Copyright (c) Chris Glover, 2016.
|
||||
//
|
||||
//
|
||||
// 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_TYPE_INDEX_RUNTIME_CAST_STD_SHARED_PTR_CAST_HPP
|
||||
#define BOOST_TYPE_INDEX_RUNTIME_CAST_STD_SHARED_PTR_CAST_HPP
|
||||
|
||||
/// \file std_shared_ptr_cast.hpp
|
||||
/// \brief Contains the overload of boost::typeindex::runtime_pointer_cast for
|
||||
/// std::shared_ptr types.
|
||||
|
||||
#include <boost/type_index/runtime_cast/detail/runtime_cast_impl.hpp>
|
||||
#include <memory>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
namespace boost { namespace typeindex {
|
||||
|
||||
/// \brief Creates a new instance of std::shared_ptr whose stored pointer is obtained from u's
|
||||
/// stored pointer using a runtime_cast.
|
||||
///
|
||||
/// The new shared_ptr will share ownership with u, except that it is empty if the runtime_cast
|
||||
/// performed by runtime_pointer_cast returns a null pointer.
|
||||
/// \tparam T The desired target type to return a pointer of.
|
||||
/// \tparam U A complete class type of the source instance pointed to from u.
|
||||
/// \return If there exists a valid conversion from U* to T*, returns a std::shared_ptr<T>
|
||||
/// that points to an address suitably offset from u.
|
||||
/// If no such conversion exists, returns std::shared_ptr<T>();
|
||||
template<typename T, typename U>
|
||||
std::shared_ptr<T> runtime_pointer_cast(std::shared_ptr<U> const& u) {
|
||||
T* value = detail::runtime_cast_impl<T>(u.get(), std::is_base_of<T, U>());
|
||||
if(value)
|
||||
return std::shared_ptr<T>(u, value);
|
||||
return std::shared_ptr<T>();
|
||||
}
|
||||
|
||||
}} // namespace boost::typeindex
|
||||
|
||||
#endif // BOOST_TYPE_INDEX_RUNTIME_CAST_STD_SHARED_PTR_CAST_HPP
|
||||
234
include/boost/type_index/stl_type_index.hpp
Normal file
234
include/boost/type_index/stl_type_index.hpp
Normal file
@@ -0,0 +1,234 @@
|
||||
//
|
||||
// Copyright 2013-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)
|
||||
//
|
||||
|
||||
#ifndef BOOST_TYPE_INDEX_STL_TYPE_INDEX_HPP
|
||||
#define BOOST_TYPE_INDEX_STL_TYPE_INDEX_HPP
|
||||
|
||||
/// \file stl_type_index.hpp
|
||||
/// \brief Contains boost::typeindex::stl_type_index class.
|
||||
///
|
||||
/// boost::typeindex::stl_type_index class can be used as a drop-in replacement
|
||||
/// for std::type_index.
|
||||
///
|
||||
/// It is used in situations when RTTI is enabled or typeid() method is available.
|
||||
/// When typeid() is disabled or BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY macro
|
||||
/// is defined boost::typeindex::ctti is usually used instead of boost::typeindex::stl_type_index.
|
||||
|
||||
#include <boost/type_index/type_index_facade.hpp>
|
||||
|
||||
// MSVC is capable of calling typeid(T) even when RTTI is off
|
||||
#if defined(BOOST_NO_RTTI) && !defined(BOOST_MSVC)
|
||||
#error "File boost/type_index/stl_type_index.ipp is not usable when typeid() is not available."
|
||||
#endif
|
||||
|
||||
#include <typeinfo>
|
||||
#include <cstring> // std::strcmp, std::strlen, std::strstr
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/core/demangle.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
namespace boost { namespace typeindex {
|
||||
|
||||
/// \class stl_type_index
|
||||
/// This class is a wrapper around std::type_info, that workarounds issues and provides
|
||||
/// much more rich interface. \b For \b description \b of \b functions \b see type_index_facade.
|
||||
///
|
||||
/// This class requires typeid() to work. For cases when RTTI is disabled see ctti_type_index.
|
||||
class stl_type_index
|
||||
: public type_index_facade<
|
||||
stl_type_index,
|
||||
#ifdef BOOST_NO_STD_TYPEINFO
|
||||
type_info
|
||||
#else
|
||||
std::type_info
|
||||
#endif
|
||||
>
|
||||
{
|
||||
public:
|
||||
#ifdef BOOST_NO_STD_TYPEINFO
|
||||
typedef type_info type_info_t;
|
||||
#else
|
||||
typedef std::type_info type_info_t;
|
||||
#endif
|
||||
|
||||
private:
|
||||
const type_info_t* data_;
|
||||
|
||||
public:
|
||||
inline stl_type_index() noexcept
|
||||
: data_(&typeid(void))
|
||||
{}
|
||||
|
||||
inline stl_type_index(const type_info_t& data) noexcept
|
||||
: data_(&data)
|
||||
{}
|
||||
|
||||
inline const type_info_t& type_info() const noexcept;
|
||||
|
||||
inline const char* raw_name() const noexcept;
|
||||
inline const char* name() const noexcept;
|
||||
inline std::string pretty_name() const;
|
||||
|
||||
inline std::size_t hash_code() const noexcept;
|
||||
inline bool equal(const stl_type_index& rhs) const noexcept;
|
||||
inline bool before(const stl_type_index& rhs) const noexcept;
|
||||
|
||||
template <class T>
|
||||
inline static stl_type_index type_id() noexcept;
|
||||
|
||||
template <class T>
|
||||
inline static stl_type_index type_id_with_cvr() noexcept;
|
||||
|
||||
template <class T>
|
||||
inline static stl_type_index type_id_runtime(const T& value) noexcept;
|
||||
};
|
||||
|
||||
inline const stl_type_index::type_info_t& stl_type_index::type_info() const noexcept {
|
||||
return *data_;
|
||||
}
|
||||
|
||||
|
||||
inline const char* stl_type_index::raw_name() const noexcept {
|
||||
#ifdef _MSC_VER
|
||||
return data_->raw_name();
|
||||
#else
|
||||
return data_->name();
|
||||
#endif
|
||||
}
|
||||
|
||||
inline const char* stl_type_index::name() const noexcept {
|
||||
return data_->name();
|
||||
}
|
||||
|
||||
inline std::string stl_type_index::pretty_name() const {
|
||||
static const char cvr_saver_name[] = "boost::typeindex::detail::cvr_saver<";
|
||||
static BOOST_CONSTEXPR_OR_CONST std::string::size_type cvr_saver_name_len = sizeof(cvr_saver_name) - 1;
|
||||
|
||||
// In case of MSVC demangle() is a no-op, and name() already returns demangled name.
|
||||
// In case of GCC and Clang (on non-Windows systems) name() returns mangled name and demangle() undecorates it.
|
||||
const boost::core::scoped_demangled_name demangled_name(data_->name());
|
||||
|
||||
const char* begin = demangled_name.get();
|
||||
if (!begin) {
|
||||
boost::throw_exception(std::runtime_error("Type name demangling failed"));
|
||||
}
|
||||
|
||||
const std::string::size_type len = std::strlen(begin);
|
||||
const char* end = begin + len;
|
||||
|
||||
if (len > cvr_saver_name_len) {
|
||||
const char* b = std::strstr(begin, cvr_saver_name);
|
||||
if (b) {
|
||||
b += cvr_saver_name_len;
|
||||
|
||||
// Trim leading spaces
|
||||
while (*b == ' ') { // the string is zero terminated, we won't exceed the buffer size
|
||||
++ b;
|
||||
}
|
||||
|
||||
// Skip the closing angle bracket
|
||||
const char* e = end - 1;
|
||||
while (e > b && *e != '>') {
|
||||
-- e;
|
||||
}
|
||||
|
||||
// Trim trailing spaces
|
||||
while (e > b && *(e - 1) == ' ') {
|
||||
-- e;
|
||||
}
|
||||
|
||||
if (b < e) {
|
||||
// Parsing seems to have succeeded, the type name is not empty
|
||||
begin = b;
|
||||
end = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return std::string(begin, end);
|
||||
}
|
||||
|
||||
|
||||
inline std::size_t stl_type_index::hash_code() const noexcept {
|
||||
return data_->hash_code();
|
||||
}
|
||||
|
||||
|
||||
/// @cond
|
||||
|
||||
// for this compiler at least, cross-shared-library type_info
|
||||
// comparisons don't work, so we are using typeid(x).name() instead.
|
||||
# if (defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5))) \
|
||||
|| defined(_AIX) \
|
||||
|| (defined(__sgi) && defined(__host_mips)) \
|
||||
|| (defined(__hpux) && defined(__HP_aCC)) \
|
||||
|| (defined(linux) && defined(__INTEL_COMPILER) && defined(__ICC))
|
||||
# define BOOST_TYPE_INDEX_CLASSINFO_COMPARE_BY_NAMES
|
||||
# endif
|
||||
|
||||
/// @endcond
|
||||
|
||||
inline bool stl_type_index::equal(const stl_type_index& rhs) const noexcept {
|
||||
#ifdef BOOST_TYPE_INDEX_CLASSINFO_COMPARE_BY_NAMES
|
||||
return raw_name() == rhs.raw_name() || !std::strcmp(raw_name(), rhs.raw_name());
|
||||
#else
|
||||
return !!(*data_ == *rhs.data_);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool stl_type_index::before(const stl_type_index& rhs) const noexcept {
|
||||
#ifdef BOOST_TYPE_INDEX_CLASSINFO_COMPARE_BY_NAMES
|
||||
return raw_name() != rhs.raw_name() && std::strcmp(raw_name(), rhs.raw_name()) < 0;
|
||||
#else
|
||||
return !!data_->before(*rhs.data_);
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef BOOST_TYPE_INDEX_CLASSINFO_COMPARE_BY_NAMES
|
||||
|
||||
|
||||
template <class T>
|
||||
inline stl_type_index stl_type_index::type_id() noexcept {
|
||||
typedef typename std::remove_reference<T>::type no_ref_t;
|
||||
typedef typename std::remove_cv<no_ref_t>::type no_cvr_t;
|
||||
return typeid(no_cvr_t);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template <class T> class cvr_saver{};
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline stl_type_index stl_type_index::type_id_with_cvr() noexcept {
|
||||
typedef typename std::conditional<
|
||||
std::is_reference<T>::value || std::is_const<T>::value || std::is_volatile<T>::value,
|
||||
detail::cvr_saver<T>,
|
||||
T
|
||||
>::type type;
|
||||
|
||||
return typeid(type);
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
inline stl_type_index stl_type_index::type_id_runtime(const T& value) noexcept {
|
||||
#ifdef BOOST_NO_RTTI
|
||||
return value.boost_type_index_type_id_runtime_();
|
||||
#else
|
||||
return typeid(value);
|
||||
#endif
|
||||
}
|
||||
|
||||
}} // namespace boost::typeindex
|
||||
|
||||
#endif // BOOST_TYPE_INDEX_STL_TYPE_INDEX_HPP
|
||||
280
include/boost/type_index/type_index_facade.hpp
Normal file
280
include/boost/type_index/type_index_facade.hpp
Normal file
@@ -0,0 +1,280 @@
|
||||
//
|
||||
// Copyright 2013-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)
|
||||
//
|
||||
|
||||
#ifndef BOOST_TYPE_INDEX_TYPE_INDEX_FACADE_HPP
|
||||
#define BOOST_TYPE_INDEX_TYPE_INDEX_FACADE_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/container_hash/hash_fwd.hpp>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <type_traits>
|
||||
#include <iosfwd> // for std::basic_ostream
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
namespace boost { namespace typeindex {
|
||||
|
||||
/// \class type_index_facade
|
||||
///
|
||||
/// This class takes care about the comparison operators, hash functions and
|
||||
/// ostream operators. Use this class as a public base class for defining new
|
||||
/// type_info-conforming classes.
|
||||
///
|
||||
/// \b Example:
|
||||
/// \code
|
||||
/// class stl_type_index: public type_index_facade<stl_type_index, std::type_info>
|
||||
/// {
|
||||
/// public:
|
||||
/// typedef std::type_info type_info_t;
|
||||
/// private:
|
||||
/// const type_info_t* data_;
|
||||
///
|
||||
/// public:
|
||||
/// stl_type_index(const type_info_t& data) noexcept
|
||||
/// : data_(&data)
|
||||
/// {}
|
||||
/// // ...
|
||||
/// };
|
||||
/// \endcode
|
||||
///
|
||||
/// \tparam Derived Class derived from type_index_facade.
|
||||
/// \tparam TypeInfo Class that will be used as a base type_info class.
|
||||
/// \note Take a look at the protected methods. They are \b not \b defined in type_index_facade.
|
||||
/// Protected member functions raw_name() \b must be defined in Derived class. All the other
|
||||
/// methods are mandatory.
|
||||
/// \see 'Making a custom type_index' section for more information about
|
||||
/// creating your own type_index using type_index_facade.
|
||||
template <class Derived, class TypeInfo>
|
||||
class type_index_facade {
|
||||
private:
|
||||
/// @cond
|
||||
BOOST_CXX14_CONSTEXPR const Derived & derived() const noexcept {
|
||||
return *static_cast<Derived const*>(this);
|
||||
}
|
||||
/// @endcond
|
||||
public:
|
||||
typedef TypeInfo type_info_t;
|
||||
|
||||
/// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw.
|
||||
/// \return Name of a type. By default returns Derived::raw_name().
|
||||
inline const char* name() const noexcept {
|
||||
return derived().raw_name();
|
||||
}
|
||||
|
||||
/// \b Override: This function \b may be redefined in Derived class. Overrides may throw.
|
||||
/// \return Human readable type name. By default returns Derived::name().
|
||||
inline std::string pretty_name() const {
|
||||
return derived().name();
|
||||
}
|
||||
|
||||
/// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw.
|
||||
/// \return True if two types are equal. By default compares types by raw_name().
|
||||
inline bool equal(const Derived& rhs) const noexcept {
|
||||
const char* const left = derived().raw_name();
|
||||
const char* const right = rhs.raw_name();
|
||||
return left == right || !std::strcmp(left, right);
|
||||
}
|
||||
|
||||
/// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw.
|
||||
/// \return True if rhs is greater than this. By default compares types by raw_name().
|
||||
inline bool before(const Derived& rhs) const noexcept {
|
||||
const char* const left = derived().raw_name();
|
||||
const char* const right = rhs.raw_name();
|
||||
return left != right && std::strcmp(left, right) < 0;
|
||||
}
|
||||
|
||||
/// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw.
|
||||
/// \return Hash code of a type. By default hashes types by raw_name().
|
||||
/// \note Derived class header \b must include <boost/container_hash/hash.hpp>, \b unless this function is redefined in
|
||||
/// Derived class to not use boost::hash_range().
|
||||
inline std::size_t hash_code() const noexcept {
|
||||
const char* const name_raw = derived().raw_name();
|
||||
return boost::hash_range(name_raw, name_raw + std::strlen(name_raw));
|
||||
}
|
||||
|
||||
#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
|
||||
protected:
|
||||
/// \b Override: This function \b must be redefined in Derived class. Overrides \b must not throw.
|
||||
/// \return Pointer to unredable/raw type name.
|
||||
inline const char* raw_name() const noexcept;
|
||||
|
||||
/// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw.
|
||||
/// \return Const reference to underlying low level type_info_t.
|
||||
inline const type_info_t& type_info() const noexcept;
|
||||
|
||||
/// This is a factory method that is used to create instances of Derived classes.
|
||||
/// boost::typeindex::type_id() will call this method, if Derived has same type as boost::typeindex::type_index.
|
||||
///
|
||||
/// \b Override: This function \b may be redefined and made public in Derived class. Overrides \b must not throw.
|
||||
/// Overrides \b must remove const, volatile && and & modifiers from T.
|
||||
/// \tparam T Type for which type_index must be created.
|
||||
/// \return type_index for type T.
|
||||
template <class T>
|
||||
static Derived type_id() noexcept;
|
||||
|
||||
/// This is a factory method that is used to create instances of Derived classes.
|
||||
/// boost::typeindex::type_id_with_cvr() will call this method, if Derived has same type as boost::typeindex::type_index.
|
||||
///
|
||||
/// \b Override: This function \b may be redefined and made public in Derived class. Overrides \b must not throw.
|
||||
/// Overrides \b must \b not remove const, volatile && and & modifiers from T.
|
||||
/// \tparam T Type for which type_index must be created.
|
||||
/// \return type_index for type T.
|
||||
template <class T>
|
||||
static Derived type_id_with_cvr() noexcept;
|
||||
|
||||
/// This is a factory method that is used to create instances of Derived classes.
|
||||
/// boost::typeindex::type_id_runtime(const T&) will call this method, if Derived has same type as boost::typeindex::type_index.
|
||||
///
|
||||
/// \b Override: This function \b may be redefined and made public in Derived class.
|
||||
/// \param variable Variable which runtime type will be stored in type_index.
|
||||
/// \return type_index with runtime type of variable.
|
||||
template <class T>
|
||||
static Derived type_id_runtime(const T& variable) noexcept;
|
||||
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
/// @cond
|
||||
template <class Derived, class TypeInfo>
|
||||
BOOST_CXX14_CONSTEXPR inline bool operator == (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) noexcept {
|
||||
return static_cast<Derived const&>(lhs).equal(static_cast<Derived const&>(rhs));
|
||||
}
|
||||
|
||||
template <class Derived, class TypeInfo>
|
||||
BOOST_CXX14_CONSTEXPR inline bool operator < (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) noexcept {
|
||||
return static_cast<Derived const&>(lhs).before(static_cast<Derived const&>(rhs));
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class Derived, class TypeInfo>
|
||||
BOOST_CXX14_CONSTEXPR inline bool operator > (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) noexcept {
|
||||
return rhs < lhs;
|
||||
}
|
||||
|
||||
template <class Derived, class TypeInfo>
|
||||
BOOST_CXX14_CONSTEXPR inline bool operator <= (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) noexcept {
|
||||
return !(lhs > rhs);
|
||||
}
|
||||
|
||||
template <class Derived, class TypeInfo>
|
||||
BOOST_CXX14_CONSTEXPR inline bool operator >= (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) noexcept {
|
||||
return !(lhs < rhs);
|
||||
}
|
||||
|
||||
template <class Derived, class TypeInfo>
|
||||
BOOST_CXX14_CONSTEXPR inline bool operator != (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) noexcept {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
// ######################### COMPARISONS with Derived ############################ //
|
||||
template <class Derived, class TypeInfo>
|
||||
inline bool operator == (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) noexcept {
|
||||
return Derived(lhs) == rhs;
|
||||
}
|
||||
|
||||
template <class Derived, class TypeInfo>
|
||||
inline bool operator < (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) noexcept {
|
||||
return Derived(lhs) < rhs;
|
||||
}
|
||||
|
||||
template <class Derived, class TypeInfo>
|
||||
inline bool operator > (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) noexcept {
|
||||
return rhs < Derived(lhs);
|
||||
}
|
||||
|
||||
template <class Derived, class TypeInfo>
|
||||
inline bool operator <= (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) noexcept {
|
||||
return !(Derived(lhs) > rhs);
|
||||
}
|
||||
|
||||
template <class Derived, class TypeInfo>
|
||||
inline bool operator >= (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) noexcept {
|
||||
return !(Derived(lhs) < rhs);
|
||||
}
|
||||
|
||||
template <class Derived, class TypeInfo>
|
||||
inline bool operator != (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) noexcept {
|
||||
return !(Derived(lhs) == rhs);
|
||||
}
|
||||
|
||||
|
||||
template <class Derived, class TypeInfo>
|
||||
inline bool operator == (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) noexcept {
|
||||
return lhs == Derived(rhs);
|
||||
}
|
||||
|
||||
template <class Derived, class TypeInfo>
|
||||
inline bool operator < (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) noexcept {
|
||||
return lhs < Derived(rhs);
|
||||
}
|
||||
|
||||
template <class Derived, class TypeInfo>
|
||||
inline bool operator > (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) noexcept {
|
||||
return Derived(rhs) < lhs;
|
||||
}
|
||||
|
||||
template <class Derived, class TypeInfo>
|
||||
inline bool operator <= (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) noexcept {
|
||||
return !(lhs > Derived(rhs));
|
||||
}
|
||||
|
||||
template <class Derived, class TypeInfo>
|
||||
inline bool operator >= (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) noexcept {
|
||||
return !(lhs < Derived(rhs));
|
||||
}
|
||||
|
||||
template <class Derived, class TypeInfo>
|
||||
inline bool operator != (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) noexcept {
|
||||
return !(lhs == Derived(rhs));
|
||||
}
|
||||
|
||||
// ######################### COMPARISONS with Derived END ############################ //
|
||||
|
||||
/// @endcond
|
||||
|
||||
#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
|
||||
|
||||
/// noexcept comparison operators for type_index_facade classes.
|
||||
bool operator ==, !=, <, ... (const type_index_facade& lhs, const type_index_facade& rhs) noexcept;
|
||||
|
||||
/// noexcept comparison operators for type_index_facade and it's TypeInfo classes.
|
||||
bool operator ==, !=, <, ... (const type_index_facade& lhs, const TypeInfo& rhs) noexcept;
|
||||
|
||||
/// noexcept comparison operators for type_index_facade's TypeInfo and type_index_facade classes.
|
||||
bool operator ==, !=, <, ... (const TypeInfo& lhs, const type_index_facade& rhs) noexcept;
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_IOSTREAM
|
||||
/// Ostream operator that will output demangled name.
|
||||
template <class CharT, class TriatT, class Derived, class TypeInfo>
|
||||
inline std::basic_ostream<CharT, TriatT>& operator<<(
|
||||
std::basic_ostream<CharT, TriatT>& ostr,
|
||||
const type_index_facade<Derived, TypeInfo>& ind)
|
||||
{
|
||||
ostr << static_cast<Derived const&>(ind).pretty_name();
|
||||
return ostr;
|
||||
}
|
||||
#endif // BOOST_NO_IOSTREAM
|
||||
|
||||
/// This free function is used by Boost's unordered containers.
|
||||
/// \note <boost/container_hash/hash.hpp> has to be included if this function is used.
|
||||
template <class Derived, class TypeInfo>
|
||||
inline std::size_t hash_value(const type_index_facade<Derived, TypeInfo>& lhs) noexcept {
|
||||
return static_cast<Derived const&>(lhs).hash_code();
|
||||
}
|
||||
|
||||
}} // namespace boost::typeindex
|
||||
|
||||
#endif // BOOST_TYPE_INDEX_TYPE_INDEX_FACADE_HPP
|
||||
|
||||
37
index.html
Normal file
37
index.html
Normal file
@@ -0,0 +1,37 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
Copyright 2014-2023 Antony Polukhin
|
||||
antoshkka at gmail dot com
|
||||
|
||||
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/boost_typeindex.html">
|
||||
<title>Boost.TypeIndex</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/boost_typeindex.html">../../doc/html/boost_typeindex.html</a>
|
||||
</p>
|
||||
<p>
|
||||
© 2014-2023 Antony Polukhin
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,140 +0,0 @@
|
||||
[library Boost.TypeIndex
|
||||
[quickbook 1.5]
|
||||
[version 1.0]
|
||||
[copyright 2012-2013 Antony Polukhin]
|
||||
[category Language Features Emulation]
|
||||
[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])
|
||||
]
|
||||
]
|
||||
|
||||
[section Motivation]
|
||||
Sometimes getting and storing information about a type at runtime is required. For such cases a construction like `&typeid(T)` or C++11 class `std::type_index` is usually used. And that is the point, where problems start:
|
||||
|
||||
* `typeid(T)` and `std::type_index` require Run Time Type Info (RTTI)
|
||||
* some implementations of `typeid(T)` strip const, volatile and references from type, while others don't
|
||||
* some compilers have bugs and do not correctly compare `std::type_info` objects across shared libraries
|
||||
* only a few implementations of Standard Library currently provide `std::type_index`
|
||||
* no easy way to store type info without stripping const, volatile and references
|
||||
* no nice and portable way to get human readable type names
|
||||
|
||||
Boost.TypeIndex was designed to work around all those issues.
|
||||
|
||||
[note `T` means type here. Think of it as of `T` in `template <class T>` ]
|
||||
|
||||
[warning This library is not accepted to Boost, it is currrently waiting for review. ]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Getting started]
|
||||
|
||||
`boost::type_index` can be used as a drop-in replacement for `std::type_index`, but
|
||||
it usually does not require RTTI. It provides the full set of comparison operators,
|
||||
hashing functions and ostream operators, so it can be used with any container class.
|
||||
|
||||
To start using it:
|
||||
|
||||
* Replace `std::type_index`, `const std::type_info&`, `const std::type_info*` with `boost::type_index`.
|
||||
* If you do not want to save `const`, `volatile`, `&` and `&&`:
|
||||
* Use `boost::type_id<T>()` instead of `typeid(T)`, `&typeid(T)`.
|
||||
* If you want to save `const`, `volatile`, `&` and `&&`:
|
||||
* Use `boost::type_id_with_cvr<T>()` instead of `typeid(T)`, `&typeid(T)`.
|
||||
* To get nice human readable names, use the `name_demangled()` member function:
|
||||
``
|
||||
#include <boost/type_index/type_index_minimal.hpp>
|
||||
|
||||
type_index ti = type_id<T>();
|
||||
std::string nice_name
|
||||
= ti.name_demangled();
|
||||
...
|
||||
std::string nice_name_with_const_volatile_ref
|
||||
= type_id_with_cvr<ParamT&>().name_demangled();
|
||||
``
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[section Examples]
|
||||
|
||||
[import ../examples/demangled_names.cpp]
|
||||
[section Getting human readable and mangled type names] [type_index_names_example] [endsect]
|
||||
|
||||
[import ../examples/registry.cpp]
|
||||
[section Storing information about a type in container ] [type_index_registry_example] [endsect]
|
||||
|
||||
[import ../examples/inheritance.cpp]
|
||||
[section Getting through the inheritance to receive a real type name ] [type_index_derived_example] [endsect]
|
||||
|
||||
[import ../examples/exact_types_match.cpp]
|
||||
[section Exact type match: storing type with const, volatile and reference ] [type_index_exact_type_match_example] [endsect]
|
||||
|
||||
[endsect]
|
||||
|
||||
[xinclude autodoc.xml]
|
||||
|
||||
[section Space and Performance]
|
||||
|
||||
* `template_index` uses the `BOOST_CURRENT_FUNCTION` macro which could lead to code bloat, so prefer using `type_index` type.
|
||||
* `type_index` and `template_index` classes hold a single pointer, so they are easy and fast to copy.
|
||||
* Calls to `const char* name()` do not require dynamic memory allocation and usually just return a pointer to an array of chars in a read-only section of the binary image.
|
||||
* Comparison operators are optimized as much as possible, and will at worst execute a single `std::strcmp`.
|
||||
* Calls to `std::string name_demangled()` for `type_index` do usually require dynamic memory allocation and some computations, so they are not recomended for usage in performance critical sections.
|
||||
* Calls to `std::string name_demangled()` for `template_index` only require a single `std::strlen` call and are considerably faster than `std::string name_demangled()` for `type_index`.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Code bloat]
|
||||
|
||||
Without RTTI TypeIndex library will switch from using `boost::type_index` class to `boost::template_index`. `boost::template_index` uses the `BOOST_CURRENT_FUNCTION` for each type that is passed to `type_id()` and `type_id_with_cvr()`
|
||||
functions.
|
||||
|
||||
This leads to big strings in binary file:
|
||||
```
|
||||
static const char* boost::detail::ctti<T>::n() [with T = int]
|
||||
static const char* boost::detail::ctti<T>::n() [with T = user_defined_type]
|
||||
```
|
||||
While using RTTI, you'll get the following (more compact) string in binary file:
|
||||
|
||||
```
|
||||
i
|
||||
17user_defined_type
|
||||
```
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Compiler support]
|
||||
|
||||
TypeIndex has been tested and sucessfully work on MSVC2010, GCC-4.5, Clang-2.9. If your compiler is not in a list of tested compilers, you shall correctly define `BOOST_TYPE_INDEX_FUNCTION_SIGNATURE`,`BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP` and `BOOST_TYPE_INDEX_CTTI_END_SKIP` macroses:
|
||||
|
||||
# define `BOOST_TYPE_INDEX_FUNCTION_SIGNATURE` to a a compiler specific macro, that outputs the *whole* function signature, including template parameters
|
||||
# define `BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP` and `BOOST_TYPE_INDEX_CTTI_END_SKIP` to `0`
|
||||
# get the output of `boost::detail::ctti<int>::n()`
|
||||
# set `BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP` equal to characters count before last occurrence of `int` in output
|
||||
# set `BOOST_TYPE_INDEX_CTTI_END_SKIP` equal to characters count after last occurrence of `int` in output
|
||||
# check that `boost::detail::ctti<int>::name_demangled()` returns "int"
|
||||
# (optional, but highly recomended) [@http://www.boost.org/support/bugs.html create ticket] with feature request to add your compiler to supported compilers list. Include `BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP` and `BOOST_TYPE_INDEX_CTTI_END_SKIP` numbers.
|
||||
|
||||
Consider the following example:
|
||||
With `BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP` and `BOOST_TYPE_INDEX_CTTI_END_SKIP` set to `0`, `boost::detail::ctti<int>::n()` returns "const char *__cdecl boost::detail::ctti<int>::n(void)". Then you shall set `BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP` to `sizeof("const char *__cdecl boost::detail::ctti<") - 1` and `BOOST_TYPE_INDEX_CTTI_END_SKIP` to `sizeof(">::n(void)") - 1`
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Mixing sources with RTTI on and RTTI off]
|
||||
|
||||
Linking a binary from source files that were compiled with different RTTI flags is not a very good idea and may lead to a lot of surprises. However if there is a very strong need TypeIndex library provides a solution for mixing sources: just define `BOOST_TYPE_INDEX_FORCE_NORTTI_COMPATIBILITY` macro. This would lead to usage of `boost::template_index` instead of `boost::type_index` class.
|
||||
|
||||
[note Do not forget to rebuild *all* the projects with `BOOST_TYPE_INDEX_FORCE_NORTTI_COMPATIBILITY` macro defined ]
|
||||
|
||||
You must know that linking RTTI on and RTTI off binaries may succeed even without defining the `BOOST_TYPE_INDEX_FORCE_NORTTI_COMPATIBILITY` macro, but that does not mean that you'll get a working binary. Such actions may break the One Definition Rule. Take a look at the table below, that shows how the `boost::type_index get_integer();` function will look like with different RTTI flags:
|
||||
|
||||
[table:diffs
|
||||
[[RTTI on] [RTTI off]]
|
||||
[[`boost::type_index get_integer();`] [`boost::template_index get_integer();`]]
|
||||
]
|
||||
|
||||
Such differences are usually not detected by linker and lead to errors at runtime.
|
||||
|
||||
[endsect]
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
// Copyright 2013 Antony Polukhin
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See the accompanying file LICENSE_1_0.txt
|
||||
// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
|
||||
|
||||
|
||||
//[type_index_names_example
|
||||
/*`
|
||||
The following example shows how short (mangled) and human readable type names could be obtained from a type.
|
||||
Works with and without RTTI.
|
||||
*/
|
||||
|
||||
|
||||
#include <boost/type_index/type_index_minimal.hpp>
|
||||
#include <iostream>
|
||||
|
||||
template <class T>
|
||||
void foo(T) {
|
||||
std::cout << "\n Short name: " << boost::type_id<T>().name();
|
||||
std::cout << "\n Readable name: " << boost::type_id<T>().name_demangled();
|
||||
}
|
||||
|
||||
struct user_defined_type{};
|
||||
|
||||
int main() {
|
||||
// Call to
|
||||
foo(1);
|
||||
// will output something like this:
|
||||
//
|
||||
// (RTTI on) (RTTI off)
|
||||
// Short name: i Short name: int]
|
||||
// Readable name: int Readable name: int
|
||||
|
||||
user_defined_type t;
|
||||
foo(t);
|
||||
// Will output:
|
||||
//
|
||||
// (RTTI on) (RTTI off)
|
||||
// Short name: 17user_defined_type user_defined_type]
|
||||
// Readable name: user_defined_type user_defined_type
|
||||
}
|
||||
|
||||
/*`
|
||||
Short names are very compiler dependant: some compiler will output `.H`, others `i`.
|
||||
|
||||
Readable names may also differ between compilers: `struct user_defined_type`, `user_defined_type`.
|
||||
*/
|
||||
|
||||
//] [/type_index_names_example]
|
||||
@@ -1,58 +0,0 @@
|
||||
// Copyright 2013 Antony Polukhin
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See the accompanying file LICENSE_1_0.txt
|
||||
// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
|
||||
|
||||
//[type_index_exact_type_match_example
|
||||
/*`
|
||||
The following example shows that `boost::template_index` is able to store the exact type, without stripping const, volatile and references.
|
||||
Example works with and without RTTI.
|
||||
|
||||
In this example we'll create a class, that stores pointer to function and remembers the exact type of a parameter that function accepts.
|
||||
When an attempt to call the stored function will be made, type of input parameter will be checked for exact match with initaily erased type of function.
|
||||
*/
|
||||
|
||||
#include <boost/type_index.hpp>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
|
||||
class type_erased_unary_function {
|
||||
void* function_ptr_;
|
||||
boost::template_index exact_param_t_;
|
||||
|
||||
public:
|
||||
template <class ParamT>
|
||||
type_erased_unary_function(void(*ptr)(ParamT))
|
||||
: function_ptr_(reinterpret_cast<void*>(ptr)) // ptr - is a pointer to function returning `void` and accepting parameter of type `ParamT`
|
||||
, exact_param_t_(boost::template_id_with_cvr<ParamT>())
|
||||
{}
|
||||
|
||||
template <class ParamT>
|
||||
void call(ParamT v) {
|
||||
if (exact_param_t_ != boost::template_id_with_cvr<ParamT>()) {
|
||||
throw std::runtime_error("Incorrect `ParamT`");
|
||||
}
|
||||
|
||||
return (reinterpret_cast<void(*)(ParamT)>(function_ptr_))(v);
|
||||
}
|
||||
};
|
||||
|
||||
void foo(int){}
|
||||
|
||||
int main() {
|
||||
type_erased_unary_function func(&foo);
|
||||
func.call(100); // OK, `100` has type `int`
|
||||
|
||||
try {
|
||||
int i = 100;
|
||||
|
||||
// An attempt to convert stored function to a function accepting reference
|
||||
func.call<int&>(i); // Will throw, because types `int&` and `int` missmatch
|
||||
|
||||
assert(false);
|
||||
} catch (const std::runtime_error& /*e*/) {}
|
||||
}
|
||||
|
||||
//] [/type_index_exact_type_match_example]
|
||||
@@ -1,33 +0,0 @@
|
||||
// Copyright 2013 Antony Polukhin
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See the accompanying file LICENSE_1_0.txt
|
||||
// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
|
||||
|
||||
//[type_index_derived_example
|
||||
/*`
|
||||
The following example shows that `boost::type_index` is able to store the real type, successfully getting through
|
||||
all the inheritances.
|
||||
Example works with RTTI only. Without RTTI support it won't compile, producing a compile-time error with message:
|
||||
"boost::type_id_rtti_only(T&) requires RTTI"
|
||||
*/
|
||||
|
||||
#include <boost/type_index/type_index_minimal.hpp>
|
||||
#include <iostream>
|
||||
|
||||
struct A { virtual ~A(){} };
|
||||
struct B: public A {};
|
||||
struct C: public B {};
|
||||
|
||||
void print_real_type(const A& a) {
|
||||
std::cout << boost::type_id_rtti_only(a).name_demangled() << '\n';
|
||||
}
|
||||
|
||||
int main() {
|
||||
C c;
|
||||
const A& c_as_a = c;
|
||||
print_real_type(c_as_a); // Outputs `struct C`
|
||||
print_real_type(B()); // Outputs `struct B`
|
||||
}
|
||||
|
||||
//] [/type_index_derived_example]
|
||||
@@ -1,36 +0,0 @@
|
||||
// Copyright 2013 Antony Polukhin
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See the accompanying file LICENSE_1_0.txt
|
||||
// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
|
||||
|
||||
//[type_index_registry_example
|
||||
/*`
|
||||
The following example shows how an information about a type could be stored.
|
||||
Example works with and without RTTI.
|
||||
*/
|
||||
|
||||
#include <boost/type_index/type_index_minimal.hpp>
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <cassert>
|
||||
|
||||
int main() {
|
||||
boost::unordered_set<boost::type_index> types;
|
||||
|
||||
// Storing some `boost::type_info`s
|
||||
types.insert(boost::type_id<int>());
|
||||
types.insert(boost::type_id<float>());
|
||||
|
||||
// `types` variable contains two `boost::type_index`es:
|
||||
assert(types.size() == 2);
|
||||
|
||||
// Const, volatile and reference will be striped from the type:
|
||||
bool is_inserted = types.insert(boost::type_id<const int>()).second;
|
||||
assert(!is_inserted);
|
||||
assert(types.erase(boost::type_id<float&>()) == 1);
|
||||
|
||||
// We have erased the `float` type, only `int` remains
|
||||
assert(*types.begin() == boost::type_id<int>());
|
||||
}
|
||||
|
||||
//] [/type_index_registry_example]
|
||||
@@ -1,63 +0,0 @@
|
||||
# Copyright (C) 2012-2013 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)
|
||||
#
|
||||
|
||||
import testing ;
|
||||
import feature ;
|
||||
|
||||
|
||||
# Variable that contains all the stuff required for linking against -lboost_unit_test
|
||||
tlib = /boost/test//boost_unit_test_framework/<link>static ;
|
||||
|
||||
# Variable that contains all the stuff required for linking together <rtti>on and <rtti>off
|
||||
compat = <define>BOOST_TYPE_INDEX_FORCE_NORTTI_COMPATIBILITY ;
|
||||
|
||||
# Making own `nortti` that is link compatible
|
||||
nortti = <toolset>gcc:<cxxflags>-fno-rtti <toolset>clang:<cxxflags>-fno-rtti <toolset>msvc:<cxxflags>/GR- ;
|
||||
|
||||
|
||||
# Making libraries that CANNOT work between rtti-on/rtti-off modules
|
||||
obj test_lib_nortti-obj : test_lib.cpp : <link>shared $(nortti) ;
|
||||
obj test_lib_rtti-obj : test_lib.cpp : <link>shared ;
|
||||
lib test_lib_rtti : test_lib_rtti-obj : <link>shared ;
|
||||
lib test_lib_nortti : test_lib_nortti-obj : <link>shared $(nortti) ;
|
||||
|
||||
# Making libraries that can work between rtti-on/rtti-off modules
|
||||
obj test_lib_nortti_compat-obj : test_lib.cpp : <link>shared $(nortti) $(compat) ;
|
||||
obj test_lib_rtti_compat-obj : test_lib.cpp : <link>shared $(nortti) $(compat) ;
|
||||
lib test_lib_nortti_compat : test_lib_nortti_compat-obj : <link>shared $(nortti) $(compat) ;
|
||||
lib test_lib_rtti_compat : test_lib_rtti_compat-obj : <link>shared $(nortti) $(compat) ;
|
||||
|
||||
|
||||
test-suite type_index
|
||||
:
|
||||
[ run type_index_test.cpp $(tlib) ]
|
||||
[ run template_index_test.cpp $(tlib) ]
|
||||
[ run testing_both.cpp $(tlib) ]
|
||||
[ run testing_both_no_rtti.cpp $(tlib) : : : <rtti>off ]
|
||||
[ run testing_minimal.cpp $(tlib) ]
|
||||
[ run testing_minimal_no_rtti.cpp $(tlib) : : : <rtti>off ]
|
||||
[ run testing_crossmodule.cpp test_lib_rtti $(tlib) ]
|
||||
[ run testing_crossmodule.cpp test_lib_nortti $(tlib) : : : <rtti>off : testing_crossmodule_no_rtti ]
|
||||
|
||||
# Mixing RTTI on and off
|
||||
[ link-fail testing_crossmodule.cpp $(tlib) test_lib_rtti : $(nortti) : link_fail_nortti_rtti ]
|
||||
[ link-fail testing_crossmodule.cpp $(tlib) test_lib_nortti : : link_fail_rtti_nortti ]
|
||||
[ run testing_crossmodule.cpp $(tlib) test_lib_rtti_compat : : : $(nortti) $(compat) : testing_crossmodule_nortti_rtti_compat ]
|
||||
[ run testing_crossmodule.cpp $(tlib) test_lib_nortti_compat : : : $(compat) : testing_crossmodule_rtti_nortti_compat ]
|
||||
|
||||
# Examples that must work even with RTTI disabled
|
||||
[ run ../examples/registry.cpp : : : <rtti>off : registry_no_rtti ]
|
||||
[ run ../examples/exact_types_match.cpp : : : <rtti>off : exact_types_match_no_rtti ]
|
||||
[ run ../examples/demangled_names.cpp : : : <rtti>off : demangled_names_no_rtti ]
|
||||
[ compile-fail ../examples/inheritance.cpp : <rtti>off : failing_inheritance_example ]
|
||||
;
|
||||
|
||||
# Assuring that examples compile and run. Adding sources from `examples` directory to the `type_index` test suite.
|
||||
for local p in [ glob ../examples/*.cpp ]
|
||||
{
|
||||
type_index += [ run $(p) ] ;
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
//
|
||||
// Copyright Antony Polukhin, 2012-2013.
|
||||
//
|
||||
// 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_TEST_MODULE template_index_test_module
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
// Byapssing internal assertion for correct header inclusion
|
||||
#define BOOST_TYPE_INDEX_TYPE_INDEX_MINIMAL_HPP
|
||||
|
||||
#include <boost/type_index/template_index_impl.hpp>
|
||||
|
||||
namespace my_namespace1 {
|
||||
class my_class{};
|
||||
}
|
||||
|
||||
|
||||
namespace my_namespace2 {
|
||||
class my_class{};
|
||||
}
|
||||
|
||||
#include "template_index_tests.ipp"
|
||||
|
||||
@@ -1,199 +0,0 @@
|
||||
//
|
||||
// Copyright Antony Polukhin, 2012.
|
||||
//
|
||||
// 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/functional/hash.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
BOOST_AUTO_TEST_CASE(names_matches_template_id)
|
||||
{
|
||||
using namespace boost;
|
||||
BOOST_CHECK_EQUAL(template_id<int>().name_demangled(), "int");
|
||||
BOOST_CHECK_EQUAL(template_id<double>().name_demangled(), "double");
|
||||
|
||||
BOOST_CHECK_EQUAL(template_id<int>().name(), template_id<int>().name());
|
||||
BOOST_CHECK_NE(template_id<int>().name(), template_id<double>().name());
|
||||
BOOST_CHECK_NE(template_id<double>().name(), template_id<int>().name());
|
||||
BOOST_CHECK_EQUAL(template_id<double>().name(), template_id<double>().name());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(comparators_template_id)
|
||||
{
|
||||
using namespace boost;
|
||||
template_index t_int = template_id<int>();
|
||||
template_index t_double = template_id<double>();
|
||||
|
||||
BOOST_CHECK_EQUAL(t_int, t_int);
|
||||
BOOST_CHECK_LE(t_int, t_int);
|
||||
BOOST_CHECK_GE(t_int, t_int);
|
||||
BOOST_CHECK_NE(t_int, t_double);
|
||||
|
||||
BOOST_CHECK_LE(t_double, t_double);
|
||||
BOOST_CHECK_GE(t_double, t_double);
|
||||
BOOST_CHECK_NE(t_double, t_int);
|
||||
|
||||
BOOST_CHECK(t_double < t_int || t_int < t_double);
|
||||
BOOST_CHECK(t_double > t_int || t_int > t_double);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(hash_code_template_id)
|
||||
{
|
||||
using namespace boost;
|
||||
std::size_t t_int1 = template_id<int>().hash_code();
|
||||
std::size_t t_double1 = template_id<double>().hash_code();
|
||||
|
||||
std::size_t t_int2 = template_id<int>().hash_code();
|
||||
std::size_t t_double2 = template_id<double>().hash_code();
|
||||
|
||||
BOOST_CHECK_EQUAL(t_int1, t_int2);
|
||||
BOOST_CHECK_NE(t_int1, t_double2);
|
||||
BOOST_CHECK_LE(t_double1, t_double2);
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
static void test_with_modofiers() {
|
||||
using namespace boost;
|
||||
|
||||
template_index t1 = template_id_with_cvr<T1>();
|
||||
template_index t2 = template_id_with_cvr<T2>();
|
||||
|
||||
BOOST_CHECK_NE(t2, t1);
|
||||
BOOST_CHECK(t1 < t2 || t2 < t1);
|
||||
BOOST_CHECK(t1 > t2 || t2 > t1);
|
||||
|
||||
BOOST_CHECK_EQUAL(t1, template_id_with_cvr<T1>());
|
||||
BOOST_CHECK_EQUAL(t2, template_id_with_cvr<T2>());
|
||||
|
||||
BOOST_CHECK_EQUAL(t1.hash_code(), template_id_with_cvr<T1>().hash_code());
|
||||
BOOST_CHECK_EQUAL(t2.hash_code(), template_id_with_cvr<T2>().hash_code());
|
||||
|
||||
BOOST_CHECK_NE(t1.hash_code(), template_id_with_cvr<T2>().hash_code());
|
||||
BOOST_CHECK_NE(t2.hash_code(), template_id_with_cvr<T1>().hash_code());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(template_id_storing_modifiers)
|
||||
{
|
||||
test_with_modofiers<int, const int>();
|
||||
test_with_modofiers<int, const int&>();
|
||||
test_with_modofiers<int, int&>();
|
||||
test_with_modofiers<int, volatile int>();
|
||||
test_with_modofiers<int, volatile int&>();
|
||||
test_with_modofiers<int, const volatile int>();
|
||||
test_with_modofiers<int, const volatile int&>();
|
||||
|
||||
test_with_modofiers<const int, int>();
|
||||
test_with_modofiers<const int, const int&>();
|
||||
test_with_modofiers<const int, int&>();
|
||||
test_with_modofiers<const int, volatile int>();
|
||||
test_with_modofiers<const int, volatile int&>();
|
||||
test_with_modofiers<const int, const volatile int>();
|
||||
test_with_modofiers<const int, const volatile int&>();
|
||||
|
||||
test_with_modofiers<const int&, int>();
|
||||
test_with_modofiers<const int&, const int>();
|
||||
test_with_modofiers<const int&, int&>();
|
||||
test_with_modofiers<const int&, volatile int>();
|
||||
test_with_modofiers<const int&, volatile int&>();
|
||||
test_with_modofiers<const int&, const volatile int>();
|
||||
test_with_modofiers<const int&, const volatile int&>();
|
||||
|
||||
test_with_modofiers<int&, const int>();
|
||||
test_with_modofiers<int&, const int&>();
|
||||
test_with_modofiers<int&, int>();
|
||||
test_with_modofiers<int&, volatile int>();
|
||||
test_with_modofiers<int&, volatile int&>();
|
||||
test_with_modofiers<int&, const volatile int>();
|
||||
test_with_modofiers<int&, const volatile int&>();
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
test_with_modofiers<int&&, const int>();
|
||||
test_with_modofiers<int&&, const int&>();
|
||||
test_with_modofiers<int&&, const int&&>();
|
||||
test_with_modofiers<int&&, int>();
|
||||
test_with_modofiers<int&&, volatile int>();
|
||||
test_with_modofiers<int&&, volatile int&>();
|
||||
test_with_modofiers<int&&, volatile int&&>();
|
||||
test_with_modofiers<int&&, const volatile int>();
|
||||
test_with_modofiers<int&&, const volatile int&>();
|
||||
test_with_modofiers<int&&, const volatile int&&>();
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static void test_storing_nonstoring_modifiers_templ() {
|
||||
using namespace boost;
|
||||
|
||||
template_index t1 = template_id_with_cvr<T>();
|
||||
template_index t2 = template_id<T>();
|
||||
|
||||
BOOST_CHECK_EQUAL(t2, t1);
|
||||
BOOST_CHECK_EQUAL(t1, t2);
|
||||
BOOST_CHECK(t1 <= t2);
|
||||
BOOST_CHECK(t1 >= t2);
|
||||
BOOST_CHECK(t2 <= t1);
|
||||
BOOST_CHECK(t2 >= t1);
|
||||
|
||||
BOOST_CHECK_EQUAL(t2.name_demangled(), t1.name_demangled());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(template_id_storing_modifiers_vs_nonstoring)
|
||||
{
|
||||
test_storing_nonstoring_modifiers_templ<int>();
|
||||
test_storing_nonstoring_modifiers_templ<my_namespace1::my_class>();
|
||||
test_storing_nonstoring_modifiers_templ<my_namespace2::my_class>();
|
||||
|
||||
boost::template_index t1 = boost::template_id_with_cvr<const int>();
|
||||
boost::template_index t2 = boost::template_id<int>();
|
||||
BOOST_CHECK_NE(t2, t1);
|
||||
BOOST_CHECK(t1.name_demangled() == "const int" || t1.name_demangled() == "int const");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(template_index_stream_operator_via_lexical_cast_testing)
|
||||
{
|
||||
using namespace boost;
|
||||
|
||||
std::string s_int2 = lexical_cast<std::string>(template_id<int>());
|
||||
BOOST_CHECK_EQUAL(s_int2, "int");
|
||||
|
||||
std::string s_double2 = lexical_cast<std::string>(template_id<double>());
|
||||
BOOST_CHECK_EQUAL(s_double2, "double");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(template_index_stripping_cvr_test)
|
||||
{
|
||||
using namespace boost;
|
||||
|
||||
BOOST_CHECK_EQUAL(template_id<int>(), template_id<const int>());
|
||||
BOOST_CHECK_EQUAL(template_id<int>(), template_id<const volatile int>());
|
||||
BOOST_CHECK_EQUAL(template_id<int>(), template_id<const volatile int&>());
|
||||
|
||||
BOOST_CHECK_EQUAL(template_id<int>(), template_id<int&>());
|
||||
BOOST_CHECK_EQUAL(template_id<int>(), template_id<volatile int>());
|
||||
BOOST_CHECK_EQUAL(template_id<int>(), template_id<volatile int&>());
|
||||
|
||||
|
||||
BOOST_CHECK_EQUAL(template_id<double>(), template_id<const double>());
|
||||
BOOST_CHECK_EQUAL(template_id<double>(), template_id<const volatile double>());
|
||||
BOOST_CHECK_EQUAL(template_id<double>(), template_id<const volatile double&>());
|
||||
|
||||
BOOST_CHECK_EQUAL(template_id<double>(), template_id<double&>());
|
||||
BOOST_CHECK_EQUAL(template_id<double>(), template_id<volatile double>());
|
||||
BOOST_CHECK_EQUAL(template_id<double>(), template_id<volatile double&>());
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(template_index_user_defined_class_test)
|
||||
{
|
||||
using namespace boost;
|
||||
|
||||
BOOST_CHECK_EQUAL(template_id<my_namespace1::my_class>(), template_id<my_namespace1::my_class>());
|
||||
BOOST_CHECK_EQUAL(template_id<my_namespace2::my_class>(), template_id<my_namespace2::my_class>());
|
||||
|
||||
BOOST_CHECK_NE(template_id<my_namespace1::my_class>(), template_id<my_namespace2::my_class>());
|
||||
BOOST_CHECK_NE(
|
||||
template_id<my_namespace1::my_class>().name_demangled().find("my_namespace1::my_class"),
|
||||
std::string::npos);
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
#define TEST_LIB_SOURCE
|
||||
#include "test_lib.hpp"
|
||||
|
||||
namespace user_defined_namespace {
|
||||
class user_defined{};
|
||||
}
|
||||
|
||||
namespace test_lib {
|
||||
|
||||
boost::type_index get_integer() {
|
||||
return boost::type_id<int>();
|
||||
}
|
||||
|
||||
boost::type_index get_user_defined_class() {
|
||||
return boost::type_id<user_defined_namespace::user_defined>();
|
||||
}
|
||||
|
||||
boost::type_index get_const_integer() {
|
||||
return boost::type_id_with_cvr<const int>();
|
||||
}
|
||||
|
||||
boost::type_index get_const_user_defined_class() {
|
||||
return boost::type_id_with_cvr<const user_defined_namespace::user_defined>();
|
||||
}
|
||||
|
||||
|
||||
// Just do nothing
|
||||
void accept_typeindex(const boost::type_index&) {}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
//
|
||||
// Copyright Antony Polukhin, 2012-2013.
|
||||
//
|
||||
// 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_TEST_MODULE testing_both_test_module
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/type_index.hpp>
|
||||
|
||||
namespace my_namespace1 {
|
||||
class my_class{};
|
||||
}
|
||||
|
||||
|
||||
namespace my_namespace2 {
|
||||
class my_class{};
|
||||
}
|
||||
|
||||
#include "type_index_tests.ipp"
|
||||
#include "template_index_tests.ipp"
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
//
|
||||
// Copyright Antony Polukhin, 2012-2013.
|
||||
//
|
||||
// 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_TEST_MODULE testing_both_test_module
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/type_index.hpp>
|
||||
|
||||
#ifndef BOOST_NO_RTTI
|
||||
#error "This test must be run with disabled RTTI"
|
||||
#endif
|
||||
|
||||
namespace my_namespace1 {
|
||||
class my_class{};
|
||||
}
|
||||
|
||||
|
||||
namespace my_namespace2 {
|
||||
class my_class{};
|
||||
}
|
||||
|
||||
#include "type_index_tests.ipp"
|
||||
#include "template_index_tests.ipp"
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
//
|
||||
// Copyright Antony Polukhin, 2012-2013.
|
||||
//
|
||||
// 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_TEST_MODULE testing_crossmodule_module
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <boost/type_index/type_index_minimal.hpp>
|
||||
#include "test_lib.hpp"
|
||||
|
||||
namespace user_defined_namespace {
|
||||
class user_defined{};
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(comparing_types_between_modules)
|
||||
{
|
||||
boost::type_index t_const_int = boost::type_id_with_cvr<const int>();
|
||||
boost::type_index t_int = boost::type_id<int>();
|
||||
|
||||
BOOST_CHECK_EQUAL(t_int, test_lib::get_integer());
|
||||
BOOST_CHECK_EQUAL(t_const_int, test_lib::get_const_integer());
|
||||
BOOST_CHECK_NE(t_const_int, test_lib::get_integer());
|
||||
BOOST_CHECK_NE(t_int, test_lib::get_const_integer());
|
||||
|
||||
|
||||
boost::type_index t_const_userdef = boost::type_id_with_cvr<const user_defined_namespace::user_defined>();
|
||||
boost::type_index t_userdef = boost::type_id<user_defined_namespace::user_defined>();
|
||||
|
||||
BOOST_CHECK_EQUAL(t_userdef, test_lib::get_user_defined_class());
|
||||
BOOST_CHECK_EQUAL(t_const_userdef, test_lib::get_const_user_defined_class());
|
||||
BOOST_CHECK_NE(t_const_userdef, test_lib::get_user_defined_class());
|
||||
BOOST_CHECK_NE(t_userdef, test_lib::get_const_user_defined_class());
|
||||
|
||||
|
||||
BOOST_CHECK_NE(t_userdef, test_lib::get_integer());
|
||||
BOOST_CHECK_NE(t_const_userdef, test_lib::get_integer());
|
||||
BOOST_CHECK_NE(t_int, test_lib::get_user_defined_class());
|
||||
BOOST_CHECK_NE(t_const_int, test_lib::get_const_user_defined_class());
|
||||
|
||||
test_lib::accept_typeindex(t_int);
|
||||
}
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
//
|
||||
// Copyright Antony Polukhin, 2012-2013.
|
||||
//
|
||||
// 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_TEST_MODULE testing_both_test_module
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/type_index/type_index_minimal.hpp>
|
||||
|
||||
namespace my_namespace1 {
|
||||
class my_class{};
|
||||
}
|
||||
|
||||
|
||||
namespace my_namespace2 {
|
||||
class my_class{};
|
||||
}
|
||||
|
||||
#include "type_index_tests.ipp"
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
//
|
||||
// Copyright Antony Polukhin, 2012-2013.
|
||||
//
|
||||
// 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_TEST_MODULE testing_both_test_module
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/type_index/type_index_minimal.hpp>
|
||||
|
||||
#ifndef BOOST_NO_RTTI
|
||||
#error "This test must be run with disabled RTTI"
|
||||
#endif
|
||||
|
||||
namespace my_namespace1 {
|
||||
class my_class{};
|
||||
}
|
||||
|
||||
|
||||
namespace my_namespace2 {
|
||||
class my_class{};
|
||||
}
|
||||
|
||||
#include "type_index_tests.ipp"
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
//
|
||||
// Copyright Antony Polukhin, 2012-2013.
|
||||
//
|
||||
// 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_TEST_MODULE type_index_test_module
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
// Byapssing internal assertion for correct header inclusion
|
||||
#define BOOST_TYPE_INDEX_TYPE_INDEX_MINIMAL_HPP
|
||||
|
||||
#include <boost/type_index/type_index_impl.hpp>
|
||||
|
||||
namespace my_namespace1 {
|
||||
class my_class{};
|
||||
}
|
||||
|
||||
|
||||
namespace my_namespace2 {
|
||||
class my_class{};
|
||||
}
|
||||
|
||||
#include "type_index_tests.ipp"
|
||||
@@ -1,301 +0,0 @@
|
||||
//
|
||||
// Copyright Antony Polukhin, 2012.
|
||||
//
|
||||
// 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/functional/hash.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
BOOST_AUTO_TEST_CASE(names_matches_type_id)
|
||||
{
|
||||
using namespace boost;
|
||||
BOOST_CHECK_EQUAL(type_id<int>().name_demangled(), "int");
|
||||
BOOST_CHECK_EQUAL(type_id<double>().name_demangled(), "double");
|
||||
|
||||
BOOST_CHECK_EQUAL(type_id<int>().name(), type_id<int>().name());
|
||||
BOOST_CHECK_NE(type_id<int>().name(), type_id<double>().name());
|
||||
BOOST_CHECK_NE(type_id<double>().name(), type_id<int>().name());
|
||||
BOOST_CHECK_EQUAL(type_id<double>().name(), type_id<double>().name());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(comparators_type_id)
|
||||
{
|
||||
using namespace boost;
|
||||
type_index t_int = type_id<int>();
|
||||
type_index t_double = type_id<double>();
|
||||
|
||||
BOOST_CHECK_EQUAL(t_int, t_int);
|
||||
BOOST_CHECK_LE(t_int, t_int);
|
||||
BOOST_CHECK_GE(t_int, t_int);
|
||||
BOOST_CHECK_NE(t_int, t_double);
|
||||
|
||||
BOOST_CHECK_LE(t_double, t_double);
|
||||
BOOST_CHECK_GE(t_double, t_double);
|
||||
BOOST_CHECK_NE(t_double, t_int);
|
||||
|
||||
BOOST_CHECK(t_double < t_int || t_int < t_double);
|
||||
BOOST_CHECK(t_double > t_int || t_int > t_double);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(hash_code_type_id)
|
||||
{
|
||||
using namespace boost;
|
||||
std::size_t t_int1 = type_id<int>().hash_code();
|
||||
std::size_t t_double1 = type_id<double>().hash_code();
|
||||
|
||||
std::size_t t_int2 = type_id<int>().hash_code();
|
||||
std::size_t t_double2 = type_id<double>().hash_code();
|
||||
|
||||
BOOST_CHECK_EQUAL(t_int1, t_int2);
|
||||
BOOST_CHECK_NE(t_int1, t_double2);
|
||||
BOOST_CHECK_LE(t_double1, t_double2);
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_RTTI
|
||||
|
||||
BOOST_AUTO_TEST_CASE(comparators_type_id_vs_type_info)
|
||||
{
|
||||
using namespace boost;
|
||||
type_index t_int = type_id<int>();
|
||||
|
||||
BOOST_CHECK(t_int == typeid(int));
|
||||
BOOST_CHECK(typeid(int) == t_int);
|
||||
BOOST_CHECK(t_int <= typeid(int));
|
||||
BOOST_CHECK(typeid(int) <= t_int);
|
||||
BOOST_CHECK(t_int >= typeid(int));
|
||||
BOOST_CHECK(typeid(int) >= t_int);
|
||||
|
||||
type_index t_double = type_id<double>();
|
||||
|
||||
BOOST_CHECK(t_double == typeid(double));
|
||||
BOOST_CHECK(typeid(double) == t_double);
|
||||
BOOST_CHECK(t_double <= typeid(double));
|
||||
BOOST_CHECK(typeid(double) <= t_double);
|
||||
BOOST_CHECK(t_double >= typeid(double));
|
||||
BOOST_CHECK(typeid(double) >= t_double);
|
||||
|
||||
if (t_double < t_int) {
|
||||
BOOST_CHECK(t_double < typeid(int));
|
||||
BOOST_CHECK(typeid(double) < t_int);
|
||||
BOOST_CHECK(typeid(int) > t_double);
|
||||
BOOST_CHECK(t_int > typeid(double));
|
||||
|
||||
|
||||
BOOST_CHECK(t_double <= typeid(int));
|
||||
BOOST_CHECK(typeid(double) <= t_int);
|
||||
BOOST_CHECK(typeid(int) >= t_double);
|
||||
BOOST_CHECK(t_int >= typeid(double));
|
||||
} else {
|
||||
BOOST_CHECK(t_double > typeid(int));
|
||||
BOOST_CHECK(typeid(double) > t_int);
|
||||
BOOST_CHECK(typeid(int) < t_double);
|
||||
BOOST_CHECK(t_int < typeid(double));
|
||||
|
||||
|
||||
BOOST_CHECK(t_double >= typeid(int));
|
||||
BOOST_CHECK(typeid(double) >= t_int);
|
||||
BOOST_CHECK(typeid(int) <= t_double);
|
||||
BOOST_CHECK(t_int <= typeid(double));
|
||||
}
|
||||
}
|
||||
|
||||
#endif // BOOST_NO_RTTI
|
||||
|
||||
template <class T1, class T2>
|
||||
static void test_with_modofiers_type_id() {
|
||||
using namespace boost;
|
||||
|
||||
type_index t1 = type_id_with_cvr<T1>();
|
||||
type_index t2 = type_id_with_cvr<T2>();
|
||||
|
||||
BOOST_CHECK_NE(t2, t1);
|
||||
BOOST_CHECK(t1 < t2 || t2 < t1);
|
||||
BOOST_CHECK(t1 > t2 || t2 > t1);
|
||||
|
||||
BOOST_CHECK_EQUAL(t1, type_id_with_cvr<T1>());
|
||||
BOOST_CHECK_EQUAL(t2, type_id_with_cvr<T2>());
|
||||
|
||||
BOOST_CHECK_EQUAL(t1.hash_code(), type_id_with_cvr<T1>().hash_code());
|
||||
BOOST_CHECK_EQUAL(t2.hash_code(), type_id_with_cvr<T2>().hash_code());
|
||||
|
||||
BOOST_CHECK_NE(t1.hash_code(), type_id_with_cvr<T2>().hash_code());
|
||||
BOOST_CHECK_NE(t2.hash_code(), type_id_with_cvr<T1>().hash_code());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(type_id_storing_modifiers)
|
||||
{
|
||||
test_with_modofiers_type_id<int, const int>();
|
||||
test_with_modofiers_type_id<int, const int&>();
|
||||
test_with_modofiers_type_id<int, int&>();
|
||||
test_with_modofiers_type_id<int, volatile int>();
|
||||
test_with_modofiers_type_id<int, volatile int&>();
|
||||
test_with_modofiers_type_id<int, const volatile int>();
|
||||
test_with_modofiers_type_id<int, const volatile int&>();
|
||||
|
||||
test_with_modofiers_type_id<const int, int>();
|
||||
test_with_modofiers_type_id<const int, const int&>();
|
||||
test_with_modofiers_type_id<const int, int&>();
|
||||
test_with_modofiers_type_id<const int, volatile int>();
|
||||
test_with_modofiers_type_id<const int, volatile int&>();
|
||||
test_with_modofiers_type_id<const int, const volatile int>();
|
||||
test_with_modofiers_type_id<const int, const volatile int&>();
|
||||
|
||||
test_with_modofiers_type_id<const int&, int>();
|
||||
test_with_modofiers_type_id<const int&, const int>();
|
||||
test_with_modofiers_type_id<const int&, int&>();
|
||||
test_with_modofiers_type_id<const int&, volatile int>();
|
||||
test_with_modofiers_type_id<const int&, volatile int&>();
|
||||
test_with_modofiers_type_id<const int&, const volatile int>();
|
||||
test_with_modofiers_type_id<const int&, const volatile int&>();
|
||||
|
||||
test_with_modofiers_type_id<int&, const int>();
|
||||
test_with_modofiers_type_id<int&, const int&>();
|
||||
test_with_modofiers_type_id<int&, int>();
|
||||
test_with_modofiers_type_id<int&, volatile int>();
|
||||
test_with_modofiers_type_id<int&, volatile int&>();
|
||||
test_with_modofiers_type_id<int&, const volatile int>();
|
||||
test_with_modofiers_type_id<int&, const volatile int&>();
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
test_with_modofiers_type_id<int&&, const int>();
|
||||
test_with_modofiers_type_id<int&&, const int&>();
|
||||
test_with_modofiers_type_id<int&&, const int&&>();
|
||||
test_with_modofiers_type_id<int&&, int>();
|
||||
test_with_modofiers_type_id<int&&, volatile int>();
|
||||
test_with_modofiers_type_id<int&&, volatile int&>();
|
||||
test_with_modofiers_type_id<int&&, volatile int&&>();
|
||||
test_with_modofiers_type_id<int&&, const volatile int>();
|
||||
test_with_modofiers_type_id<int&&, const volatile int&>();
|
||||
test_with_modofiers_type_id<int&&, const volatile int&&>();
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static void test_storing_nonstoring_modifiers() {
|
||||
using namespace boost;
|
||||
|
||||
type_index t1 = type_id_with_cvr<T>();
|
||||
type_index t2 = type_id<T>();
|
||||
|
||||
BOOST_CHECK_EQUAL(t2, t1);
|
||||
BOOST_CHECK_EQUAL(t1, t2);
|
||||
BOOST_CHECK(t1 <= t2);
|
||||
BOOST_CHECK(t1 >= t2);
|
||||
BOOST_CHECK(t2 <= t1);
|
||||
BOOST_CHECK(t2 >= t1);
|
||||
|
||||
BOOST_CHECK_EQUAL(t2.name_demangled(), t1.name_demangled());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(type_id_storing_modifiers_vs_nonstoring)
|
||||
{
|
||||
test_storing_nonstoring_modifiers<int>();
|
||||
test_storing_nonstoring_modifiers<my_namespace1::my_class>();
|
||||
test_storing_nonstoring_modifiers<my_namespace2::my_class>();
|
||||
|
||||
boost::type_index t1 = boost::type_id_with_cvr<const int>();
|
||||
boost::type_index t2 = boost::type_id<int>();
|
||||
BOOST_CHECK_NE(t2, t1);
|
||||
BOOST_CHECK(t1.name_demangled() == "const int" || t1.name_demangled() == "int const");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(type_index_stream_operator_via_lexical_cast_testing)
|
||||
{
|
||||
using namespace boost;
|
||||
std::string s_int1 = lexical_cast<std::string>(type_id<int>());
|
||||
BOOST_CHECK_EQUAL(s_int1, "int");
|
||||
|
||||
std::string s_double1 = lexical_cast<std::string>(type_id<double>());
|
||||
BOOST_CHECK_EQUAL(s_double1, "double");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(type_index_stripping_cvr_test)
|
||||
{
|
||||
using namespace boost;
|
||||
|
||||
BOOST_CHECK_EQUAL(type_id<int>(), type_id<const int>());
|
||||
BOOST_CHECK_EQUAL(type_id<int>(), type_id<const volatile int>());
|
||||
BOOST_CHECK_EQUAL(type_id<int>(), type_id<const volatile int&>());
|
||||
|
||||
BOOST_CHECK_EQUAL(type_id<int>(), type_id<int&>());
|
||||
BOOST_CHECK_EQUAL(type_id<int>(), type_id<volatile int>());
|
||||
BOOST_CHECK_EQUAL(type_id<int>(), type_id<volatile int&>());
|
||||
|
||||
|
||||
BOOST_CHECK_EQUAL(type_id<double>(), type_id<const double>());
|
||||
BOOST_CHECK_EQUAL(type_id<double>(), type_id<const volatile double>());
|
||||
BOOST_CHECK_EQUAL(type_id<double>(), type_id<const volatile double&>());
|
||||
|
||||
BOOST_CHECK_EQUAL(type_id<double>(), type_id<double&>());
|
||||
BOOST_CHECK_EQUAL(type_id<double>(), type_id<volatile double>());
|
||||
BOOST_CHECK_EQUAL(type_id<double>(), type_id<volatile double&>());
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(type_index_user_defined_class_test)
|
||||
{
|
||||
using namespace boost;
|
||||
|
||||
BOOST_CHECK_EQUAL(type_id<my_namespace1::my_class>(), type_id<my_namespace1::my_class>());
|
||||
BOOST_CHECK_EQUAL(type_id<my_namespace2::my_class>(), type_id<my_namespace2::my_class>());
|
||||
|
||||
#ifndef BOOST_NO_RTTI
|
||||
BOOST_CHECK(type_id<my_namespace1::my_class>() == typeid(my_namespace1::my_class));
|
||||
BOOST_CHECK(type_id<my_namespace2::my_class>() == typeid(my_namespace2::my_class));
|
||||
BOOST_CHECK(typeid(my_namespace1::my_class) == type_id<my_namespace1::my_class>());
|
||||
BOOST_CHECK(typeid(my_namespace2::my_class) == type_id<my_namespace2::my_class>());
|
||||
#endif
|
||||
|
||||
BOOST_CHECK_NE(type_id<my_namespace1::my_class>(), type_id<my_namespace2::my_class>());
|
||||
BOOST_CHECK_NE(
|
||||
type_id<my_namespace1::my_class>().name_demangled().find("my_namespace1::my_class"),
|
||||
std::string::npos);
|
||||
}
|
||||
|
||||
|
||||
#ifndef BOOST_NO_RTTI
|
||||
|
||||
class A { public: virtual ~A(){} };
|
||||
class B: public A{};
|
||||
class C: public B {};
|
||||
|
||||
BOOST_AUTO_TEST_CASE(comparators_type_id_rtti_only)
|
||||
{
|
||||
C c1;
|
||||
B b1;
|
||||
A* pc1 = &c1;
|
||||
A& rc1 = c1;
|
||||
A* pb1 = &b1;
|
||||
A& rb1 = b1;
|
||||
BOOST_CHECK(typeid(rc1) == typeid(*pc1));
|
||||
BOOST_CHECK(typeid(rb1) == typeid(*pb1));
|
||||
|
||||
BOOST_CHECK(typeid(rc1) != typeid(*pb1));
|
||||
BOOST_CHECK(typeid(rb1) != typeid(*pc1));
|
||||
|
||||
BOOST_CHECK(typeid(&rc1) == typeid(pb1));
|
||||
BOOST_CHECK(typeid(&rb1) == typeid(pc1));
|
||||
|
||||
BOOST_CHECK_EQUAL(boost::type_id_rtti_only(rc1), boost::type_id_rtti_only(*pc1));
|
||||
BOOST_CHECK_EQUAL(boost::type_id_rtti_only(rb1), boost::type_id_rtti_only(*pb1));
|
||||
|
||||
BOOST_CHECK_NE(boost::type_id_rtti_only(rc1), boost::type_id_rtti_only(*pb1));
|
||||
BOOST_CHECK_NE(boost::type_id_rtti_only(rb1), boost::type_id_rtti_only(*pc1));
|
||||
BOOST_CHECK_EQUAL(boost::type_id_rtti_only(&rc1), boost::type_id_rtti_only(pb1));
|
||||
BOOST_CHECK_EQUAL(boost::type_id_rtti_only(&rb1), boost::type_id_rtti_only(pc1));
|
||||
|
||||
BOOST_CHECK(boost::type_id_rtti_only(rc1) == typeid(*pc1));
|
||||
BOOST_CHECK(boost::type_id_rtti_only(rb1) == typeid(*pb1));
|
||||
|
||||
BOOST_CHECK(boost::type_id_rtti_only(rc1) != typeid(*pb1));
|
||||
BOOST_CHECK(boost::type_id_rtti_only(rb1) != typeid(*pc1));
|
||||
BOOST_CHECK(boost::type_id_rtti_only(&rc1) == typeid(pb1));
|
||||
BOOST_CHECK(boost::type_id_rtti_only(&rb1) == typeid(pc1));
|
||||
}
|
||||
|
||||
#endif // BOOST_NO_RTTI
|
||||
|
||||
|
||||
15
meta/libraries.json
Normal file
15
meta/libraries.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"key": "type_index",
|
||||
"name": "Type Index",
|
||||
"authors": [
|
||||
"Antony Polukhin"
|
||||
],
|
||||
"maintainers": [
|
||||
"Antony Polukhin <antoshkka -at- gmail.com>"
|
||||
],
|
||||
"description": "Runtime/Compile time copyable type info.",
|
||||
"category": [
|
||||
"Emulation"
|
||||
],
|
||||
"cxxstd": "11"
|
||||
}
|
||||
9
patched/README.md
Normal file
9
patched/README.md
Normal file
@@ -0,0 +1,9 @@
|
||||
patches for Boost libraries to work without RTTI
|
||||
==========
|
||||
|
||||
Here are the patches that are TESTED and work well with RTTI disabled and enabled.
|
||||
Patches add tests for some of the libraries to make sure that library compile and work without RTTI.
|
||||
|
||||
Patches remove duplicate code, improve output, allow compilation with RTTI off...
|
||||
|
||||
Libraries Boost.Graph, Boost.XPressive, Boost.PropertyMap and others may also benefit from TypeIndex library.
|
||||
239
patched/any.hpp
239
patched/any.hpp
@@ -1,239 +0,0 @@
|
||||
// See http://www.boost.org/libs/any for Documentation.
|
||||
|
||||
#ifndef BOOST_ANY_INCLUDED
|
||||
#define BOOST_ANY_INCLUDED
|
||||
|
||||
// what: variant type boost::any
|
||||
// who: contributed by Kevlin Henney,
|
||||
// with features contributed and bugs found by
|
||||
// Ed Brey, Mark Rodgers, Peter Dimov, and James Curran
|
||||
// when: July 2001
|
||||
// where: tested with BCC 5.5, MSVC 6.0, and g++ 2.95
|
||||
|
||||
#include <algorithm>
|
||||
#include <typeinfo>
|
||||
|
||||
#include "boost/config.hpp"
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/type_traits/is_reference.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_index.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
class any
|
||||
{
|
||||
public: // structors
|
||||
|
||||
any()
|
||||
: content(0)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename ValueType>
|
||||
any(const ValueType & value)
|
||||
: content(new holder<ValueType>(value))
|
||||
{
|
||||
}
|
||||
|
||||
any(const any & other)
|
||||
: content(other.content ? other.content->clone() : 0)
|
||||
{
|
||||
}
|
||||
|
||||
~any()
|
||||
{
|
||||
delete content;
|
||||
}
|
||||
|
||||
public: // modifiers
|
||||
|
||||
any & swap(any & rhs)
|
||||
{
|
||||
std::swap(content, rhs.content);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename ValueType>
|
||||
any & operator=(const ValueType & rhs)
|
||||
{
|
||||
any(rhs).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
any & operator=(any rhs)
|
||||
{
|
||||
rhs.swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
public: // queries
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return !content;
|
||||
}
|
||||
|
||||
type_index type() const
|
||||
{
|
||||
return content ? content->type() : type_id<void>();
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
|
||||
private: // types
|
||||
#else
|
||||
public: // types (public so any_cast can be non-friend)
|
||||
#endif
|
||||
|
||||
class placeholder
|
||||
{
|
||||
public: // structors
|
||||
|
||||
virtual ~placeholder()
|
||||
{
|
||||
}
|
||||
|
||||
public: // queries
|
||||
|
||||
virtual type_index type() const = 0;
|
||||
|
||||
virtual placeholder * clone() const = 0;
|
||||
|
||||
};
|
||||
|
||||
template<typename ValueType>
|
||||
class holder : public placeholder
|
||||
{
|
||||
public: // structors
|
||||
|
||||
holder(const ValueType & value)
|
||||
: held(value)
|
||||
{
|
||||
}
|
||||
|
||||
public: // queries
|
||||
|
||||
virtual type_index type() const
|
||||
{
|
||||
return type_id<ValueType>();
|
||||
}
|
||||
|
||||
virtual placeholder * clone() const
|
||||
{
|
||||
return new holder(held);
|
||||
}
|
||||
|
||||
public: // representation
|
||||
|
||||
ValueType held;
|
||||
|
||||
private: // intentionally left unimplemented
|
||||
holder & operator=(const holder &);
|
||||
};
|
||||
|
||||
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
|
||||
|
||||
private: // representation
|
||||
|
||||
template<typename ValueType>
|
||||
friend ValueType * any_cast(any *);
|
||||
|
||||
template<typename ValueType>
|
||||
friend ValueType * unsafe_any_cast(any *);
|
||||
|
||||
#else
|
||||
|
||||
public: // representation (public so any_cast can be non-friend)
|
||||
|
||||
#endif
|
||||
|
||||
placeholder * content;
|
||||
|
||||
};
|
||||
|
||||
class bad_any_cast : public std::bad_cast
|
||||
{
|
||||
public:
|
||||
virtual const char * what() const throw()
|
||||
{
|
||||
return "boost::bad_any_cast: "
|
||||
"failed conversion using boost::any_cast";
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ValueType>
|
||||
ValueType * any_cast(any * operand)
|
||||
{
|
||||
return operand &&
|
||||
operand->type() == type_id<ValueType>()
|
||||
? &static_cast<any::holder<ValueType> *>(operand->content)->held
|
||||
: 0;
|
||||
}
|
||||
|
||||
template<typename ValueType>
|
||||
inline const ValueType * any_cast(const any * operand)
|
||||
{
|
||||
return any_cast<ValueType>(const_cast<any *>(operand));
|
||||
}
|
||||
|
||||
template<typename ValueType>
|
||||
ValueType any_cast(any & operand)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref;
|
||||
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
// If 'nonref' is still reference type, it means the user has not
|
||||
// specialized 'remove_reference'.
|
||||
|
||||
// Please use BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION macro
|
||||
// to generate specialization of remove_reference for your class
|
||||
// See type traits library documentation for details
|
||||
BOOST_STATIC_ASSERT(!is_reference<nonref>::value);
|
||||
#endif
|
||||
|
||||
nonref * result = any_cast<nonref>(&operand);
|
||||
if(!result)
|
||||
boost::throw_exception(bad_any_cast());
|
||||
return *result;
|
||||
}
|
||||
|
||||
template<typename ValueType>
|
||||
inline ValueType any_cast(const any & operand)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref;
|
||||
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
// The comment in the above version of 'any_cast' explains when this
|
||||
// assert is fired and what to do.
|
||||
BOOST_STATIC_ASSERT(!is_reference<nonref>::value);
|
||||
#endif
|
||||
|
||||
return any_cast<const nonref &>(const_cast<any &>(operand));
|
||||
}
|
||||
|
||||
// Note: The "unsafe" versions of any_cast are not part of the
|
||||
// public interface and may be removed at any time. They are
|
||||
// required where we know what type is stored in the any and can't
|
||||
// use type_id<>() comparison, e.g., when our types may travel across
|
||||
// different shared libraries.
|
||||
template<typename ValueType>
|
||||
inline ValueType * unsafe_any_cast(any * operand)
|
||||
{
|
||||
return &static_cast<any::holder<ValueType> *>(operand->content)->held;
|
||||
}
|
||||
|
||||
template<typename ValueType>
|
||||
inline const ValueType * unsafe_any_cast(const any * operand)
|
||||
{
|
||||
return unsafe_any_cast<ValueType>(const_cast<any *>(operand));
|
||||
}
|
||||
}
|
||||
|
||||
// Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved.
|
||||
//
|
||||
// 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)
|
||||
|
||||
#endif
|
||||
151
patched/boost_detail_sp_typeinfo.patch
Normal file
151
patched/boost_detail_sp_typeinfo.patch
Normal file
@@ -0,0 +1,151 @@
|
||||
From b77c0af6af8bc4797defc3627878acc3cf7a6f39 Mon Sep 17 00:00:00 2001
|
||||
From: Antony Polukhin <antoshkka@gmail.com>
|
||||
Date: Thu, 20 Feb 2014 17:57:24 +0400
|
||||
Subject: [PATCH] detail/sp_typeinfo.hpp now uses TypeIndex
|
||||
|
||||
---
|
||||
include/boost/detail/sp_typeinfo.hpp | 123 +++--------------------------------
|
||||
1 file changed, 8 insertions(+), 115 deletions(-)
|
||||
|
||||
diff --git a/include/boost/detail/sp_typeinfo.hpp b/include/boost/detail/sp_typeinfo.hpp
|
||||
index 43fae78..fbdf86d 100644
|
||||
--- a/include/boost/detail/sp_typeinfo.hpp
|
||||
+++ b/include/boost/detail/sp_typeinfo.hpp
|
||||
@@ -10,126 +10,19 @@
|
||||
// detail/sp_typeinfo.hpp
|
||||
//
|
||||
// Copyright 2007 Peter Dimov
|
||||
+// Copyright 2014 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 <boost/config.hpp>
|
||||
+#include <boost/type_index.hpp>
|
||||
+namespace boost { namespace detail {
|
||||
+
|
||||
+typedef boost::typeind::type_info sp_typeinfo;
|
||||
+
|
||||
+}} // namespace boost::detail
|
||||
|
||||
-#if defined( BOOST_NO_TYPEID )
|
||||
-
|
||||
-#include <boost/current_function.hpp>
|
||||
-#include <functional>
|
||||
-
|
||||
-namespace boost
|
||||
-{
|
||||
-
|
||||
-namespace detail
|
||||
-{
|
||||
-
|
||||
-class sp_typeinfo
|
||||
-{
|
||||
-private:
|
||||
-
|
||||
- sp_typeinfo( sp_typeinfo const& );
|
||||
- sp_typeinfo& operator=( sp_typeinfo const& );
|
||||
-
|
||||
- char const * name_;
|
||||
-
|
||||
-public:
|
||||
-
|
||||
- explicit sp_typeinfo( char const * name ): name_( name )
|
||||
- {
|
||||
- }
|
||||
-
|
||||
- bool operator==( sp_typeinfo const& rhs ) const
|
||||
- {
|
||||
- return this == &rhs;
|
||||
- }
|
||||
-
|
||||
- bool operator!=( sp_typeinfo const& rhs ) const
|
||||
- {
|
||||
- return this != &rhs;
|
||||
- }
|
||||
-
|
||||
- bool before( sp_typeinfo const& rhs ) const
|
||||
- {
|
||||
- return std::less< sp_typeinfo const* >()( this, &rhs );
|
||||
- }
|
||||
-
|
||||
- char const* name() const
|
||||
- {
|
||||
- return name_;
|
||||
- }
|
||||
-};
|
||||
-
|
||||
-template<class T> struct sp_typeid_
|
||||
-{
|
||||
- static sp_typeinfo ti_;
|
||||
-
|
||||
- static char const * name()
|
||||
- {
|
||||
- return BOOST_CURRENT_FUNCTION;
|
||||
- }
|
||||
-};
|
||||
-
|
||||
-#if defined(__SUNPRO_CC)
|
||||
-// see #4199, the Sun Studio compiler gets confused about static initialization
|
||||
-// constructor arguments. But an assignment works just fine.
|
||||
-template<class T> sp_typeinfo sp_typeid_< T >::ti_ = sp_typeid_< T >::name();
|
||||
-#else
|
||||
-template<class T> sp_typeinfo sp_typeid_< T >::ti_(sp_typeid_< T >::name());
|
||||
-#endif
|
||||
-
|
||||
-template<class T> struct sp_typeid_< T & >: sp_typeid_< T >
|
||||
-{
|
||||
-};
|
||||
-
|
||||
-template<class T> struct sp_typeid_< T const >: sp_typeid_< T >
|
||||
-{
|
||||
-};
|
||||
-
|
||||
-template<class T> struct sp_typeid_< T volatile >: sp_typeid_< T >
|
||||
-{
|
||||
-};
|
||||
-
|
||||
-template<class T> struct sp_typeid_< T const volatile >: sp_typeid_< T >
|
||||
-{
|
||||
-};
|
||||
-
|
||||
-} // namespace detail
|
||||
-
|
||||
-} // namespace boost
|
||||
-
|
||||
-#define BOOST_SP_TYPEID(T) (boost::detail::sp_typeid_<T>::ti_)
|
||||
-
|
||||
-#else
|
||||
-
|
||||
-#include <typeinfo>
|
||||
-
|
||||
-namespace boost
|
||||
-{
|
||||
-
|
||||
-namespace detail
|
||||
-{
|
||||
-
|
||||
-#if defined( BOOST_NO_STD_TYPEINFO )
|
||||
-
|
||||
-typedef ::type_info sp_typeinfo;
|
||||
-
|
||||
-#else
|
||||
-
|
||||
-typedef std::type_info sp_typeinfo;
|
||||
-
|
||||
-#endif
|
||||
-
|
||||
-} // namespace detail
|
||||
-
|
||||
-} // namespace boost
|
||||
-
|
||||
-#define BOOST_SP_TYPEID(T) typeid(T)
|
||||
-
|
||||
-#endif
|
||||
+#define BOOST_SP_TYPEID(T) (boost::typeind::type_id<T>().type_info())
|
||||
|
||||
#endif // #ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED
|
||||
--
|
||||
1.8.5.3
|
||||
|
||||
156
patched/boost_exception.patch
Normal file
156
patched/boost_exception.patch
Normal file
@@ -0,0 +1,156 @@
|
||||
From 8f57d59bfbc978673a2493a90b4f3e7e54ddbf18 Mon Sep 17 00:00:00 2001
|
||||
From: Antony Polukhin <antoshkka@gmail.com>
|
||||
Date: Thu, 20 Feb 2014 18:30:11 +0400
|
||||
Subject: [PATCH] Boost.Exception now uses TypeIndex to reduce duplicate code
|
||||
and simplify name demanglings
|
||||
|
||||
---
|
||||
include/boost/exception/detail/type_info.hpp | 43 +++-------------------
|
||||
include/boost/exception/diagnostic_information.hpp | 2 +-
|
||||
include/boost/exception/exception.hpp | 3 +-
|
||||
include/boost/exception/info.hpp | 2 +-
|
||||
test/Jamfile.v2 | 2 +
|
||||
5 files changed, 12 insertions(+), 40 deletions(-)
|
||||
|
||||
diff --git a/include/boost/exception/detail/type_info.hpp b/include/boost/exception/detail/type_info.hpp
|
||||
index 6e5942d..a247b71 100644
|
||||
--- a/include/boost/exception/detail/type_info.hpp
|
||||
+++ b/include/boost/exception/detail/type_info.hpp
|
||||
@@ -12,13 +12,7 @@
|
||||
#pragma warning(push,1)
|
||||
#endif
|
||||
|
||||
-#include <boost/detail/sp_typeinfo.hpp>
|
||||
-#include <boost/current_function.hpp>
|
||||
-#include <boost/config.hpp>
|
||||
-//#ifndef BOOST_NO_TYPEID
|
||||
-//#include <boost/units/detail/utility.hpp>
|
||||
-//#endif
|
||||
-#include <string>
|
||||
+#include <boost/type_index.hpp>
|
||||
|
||||
namespace
|
||||
boost
|
||||
@@ -28,11 +22,7 @@ boost
|
||||
std::string
|
||||
tag_type_name()
|
||||
{
|
||||
-#ifdef BOOST_NO_TYPEID
|
||||
- return BOOST_CURRENT_FUNCTION;
|
||||
-#else
|
||||
- return /*units::detail::demangle*/(typeid(T*).name());
|
||||
-#endif
|
||||
+ return boost::typeind::type_id<T*>().pretty_name();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
@@ -40,41 +30,20 @@ boost
|
||||
std::string
|
||||
type_name()
|
||||
{
|
||||
-#ifdef BOOST_NO_TYPEID
|
||||
- return BOOST_CURRENT_FUNCTION;
|
||||
-#else
|
||||
- return /*units::detail::demangle*/(typeid(T).name());
|
||||
-#endif
|
||||
+ return boost::typeind::type_id<T>().pretty_name();
|
||||
}
|
||||
|
||||
namespace
|
||||
exception_detail
|
||||
{
|
||||
- struct
|
||||
- type_info_
|
||||
- {
|
||||
- detail::sp_typeinfo const * type_;
|
||||
-
|
||||
- explicit
|
||||
- type_info_( detail::sp_typeinfo const & type ):
|
||||
- type_(&type)
|
||||
- {
|
||||
- }
|
||||
-
|
||||
- friend
|
||||
- bool
|
||||
- operator<( type_info_ const & a, type_info_ const & b )
|
||||
- {
|
||||
- return 0!=(a.type_->before(*b.type_));
|
||||
- }
|
||||
- };
|
||||
+ typedef boost::typeind::type_index type_info_;
|
||||
}
|
||||
}
|
||||
|
||||
-#define BOOST_EXCEPTION_STATIC_TYPEID(T) ::boost::exception_detail::type_info_(BOOST_SP_TYPEID(T))
|
||||
+#define BOOST_EXCEPTION_STATIC_TYPEID(T) ::boost::typeind::type_id<T>()
|
||||
|
||||
#ifndef BOOST_NO_RTTI
|
||||
-#define BOOST_EXCEPTION_DYNAMIC_TYPEID(x) ::boost::exception_detail::type_info_(typeid(x))
|
||||
+#define BOOST_EXCEPTION_DYNAMIC_TYPEID(x) ::boost::typeind::type_id_runtime(x)
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
|
||||
diff --git a/include/boost/exception/diagnostic_information.hpp b/include/boost/exception/diagnostic_information.hpp
|
||||
index 2f5cb88..0f8b5e8 100644
|
||||
--- a/include/boost/exception/diagnostic_information.hpp
|
||||
+++ b/include/boost/exception/diagnostic_information.hpp
|
||||
@@ -151,7 +151,7 @@ boost
|
||||
#ifndef BOOST_NO_RTTI
|
||||
if ( verbose )
|
||||
tmp << std::string("Dynamic exception type: ") <<
|
||||
- /*units::detail::demangle*/((be?(BOOST_EXCEPTION_DYNAMIC_TYPEID(*be)):(BOOST_EXCEPTION_DYNAMIC_TYPEID(*se))).type_->name()) << '\n';
|
||||
+ /*units::detail::demangle*/((be?(BOOST_EXCEPTION_DYNAMIC_TYPEID(*be)):(BOOST_EXCEPTION_DYNAMIC_TYPEID(*se)))) << '\n';
|
||||
#endif
|
||||
if( with_what && se && verbose )
|
||||
tmp << "std::exception::what: " << wh << '\n';
|
||||
diff --git a/include/boost/exception/exception.hpp b/include/boost/exception/exception.hpp
|
||||
index 9f20a04..53c341f 100644
|
||||
--- a/include/boost/exception/exception.hpp
|
||||
+++ b/include/boost/exception/exception.hpp
|
||||
@@ -12,6 +12,8 @@
|
||||
#pragma warning(push,1)
|
||||
#endif
|
||||
|
||||
+#include <boost/exception/detail/type_info.hpp>
|
||||
+
|
||||
namespace
|
||||
boost
|
||||
{
|
||||
@@ -151,7 +153,6 @@ boost
|
||||
exception_detail
|
||||
{
|
||||
class error_info_base;
|
||||
- struct type_info_;
|
||||
|
||||
struct
|
||||
error_info_container
|
||||
diff --git a/include/boost/exception/info.hpp b/include/boost/exception/info.hpp
|
||||
index edbf058..e0f4950 100644
|
||||
--- a/include/boost/exception/info.hpp
|
||||
+++ b/include/boost/exception/info.hpp
|
||||
@@ -96,7 +96,7 @@ boost
|
||||
{
|
||||
shared_ptr<error_info_base> const & p = i->second;
|
||||
#ifndef BOOST_NO_RTTI
|
||||
- BOOST_ASSERT( *BOOST_EXCEPTION_DYNAMIC_TYPEID(*p).type_==*ti.type_ );
|
||||
+ BOOST_ASSERT(BOOST_EXCEPTION_DYNAMIC_TYPEID(*p)==ti );
|
||||
#endif
|
||||
return p;
|
||||
}
|
||||
diff --git a/test/Jamfile.v2 b/test/Jamfile.v2
|
||||
index d2dfcd6..5bd076d 100644
|
||||
--- a/test/Jamfile.v2
|
||||
+++ b/test/Jamfile.v2
|
||||
@@ -35,7 +35,9 @@ run enable_error_info_test.cpp helper1.cpp ;
|
||||
run throw_exception_test.cpp helper2.cpp ;
|
||||
run errno_test.cpp ;
|
||||
run error_info_test.cpp ;
|
||||
+run error_info_test.cpp : : : <rtti>off : error_info_test_rtti ;
|
||||
run diagnostic_information_test.cpp ;
|
||||
+run diagnostic_information_test.cpp : : : <rtti>off : diagnostic_information_test_rtti ;
|
||||
run refcount_ptr_test.cpp ;
|
||||
run current_exception_cast_test.cpp ;
|
||||
run no_exceptions_test.cpp : : : <exception-handling>off ;
|
||||
--
|
||||
1.8.5.3
|
||||
|
||||
26
patched/boost_smart_ptr.patch
Normal file
26
patched/boost_smart_ptr.patch
Normal file
@@ -0,0 +1,26 @@
|
||||
From 03194eefcb9c3314054855d28bd9a90d3188768d Mon Sep 17 00:00:00 2001
|
||||
From: Antony Polukhin <antoshkka@gmail.com>
|
||||
Date: Thu, 20 Feb 2014 18:50:10 +0400
|
||||
Subject: [PATCH] Use TypeIndex features in Boost.SharedPtr to avoid type_info
|
||||
related bugs
|
||||
|
||||
---
|
||||
include/boost/smart_ptr/detail/sp_counted_impl.hpp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/include/boost/smart_ptr/detail/sp_counted_impl.hpp b/include/boost/smart_ptr/detail/sp_counted_impl.hpp
|
||||
index a7b43ae..5955036 100644
|
||||
--- a/include/boost/smart_ptr/detail/sp_counted_impl.hpp
|
||||
+++ b/include/boost/smart_ptr/detail/sp_counted_impl.hpp
|
||||
@@ -155,7 +155,7 @@ public:
|
||||
|
||||
virtual void * get_deleter( detail::sp_typeinfo const & ti )
|
||||
{
|
||||
- return ti == BOOST_SP_TYPEID(D)? &reinterpret_cast<char&>( del ): 0;
|
||||
+ return ti == boost::typeind::type_id<D>()? &reinterpret_cast<char&>( del ): 0;
|
||||
}
|
||||
|
||||
virtual void * get_untyped_deleter()
|
||||
--
|
||||
1.8.5.3
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
#ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED
|
||||
#define BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
// detail/sp_typeinfo.hpp
|
||||
//
|
||||
// Copyright 2007 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/config.hpp>
|
||||
|
||||
#if defined( BOOST_NO_TYPEID )
|
||||
|
||||
#include <boost/current_function.hpp>
|
||||
#include <functional>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class sp_typeinfo
|
||||
{
|
||||
private:
|
||||
|
||||
sp_typeinfo( sp_typeinfo const& );
|
||||
sp_typeinfo& operator=( sp_typeinfo const& );
|
||||
|
||||
char const * name_;
|
||||
|
||||
public:
|
||||
|
||||
explicit sp_typeinfo( char const * name ): name_( name )
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==( sp_typeinfo const& rhs ) const
|
||||
{
|
||||
return this == &rhs;
|
||||
}
|
||||
|
||||
bool operator!=( sp_typeinfo const& rhs ) const
|
||||
{
|
||||
return this != &rhs;
|
||||
}
|
||||
|
||||
bool before( sp_typeinfo const& rhs ) const
|
||||
{
|
||||
return std::less< sp_typeinfo const* >()( this, &rhs );
|
||||
}
|
||||
|
||||
char const* name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
};
|
||||
|
||||
template<class T> struct sp_typeid_
|
||||
{
|
||||
static sp_typeinfo ti_;
|
||||
|
||||
static char const * name()
|
||||
{
|
||||
return BOOST_CURRENT_FUNCTION;
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(__SUNPRO_CC)
|
||||
// see #4199, the Sun Studio compiler gets confused about static initialization
|
||||
// constructor arguments. But an assignment works just fine.
|
||||
template<class T> sp_typeinfo sp_typeid_< T >::ti_ = sp_typeid_< T >::name();
|
||||
#else
|
||||
template<class T> sp_typeinfo sp_typeid_< T >::ti_(sp_typeid_< T >::name());
|
||||
#endif
|
||||
|
||||
template<class T> struct sp_typeid_< T & >: sp_typeid_< T >
|
||||
{
|
||||
};
|
||||
|
||||
template<class T> struct sp_typeid_< T const >: sp_typeid_< T >
|
||||
{
|
||||
};
|
||||
|
||||
template<class T> struct sp_typeid_< T volatile >: sp_typeid_< T >
|
||||
{
|
||||
};
|
||||
|
||||
template<class T> struct sp_typeid_< T const volatile >: sp_typeid_< T >
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#define BOOST_SP_TYPEID(T) (boost::detail::sp_typeid_<T>::ti_)
|
||||
|
||||
#else
|
||||
|
||||
#include <typeinfo>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
#if defined( BOOST_NO_STD_TYPEINFO )
|
||||
|
||||
typedef ::type_info sp_typeinfo;
|
||||
|
||||
#else
|
||||
|
||||
typedef std::type_info sp_typeinfo;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#define BOOST_SP_TYPEID(T) typeid(T)
|
||||
|
||||
#endif
|
||||
|
||||
#endif // #ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED
|
||||
@@ -1,352 +0,0 @@
|
||||
// Copyright (C) 2006 Tiago de Paula Peixoto <tiago@forked.de>
|
||||
// Copyright (C) 2004 The Trustees of Indiana University.
|
||||
//
|
||||
// Use, modification and distribution is 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)
|
||||
//
|
||||
// Authors: Douglas Gregor
|
||||
// Andrew Lumsdaine
|
||||
// Tiago de Paula Peixoto
|
||||
|
||||
#ifndef BOOST_GRAPH_GRAPHML_HPP
|
||||
#define BOOST_GRAPH_GRAPHML_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/any.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/graph/dll_import_export.hpp>
|
||||
#include <boost/graph/graphviz.hpp> // for exceptions
|
||||
#include <boost/type_index.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/mpl/find.hpp>
|
||||
#include <boost/mpl/for_each.hpp>
|
||||
#include <boost/property_tree/detail/xml_parser_utils.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <exception>
|
||||
#include <sstream>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Graph reader exceptions
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
struct parse_error: public graph_exception
|
||||
{
|
||||
parse_error(const std::string& err) {error = err; statement = "parse error: " + error;}
|
||||
virtual ~parse_error() throw() {}
|
||||
virtual const char* what() const throw() {return statement.c_str();}
|
||||
std::string statement;
|
||||
std::string error;
|
||||
};
|
||||
|
||||
|
||||
class mutate_graph
|
||||
{
|
||||
public:
|
||||
virtual ~mutate_graph() {}
|
||||
virtual bool is_directed() const = 0;
|
||||
|
||||
virtual boost::any do_add_vertex() = 0;
|
||||
virtual std::pair<boost::any,bool> do_add_edge(boost::any source, boost::any target) = 0;
|
||||
|
||||
virtual void
|
||||
set_graph_property(const std::string& name, const std::string& value, const std::string& value_type) = 0;
|
||||
|
||||
virtual void
|
||||
set_vertex_property(const std::string& name, boost::any vertex, const std::string& value, const std::string& value_type) = 0;
|
||||
|
||||
virtual void
|
||||
set_edge_property(const std::string& name, boost::any edge, const std::string& value, const std::string& value_type) = 0;
|
||||
};
|
||||
|
||||
template<typename MutableGraph>
|
||||
class mutate_graph_impl : public mutate_graph
|
||||
{
|
||||
typedef typename graph_traits<MutableGraph>::vertex_descriptor vertex_descriptor;
|
||||
typedef typename graph_traits<MutableGraph>::edge_descriptor edge_descriptor;
|
||||
|
||||
public:
|
||||
mutate_graph_impl(MutableGraph& g, dynamic_properties& dp)
|
||||
: m_g(g), m_dp(dp) { }
|
||||
|
||||
bool is_directed() const
|
||||
{
|
||||
return is_convertible<typename graph_traits<MutableGraph>::directed_category,
|
||||
directed_tag>::value;
|
||||
}
|
||||
|
||||
virtual any do_add_vertex()
|
||||
{
|
||||
return any(add_vertex(m_g));
|
||||
}
|
||||
|
||||
virtual std::pair<any,bool> do_add_edge(any source, any target)
|
||||
{
|
||||
std::pair<edge_descriptor,bool> retval = add_edge(any_cast<vertex_descriptor>(source),
|
||||
any_cast<vertex_descriptor>(target), m_g);
|
||||
return std::make_pair(any(retval.first), retval.second);
|
||||
}
|
||||
|
||||
virtual void
|
||||
set_graph_property(const std::string& name, const std::string& value, const std::string& value_type)
|
||||
{
|
||||
bool type_found = false;
|
||||
try
|
||||
{
|
||||
mpl::for_each<value_types>(put_property<MutableGraph,value_types>
|
||||
(name, m_dp, m_g, value, value_type, m_type_names, type_found));
|
||||
}
|
||||
catch (bad_lexical_cast)
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(
|
||||
parse_error("invalid value \"" + value + "\" for key " +
|
||||
name + " of type " + value_type));
|
||||
}
|
||||
if (!type_found)
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(
|
||||
parse_error("unrecognized type \"" + value_type +
|
||||
"\" for key " + name));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
virtual void
|
||||
set_vertex_property(const std::string& name, any vertex, const std::string& value, const std::string& value_type)
|
||||
{
|
||||
bool type_found = false;
|
||||
try
|
||||
{
|
||||
mpl::for_each<value_types>(put_property<vertex_descriptor,value_types>
|
||||
(name, m_dp, any_cast<vertex_descriptor>(vertex),
|
||||
value, value_type, m_type_names, type_found));
|
||||
}
|
||||
catch (bad_lexical_cast)
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(
|
||||
parse_error("invalid value \"" + value + "\" for key " +
|
||||
name + " of type " + value_type));
|
||||
}
|
||||
if (!type_found)
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(
|
||||
parse_error("unrecognized type \"" + value_type +
|
||||
"\" for key " + name));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
virtual void
|
||||
set_edge_property(const std::string& name, any edge, const std::string& value, const std::string& value_type)
|
||||
{
|
||||
bool type_found = false;
|
||||
try
|
||||
{
|
||||
mpl::for_each<value_types>(put_property<edge_descriptor,value_types>
|
||||
(name, m_dp, any_cast<edge_descriptor>(edge),
|
||||
value, value_type, m_type_names, type_found));
|
||||
}
|
||||
catch (bad_lexical_cast)
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(
|
||||
parse_error("invalid value \"" + value + "\" for key " +
|
||||
name + " of type " + value_type));
|
||||
}
|
||||
if (!type_found)
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(
|
||||
parse_error("unrecognized type \"" + value_type +
|
||||
"\" for key " + name));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Key, typename ValueVector>
|
||||
class put_property
|
||||
{
|
||||
public:
|
||||
put_property(const std::string& name, dynamic_properties& dp, const Key& key,
|
||||
const std::string& value, const std::string& value_type,
|
||||
const char** type_names, bool& type_found)
|
||||
: m_name(name), m_dp(dp), m_key(key), m_value(value),
|
||||
m_value_type(value_type), m_type_names(type_names),
|
||||
m_type_found(type_found) {}
|
||||
template <class Value>
|
||||
void operator()(Value)
|
||||
{
|
||||
if (m_value_type == m_type_names[mpl::find<ValueVector,Value>::type::pos::value])
|
||||
{
|
||||
put(m_name, m_dp, m_key, lexical_cast<Value>(m_value));
|
||||
m_type_found = true;
|
||||
}
|
||||
}
|
||||
private:
|
||||
const std::string& m_name;
|
||||
dynamic_properties& m_dp;
|
||||
const Key& m_key;
|
||||
const std::string& m_value;
|
||||
const std::string& m_value_type;
|
||||
const char** m_type_names;
|
||||
bool& m_type_found;
|
||||
};
|
||||
|
||||
protected:
|
||||
MutableGraph& m_g;
|
||||
dynamic_properties& m_dp;
|
||||
typedef mpl::vector<bool, int, long, float, double, std::string> value_types;
|
||||
static const char* m_type_names[];
|
||||
};
|
||||
|
||||
template<typename MutableGraph>
|
||||
const char* mutate_graph_impl<MutableGraph>::m_type_names[] = {"boolean", "int", "long", "float", "double", "string"};
|
||||
|
||||
void BOOST_GRAPH_DECL
|
||||
read_graphml(std::istream& in, mutate_graph& g);
|
||||
|
||||
template<typename MutableGraph>
|
||||
void
|
||||
read_graphml(std::istream& in, MutableGraph& g, dynamic_properties& dp)
|
||||
{
|
||||
mutate_graph_impl<MutableGraph> mg(g,dp);
|
||||
read_graphml(in, mg);
|
||||
}
|
||||
|
||||
template <typename Types>
|
||||
class get_type_name
|
||||
{
|
||||
public:
|
||||
get_type_name(const type_index& type, const char** type_names, std::string& type_name)
|
||||
: m_type(type), m_type_names(type_names), m_type_name(type_name) {}
|
||||
template <typename Type>
|
||||
void operator()(Type)
|
||||
{
|
||||
if (type_id<Type>() == m_type)
|
||||
m_type_name = m_type_names[mpl::find<Types,Type>::type::pos::value];
|
||||
}
|
||||
private:
|
||||
const type_index m_type;
|
||||
const char** m_type_names;
|
||||
std::string &m_type_name;
|
||||
};
|
||||
|
||||
|
||||
template <typename Graph, typename VertexIndexMap>
|
||||
void
|
||||
write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index,
|
||||
const dynamic_properties& dp, bool ordered_vertices=false)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::directed_category directed_category;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
|
||||
|
||||
using boost::property_tree::xml_parser::encode_char_entities;
|
||||
|
||||
BOOST_STATIC_CONSTANT(bool,
|
||||
graph_is_directed =
|
||||
(is_convertible<directed_category*, directed_tag*>::value));
|
||||
|
||||
out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
<< "<graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd\">\n";
|
||||
|
||||
typedef mpl::vector<bool, short, unsigned short, int, unsigned int, long, unsigned long, long long, unsigned long long, float, double, long double, std::string> value_types;
|
||||
const char* type_names[] = {"boolean", "int", "int", "int", "int", "long", "long", "long", "long", "float", "double", "double", "string"};
|
||||
std::map<std::string, std::string> graph_key_ids;
|
||||
std::map<std::string, std::string> vertex_key_ids;
|
||||
std::map<std::string, std::string> edge_key_ids;
|
||||
int key_count = 0;
|
||||
|
||||
// Output keys
|
||||
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
|
||||
{
|
||||
std::string key_id = "key" + lexical_cast<std::string>(key_count++);
|
||||
if (i->second->key() == type_id<Graph*>())
|
||||
graph_key_ids[i->first] = key_id;
|
||||
else if (i->second->key() == type_id<vertex_descriptor>())
|
||||
vertex_key_ids[i->first] = key_id;
|
||||
else if (i->second->key() == type_id<edge_descriptor>())
|
||||
edge_key_ids[i->first] = key_id;
|
||||
else
|
||||
continue;
|
||||
std::string type_name = "string";
|
||||
mpl::for_each<value_types>(get_type_name<value_types>(i->second->value(), type_names, type_name));
|
||||
out << " <key id=\"" << encode_char_entities(key_id) << "\" for=\""
|
||||
<< (i->second->key() == type_id<Graph*>() ? "graph" : (i->second->key() == type_id<vertex_descriptor>() ? "node" : "edge")) << "\""
|
||||
<< " attr.name=\"" << i->first << "\""
|
||||
<< " attr.type=\"" << type_name << "\""
|
||||
<< " />\n";
|
||||
}
|
||||
|
||||
out << " <graph id=\"G\" edgedefault=\""
|
||||
<< (graph_is_directed ? "directed" : "undirected") << "\""
|
||||
<< " parse.nodeids=\"" << (ordered_vertices ? "canonical" : "free") << "\""
|
||||
<< " parse.edgeids=\"canonical\" parse.order=\"nodesfirst\">\n";
|
||||
|
||||
// Output graph data
|
||||
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
|
||||
{
|
||||
if (i->second->key() == type_id<Graph*>())
|
||||
{
|
||||
// The const_cast here is just to get typeid correct for property
|
||||
// map key; the graph should not be mutated using it.
|
||||
out << " <data key=\"" << graph_key_ids[i->first] << "\">"
|
||||
<< encode_char_entities(i->second->get_string(const_cast<Graph*>(&g))) << "</data>\n";
|
||||
}
|
||||
}
|
||||
|
||||
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
|
||||
vertex_iterator v, v_end;
|
||||
for (boost::tie(v, v_end) = vertices(g); v != v_end; ++v)
|
||||
{
|
||||
out << " <node id=\"n" << get(vertex_index, *v) << "\">\n";
|
||||
// Output data
|
||||
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
|
||||
{
|
||||
if (i->second->key() == type_id<vertex_descriptor>())
|
||||
{
|
||||
out << " <data key=\"" << vertex_key_ids[i->first] << "\">"
|
||||
<< encode_char_entities(i->second->get_string(*v)) << "</data>\n";
|
||||
}
|
||||
}
|
||||
out << " </node>\n";
|
||||
}
|
||||
|
||||
typedef typename graph_traits<Graph>::edge_iterator edge_iterator;
|
||||
edge_iterator e, e_end;
|
||||
typename graph_traits<Graph>::edges_size_type edge_count = 0;
|
||||
for (boost::tie(e, e_end) = edges(g); e != e_end; ++e)
|
||||
{
|
||||
out << " <edge id=\"e" << edge_count++ << "\" source=\"n"
|
||||
<< get(vertex_index, source(*e, g)) << "\" target=\"n"
|
||||
<< get(vertex_index, target(*e, g)) << "\">\n";
|
||||
|
||||
// Output data
|
||||
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
|
||||
{
|
||||
if (i->second->key() == type_id<edge_descriptor>())
|
||||
{
|
||||
out << " <data key=\"" << edge_key_ids[i->first] << "\">"
|
||||
<< encode_char_entities(i->second->get_string(*e)) << "</data>\n";
|
||||
}
|
||||
}
|
||||
out << " </edge>\n";
|
||||
}
|
||||
|
||||
out << " </graph>\n"
|
||||
<< "</graphml>\n";
|
||||
}
|
||||
|
||||
|
||||
template <typename Graph>
|
||||
void
|
||||
write_graphml(std::ostream& out, const Graph& g, const dynamic_properties& dp,
|
||||
bool ordered_vertices=false)
|
||||
{
|
||||
write_graphml(out, g, get(vertex_index, g), dp, ordered_vertices);
|
||||
}
|
||||
|
||||
} // boost namespace
|
||||
|
||||
#endif // BOOST_GRAPH_GRAPHML_HPP
|
||||
@@ -1,858 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 2001 University of Notre Dame.
|
||||
// Copyright 2003 Jeremy Siek
|
||||
// Authors: Lie-Quan Lee, Jeremy Siek, and Douglas Gregor
|
||||
//
|
||||
// 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_GRAPHVIZ_HPP
|
||||
#define BOOST_GRAPHVIZ_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <stdio.h> // for FILE
|
||||
#include <boost/property_map/property_map.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/properties.hpp>
|
||||
#include <boost/graph/subgraph.hpp>
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
#include <boost/property_map/dynamic_property_map.hpp>
|
||||
#include <boost/graph/overloading.hpp>
|
||||
#include <boost/graph/dll_import_export.hpp>
|
||||
#include <boost/spirit/include/classic_multi_pass.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/xpressive/xpressive_static.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/type_index.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <typename directed_category>
|
||||
struct graphviz_io_traits {
|
||||
static std::string name() {
|
||||
return "digraph";
|
||||
}
|
||||
static std::string delimiter() {
|
||||
return "->";
|
||||
} };
|
||||
|
||||
template <>
|
||||
struct graphviz_io_traits <undirected_tag> {
|
||||
static std::string name() {
|
||||
return "graph";
|
||||
}
|
||||
static std::string delimiter() {
|
||||
return "--";
|
||||
}
|
||||
};
|
||||
|
||||
struct default_writer {
|
||||
void operator()(std::ostream&) const {
|
||||
}
|
||||
template <class VorE>
|
||||
void operator()(std::ostream&, const VorE&) const {
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline std::string escape_dot_string(const T& obj) {
|
||||
using namespace boost::xpressive;
|
||||
static sregex valid_unquoted_id = (((alpha | '_') >> *_w) | (!as_xpr('-') >> (('.' >> *_d) | (+_d >> !('.' >> *_d)))));
|
||||
std::string s(boost::lexical_cast<std::string>(obj));
|
||||
if (regex_match(s, valid_unquoted_id)) {
|
||||
return s;
|
||||
} else {
|
||||
boost::algorithm::replace_all(s, "\"", "\\\"");
|
||||
return "\"" + s + "\"";
|
||||
}
|
||||
}
|
||||
|
||||
template <class Name>
|
||||
class label_writer {
|
||||
public:
|
||||
label_writer(Name _name) : name(_name) {}
|
||||
template <class VertexOrEdge>
|
||||
void operator()(std::ostream& out, const VertexOrEdge& v) const {
|
||||
out << "[label=" << escape_dot_string(get(name, v)) << "]";
|
||||
}
|
||||
private:
|
||||
Name name;
|
||||
};
|
||||
template <class Name>
|
||||
inline label_writer<Name>
|
||||
make_label_writer(Name n) {
|
||||
return label_writer<Name>(n);
|
||||
}
|
||||
|
||||
enum edge_attribute_t { edge_attribute = 1111 };
|
||||
enum vertex_attribute_t { vertex_attribute = 2222 };
|
||||
enum graph_graph_attribute_t { graph_graph_attribute = 3333 };
|
||||
enum graph_vertex_attribute_t { graph_vertex_attribute = 4444 };
|
||||
enum graph_edge_attribute_t { graph_edge_attribute = 5555 };
|
||||
|
||||
BOOST_INSTALL_PROPERTY(edge, attribute);
|
||||
BOOST_INSTALL_PROPERTY(vertex, attribute);
|
||||
BOOST_INSTALL_PROPERTY(graph, graph_attribute);
|
||||
BOOST_INSTALL_PROPERTY(graph, vertex_attribute);
|
||||
BOOST_INSTALL_PROPERTY(graph, edge_attribute);
|
||||
|
||||
|
||||
template <class Attribute>
|
||||
inline void write_attributes(const Attribute& attr, std::ostream& out) {
|
||||
typename Attribute::const_iterator i, iend;
|
||||
i = attr.begin();
|
||||
iend = attr.end();
|
||||
|
||||
while ( i != iend ) {
|
||||
out << i->first << "=" << escape_dot_string(i->second);
|
||||
++i;
|
||||
if ( i != iend )
|
||||
out << ", ";
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Attributes>
|
||||
inline void write_all_attributes(Attributes attributes,
|
||||
const std::string& name,
|
||||
std::ostream& out)
|
||||
{
|
||||
typename Attributes::const_iterator i = attributes.begin(),
|
||||
end = attributes.end();
|
||||
if (i != end) {
|
||||
out << name << " [\n";
|
||||
write_attributes(attributes, out);
|
||||
out << "];\n";
|
||||
}
|
||||
}
|
||||
|
||||
inline void write_all_attributes(detail::error_property_not_found,
|
||||
const std::string&,
|
||||
std::ostream&)
|
||||
{
|
||||
// Do nothing - no attributes exist
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename GraphGraphAttributes,
|
||||
typename GraphNodeAttributes,
|
||||
typename GraphEdgeAttributes>
|
||||
struct graph_attributes_writer
|
||||
{
|
||||
graph_attributes_writer(GraphGraphAttributes gg,
|
||||
GraphNodeAttributes gn,
|
||||
GraphEdgeAttributes ge)
|
||||
: g_attributes(gg), n_attributes(gn), e_attributes(ge) { }
|
||||
|
||||
void operator()(std::ostream& out) const {
|
||||
write_all_attributes(g_attributes, "graph", out);
|
||||
write_all_attributes(n_attributes, "node", out);
|
||||
write_all_attributes(e_attributes, "edge", out);
|
||||
}
|
||||
GraphGraphAttributes g_attributes;
|
||||
GraphNodeAttributes n_attributes;
|
||||
GraphEdgeAttributes e_attributes;
|
||||
};
|
||||
|
||||
template <typename GAttrMap, typename NAttrMap, typename EAttrMap>
|
||||
graph_attributes_writer<GAttrMap, NAttrMap, EAttrMap>
|
||||
make_graph_attributes_writer(const GAttrMap& g_attr, const NAttrMap& n_attr,
|
||||
const EAttrMap& e_attr) {
|
||||
return graph_attributes_writer<GAttrMap, NAttrMap, EAttrMap>
|
||||
(g_attr, n_attr, e_attr);
|
||||
}
|
||||
|
||||
|
||||
template <typename Graph>
|
||||
graph_attributes_writer
|
||||
<typename graph_property<Graph, graph_graph_attribute_t>::type,
|
||||
typename graph_property<Graph, graph_vertex_attribute_t>::type,
|
||||
typename graph_property<Graph, graph_edge_attribute_t>::type>
|
||||
make_graph_attributes_writer(const Graph& g)
|
||||
{
|
||||
typedef typename graph_property<Graph, graph_graph_attribute_t>::type
|
||||
GAttrMap;
|
||||
typedef typename graph_property<Graph, graph_vertex_attribute_t>::type
|
||||
NAttrMap;
|
||||
typedef typename graph_property<Graph, graph_edge_attribute_t>::type
|
||||
EAttrMap;
|
||||
GAttrMap gam = get_property(g, graph_graph_attribute);
|
||||
NAttrMap nam = get_property(g, graph_vertex_attribute);
|
||||
EAttrMap eam = get_property(g, graph_edge_attribute);
|
||||
graph_attributes_writer<GAttrMap, NAttrMap, EAttrMap> writer(gam, nam, eam);
|
||||
return writer;
|
||||
}
|
||||
|
||||
template <typename AttributeMap>
|
||||
struct attributes_writer {
|
||||
attributes_writer(AttributeMap attr)
|
||||
: attributes(attr) { }
|
||||
|
||||
template <class VorE>
|
||||
void operator()(std::ostream& out, const VorE& e) const {
|
||||
this->write_attribute(out, attributes[e]);
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename AttributeSequence>
|
||||
void write_attribute(std::ostream& out,
|
||||
const AttributeSequence& seq) const
|
||||
{
|
||||
if (!seq.empty()) {
|
||||
out << "[";
|
||||
write_attributes(seq, out);
|
||||
out << "]";
|
||||
}
|
||||
}
|
||||
|
||||
void write_attribute(std::ostream&,
|
||||
detail::error_property_not_found) const
|
||||
{
|
||||
}
|
||||
AttributeMap attributes;
|
||||
};
|
||||
|
||||
template <typename Graph>
|
||||
attributes_writer
|
||||
<typename property_map<Graph, edge_attribute_t>::const_type>
|
||||
make_edge_attributes_writer(const Graph& g)
|
||||
{
|
||||
typedef typename property_map<Graph, edge_attribute_t>::const_type
|
||||
EdgeAttributeMap;
|
||||
return attributes_writer<EdgeAttributeMap>(get(edge_attribute, g));
|
||||
}
|
||||
|
||||
template <typename Graph>
|
||||
attributes_writer
|
||||
<typename property_map<Graph, vertex_attribute_t>::const_type>
|
||||
make_vertex_attributes_writer(const Graph& g)
|
||||
{
|
||||
typedef typename property_map<Graph, vertex_attribute_t>::const_type
|
||||
VertexAttributeMap;
|
||||
return attributes_writer<VertexAttributeMap>(get(vertex_attribute, g));
|
||||
}
|
||||
|
||||
template <typename Graph, typename VertexPropertiesWriter,
|
||||
typename EdgePropertiesWriter, typename GraphPropertiesWriter,
|
||||
typename VertexID>
|
||||
inline void
|
||||
write_graphviz
|
||||
(std::ostream& out, const Graph& g,
|
||||
VertexPropertiesWriter vpw,
|
||||
EdgePropertiesWriter epw,
|
||||
GraphPropertiesWriter gpw,
|
||||
VertexID vertex_id
|
||||
BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag))
|
||||
{
|
||||
BOOST_CONCEPT_ASSERT((EdgeListGraphConcept<Graph>));
|
||||
|
||||
typedef typename graph_traits<Graph>::directed_category cat_type;
|
||||
typedef graphviz_io_traits<cat_type> Traits;
|
||||
std::string name = "G";
|
||||
out << Traits::name() << " " << escape_dot_string(name) << " {" << std::endl;
|
||||
|
||||
gpw(out); //print graph properties
|
||||
|
||||
typename graph_traits<Graph>::vertex_iterator i, end;
|
||||
|
||||
for(boost::tie(i,end) = vertices(g); i != end; ++i) {
|
||||
out << escape_dot_string(get(vertex_id, *i));
|
||||
vpw(out, *i); //print vertex attributes
|
||||
out << ";" << std::endl;
|
||||
}
|
||||
typename graph_traits<Graph>::edge_iterator ei, edge_end;
|
||||
for(boost::tie(ei, edge_end) = edges(g); ei != edge_end; ++ei) {
|
||||
out << escape_dot_string(get(vertex_id, source(*ei, g))) << Traits::delimiter() << escape_dot_string(get(vertex_id, target(*ei, g))) << " ";
|
||||
epw(out, *ei); //print edge attributes
|
||||
out << ";" << std::endl;
|
||||
}
|
||||
out << "}" << std::endl;
|
||||
}
|
||||
|
||||
template <typename Graph, typename VertexPropertiesWriter,
|
||||
typename EdgePropertiesWriter, typename GraphPropertiesWriter>
|
||||
inline void
|
||||
write_graphviz(std::ostream& out, const Graph& g,
|
||||
VertexPropertiesWriter vpw,
|
||||
EdgePropertiesWriter epw,
|
||||
GraphPropertiesWriter gpw
|
||||
BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag))
|
||||
{ write_graphviz(out, g, vpw, epw, gpw, get(vertex_index, g)); }
|
||||
|
||||
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
|
||||
// ambiguous overload problem with VC++
|
||||
template <typename Graph>
|
||||
inline void
|
||||
write_graphviz(std::ostream& out, const Graph& g
|
||||
BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag))
|
||||
{
|
||||
default_writer dw;
|
||||
default_writer gw;
|
||||
write_graphviz(out, g, dw, dw, gw);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename Graph, typename VertexWriter>
|
||||
inline void
|
||||
write_graphviz(std::ostream& out, const Graph& g, VertexWriter vw
|
||||
BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag))
|
||||
{
|
||||
default_writer dw;
|
||||
default_writer gw;
|
||||
write_graphviz(out, g, vw, dw, gw);
|
||||
}
|
||||
|
||||
template <typename Graph, typename VertexWriter, typename EdgeWriter>
|
||||
inline void
|
||||
write_graphviz(std::ostream& out, const Graph& g,
|
||||
VertexWriter vw, EdgeWriter ew
|
||||
BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag))
|
||||
{
|
||||
default_writer gw;
|
||||
write_graphviz(out, g, vw, ew, gw);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class Graph_, class RandomAccessIterator, class VertexID>
|
||||
void write_graphviz_subgraph (std::ostream& out,
|
||||
const subgraph<Graph_>& g,
|
||||
RandomAccessIterator vertex_marker,
|
||||
RandomAccessIterator edge_marker,
|
||||
VertexID vertex_id)
|
||||
{
|
||||
typedef subgraph<Graph_> Graph;
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
typedef typename graph_traits<Graph>::directed_category cat_type;
|
||||
typedef graphviz_io_traits<cat_type> Traits;
|
||||
|
||||
typedef typename graph_property<Graph, graph_name_t>::type NameType;
|
||||
const NameType& g_name = get_property(g, graph_name);
|
||||
|
||||
if ( g.is_root() )
|
||||
out << Traits::name() ;
|
||||
else
|
||||
out << "subgraph";
|
||||
|
||||
out << " " << escape_dot_string(g_name) << " {" << std::endl;
|
||||
|
||||
typename Graph::const_children_iterator i_child, j_child;
|
||||
|
||||
//print graph/node/edge attributes
|
||||
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
|
||||
typedef typename graph_property<Graph, graph_graph_attribute_t>::type
|
||||
GAttrMap;
|
||||
typedef typename graph_property<Graph, graph_vertex_attribute_t>::type
|
||||
NAttrMap;
|
||||
typedef typename graph_property<Graph, graph_edge_attribute_t>::type
|
||||
EAttrMap;
|
||||
GAttrMap gam = get_property(g, graph_graph_attribute);
|
||||
NAttrMap nam = get_property(g, graph_vertex_attribute);
|
||||
EAttrMap eam = get_property(g, graph_edge_attribute);
|
||||
graph_attributes_writer<GAttrMap, NAttrMap, EAttrMap> writer(gam, nam, eam);
|
||||
writer(out);
|
||||
#else
|
||||
make_graph_attributes_writer(g)(out);
|
||||
#endif
|
||||
|
||||
//print subgraph
|
||||
for ( boost::tie(i_child,j_child) = g.children();
|
||||
i_child != j_child; ++i_child )
|
||||
write_graphviz_subgraph(out, *i_child, vertex_marker, edge_marker,
|
||||
vertex_id);
|
||||
|
||||
// Print out vertices and edges not in the subgraphs.
|
||||
|
||||
typename graph_traits<Graph>::vertex_iterator i, end;
|
||||
typename graph_traits<Graph>::edge_iterator ei, edge_end;
|
||||
|
||||
for(boost::tie(i,end) = vertices(g); i != end; ++i) {
|
||||
Vertex v = g.local_to_global(*i);
|
||||
int pos = get(vertex_id, v);
|
||||
if ( vertex_marker[pos] ) {
|
||||
vertex_marker[pos] = false;
|
||||
out << escape_dot_string(pos);
|
||||
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
|
||||
typedef typename property_map<Graph, vertex_attribute_t>::const_type
|
||||
VertexAttributeMap;
|
||||
attributes_writer<VertexAttributeMap> vawriter(get(vertex_attribute,
|
||||
g.root()));
|
||||
vawriter(out, v);
|
||||
#else
|
||||
make_vertex_attributes_writer(g.root())(out, v);
|
||||
#endif
|
||||
out << ";" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
for (boost::tie(ei, edge_end) = edges(g); ei != edge_end; ++ei) {
|
||||
Vertex u = g.local_to_global(source(*ei,g)),
|
||||
v = g.local_to_global(target(*ei, g));
|
||||
int pos = get(get(edge_index, g.root()), g.local_to_global(*ei));
|
||||
if ( edge_marker[pos] ) {
|
||||
edge_marker[pos] = false;
|
||||
out << escape_dot_string(get(vertex_id, u)) << " " << Traits::delimiter()
|
||||
<< " " << escape_dot_string(get(vertex_id, v));
|
||||
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
|
||||
typedef typename property_map<Graph, edge_attribute_t>::const_type
|
||||
EdgeAttributeMap;
|
||||
attributes_writer<EdgeAttributeMap> eawriter(get(edge_attribute, g));
|
||||
eawriter(out, *ei);
|
||||
#else
|
||||
make_edge_attributes_writer(g)(out, *ei); //print edge properties
|
||||
#endif
|
||||
out << ";" << std::endl;
|
||||
}
|
||||
}
|
||||
out << "}" << std::endl;
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
// requires graph_name graph property
|
||||
template <typename Graph>
|
||||
void write_graphviz(std::ostream& out, const subgraph<Graph>& g) {
|
||||
std::vector<bool> edge_marker(num_edges(g), true);
|
||||
std::vector<bool> vertex_marker(num_vertices(g), true);
|
||||
|
||||
detail::write_graphviz_subgraph(out, g,
|
||||
vertex_marker.begin(),
|
||||
edge_marker.begin(),
|
||||
get(vertex_index, g));
|
||||
}
|
||||
|
||||
template <typename Graph>
|
||||
void write_graphviz(const std::string& filename, const subgraph<Graph>& g) {
|
||||
std::ofstream out(filename.c_str());
|
||||
std::vector<bool> edge_marker(num_edges(g), true);
|
||||
std::vector<bool> vertex_marker(num_vertices(g), true);
|
||||
|
||||
detail::write_graphviz_subgraph(out, g,
|
||||
vertex_marker.begin(),
|
||||
edge_marker.begin(),
|
||||
get(vertex_index, g));
|
||||
}
|
||||
|
||||
template <typename Graph, typename VertexID>
|
||||
void write_graphviz(std::ostream& out, const subgraph<Graph>& g,
|
||||
VertexID vertex_id)
|
||||
{
|
||||
std::vector<bool> edge_marker(num_edges(g), true);
|
||||
std::vector<bool> vertex_marker(num_vertices(g), true);
|
||||
|
||||
detail::write_graphviz_subgraph(out, g,
|
||||
vertex_marker.begin(),
|
||||
edge_marker.begin(),
|
||||
vertex_id);
|
||||
}
|
||||
|
||||
template <typename Graph, typename VertexID>
|
||||
void write_graphviz(const std::string& filename, const subgraph<Graph>& g,
|
||||
VertexID vertex_id)
|
||||
{
|
||||
std::ofstream out(filename.c_str());
|
||||
std::vector<bool> edge_marker(num_edges(g), true);
|
||||
std::vector<bool> vertex_marker(num_vertices(g), true);
|
||||
|
||||
detail::write_graphviz_subgraph(out, g,
|
||||
vertex_marker.begin(),
|
||||
edge_marker.begin(),
|
||||
vertex_id);
|
||||
}
|
||||
|
||||
#if 0
|
||||
// This interface has not worked for a long time
|
||||
typedef std::map<std::string, std::string> GraphvizAttrList;
|
||||
|
||||
typedef property<vertex_attribute_t, GraphvizAttrList>
|
||||
GraphvizVertexProperty;
|
||||
|
||||
typedef property<edge_attribute_t, GraphvizAttrList,
|
||||
property<edge_index_t, int> >
|
||||
GraphvizEdgeProperty;
|
||||
|
||||
typedef property<graph_graph_attribute_t, GraphvizAttrList,
|
||||
property<graph_vertex_attribute_t, GraphvizAttrList,
|
||||
property<graph_edge_attribute_t, GraphvizAttrList,
|
||||
property<graph_name_t, std::string> > > >
|
||||
GraphvizGraphProperty;
|
||||
|
||||
typedef subgraph<adjacency_list<vecS,
|
||||
vecS, directedS,
|
||||
GraphvizVertexProperty,
|
||||
GraphvizEdgeProperty,
|
||||
GraphvizGraphProperty> >
|
||||
GraphvizDigraph;
|
||||
|
||||
typedef subgraph<adjacency_list<vecS,
|
||||
vecS, undirectedS,
|
||||
GraphvizVertexProperty,
|
||||
GraphvizEdgeProperty,
|
||||
GraphvizGraphProperty> >
|
||||
GraphvizGraph;
|
||||
|
||||
// These four require linking the BGL-Graphviz library: libbgl-viz.a
|
||||
// from the /src directory.
|
||||
// Library has not existed for a while
|
||||
extern void read_graphviz(const std::string& file, GraphvizDigraph& g);
|
||||
extern void read_graphviz(FILE* file, GraphvizDigraph& g);
|
||||
|
||||
extern void read_graphviz(const std::string& file, GraphvizGraph& g);
|
||||
extern void read_graphviz(FILE* file, GraphvizGraph& g);
|
||||
#endif
|
||||
|
||||
class dynamic_properties_writer
|
||||
{
|
||||
public:
|
||||
dynamic_properties_writer(const dynamic_properties& dp) : dp(&dp) { }
|
||||
|
||||
template<typename Descriptor>
|
||||
void operator()(std::ostream& out, Descriptor key) const
|
||||
{
|
||||
bool first = true;
|
||||
for (dynamic_properties::const_iterator i = dp->begin();
|
||||
i != dp->end(); ++i) {
|
||||
if (type_id<Descriptor>() == i->second->key()) {
|
||||
if (first) out << " [";
|
||||
else out << ", ";
|
||||
first = false;
|
||||
|
||||
out << i->first << "=" << escape_dot_string(i->second->get_string(key));
|
||||
}
|
||||
}
|
||||
|
||||
if (!first) out << "]";
|
||||
}
|
||||
|
||||
private:
|
||||
const dynamic_properties* dp;
|
||||
};
|
||||
|
||||
class dynamic_vertex_properties_writer
|
||||
{
|
||||
public:
|
||||
dynamic_vertex_properties_writer(const dynamic_properties& dp,
|
||||
const std::string& node_id)
|
||||
: dp(&dp), node_id(&node_id) { }
|
||||
|
||||
template<typename Descriptor>
|
||||
void operator()(std::ostream& out, Descriptor key) const
|
||||
{
|
||||
bool first = true;
|
||||
for (dynamic_properties::const_iterator i = dp->begin();
|
||||
i != dp->end(); ++i) {
|
||||
if (type_id<Descriptor>(key) == i->second->key()
|
||||
&& i->first != *node_id) {
|
||||
if (first) out << " [";
|
||||
else out << ", ";
|
||||
first = false;
|
||||
|
||||
out << i->first << "=" << escape_dot_string(i->second->get_string(key));
|
||||
}
|
||||
}
|
||||
|
||||
if (!first) out << "]";
|
||||
}
|
||||
|
||||
private:
|
||||
const dynamic_properties* dp;
|
||||
const std::string* node_id;
|
||||
};
|
||||
|
||||
namespace graph { namespace detail {
|
||||
|
||||
template<typename Vertex>
|
||||
struct node_id_property_map
|
||||
{
|
||||
typedef std::string value_type;
|
||||
typedef value_type reference;
|
||||
typedef Vertex key_type;
|
||||
typedef readable_property_map_tag category;
|
||||
|
||||
node_id_property_map() {}
|
||||
|
||||
node_id_property_map(const dynamic_properties& dp,
|
||||
const std::string& node_id)
|
||||
: dp(&dp), node_id(&node_id) { }
|
||||
|
||||
const dynamic_properties* dp;
|
||||
const std::string* node_id;
|
||||
};
|
||||
|
||||
template<typename Vertex>
|
||||
inline std::string
|
||||
get(node_id_property_map<Vertex> pm,
|
||||
typename node_id_property_map<Vertex>::key_type v)
|
||||
{ return get(*pm.node_id, *pm.dp, v); }
|
||||
|
||||
} } // end namespace graph::detail
|
||||
|
||||
template<typename Graph>
|
||||
inline void
|
||||
write_graphviz_dp(std::ostream& out, const Graph& g,
|
||||
const dynamic_properties& dp,
|
||||
const std::string& node_id = "node_id"
|
||||
BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag))
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
write_graphviz_dp(out, g, dp, node_id,
|
||||
graph::detail::node_id_property_map<Vertex>(dp, node_id));
|
||||
}
|
||||
|
||||
template<typename Graph, typename VertexID>
|
||||
void
|
||||
write_graphviz_dp(std::ostream& out, const Graph& g,
|
||||
const dynamic_properties& dp, const std::string& node_id,
|
||||
VertexID id
|
||||
BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag))
|
||||
{
|
||||
write_graphviz
|
||||
(out, g,
|
||||
/*vertex_writer=*/dynamic_vertex_properties_writer(dp, node_id),
|
||||
/*edge_writer=*/dynamic_properties_writer(dp),
|
||||
/*graph_writer=*/default_writer(),
|
||||
id);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Graph reader exceptions
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
struct graph_exception : public std::exception {
|
||||
virtual ~graph_exception() throw() {}
|
||||
virtual const char* what() const throw() = 0;
|
||||
};
|
||||
|
||||
struct bad_parallel_edge : public graph_exception {
|
||||
std::string from;
|
||||
std::string to;
|
||||
mutable std::string statement;
|
||||
bad_parallel_edge(const std::string& i, const std::string& j) :
|
||||
from(i), to(j) {}
|
||||
|
||||
virtual ~bad_parallel_edge() throw() {}
|
||||
const char* what() const throw() {
|
||||
if(statement.empty())
|
||||
statement =
|
||||
std::string("Failed to add parallel edge: (")
|
||||
+ from + "," + to + ")\n";
|
||||
|
||||
return statement.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
struct directed_graph_error : public graph_exception {
|
||||
virtual ~directed_graph_error() throw() {}
|
||||
virtual const char* what() const throw() {
|
||||
return
|
||||
"read_graphviz: "
|
||||
"Tried to read a directed graph into an undirected graph.";
|
||||
}
|
||||
};
|
||||
|
||||
struct undirected_graph_error : public graph_exception {
|
||||
virtual ~undirected_graph_error() throw() {}
|
||||
virtual const char* what() const throw() {
|
||||
return
|
||||
"read_graphviz: "
|
||||
"Tried to read an undirected graph into a directed graph.";
|
||||
}
|
||||
};
|
||||
|
||||
struct bad_graphviz_syntax: public graph_exception {
|
||||
std::string errmsg;
|
||||
bad_graphviz_syntax(const std::string& errmsg)
|
||||
: errmsg(errmsg) {}
|
||||
const char* what() const throw () {return errmsg.c_str();}
|
||||
~bad_graphviz_syntax() throw () {};
|
||||
};
|
||||
|
||||
namespace detail { namespace graph {
|
||||
|
||||
typedef std::string id_t;
|
||||
typedef id_t node_t;
|
||||
|
||||
// edges are not uniquely determined by adjacent nodes
|
||||
class edge_t {
|
||||
int idx_;
|
||||
explicit edge_t(int i) : idx_(i) {}
|
||||
public:
|
||||
static edge_t new_edge() {
|
||||
static int idx = 0;
|
||||
return edge_t(idx++);
|
||||
};
|
||||
|
||||
bool operator==(const edge_t& rhs) const {
|
||||
return idx_ == rhs.idx_;
|
||||
}
|
||||
bool operator<(const edge_t& rhs) const {
|
||||
return idx_ < rhs.idx_;
|
||||
}
|
||||
};
|
||||
|
||||
class mutate_graph
|
||||
{
|
||||
public:
|
||||
virtual ~mutate_graph() {}
|
||||
virtual bool is_directed() const = 0;
|
||||
virtual void do_add_vertex(const node_t& node) = 0;
|
||||
|
||||
virtual void
|
||||
do_add_edge(const edge_t& edge, const node_t& source, const node_t& target)
|
||||
= 0;
|
||||
|
||||
virtual void
|
||||
set_node_property(const id_t& key, const node_t& node, const id_t& value) = 0;
|
||||
|
||||
virtual void
|
||||
set_edge_property(const id_t& key, const edge_t& edge, const id_t& value) = 0;
|
||||
|
||||
virtual void // RG: need new second parameter to support BGL subgraphs
|
||||
set_graph_property(const id_t& key, const id_t& value) = 0;
|
||||
};
|
||||
|
||||
template<typename MutableGraph>
|
||||
class mutate_graph_impl : public mutate_graph
|
||||
{
|
||||
typedef typename graph_traits<MutableGraph>::vertex_descriptor bgl_vertex_t;
|
||||
typedef typename graph_traits<MutableGraph>::edge_descriptor bgl_edge_t;
|
||||
|
||||
public:
|
||||
mutate_graph_impl(MutableGraph& graph, dynamic_properties& dp,
|
||||
std::string node_id_prop)
|
||||
: graph_(graph), dp_(dp), node_id_prop_(node_id_prop) { }
|
||||
|
||||
~mutate_graph_impl() {}
|
||||
|
||||
bool is_directed() const
|
||||
{
|
||||
return
|
||||
boost::is_convertible<
|
||||
typename boost::graph_traits<MutableGraph>::directed_category,
|
||||
boost::directed_tag>::value;
|
||||
}
|
||||
|
||||
virtual void do_add_vertex(const node_t& node)
|
||||
{
|
||||
// Add the node to the graph.
|
||||
bgl_vertex_t v = add_vertex(graph_);
|
||||
|
||||
// Set up a mapping from name to BGL vertex.
|
||||
bgl_nodes.insert(std::make_pair(node, v));
|
||||
|
||||
// node_id_prop_ allows the caller to see the real id names for nodes.
|
||||
put(node_id_prop_, dp_, v, node);
|
||||
}
|
||||
|
||||
void
|
||||
do_add_edge(const edge_t& edge, const node_t& source, const node_t& target)
|
||||
{
|
||||
std::pair<bgl_edge_t, bool> result =
|
||||
add_edge(bgl_nodes[source], bgl_nodes[target], graph_);
|
||||
|
||||
if(!result.second) {
|
||||
// In the case of no parallel edges allowed
|
||||
boost::throw_exception(bad_parallel_edge(source, target));
|
||||
} else {
|
||||
bgl_edges.insert(std::make_pair(edge, result.first));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
set_node_property(const id_t& key, const node_t& node, const id_t& value)
|
||||
{
|
||||
put(key, dp_, bgl_nodes[node], value);
|
||||
}
|
||||
|
||||
void
|
||||
set_edge_property(const id_t& key, const edge_t& edge, const id_t& value)
|
||||
{
|
||||
put(key, dp_, bgl_edges[edge], value);
|
||||
}
|
||||
|
||||
void
|
||||
set_graph_property(const id_t& key, const id_t& value)
|
||||
{
|
||||
/* RG: pointer to graph prevents copying */
|
||||
put(key, dp_, &graph_, value);
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
MutableGraph& graph_;
|
||||
dynamic_properties& dp_;
|
||||
std::string node_id_prop_;
|
||||
std::map<node_t, bgl_vertex_t> bgl_nodes;
|
||||
std::map<edge_t, bgl_edge_t> bgl_edges;
|
||||
};
|
||||
|
||||
} } } // end namespace boost::detail::graph
|
||||
|
||||
#ifdef BOOST_GRAPH_USE_SPIRIT_PARSER
|
||||
# ifndef BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS
|
||||
# define BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS
|
||||
# endif
|
||||
# include <boost/graph/detail/read_graphviz_spirit.hpp>
|
||||
#else // New default parser
|
||||
# include <boost/graph/detail/read_graphviz_new.hpp>
|
||||
#endif // BOOST_GRAPH_USE_SPIRIT_PARSER
|
||||
|
||||
namespace boost {
|
||||
|
||||
// Parse the passed string as a GraphViz dot file.
|
||||
template <typename MutableGraph>
|
||||
bool read_graphviz(const std::string& data,
|
||||
MutableGraph& graph,
|
||||
dynamic_properties& dp,
|
||||
std::string const& node_id = "node_id") {
|
||||
#ifdef BOOST_GRAPH_USE_SPIRIT_PARSER
|
||||
return read_graphviz_spirit(data.begin(), data.end(), graph, dp, node_id);
|
||||
#else // Non-Spirit parser
|
||||
return read_graphviz_new(data,graph,dp,node_id);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Parse the passed iterator range as a GraphViz dot file.
|
||||
template <typename InputIterator, typename MutableGraph>
|
||||
bool read_graphviz(InputIterator user_first,
|
||||
InputIterator user_last,
|
||||
MutableGraph& graph,
|
||||
dynamic_properties& dp,
|
||||
std::string const& node_id = "node_id") {
|
||||
#ifdef BOOST_GRAPH_USE_SPIRIT_PARSER
|
||||
typedef InputIterator is_t;
|
||||
typedef boost::spirit::classic::multi_pass<is_t> iterator_t;
|
||||
|
||||
iterator_t first(boost::spirit::classic::make_multi_pass(user_first));
|
||||
iterator_t last(boost::spirit::classic::make_multi_pass(user_last));
|
||||
|
||||
return read_graphviz_spirit(first, last, graph, dp, node_id);
|
||||
#else // Non-Spirit parser
|
||||
return read_graphviz_new(std::string(user_first, user_last), graph, dp, node_id);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Parse the passed stream as a GraphViz dot file.
|
||||
template <typename MutableGraph>
|
||||
bool read_graphviz(std::istream& in, MutableGraph& graph,
|
||||
dynamic_properties& dp,
|
||||
std::string const& node_id = "node_id")
|
||||
{
|
||||
typedef std::istream_iterator<char> is_t;
|
||||
in >> std::noskipws;
|
||||
return read_graphviz(is_t(in), is_t(), graph, dp, node_id);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#ifdef BOOST_GRAPH_USE_MPI
|
||||
# include <boost/graph/distributed/graphviz.hpp>
|
||||
#endif
|
||||
|
||||
#endif // BOOST_GRAPHVIZ_HPP
|
||||
@@ -1,615 +0,0 @@
|
||||
// Copyright 2004 The Trustees of Indiana University.
|
||||
|
||||
// Use, modification and distribution is 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)
|
||||
|
||||
// Authors: Douglas Gregor
|
||||
// Peter Gottschling
|
||||
// Andrew Lumsdaine
|
||||
#ifndef BOOST_PARALLEL_DISTRIBUTION_HPP
|
||||
#define BOOST_PARALLEL_DISTRIBUTION_HPP
|
||||
|
||||
#ifndef BOOST_GRAPH_USE_MPI
|
||||
#error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/iterator/counting_iterator.hpp>
|
||||
#include <boost/random/uniform_int.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/type_index.hpp>
|
||||
|
||||
namespace boost { namespace parallel {
|
||||
|
||||
template<typename ProcessGroup, typename SizeType = std::size_t>
|
||||
class variant_distribution
|
||||
{
|
||||
public:
|
||||
typedef typename ProcessGroup::process_id_type process_id_type;
|
||||
typedef typename ProcessGroup::process_size_type process_size_type;
|
||||
typedef SizeType size_type;
|
||||
|
||||
private:
|
||||
struct basic_distribution
|
||||
{
|
||||
virtual ~basic_distribution() {}
|
||||
virtual size_type block_size(process_id_type, size_type) const = 0;
|
||||
virtual process_id_type in_process(size_type) const = 0;
|
||||
virtual size_type local(size_type) const = 0;
|
||||
virtual size_type global(size_type) const = 0;
|
||||
virtual size_type global(process_id_type, size_type) const = 0;
|
||||
virtual void* address() = 0;
|
||||
virtual const void* address() const = 0;
|
||||
virtual type_index type() const = 0;
|
||||
};
|
||||
|
||||
template<typename Distribution>
|
||||
struct poly_distribution : public basic_distribution
|
||||
{
|
||||
explicit poly_distribution(const Distribution& distribution)
|
||||
: distribution_(distribution) { }
|
||||
|
||||
virtual size_type block_size(process_id_type id, size_type n) const
|
||||
{ return distribution_.block_size(id, n); }
|
||||
|
||||
virtual process_id_type in_process(size_type i) const
|
||||
{ return distribution_(i); }
|
||||
|
||||
virtual size_type local(size_type i) const
|
||||
{ return distribution_.local(i); }
|
||||
|
||||
virtual size_type global(size_type n) const
|
||||
{ return distribution_.global(n); }
|
||||
|
||||
virtual size_type global(process_id_type id, size_type n) const
|
||||
{ return distribution_.global(id, n); }
|
||||
|
||||
virtual void* address() { return &distribution_; }
|
||||
virtual const void* address() const { return &distribution_; }
|
||||
virtual type_index type() const { return type_id<Distribution>(); }
|
||||
|
||||
private:
|
||||
Distribution distribution_;
|
||||
};
|
||||
|
||||
public:
|
||||
variant_distribution() { }
|
||||
|
||||
template<typename Distribution>
|
||||
variant_distribution(const Distribution& distribution)
|
||||
: distribution_(new poly_distribution<Distribution>(distribution)) { }
|
||||
|
||||
size_type block_size(process_id_type id, size_type n) const
|
||||
{ return distribution_->block_size(id, n); }
|
||||
|
||||
process_id_type operator()(size_type i) const
|
||||
{ return distribution_->in_process(i); }
|
||||
|
||||
size_type local(size_type i) const
|
||||
{ return distribution_->local(i); }
|
||||
|
||||
size_type global(size_type n) const
|
||||
{ return distribution_->global(n); }
|
||||
|
||||
size_type global(process_id_type id, size_type n) const
|
||||
{ return distribution_->global(id, n); }
|
||||
|
||||
operator bool() const { return distribution_; }
|
||||
|
||||
void clear() { distribution_.reset(); }
|
||||
|
||||
template<typename T>
|
||||
T* as()
|
||||
{
|
||||
if (distribution_->type() == type_id<T>())
|
||||
return static_cast<T*>(distribution_->address());
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const T* as() const
|
||||
{
|
||||
if (distribution_->type() == type_id<T>())
|
||||
return static_cast<T*>(distribution_->address());
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
shared_ptr<basic_distribution> distribution_;
|
||||
};
|
||||
|
||||
struct block
|
||||
{
|
||||
template<typename LinearProcessGroup>
|
||||
explicit block(const LinearProcessGroup& pg, std::size_t n)
|
||||
: id(process_id(pg)), p(num_processes(pg)), n(n) { }
|
||||
|
||||
// If there are n elements in the distributed data structure, returns the number of elements stored locally.
|
||||
template<typename SizeType>
|
||||
SizeType block_size(SizeType n) const
|
||||
{ return (n / p) + ((std::size_t)(n % p) > id? 1 : 0); }
|
||||
|
||||
// If there are n elements in the distributed data structure, returns the number of elements stored on processor ID
|
||||
template<typename SizeType, typename ProcessID>
|
||||
SizeType block_size(ProcessID id, SizeType n) const
|
||||
{ return (n / p) + ((ProcessID)(n % p) > id? 1 : 0); }
|
||||
|
||||
// Returns the processor on which element with global index i is stored
|
||||
template<typename SizeType>
|
||||
SizeType operator()(SizeType i) const
|
||||
{
|
||||
SizeType cutoff_processor = n % p;
|
||||
SizeType cutoff = cutoff_processor * (n / p + 1);
|
||||
|
||||
if (i < cutoff) return i / (n / p + 1);
|
||||
else return cutoff_processor + (i - cutoff) / (n / p);
|
||||
}
|
||||
|
||||
// Find the starting index for processor with the given id
|
||||
template<typename ID>
|
||||
std::size_t start(ID id) const
|
||||
{
|
||||
std::size_t estimate = id * (n / p + 1);
|
||||
ID cutoff_processor = n % p;
|
||||
if (id < cutoff_processor) return estimate;
|
||||
else return estimate - (id - cutoff_processor);
|
||||
}
|
||||
|
||||
// Find the local index for the ith global element
|
||||
template<typename SizeType>
|
||||
SizeType local(SizeType i) const
|
||||
{
|
||||
SizeType owner = (*this)(i);
|
||||
return i - start(owner);
|
||||
}
|
||||
|
||||
// Returns the global index of local element i
|
||||
template<typename SizeType>
|
||||
SizeType global(SizeType i) const
|
||||
{ return global(id, i); }
|
||||
|
||||
// Returns the global index of the ith local element on processor id
|
||||
template<typename ProcessID, typename SizeType>
|
||||
SizeType global(ProcessID id, SizeType i) const
|
||||
{ return i + start(id); }
|
||||
|
||||
private:
|
||||
std::size_t id; //< The ID number of this processor
|
||||
std::size_t p; //< The number of processors
|
||||
std::size_t n; //< The size of the problem space
|
||||
};
|
||||
|
||||
// Block distribution with arbitrary block sizes
|
||||
struct uneven_block
|
||||
{
|
||||
typedef std::vector<std::size_t> size_vector;
|
||||
|
||||
template<typename LinearProcessGroup>
|
||||
explicit uneven_block(const LinearProcessGroup& pg, const std::vector<std::size_t>& local_sizes)
|
||||
: id(process_id(pg)), p(num_processes(pg)), local_sizes(local_sizes)
|
||||
{
|
||||
BOOST_ASSERT(local_sizes.size() == p);
|
||||
local_starts.resize(p + 1);
|
||||
local_starts[0] = 0;
|
||||
std::partial_sum(local_sizes.begin(), local_sizes.end(), &local_starts[1]);
|
||||
n = local_starts[p];
|
||||
}
|
||||
|
||||
// To do maybe: enter local size in each process and gather in constructor (much handier)
|
||||
// template<typename LinearProcessGroup>
|
||||
// explicit uneven_block(const LinearProcessGroup& pg, std::size_t my_local_size)
|
||||
|
||||
// If there are n elements in the distributed data structure, returns the number of elements stored locally.
|
||||
template<typename SizeType>
|
||||
SizeType block_size(SizeType) const
|
||||
{ return local_sizes[id]; }
|
||||
|
||||
// If there are n elements in the distributed data structure, returns the number of elements stored on processor ID
|
||||
template<typename SizeType, typename ProcessID>
|
||||
SizeType block_size(ProcessID id, SizeType) const
|
||||
{ return local_sizes[id]; }
|
||||
|
||||
// Returns the processor on which element with global index i is stored
|
||||
template<typename SizeType>
|
||||
SizeType operator()(SizeType i) const
|
||||
{
|
||||
BOOST_ASSERT (i >= (SizeType) 0 && i < (SizeType) n); // check for valid range
|
||||
size_vector::const_iterator lb = std::lower_bound(local_starts.begin(), local_starts.end(), (std::size_t) i);
|
||||
return ((SizeType)(*lb) == i ? lb : --lb) - local_starts.begin();
|
||||
}
|
||||
|
||||
// Find the starting index for processor with the given id
|
||||
template<typename ID>
|
||||
std::size_t start(ID id) const
|
||||
{
|
||||
return local_starts[id];
|
||||
}
|
||||
|
||||
// Find the local index for the ith global element
|
||||
template<typename SizeType>
|
||||
SizeType local(SizeType i) const
|
||||
{
|
||||
SizeType owner = (*this)(i);
|
||||
return i - start(owner);
|
||||
}
|
||||
|
||||
// Returns the global index of local element i
|
||||
template<typename SizeType>
|
||||
SizeType global(SizeType i) const
|
||||
{ return global(id, i); }
|
||||
|
||||
// Returns the global index of the ith local element on processor id
|
||||
template<typename ProcessID, typename SizeType>
|
||||
SizeType global(ProcessID id, SizeType i) const
|
||||
{ return i + start(id); }
|
||||
|
||||
private:
|
||||
std::size_t id; //< The ID number of this processor
|
||||
std::size_t p; //< The number of processors
|
||||
std::size_t n; //< The size of the problem space
|
||||
std::vector<std::size_t> local_sizes; //< The sizes of all blocks
|
||||
std::vector<std::size_t> local_starts; //< Lowest global index of each block
|
||||
};
|
||||
|
||||
|
||||
struct oned_block_cyclic
|
||||
{
|
||||
template<typename LinearProcessGroup>
|
||||
explicit oned_block_cyclic(const LinearProcessGroup& pg, std::size_t size)
|
||||
: id(process_id(pg)), p(num_processes(pg)), size(size) { }
|
||||
|
||||
template<typename SizeType>
|
||||
SizeType block_size(SizeType n) const
|
||||
{
|
||||
return block_size(id, n);
|
||||
}
|
||||
|
||||
template<typename SizeType, typename ProcessID>
|
||||
SizeType block_size(ProcessID id, SizeType n) const
|
||||
{
|
||||
SizeType all_blocks = n / size;
|
||||
SizeType extra_elements = n % size;
|
||||
SizeType everyone_gets = all_blocks / p;
|
||||
SizeType extra_blocks = all_blocks % p;
|
||||
SizeType my_blocks = everyone_gets + (p < extra_blocks? 1 : 0);
|
||||
SizeType my_elements = my_blocks * size
|
||||
+ (p == extra_blocks? extra_elements : 0);
|
||||
return my_elements;
|
||||
}
|
||||
|
||||
template<typename SizeType>
|
||||
SizeType operator()(SizeType i) const
|
||||
{
|
||||
return (i / size) % p;
|
||||
}
|
||||
|
||||
template<typename SizeType>
|
||||
SizeType local(SizeType i) const
|
||||
{
|
||||
return ((i / size) / p) * size + i % size;
|
||||
}
|
||||
|
||||
template<typename SizeType>
|
||||
SizeType global(SizeType i) const
|
||||
{ return global(id, i); }
|
||||
|
||||
template<typename ProcessID, typename SizeType>
|
||||
SizeType global(ProcessID id, SizeType i) const
|
||||
{
|
||||
return ((i / size) * p + id) * size + i % size;
|
||||
}
|
||||
|
||||
private:
|
||||
std::size_t id; //< The ID number of this processor
|
||||
std::size_t p; //< The number of processors
|
||||
std::size_t size; //< Block size
|
||||
};
|
||||
|
||||
struct twod_block_cyclic
|
||||
{
|
||||
template<typename LinearProcessGroup>
|
||||
explicit twod_block_cyclic(const LinearProcessGroup& pg,
|
||||
std::size_t block_rows, std::size_t block_columns,
|
||||
std::size_t data_columns_per_row)
|
||||
: id(process_id(pg)), p(num_processes(pg)),
|
||||
block_rows(block_rows), block_columns(block_columns),
|
||||
data_columns_per_row(data_columns_per_row)
|
||||
{ }
|
||||
|
||||
template<typename SizeType>
|
||||
SizeType block_size(SizeType n) const
|
||||
{
|
||||
return block_size(id, n);
|
||||
}
|
||||
|
||||
template<typename SizeType, typename ProcessID>
|
||||
SizeType block_size(ProcessID id, SizeType n) const
|
||||
{
|
||||
// TBD: This is really lame :)
|
||||
int result = -1;
|
||||
while (n > 0) {
|
||||
--n;
|
||||
if ((*this)(n) == id && (int)local(n) > result) result = local(n);
|
||||
}
|
||||
++result;
|
||||
|
||||
// std::cerr << "Block size of id " << id << " is " << result << std::endl;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename SizeType>
|
||||
SizeType operator()(SizeType i) const
|
||||
{
|
||||
SizeType result = get_block_num(i) % p;
|
||||
// std::cerr << "Item " << i << " goes on processor " << result << std::endl;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename SizeType>
|
||||
SizeType local(SizeType i) const
|
||||
{
|
||||
// Compute the start of the block
|
||||
std::size_t block_num = get_block_num(i);
|
||||
// std::cerr << "Item " << i << " is in block #" << block_num << std::endl;
|
||||
|
||||
std::size_t local_block_num = block_num / p;
|
||||
std::size_t block_start = local_block_num * block_rows * block_columns;
|
||||
|
||||
// Compute the offset into the block
|
||||
std::size_t data_row = i / data_columns_per_row;
|
||||
std::size_t data_col = i % data_columns_per_row;
|
||||
std::size_t block_offset = (data_row % block_rows) * block_columns
|
||||
+ (data_col % block_columns);
|
||||
|
||||
// std::cerr << "Item " << i << " maps to local index " << block_start+block_offset << std::endl;
|
||||
return block_start + block_offset;
|
||||
}
|
||||
|
||||
template<typename SizeType>
|
||||
SizeType global(SizeType i) const
|
||||
{
|
||||
// Compute the (global) block in which this element resides
|
||||
SizeType local_block_num = i / (block_rows * block_columns);
|
||||
SizeType block_offset = i % (block_rows * block_columns);
|
||||
SizeType block_num = local_block_num * p + id;
|
||||
|
||||
// Compute the position of the start of the block (globally)
|
||||
SizeType block_start = block_num * block_rows * block_columns;
|
||||
|
||||
std::cerr << "Block " << block_num << " starts at index " << block_start
|
||||
<< std::endl;
|
||||
|
||||
// Compute the row and column of this block
|
||||
SizeType block_row = block_num / (data_columns_per_row / block_columns);
|
||||
SizeType block_col = block_num % (data_columns_per_row / block_columns);
|
||||
|
||||
SizeType row_in_block = block_offset / block_columns;
|
||||
SizeType col_in_block = block_offset % block_columns;
|
||||
|
||||
std::cerr << "Local index " << i << " is in block at row " << block_row
|
||||
<< ", column " << block_col << ", in-block row " << row_in_block
|
||||
<< ", in-block col " << col_in_block << std::endl;
|
||||
|
||||
SizeType result = block_row * block_rows + block_col * block_columns
|
||||
+ row_in_block * block_rows + col_in_block;
|
||||
|
||||
|
||||
std::cerr << "global(" << i << "@" << id << ") = " << result
|
||||
<< " =? " << local(result) << std::endl;
|
||||
BOOST_ASSERT(i == local(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename SizeType>
|
||||
std::size_t get_block_num(SizeType i) const
|
||||
{
|
||||
std::size_t data_row = i / data_columns_per_row;
|
||||
std::size_t data_col = i % data_columns_per_row;
|
||||
std::size_t block_row = data_row / block_rows;
|
||||
std::size_t block_col = data_col / block_columns;
|
||||
std::size_t blocks_in_row = data_columns_per_row / block_columns;
|
||||
std::size_t block_num = block_col * blocks_in_row + block_row;
|
||||
return block_num;
|
||||
}
|
||||
|
||||
std::size_t id; //< The ID number of this processor
|
||||
std::size_t p; //< The number of processors
|
||||
std::size_t block_rows; //< The # of rows in each block
|
||||
std::size_t block_columns; //< The # of columns in each block
|
||||
std::size_t data_columns_per_row; //< The # of columns per row of data
|
||||
};
|
||||
|
||||
class twod_random
|
||||
{
|
||||
template<typename RandomNumberGen>
|
||||
struct random_int
|
||||
{
|
||||
explicit random_int(RandomNumberGen& gen) : gen(gen) { }
|
||||
|
||||
template<typename T>
|
||||
T operator()(T n) const
|
||||
{
|
||||
uniform_int<T> distrib(0, n-1);
|
||||
return distrib(gen);
|
||||
}
|
||||
|
||||
private:
|
||||
RandomNumberGen& gen;
|
||||
};
|
||||
|
||||
public:
|
||||
template<typename LinearProcessGroup, typename RandomNumberGen>
|
||||
explicit twod_random(const LinearProcessGroup& pg,
|
||||
std::size_t block_rows, std::size_t block_columns,
|
||||
std::size_t data_columns_per_row,
|
||||
std::size_t n,
|
||||
RandomNumberGen& gen)
|
||||
: id(process_id(pg)), p(num_processes(pg)),
|
||||
block_rows(block_rows), block_columns(block_columns),
|
||||
data_columns_per_row(data_columns_per_row),
|
||||
global_to_local(n / (block_rows * block_columns))
|
||||
{
|
||||
std::copy(make_counting_iterator(std::size_t(0)),
|
||||
make_counting_iterator(global_to_local.size()),
|
||||
global_to_local.begin());
|
||||
|
||||
random_int<RandomNumberGen> rand(gen);
|
||||
std::random_shuffle(global_to_local.begin(), global_to_local.end(), rand);
|
||||
}
|
||||
|
||||
template<typename SizeType>
|
||||
SizeType block_size(SizeType n) const
|
||||
{
|
||||
return block_size(id, n);
|
||||
}
|
||||
|
||||
template<typename SizeType, typename ProcessID>
|
||||
SizeType block_size(ProcessID id, SizeType n) const
|
||||
{
|
||||
// TBD: This is really lame :)
|
||||
int result = -1;
|
||||
while (n > 0) {
|
||||
--n;
|
||||
if ((*this)(n) == id && (int)local(n) > result) result = local(n);
|
||||
}
|
||||
++result;
|
||||
|
||||
// std::cerr << "Block size of id " << id << " is " << result << std::endl;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename SizeType>
|
||||
SizeType operator()(SizeType i) const
|
||||
{
|
||||
SizeType result = get_block_num(i) % p;
|
||||
// std::cerr << "Item " << i << " goes on processor " << result << std::endl;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename SizeType>
|
||||
SizeType local(SizeType i) const
|
||||
{
|
||||
// Compute the start of the block
|
||||
std::size_t block_num = get_block_num(i);
|
||||
// std::cerr << "Item " << i << " is in block #" << block_num << std::endl;
|
||||
|
||||
std::size_t local_block_num = block_num / p;
|
||||
std::size_t block_start = local_block_num * block_rows * block_columns;
|
||||
|
||||
// Compute the offset into the block
|
||||
std::size_t data_row = i / data_columns_per_row;
|
||||
std::size_t data_col = i % data_columns_per_row;
|
||||
std::size_t block_offset = (data_row % block_rows) * block_columns
|
||||
+ (data_col % block_columns);
|
||||
|
||||
// std::cerr << "Item " << i << " maps to local index " << block_start+block_offset << std::endl;
|
||||
return block_start + block_offset;
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename SizeType>
|
||||
std::size_t get_block_num(SizeType i) const
|
||||
{
|
||||
std::size_t data_row = i / data_columns_per_row;
|
||||
std::size_t data_col = i % data_columns_per_row;
|
||||
std::size_t block_row = data_row / block_rows;
|
||||
std::size_t block_col = data_col / block_columns;
|
||||
std::size_t blocks_in_row = data_columns_per_row / block_columns;
|
||||
std::size_t block_num = block_col * blocks_in_row + block_row;
|
||||
return global_to_local[block_num];
|
||||
}
|
||||
|
||||
std::size_t id; //< The ID number of this processor
|
||||
std::size_t p; //< The number of processors
|
||||
std::size_t block_rows; //< The # of rows in each block
|
||||
std::size_t block_columns; //< The # of columns in each block
|
||||
std::size_t data_columns_per_row; //< The # of columns per row of data
|
||||
std::vector<std::size_t> global_to_local;
|
||||
};
|
||||
|
||||
class random_distribution
|
||||
{
|
||||
template<typename RandomNumberGen>
|
||||
struct random_int
|
||||
{
|
||||
explicit random_int(RandomNumberGen& gen) : gen(gen) { }
|
||||
|
||||
template<typename T>
|
||||
T operator()(T n) const
|
||||
{
|
||||
uniform_int<T> distrib(0, n-1);
|
||||
return distrib(gen);
|
||||
}
|
||||
|
||||
private:
|
||||
RandomNumberGen& gen;
|
||||
};
|
||||
|
||||
public:
|
||||
template<typename LinearProcessGroup, typename RandomNumberGen>
|
||||
random_distribution(const LinearProcessGroup& pg, RandomNumberGen& gen,
|
||||
std::size_t n)
|
||||
: base(pg, n), local_to_global(n), global_to_local(n)
|
||||
{
|
||||
std::copy(make_counting_iterator(std::size_t(0)),
|
||||
make_counting_iterator(n),
|
||||
local_to_global.begin());
|
||||
|
||||
random_int<RandomNumberGen> rand(gen);
|
||||
std::random_shuffle(local_to_global.begin(), local_to_global.end(), rand);
|
||||
|
||||
|
||||
for (std::vector<std::size_t>::size_type i = 0; i < n; ++i)
|
||||
global_to_local[local_to_global[i]] = i;
|
||||
}
|
||||
|
||||
template<typename SizeType>
|
||||
SizeType block_size(SizeType n) const
|
||||
{ return base.block_size(n); }
|
||||
|
||||
template<typename SizeType, typename ProcessID>
|
||||
SizeType block_size(ProcessID id, SizeType n) const
|
||||
{ return base.block_size(id, n); }
|
||||
|
||||
template<typename SizeType>
|
||||
SizeType operator()(SizeType i) const
|
||||
{
|
||||
return base(global_to_local[i]);
|
||||
}
|
||||
|
||||
template<typename SizeType>
|
||||
SizeType local(SizeType i) const
|
||||
{
|
||||
return base.local(global_to_local[i]);
|
||||
}
|
||||
|
||||
template<typename ProcessID, typename SizeType>
|
||||
SizeType global(ProcessID p, SizeType i) const
|
||||
{
|
||||
return local_to_global[base.global(p, i)];
|
||||
}
|
||||
|
||||
template<typename SizeType>
|
||||
SizeType global(SizeType i) const
|
||||
{
|
||||
return local_to_global[base.global(i)];
|
||||
}
|
||||
|
||||
private:
|
||||
block base;
|
||||
std::vector<std::size_t> local_to_global;
|
||||
std::vector<std::size_t> global_to_local;
|
||||
};
|
||||
|
||||
} } // end namespace boost::parallel
|
||||
|
||||
#endif // BOOST_PARALLEL_DISTRIBUTION_HPP
|
||||
|
||||
@@ -1,163 +0,0 @@
|
||||
// Copyright John Maddock 2010.
|
||||
// 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)
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_MATH_CONSTANTS_INFO_INCLUDED
|
||||
#define BOOST_MATH_CONSTANTS_INFO_INCLUDED
|
||||
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
#include <boost/type_index.hpp>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
namespace boost{ namespace math{ namespace constants{
|
||||
|
||||
namespace detail{
|
||||
|
||||
template <class T>
|
||||
const char* nameof(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(T))
|
||||
{
|
||||
return type_id<T>().name_demangled();
|
||||
}
|
||||
template <>
|
||||
const char* nameof<float>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(float))
|
||||
{
|
||||
return "float";
|
||||
}
|
||||
template <>
|
||||
const char* nameof<double>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(double))
|
||||
{
|
||||
return "double";
|
||||
}
|
||||
template <>
|
||||
const char* nameof<long double>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(long double))
|
||||
{
|
||||
return "long double";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
void print_info_on_type(std::ostream& os = std::cout BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(T) BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(Policy))
|
||||
{
|
||||
using detail::nameof;
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4127)
|
||||
#endif
|
||||
os <<
|
||||
"Information on the Implementation and Handling of \n"
|
||||
"Mathematical Constants for Type " << nameof<T>() <<
|
||||
"\n\n"
|
||||
"Checking for std::numeric_limits<" << nameof<T>() << "> specialisation: " <<
|
||||
(std::numeric_limits<T>::is_specialized ? "yes" : "no") << std::endl;
|
||||
if(std::numeric_limits<T>::is_specialized)
|
||||
{
|
||||
os <<
|
||||
"std::numeric_limits<" << nameof<T>() << ">::digits reports that the radix is " << std::numeric_limits<T>::radix << ".\n";
|
||||
if (std::numeric_limits<T>::radix == 2)
|
||||
{
|
||||
os <<
|
||||
"std::numeric_limits<" << nameof<T>() << ">::digits reports that the precision is \n" << std::numeric_limits<T>::digits << " binary digits.\n";
|
||||
}
|
||||
else if (std::numeric_limits<T>::radix == 10)
|
||||
{
|
||||
os <<
|
||||
"std::numeric_limits<" << nameof<T>() << ">::digits reports that the precision is \n" << std::numeric_limits<T>::digits10 << " decimal digits.\n";
|
||||
os <<
|
||||
"std::numeric_limits<" << nameof<T>() << ">::digits reports that the precision is \n"
|
||||
<< std::numeric_limits<T>::digits * 1000L /301L << " binary digits.\n"; // divide by log2(10) - about 3 bits per decimal digit.
|
||||
}
|
||||
else
|
||||
{
|
||||
os << "Unknown radix = " << std::numeric_limits<T>::radix << "\n";
|
||||
}
|
||||
}
|
||||
typedef typename boost::math::policies::precision<T, Policy>::type precision_type;
|
||||
if(precision_type::value)
|
||||
{
|
||||
if (std::numeric_limits<T>::radix == 2)
|
||||
{
|
||||
os <<
|
||||
"boost::math::policies::precision<" << nameof<T>() << ", " << nameof<Policy>() << " reports that the compile time precision is \n" << precision_type::value << " binary digits.\n";
|
||||
}
|
||||
else if (std::numeric_limits<T>::radix == 10)
|
||||
{
|
||||
os <<
|
||||
"boost::math::policies::precision<" << nameof<T>() << ", " << nameof<Policy>() << " reports that the compile time precision is \n" << precision_type::value << " binary digits.\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
os << "Unknown radix = " << std::numeric_limits<T>::radix << "\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
os <<
|
||||
"boost::math::policies::precision<" << nameof<T>() << ", Policy> \n"
|
||||
"reports that there is no compile type precision available.\n"
|
||||
"boost::math::tools::digits<" << nameof<T>() << ">() \n"
|
||||
"reports that the current runtime precision is \n" <<
|
||||
boost::math::tools::digits<T>() << " binary digits.\n";
|
||||
}
|
||||
|
||||
typedef typename construction_traits<T, Policy>::type construction_type;
|
||||
|
||||
switch(construction_type::value)
|
||||
{
|
||||
case 0:
|
||||
os <<
|
||||
"No compile time precision is available, the construction method \n"
|
||||
"will be decided at runtime and results will not be cached \n"
|
||||
"- this may lead to poor runtime performance.\n"
|
||||
"Current runtime precision indicates that\n";
|
||||
if(boost::math::tools::digits<T>() > max_string_digits)
|
||||
{
|
||||
os << "the constant will be recalculated on each call.\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
os << "the constant will be constructed from a string on each call.\n";
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
os <<
|
||||
"The constant will be constructed from a float.\n";
|
||||
break;
|
||||
case 2:
|
||||
os <<
|
||||
"The constant will be constructed from a double.\n";
|
||||
break;
|
||||
case 3:
|
||||
os <<
|
||||
"The constant will be constructed from a long double.\n";
|
||||
break;
|
||||
case 4:
|
||||
os <<
|
||||
"The constant will be constructed from a string (and the result cached).\n";
|
||||
break;
|
||||
default:
|
||||
os <<
|
||||
"The constant will be calculated (and the result cached).\n";
|
||||
break;
|
||||
}
|
||||
os << std::endl;
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void print_info_on_type(std::ostream& os = std::cout BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(T))
|
||||
{
|
||||
print_info_on_type<T, boost::math::policies::policy<> >(os);
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_CONSTANTS_INFO_INCLUDED
|
||||
@@ -1,488 +0,0 @@
|
||||
// Copyright 2008 Gautam Sewani
|
||||
// Copyright 2008 John Maddock
|
||||
//
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_MATH_DISTRIBUTIONS_DETAIL_HG_PDF_HPP
|
||||
#define BOOST_MATH_DISTRIBUTIONS_DETAIL_HG_PDF_HPP
|
||||
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
#include <boost/math/special_functions/lanczos.hpp>
|
||||
#include <boost/math/special_functions/gamma.hpp>
|
||||
#include <boost/math/special_functions/pow.hpp>
|
||||
#include <boost/math/special_functions/prime.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
|
||||
#ifdef BOOST_MATH_INSTRUMENT
|
||||
#include <boost/type_index.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost{ namespace math{ namespace detail{
|
||||
|
||||
template <class T, class Func>
|
||||
void bubble_down_one(T* first, T* last, Func f)
|
||||
{
|
||||
using std::swap;
|
||||
T* next = first;
|
||||
++next;
|
||||
while((next != last) && (!f(*first, *next)))
|
||||
{
|
||||
swap(*first, *next);
|
||||
++first;
|
||||
++next;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct sort_functor
|
||||
{
|
||||
sort_functor(const T* exponents) : m_exponents(exponents){}
|
||||
bool operator()(int i, int j)
|
||||
{
|
||||
return m_exponents[i] > m_exponents[j];
|
||||
}
|
||||
private:
|
||||
const T* m_exponents;
|
||||
};
|
||||
|
||||
template <class T, class Lanczos, class Policy>
|
||||
T hypergeometric_pdf_lanczos_imp(T /*dummy*/, unsigned x, unsigned r, unsigned n, unsigned N, const Lanczos&, const Policy&)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
BOOST_MATH_INSTRUMENT_FPU
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(x);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(r);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(n);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(N);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(type_id<Lanczos>().name_demangled());
|
||||
|
||||
T bases[9] = {
|
||||
T(n) + Lanczos::g() + 0.5f,
|
||||
T(r) + Lanczos::g() + 0.5f,
|
||||
T(N - n) + Lanczos::g() + 0.5f,
|
||||
T(N - r) + Lanczos::g() + 0.5f,
|
||||
1 / (T(N) + Lanczos::g() + 0.5f),
|
||||
1 / (T(x) + Lanczos::g() + 0.5f),
|
||||
1 / (T(n - x) + Lanczos::g() + 0.5f),
|
||||
1 / (T(r - x) + Lanczos::g() + 0.5f),
|
||||
1 / (T(N - n - r + x) + Lanczos::g() + 0.5f)
|
||||
};
|
||||
T exponents[9] = {
|
||||
n + T(0.5f),
|
||||
r + T(0.5f),
|
||||
N - n + T(0.5f),
|
||||
N - r + T(0.5f),
|
||||
N + T(0.5f),
|
||||
x + T(0.5f),
|
||||
n - x + T(0.5f),
|
||||
r - x + T(0.5f),
|
||||
N - n - r + x + T(0.5f)
|
||||
};
|
||||
int base_e_factors[9] = {
|
||||
-1, -1, -1, -1, 1, 1, 1, 1, 1
|
||||
};
|
||||
int sorted_indexes[9] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8
|
||||
};
|
||||
#ifdef BOOST_MATH_INSTRUMENT
|
||||
BOOST_MATH_INSTRUMENT_FPU
|
||||
for(unsigned i = 0; i < 9; ++i)
|
||||
{
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(i);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(bases[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(exponents[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(base_e_factors[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(sorted_indexes[i]);
|
||||
}
|
||||
#endif
|
||||
std::sort(sorted_indexes, sorted_indexes + 9, sort_functor<T>(exponents));
|
||||
#ifdef BOOST_MATH_INSTRUMENT
|
||||
BOOST_MATH_INSTRUMENT_FPU
|
||||
for(unsigned i = 0; i < 9; ++i)
|
||||
{
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(i);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(bases[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(exponents[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(base_e_factors[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(sorted_indexes[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
do{
|
||||
exponents[sorted_indexes[0]] -= exponents[sorted_indexes[1]];
|
||||
bases[sorted_indexes[1]] *= bases[sorted_indexes[0]];
|
||||
if((bases[sorted_indexes[1]] < tools::min_value<T>()) && (exponents[sorted_indexes[1]] != 0))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
base_e_factors[sorted_indexes[1]] += base_e_factors[sorted_indexes[0]];
|
||||
bubble_down_one(sorted_indexes, sorted_indexes + 9, sort_functor<T>(exponents));
|
||||
|
||||
#ifdef BOOST_MATH_INSTRUMENT
|
||||
for(unsigned i = 0; i < 9; ++i)
|
||||
{
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(i);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(bases[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(exponents[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(base_e_factors[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(sorted_indexes[i]);
|
||||
}
|
||||
#endif
|
||||
}while(exponents[sorted_indexes[1]] > 1);
|
||||
|
||||
//
|
||||
// Combine equal powers:
|
||||
//
|
||||
int j = 8;
|
||||
while(exponents[sorted_indexes[j]] == 0) --j;
|
||||
while(j)
|
||||
{
|
||||
while(j && (exponents[sorted_indexes[j-1]] == exponents[sorted_indexes[j]]))
|
||||
{
|
||||
bases[sorted_indexes[j-1]] *= bases[sorted_indexes[j]];
|
||||
exponents[sorted_indexes[j]] = 0;
|
||||
base_e_factors[sorted_indexes[j-1]] += base_e_factors[sorted_indexes[j]];
|
||||
bubble_down_one(sorted_indexes + j, sorted_indexes + 9, sort_functor<T>(exponents));
|
||||
--j;
|
||||
}
|
||||
--j;
|
||||
|
||||
#ifdef BOOST_MATH_INSTRUMENT
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(j);
|
||||
for(unsigned i = 0; i < 9; ++i)
|
||||
{
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(i);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(bases[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(exponents[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(base_e_factors[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(sorted_indexes[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef BOOST_MATH_INSTRUMENT
|
||||
BOOST_MATH_INSTRUMENT_FPU
|
||||
for(unsigned i = 0; i < 9; ++i)
|
||||
{
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(i);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(bases[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(exponents[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(base_e_factors[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(sorted_indexes[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
T result;
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(bases[sorted_indexes[0]] * exp(static_cast<T>(base_e_factors[sorted_indexes[0]])));
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(exponents[sorted_indexes[0]]);
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
result = pow(bases[sorted_indexes[0]] * exp(static_cast<T>(base_e_factors[sorted_indexes[0]])), exponents[sorted_indexes[0]]);
|
||||
}
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(result);
|
||||
for(unsigned i = 1; (i < 9) && (exponents[sorted_indexes[i]] > 0); ++i)
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
if(result < tools::min_value<T>())
|
||||
return 0; // short circuit further evaluation
|
||||
if(exponents[sorted_indexes[i]] == 1)
|
||||
result *= bases[sorted_indexes[i]] * exp(static_cast<T>(base_e_factors[sorted_indexes[i]]));
|
||||
else if(exponents[sorted_indexes[i]] == 0.5f)
|
||||
result *= sqrt(bases[sorted_indexes[i]] * exp(static_cast<T>(base_e_factors[sorted_indexes[i]])));
|
||||
else
|
||||
result *= pow(bases[sorted_indexes[i]] * exp(static_cast<T>(base_e_factors[sorted_indexes[i]])), exponents[sorted_indexes[i]]);
|
||||
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(result);
|
||||
}
|
||||
|
||||
result *= Lanczos::lanczos_sum_expG_scaled(static_cast<T>(n + 1))
|
||||
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(r + 1))
|
||||
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(N - n + 1))
|
||||
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(N - r + 1))
|
||||
/
|
||||
( Lanczos::lanczos_sum_expG_scaled(static_cast<T>(N + 1))
|
||||
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(x + 1))
|
||||
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(n - x + 1))
|
||||
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(r - x + 1))
|
||||
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(N - n - r + x + 1)));
|
||||
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T hypergeometric_pdf_lanczos_imp(T /*dummy*/, unsigned x, unsigned r, unsigned n, unsigned N, const boost::math::lanczos::undefined_lanczos&, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
return exp(
|
||||
boost::math::lgamma(T(n + 1), pol)
|
||||
+ boost::math::lgamma(T(r + 1), pol)
|
||||
+ boost::math::lgamma(T(N - n + 1), pol)
|
||||
+ boost::math::lgamma(T(N - r + 1), pol)
|
||||
- boost::math::lgamma(T(N + 1), pol)
|
||||
- boost::math::lgamma(T(x + 1), pol)
|
||||
- boost::math::lgamma(T(n - x + 1), pol)
|
||||
- boost::math::lgamma(T(r - x + 1), pol)
|
||||
- boost::math::lgamma(T(N - n - r + x + 1), pol));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T integer_power(const T& x, int ex)
|
||||
{
|
||||
if(ex < 0)
|
||||
return 1 / integer_power(x, -ex);
|
||||
switch(ex)
|
||||
{
|
||||
case 0:
|
||||
return 1;
|
||||
case 1:
|
||||
return x;
|
||||
case 2:
|
||||
return x * x;
|
||||
case 3:
|
||||
return x * x * x;
|
||||
case 4:
|
||||
return boost::math::pow<4>(x);
|
||||
case 5:
|
||||
return boost::math::pow<5>(x);
|
||||
case 6:
|
||||
return boost::math::pow<6>(x);
|
||||
case 7:
|
||||
return boost::math::pow<7>(x);
|
||||
case 8:
|
||||
return boost::math::pow<8>(x);
|
||||
}
|
||||
BOOST_MATH_STD_USING
|
||||
#ifdef __SUNPRO_CC
|
||||
return pow(x, T(ex));
|
||||
#else
|
||||
return pow(x, ex);
|
||||
#endif
|
||||
}
|
||||
template <class T>
|
||||
struct hypergeometric_pdf_prime_loop_result_entry
|
||||
{
|
||||
T value;
|
||||
const hypergeometric_pdf_prime_loop_result_entry* next;
|
||||
};
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4510 4512 4610)
|
||||
#endif
|
||||
|
||||
struct hypergeometric_pdf_prime_loop_data
|
||||
{
|
||||
const unsigned x;
|
||||
const unsigned r;
|
||||
const unsigned n;
|
||||
const unsigned N;
|
||||
unsigned prime_index;
|
||||
unsigned current_prime;
|
||||
};
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
T hypergeometric_pdf_prime_loop_imp(hypergeometric_pdf_prime_loop_data& data, hypergeometric_pdf_prime_loop_result_entry<T>& result)
|
||||
{
|
||||
while(data.current_prime <= data.N)
|
||||
{
|
||||
unsigned base = data.current_prime;
|
||||
int prime_powers = 0;
|
||||
while(base <= data.N)
|
||||
{
|
||||
prime_powers += data.n / base;
|
||||
prime_powers += data.r / base;
|
||||
prime_powers += (data.N - data.n) / base;
|
||||
prime_powers += (data.N - data.r) / base;
|
||||
prime_powers -= data.N / base;
|
||||
prime_powers -= data.x / base;
|
||||
prime_powers -= (data.n - data.x) / base;
|
||||
prime_powers -= (data.r - data.x) / base;
|
||||
prime_powers -= (data.N - data.n - data.r + data.x) / base;
|
||||
base *= data.current_prime;
|
||||
}
|
||||
if(prime_powers)
|
||||
{
|
||||
T p = integer_power<T>(data.current_prime, prime_powers);
|
||||
if((p > 1) && (tools::max_value<T>() / p < result.value))
|
||||
{
|
||||
//
|
||||
// The next calculation would overflow, use recursion
|
||||
// to sidestep the issue:
|
||||
//
|
||||
hypergeometric_pdf_prime_loop_result_entry<T> t = { p, &result };
|
||||
data.current_prime = prime(++data.prime_index);
|
||||
return hypergeometric_pdf_prime_loop_imp<T>(data, t);
|
||||
}
|
||||
if((p < 1) && (tools::min_value<T>() / p > result.value))
|
||||
{
|
||||
//
|
||||
// The next calculation would underflow, use recursion
|
||||
// to sidestep the issue:
|
||||
//
|
||||
hypergeometric_pdf_prime_loop_result_entry<T> t = { p, &result };
|
||||
data.current_prime = prime(++data.prime_index);
|
||||
return hypergeometric_pdf_prime_loop_imp<T>(data, t);
|
||||
}
|
||||
result.value *= p;
|
||||
}
|
||||
data.current_prime = prime(++data.prime_index);
|
||||
}
|
||||
//
|
||||
// When we get to here we have run out of prime factors,
|
||||
// the overall result is the product of all the partial
|
||||
// results we have accumulated on the stack so far, these
|
||||
// are in a linked list starting with "data.head" and ending
|
||||
// with "result".
|
||||
//
|
||||
// All that remains is to multiply them together, taking
|
||||
// care not to overflow or underflow.
|
||||
//
|
||||
// Enumerate partial results >= 1 in variable i
|
||||
// and partial results < 1 in variable j:
|
||||
//
|
||||
hypergeometric_pdf_prime_loop_result_entry<T> const *i, *j;
|
||||
i = &result;
|
||||
while(i && i->value < 1)
|
||||
i = i->next;
|
||||
j = &result;
|
||||
while(j && j->value >= 1)
|
||||
j = j->next;
|
||||
|
||||
T prod = 1;
|
||||
|
||||
while(i || j)
|
||||
{
|
||||
while(i && ((prod <= 1) || (j == 0)))
|
||||
{
|
||||
prod *= i->value;
|
||||
i = i->next;
|
||||
while(i && i->value < 1)
|
||||
i = i->next;
|
||||
}
|
||||
while(j && ((prod >= 1) || (i == 0)))
|
||||
{
|
||||
prod *= j->value;
|
||||
j = j->next;
|
||||
while(j && j->value >= 1)
|
||||
j = j->next;
|
||||
}
|
||||
}
|
||||
|
||||
return prod;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T hypergeometric_pdf_prime_imp(unsigned x, unsigned r, unsigned n, unsigned N, const Policy&)
|
||||
{
|
||||
hypergeometric_pdf_prime_loop_result_entry<T> result = { 1, 0 };
|
||||
hypergeometric_pdf_prime_loop_data data = { x, r, n, N, 0, prime(0) };
|
||||
return hypergeometric_pdf_prime_loop_imp<T>(data, result);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T hypergeometric_pdf_factorial_imp(unsigned x, unsigned r, unsigned n, unsigned N, const Policy&)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
BOOST_ASSERT(N < boost::math::max_factorial<T>::value);
|
||||
T result = boost::math::unchecked_factorial<T>(n);
|
||||
T num[3] = {
|
||||
boost::math::unchecked_factorial<T>(r),
|
||||
boost::math::unchecked_factorial<T>(N - n),
|
||||
boost::math::unchecked_factorial<T>(N - r)
|
||||
};
|
||||
T denom[5] = {
|
||||
boost::math::unchecked_factorial<T>(N),
|
||||
boost::math::unchecked_factorial<T>(x),
|
||||
boost::math::unchecked_factorial<T>(n - x),
|
||||
boost::math::unchecked_factorial<T>(r - x),
|
||||
boost::math::unchecked_factorial<T>(N - n - r + x)
|
||||
};
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
while((i < 3) || (j < 5))
|
||||
{
|
||||
while((j < 5) && ((result >= 1) || (i >= 3)))
|
||||
{
|
||||
result /= denom[j];
|
||||
++j;
|
||||
}
|
||||
while((i < 3) && ((result <= 1) || (j >= 5)))
|
||||
{
|
||||
result *= num[i];
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type
|
||||
hypergeometric_pdf(unsigned x, unsigned r, unsigned n, unsigned N, const Policy&)
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
typedef typename lanczos::lanczos<value_type, Policy>::type evaluation_type;
|
||||
typedef typename policies::normalise<
|
||||
Policy,
|
||||
policies::promote_float<false>,
|
||||
policies::promote_double<false>,
|
||||
policies::discrete_quantile<>,
|
||||
policies::assert_undefined<> >::type forwarding_policy;
|
||||
|
||||
value_type result;
|
||||
if(N <= boost::math::max_factorial<value_type>::value)
|
||||
{
|
||||
//
|
||||
// If N is small enough then we can evaluate the PDF via the factorials
|
||||
// directly: table lookup of the factorials gives the best performance
|
||||
// of the methods available:
|
||||
//
|
||||
result = detail::hypergeometric_pdf_factorial_imp<value_type>(x, r, n, N, forwarding_policy());
|
||||
}
|
||||
else if(N <= boost::math::prime(boost::math::max_prime - 1))
|
||||
{
|
||||
//
|
||||
// If N is no larger than the largest prime number in our lookup table
|
||||
// (104729) then we can use prime factorisation to evaluate the PDF,
|
||||
// this is slow but accurate:
|
||||
//
|
||||
result = detail::hypergeometric_pdf_prime_imp<value_type>(x, r, n, N, forwarding_policy());
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Catch all case - use the lanczos approximation - where available -
|
||||
// to evaluate the ratio of factorials. This is reasonably fast
|
||||
// (almost as quick as using logarithmic evaluation in terms of lgamma)
|
||||
// but only a few digits better in accuracy than using lgamma:
|
||||
//
|
||||
result = detail::hypergeometric_pdf_lanczos_imp(value_type(), x, r, n, N, evaluation_type(), forwarding_policy());
|
||||
}
|
||||
|
||||
if(result > 1)
|
||||
{
|
||||
result = 1;
|
||||
}
|
||||
if(result < 0)
|
||||
{
|
||||
result = 0;
|
||||
}
|
||||
|
||||
return policies::checked_narrowing_cast<result_type, forwarding_policy>(result, "boost::math::hypergeometric_pdf<%1%>(%1%,%1%,%1%,%1%)");
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,692 +0,0 @@
|
||||
// Copyright John Maddock 2007.
|
||||
// Copyright Paul A. Bristow 2007.
|
||||
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_MATH_POLICY_ERROR_HANDLING_HPP
|
||||
#define BOOST_MATH_POLICY_ERROR_HANDLING_HPP
|
||||
|
||||
#include <stdexcept>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
#include <cerrno>
|
||||
#include <complex>
|
||||
#include <boost/config/no_tr1/cmath.hpp>
|
||||
#include <stdexcept>
|
||||
#include <boost/math/tools/config.hpp>
|
||||
#include <boost/math/policies/policy.hpp>
|
||||
#include <boost/math/tools/precision.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(push) // Quiet warnings in boost/format.hpp
|
||||
# pragma warning(disable: 4996) // _SCL_SECURE_NO_DEPRECATE
|
||||
# pragma warning(disable: 4512) // assignment operator could not be generated.
|
||||
// And warnings in error handling:
|
||||
# pragma warning(disable: 4702) // unreachable code
|
||||
// Note that this only occurs when the compiler can deduce code is unreachable,
|
||||
// for example when policy macros are used to ignore errors rather than throw.
|
||||
#endif
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/type_index.hpp>
|
||||
|
||||
namespace boost{ namespace math{
|
||||
|
||||
class evaluation_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
evaluation_error(const std::string& s) : std::runtime_error(s){}
|
||||
};
|
||||
|
||||
class rounding_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
rounding_error(const std::string& s) : std::runtime_error(s){}
|
||||
};
|
||||
|
||||
namespace policies{
|
||||
//
|
||||
// Forward declarations of user error handlers,
|
||||
// it's up to the user to provide the definition of these:
|
||||
//
|
||||
template <class T>
|
||||
T user_domain_error(const char* function, const char* message, const T& val);
|
||||
template <class T>
|
||||
T user_pole_error(const char* function, const char* message, const T& val);
|
||||
template <class T>
|
||||
T user_overflow_error(const char* function, const char* message, const T& val);
|
||||
template <class T>
|
||||
T user_underflow_error(const char* function, const char* message, const T& val);
|
||||
template <class T>
|
||||
T user_denorm_error(const char* function, const char* message, const T& val);
|
||||
template <class T>
|
||||
T user_evaluation_error(const char* function, const char* message, const T& val);
|
||||
template <class T, class TargetType>
|
||||
T user_rounding_error(const char* function, const char* message, const T& val, const TargetType& t);
|
||||
template <class T>
|
||||
T user_indeterminate_result_error(const char* function, const char* message, const T& val);
|
||||
|
||||
namespace detail
|
||||
{
|
||||
//
|
||||
// Helper function to avoid binding rvalue to non-const-reference,
|
||||
// in other words a warning suppression mechansim:
|
||||
//
|
||||
template <class Formatter, class Group>
|
||||
inline std::string do_format(Formatter f, const Group& g)
|
||||
{
|
||||
return (f % g).str();
|
||||
}
|
||||
|
||||
template <class E, class T>
|
||||
void raise_error(const char* function, const char* message)
|
||||
{
|
||||
if(function == 0)
|
||||
function = "Unknown function operating on type %1%";
|
||||
if(message == 0)
|
||||
message = "Cause unknown";
|
||||
|
||||
std::string msg("Error in function ");
|
||||
msg += (boost::format(function) % type_id<T>().name_demangled()).str();
|
||||
msg += ": ";
|
||||
msg += message;
|
||||
|
||||
E e(msg);
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
|
||||
template <class E, class T>
|
||||
void raise_error(const char* function, const char* message, const T& val)
|
||||
{
|
||||
if(function == 0)
|
||||
function = "Unknown function operating on type %1%";
|
||||
if(message == 0)
|
||||
message = "Cause unknown: error caused by bad argument with value %1%";
|
||||
|
||||
std::string msg("Error in function ");
|
||||
msg += (boost::format(function) % type_id<T>().name_demangled()).str();
|
||||
msg += ": ";
|
||||
msg += message;
|
||||
|
||||
int prec = 2 + (boost::math::policies::digits<T, boost::math::policies::policy<> >() * 30103UL) / 100000UL;
|
||||
msg = do_format(boost::format(msg), boost::io::group(std::setprecision(prec), val));
|
||||
|
||||
E e(msg);
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_domain_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const T& val,
|
||||
const ::boost::math::policies::domain_error< ::boost::math::policies::throw_on_error>&)
|
||||
{
|
||||
raise_error<std::domain_error, T>(function, message, val);
|
||||
// we never get here:
|
||||
return std::numeric_limits<T>::quiet_NaN();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_domain_error(
|
||||
const char* ,
|
||||
const char* ,
|
||||
const T& ,
|
||||
const ::boost::math::policies::domain_error< ::boost::math::policies::ignore_error>&)
|
||||
{
|
||||
// This may or may not do the right thing, but the user asked for the error
|
||||
// to be ignored so here we go anyway:
|
||||
return std::numeric_limits<T>::quiet_NaN();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_domain_error(
|
||||
const char* ,
|
||||
const char* ,
|
||||
const T& ,
|
||||
const ::boost::math::policies::domain_error< ::boost::math::policies::errno_on_error>&)
|
||||
{
|
||||
errno = EDOM;
|
||||
// This may or may not do the right thing, but the user asked for the error
|
||||
// to be silent so here we go anyway:
|
||||
return std::numeric_limits<T>::quiet_NaN();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_domain_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const T& val,
|
||||
const ::boost::math::policies::domain_error< ::boost::math::policies::user_error>&)
|
||||
{
|
||||
return user_domain_error(function, message, val);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_pole_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const T& val,
|
||||
const ::boost::math::policies::pole_error< ::boost::math::policies::throw_on_error>&)
|
||||
{
|
||||
return boost::math::policies::detail::raise_domain_error(function, message, val, ::boost::math::policies::domain_error< ::boost::math::policies::throw_on_error>());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_pole_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const T& val,
|
||||
const ::boost::math::policies::pole_error< ::boost::math::policies::ignore_error>&)
|
||||
{
|
||||
return ::boost::math::policies::detail::raise_domain_error(function, message, val, ::boost::math::policies::domain_error< ::boost::math::policies::ignore_error>());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_pole_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const T& val,
|
||||
const ::boost::math::policies::pole_error< ::boost::math::policies::errno_on_error>&)
|
||||
{
|
||||
return ::boost::math::policies::detail::raise_domain_error(function, message, val, ::boost::math::policies::domain_error< ::boost::math::policies::errno_on_error>());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_pole_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const T& val,
|
||||
const ::boost::math::policies::pole_error< ::boost::math::policies::user_error>&)
|
||||
{
|
||||
return user_pole_error(function, message, val);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_overflow_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const ::boost::math::policies::overflow_error< ::boost::math::policies::throw_on_error>&)
|
||||
{
|
||||
raise_error<std::overflow_error, T>(function, message ? message : "numeric overflow");
|
||||
// we never get here:
|
||||
return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_overflow_error(
|
||||
const char* ,
|
||||
const char* ,
|
||||
const ::boost::math::policies::overflow_error< ::boost::math::policies::ignore_error>&)
|
||||
{
|
||||
// This may or may not do the right thing, but the user asked for the error
|
||||
// to be ignored so here we go anyway:
|
||||
return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_overflow_error(
|
||||
const char* ,
|
||||
const char* ,
|
||||
const ::boost::math::policies::overflow_error< ::boost::math::policies::errno_on_error>&)
|
||||
{
|
||||
errno = ERANGE;
|
||||
// This may or may not do the right thing, but the user asked for the error
|
||||
// to be silent so here we go anyway:
|
||||
return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_overflow_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const ::boost::math::policies::overflow_error< ::boost::math::policies::user_error>&)
|
||||
{
|
||||
return user_overflow_error(function, message, std::numeric_limits<T>::infinity());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_underflow_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const ::boost::math::policies::underflow_error< ::boost::math::policies::throw_on_error>&)
|
||||
{
|
||||
raise_error<std::underflow_error, T>(function, message ? message : "numeric underflow");
|
||||
// we never get here:
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_underflow_error(
|
||||
const char* ,
|
||||
const char* ,
|
||||
const ::boost::math::policies::underflow_error< ::boost::math::policies::ignore_error>&)
|
||||
{
|
||||
// This may or may not do the right thing, but the user asked for the error
|
||||
// to be ignored so here we go anyway:
|
||||
return T(0);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_underflow_error(
|
||||
const char* /* function */,
|
||||
const char* /* message */,
|
||||
const ::boost::math::policies::underflow_error< ::boost::math::policies::errno_on_error>&)
|
||||
{
|
||||
errno = ERANGE;
|
||||
// This may or may not do the right thing, but the user asked for the error
|
||||
// to be silent so here we go anyway:
|
||||
return T(0);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_underflow_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const ::boost::math::policies::underflow_error< ::boost::math::policies::user_error>&)
|
||||
{
|
||||
return user_underflow_error(function, message, T(0));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_denorm_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const T& /* val */,
|
||||
const ::boost::math::policies::denorm_error< ::boost::math::policies::throw_on_error>&)
|
||||
{
|
||||
raise_error<std::underflow_error, T>(function, message ? message : "denormalised result");
|
||||
// we never get here:
|
||||
return T(0);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_denorm_error(
|
||||
const char* ,
|
||||
const char* ,
|
||||
const T& val,
|
||||
const ::boost::math::policies::denorm_error< ::boost::math::policies::ignore_error>&)
|
||||
{
|
||||
// This may or may not do the right thing, but the user asked for the error
|
||||
// to be ignored so here we go anyway:
|
||||
return val;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_denorm_error(
|
||||
const char* ,
|
||||
const char* ,
|
||||
const T& val,
|
||||
const ::boost::math::policies::denorm_error< ::boost::math::policies::errno_on_error>&)
|
||||
{
|
||||
errno = ERANGE;
|
||||
// This may or may not do the right thing, but the user asked for the error
|
||||
// to be silent so here we go anyway:
|
||||
return val;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_denorm_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const T& val,
|
||||
const ::boost::math::policies::denorm_error< ::boost::math::policies::user_error>&)
|
||||
{
|
||||
return user_denorm_error(function, message, val);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_evaluation_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const T& val,
|
||||
const ::boost::math::policies::evaluation_error< ::boost::math::policies::throw_on_error>&)
|
||||
{
|
||||
raise_error<boost::math::evaluation_error, T>(function, message, val);
|
||||
// we never get here:
|
||||
return T(0);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_evaluation_error(
|
||||
const char* ,
|
||||
const char* ,
|
||||
const T& val,
|
||||
const ::boost::math::policies::evaluation_error< ::boost::math::policies::ignore_error>&)
|
||||
{
|
||||
// This may or may not do the right thing, but the user asked for the error
|
||||
// to be ignored so here we go anyway:
|
||||
return val;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_evaluation_error(
|
||||
const char* ,
|
||||
const char* ,
|
||||
const T& val,
|
||||
const ::boost::math::policies::evaluation_error< ::boost::math::policies::errno_on_error>&)
|
||||
{
|
||||
errno = EDOM;
|
||||
// This may or may not do the right thing, but the user asked for the error
|
||||
// to be silent so here we go anyway:
|
||||
return val;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_evaluation_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const T& val,
|
||||
const ::boost::math::policies::evaluation_error< ::boost::math::policies::user_error>&)
|
||||
{
|
||||
return user_evaluation_error(function, message, val);
|
||||
}
|
||||
|
||||
template <class T, class TargetType>
|
||||
inline T raise_rounding_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const T& val,
|
||||
const TargetType&,
|
||||
const ::boost::math::policies::rounding_error< ::boost::math::policies::throw_on_error>&)
|
||||
{
|
||||
raise_error<boost::math::rounding_error, T>(function, message, val);
|
||||
// we never get here:
|
||||
return T(0);
|
||||
}
|
||||
|
||||
template <class T, class TargetType>
|
||||
inline T raise_rounding_error(
|
||||
const char* ,
|
||||
const char* ,
|
||||
const T& val,
|
||||
const TargetType&,
|
||||
const ::boost::math::policies::rounding_error< ::boost::math::policies::ignore_error>&)
|
||||
{
|
||||
// This may or may not do the right thing, but the user asked for the error
|
||||
// to be ignored so here we go anyway:
|
||||
return std::numeric_limits<T>::is_specialized ? (val > 0 ? (std::numeric_limits<T>::max)() : -(std::numeric_limits<T>::max)()): val;
|
||||
}
|
||||
|
||||
template <class T, class TargetType>
|
||||
inline T raise_rounding_error(
|
||||
const char* ,
|
||||
const char* ,
|
||||
const T& val,
|
||||
const TargetType&,
|
||||
const ::boost::math::policies::rounding_error< ::boost::math::policies::errno_on_error>&)
|
||||
{
|
||||
errno = ERANGE;
|
||||
// This may or may not do the right thing, but the user asked for the error
|
||||
// to be silent so here we go anyway:
|
||||
return std::numeric_limits<T>::is_specialized ? (val > 0 ? (std::numeric_limits<T>::max)() : -(std::numeric_limits<T>::max)()): val;
|
||||
}
|
||||
|
||||
template <class T, class TargetType>
|
||||
inline T raise_rounding_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const T& val,
|
||||
const TargetType& t,
|
||||
const ::boost::math::policies::rounding_error< ::boost::math::policies::user_error>&)
|
||||
{
|
||||
return user_rounding_error(function, message, val, t);
|
||||
}
|
||||
|
||||
template <class T, class R>
|
||||
inline T raise_indeterminate_result_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const T& val,
|
||||
const R& ,
|
||||
const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::throw_on_error>&)
|
||||
{
|
||||
raise_error<std::domain_error, T>(function, message, val);
|
||||
// we never get here:
|
||||
return std::numeric_limits<T>::quiet_NaN();
|
||||
}
|
||||
|
||||
template <class T, class R>
|
||||
inline T raise_indeterminate_result_error(
|
||||
const char* ,
|
||||
const char* ,
|
||||
const T& ,
|
||||
const R& result,
|
||||
const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::ignore_error>&)
|
||||
{
|
||||
// This may or may not do the right thing, but the user asked for the error
|
||||
// to be ignored so here we go anyway:
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T, class R>
|
||||
inline T raise_indeterminate_result_error(
|
||||
const char* ,
|
||||
const char* ,
|
||||
const T& ,
|
||||
const R& result,
|
||||
const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::errno_on_error>&)
|
||||
{
|
||||
errno = EDOM;
|
||||
// This may or may not do the right thing, but the user asked for the error
|
||||
// to be silent so here we go anyway:
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T, class R>
|
||||
inline T raise_indeterminate_result_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const T& val,
|
||||
const R& ,
|
||||
const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::user_error>&)
|
||||
{
|
||||
return user_indeterminate_result_error(function, message, val);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T raise_domain_error(const char* function, const char* message, const T& val, const Policy&)
|
||||
{
|
||||
typedef typename Policy::domain_error_type policy_type;
|
||||
return detail::raise_domain_error(
|
||||
function, message ? message : "Domain Error evaluating function at %1%",
|
||||
val, policy_type());
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T raise_pole_error(const char* function, const char* message, const T& val, const Policy&)
|
||||
{
|
||||
typedef typename Policy::pole_error_type policy_type;
|
||||
return detail::raise_pole_error(
|
||||
function, message ? message : "Evaluation of function at pole %1%",
|
||||
val, policy_type());
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T raise_overflow_error(const char* function, const char* message, const Policy&)
|
||||
{
|
||||
typedef typename Policy::overflow_error_type policy_type;
|
||||
return detail::raise_overflow_error<T>(
|
||||
function, message ? message : "Overflow Error",
|
||||
policy_type());
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T raise_underflow_error(const char* function, const char* message, const Policy&)
|
||||
{
|
||||
typedef typename Policy::underflow_error_type policy_type;
|
||||
return detail::raise_underflow_error<T>(
|
||||
function, message ? message : "Underflow Error",
|
||||
policy_type());
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T raise_denorm_error(const char* function, const char* message, const T& val, const Policy&)
|
||||
{
|
||||
typedef typename Policy::denorm_error_type policy_type;
|
||||
return detail::raise_denorm_error<T>(
|
||||
function, message ? message : "Denorm Error",
|
||||
val,
|
||||
policy_type());
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T raise_evaluation_error(const char* function, const char* message, const T& val, const Policy&)
|
||||
{
|
||||
typedef typename Policy::evaluation_error_type policy_type;
|
||||
return detail::raise_evaluation_error(
|
||||
function, message ? message : "Internal Evaluation Error, best value so far was %1%",
|
||||
val, policy_type());
|
||||
}
|
||||
|
||||
template <class T, class TargetType, class Policy>
|
||||
inline T raise_rounding_error(const char* function, const char* message, const T& val, const TargetType& t, const Policy&)
|
||||
{
|
||||
typedef typename Policy::rounding_error_type policy_type;
|
||||
return detail::raise_rounding_error(
|
||||
function, message ? message : "Value %1% can not be represented in the target integer type.",
|
||||
val, t, policy_type());
|
||||
}
|
||||
|
||||
template <class T, class R, class Policy>
|
||||
inline T raise_indeterminate_result_error(const char* function, const char* message, const T& val, const R& result, const Policy&)
|
||||
{
|
||||
typedef typename Policy::indeterminate_result_error_type policy_type;
|
||||
return detail::raise_indeterminate_result_error(
|
||||
function, message ? message : "Indeterminate result with value %1%",
|
||||
val, result, policy_type());
|
||||
}
|
||||
|
||||
//
|
||||
// checked_narrowing_cast:
|
||||
//
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <class R, class T, class Policy>
|
||||
inline bool check_overflow(T val, R* result, const char* function, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
if(fabs(val) > tools::max_value<R>())
|
||||
{
|
||||
*result = static_cast<R>(boost::math::policies::detail::raise_overflow_error<R>(function, 0, pol));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
template <class R, class T, class Policy>
|
||||
inline bool check_overflow(std::complex<T> val, R* result, const char* function, const Policy& pol)
|
||||
{
|
||||
typedef typename R::value_type r_type;
|
||||
r_type re, im;
|
||||
bool r = check_overflow<r_type>(val.real(), &re, function, pol) || check_overflow<r_type>(val.imag(), &im, function, pol);
|
||||
*result = R(re, im);
|
||||
return r;
|
||||
}
|
||||
template <class R, class T, class Policy>
|
||||
inline bool check_underflow(T val, R* result, const char* function, const Policy& pol)
|
||||
{
|
||||
if((val != 0) && (static_cast<R>(val) == 0))
|
||||
{
|
||||
*result = static_cast<R>(boost::math::policies::detail::raise_underflow_error<R>(function, 0, pol));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
template <class R, class T, class Policy>
|
||||
inline bool check_underflow(std::complex<T> val, R* result, const char* function, const Policy& pol)
|
||||
{
|
||||
typedef typename R::value_type r_type;
|
||||
r_type re, im;
|
||||
bool r = check_underflow<r_type>(val.real(), &re, function, pol) || check_underflow<r_type>(val.imag(), &im, function, pol);
|
||||
*result = R(re, im);
|
||||
return r;
|
||||
}
|
||||
template <class R, class T, class Policy>
|
||||
inline bool check_denorm(T val, R* result, const char* function, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
if((fabs(val) < static_cast<T>(tools::min_value<R>())) && (static_cast<R>(val) != 0))
|
||||
{
|
||||
*result = static_cast<R>(boost::math::policies::detail::raise_denorm_error<R>(function, 0, static_cast<R>(val), pol));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
template <class R, class T, class Policy>
|
||||
inline bool check_denorm(std::complex<T> val, R* result, const char* function, const Policy& pol)
|
||||
{
|
||||
typedef typename R::value_type r_type;
|
||||
r_type re, im;
|
||||
bool r = check_denorm<r_type>(val.real(), &re, function, pol) || check_denorm<r_type>(val.imag(), &im, function, pol);
|
||||
*result = R(re, im);
|
||||
return r;
|
||||
}
|
||||
|
||||
// Default instantiations with ignore_error policy.
|
||||
template <class R, class T>
|
||||
inline bool check_overflow(T /* val */, R* /* result */, const char* /* function */, const overflow_error<ignore_error>&){ return false; }
|
||||
template <class R, class T>
|
||||
inline bool check_overflow(std::complex<T> /* val */, R* /* result */, const char* /* function */, const overflow_error<ignore_error>&){ return false; }
|
||||
template <class R, class T>
|
||||
inline bool check_underflow(T /* val */, R* /* result */, const char* /* function */, const underflow_error<ignore_error>&){ return false; }
|
||||
template <class R, class T>
|
||||
inline bool check_underflow(std::complex<T> /* val */, R* /* result */, const char* /* function */, const underflow_error<ignore_error>&){ return false; }
|
||||
template <class R, class T>
|
||||
inline bool check_denorm(T /* val */, R* /* result*/, const char* /* function */, const denorm_error<ignore_error>&){ return false; }
|
||||
template <class R, class T>
|
||||
inline bool check_denorm(std::complex<T> /* val */, R* /* result*/, const char* /* function */, const denorm_error<ignore_error>&){ return false; }
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class R, class Policy, class T>
|
||||
inline R checked_narrowing_cast(T val, const char* function)
|
||||
{
|
||||
typedef typename Policy::overflow_error_type overflow_type;
|
||||
typedef typename Policy::underflow_error_type underflow_type;
|
||||
typedef typename Policy::denorm_error_type denorm_type;
|
||||
//
|
||||
// Most of what follows will evaluate to a no-op:
|
||||
//
|
||||
R result = 0;
|
||||
if(detail::check_overflow<R>(val, &result, function, overflow_type()))
|
||||
return result;
|
||||
if(detail::check_underflow<R>(val, &result, function, underflow_type()))
|
||||
return result;
|
||||
if(detail::check_denorm<R>(val, &result, function, denorm_type()))
|
||||
return result;
|
||||
|
||||
return static_cast<R>(val);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline void check_series_iterations(const char* function, boost::uintmax_t max_iter, const Policy& pol)
|
||||
{
|
||||
if(max_iter >= policies::get_max_series_iterations<Policy>())
|
||||
raise_evaluation_error<T>(
|
||||
function,
|
||||
"Series evaluation exceeded %1% iterations, giving up now.", static_cast<T>(static_cast<double>(max_iter)), pol);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline void check_root_iterations(const char* function, boost::uintmax_t max_iter, const Policy& pol)
|
||||
{
|
||||
if(max_iter >= policies::get_max_root_iterations<Policy>())
|
||||
raise_evaluation_error<T>(
|
||||
function,
|
||||
"Root finding evaluation exceeded %1% iterations, giving up now.", static_cast<T>(static_cast<double>(max_iter)), pol);
|
||||
}
|
||||
|
||||
} //namespace policies
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
}} // namespaces boost/math
|
||||
|
||||
#endif // BOOST_MATH_POLICY_ERROR_HANDLING_HPP
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,69 +0,0 @@
|
||||
// Copyright 2008 Christophe Henry
|
||||
// henry UNDERSCORE christophe AT hotmail DOT com
|
||||
// This is an extended version of the state machine available in the boost::mpl library
|
||||
// Distributed under the same license as the original.
|
||||
// Copyright for the original version:
|
||||
// Copyright 2005 David Abrahams and Aleksey Gurtovoy. 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_MSM_BACK_TOOLS_H
|
||||
#define BOOST_MSM_BACK_TOOLS_H
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <boost/msm/back/common_types.hpp>
|
||||
#include <boost/msm/back/metafunctions.hpp>
|
||||
#include <boost/type_index.hpp>
|
||||
|
||||
namespace boost { namespace msm { namespace back
|
||||
{
|
||||
|
||||
// fills the array passed in with the state names in the correct order
|
||||
// the array must be big enough. To know the needed size, use mpl::size
|
||||
// on fsm::generate_state_set
|
||||
template <class stt>
|
||||
struct fill_state_names
|
||||
{
|
||||
fill_state_names(char const** names):m_names(names){}
|
||||
template <class StateType>
|
||||
void operator()(boost::msm::wrap<StateType> const&)
|
||||
{
|
||||
m_names[get_state_id<stt,StateType>::value]= type_id<StateType>().name_demangled();
|
||||
}
|
||||
private:
|
||||
char const** m_names;
|
||||
};
|
||||
|
||||
// fills the typeid-generated name of the given state in the string passed as argument
|
||||
template <class stt>
|
||||
struct get_state_name
|
||||
{
|
||||
get_state_name(std::string& name_to_fill, int state_id):m_name(name_to_fill),m_state_id(state_id){}
|
||||
template <class StateType>
|
||||
void operator()(boost::msm::wrap<StateType> const&)
|
||||
{
|
||||
if (get_state_id<stt,StateType>::value == m_state_id)
|
||||
{
|
||||
m_name = type_id<StateType>().name_demangled();
|
||||
}
|
||||
}
|
||||
private:
|
||||
std::string& m_name;
|
||||
int m_state_id;
|
||||
};
|
||||
|
||||
// displays the typeid of the given Type
|
||||
struct display_type
|
||||
{
|
||||
template <class Type>
|
||||
void operator()(boost::msm::wrap<Type> const&)
|
||||
{
|
||||
std::cout << type_id<Type>().name_demangled() << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
} } }//boost::msm::back
|
||||
#endif //BOOST_MSM_BACK_TOOLS_H
|
||||
@@ -1,345 +0,0 @@
|
||||
#ifndef DYNAMIC_PROPERTY_MAP_RG09302004_HPP
|
||||
#define DYNAMIC_PROPERTY_MAP_RG09302004_HPP
|
||||
|
||||
// Copyright 2004-5 The Trustees of Indiana University.
|
||||
|
||||
// Use, modification and distribution is 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)
|
||||
|
||||
// dynamic_property_map.hpp -
|
||||
// Support for runtime-polymorphic property maps. This header is factored
|
||||
// out of Doug Gregor's routines for reading GraphML files for use in reading
|
||||
// GraphViz graph files.
|
||||
|
||||
// Authors: Doug Gregor
|
||||
// Ronald Garcia
|
||||
//
|
||||
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/property_map/property_map.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/any.hpp>
|
||||
#include <boost/function/function3.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <typeinfo>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <stdexcept>
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
#include <boost/type.hpp>
|
||||
#include <boost/smart_ptr.hpp>
|
||||
#include <boost/type_index.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// read_value -
|
||||
// A wrapper around lexical_cast, which does not behave as
|
||||
// desired for std::string types.
|
||||
template<typename Value>
|
||||
inline Value read_value(const std::string& value)
|
||||
{ return boost::lexical_cast<Value>(value); }
|
||||
|
||||
template<>
|
||||
inline std::string read_value<std::string>(const std::string& value)
|
||||
{ return value; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
// dynamic_property_map -
|
||||
// This interface supports polymorphic manipulation of property maps.
|
||||
class dynamic_property_map
|
||||
{
|
||||
public:
|
||||
virtual ~dynamic_property_map() { }
|
||||
|
||||
virtual boost::any get(const any& key) = 0;
|
||||
virtual std::string get_string(const any& key) = 0;
|
||||
virtual void put(const any& key, const any& value) = 0;
|
||||
virtual type_index key() const = 0;
|
||||
virtual type_index value() const = 0;
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Property map exceptions
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct dynamic_property_exception : public std::exception {
|
||||
virtual ~dynamic_property_exception() throw() {}
|
||||
virtual const char* what() const throw() = 0;
|
||||
};
|
||||
|
||||
struct property_not_found : public dynamic_property_exception {
|
||||
std::string property;
|
||||
mutable std::string statement;
|
||||
property_not_found(const std::string& property) : property(property) {}
|
||||
virtual ~property_not_found() throw() {}
|
||||
|
||||
const char* what() const throw() {
|
||||
if(statement.empty())
|
||||
statement =
|
||||
std::string("Property not found: ") + property + ".";
|
||||
|
||||
return statement.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
struct dynamic_get_failure : public dynamic_property_exception {
|
||||
std::string property;
|
||||
mutable std::string statement;
|
||||
dynamic_get_failure(const std::string& property) : property(property) {}
|
||||
virtual ~dynamic_get_failure() throw() {}
|
||||
|
||||
const char* what() const throw() {
|
||||
if(statement.empty())
|
||||
statement =
|
||||
std::string(
|
||||
"dynamic property get cannot retrieve value for property: ")
|
||||
+ property + ".";
|
||||
|
||||
return statement.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
struct dynamic_const_put_error : public dynamic_property_exception {
|
||||
virtual ~dynamic_const_put_error() throw() {}
|
||||
|
||||
const char* what() const throw() {
|
||||
return "Attempt to put a value into a const property map: ";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
namespace detail {
|
||||
|
||||
// Trying to work around VC++ problem that seems to relate to having too many
|
||||
// functions named "get"
|
||||
template <typename PMap, typename Key>
|
||||
typename boost::property_traits<PMap>::reference
|
||||
get_wrapper_xxx(const PMap& pmap, const Key& key) {
|
||||
using boost::get;
|
||||
return get(pmap, key);
|
||||
}
|
||||
|
||||
//
|
||||
// dynamic_property_map_adaptor -
|
||||
// property-map adaptor to support runtime polymorphism.
|
||||
template<typename PropertyMap>
|
||||
class dynamic_property_map_adaptor : public dynamic_property_map
|
||||
{
|
||||
typedef typename property_traits<PropertyMap>::key_type key_type;
|
||||
typedef typename property_traits<PropertyMap>::value_type value_type;
|
||||
typedef typename property_traits<PropertyMap>::category category;
|
||||
|
||||
// do_put - overloaded dispatches from the put() member function.
|
||||
// Attempts to "put" to a property map that does not model
|
||||
// WritablePropertyMap result in a runtime exception.
|
||||
|
||||
// in_value must either hold an object of value_type or a string that
|
||||
// can be converted to value_type via iostreams.
|
||||
void do_put(const any& in_key, const any& in_value, mpl::bool_<true>)
|
||||
{
|
||||
using boost::put;
|
||||
|
||||
key_type key = any_cast<key_type>(in_key);
|
||||
if (in_value.type() == type_id<value_type>()) {
|
||||
put(property_map_, key, any_cast<value_type>(in_value));
|
||||
} else {
|
||||
// if in_value is an empty string, put a default constructed value_type.
|
||||
std::string v = any_cast<std::string>(in_value);
|
||||
if (v.empty()) {
|
||||
put(property_map_, key, value_type());
|
||||
} else {
|
||||
put(property_map_, key, detail::read_value<value_type>(v));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void do_put(const any&, const any&, mpl::bool_<false>)
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(dynamic_const_put_error());
|
||||
}
|
||||
|
||||
public:
|
||||
explicit dynamic_property_map_adaptor(const PropertyMap& property_map_)
|
||||
: property_map_(property_map_) { }
|
||||
|
||||
virtual boost::any get(const any& key)
|
||||
{
|
||||
return get_wrapper_xxx(property_map_, any_cast<key_type>(key));
|
||||
}
|
||||
|
||||
virtual std::string get_string(const any& key)
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << get_wrapper_xxx(property_map_, any_cast<key_type>(key));
|
||||
return out.str();
|
||||
}
|
||||
|
||||
virtual void put(const any& in_key, const any& in_value)
|
||||
{
|
||||
do_put(in_key, in_value,
|
||||
mpl::bool_<(is_convertible<category*,
|
||||
writable_property_map_tag*>::value)>());
|
||||
}
|
||||
|
||||
virtual type_index key() const { return type_id<key_type>(); }
|
||||
virtual type_index value() const { return type_id<value_type>(); }
|
||||
|
||||
PropertyMap& base() { return property_map_; }
|
||||
const PropertyMap& base() const { return property_map_; }
|
||||
|
||||
private:
|
||||
PropertyMap property_map_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
//
|
||||
// dynamic_properties -
|
||||
// container for dynamic property maps
|
||||
//
|
||||
struct dynamic_properties
|
||||
{
|
||||
typedef std::multimap<std::string, boost::shared_ptr<dynamic_property_map> >
|
||||
property_maps_type;
|
||||
typedef boost::function3<boost::shared_ptr<dynamic_property_map>,
|
||||
const std::string&,
|
||||
const boost::any&,
|
||||
const boost::any&> generate_fn_type;
|
||||
public:
|
||||
|
||||
typedef property_maps_type::iterator iterator;
|
||||
typedef property_maps_type::const_iterator const_iterator;
|
||||
|
||||
dynamic_properties() : generate_fn() { }
|
||||
dynamic_properties(const generate_fn_type& g) : generate_fn(g) {}
|
||||
|
||||
~dynamic_properties() {}
|
||||
|
||||
template<typename PropertyMap>
|
||||
dynamic_properties&
|
||||
property(const std::string& name, PropertyMap property_map_)
|
||||
{
|
||||
boost::shared_ptr<dynamic_property_map> pm(
|
||||
boost::make_shared<detail::dynamic_property_map_adaptor<PropertyMap> >(property_map_));
|
||||
property_maps.insert(property_maps_type::value_type(name, pm));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator begin() { return property_maps.begin(); }
|
||||
const_iterator begin() const { return property_maps.begin(); }
|
||||
iterator end() { return property_maps.end(); }
|
||||
const_iterator end() const { return property_maps.end(); }
|
||||
|
||||
iterator lower_bound(const std::string& name)
|
||||
{ return property_maps.lower_bound(name); }
|
||||
|
||||
const_iterator lower_bound(const std::string& name) const
|
||||
{ return property_maps.lower_bound(name); }
|
||||
|
||||
void
|
||||
insert(const std::string& name, boost::shared_ptr<dynamic_property_map> pm)
|
||||
{
|
||||
property_maps.insert(property_maps_type::value_type(name, pm));
|
||||
}
|
||||
|
||||
template<typename Key, typename Value>
|
||||
boost::shared_ptr<dynamic_property_map>
|
||||
generate(const std::string& name, const Key& key, const Value& value)
|
||||
{
|
||||
if(!generate_fn) {
|
||||
BOOST_THROW_EXCEPTION(property_not_found(name));
|
||||
} else {
|
||||
return generate_fn(name,key,value);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
property_maps_type property_maps;
|
||||
generate_fn_type generate_fn;
|
||||
};
|
||||
|
||||
template<typename Key, typename Value>
|
||||
bool
|
||||
put(const std::string& name, dynamic_properties& dp, const Key& key,
|
||||
const Value& value)
|
||||
{
|
||||
for (dynamic_properties::iterator i = dp.lower_bound(name);
|
||||
i != dp.end() && i->first == name; ++i) {
|
||||
if (i->second->key() == type_id<key>()) {
|
||||
i->second->put(key, value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
boost::shared_ptr<dynamic_property_map> new_map = dp.generate(name, key, value);
|
||||
if (new_map.get()) {
|
||||
new_map->put(key, value);
|
||||
dp.insert(name, new_map);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS
|
||||
template<typename Value, typename Key>
|
||||
Value
|
||||
get(const std::string& name, const dynamic_properties& dp, const Key& key)
|
||||
{
|
||||
for (dynamic_properties::const_iterator i = dp.lower_bound(name);
|
||||
i != dp.end() && i->first == name; ++i) {
|
||||
if (i->second->key() == type_id<key>())
|
||||
return any_cast<Value>(i->second->get(key));
|
||||
}
|
||||
|
||||
BOOST_THROW_EXCEPTION(dynamic_get_failure(name));
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename Value, typename Key>
|
||||
Value
|
||||
get(const std::string& name, const dynamic_properties& dp, const Key& key, type<Value>)
|
||||
{
|
||||
for (dynamic_properties::const_iterator i = dp.lower_bound(name);
|
||||
i != dp.end() && i->first == name; ++i) {
|
||||
if (i->second->key() == type_id<key>())
|
||||
return any_cast<Value>(i->second->get(key));
|
||||
}
|
||||
|
||||
BOOST_THROW_EXCEPTION(dynamic_get_failure(name));
|
||||
}
|
||||
|
||||
template<typename Key>
|
||||
std::string
|
||||
get(const std::string& name, const dynamic_properties& dp, const Key& key)
|
||||
{
|
||||
for (dynamic_properties::const_iterator i = dp.lower_bound(name);
|
||||
i != dp.end() && i->first == name; ++i) {
|
||||
if (i->second->key() == type_id<key>())
|
||||
return i->second->get_string(key);
|
||||
}
|
||||
|
||||
BOOST_THROW_EXCEPTION(dynamic_get_failure(name));
|
||||
}
|
||||
|
||||
// The easy way to ignore properties.
|
||||
inline
|
||||
boost::shared_ptr<boost::dynamic_property_map>
|
||||
ignore_other_properties(const std::string&,
|
||||
const boost::any&,
|
||||
const boost::any&) {
|
||||
return boost::shared_ptr<boost::dynamic_property_map>();
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // DYNAMIC_PROPERTY_MAP_RG09302004_HPP
|
||||
@@ -1,915 +0,0 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright (C) 2002-2006 Marcin Kalicinski
|
||||
// Copyright (C) 2009 Sebastian Redl
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
// For more information, see www.boost.org
|
||||
// ----------------------------------------------------------------------------
|
||||
#ifndef BOOST_PROPERTY_TREE_DETAIL_PTREE_IMPLEMENTATION_HPP_INCLUDED
|
||||
#define BOOST_PROPERTY_TREE_DETAIL_PTREE_IMPLEMENTATION_HPP_INCLUDED
|
||||
|
||||
#include <boost/iterator/iterator_adaptor.hpp>
|
||||
#include <boost/iterator/reverse_iterator.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/type_index.hpp>
|
||||
#include <boost/utility/swap.hpp>
|
||||
#include <memory>
|
||||
|
||||
#if (defined(BOOST_MSVC) && \
|
||||
(_MSC_FULL_VER >= 160000000 && _MSC_FULL_VER < 170000000)) || \
|
||||
(defined(BOOST_INTEL_WIN) && \
|
||||
defined(BOOST_DINKUMWARE_STDLIB))
|
||||
#define BOOST_PROPERTY_TREE_PAIR_BUG
|
||||
#endif
|
||||
|
||||
namespace boost { namespace property_tree
|
||||
{
|
||||
template <class K, class D, class C>
|
||||
struct basic_ptree<K, D, C>::subs
|
||||
{
|
||||
struct by_name {};
|
||||
// The actual child container.
|
||||
#if defined(BOOST_PROPERTY_TREE_PAIR_BUG)
|
||||
// MSVC 10 has moved std::pair's members to a base
|
||||
// class. Unfortunately this does break the interface.
|
||||
BOOST_STATIC_CONSTANT(unsigned,
|
||||
first_offset = offsetof(value_type, first));
|
||||
#endif
|
||||
typedef multi_index_container<value_type,
|
||||
multi_index::indexed_by<
|
||||
multi_index::sequenced<>,
|
||||
multi_index::ordered_non_unique<multi_index::tag<by_name>,
|
||||
#if defined(BOOST_PROPERTY_TREE_PAIR_BUG)
|
||||
multi_index::member_offset<value_type, const key_type,
|
||||
first_offset>,
|
||||
#else
|
||||
multi_index::member<value_type, const key_type,
|
||||
&value_type::first>,
|
||||
#endif
|
||||
key_compare
|
||||
>
|
||||
>
|
||||
> base_container;
|
||||
|
||||
// The by-name lookup index.
|
||||
typedef typename base_container::template index<by_name>::type
|
||||
by_name_index;
|
||||
|
||||
// Access functions for getting to the children of a tree.
|
||||
static base_container& ch(self_type *s) {
|
||||
return *static_cast<base_container*>(s->m_children);
|
||||
}
|
||||
static const base_container& ch(const self_type *s) {
|
||||
return *static_cast<const base_container*>(s->m_children);
|
||||
}
|
||||
static by_name_index& assoc(self_type *s) {
|
||||
return ch(s).BOOST_NESTED_TEMPLATE get<by_name>();
|
||||
}
|
||||
static const by_name_index& assoc(const self_type *s) {
|
||||
return ch(s).BOOST_NESTED_TEMPLATE get<by_name>();
|
||||
}
|
||||
};
|
||||
template <class K, class D, class C>
|
||||
class basic_ptree<K, D, C>::iterator : public boost::iterator_adaptor<
|
||||
iterator, typename subs::base_container::iterator, value_type>
|
||||
{
|
||||
friend class boost::iterator_core_access;
|
||||
typedef boost::iterator_adaptor<
|
||||
iterator, typename subs::base_container::iterator, value_type>
|
||||
baset;
|
||||
public:
|
||||
typedef typename baset::reference reference;
|
||||
iterator() {}
|
||||
explicit iterator(typename iterator::base_type b)
|
||||
: iterator::iterator_adaptor_(b)
|
||||
{}
|
||||
reference dereference() const
|
||||
{
|
||||
// multi_index doesn't allow modification of its values, because
|
||||
// indexes could sort by anything, and modification screws that up.
|
||||
// However, we only sort by the key, and it's protected against
|
||||
// modification in the value_type, so this const_cast is safe.
|
||||
return const_cast<reference>(*this->base_reference());
|
||||
}
|
||||
};
|
||||
template <class K, class D, class C>
|
||||
class basic_ptree<K, D, C>::const_iterator : public boost::iterator_adaptor<
|
||||
const_iterator, typename subs::base_container::const_iterator>
|
||||
{
|
||||
public:
|
||||
const_iterator() {}
|
||||
explicit const_iterator(typename const_iterator::base_type b)
|
||||
: const_iterator::iterator_adaptor_(b)
|
||||
{}
|
||||
const_iterator(iterator b)
|
||||
: const_iterator::iterator_adaptor_(b.base())
|
||||
{}
|
||||
};
|
||||
template <class K, class D, class C>
|
||||
class basic_ptree<K, D, C>::reverse_iterator
|
||||
: public boost::reverse_iterator<iterator>
|
||||
{
|
||||
public:
|
||||
reverse_iterator() {}
|
||||
explicit reverse_iterator(iterator b)
|
||||
: boost::reverse_iterator<iterator>(b)
|
||||
{}
|
||||
};
|
||||
template <class K, class D, class C>
|
||||
class basic_ptree<K, D, C>::const_reverse_iterator
|
||||
: public boost::reverse_iterator<const_iterator>
|
||||
{
|
||||
public:
|
||||
const_reverse_iterator() {}
|
||||
explicit const_reverse_iterator(const_iterator b)
|
||||
: boost::reverse_iterator<const_iterator>(b)
|
||||
{}
|
||||
const_reverse_iterator(
|
||||
typename basic_ptree<K, D, C>::reverse_iterator b)
|
||||
: boost::reverse_iterator<const_iterator>(b)
|
||||
{}
|
||||
};
|
||||
template <class K, class D, class C>
|
||||
class basic_ptree<K, D, C>::assoc_iterator
|
||||
: public boost::iterator_adaptor<assoc_iterator,
|
||||
typename subs::by_name_index::iterator,
|
||||
value_type>
|
||||
{
|
||||
friend class boost::iterator_core_access;
|
||||
typedef boost::iterator_adaptor<assoc_iterator,
|
||||
typename subs::by_name_index::iterator,
|
||||
value_type>
|
||||
baset;
|
||||
public:
|
||||
typedef typename baset::reference reference;
|
||||
assoc_iterator() {}
|
||||
explicit assoc_iterator(typename assoc_iterator::base_type b)
|
||||
: assoc_iterator::iterator_adaptor_(b)
|
||||
{}
|
||||
reference dereference() const
|
||||
{
|
||||
return const_cast<reference>(*this->base_reference());
|
||||
}
|
||||
};
|
||||
template <class K, class D, class C>
|
||||
class basic_ptree<K, D, C>::const_assoc_iterator
|
||||
: public boost::iterator_adaptor<const_assoc_iterator,
|
||||
typename subs::by_name_index::const_iterator>
|
||||
{
|
||||
public:
|
||||
const_assoc_iterator() {}
|
||||
explicit const_assoc_iterator(
|
||||
typename const_assoc_iterator::base_type b)
|
||||
: const_assoc_iterator::iterator_adaptor_(b)
|
||||
{}
|
||||
const_assoc_iterator(assoc_iterator b)
|
||||
: const_assoc_iterator::iterator_adaptor_(b.base())
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
// Big five
|
||||
|
||||
// Perhaps the children collection could be created on-demand only, to
|
||||
// reduce heap traffic. But that's a lot more work to implement.
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
basic_ptree<K, D, C>::basic_ptree()
|
||||
: m_children(new typename subs::base_container)
|
||||
{
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
basic_ptree<K, D, C>::basic_ptree(const data_type &d)
|
||||
: m_data(d), m_children(new typename subs::base_container)
|
||||
{
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
basic_ptree<K, D, C>::basic_ptree(const basic_ptree<K, D, C> &rhs)
|
||||
: m_data(rhs.m_data),
|
||||
m_children(new typename subs::base_container(subs::ch(&rhs)))
|
||||
{
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
basic_ptree<K, D, C> &
|
||||
basic_ptree<K, D, C>::operator =(const basic_ptree<K, D, C> &rhs)
|
||||
{
|
||||
self_type(rhs).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
basic_ptree<K, D, C>::~basic_ptree()
|
||||
{
|
||||
delete &subs::ch(this);
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
void basic_ptree<K, D, C>::swap(basic_ptree<K, D, C> &rhs)
|
||||
{
|
||||
boost::swap(m_data, rhs.m_data);
|
||||
// Void pointers, no ADL necessary
|
||||
std::swap(m_children, rhs.m_children);
|
||||
}
|
||||
|
||||
// Container view
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::size_type
|
||||
basic_ptree<K, D, C>::size() const
|
||||
{
|
||||
return subs::ch(this).size();
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::size_type
|
||||
basic_ptree<K, D, C>::max_size() const
|
||||
{
|
||||
return subs::ch(this).max_size();
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
bool basic_ptree<K, D, C>::empty() const
|
||||
{
|
||||
return subs::ch(this).empty();
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::iterator
|
||||
basic_ptree<K, D, C>::begin()
|
||||
{
|
||||
return iterator(subs::ch(this).begin());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::const_iterator
|
||||
basic_ptree<K, D, C>::begin() const
|
||||
{
|
||||
return const_iterator(subs::ch(this).begin());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::iterator
|
||||
basic_ptree<K, D, C>::end()
|
||||
{
|
||||
return iterator(subs::ch(this).end());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::const_iterator
|
||||
basic_ptree<K, D, C>::end() const
|
||||
{
|
||||
return const_iterator(subs::ch(this).end());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::reverse_iterator
|
||||
basic_ptree<K, D, C>::rbegin()
|
||||
{
|
||||
return reverse_iterator(this->end());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::const_reverse_iterator
|
||||
basic_ptree<K, D, C>::rbegin() const
|
||||
{
|
||||
return const_reverse_iterator(this->end());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::reverse_iterator
|
||||
basic_ptree<K, D, C>::rend()
|
||||
{
|
||||
return reverse_iterator(this->begin());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::const_reverse_iterator
|
||||
basic_ptree<K, D, C>::rend() const
|
||||
{
|
||||
return const_reverse_iterator(this->begin());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::value_type &
|
||||
basic_ptree<K, D, C>::front()
|
||||
{
|
||||
return const_cast<value_type&>(subs::ch(this).front());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
const typename basic_ptree<K, D, C>::value_type &
|
||||
basic_ptree<K, D, C>::front() const
|
||||
{
|
||||
return subs::ch(this).front();
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::value_type &
|
||||
basic_ptree<K, D, C>::back()
|
||||
{
|
||||
return const_cast<value_type&>(subs::ch(this).back());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
const typename basic_ptree<K, D, C>::value_type &
|
||||
basic_ptree<K, D, C>::back() const
|
||||
{
|
||||
return subs::ch(this).back();
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::iterator
|
||||
basic_ptree<K, D, C>::insert(iterator where, const value_type &value)
|
||||
{
|
||||
return iterator(subs::ch(this).insert(where.base(), value).first);
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class It> inline
|
||||
void basic_ptree<K, D, C>::insert(iterator where, It first, It last)
|
||||
{
|
||||
subs::ch(this).insert(where.base(), first, last);
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::iterator
|
||||
basic_ptree<K, D, C>::erase(iterator where)
|
||||
{
|
||||
return iterator(subs::ch(this).erase(where.base()));
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::iterator
|
||||
basic_ptree<K, D, C>::erase(iterator first, iterator last)
|
||||
{
|
||||
return iterator(subs::ch(this).erase(first.base(), last.base()));
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::iterator
|
||||
basic_ptree<K, D, C>::push_front(const value_type &value)
|
||||
{
|
||||
return iterator(subs::ch(this).push_front(value).first);
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::iterator
|
||||
basic_ptree<K, D, C>::push_back(const value_type &value)
|
||||
{
|
||||
return iterator(subs::ch(this).push_back(value).first);
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
void basic_ptree<K, D, C>::pop_front()
|
||||
{
|
||||
subs::ch(this).pop_front();
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
void basic_ptree<K, D, C>::pop_back()
|
||||
{
|
||||
subs::ch(this).pop_back();
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
void basic_ptree<K, D, C>::reverse()
|
||||
{
|
||||
subs::ch(this).reverse();
|
||||
}
|
||||
|
||||
namespace impl
|
||||
{
|
||||
struct by_first
|
||||
{
|
||||
template <typename P>
|
||||
bool operator ()(const P& lhs, const P& rhs) const {
|
||||
return lhs.first < rhs.first;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
void basic_ptree<K, D, C>::sort()
|
||||
{
|
||||
sort(impl::by_first());
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Compare> inline
|
||||
void basic_ptree<K, D, C>::sort(Compare comp)
|
||||
{
|
||||
subs::ch(this).sort(comp);
|
||||
}
|
||||
|
||||
// Equality
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
bool basic_ptree<K, D, C>::operator ==(
|
||||
const basic_ptree<K, D, C> &rhs) const
|
||||
{
|
||||
// The size test is cheap, so add it as an optimization
|
||||
return size() == rhs.size() && data() == rhs.data() &&
|
||||
subs::ch(this) == subs::ch(&rhs);
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
bool basic_ptree<K, D, C>::operator !=(
|
||||
const basic_ptree<K, D, C> &rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
// Associative view
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::assoc_iterator
|
||||
basic_ptree<K, D, C>::ordered_begin()
|
||||
{
|
||||
return assoc_iterator(subs::assoc(this).begin());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::const_assoc_iterator
|
||||
basic_ptree<K, D, C>::ordered_begin() const
|
||||
{
|
||||
return const_assoc_iterator(subs::assoc(this).begin());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::assoc_iterator
|
||||
basic_ptree<K, D, C>::not_found()
|
||||
{
|
||||
return assoc_iterator(subs::assoc(this).end());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::const_assoc_iterator
|
||||
basic_ptree<K, D, C>::not_found() const
|
||||
{
|
||||
return const_assoc_iterator(subs::assoc(this).end());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::assoc_iterator
|
||||
basic_ptree<K, D, C>::find(const key_type &key)
|
||||
{
|
||||
return assoc_iterator(subs::assoc(this).find(key));
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::const_assoc_iterator
|
||||
basic_ptree<K, D, C>::find(const key_type &key) const
|
||||
{
|
||||
return const_assoc_iterator(subs::assoc(this).find(key));
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
std::pair<
|
||||
typename basic_ptree<K, D, C>::assoc_iterator,
|
||||
typename basic_ptree<K, D, C>::assoc_iterator
|
||||
> basic_ptree<K, D, C>::equal_range(const key_type &key)
|
||||
{
|
||||
std::pair<typename subs::by_name_index::iterator,
|
||||
typename subs::by_name_index::iterator> r(
|
||||
subs::assoc(this).equal_range(key));
|
||||
return std::pair<assoc_iterator, assoc_iterator>(
|
||||
assoc_iterator(r.first), assoc_iterator(r.second));
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
std::pair<
|
||||
typename basic_ptree<K, D, C>::const_assoc_iterator,
|
||||
typename basic_ptree<K, D, C>::const_assoc_iterator
|
||||
> basic_ptree<K, D, C>::equal_range(const key_type &key) const
|
||||
{
|
||||
std::pair<typename subs::by_name_index::const_iterator,
|
||||
typename subs::by_name_index::const_iterator> r(
|
||||
subs::assoc(this).equal_range(key));
|
||||
return std::pair<const_assoc_iterator, const_assoc_iterator>(
|
||||
const_assoc_iterator(r.first), const_assoc_iterator(r.second));
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::size_type
|
||||
basic_ptree<K, D, C>::count(const key_type &key) const
|
||||
{
|
||||
return subs::assoc(this).count(key);
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::size_type
|
||||
basic_ptree<K, D, C>::erase(const key_type &key)
|
||||
{
|
||||
return subs::assoc(this).erase(key);
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::iterator
|
||||
basic_ptree<K, D, C>::to_iterator(assoc_iterator ai)
|
||||
{
|
||||
return iterator(subs::ch(this).
|
||||
BOOST_NESTED_TEMPLATE project<0>(ai.base()));
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::const_iterator
|
||||
basic_ptree<K, D, C>::to_iterator(const_assoc_iterator ai) const
|
||||
{
|
||||
return const_iterator(subs::ch(this).
|
||||
BOOST_NESTED_TEMPLATE project<0>(ai.base()));
|
||||
}
|
||||
|
||||
// Property tree view
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::data_type &
|
||||
basic_ptree<K, D, C>::data()
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
const typename basic_ptree<K, D, C>::data_type &
|
||||
basic_ptree<K, D, C>::data() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
void basic_ptree<K, D, C>::clear()
|
||||
{
|
||||
m_data = data_type();
|
||||
subs::ch(this).clear();
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
basic_ptree<K, D, C> &
|
||||
basic_ptree<K, D, C>::get_child(const path_type &path)
|
||||
{
|
||||
path_type p(path);
|
||||
self_type *n = walk_path(p);
|
||||
if (!n) {
|
||||
BOOST_PROPERTY_TREE_THROW(ptree_bad_path("No such node", path));
|
||||
}
|
||||
return *n;
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
const basic_ptree<K, D, C> &
|
||||
basic_ptree<K, D, C>::get_child(const path_type &path) const
|
||||
{
|
||||
return const_cast<self_type*>(this)->get_child(path);
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
basic_ptree<K, D, C> &
|
||||
basic_ptree<K, D, C>::get_child(const path_type &path,
|
||||
self_type &default_value)
|
||||
{
|
||||
path_type p(path);
|
||||
self_type *n = walk_path(p);
|
||||
return n ? *n : default_value;
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
const basic_ptree<K, D, C> &
|
||||
basic_ptree<K, D, C>::get_child(const path_type &path,
|
||||
const self_type &default_value) const
|
||||
{
|
||||
return const_cast<self_type*>(this)->get_child(path,
|
||||
const_cast<self_type&>(default_value));
|
||||
}
|
||||
|
||||
|
||||
template<class K, class D, class C>
|
||||
optional<basic_ptree<K, D, C> &>
|
||||
basic_ptree<K, D, C>::get_child_optional(const path_type &path)
|
||||
{
|
||||
path_type p(path);
|
||||
self_type *n = walk_path(p);
|
||||
if (!n) {
|
||||
return optional<self_type&>();
|
||||
}
|
||||
return *n;
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
optional<const basic_ptree<K, D, C> &>
|
||||
basic_ptree<K, D, C>::get_child_optional(const path_type &path) const
|
||||
{
|
||||
path_type p(path);
|
||||
self_type *n = walk_path(p);
|
||||
if (!n) {
|
||||
return optional<const self_type&>();
|
||||
}
|
||||
return *n;
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
basic_ptree<K, D, C> &
|
||||
basic_ptree<K, D, C>::put_child(const path_type &path,
|
||||
const self_type &value)
|
||||
{
|
||||
path_type p(path);
|
||||
self_type &parent = force_path(p);
|
||||
// Got the parent. Now get the correct child.
|
||||
key_type fragment = p.reduce();
|
||||
assoc_iterator el = parent.find(fragment);
|
||||
// If the new child exists, replace it.
|
||||
if(el != parent.not_found()) {
|
||||
return el->second = value;
|
||||
} else {
|
||||
return parent.push_back(value_type(fragment, value))->second;
|
||||
}
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
basic_ptree<K, D, C> &
|
||||
basic_ptree<K, D, C>::add_child(const path_type &path,
|
||||
const self_type &value)
|
||||
{
|
||||
path_type p(path);
|
||||
self_type &parent = force_path(p);
|
||||
// Got the parent.
|
||||
key_type fragment = p.reduce();
|
||||
return parent.push_back(value_type(fragment, value))->second;
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type, class Translator>
|
||||
typename boost::enable_if<detail::is_translator<Translator>, Type>::type
|
||||
basic_ptree<K, D, C>::get_value(Translator tr) const
|
||||
{
|
||||
if(boost::optional<Type> o = get_value_optional<Type>(tr)) {
|
||||
return *o;
|
||||
}
|
||||
BOOST_PROPERTY_TREE_THROW(ptree_bad_data(
|
||||
std::string("conversion of data to type \"") +
|
||||
type_id<Type>().name_demangled() + "\" failed", data()));
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type> inline
|
||||
Type basic_ptree<K, D, C>::get_value() const
|
||||
{
|
||||
return get_value<Type>(
|
||||
typename translator_between<data_type, Type>::type());
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type, class Translator> inline
|
||||
Type basic_ptree<K, D, C>::get_value(const Type &default_value,
|
||||
Translator tr) const
|
||||
{
|
||||
return get_value_optional<Type>(tr).get_value_or(default_value);
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template <class Ch, class Translator>
|
||||
typename boost::enable_if<
|
||||
detail::is_character<Ch>,
|
||||
std::basic_string<Ch>
|
||||
>::type
|
||||
basic_ptree<K, D, C>::get_value(const Ch *default_value, Translator tr)const
|
||||
{
|
||||
return get_value<std::basic_string<Ch>, Translator>(default_value, tr);
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type> inline
|
||||
typename boost::disable_if<detail::is_translator<Type>, Type>::type
|
||||
basic_ptree<K, D, C>::get_value(const Type &default_value) const
|
||||
{
|
||||
return get_value(default_value,
|
||||
typename translator_between<data_type, Type>::type());
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template <class Ch>
|
||||
typename boost::enable_if<
|
||||
detail::is_character<Ch>,
|
||||
std::basic_string<Ch>
|
||||
>::type
|
||||
basic_ptree<K, D, C>::get_value(const Ch *default_value) const
|
||||
{
|
||||
return get_value< std::basic_string<Ch> >(default_value);
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type, class Translator> inline
|
||||
optional<Type> basic_ptree<K, D, C>::get_value_optional(
|
||||
Translator tr) const
|
||||
{
|
||||
return tr.get_value(data());
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type> inline
|
||||
optional<Type> basic_ptree<K, D, C>::get_value_optional() const
|
||||
{
|
||||
return get_value_optional<Type>(
|
||||
typename translator_between<data_type, Type>::type());
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type, class Translator> inline
|
||||
typename boost::enable_if<detail::is_translator<Translator>, Type>::type
|
||||
basic_ptree<K, D, C>::get(const path_type &path,
|
||||
Translator tr) const
|
||||
{
|
||||
return get_child(path).BOOST_NESTED_TEMPLATE get_value<Type>(tr);
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type> inline
|
||||
Type basic_ptree<K, D, C>::get(const path_type &path) const
|
||||
{
|
||||
return get_child(path).BOOST_NESTED_TEMPLATE get_value<Type>();
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type, class Translator> inline
|
||||
Type basic_ptree<K, D, C>::get(const path_type &path,
|
||||
const Type &default_value,
|
||||
Translator tr) const
|
||||
{
|
||||
return get_optional<Type>(path, tr).get_value_or(default_value);
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template <class Ch, class Translator>
|
||||
typename boost::enable_if<
|
||||
detail::is_character<Ch>,
|
||||
std::basic_string<Ch>
|
||||
>::type
|
||||
basic_ptree<K, D, C>::get(
|
||||
const path_type &path, const Ch *default_value, Translator tr) const
|
||||
{
|
||||
return get<std::basic_string<Ch>, Translator>(path, default_value, tr);
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type> inline
|
||||
typename boost::disable_if<detail::is_translator<Type>, Type>::type
|
||||
basic_ptree<K, D, C>::get(const path_type &path,
|
||||
const Type &default_value) const
|
||||
{
|
||||
return get_optional<Type>(path).get_value_or(default_value);
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template <class Ch>
|
||||
typename boost::enable_if<
|
||||
detail::is_character<Ch>,
|
||||
std::basic_string<Ch>
|
||||
>::type
|
||||
basic_ptree<K, D, C>::get(
|
||||
const path_type &path, const Ch *default_value) const
|
||||
{
|
||||
return get< std::basic_string<Ch> >(path, default_value);
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type, class Translator>
|
||||
optional<Type> basic_ptree<K, D, C>::get_optional(const path_type &path,
|
||||
Translator tr) const
|
||||
{
|
||||
if (optional<const self_type&> child = get_child_optional(path))
|
||||
return child.get().
|
||||
BOOST_NESTED_TEMPLATE get_value_optional<Type>(tr);
|
||||
else
|
||||
return optional<Type>();
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type>
|
||||
optional<Type> basic_ptree<K, D, C>::get_optional(
|
||||
const path_type &path) const
|
||||
{
|
||||
if (optional<const self_type&> child = get_child_optional(path))
|
||||
return child.get().BOOST_NESTED_TEMPLATE get_value_optional<Type>();
|
||||
else
|
||||
return optional<Type>();
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type, class Translator>
|
||||
void basic_ptree<K, D, C>::put_value(const Type &value, Translator tr)
|
||||
{
|
||||
if(optional<data_type> o = tr.put_value(value)) {
|
||||
data() = *o;
|
||||
} else {
|
||||
BOOST_PROPERTY_TREE_THROW(ptree_bad_data(
|
||||
std::string("conversion of type \"") + type_id<Type>().name_demangled() +
|
||||
"\" to data failed", boost::any()));
|
||||
}
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type> inline
|
||||
void basic_ptree<K, D, C>::put_value(const Type &value)
|
||||
{
|
||||
put_value(value, typename translator_between<data_type, Type>::type());
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type, typename Translator>
|
||||
basic_ptree<K, D, C> & basic_ptree<K, D, C>::put(
|
||||
const path_type &path, const Type &value, Translator tr)
|
||||
{
|
||||
if(optional<self_type &> child = get_child_optional(path)) {
|
||||
child.get().put_value(value, tr);
|
||||
return *child;
|
||||
} else {
|
||||
self_type &child2 = put_child(path, self_type());
|
||||
child2.put_value(value, tr);
|
||||
return child2;
|
||||
}
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type> inline
|
||||
basic_ptree<K, D, C> & basic_ptree<K, D, C>::put(
|
||||
const path_type &path, const Type &value)
|
||||
{
|
||||
return put(path, value,
|
||||
typename translator_between<data_type, Type>::type());
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type, typename Translator> inline
|
||||
basic_ptree<K, D, C> & basic_ptree<K, D, C>::add(
|
||||
const path_type &path, const Type &value, Translator tr)
|
||||
{
|
||||
self_type &child = add_child(path, self_type());
|
||||
child.put_value(value, tr);
|
||||
return child;
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type> inline
|
||||
basic_ptree<K, D, C> & basic_ptree<K, D, C>::add(
|
||||
const path_type &path, const Type &value)
|
||||
{
|
||||
return add(path, value,
|
||||
typename translator_between<data_type, Type>::type());
|
||||
}
|
||||
|
||||
|
||||
template<class K, class D, class C>
|
||||
basic_ptree<K, D, C> *
|
||||
basic_ptree<K, D, C>::walk_path(path_type &p) const
|
||||
{
|
||||
if(p.empty()) {
|
||||
// I'm the child we're looking for.
|
||||
return const_cast<basic_ptree*>(this);
|
||||
}
|
||||
// Recurse down the tree to find the path.
|
||||
key_type fragment = p.reduce();
|
||||
const_assoc_iterator el = find(fragment);
|
||||
if(el == not_found()) {
|
||||
// No such child.
|
||||
return 0;
|
||||
}
|
||||
// Not done yet, recurse.
|
||||
return el->second.walk_path(p);
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
basic_ptree<K, D, C> & basic_ptree<K, D, C>::force_path(path_type &p)
|
||||
{
|
||||
BOOST_ASSERT(!p.empty() && "Empty path not allowed for put_child.");
|
||||
if(p.single()) {
|
||||
// I'm the parent we're looking for.
|
||||
return *this;
|
||||
}
|
||||
key_type fragment = p.reduce();
|
||||
assoc_iterator el = find(fragment);
|
||||
// If we've found an existing child, go down that path. Else
|
||||
// create a new one.
|
||||
self_type& child = el == not_found() ?
|
||||
push_back(value_type(fragment, self_type()))->second : el->second;
|
||||
return child.force_path(p);
|
||||
}
|
||||
|
||||
// Free functions
|
||||
|
||||
template<class K, class D, class C>
|
||||
inline void swap(basic_ptree<K, D, C> &pt1, basic_ptree<K, D, C> &pt2)
|
||||
{
|
||||
pt1.swap(pt2);
|
||||
}
|
||||
|
||||
} }
|
||||
|
||||
#if defined(BOOST_PROPERTY_TREE_PAIR_BUG)
|
||||
#undef BOOST_PROPERTY_TREE_PAIR_BUG
|
||||
#endif
|
||||
|
||||
#endif
|
||||
89
test/Jamfile.v2
Normal file
89
test/Jamfile.v2
Normal file
@@ -0,0 +1,89 @@
|
||||
# Copyright 2012-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)
|
||||
#
|
||||
|
||||
import testing ;
|
||||
import feature ;
|
||||
import os ;
|
||||
|
||||
import ../../config/checks/config : requires ;
|
||||
|
||||
project
|
||||
: source-location .
|
||||
: requirements
|
||||
[ requires cxx11_rvalue_references ]
|
||||
;
|
||||
|
||||
# Variable that contains all the stuff required for linking together <rtti>on and <rtti>off
|
||||
compat = <define>BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY ;
|
||||
|
||||
# Making own `nortti` that is link compatible.
|
||||
# We explicitly define BOOST_NO_RTTI because it sometimes can not be detected by build system.
|
||||
nortti = <toolset>gcc:<cxxflags>"-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID" <toolset>clang:<cxxflags>"-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID" <toolset>intel:<cxxflags>"-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID" <toolset>darwin:<cxxflags>"-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID" <toolset>msvc:<cxxflags>"/GR-" ;
|
||||
|
||||
norttidefines = <toolset>gcc:<cxxflags>"-DBOOST_NO_RTTI -DBOOST_NO_TYPEID" <toolset>clang:<cxxflags>"-DBOOST_NO_RTTI -DBOOST_NO_TYPEID" <toolset>intel:<cxxflags>"-DBOOST_NO_RTTI -DBOOST_NO_TYPEID" <toolset>darwin:<cxxflags>"-DBOOST_NO_RTTI -DBOOST_NO_TYPEID" <toolset>msvc:<cxxflags>"-DBOOST_NO_RTTI" ;
|
||||
|
||||
|
||||
# Making libraries that CANNOT work between rtti-on/rtti-off modules
|
||||
obj test_lib_nortti-obj : test_lib.cpp : <link>shared <rtti>off $(norttidefines) ;
|
||||
obj test_lib_anonymous_nortti-obj : test_lib_anonymous.cpp : <link>shared <rtti>off $(norttidefines) ;
|
||||
lib test_lib_nortti : test_lib_nortti-obj : <link>shared <rtti>off $(norttidefines) ;
|
||||
lib test_lib_anonymous_nortti : test_lib_anonymous_nortti-obj : <link>shared <rtti>off $(norttidefines) ;
|
||||
|
||||
obj test_lib_rtti-obj : test_lib.cpp : <link>shared ;
|
||||
obj test_lib_anonymous_rtti-obj : test_lib_anonymous.cpp : <link>shared ;
|
||||
lib test_lib_rtti : test_lib_rtti-obj : <link>shared ;
|
||||
lib test_lib_anonymous_rtti : test_lib_anonymous_rtti-obj : <link>shared ;
|
||||
|
||||
# Making libraries that can work between rtti-on/rtti-off modules
|
||||
obj test_lib_nortti_compat-obj : test_lib.cpp : <link>shared $(nortti) $(compat) ;
|
||||
obj test_lib_rtti_compat-obj : test_lib.cpp : <link>shared $(nortti) $(compat) ;
|
||||
lib test_lib_nortti_compat : test_lib_nortti_compat-obj : <link>shared $(nortti) $(compat) ;
|
||||
lib test_lib_rtti_compat : test_lib_rtti_compat-obj : <link>shared $(nortti) $(compat) ;
|
||||
|
||||
exe testing_crossmodule_anonymous_no_rtti : testing_crossmodule_anonymous.cpp test_lib_anonymous_nortti : <rtti>off $(norttidefines) ;
|
||||
|
||||
test-suite type_index
|
||||
:
|
||||
[ run type_index_test.cpp ]
|
||||
[ run type_index_runtime_cast_test.cpp ]
|
||||
[ run type_index_constexpr_test.cpp ]
|
||||
[ run type_index_test.cpp : : : <rtti>off $(norttidefines) : type_index_test_no_rtti ]
|
||||
[ run ctti_print_name.cpp : : : <test-info>always_show_run_output ]
|
||||
[ run testing_crossmodule.cpp test_lib_rtti ]
|
||||
[ run testing_crossmodule.cpp test_lib_nortti : : : <rtti>off $(norttidefines) : testing_crossmodule_no_rtti ]
|
||||
[ run testing_crossmodule_anonymous.cpp test_lib_anonymous_rtti : : : <test-info>always_show_run_output ]
|
||||
[ run compare_ctti_stl.cpp ]
|
||||
[ run track_13621.cpp ]
|
||||
|
||||
[ compile-fail type_index_test_ctti_copy_fail.cpp ]
|
||||
[ compile-fail type_index_test_ctti_construct_fail.cpp ]
|
||||
[ compile type_index_test_ctti_alignment.cpp ]
|
||||
|
||||
# Mixing RTTI on and off
|
||||
|
||||
# MSVC sometimes overrides the /GR-, without `detect_missmatch` this test may link.
|
||||
# TODO: Disabled on MSVC. Enable again when there'll be an understanding of how to write this test correctly wor MSVC.
|
||||
[ link-fail testing_crossmodule.cpp test_lib_rtti : $(nortti) <toolset>msvc:<build>no : link_fail_nortti_rtti ]
|
||||
[ link-fail testing_crossmodule.cpp test_lib_nortti : <toolset>msvc:<build>no : link_fail_rtti_nortti ]
|
||||
|
||||
[ run testing_crossmodule.cpp test_lib_rtti_compat : : : $(nortti) $(compat) : testing_crossmodule_nortti_rtti_compat ]
|
||||
[ run testing_crossmodule.cpp test_lib_nortti_compat : : : $(compat) : testing_crossmodule_rtti_nortti_compat ]
|
||||
;
|
||||
|
||||
# Assuring that examples compile and run. Adding sources from `examples` directory to the `type_index` test suite.
|
||||
for local p in [ glob ../examples/*.cpp ]
|
||||
{
|
||||
# RTTI on
|
||||
type_index += [ run $(p) ] ;
|
||||
|
||||
# RTTI off
|
||||
local target_name = $(p[1]:B)_no_rtti ;
|
||||
if $(target_name) != "table_of_names_no_rtti"
|
||||
{
|
||||
type_index += [ run $(p) : : : <rtti>off $(norttidefines) : $(target_name) ] ;
|
||||
}
|
||||
}
|
||||
|
||||
87
test/appveyor.yml
Normal file
87
test/appveyor.yml
Normal file
@@ -0,0 +1,87 @@
|
||||
# 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 2016-2023 Antony Polukhin.
|
||||
|
||||
#
|
||||
# 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.64.{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 libs/unordered # Boost.TypeIndex examples need Boost.Unordered
|
||||
|
||||
- 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:
|
||||
67
test/compare_ctti_stl.cpp
Normal file
67
test/compare_ctti_stl.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
// Copyright Klemens Morgenstern, 2012-2015.
|
||||
// Copyright 2019-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)
|
||||
|
||||
#include <boost/type_index/ctti_type_index.hpp>
|
||||
#include <boost/type_index/stl_type_index.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
|
||||
namespace my_namespace1 {
|
||||
class my_class{};
|
||||
}
|
||||
|
||||
|
||||
namespace my_namespace2 {
|
||||
class my_class{};
|
||||
}
|
||||
|
||||
namespace my_namespace3
|
||||
{
|
||||
template<typename T, typename U>
|
||||
struct my_template {};
|
||||
|
||||
}
|
||||
|
||||
#if !defined( BOOST_NO_RTTI )
|
||||
|
||||
template<typename T>
|
||||
void compare()
|
||||
{
|
||||
typedef boost::typeindex::ctti_type_index ctti;
|
||||
typedef boost::typeindex::stl_type_index stl;
|
||||
BOOST_TEST_EQ(
|
||||
ctti::type_id<int>().pretty_name(),
|
||||
stl::type_id<int>().pretty_name()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
compare<void>();
|
||||
compare<int>();
|
||||
compare<double*>();
|
||||
compare<const double&>();
|
||||
compare<my_namespace1::my_class>();
|
||||
|
||||
compare<my_namespace3::my_template<
|
||||
my_namespace1::my_class,
|
||||
my_namespace2::my_class> >();
|
||||
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
44
test/ctti_print_name.cpp
Normal file
44
test/ctti_print_name.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// Copyright 2012-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)
|
||||
|
||||
#include <iostream>
|
||||
|
||||
// This cpp file:
|
||||
// * tests BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING macro
|
||||
// * outputs full ctti name so that TypeIndex library could be adjust to new compiler without requesting regression tester's help
|
||||
#define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING (0,0,false,"")
|
||||
#include <boost/type_index/ctti_type_index.hpp>
|
||||
|
||||
namespace user_defined_namespace {
|
||||
class user_defined_class {};
|
||||
}
|
||||
|
||||
class empty
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace boost::typeindex;
|
||||
|
||||
std::cout << "int: "
|
||||
<< ctti_type_index::type_id<int>() << '\n';
|
||||
|
||||
std::cout << "double: "
|
||||
<< ctti_type_index::type_id<double>() << '\n';
|
||||
|
||||
std::cout << "user_defined_namespace::user_defined_class: "
|
||||
<< ctti_type_index::type_id<user_defined_namespace::user_defined_class>() << '\n';
|
||||
|
||||
|
||||
std::cout << "empty:"
|
||||
<< ctti_type_index::type_id<empty>() << '\n';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
40
test/test_lib.cpp
Normal file
40
test/test_lib.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// Copyright 2012-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 TEST_LIB_SOURCE
|
||||
#include "test_lib.hpp"
|
||||
|
||||
namespace user_defined_namespace {
|
||||
class user_defined{};
|
||||
}
|
||||
|
||||
namespace test_lib {
|
||||
|
||||
boost::typeindex::type_index get_integer() {
|
||||
return boost::typeindex::type_id<int>();
|
||||
}
|
||||
|
||||
boost::typeindex::type_index get_user_defined_class() {
|
||||
return boost::typeindex::type_id<user_defined_namespace::user_defined>();
|
||||
}
|
||||
|
||||
boost::typeindex::type_index get_const_integer() {
|
||||
return boost::typeindex::type_id_with_cvr<const int>();
|
||||
}
|
||||
|
||||
boost::typeindex::type_index get_const_user_defined_class() {
|
||||
return boost::typeindex::type_id_with_cvr<const user_defined_namespace::user_defined>();
|
||||
}
|
||||
|
||||
#if !defined(BOOST_HAS_PRAGMA_DETECT_MISMATCH) || !defined(_CPPRTTI)
|
||||
// Just do nothing
|
||||
void accept_typeindex(const boost::typeindex::type_index&) {}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) Antony Polukhin, 2012-2013.
|
||||
// Copyright 2012-2023 Antony Polukhin.
|
||||
//
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
@@ -25,14 +25,16 @@
|
||||
|
||||
namespace test_lib {
|
||||
|
||||
TEST_LIB_DECL boost::type_index get_integer();
|
||||
TEST_LIB_DECL boost::type_index get_user_defined_class();
|
||||
TEST_LIB_DECL boost::typeindex::type_index get_integer();
|
||||
TEST_LIB_DECL boost::typeindex::type_index get_user_defined_class();
|
||||
|
||||
TEST_LIB_DECL boost::type_index get_const_integer();
|
||||
TEST_LIB_DECL boost::type_index get_const_user_defined_class();
|
||||
TEST_LIB_DECL boost::typeindex::type_index get_const_integer();
|
||||
TEST_LIB_DECL boost::typeindex::type_index get_const_user_defined_class();
|
||||
|
||||
#if !defined(BOOST_HAS_PRAGMA_DETECT_MISMATCH) || !defined(_CPPRTTI)
|
||||
// This is required for checking RTTI on/off linkage
|
||||
TEST_LIB_DECL void accept_typeindex(const boost::type_index&);
|
||||
TEST_LIB_DECL void accept_typeindex(const boost::typeindex::type_index&);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
27
test/test_lib_anonymous.cpp
Normal file
27
test/test_lib_anonymous.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// Copyright 2012-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 TEST_LIB_SOURCE
|
||||
#include "test_lib_anonymous.hpp"
|
||||
|
||||
namespace {
|
||||
class user_defined{};
|
||||
} // anonymous namespace
|
||||
|
||||
namespace test_lib {
|
||||
|
||||
boost::typeindex::type_index get_anonymous_user_defined_class() {
|
||||
return boost::typeindex::type_id<user_defined>();
|
||||
}
|
||||
|
||||
boost::typeindex::type_index get_const_anonymous_user_defined_class() {
|
||||
return boost::typeindex::type_id_with_cvr<const user_defined>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
34
test/test_lib_anonymous.hpp
Normal file
34
test/test_lib_anonymous.hpp
Normal file
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// Copyright 2012-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)
|
||||
//
|
||||
|
||||
#ifndef BOOST_TYPE_INDEX_TESTS_TEST_LIB_ANONYMOUS_HPP
|
||||
#define BOOST_TYPE_INDEX_TESTS_TEST_LIB_ANONYMOUS_HPP
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
#if defined(_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/type_index.hpp>
|
||||
|
||||
// This is ALWAYS a dynamic library
|
||||
#if defined(TEST_LIB_SOURCE)
|
||||
# define TEST_LIB_DECL BOOST_SYMBOL_EXPORT
|
||||
# else
|
||||
# define TEST_LIB_DECL BOOST_SYMBOL_IMPORT
|
||||
# endif
|
||||
|
||||
namespace test_lib {
|
||||
|
||||
TEST_LIB_DECL boost::typeindex::type_index get_anonymous_user_defined_class();
|
||||
TEST_LIB_DECL boost::typeindex::type_index get_const_anonymous_user_defined_class();
|
||||
|
||||
}
|
||||
|
||||
#endif // BOOST_TYPE_INDEX_TESTS_TEST_LIB_ANONYMOUS_HPP
|
||||
|
||||
57
test/testing_crossmodule.cpp
Normal file
57
test/testing_crossmodule.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
//
|
||||
// Copyright 2012-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)
|
||||
|
||||
#include <boost/type_index.hpp>
|
||||
#include "test_lib.hpp"
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
namespace user_defined_namespace {
|
||||
class user_defined{};
|
||||
}
|
||||
|
||||
void comparing_types_between_modules()
|
||||
{
|
||||
boost::typeindex::type_index t_const_int = boost::typeindex::type_id_with_cvr<const int>();
|
||||
boost::typeindex::type_index t_int = boost::typeindex::type_id<int>();
|
||||
|
||||
BOOST_TEST_EQ(t_int, test_lib::get_integer());
|
||||
BOOST_TEST_EQ(t_const_int, test_lib::get_const_integer());
|
||||
BOOST_TEST_NE(t_const_int, test_lib::get_integer());
|
||||
BOOST_TEST_NE(t_int, test_lib::get_const_integer());
|
||||
|
||||
|
||||
boost::typeindex::type_index t_const_userdef
|
||||
= boost::typeindex::type_id_with_cvr<const user_defined_namespace::user_defined>();
|
||||
boost::typeindex::type_index t_userdef
|
||||
= boost::typeindex::type_id<user_defined_namespace::user_defined>();
|
||||
|
||||
BOOST_TEST_EQ(t_userdef, test_lib::get_user_defined_class());
|
||||
BOOST_TEST_EQ(t_const_userdef, test_lib::get_const_user_defined_class());
|
||||
BOOST_TEST_NE(t_const_userdef, test_lib::get_user_defined_class());
|
||||
BOOST_TEST_NE(t_userdef, test_lib::get_const_user_defined_class());
|
||||
|
||||
|
||||
BOOST_TEST_NE(t_userdef, test_lib::get_integer());
|
||||
BOOST_TEST_NE(t_const_userdef, test_lib::get_integer());
|
||||
BOOST_TEST_NE(t_int, test_lib::get_user_defined_class());
|
||||
BOOST_TEST_NE(t_const_int, test_lib::get_const_user_defined_class());
|
||||
|
||||
// MSVC supports detect_missmatch pragma, but /GR- silently switch disable the link time check.
|
||||
// /GR- undefies the _CPPRTTI macro. Using it to detect working detect_missmatch pragma.
|
||||
#if !defined(BOOST_HAS_PRAGMA_DETECT_MISMATCH) || !defined(_CPPRTTI)
|
||||
test_lib::accept_typeindex(t_int);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
comparing_types_between_modules();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
48
test/testing_crossmodule_anonymous.cpp
Normal file
48
test/testing_crossmodule_anonymous.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
//
|
||||
// Copyright 2012-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)
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
#include <boost/type_index.hpp>
|
||||
#include "test_lib_anonymous.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#define BOOST_CHECK_NE(x, y) BOOST_CHECK(x != y)
|
||||
|
||||
namespace {
|
||||
class user_defined{};
|
||||
}
|
||||
|
||||
void comparing_anonymous_types_between_modules()
|
||||
{
|
||||
boost::typeindex::type_index t_const_userdef = boost::typeindex::type_id_with_cvr<const user_defined>();
|
||||
boost::typeindex::type_index t_userdef = boost::typeindex::type_id<user_defined>();
|
||||
|
||||
// Known to fail on Clang and old versions of GCC.
|
||||
//BOOST_TEST_NE(t_userdef, test_lib::get_anonymous_user_defined_class());
|
||||
//BOOST_TEST_NE(t_const_userdef, test_lib::get_const_anonymous_user_defined_class());
|
||||
|
||||
std::cout
|
||||
<< "t_userdef == " << t_userdef
|
||||
<< ", test_lib::get_anonymous_user_defined_class() == " << test_lib::get_anonymous_user_defined_class()
|
||||
<< '\n';
|
||||
std::cout
|
||||
<< "t_const_userdef == " << t_const_userdef
|
||||
<< ", test_lib::get_const_anonymous_user_defined_class() == " << test_lib::get_const_anonymous_user_defined_class()
|
||||
<< '\n';
|
||||
|
||||
BOOST_TEST_NE(t_const_userdef, test_lib::get_anonymous_user_defined_class());
|
||||
BOOST_TEST_NE(t_userdef, test_lib::get_const_anonymous_user_defined_class());
|
||||
}
|
||||
|
||||
int main() {
|
||||
comparing_anonymous_types_between_modules();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
23
test/track_13621.cpp
Normal file
23
test/track_13621.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// Copyright 2018-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)
|
||||
|
||||
#include <boost/type_index/ctti_type_index.hpp>
|
||||
#include <string>
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
class empty
|
||||
{
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
std::string name = boost::typeindex::ctti_type_index::type_id<empty>().pretty_name();
|
||||
BOOST_TEST(name.find("empty") != std::string::npos);
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
157
test/type_index_constexpr_test.cpp
Normal file
157
test/type_index_constexpr_test.cpp
Normal file
@@ -0,0 +1,157 @@
|
||||
//
|
||||
// Copyright 2015-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)
|
||||
|
||||
#include <boost/type_index/ctti_type_index.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
const char* hello1 = "Hello word";
|
||||
const char* hello1_end = hello1 + sizeof("Hello word");
|
||||
const char* hello2 = "Hello word, pal!";
|
||||
const char* hello2_end = hello2 + sizeof("Hello word, pal!");
|
||||
|
||||
void strcmp_same() {
|
||||
using boost::typeindex::detail::constexpr_strcmp;
|
||||
|
||||
BOOST_TEST(
|
||||
constexpr_strcmp(hello1, hello1) == 0
|
||||
);
|
||||
|
||||
BOOST_TEST(
|
||||
constexpr_strcmp(hello2, hello2) == 0
|
||||
);
|
||||
|
||||
BOOST_TEST(
|
||||
constexpr_strcmp(hello1, hello2) != 0
|
||||
);
|
||||
|
||||
BOOST_TEST(
|
||||
constexpr_strcmp(hello2, hello1) != 0
|
||||
);
|
||||
|
||||
BOOST_TEST(
|
||||
(constexpr_strcmp(hello2, hello1) < 0)
|
||||
==
|
||||
(std::strcmp(hello2, hello1) < 0)
|
||||
);
|
||||
|
||||
BOOST_TEST(
|
||||
(constexpr_strcmp(hello1, hello2) < 0)
|
||||
==
|
||||
(std::strcmp(hello1, hello2) < 0)
|
||||
);
|
||||
}
|
||||
|
||||
void search_same() {
|
||||
using boost::typeindex::detail::constexpr_search;
|
||||
BOOST_TEST(
|
||||
constexpr_search(hello1, hello1_end, hello2, hello2_end) == std::search(hello1, hello1_end, hello2, hello2_end)
|
||||
);
|
||||
|
||||
BOOST_TEST(
|
||||
constexpr_search(hello2, hello2_end, hello1, hello1_end) == std::search(hello2, hello2_end, hello1, hello1_end)
|
||||
);
|
||||
|
||||
const char* word = "word";
|
||||
const char* word_end = word + sizeof("word") - 1;
|
||||
BOOST_TEST(
|
||||
constexpr_search(hello1, hello1_end, word, word_end) == std::search(hello1, hello1_end, word, word_end)
|
||||
);
|
||||
|
||||
BOOST_TEST(
|
||||
constexpr_search(hello2, hello2_end, word, word_end) == std::search(hello2, hello2_end, word, word_end)
|
||||
);
|
||||
}
|
||||
|
||||
template <class T, std::size_t N>
|
||||
BOOST_CXX14_CONSTEXPR bool in_namespace(const char (&ns)[N]) BOOST_NOEXCEPT {
|
||||
BOOST_CXX14_CONSTEXPR const char* name = boost::typeindex::ctti_type_index::type_id<T>().raw_name();
|
||||
for (std::size_t i = 0; i < N - 1; ++i)
|
||||
if (name[i] != ns[i])
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
BOOST_CXX14_CONSTEXPR bool is_boost_namespace() BOOST_NOEXCEPT {
|
||||
return in_namespace<T>("boost::") || in_namespace<T>("class boost::") || in_namespace<T>("struct boost::");
|
||||
}
|
||||
|
||||
void constexpr_test() {
|
||||
using namespace boost::typeindex;
|
||||
|
||||
BOOST_CXX14_CONSTEXPR ctti_type_index t_int0 = ctti_type_index::type_id<int>();
|
||||
(void)t_int0;
|
||||
|
||||
BOOST_CXX14_CONSTEXPR ctti_type_index t_short0 = ctti_type_index::type_id<short>();
|
||||
(void)t_short0;
|
||||
|
||||
BOOST_CXX14_CONSTEXPR ctti_type_index t_int1 = ctti_type_index::type_id<int>();
|
||||
(void)t_int1;
|
||||
|
||||
BOOST_CXX14_CONSTEXPR ctti_type_index t_short1 = ctti_type_index::type_id<short>();
|
||||
(void)t_short1;
|
||||
|
||||
// Following tests are known to fail on _MSC_VER == 1916.
|
||||
#if !defined(_MSC_VER) || _MSC_VER > 1916
|
||||
|
||||
BOOST_CXX14_CONSTEXPR bool same0 = (t_int0 == t_int1);
|
||||
BOOST_TEST(same0);
|
||||
|
||||
BOOST_CXX14_CONSTEXPR bool same1 = (t_short1 == t_short0);
|
||||
BOOST_TEST(same1);
|
||||
|
||||
BOOST_CXX14_CONSTEXPR bool same2 = (t_int1 == t_int1);
|
||||
BOOST_TEST(same2);
|
||||
|
||||
BOOST_CXX14_CONSTEXPR bool same3 = (t_short0 == t_short0);
|
||||
BOOST_TEST(same3);
|
||||
|
||||
BOOST_CXX14_CONSTEXPR bool same4 = !(t_short0 < t_short0 || t_short0 > t_short0);
|
||||
BOOST_TEST(same4);
|
||||
|
||||
BOOST_CXX14_CONSTEXPR bool same5 = (t_short0 <= t_short0 && t_short0 >= t_short0);
|
||||
BOOST_TEST(same5);
|
||||
|
||||
|
||||
BOOST_CXX14_CONSTEXPR bool not_same0 = (t_int0 != t_short1);
|
||||
BOOST_TEST(not_same0);
|
||||
|
||||
BOOST_CXX14_CONSTEXPR bool not_same1 = (t_int1 != t_short0);
|
||||
BOOST_TEST(not_same1);
|
||||
|
||||
BOOST_CXX14_CONSTEXPR bool not_same2 = (t_int1 < t_short0 || t_int1 > t_short0);
|
||||
BOOST_TEST(not_same2);
|
||||
|
||||
|
||||
BOOST_CXX14_CONSTEXPR const char* int_name = t_int0.name();
|
||||
BOOST_TEST(*int_name != '\0');
|
||||
|
||||
BOOST_CXX14_CONSTEXPR const char* short_name = t_short0.name();
|
||||
BOOST_TEST(*short_name != '\0');
|
||||
|
||||
BOOST_CXX14_CONSTEXPR bool in_namespace = is_boost_namespace<ctti_type_index>();
|
||||
BOOST_TEST(in_namespace);
|
||||
|
||||
BOOST_CXX14_CONSTEXPR bool not_in_namespace = !is_boost_namespace<std::string>();
|
||||
BOOST_TEST(not_in_namespace);
|
||||
|
||||
#endif // #if !defined(_MSC_VER) || _MSC_VER > 1916
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
strcmp_same();
|
||||
search_same();
|
||||
constexpr_test();
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
296
test/type_index_runtime_cast_test.cpp
Normal file
296
test/type_index_runtime_cast_test.cpp
Normal file
@@ -0,0 +1,296 @@
|
||||
//
|
||||
// Copyright Chris Glover, 2016.
|
||||
//
|
||||
// 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/type_index/runtime_cast.hpp>
|
||||
// #include <boost/type_index/runtime_reference_cast.hpp>
|
||||
|
||||
#include <boost/type_index/runtime_cast.hpp>
|
||||
#include <boost/type_index/runtime_cast/boost_shared_ptr_cast.hpp>
|
||||
#include <boost/smart_ptr/make_shared.hpp>
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_SMART_PTR)
|
||||
# include <boost/type_index/runtime_cast/std_shared_ptr_cast.hpp>
|
||||
#endif
|
||||
|
||||
// Classes include a member variable "name" with the
|
||||
// name of the class hard coded so we can be sure that
|
||||
// the pointer offsets are all working, since we're doing
|
||||
// a cast from void* at some point.
|
||||
|
||||
#define IMPLEMENT_CLASS(type_name) \
|
||||
type_name() : name( #type_name ) {} \
|
||||
std::string name;
|
||||
|
||||
struct base {
|
||||
BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST()
|
||||
IMPLEMENT_CLASS(base)
|
||||
};
|
||||
|
||||
struct single_derived : base {
|
||||
BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(base)
|
||||
IMPLEMENT_CLASS(single_derived)
|
||||
};
|
||||
|
||||
struct base1 {
|
||||
BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST()
|
||||
IMPLEMENT_CLASS(base1)
|
||||
};
|
||||
|
||||
struct base2 {
|
||||
BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST()
|
||||
IMPLEMENT_CLASS(base2)
|
||||
};
|
||||
|
||||
struct multiple_derived : base1, base2 {
|
||||
BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(base1, base2)
|
||||
IMPLEMENT_CLASS(multiple_derived)
|
||||
};
|
||||
|
||||
struct baseV1 : virtual base {
|
||||
BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(base)
|
||||
IMPLEMENT_CLASS(baseV1)
|
||||
};
|
||||
|
||||
struct baseV2 : virtual base {
|
||||
BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(base)
|
||||
IMPLEMENT_CLASS(baseV2)
|
||||
};
|
||||
|
||||
struct multiple_virtual_derived : baseV1, baseV2 {
|
||||
BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(baseV1, baseV2)
|
||||
IMPLEMENT_CLASS(multiple_virtual_derived)
|
||||
};
|
||||
|
||||
struct unrelated {
|
||||
BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST()
|
||||
IMPLEMENT_CLASS(unrelated)
|
||||
};
|
||||
|
||||
struct unrelated_with_base : base {
|
||||
BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(base)
|
||||
IMPLEMENT_CLASS(unrelated_with_base)
|
||||
};
|
||||
|
||||
struct unrelatedV1 : virtual base {
|
||||
BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(base)
|
||||
IMPLEMENT_CLASS(unrelatedV1)
|
||||
};
|
||||
|
||||
struct level1_a : base {
|
||||
BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(base)
|
||||
IMPLEMENT_CLASS(level1_a)
|
||||
};
|
||||
|
||||
struct level1_b : base {
|
||||
BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(base)
|
||||
IMPLEMENT_CLASS(level1_b)
|
||||
};
|
||||
|
||||
struct level2 : level1_a, level1_b {
|
||||
BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(level1_a, level1_b)
|
||||
IMPLEMENT_CLASS(level2)
|
||||
};
|
||||
|
||||
struct reg_base {
|
||||
BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS()
|
||||
};
|
||||
|
||||
struct reg_derived : reg_base {
|
||||
BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(reg_base)
|
||||
};
|
||||
|
||||
void no_base()
|
||||
{
|
||||
using namespace boost::typeindex;
|
||||
base b;
|
||||
base* b2 = runtime_pointer_cast<base>(&b);
|
||||
BOOST_TEST_NE(b2, (base*)NULL);
|
||||
BOOST_TEST_EQ(b2->name, "base");
|
||||
|
||||
BOOST_TEST_EQ(runtime_pointer_cast<unrelated>(&b), (unrelated*)NULL);
|
||||
BOOST_TEST_EQ(runtime_pointer_cast<single_derived>(&b), (single_derived*)NULL);
|
||||
BOOST_TEST_EQ(runtime_pointer_cast<unrelatedV1>(&b), (unrelatedV1*)NULL);
|
||||
BOOST_TEST_EQ(runtime_pointer_cast<unrelated_with_base>(&b), (unrelated_with_base*)NULL);
|
||||
}
|
||||
|
||||
void single_base()
|
||||
{
|
||||
using namespace boost::typeindex;
|
||||
single_derived d;
|
||||
base* b = &d;
|
||||
single_derived* d2 = runtime_pointer_cast<single_derived>(b);
|
||||
BOOST_TEST_NE(d2, (single_derived*)NULL);
|
||||
BOOST_TEST_EQ(d2->name, "single_derived");
|
||||
|
||||
BOOST_TEST_EQ(runtime_pointer_cast<unrelated>(&d), (unrelated*)NULL);
|
||||
BOOST_TEST_EQ(runtime_pointer_cast<unrelated>(b), (unrelated*)NULL);
|
||||
BOOST_TEST_EQ(runtime_pointer_cast<unrelated_with_base>(b), (unrelated_with_base*)NULL);
|
||||
}
|
||||
|
||||
void multiple_base()
|
||||
{
|
||||
using namespace boost::typeindex;
|
||||
multiple_derived d;
|
||||
base1* b1 = &d;
|
||||
multiple_derived* d2 = runtime_pointer_cast<multiple_derived>(b1);
|
||||
BOOST_TEST_NE(d2, (multiple_derived*)NULL);
|
||||
BOOST_TEST_EQ(d2->name, "multiple_derived");
|
||||
|
||||
base2* b2 = runtime_pointer_cast<base2>(b1);
|
||||
BOOST_TEST_NE(b2, (base2*)NULL);
|
||||
BOOST_TEST_EQ(b2->name, "base2");
|
||||
|
||||
BOOST_TEST_EQ(runtime_pointer_cast<unrelated>(&d), (unrelated*)NULL);
|
||||
BOOST_TEST_EQ(runtime_pointer_cast<unrelated>(b1), (unrelated*)NULL);
|
||||
BOOST_TEST_EQ(runtime_pointer_cast<unrelated_with_base>(b1), (unrelated_with_base*)NULL);
|
||||
}
|
||||
|
||||
void virtual_base()
|
||||
{
|
||||
using namespace boost::typeindex;
|
||||
multiple_virtual_derived d;
|
||||
base* b = &d;
|
||||
multiple_virtual_derived* d2 = runtime_pointer_cast<multiple_virtual_derived>(b);
|
||||
baseV1* bv1 = runtime_pointer_cast<baseV1>(b);
|
||||
baseV2* bv2 = runtime_pointer_cast<baseV2>(b);
|
||||
|
||||
BOOST_TEST_NE(d2, (multiple_virtual_derived*)NULL);
|
||||
BOOST_TEST_EQ(d2->name, "multiple_virtual_derived");
|
||||
|
||||
BOOST_TEST_NE(bv1, (baseV1*)NULL);
|
||||
BOOST_TEST_EQ(bv1->name, "baseV1");
|
||||
|
||||
BOOST_TEST_NE(bv2, (baseV2*)NULL);
|
||||
BOOST_TEST_EQ(bv2->name, "baseV2");
|
||||
|
||||
BOOST_TEST_EQ(runtime_pointer_cast<unrelated>(b), (unrelated*)NULL);
|
||||
BOOST_TEST_EQ(runtime_pointer_cast<unrelated>(&d), (unrelated*)NULL);
|
||||
BOOST_TEST_EQ(runtime_pointer_cast<unrelated_with_base>(b), (unrelated_with_base*)NULL);
|
||||
}
|
||||
|
||||
void pointer_interface()
|
||||
{
|
||||
using namespace boost::typeindex;
|
||||
single_derived d;
|
||||
base* b = &d;
|
||||
single_derived* d2 = runtime_cast<single_derived*>(b);
|
||||
BOOST_TEST_NE(d2, (single_derived*)NULL);
|
||||
BOOST_TEST_EQ(d2->name, "single_derived");
|
||||
BOOST_TEST_EQ(runtime_pointer_cast<unrelated>(b), (unrelated*)NULL);
|
||||
}
|
||||
|
||||
void reference_interface()
|
||||
{
|
||||
using namespace boost::typeindex;
|
||||
single_derived d;
|
||||
base& b = d;
|
||||
single_derived& d2 = runtime_cast<single_derived&>(b);
|
||||
BOOST_TEST_EQ(d2.name, "single_derived");
|
||||
|
||||
try {
|
||||
unrelated& u = runtime_cast<unrelated&>(b);
|
||||
(void)u;
|
||||
BOOST_TEST(!"should throw bad_runtime_cast");
|
||||
}
|
||||
catch(boost::typeindex::bad_runtime_cast&) {
|
||||
}
|
||||
catch(...) {
|
||||
BOOST_TEST(!"should throw bad_runtime_cast");
|
||||
}
|
||||
}
|
||||
|
||||
void const_pointer_interface()
|
||||
{
|
||||
using namespace boost::typeindex;
|
||||
const single_derived d;
|
||||
base const* b = &d;
|
||||
single_derived const* d2 = runtime_cast<single_derived const*>(b);
|
||||
BOOST_TEST_NE(d2, (single_derived*)NULL);
|
||||
BOOST_TEST_EQ(d2->name, "single_derived");
|
||||
BOOST_TEST_EQ(runtime_pointer_cast<unrelated>(b), (unrelated*)NULL);
|
||||
}
|
||||
|
||||
void const_reference_interface()
|
||||
{
|
||||
using namespace boost::typeindex;
|
||||
const single_derived d;
|
||||
base const& b = d;
|
||||
single_derived const& d2 = runtime_cast<single_derived const&>(b);
|
||||
BOOST_TEST_EQ(d2.name, "single_derived");
|
||||
|
||||
try {
|
||||
unrelated const& u = runtime_cast<unrelated const&>(b);
|
||||
(void)u;
|
||||
BOOST_TEST(!"should throw bad_runtime_cast");
|
||||
}
|
||||
catch(boost::typeindex::bad_runtime_cast&) {
|
||||
}
|
||||
catch(...) {
|
||||
BOOST_TEST(!"should throw bad_runtime_cast");
|
||||
}
|
||||
}
|
||||
|
||||
void diamond_non_virtual()
|
||||
{
|
||||
using namespace boost::typeindex;
|
||||
level2 inst;
|
||||
level1_a* l1a = &inst;
|
||||
base* b1 = l1a;
|
||||
level1_b* l1_b = runtime_cast<level1_b*>(b1);
|
||||
BOOST_TEST_NE(l1_b, (level1_b*)NULL);
|
||||
BOOST_TEST_EQ(l1_b->name, "level1_b");
|
||||
}
|
||||
|
||||
void boost_shared_ptr()
|
||||
{
|
||||
using namespace boost::typeindex;
|
||||
boost::shared_ptr<single_derived> d = boost::make_shared<single_derived>();
|
||||
boost::shared_ptr<base> b = d;
|
||||
boost::shared_ptr<single_derived> d2 = runtime_pointer_cast<single_derived>(b);
|
||||
BOOST_TEST_NE(d2, boost::shared_ptr<single_derived>());
|
||||
BOOST_TEST_EQ(d2->name, "single_derived");
|
||||
}
|
||||
|
||||
void std_shared_ptr()
|
||||
{
|
||||
#if !defined(BOOST_NO_CXX11_SMART_PTR)
|
||||
using namespace boost::typeindex;
|
||||
std::shared_ptr<single_derived> d = std::make_shared<single_derived>();
|
||||
std::shared_ptr<base> b = d;
|
||||
std::shared_ptr<single_derived> d2 = runtime_pointer_cast<single_derived>(b);
|
||||
BOOST_TEST_NE(d2, std::shared_ptr<single_derived>());
|
||||
BOOST_TEST_EQ(d2->name, "single_derived");
|
||||
#endif
|
||||
}
|
||||
|
||||
void register_runtime_class()
|
||||
{
|
||||
using namespace boost::typeindex;
|
||||
reg_derived rd;
|
||||
reg_base* rb = &rd;
|
||||
reg_derived* prd = runtime_pointer_cast<reg_derived>(rb);
|
||||
BOOST_TEST_NE(prd, (reg_derived*)NULL);
|
||||
BOOST_TEST_EQ(type_id_runtime(*prd), type_id<reg_derived>());
|
||||
}
|
||||
|
||||
int main() {
|
||||
no_base();
|
||||
single_derived();
|
||||
multiple_base();
|
||||
virtual_base();
|
||||
pointer_interface();
|
||||
reference_interface();
|
||||
const_pointer_interface();
|
||||
const_reference_interface();
|
||||
diamond_non_virtual();
|
||||
boost_shared_ptr();
|
||||
std_shared_ptr();
|
||||
register_runtime_class();
|
||||
return boost::report_errors();
|
||||
}
|
||||
400
test/type_index_test.cpp
Normal file
400
test/type_index_test.cpp
Normal file
@@ -0,0 +1,400 @@
|
||||
//
|
||||
// Copyright 2012-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)
|
||||
|
||||
#include <boost/type_index.hpp>
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
namespace my_namespace1 {
|
||||
class my_class{};
|
||||
}
|
||||
|
||||
|
||||
namespace my_namespace2 {
|
||||
class my_class{};
|
||||
}
|
||||
|
||||
|
||||
void names_matches_type_id()
|
||||
{
|
||||
using namespace boost::typeindex;
|
||||
BOOST_TEST_EQ(type_id<int>().pretty_name(), "int");
|
||||
BOOST_TEST_EQ(type_id<double>().pretty_name(), "double");
|
||||
|
||||
BOOST_TEST_EQ(type_id<int>().name(), type_id<int>().name());
|
||||
BOOST_TEST_NE(type_id<int>().name(), type_id<double>().name());
|
||||
BOOST_TEST_NE(type_id<double>().name(), type_id<int>().name());
|
||||
BOOST_TEST_EQ(type_id<double>().name(), type_id<double>().name());
|
||||
}
|
||||
|
||||
void default_construction()
|
||||
{
|
||||
using namespace boost::typeindex;
|
||||
type_index ti1, ti2;
|
||||
BOOST_TEST_EQ(ti1, ti2);
|
||||
BOOST_TEST_EQ(type_id<void>(), ti1);
|
||||
|
||||
BOOST_TEST_EQ(type_id<void>().name(), ti1.name());
|
||||
BOOST_TEST_NE(type_id<int>(), ti1);
|
||||
}
|
||||
|
||||
|
||||
void copy_construction()
|
||||
{
|
||||
using namespace boost::typeindex;
|
||||
type_index ti1, ti2 = type_id<int>();
|
||||
BOOST_TEST_NE(ti1, ti2);
|
||||
ti1 = ti2;
|
||||
BOOST_TEST_EQ(ti2, ti1);
|
||||
|
||||
const type_index ti3(ti1);
|
||||
BOOST_TEST_EQ(ti3, ti1);
|
||||
}
|
||||
|
||||
void comparators_type_id()
|
||||
{
|
||||
using namespace boost::typeindex;
|
||||
type_index t_int = type_id<int>();
|
||||
type_index t_double = type_id<double>();
|
||||
|
||||
BOOST_TEST_EQ(t_int, t_int);
|
||||
BOOST_TEST_LE(t_int, t_int);
|
||||
BOOST_TEST_GE(t_int, t_int);
|
||||
BOOST_TEST_NE(t_int, t_double);
|
||||
|
||||
BOOST_TEST_LE(t_double, t_double);
|
||||
BOOST_TEST_GE(t_double, t_double);
|
||||
BOOST_TEST_NE(t_double, t_int);
|
||||
|
||||
BOOST_TEST(t_double < t_int || t_int < t_double);
|
||||
BOOST_TEST(t_double > t_int || t_int > t_double);
|
||||
}
|
||||
|
||||
void hash_code_type_id()
|
||||
{
|
||||
using namespace boost::typeindex;
|
||||
std::size_t t_int1 = type_id<int>().hash_code();
|
||||
std::size_t t_double1 = type_id<double>().hash_code();
|
||||
|
||||
std::size_t t_int2 = type_id<int>().hash_code();
|
||||
std::size_t t_double2 = type_id<double>().hash_code();
|
||||
|
||||
BOOST_TEST_EQ(t_int1, t_int2);
|
||||
BOOST_TEST_NE(t_int1, t_double2);
|
||||
BOOST_TEST_LE(t_double1, t_double2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class T1, class T2>
|
||||
static void test_with_modofiers() {
|
||||
using namespace boost::typeindex;
|
||||
|
||||
type_index t1 = type_id_with_cvr<T1>();
|
||||
type_index t2 = type_id_with_cvr<T2>();
|
||||
|
||||
BOOST_TEST_NE(t2, t1);
|
||||
BOOST_TEST(t2 != t1.type_info());
|
||||
BOOST_TEST(t2.type_info() != t1);
|
||||
|
||||
BOOST_TEST(t1 < t2 || t2 < t1);
|
||||
BOOST_TEST(t1 > t2 || t2 > t1);
|
||||
BOOST_TEST(t1.type_info() < t2 || t2.type_info() < t1);
|
||||
BOOST_TEST(t1.type_info() > t2 || t2.type_info() > t1);
|
||||
BOOST_TEST(t1 < t2.type_info() || t2 < t1.type_info());
|
||||
BOOST_TEST(t1 > t2.type_info() || t2 > t1.type_info());
|
||||
|
||||
// Chaecking that comparison operators overloads compile
|
||||
BOOST_TEST(t1 <= t2 || t2 <= t1);
|
||||
BOOST_TEST(t1 >= t2 || t2 >= t1);
|
||||
BOOST_TEST(t1.type_info() <= t2 || t2.type_info() <= t1);
|
||||
BOOST_TEST(t1.type_info() >= t2 || t2.type_info() >= t1);
|
||||
BOOST_TEST(t1 <= t2.type_info() || t2 <= t1.type_info());
|
||||
BOOST_TEST(t1 >= t2.type_info() || t2 >= t1.type_info());
|
||||
|
||||
BOOST_TEST_EQ(t1, type_id_with_cvr<T1>());
|
||||
BOOST_TEST_EQ(t2, type_id_with_cvr<T2>());
|
||||
BOOST_TEST(t1 == type_id_with_cvr<T1>().type_info());
|
||||
BOOST_TEST(t2 == type_id_with_cvr<T2>().type_info());
|
||||
BOOST_TEST(t1.type_info() == type_id_with_cvr<T1>());
|
||||
BOOST_TEST(t2.type_info() == type_id_with_cvr<T2>());
|
||||
|
||||
BOOST_TEST_EQ(t1.hash_code(), type_id_with_cvr<T1>().hash_code());
|
||||
BOOST_TEST_EQ(t2.hash_code(), type_id_with_cvr<T2>().hash_code());
|
||||
|
||||
BOOST_TEST_NE(t1.hash_code(), type_id_with_cvr<T2>().hash_code());
|
||||
BOOST_TEST_NE(t2.hash_code(), type_id_with_cvr<T1>().hash_code());
|
||||
}
|
||||
|
||||
void type_id_storing_modifiers()
|
||||
{
|
||||
test_with_modofiers<int, const int>();
|
||||
test_with_modofiers<int, const int&>();
|
||||
test_with_modofiers<int, int&>();
|
||||
test_with_modofiers<int, volatile int>();
|
||||
test_with_modofiers<int, volatile int&>();
|
||||
test_with_modofiers<int, const volatile int>();
|
||||
test_with_modofiers<int, const volatile int&>();
|
||||
|
||||
test_with_modofiers<const int, int>();
|
||||
test_with_modofiers<const int, const int&>();
|
||||
test_with_modofiers<const int, int&>();
|
||||
test_with_modofiers<const int, volatile int>();
|
||||
test_with_modofiers<const int, volatile int&>();
|
||||
test_with_modofiers<const int, const volatile int>();
|
||||
test_with_modofiers<const int, const volatile int&>();
|
||||
|
||||
test_with_modofiers<const int&, int>();
|
||||
test_with_modofiers<const int&, const int>();
|
||||
test_with_modofiers<const int&, int&>();
|
||||
test_with_modofiers<const int&, volatile int>();
|
||||
test_with_modofiers<const int&, volatile int&>();
|
||||
test_with_modofiers<const int&, const volatile int>();
|
||||
test_with_modofiers<const int&, const volatile int&>();
|
||||
|
||||
test_with_modofiers<int&, const int>();
|
||||
test_with_modofiers<int&, const int&>();
|
||||
test_with_modofiers<int&, int>();
|
||||
test_with_modofiers<int&, volatile int>();
|
||||
test_with_modofiers<int&, volatile int&>();
|
||||
test_with_modofiers<int&, const volatile int>();
|
||||
test_with_modofiers<int&, const volatile int&>();
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
test_with_modofiers<int&&, const int>();
|
||||
test_with_modofiers<int&&, const int&>();
|
||||
test_with_modofiers<int&&, const int&&>();
|
||||
test_with_modofiers<int&&, int>();
|
||||
test_with_modofiers<int&&, volatile int>();
|
||||
test_with_modofiers<int&&, volatile int&>();
|
||||
test_with_modofiers<int&&, volatile int&&>();
|
||||
test_with_modofiers<int&&, const volatile int>();
|
||||
test_with_modofiers<int&&, const volatile int&>();
|
||||
test_with_modofiers<int&&, const volatile int&&>();
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static void test_storing_nonstoring_modifiers_templ() {
|
||||
using namespace boost::typeindex;
|
||||
|
||||
type_index t1 = type_id_with_cvr<T>();
|
||||
type_index t2 = type_id<T>();
|
||||
|
||||
BOOST_TEST_EQ(t2, t1);
|
||||
BOOST_TEST_EQ(t1, t2);
|
||||
BOOST_TEST(t1 <= t2);
|
||||
BOOST_TEST(t1 >= t2);
|
||||
BOOST_TEST(t2 <= t1);
|
||||
BOOST_TEST(t2 >= t1);
|
||||
|
||||
BOOST_TEST_EQ(t2.pretty_name(), t1.pretty_name());
|
||||
}
|
||||
|
||||
void type_id_storing_modifiers_vs_nonstoring()
|
||||
{
|
||||
test_storing_nonstoring_modifiers_templ<int>();
|
||||
test_storing_nonstoring_modifiers_templ<my_namespace1::my_class>();
|
||||
test_storing_nonstoring_modifiers_templ<my_namespace2::my_class>();
|
||||
|
||||
boost::typeindex::type_index t1 = boost::typeindex::type_id_with_cvr<const int>();
|
||||
boost::typeindex::type_index t2 = boost::typeindex::type_id<int>();
|
||||
BOOST_TEST_NE(t2, t1);
|
||||
BOOST_TEST(t1.pretty_name() == "const int" || t1.pretty_name() == "int const");
|
||||
}
|
||||
|
||||
void type_index_stream_operator_via_lexical_cast_testing()
|
||||
{
|
||||
using namespace boost::typeindex;
|
||||
|
||||
std::string s_int2 = boost::lexical_cast<std::string>(type_id<int>());
|
||||
BOOST_TEST_EQ(s_int2, "int");
|
||||
|
||||
std::string s_double2 = boost::lexical_cast<std::string>(type_id<double>());
|
||||
BOOST_TEST_EQ(s_double2, "double");
|
||||
}
|
||||
|
||||
void type_index_stripping_cvr_test()
|
||||
{
|
||||
using namespace boost::typeindex;
|
||||
|
||||
BOOST_TEST_EQ(type_id<int>(), type_id<const int>());
|
||||
BOOST_TEST_EQ(type_id<int>(), type_id<const volatile int>());
|
||||
BOOST_TEST_EQ(type_id<int>(), type_id<const volatile int&>());
|
||||
|
||||
BOOST_TEST_EQ(type_id<int>(), type_id<int&>());
|
||||
BOOST_TEST_EQ(type_id<int>(), type_id<volatile int>());
|
||||
BOOST_TEST_EQ(type_id<int>(), type_id<volatile int&>());
|
||||
|
||||
|
||||
BOOST_TEST_EQ(type_id<double>(), type_id<const double>());
|
||||
BOOST_TEST_EQ(type_id<double>(), type_id<const volatile double>());
|
||||
BOOST_TEST_EQ(type_id<double>(), type_id<const volatile double&>());
|
||||
|
||||
BOOST_TEST_EQ(type_id<double>(), type_id<double&>());
|
||||
BOOST_TEST_EQ(type_id<double>(), type_id<volatile double>());
|
||||
BOOST_TEST_EQ(type_id<double>(), type_id<volatile double&>());
|
||||
}
|
||||
|
||||
|
||||
void type_index_user_defined_class_test()
|
||||
{
|
||||
using namespace boost::typeindex;
|
||||
|
||||
BOOST_TEST_EQ(type_id<my_namespace1::my_class>(), type_id<my_namespace1::my_class>());
|
||||
BOOST_TEST_EQ(type_id<my_namespace2::my_class>(), type_id<my_namespace2::my_class>());
|
||||
|
||||
#ifndef BOOST_NO_RTTI
|
||||
BOOST_TEST(type_id<my_namespace1::my_class>() == typeid(my_namespace1::my_class));
|
||||
BOOST_TEST(type_id<my_namespace2::my_class>() == typeid(my_namespace2::my_class));
|
||||
BOOST_TEST(typeid(my_namespace1::my_class) == type_id<my_namespace1::my_class>());
|
||||
BOOST_TEST(typeid(my_namespace2::my_class) == type_id<my_namespace2::my_class>());
|
||||
#endif
|
||||
|
||||
BOOST_TEST_NE(type_id<my_namespace1::my_class>(), type_id<my_namespace2::my_class>());
|
||||
BOOST_TEST_NE(
|
||||
type_id<my_namespace1::my_class>().pretty_name().find("my_namespace1::my_class"),
|
||||
std::string::npos);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct A {
|
||||
public:
|
||||
BOOST_TYPE_INDEX_REGISTER_CLASS
|
||||
virtual ~A(){}
|
||||
};
|
||||
|
||||
struct B: public A {
|
||||
BOOST_TYPE_INDEX_REGISTER_CLASS
|
||||
};
|
||||
|
||||
struct C: public B {
|
||||
BOOST_TYPE_INDEX_REGISTER_CLASS
|
||||
};
|
||||
|
||||
void comparators_type_id_runtime()
|
||||
{
|
||||
C c1;
|
||||
B b1;
|
||||
A* pc1 = &c1;
|
||||
A& rc1 = c1;
|
||||
A* pb1 = &b1;
|
||||
A& rb1 = b1;
|
||||
|
||||
#ifndef BOOST_NO_RTTI
|
||||
BOOST_TEST(typeid(rc1) == typeid(*pc1));
|
||||
BOOST_TEST(typeid(rb1) == typeid(*pb1));
|
||||
|
||||
BOOST_TEST(typeid(rc1) != typeid(*pb1));
|
||||
BOOST_TEST(typeid(rb1) != typeid(*pc1));
|
||||
|
||||
BOOST_TEST(typeid(&rc1) == typeid(pb1));
|
||||
BOOST_TEST(typeid(&rb1) == typeid(pc1));
|
||||
#else
|
||||
BOOST_TEST(boost::typeindex::type_index(pc1->boost_type_index_type_id_runtime_()).raw_name());
|
||||
#endif
|
||||
|
||||
BOOST_TEST_EQ(boost::typeindex::type_id_runtime(rc1), boost::typeindex::type_id_runtime(*pc1));
|
||||
BOOST_TEST_EQ(boost::typeindex::type_id<C>(), boost::typeindex::type_id_runtime(*pc1));
|
||||
BOOST_TEST_EQ(boost::typeindex::type_id_runtime(rb1), boost::typeindex::type_id_runtime(*pb1));
|
||||
BOOST_TEST_EQ(boost::typeindex::type_id<B>(), boost::typeindex::type_id_runtime(*pb1));
|
||||
|
||||
BOOST_TEST_NE(boost::typeindex::type_id_runtime(rc1), boost::typeindex::type_id_runtime(*pb1));
|
||||
BOOST_TEST_NE(boost::typeindex::type_id_runtime(rb1), boost::typeindex::type_id_runtime(*pc1));
|
||||
|
||||
#ifndef BOOST_NO_RTTI
|
||||
BOOST_TEST_EQ(boost::typeindex::type_id_runtime(&rc1), boost::typeindex::type_id_runtime(pb1));
|
||||
BOOST_TEST_EQ(boost::typeindex::type_id_runtime(&rb1), boost::typeindex::type_id_runtime(pc1));
|
||||
|
||||
BOOST_TEST(boost::typeindex::type_id_runtime(rc1) == typeid(*pc1));
|
||||
BOOST_TEST(boost::typeindex::type_id_runtime(rb1) == typeid(*pb1));
|
||||
|
||||
BOOST_TEST(boost::typeindex::type_id_runtime(rc1) != typeid(*pb1));
|
||||
BOOST_TEST(boost::typeindex::type_id_runtime(rb1) != typeid(*pc1));
|
||||
BOOST_TEST(boost::typeindex::type_id_runtime(&rc1) == typeid(pb1));
|
||||
BOOST_TEST(boost::typeindex::type_id_runtime(&rb1) == typeid(pc1));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifndef BOOST_NO_RTTI
|
||||
|
||||
void comparators_type_id_vs_type_info()
|
||||
{
|
||||
using namespace boost::typeindex;
|
||||
type_index t_int = type_id<int>();
|
||||
|
||||
BOOST_TEST(t_int == typeid(int));
|
||||
BOOST_TEST(typeid(int) == t_int);
|
||||
BOOST_TEST(t_int <= typeid(int));
|
||||
BOOST_TEST(typeid(int) <= t_int);
|
||||
BOOST_TEST(t_int >= typeid(int));
|
||||
BOOST_TEST(typeid(int) >= t_int);
|
||||
|
||||
type_index t_double = type_id<double>();
|
||||
|
||||
BOOST_TEST(t_double == typeid(double));
|
||||
BOOST_TEST(typeid(double) == t_double);
|
||||
BOOST_TEST(t_double <= typeid(double));
|
||||
BOOST_TEST(typeid(double) <= t_double);
|
||||
BOOST_TEST(t_double >= typeid(double));
|
||||
BOOST_TEST(typeid(double) >= t_double);
|
||||
|
||||
if (t_double < t_int) {
|
||||
BOOST_TEST(t_double < typeid(int));
|
||||
BOOST_TEST(typeid(double) < t_int);
|
||||
BOOST_TEST(typeid(int) > t_double);
|
||||
BOOST_TEST(t_int > typeid(double));
|
||||
|
||||
|
||||
BOOST_TEST(t_double <= typeid(int));
|
||||
BOOST_TEST(typeid(double) <= t_int);
|
||||
BOOST_TEST(typeid(int) >= t_double);
|
||||
BOOST_TEST(t_int >= typeid(double));
|
||||
} else {
|
||||
BOOST_TEST(t_double > typeid(int));
|
||||
BOOST_TEST(typeid(double) > t_int);
|
||||
BOOST_TEST(typeid(int) < t_double);
|
||||
BOOST_TEST(t_int < typeid(double));
|
||||
|
||||
|
||||
BOOST_TEST(t_double >= typeid(int));
|
||||
BOOST_TEST(typeid(double) >= t_int);
|
||||
BOOST_TEST(typeid(int) <= t_double);
|
||||
BOOST_TEST(t_int <= typeid(double));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // BOOST_NO_RTTI
|
||||
|
||||
int main() {
|
||||
names_matches_type_id();
|
||||
default_construction();
|
||||
copy_construction();
|
||||
comparators_type_id();
|
||||
hash_code_type_id();
|
||||
|
||||
type_id_storing_modifiers();
|
||||
type_id_storing_modifiers_vs_nonstoring();
|
||||
type_index_stream_operator_via_lexical_cast_testing();
|
||||
type_index_stripping_cvr_test();
|
||||
type_index_user_defined_class_test();
|
||||
|
||||
comparators_type_id_runtime();
|
||||
#ifndef BOOST_NO_RTTI
|
||||
comparators_type_id_vs_type_info();
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
18
test/type_index_test_ctti_alignment.cpp
Normal file
18
test/type_index_test_ctti_alignment.cpp
Normal file
@@ -0,0 +1,18 @@
|
||||
//
|
||||
// Copyright 2012-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)
|
||||
|
||||
#include <boost/type_index/ctti_type_index.hpp>
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
|
||||
int main() {
|
||||
BOOST_STATIC_ASSERT_MSG(
|
||||
boost::alignment_of<boost::typeindex::detail::ctti_data>::value == boost::alignment_of<char>::value,
|
||||
"Alignments of boost::typeindex::detail::ctti_data and char differ. "
|
||||
"It is unsafe to reinterpret_cast between them."
|
||||
);
|
||||
}
|
||||
|
||||
15
test/type_index_test_ctti_construct_fail.cpp
Normal file
15
test/type_index_test_ctti_construct_fail.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
//
|
||||
// Copyright 2012-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)
|
||||
|
||||
#include <boost/type_index/ctti_type_index.hpp>
|
||||
|
||||
int main() {
|
||||
using namespace boost::typeindex;
|
||||
ctti_type_index::type_info_t t;
|
||||
(void)t;
|
||||
}
|
||||
|
||||
15
test/type_index_test_ctti_copy_fail.cpp
Normal file
15
test/type_index_test_ctti_copy_fail.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
//
|
||||
// Copyright 2012-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)
|
||||
|
||||
#include <boost/type_index/ctti_type_index.hpp>
|
||||
|
||||
int main() {
|
||||
using namespace boost::typeindex;
|
||||
ctti_type_index::type_info_t t = ctti_type_index::type_id<int>().type_info();
|
||||
(void)t;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user