forked from boostorg/utility
Compare commits
426 Commits
svn-branch
...
develop
Author | SHA1 | Date | |
---|---|---|---|
06548cf5fa | |||
932973fe39 | |||
c63d36cf5b | |||
0106ffda5f | |||
0c1d01d30a | |||
7ac95c156c | |||
eb29d71245 | |||
fe417f6237 | |||
d5c33889b9 | |||
11cff46019 | |||
f11a56c2a7 | |||
69f6588d7c | |||
6950023bca | |||
c3aab6a184 | |||
7717dac7bc | |||
63aadf3f0f | |||
0feb28b467 | |||
78f1b38930 | |||
e6edd4eb91 | |||
9d1284ef6d | |||
aa0ccfa65e | |||
c21d2818c7 | |||
5ae025b56a | |||
f3f7c3c041 | |||
bdc983b804 | |||
a1583e3072 | |||
30caa722c1 | |||
96169c9fc6 | |||
b6119df27f | |||
9941e831bb | |||
a8cdbe516d | |||
485a160dde | |||
2b0441e95f | |||
de106bf696 | |||
b9a91970be | |||
73bccf50db | |||
f7c17df050 | |||
51104850f6 | |||
301ad68447 | |||
5f5aa500d0 | |||
fede5878c3 | |||
a3ec92334d | |||
d186ad3539 | |||
1d6d44c1c4 | |||
0171af0f77 | |||
703a4bf752 | |||
05e0d1688d | |||
dcaf2c0e3b | |||
71107238eb | |||
28c90abaf0 | |||
2cc83cc7d5 | |||
e8fc7cc2a1 | |||
09d24c0516 | |||
3f51807f24 | |||
a04a0d9531 | |||
449a03e13d | |||
dc59afafdb | |||
e845ae6752 | |||
375382e1e6 | |||
6cca23a63a | |||
9ad7e51912 | |||
601f80e8c1 | |||
c960bef6ef | |||
6ab27d5689 | |||
3e2f0199cf | |||
9c2aa8d193 | |||
601fc9371f | |||
7aafdf92a0 | |||
a7570d7608 | |||
37168a3f4b | |||
e56171989a | |||
f00a5bf0d3 | |||
a4feaf4f24 | |||
688628f764 | |||
8faf831bd1 | |||
25cb7aa122 | |||
0ae5cebc7f | |||
1caa002121 | |||
691f3238d7 | |||
8b6da499a3 | |||
6e6d0777e8 | |||
64fffa0f97 | |||
5da340a2a4 | |||
9a4cff038b | |||
0c059a50ad | |||
bdc5b5cf3a | |||
86e7caefea | |||
7953ba56ba | |||
46f72656b3 | |||
e3a2a06011 | |||
a4752e066d | |||
957aeba2e9 | |||
2b436d7d50 | |||
882c9c86c4 | |||
c81d8e3990 | |||
75276a055d | |||
309e6a1b31 | |||
9eeb7f85c5 | |||
62c34f51f6 | |||
6a1917ceec | |||
47c9f69ffe | |||
7b74d2d494 | |||
57da5f0c18 | |||
dabf53a703 | |||
ff56b3649e | |||
31e0ae4c37 | |||
5fe9df91c0 | |||
f03b681d01 | |||
e120a83d1e | |||
424fea5881 | |||
53d9aa9d2f | |||
6b62dcc504 | |||
91ebdcd1dd | |||
e8d2b2ba76 | |||
ce64b13846 | |||
32c50e0814 | |||
05dda09fd3 | |||
a4cafcc75d | |||
796fb965be | |||
08da98a551 | |||
57b027f1cd | |||
db05c11f50 | |||
3d2a7f0c17 | |||
8858bad352 | |||
fc135e0d72 | |||
ebe44296ca | |||
bdf55e0b6f | |||
d4170ccdb5 | |||
e2d115db97 | |||
15cfa44937 | |||
473be2e4c1 | |||
6ad6bc005c | |||
7709f0e430 | |||
eacea4664d | |||
1fe5af5264 | |||
d2fb06e6a0 | |||
73baeb7a63 | |||
56f13625b1 | |||
ac4e8da91d | |||
426836d860 | |||
82df2b82fc | |||
f8a243bcff | |||
51f7f7f53e | |||
5f535a151c | |||
c88936800d | |||
96fbce5759 | |||
9d46de1578 | |||
976a4d2fc1 | |||
ea81279b35 | |||
7d101d420c | |||
d8acfef27b | |||
d7ae336915 | |||
b74f49f1e5 | |||
5977f11be8 | |||
ad0fc7c9d3 | |||
a6c175e2c3 | |||
874ca2307b | |||
5220260145 | |||
2f5a6fbcf1 | |||
51ba9f1b45 | |||
5cef1403b0 | |||
81ce4693f6 | |||
fb2f110eb4 | |||
2ed5ee9588 | |||
88c36c1941 | |||
0b2409a942 | |||
62b39548be | |||
2722fdcda3 | |||
792d0538d2 | |||
06ae661775 | |||
d9d076874e | |||
e25d85446e | |||
5bc9e47688 | |||
ec50f22b8b | |||
592382dc61 | |||
6cf9c22cf1 | |||
33475f87e4 | |||
21261a8630 | |||
7d60e8e378 | |||
10ff4d4fcd | |||
89bf74beee | |||
bfdcce0f97 | |||
330b49d602 | |||
68b26cddbe | |||
6c4ab93573 | |||
0876da45db | |||
00f02167e3 | |||
9960d9f395 | |||
ccfd741c0a | |||
c5c479d49c | |||
3e8f73c6ac | |||
38121f2af3 | |||
38b536ff05 | |||
9ae6492af9 | |||
816607e212 | |||
a3ab942bc2 | |||
0f1f793caf | |||
ff445c0ece | |||
9fae8be166 | |||
b90a28f0e1 | |||
febca584d9 | |||
21dc552cf9 | |||
fda210f597 | |||
3d853b0e83 | |||
4814d1ebfe | |||
e5932ebb08 | |||
93a2e25092 | |||
39577f86d1 | |||
8392991c46 | |||
c5b1256650 | |||
c56dd13592 | |||
181f302ee4 | |||
287844fe76 | |||
3982b6d633 | |||
0b492bee9c | |||
a9236d00a9 | |||
4313bfc323 | |||
f61c94e812 | |||
1dfacff7ec | |||
a25ac4550b | |||
d767054a79 | |||
08a1b7da61 | |||
8ab8e36dcf | |||
1caa745dd7 | |||
cf5ad341ed | |||
1f6de83fe2 | |||
cb6500161b | |||
13610caa36 | |||
6bcf4f92bf | |||
fa8301a56a | |||
7306c8c359 | |||
492fd7f091 | |||
4fbd789253 | |||
4522603132 | |||
cae8d90d65 | |||
2ec0488e2a | |||
520dff9270 | |||
8e24c798ad | |||
651a869d4f | |||
7a8f16efdc | |||
2fa70612bb | |||
f1edd107eb | |||
c185d2dfa9 | |||
4531b2a2a6 | |||
51e482edfe | |||
61d07273fc | |||
42d56fbd51 | |||
6a1e97f870 | |||
c0fdaba925 | |||
87bc4c8dce | |||
34c11cb995 | |||
beab2e74ca | |||
10b8041472 | |||
1ed9aaa2a4 | |||
5a54e21ec5 | |||
8e06104836 | |||
45d884ffd7 | |||
329ca0bae8 | |||
afd9ab17ec | |||
036f6b9107 | |||
da239df58d | |||
46b3739b79 | |||
c5fc075d07 | |||
5ce9683858 | |||
991539725e | |||
df8e0c2dae | |||
f5869d0f82 | |||
db7bba3259 | |||
379e2111e2 | |||
d1bfa8e7b0 | |||
de0e18ca0a | |||
8ae3bfa961 | |||
d4b5fde5a8 | |||
9c4d2843da | |||
ad61f347e4 | |||
b434003b13 | |||
50eafe2027 | |||
87b8e03ca9 | |||
d595357b41 | |||
79d9d9f514 | |||
c48f86c9e4 | |||
514e5299ca | |||
3bac7b132a | |||
9382b69eb1 | |||
52a64d6aec | |||
a292dba021 | |||
e25bd18bd8 | |||
80895c071c | |||
f90812f1d9 | |||
244c343efe | |||
14e9e95c17 | |||
fd9f12b8f1 | |||
96da5105ab | |||
ad98ca9c3c | |||
dfad2950ea | |||
44a98b121b | |||
d5e86bb576 | |||
65d9a78735 | |||
12d17bc26d | |||
03047e3f00 | |||
468fb2dd5f | |||
e97577a0ae | |||
a90bc68a7f | |||
b39e4e5aea | |||
37c8f45edc | |||
4dc9659097 | |||
3d1646cf51 | |||
adf57817ec | |||
1fd5883b34 | |||
fc4bc227b5 | |||
bcd50e9105 | |||
e33f8b0055 | |||
b051dd665b | |||
b813232bba | |||
e02523e286 | |||
0d605befd4 | |||
4080fe22e3 | |||
2eda3f5299 | |||
1ab9131bca | |||
d51799518b | |||
f9540f360c | |||
c1fdb477c1 | |||
1b2cd6378b | |||
9383bbc283 | |||
1730c1319b | |||
856b01240a | |||
611395441e | |||
b35ef27b35 | |||
124f4ea879 | |||
0f43c44e97 | |||
7d8353f46a | |||
1920623a4f | |||
c0cca9e8cc | |||
d63444f22e | |||
1f23425baa | |||
a89b0101fc | |||
fb2d391928 | |||
ad5cf8cf08 | |||
2fc827ad23 | |||
88e7d86270 | |||
6b9f0103d5 | |||
7aa68731b4 | |||
87b3643647 | |||
c9d56eed6e | |||
e36315c151 | |||
1aa48ea698 | |||
d01eb82fb7 | |||
86791caf0e | |||
8176af84e1 | |||
b7d4b6edae | |||
d7cf3628f7 | |||
b273cd3914 | |||
ca7db1f361 | |||
2a7e81e07f | |||
13da21e7b1 | |||
b3ffef536d | |||
e2c98762db | |||
8af4250c3c | |||
e30889304c | |||
b4dee80e61 | |||
a47dce770c | |||
dab1e8e522 | |||
583422cda2 | |||
ee146a02a1 | |||
c131cbd0b2 | |||
f8bef7ba95 | |||
e54cbf3053 | |||
d5291d08b8 | |||
61755605af | |||
cd12e322bd | |||
8cb975feb7 | |||
ffe151458e | |||
4003a9f74a | |||
211eb04f33 | |||
e57213b298 | |||
51f9adbfa1 | |||
eaaf17a88f | |||
48cfd42123 | |||
76aa5d2f27 | |||
ce67dde4f0 | |||
a69e872a91 | |||
e3640e45c2 | |||
b7cd171b2b | |||
b2e6a82adb | |||
390372294a | |||
ffbbf38e12 | |||
9e73b2c6ae | |||
633832e872 | |||
862cb2a4e0 | |||
b012f16ee5 | |||
3d96ab26d4 | |||
8652bf51ec | |||
9168cb9c61 | |||
e1991374ae | |||
d0ee9a7c28 | |||
10e83b490b | |||
4b24dba257 | |||
7a036f6f3a | |||
e632b0fb1f | |||
17bee9d43f | |||
492a8ad213 | |||
8827b8ed8b | |||
8849fbc52d | |||
50bc75a802 | |||
9b52e49fda | |||
ab479794f3 | |||
97b8966337 | |||
88099a882f | |||
d5554eb6d7 | |||
13bdfb8bbd | |||
74462349c2 | |||
6aa648d315 | |||
9ff18c2c96 | |||
d5ea07c737 | |||
aa0096bf42 | |||
005c2f3cc8 | |||
09f7aab52d | |||
30a40f9f76 | |||
d9f8bae673 | |||
3c7b409460 | |||
ee3551e8dc | |||
95da2e90de | |||
6dd93ab916 | |||
505d419a1b | |||
d968b5f5b9 | |||
d809d4e832 |
429
.github/workflows/ci.yml
vendored
Normal file
429
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,429 @@
|
||||
# Copyright 2021 Andrey Semashev
|
||||
#
|
||||
# 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)
|
||||
|
||||
name: CI
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
- feature/**
|
||||
|
||||
concurrency:
|
||||
group: ${{format('{0}:{1}', github.repository, github.ref)}}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
GIT_FETCH_JOBS: 8
|
||||
NET_RETRY_COUNT: 5
|
||||
DEFAULT_BUILD_VARIANT: debug,release
|
||||
|
||||
jobs:
|
||||
posix:
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
# Linux, gcc
|
||||
- toolset: gcc-4.4
|
||||
cxxstd: "98,0x"
|
||||
os: ubuntu-20.04
|
||||
container: ubuntu:16.04
|
||||
install:
|
||||
- g++-4.4
|
||||
sources:
|
||||
- "ppa:ubuntu-toolchain-r/test"
|
||||
- toolset: gcc-4.6
|
||||
cxxstd: "03,0x"
|
||||
os: ubuntu-20.04
|
||||
container: ubuntu:16.04
|
||||
install:
|
||||
- g++-4.6
|
||||
sources:
|
||||
- "ppa:ubuntu-toolchain-r/test"
|
||||
- toolset: gcc-4.7
|
||||
cxxstd: "03,11"
|
||||
os: ubuntu-20.04
|
||||
container: ubuntu:16.04
|
||||
install:
|
||||
- g++-4.7
|
||||
- toolset: gcc-4.8
|
||||
cxxstd: "03,11"
|
||||
os: ubuntu-18.04
|
||||
install:
|
||||
- g++-4.8
|
||||
- toolset: gcc-4.9
|
||||
cxxstd: "03,11"
|
||||
os: ubuntu-20.04
|
||||
container: ubuntu:16.04
|
||||
install:
|
||||
- g++-4.9
|
||||
- toolset: gcc-5
|
||||
cxxstd: "03,11,14,1z"
|
||||
os: ubuntu-20.04
|
||||
container: ubuntu:16.04
|
||||
install:
|
||||
- g++-5
|
||||
- toolset: gcc-6
|
||||
cxxstd: "03,11,14,1z"
|
||||
os: ubuntu-18.04
|
||||
install:
|
||||
- g++-6
|
||||
- toolset: gcc-7
|
||||
cxxstd: "03,11,14,17"
|
||||
os: ubuntu-18.04
|
||||
install:
|
||||
- g++-7
|
||||
- toolset: gcc-8
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-18.04
|
||||
install:
|
||||
- g++-8
|
||||
- toolset: gcc-9
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-18.04
|
||||
install:
|
||||
- g++-9
|
||||
- toolset: gcc-10
|
||||
cxxstd: "03,11,14,17,20"
|
||||
os: ubuntu-20.04
|
||||
install:
|
||||
- g++-10
|
||||
- toolset: gcc-11
|
||||
cxxstd: "03,11,14,17,20"
|
||||
os: ubuntu-20.04
|
||||
install:
|
||||
- g++-11
|
||||
sources:
|
||||
- "ppa:ubuntu-toolchain-r/test"
|
||||
- name: UBSAN
|
||||
toolset: gcc-11
|
||||
cxxstd: "03,11,14,17,20"
|
||||
ubsan: 1
|
||||
build_variant: debug
|
||||
os: ubuntu-20.04
|
||||
install:
|
||||
- g++-11
|
||||
sources:
|
||||
- "ppa:ubuntu-toolchain-r/test"
|
||||
|
||||
# Linux, clang
|
||||
- toolset: clang
|
||||
compiler: clang++-3.5
|
||||
cxxstd: "03,11"
|
||||
os: ubuntu-20.04
|
||||
container: ubuntu:16.04
|
||||
install:
|
||||
- clang-3.5
|
||||
- toolset: clang
|
||||
compiler: clang++-3.6
|
||||
cxxstd: "03,11,14"
|
||||
os: ubuntu-20.04
|
||||
container: ubuntu:16.04
|
||||
install:
|
||||
- clang-3.6
|
||||
- toolset: clang
|
||||
compiler: clang++-3.7
|
||||
cxxstd: "03,11,14"
|
||||
os: ubuntu-20.04
|
||||
container: ubuntu:16.04
|
||||
install:
|
||||
- clang-3.7
|
||||
- toolset: clang
|
||||
compiler: clang++-3.8
|
||||
cxxstd: "03,11,14"
|
||||
os: ubuntu-20.04
|
||||
container: ubuntu:16.04
|
||||
install:
|
||||
- clang-3.8
|
||||
- toolset: clang
|
||||
compiler: clang++-3.9
|
||||
cxxstd: "03,11,14"
|
||||
os: ubuntu-18.04
|
||||
install:
|
||||
- clang-3.9
|
||||
- toolset: clang
|
||||
compiler: clang++-4.0
|
||||
cxxstd: "03,11,14"
|
||||
os: ubuntu-18.04
|
||||
install:
|
||||
- clang-4.0
|
||||
- toolset: clang
|
||||
compiler: clang++-5.0
|
||||
cxxstd: "03,11,14,1z"
|
||||
os: ubuntu-18.04
|
||||
install:
|
||||
- clang-5.0
|
||||
- toolset: clang
|
||||
compiler: clang++-6.0
|
||||
cxxstd: "03,11,14,17"
|
||||
os: ubuntu-18.04
|
||||
install:
|
||||
- clang-6.0
|
||||
- toolset: clang
|
||||
compiler: clang++-7
|
||||
cxxstd: "03,11,14,17"
|
||||
os: ubuntu-18.04
|
||||
install:
|
||||
- clang-7
|
||||
# Note: clang-8 does not fully support C++20, so it is not compatible with libstdc++-8 in this mode
|
||||
- toolset: clang
|
||||
compiler: clang++-8
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-18.04
|
||||
install:
|
||||
- clang-8
|
||||
- g++-7
|
||||
gcc_toolchain: 7
|
||||
- toolset: clang
|
||||
compiler: clang++-9
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-20.04
|
||||
install:
|
||||
- clang-9
|
||||
- toolset: clang
|
||||
compiler: clang++-10
|
||||
cxxstd: "03,11,14,17,20"
|
||||
os: ubuntu-20.04
|
||||
install:
|
||||
- clang-10
|
||||
- toolset: clang
|
||||
compiler: clang++-11
|
||||
cxxstd: "03,11,14,17,20"
|
||||
os: ubuntu-20.04
|
||||
install:
|
||||
- clang-11
|
||||
- toolset: clang
|
||||
compiler: clang++-12
|
||||
cxxstd: "03,11,14,17,20"
|
||||
os: ubuntu-20.04
|
||||
install:
|
||||
- clang-12
|
||||
- toolset: clang
|
||||
compiler: clang++-12
|
||||
cxxstd: "03,11,14,17,20"
|
||||
os: ubuntu-20.04
|
||||
install:
|
||||
- clang-12
|
||||
- libc++-12-dev
|
||||
- libc++abi-12-dev
|
||||
cxxflags: -stdlib=libc++
|
||||
linkflags: -stdlib=libc++
|
||||
- name: UBSAN
|
||||
toolset: clang
|
||||
compiler: clang++-12
|
||||
cxxstd: "03,11,14,17,20"
|
||||
cxxflags: -stdlib=libc++
|
||||
linkflags: -stdlib=libc++
|
||||
ubsan: 1
|
||||
build_variant: debug
|
||||
os: ubuntu-20.04
|
||||
install:
|
||||
- clang-12
|
||||
- libc++-12-dev
|
||||
- libc++abi-12-dev
|
||||
|
||||
- toolset: clang
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: macos-10.15
|
||||
|
||||
timeout-minutes: 60
|
||||
runs-on: ${{matrix.os}}
|
||||
container: ${{matrix.container}}
|
||||
|
||||
steps:
|
||||
- name: Setup environment
|
||||
run: |
|
||||
if [ -f "/etc/debian_version" ]
|
||||
then
|
||||
echo "DEBIAN_FRONTEND=noninteractive" >> $GITHUB_ENV
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
fi
|
||||
if [ -n "${{matrix.container}}" ]
|
||||
then
|
||||
echo "GHA_CONTAINER=${{matrix.container}}" >> $GITHUB_ENV
|
||||
if [ -f "/etc/debian_version" ]
|
||||
then
|
||||
apt-get -o Acquire::Retries=$NET_RETRY_COUNT update
|
||||
apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y sudo software-properties-common tzdata wget curl apt-transport-https ca-certificates make build-essential g++ python python3 perl git cmake
|
||||
fi
|
||||
fi
|
||||
git config --global pack.threads 0
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install packages
|
||||
if: matrix.install
|
||||
run: |
|
||||
declare -a SOURCE_KEYS SOURCES
|
||||
if [ -n "${{join(matrix.source_keys, ' ')}}" ]
|
||||
then
|
||||
SOURCE_KEYS=("${{join(matrix.source_keys, '" "')}}")
|
||||
fi
|
||||
if [ -n "${{join(matrix.sources, ' ')}}" ]
|
||||
then
|
||||
SOURCES=("${{join(matrix.sources, '" "')}}")
|
||||
fi
|
||||
for key in "${SOURCE_KEYS[@]}"
|
||||
do
|
||||
for i in {1..$NET_RETRY_COUNT}
|
||||
do
|
||||
echo "Adding key: $key"
|
||||
wget -O - "$key" | sudo apt-key add - && break || sleep 2
|
||||
done
|
||||
done
|
||||
if [ ${#SOURCES[@]} -gt 0 ]
|
||||
then
|
||||
APT_ADD_REPO_COMMON_ARGS=("-y")
|
||||
APT_ADD_REPO_SUPPORTED_ARGS="$(apt-add-repository --help | perl -ne 'if (/^\s*-n/) { print "n"; } elsif (/^\s*-P/) { print "P"; } elsif (/^\s*-S/) { print "S"; } elsif (/^\s*-U/) { print "U"; }')"
|
||||
if [ -n "$APT_ADD_REPO_SUPPORTED_ARGS" -a -z "${APT_ADD_REPO_SUPPORTED_ARGS##*n*}" ]
|
||||
then
|
||||
APT_ADD_REPO_COMMON_ARGS+=("-n")
|
||||
fi
|
||||
APT_ADD_REPO_HAS_SOURCE_ARGS="$([ -n "$APT_ADD_REPO_SUPPORTED_ARGS" -a -z "${APT_ADD_REPO_SUPPORTED_ARGS##*P*}" -a -z "${APT_ADD_REPO_SUPPORTED_ARGS##*S*}" -a -z "${APT_ADD_REPO_SUPPORTED_ARGS##*U*}" ] && echo 1 || echo 0)"
|
||||
for source in "${SOURCES[@]}"
|
||||
do
|
||||
for i in {1..$NET_RETRY_COUNT}
|
||||
do
|
||||
APT_ADD_REPO_ARGS=("${APT_ADD_REPO_COMMON_ARGS[@]}")
|
||||
if [ $APT_ADD_REPO_HAS_SOURCE_ARGS -ne 0 ]
|
||||
then
|
||||
case "$source" in
|
||||
"ppa:"*)
|
||||
APT_ADD_REPO_ARGS+=("-P")
|
||||
;;
|
||||
"deb "*)
|
||||
APT_ADD_REPO_ARGS+=("-S")
|
||||
;;
|
||||
*)
|
||||
APT_ADD_REPO_ARGS+=("-U")
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
APT_ADD_REPO_ARGS+=("$source")
|
||||
echo "apt-add-repository ${APT_ADD_REPO_ARGS[@]}"
|
||||
sudo -E apt-add-repository "${APT_ADD_REPO_ARGS[@]}" && break || sleep 2
|
||||
done
|
||||
done
|
||||
fi
|
||||
sudo apt-get -o Acquire::Retries=$NET_RETRY_COUNT update
|
||||
sudo apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y ${{join(matrix.install, ' ')}}
|
||||
|
||||
- name: Setup GCC Toolchain
|
||||
if: matrix.gcc_toolchain
|
||||
run: |
|
||||
GCC_TOOLCHAIN_ROOT="$HOME/gcc-toolchain"
|
||||
echo "GCC_TOOLCHAIN_ROOT=\"$GCC_TOOLCHAIN_ROOT\"" >> $GITHUB_ENV
|
||||
MULTIARCH_TRIPLET="$(dpkg-architecture -qDEB_HOST_MULTIARCH)"
|
||||
mkdir -p "$GCC_TOOLCHAIN_ROOT"
|
||||
ln -s /usr/include "$GCC_TOOLCHAIN_ROOT/include"
|
||||
ln -s /usr/bin "$GCC_TOOLCHAIN_ROOT/bin"
|
||||
mkdir -p "$GCC_TOOLCHAIN_ROOT/lib/gcc/$MULTIARCH_TRIPLET"
|
||||
ln -s "/usr/lib/gcc/$MULTIARCH_TRIPLET/${{matrix.gcc_toolchain}}" "$GCC_TOOLCHAIN_ROOT/lib/gcc/$MULTIARCH_TRIPLET/${{matrix.gcc_toolchain}}"
|
||||
|
||||
- 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
|
||||
BUILD_JOBS=$((nproc || sysctl -n hw.ncpu) 2> /dev/null)
|
||||
echo "BUILD_JOBS=$BUILD_JOBS" >> $GITHUB_ENV
|
||||
echo "CMAKE_BUILD_PARALLEL_LEVEL=$BUILD_JOBS" >> $GITHUB_ENV
|
||||
DEPINST_ARGS=()
|
||||
GIT_VERSION="$(git --version | sed -e 's/git version //')"
|
||||
GIT_HAS_JOBS=1
|
||||
if [ -f "/etc/debian_version" ]
|
||||
then
|
||||
if $(dpkg --compare-versions "$GIT_VERSION" lt 2.8.0)
|
||||
then
|
||||
GIT_HAS_JOBS=0
|
||||
fi
|
||||
else
|
||||
declare -a GIT_VER=(${GIT_VERSION//./ })
|
||||
declare -a GIT_MIN_VER=(2 8 0)
|
||||
for ((i=0; i<${#GIT_VER[@]}; i++))
|
||||
do
|
||||
if [ -z "${GIT_MIN_VER[i]}" ]
|
||||
then
|
||||
GIT_MIN_VER[i]=0
|
||||
fi
|
||||
if [ "${GIT_VER[i]}" -lt "${GIT_MIN_VER[i]}" ]
|
||||
then
|
||||
GIT_HAS_JOBS=0
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if [ "$GIT_HAS_JOBS" -ne 0 ]
|
||||
then
|
||||
DEPINST_ARGS+=("--git_args" "--jobs $GIT_FETCH_JOBS")
|
||||
fi
|
||||
cd ..
|
||||
git clone -b "$BOOST_BRANCH" --depth 1 "https://github.com/boostorg/boost.git" "boost-root"
|
||||
cd boost-root
|
||||
mkdir -p libs/$LIBRARY
|
||||
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
|
||||
git submodule update --init tools/boostdep
|
||||
DEPINST_ARGS+=("$LIBRARY")
|
||||
python tools/boostdep/depinst/depinst.py "${DEPINST_ARGS[@]}"
|
||||
if [ -z "${{matrix.cmake_tests}}" ]
|
||||
then
|
||||
./bootstrap.sh
|
||||
./b2 headers
|
||||
if [ -n "${{matrix.compiler}}" -o -n "$GCC_TOOLCHAIN_ROOT" ]
|
||||
then
|
||||
echo -n "using ${{matrix.toolset}} : : ${{matrix.compiler}}" > ~/user-config.jam
|
||||
if [ -n "$GCC_TOOLCHAIN_ROOT" ]
|
||||
then
|
||||
echo -n " : <compileflags>\"--gcc-toolchain=$GCC_TOOLCHAIN_ROOT\" <linkflags>\"--gcc-toolchain=$GCC_TOOLCHAIN_ROOT\"" >> ~/user-config.jam
|
||||
fi
|
||||
echo " ;" >> ~/user-config.jam
|
||||
fi
|
||||
fi
|
||||
|
||||
- name: Run tests
|
||||
if: matrix.cmake_tests == ''
|
||||
run: |
|
||||
cd ../boost-root
|
||||
B2_ARGS=("-j" "$BUILD_JOBS" "toolset=${{matrix.toolset}}" "cxxstd=${{matrix.cxxstd}}")
|
||||
if [ -n "${{matrix.build_variant}}" ]
|
||||
then
|
||||
B2_ARGS+=("variant=${{matrix.build_variant}}")
|
||||
else
|
||||
B2_ARGS+=("variant=$DEFAULT_BUILD_VARIANT")
|
||||
fi
|
||||
if [ -n "${{matrix.threading}}" ]
|
||||
then
|
||||
B2_ARGS+=("threading=${{matrix.threading}}")
|
||||
fi
|
||||
if [ -n "${{matrix.ubsan}}" ]
|
||||
then
|
||||
export UBSAN_OPTIONS="print_stacktrace=1"
|
||||
B2_ARGS+=("cxxflags=-fsanitize=undefined -fno-sanitize-recover=undefined" "linkflags=-fsanitize=undefined -fuse-ld=gold" "define=UBSAN=1" "debug-symbols=on" "visibility=global")
|
||||
fi
|
||||
if [ -n "${{matrix.cxxflags}}" ]
|
||||
then
|
||||
B2_ARGS+=("cxxflags=${{matrix.cxxflags}}")
|
||||
fi
|
||||
if [ -n "${{matrix.linkflags}}" ]
|
||||
then
|
||||
B2_ARGS+=("linkflags=${{matrix.linkflags}}")
|
||||
fi
|
||||
B2_ARGS+=("libs/$LIBRARY/test")
|
||||
./b2 "${B2_ARGS[@]}"
|
118
Assignable.html
118
Assignable.html
@ -1,109 +1,19 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Language" content="en-us">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
|
||||
|
||||
<title>Assignable</title>
|
||||
<title>Boost.Utility</title>
|
||||
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
|
||||
"#FF0000">
|
||||
<img src="../../boost.png" alt="C++ Boost" width="277" height=
|
||||
"86"><br clear="none">
|
||||
|
||||
<h1>Assignable</h1>
|
||||
|
||||
<h3>Description</h3>
|
||||
|
||||
<p>A type is Assignable if it is possible to assign one object of the type
|
||||
to another object of that type.</p>
|
||||
|
||||
<h3>Notation</h3>
|
||||
|
||||
<table summary="">
|
||||
<tr>
|
||||
<td valign="top"><tt>T</tt></td>
|
||||
|
||||
<td valign="top">is type that is a model of Assignable</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top"><tt>t</tt></td>
|
||||
|
||||
<td valign="top">is an object of type <tt>T</tt></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top"><tt>u</tt></td>
|
||||
|
||||
<td valign="top">is an object of type <tt>T</tt> or possibly <tt>const
|
||||
T</tt></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3>Definitions</h3>
|
||||
|
||||
<h3>Valid expressions</h3>
|
||||
|
||||
<table border summary="">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
|
||||
<th>Expression</th>
|
||||
|
||||
<th>Return type</th>
|
||||
|
||||
<th>Semantics</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Assignment</td>
|
||||
|
||||
<td valign="top"><tt>t = u</tt></td>
|
||||
|
||||
<td valign="top"><tt>T&</tt></td>
|
||||
|
||||
<td valign="top"><tt>t</tt> is equivalent to <tt>u</tt></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3>Models</h3>
|
||||
|
||||
<ul>
|
||||
<li><tt>int</tt></li>
|
||||
|
||||
<li><tt>std::pair</tt></li>
|
||||
</ul>
|
||||
|
||||
<h3>See also</h3>
|
||||
|
||||
<p><a href=
|
||||
"http://www.sgi.com/tech/stl/DefaultConstructible.html">DefaultConstructible</a>
|
||||
and <a href="./CopyConstructible.html">CopyConstructible</a><br></p>
|
||||
<hr>
|
||||
|
||||
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
|
||||
"../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
|
||||
height="31" width="88"></a></p>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->05 December, 2006<!--webbot bot="Timestamp" endspan i-checksum="38516" --></p>
|
||||
|
||||
<table summary="">
|
||||
<tr valign="top">
|
||||
<td nowrap><i>Copyright © 2000</i></td>
|
||||
|
||||
<td><i><a href="http://www.lsc.nd.edu/~jsiek">Jeremy Siek</a>, Univ.of
|
||||
Notre Dame (<a href=
|
||||
"mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</a>)</i></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p><i>Distributed under the Boost Software License, Version 1.0. (See
|
||||
accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or
|
||||
copy at <a href=
|
||||
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="./doc/html/index.html">./doc/html/index.html</a>
|
||||
<hr>
|
||||
<tt>
|
||||
Boost.Utility<br>
|
||||
<br>
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||
<br>
|
||||
</tt>
|
||||
</body>
|
||||
</html>
|
||||
|
24
CMakeLists.txt
Normal file
24
CMakeLists.txt
Normal file
@ -0,0 +1,24 @@
|
||||
# Copyright 2018 Peter Dimov
|
||||
# Copyright 2018 Andrey Semashev
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
cmake_minimum_required(VERSION 3.5...3.20)
|
||||
|
||||
project(boost_utility VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX)
|
||||
|
||||
add_library(boost_utility INTERFACE)
|
||||
add_library(Boost::utility ALIAS boost_utility)
|
||||
|
||||
target_include_directories(boost_utility INTERFACE include)
|
||||
|
||||
target_link_libraries(boost_utility
|
||||
INTERFACE
|
||||
Boost::config
|
||||
Boost::core
|
||||
Boost::io
|
||||
Boost::preprocessor
|
||||
Boost::static_assert
|
||||
Boost::throw_exception
|
||||
Boost::type_traits
|
||||
)
|
543
Collection.html
543
Collection.html
@ -1,534 +1,19 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Language" content="en-us">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
|
||||
|
||||
<title>Collection</title>
|
||||
<title>Boost.Utility</title>
|
||||
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
|
||||
"#FF0000">
|
||||
<h1><img src="../../boost.png" alt="boost logo" width="277" align="middle"
|
||||
height="86"><br>
|
||||
Collection</h1>
|
||||
|
||||
<h3>Description</h3>
|
||||
|
||||
<p>A Collection is a <i>concept</i> similar to the STL <a href=
|
||||
"http://www.sgi.com/tech/stl/Container.html">Container</a> concept. A
|
||||
Collection provides iterators for accessing a range of elements and
|
||||
provides information about the number of elements in the Collection.
|
||||
However, a Collection has fewer requirements than a Container. The
|
||||
motivation for the Collection concept is that there are many useful
|
||||
Container-like types that do not meet the full requirements of Container,
|
||||
and many algorithms that can be written with this reduced set of
|
||||
requirements. To summarize the reduction in requirements:</p>
|
||||
|
||||
<ul>
|
||||
<li>It is not required to "own" its elements: the lifetime of an element
|
||||
in a Collection does not have to match the lifetime of the Collection
|
||||
object, though the lifetime of the element should cover the lifetime of
|
||||
the Collection object.</li>
|
||||
|
||||
<li>The semantics of copying a Collection object is not defined (it could
|
||||
be a deep or shallow copy or not even support copying).</li>
|
||||
|
||||
<li>The associated reference type of a Collection does not have to be a
|
||||
real C++ reference.</li>
|
||||
</ul>Because of the reduced requirements, some care must be taken when
|
||||
writing code that is meant to be generic for all Collection types. In
|
||||
particular, a Collection object should be passed by-reference since
|
||||
assumptions can not be made about the behaviour of the copy constructor.
|
||||
|
||||
<h3>Associated types</h3>
|
||||
|
||||
<table border summary="">
|
||||
<tr>
|
||||
<td valign="top">Value type</td>
|
||||
|
||||
<td valign="top"><tt>X::value_type</tt></td>
|
||||
|
||||
<td valign="top">The type of the object stored in a Collection. If the
|
||||
Collection is <i>mutable</i> then the value type must be <a href=
|
||||
"http://www.sgi.com/tech/stl/Assignable.html">Assignable</a>. Otherwise
|
||||
the value type must be <a href=
|
||||
"./CopyConstructible.html">CopyConstructible</a>.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Iterator type</td>
|
||||
|
||||
<td valign="top"><tt>X::iterator</tt></td>
|
||||
|
||||
<td valign="top">The type of iterator used to iterate through a
|
||||
Collection's elements. The iterator's value type is expected to be the
|
||||
Collection's value type. A conversion from the iterator type to the
|
||||
const iterator type must exist. The iterator type must be an <a href=
|
||||
"http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Const iterator type</td>
|
||||
|
||||
<td valign="top"><tt>X::const_iterator</tt></td>
|
||||
|
||||
<td valign="top">A type of iterator that may be used to examine, but
|
||||
not to modify, a Collection's elements.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Reference type</td>
|
||||
|
||||
<td valign="top"><tt>X::reference</tt></td>
|
||||
|
||||
<td valign="top">A type that behaves like a reference to the
|
||||
Collection's value type. <a href="#n1">[1]</a></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Const reference type</td>
|
||||
|
||||
<td valign="top"><tt>X::const_reference</tt></td>
|
||||
|
||||
<td valign="top">A type that behaves like a const reference to the
|
||||
Collection's value type.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Pointer type</td>
|
||||
|
||||
<td valign="top"><tt>X::pointer</tt></td>
|
||||
|
||||
<td valign="top">A type that behaves as a pointer to the Collection's
|
||||
value type.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Distance type</td>
|
||||
|
||||
<td valign="top"><tt>X::difference_type</tt></td>
|
||||
|
||||
<td valign="top">A signed integral type used to represent the distance
|
||||
between two of the Collection's iterators. This type must be the same
|
||||
as the iterator's distance type.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Size type</td>
|
||||
|
||||
<td valign="top"><tt>X::size_type</tt></td>
|
||||
|
||||
<td valign="top">An unsigned integral type that can represent any
|
||||
nonnegative value of the Collection's distance type.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3>Notation</h3>
|
||||
|
||||
<table summary="">
|
||||
<tr>
|
||||
<td valign="top"><tt>X</tt></td>
|
||||
|
||||
<td valign="top">A type that is a model of Collection.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top"><tt>a</tt>, <tt>b</tt></td>
|
||||
|
||||
<td valign="top">Object of type <tt>X</tt>.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top"><tt>T</tt></td>
|
||||
|
||||
<td valign="top">The value type of <tt>X</tt>.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3>Valid expressions</h3>
|
||||
|
||||
<p>The following expressions must be valid.</p>
|
||||
|
||||
<table border summary="">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
|
||||
<th>Expression</th>
|
||||
|
||||
<th>Return type</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Beginning of range</td>
|
||||
|
||||
<td valign="top"><tt>a.begin()</tt></td>
|
||||
|
||||
<td valign="top"><tt>iterator</tt> if <tt>a</tt> is mutable,
|
||||
<tt>const_iterator</tt> otherwise</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">End of range</td>
|
||||
|
||||
<td valign="top"><tt>a.end()</tt></td>
|
||||
|
||||
<td valign="top"><tt>iterator</tt> if <tt>a</tt> is mutable,
|
||||
<tt>const_iterator</tt> otherwise</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Size</td>
|
||||
|
||||
<td valign="top"><tt>a.size()</tt></td>
|
||||
|
||||
<td valign="top"><tt>size_type</tt></td>
|
||||
</tr><!--
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Maximum size
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>a.max_size()</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>size_type</tt>
|
||||
</TD>
|
||||
</TR>
|
||||
-->
|
||||
|
||||
<tr>
|
||||
<td valign="top">Empty Collection</td>
|
||||
|
||||
<td valign="top"><tt>a.empty()</tt></td>
|
||||
|
||||
<td valign="top">Convertible to <tt>bool</tt></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Swap</td>
|
||||
|
||||
<td valign="top"><tt>a.swap(b)</tt></td>
|
||||
|
||||
<td valign="top"><tt>void</tt></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3>Expression semantics</h3>
|
||||
|
||||
<table border summary="">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
|
||||
<th>Expression</th>
|
||||
|
||||
<th>Semantics</th>
|
||||
|
||||
<th>Postcondition</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Beginning of range</td>
|
||||
|
||||
<td valign="top"><tt>a.begin()</tt></td>
|
||||
|
||||
<td valign="top">Returns an iterator pointing to the first element in
|
||||
the Collection.</td>
|
||||
|
||||
<td valign="top"><tt>a.begin()</tt> is either dereferenceable or
|
||||
past-the-end. It is past-the-end if and only if <tt>a.size() ==
|
||||
0</tt>.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">End of range</td>
|
||||
|
||||
<td valign="top"><tt>a.end()</tt></td>
|
||||
|
||||
<td valign="top">Returns an iterator pointing one past the last element
|
||||
in the Collection.</td>
|
||||
|
||||
<td valign="top"><tt>a.end()</tt> is past-the-end.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Size</td>
|
||||
|
||||
<td valign="top"><tt>a.size()</tt></td>
|
||||
|
||||
<td valign="top">Returns the size of the Collection, that is, its
|
||||
number of elements.</td>
|
||||
|
||||
<td valign="top"><tt>a.size() >= 0</tt></td>
|
||||
</tr><!--
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Maximum size
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>a.max_size()</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
Returns the largest size that this Collection can ever have. <A href="#8">[8]</A>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>a.max_size() >= 0 && a.max_size() >= a.size()</tt>
|
||||
</TD>
|
||||
</TR>
|
||||
-->
|
||||
|
||||
<tr>
|
||||
<td valign="top">Empty Collection</td>
|
||||
|
||||
<td valign="top"><tt>a.empty()</tt></td>
|
||||
|
||||
<td valign="top">Equivalent to <tt>a.size() == 0</tt>. (But possibly
|
||||
faster.)</td>
|
||||
|
||||
<td valign="top"> </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Swap</td>
|
||||
|
||||
<td valign="top"><tt>a.swap(b)</tt></td>
|
||||
|
||||
<td valign="top">Equivalent to <tt>swap(a,b)</tt></td>
|
||||
|
||||
<td valign="top"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3>Complexity guarantees</h3>
|
||||
|
||||
<p><tt>begin()</tt> and <tt>end()</tt> are amortized constant time.</p>
|
||||
|
||||
<p><tt>size()</tt> is at most linear in the Collection's size.
|
||||
<tt>empty()</tt> is amortized constant time.</p>
|
||||
|
||||
<p><tt>swap()</tt> is at most linear in the size of the two
|
||||
collections.</p>
|
||||
|
||||
<h3>Invariants</h3>
|
||||
|
||||
<table border summary="">
|
||||
<tr>
|
||||
<td valign="top">Valid range</td>
|
||||
|
||||
<td valign="top">For any Collection <tt>a</tt>, <tt>[a.begin(),
|
||||
a.end())</tt> is a valid range.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Range size</td>
|
||||
|
||||
<td valign="top"><tt>a.size()</tt> is equal to the distance from
|
||||
<tt>a.begin()</tt> to <tt>a.end()</tt>.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Completeness</td>
|
||||
|
||||
<td valign="top">An algorithm that iterates through the range
|
||||
<tt>[a.begin(), a.end())</tt> will pass through every element of
|
||||
<tt>a</tt>.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3>Models</h3>
|
||||
|
||||
<ul>
|
||||
<li><tt>array</tt></li>
|
||||
|
||||
<li><tt>array_ptr</tt></li>
|
||||
|
||||
<li><tt>vector<bool></tt></li>
|
||||
</ul>
|
||||
|
||||
<h3>Collection Refinements</h3>
|
||||
|
||||
<p>There are quite a few concepts that refine the Collection concept,
|
||||
similar to the concepts that refine the Container concept. Here is a brief
|
||||
overview of the refining concepts.</p>
|
||||
|
||||
<h4>ForwardCollection</h4>
|
||||
|
||||
<p>The elements are arranged in some order that does not change
|
||||
spontaneously from one iteration to the next. As a result, a
|
||||
ForwardCollection is <a href=
|
||||
"http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</a>
|
||||
and <a href=
|
||||
"http://www.sgi.com/tech/stl/LessThanComparable.html">LessThanComparable</a>.
|
||||
In addition, the iterator type of a ForwardCollection is a
|
||||
MultiPassInputIterator which is just an InputIterator with the added
|
||||
requirements that the iterator can be used to make multiple passes through
|
||||
a range, and that if <tt>it1 == it2</tt> and <tt>it1</tt> is
|
||||
dereferenceable then <tt>++it1 == ++it2</tt>. The ForwardCollection also
|
||||
has a <tt>front()</tt> method.</p>
|
||||
|
||||
<table border summary="">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
|
||||
<th>Expression</th>
|
||||
|
||||
<th>Return type</th>
|
||||
|
||||
<th>Semantics</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Front</td>
|
||||
|
||||
<td valign="top"><tt>a.front()</tt></td>
|
||||
|
||||
<td valign="top"><tt>reference</tt> if <tt>a</tt> is mutable,<br>
|
||||
<tt>const_reference</tt> otherwise.</td>
|
||||
|
||||
<td valign="top">Equivalent to <tt>*(a.begin())</tt>.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h4>ReversibleCollection</h4>
|
||||
|
||||
<p>The container provides access to iterators that traverse in both
|
||||
directions (forward and reverse). The iterator type must meet all of the
|
||||
requirements of <a href=
|
||||
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterator</a>
|
||||
except that the reference type does not have to be a real C++ reference.
|
||||
The ReversibleCollection adds the following requirements to those of
|
||||
ForwardCollection.</p>
|
||||
|
||||
<table border summary="">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
|
||||
<th>Expression</th>
|
||||
|
||||
<th>Return type</th>
|
||||
|
||||
<th>Semantics</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Beginning of range</td>
|
||||
|
||||
<td valign="top"><tt>a.rbegin()</tt></td>
|
||||
|
||||
<td valign="top"><tt>reverse_iterator</tt> if <tt>a</tt> is mutable,
|
||||
<tt>const_reverse_iterator</tt> otherwise.</td>
|
||||
|
||||
<td valign="top">Equivalent to
|
||||
<tt>X::reverse_iterator(a.end())</tt>.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">End of range</td>
|
||||
|
||||
<td valign="top"><tt>a.rend()</tt></td>
|
||||
|
||||
<td valign="top"><tt>reverse_iterator</tt> if <tt>a</tt> is mutable,
|
||||
<tt>const_reverse_iterator</tt> otherwise.</td>
|
||||
|
||||
<td valign="top">Equivalent to
|
||||
<tt>X::reverse_iterator(a.begin())</tt>.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Back</td>
|
||||
|
||||
<td valign="top"><tt>a.back()</tt></td>
|
||||
|
||||
<td valign="top"><tt>reference</tt> if <tt>a</tt> is mutable,<br>
|
||||
<tt>const_reference</tt> otherwise.</td>
|
||||
|
||||
<td valign="top">Equivalent to <tt>*(--a.end())</tt>.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h4>SequentialCollection</h4>
|
||||
|
||||
<p>The elements are arranged in a strict linear order. No extra methods are
|
||||
required.</p>
|
||||
|
||||
<h4>RandomAccessCollection</h4>
|
||||
|
||||
<p>The iterators of a RandomAccessCollection satisfy all of the
|
||||
requirements of <a href=
|
||||
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a>
|
||||
except that the reference type does not have to be a real C++ reference. In
|
||||
addition, a RandomAccessCollection provides an element access operator.</p>
|
||||
|
||||
<table border summary="">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
|
||||
<th>Expression</th>
|
||||
|
||||
<th>Return type</th>
|
||||
|
||||
<th>Semantics</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Element Access</td>
|
||||
|
||||
<td valign="top"><tt>a[n]</tt></td>
|
||||
|
||||
<td valign="top"><tt>reference</tt> if <tt>a</tt> is mutable,
|
||||
<tt>const_reference</tt> otherwise.</td>
|
||||
|
||||
<td valign="top">Returns the nth element of the Collection. <tt>n</tt>
|
||||
must be convertible to <tt>size_type</tt>. Precondition: <tt>0 <= n
|
||||
< a.size()</tt>.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3>Notes</h3>
|
||||
|
||||
<p><a name="n1" id="n1">[1]</a> The reference type does not have to be a
|
||||
real C++ reference. The requirements of the reference type depend on the
|
||||
context within which the Collection is being used. Specifically it depends
|
||||
on the requirements the context places on the value type of the Collection.
|
||||
The reference type of the Collection must meet the same requirements as the
|
||||
value type. In addition, the reference objects must be equivalent to the
|
||||
value type objects in the collection (which is trivially true if they are
|
||||
the same object). Also, in a mutable Collection, an assignment to the
|
||||
reference object must result in an assignment to the object in the
|
||||
Collection (again, which is trivially true if they are the same object, but
|
||||
non-trivial if the reference type is a proxy class).</p>
|
||||
|
||||
<h3>See also</h3>
|
||||
|
||||
<p><a href=
|
||||
"http://www.sgi.com/tech/stl/Container.html">Container</a><br></p>
|
||||
<hr>
|
||||
|
||||
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
|
||||
"../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
|
||||
height="31" width="88"></a></p>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->05
|
||||
December, 2006<!--webbot bot="Timestamp" endspan i-checksum="38516" --></p>
|
||||
|
||||
<table summary="">
|
||||
<tr valign="top">
|
||||
<td nowrap><i>Copyright © 2000</i></td>
|
||||
|
||||
<td><i><a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy
|
||||
Siek</a>, Univ.of Notre Dame and C++ Library & Compiler Group/SGI
|
||||
(<a href="mailto:jsiek@engr.sgi.com">jsiek@engr.sgi.com</a>)</i></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p><i>Distributed under the Boost Software License, Version 1.0. (See
|
||||
accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or
|
||||
copy at <a href=
|
||||
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="./doc/html/index.html">./doc/html/index.html</a>
|
||||
<hr>
|
||||
<tt>
|
||||
Boost.Utility<br>
|
||||
<br>
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||
<br>
|
||||
</tt>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,185 +1,19 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Language" content="en-us">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
|
||||
|
||||
<title>Copy Constructible</title>
|
||||
<title>Boost.Utility</title>
|
||||
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
|
||||
"#FF0000">
|
||||
<img src="../../boost.png" alt="C++ Boost" width="277" height=
|
||||
"86"><br clear="none">
|
||||
|
||||
<h1>Copy Constructible</h1>
|
||||
|
||||
<h3>Description</h3>
|
||||
|
||||
<p>A type is Copy Constructible if it is possible to copy objects of that
|
||||
type.</p>
|
||||
|
||||
<h3>Notation</h3>
|
||||
|
||||
<table summary="">
|
||||
<tr>
|
||||
<td valign="top"><tt>T</tt></td>
|
||||
|
||||
<td valign="top">is type that is a model of Copy Constructible</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top"><tt>t</tt></td>
|
||||
|
||||
<td valign="top">is an object of type <tt>T</tt></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top"><tt>u</tt></td>
|
||||
|
||||
<td valign="top">is an object of type <tt>const T</tt></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3>Definitions</h3>
|
||||
|
||||
<h3>Valid expressions</h3>
|
||||
|
||||
<table border summary="">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
|
||||
<th>Expression</th>
|
||||
|
||||
<th>Return type</th>
|
||||
|
||||
<th>Semantics</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Copy constructor</td>
|
||||
|
||||
<td valign="top"><tt>T(t)</tt></td>
|
||||
|
||||
<td valign="top"><tt>T</tt></td>
|
||||
|
||||
<td valign="top"><tt>t</tt> is equivalent to <tt>T(t)</tt></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Copy constructor</td>
|
||||
|
||||
<td valign="top">
|
||||
<pre>
|
||||
T(u)
|
||||
</pre>
|
||||
</td>
|
||||
|
||||
<td valign="top"><tt>T</tt></td>
|
||||
|
||||
<td valign="top"><tt>u</tt> is equivalent to <tt>T(u)</tt></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Destructor</td>
|
||||
|
||||
<td valign="top">
|
||||
<pre>
|
||||
t.~T()
|
||||
</pre>
|
||||
</td>
|
||||
|
||||
<td valign="top"><tt>T</tt></td>
|
||||
|
||||
<td valign="top"> </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Address Operator</td>
|
||||
|
||||
<td valign="top">
|
||||
<pre>
|
||||
&t
|
||||
</pre>
|
||||
</td>
|
||||
|
||||
<td valign="top"><tt>T*</tt></td>
|
||||
|
||||
<td valign="top">denotes the address of <tt>t</tt></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Address Operator</td>
|
||||
|
||||
<td valign="top">
|
||||
<pre>
|
||||
&u
|
||||
</pre>
|
||||
</td>
|
||||
|
||||
<td valign="top"><tt>T*</tt></td>
|
||||
|
||||
<td valign="top">denotes the address of <tt>u</tt></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3>Models</h3>
|
||||
|
||||
<ul>
|
||||
<li><tt>int</tt></li>
|
||||
|
||||
<li><tt>std::pair</tt></li>
|
||||
</ul>
|
||||
|
||||
<h3>Concept Checking Class</h3>
|
||||
<pre>
|
||||
template <class T>
|
||||
struct CopyConstructibleConcept
|
||||
{
|
||||
void constraints() {
|
||||
T a(b); // require copy constructor
|
||||
T* ptr = &a; // require address of operator
|
||||
const_constraints(a);
|
||||
ignore_unused_variable_warning(ptr);
|
||||
}
|
||||
void const_constraints(const T& a) {
|
||||
T c(a); // require const copy constructor
|
||||
const T* ptr = &a; // require const address of operator
|
||||
ignore_unused_variable_warning(c);
|
||||
ignore_unused_variable_warning(ptr);
|
||||
}
|
||||
T b;
|
||||
};
|
||||
</pre>
|
||||
|
||||
<h3>See also</h3>
|
||||
|
||||
<p><a href="http://www.sgi.com/tech/stl/DefaultConstructible.html">Default
|
||||
Constructible</a> and <a href="./Assignable.html">Assignable</a><br></p>
|
||||
<hr>
|
||||
|
||||
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
|
||||
"../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
|
||||
height="31" width="88"></a></p>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->05
|
||||
December, 2006<!--webbot bot="Timestamp" endspan i-checksum="38516" --></p>
|
||||
|
||||
<table summary="">
|
||||
<tr valign="top">
|
||||
<td nowrap><i>Copyright © 2000</i></td>
|
||||
|
||||
<td><i><a href="http://www.lsc.nd.edu/~jsiek">Jeremy Siek</a>, Univ.of
|
||||
Notre Dame (<a href=
|
||||
"mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</a>)</i></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p><i>Distributed under the Boost Software License, Version 1.0. (See
|
||||
accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or
|
||||
copy at <a href=
|
||||
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="./doc/html/index.html">./doc/html/index.html</a>
|
||||
<hr>
|
||||
<tt>
|
||||
Boost.Utility<br>
|
||||
<br>
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||
<br>
|
||||
</tt>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,210 +1,19 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<!--
|
||||
== Copyright (c) 1996-1999
|
||||
== Silicon Graphics Computer Systems, Inc.
|
||||
==
|
||||
== Permission to use, copy, modify, distribute and sell this software
|
||||
== and its documentation for any purpose is hereby granted without fee,
|
||||
== provided that the above copyright notice appears in all copies and
|
||||
== that both that copyright notice and this permission notice appear
|
||||
== in supporting documentation. Silicon Graphics makes no
|
||||
== representations about the suitability of this software for any
|
||||
== purpose. It is provided "as is" without express or implied warranty.
|
||||
==
|
||||
== Copyright (c) 1994
|
||||
== Hewlett-Packard Company
|
||||
==
|
||||
== Permission to use, copy, modify, distribute and sell this software
|
||||
== and its documentation for any purpose is hereby granted without fee,
|
||||
== provided that the above copyright notice appears in all copies and
|
||||
== that both that copyright notice and this permission notice appear
|
||||
== in supporting documentation. Hewlett-Packard Company makes no
|
||||
== representations about the suitability of this software for any
|
||||
== purpose. It is provided "as is" without express or implied warranty.
|
||||
==
|
||||
-->
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Language" content="en-us">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
|
||||
|
||||
<title>LessThanComparable</title>
|
||||
<title>Boost.Utility</title>
|
||||
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
|
||||
"#FF0000">
|
||||
<img src="../../boost.png" alt="C++ Boost" width="277" height=
|
||||
"86"><br clear="none">
|
||||
|
||||
<h1>LessThanComparable</h1>
|
||||
|
||||
<h3>Description</h3>
|
||||
|
||||
<p>A type is LessThanComparable if it is ordered: it must be possible to
|
||||
compare two objects of that type using <tt>operator<</tt>, and
|
||||
<tt>operator<</tt> must be a strict weak ordering relation.</p>
|
||||
|
||||
<h3>Refinement of</h3>
|
||||
|
||||
<h3>Associated types</h3>
|
||||
|
||||
<h3>Notation</h3>
|
||||
|
||||
<table summary="">
|
||||
<tr>
|
||||
<td valign="top"><tt>X</tt></td>
|
||||
|
||||
<td valign="top">A type that is a model of LessThanComparable</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top"><tt>x</tt>, <tt>y</tt>, <tt>z</tt></td>
|
||||
|
||||
<td valign="top">Object of type <tt>X</tt></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3>Definitions</h3>
|
||||
|
||||
<p>Consider the relation <tt>!(x < y) && !(y < x)</tt>. If
|
||||
this relation is transitive (that is, if <tt>!(x < y) && !(y
|
||||
< x) && !(y < z) && !(z < y)</tt> implies <tt>!(x
|
||||
< z) && !(z < x)</tt>), then it satisfies the mathematical
|
||||
definition of an equivalence relation. In this case, <tt>operator<</tt>
|
||||
is a <i>strict weak ordering</i>.</p>
|
||||
|
||||
<p>If <tt>operator<</tt> is a strict weak ordering, and if each
|
||||
equivalence class has only a single element, then <tt>operator<</tt> is
|
||||
a <i>total ordering</i>.</p>
|
||||
|
||||
<h3>Valid expressions</h3>
|
||||
|
||||
<table border summary="">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
|
||||
<th>Expression</th>
|
||||
|
||||
<th>Type requirements</th>
|
||||
|
||||
<th>Return type</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Less</td>
|
||||
|
||||
<td valign="top"><tt>x < y</tt></td>
|
||||
|
||||
<td valign="top"> </td>
|
||||
|
||||
<td valign="top">Convertible to <tt>bool</tt></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3>Expression semantics</h3>
|
||||
|
||||
<table border summary="">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
|
||||
<th>Expression</th>
|
||||
|
||||
<th>Precondition</th>
|
||||
|
||||
<th>Semantics</th>
|
||||
|
||||
<th>Postcondition</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Less</td>
|
||||
|
||||
<td valign="top"><tt>x < y</tt></td>
|
||||
|
||||
<td valign="top"><tt>x</tt> and <tt>y</tt> are in the domain of
|
||||
<tt><</tt></td>
|
||||
|
||||
<td valign="top"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3>Complexity guarantees</h3>
|
||||
|
||||
<h3>Invariants</h3>
|
||||
|
||||
<table border summary="">
|
||||
<tr>
|
||||
<td valign="top">Irreflexivity</td>
|
||||
|
||||
<td valign="top"><tt>x < x</tt> must be false.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Antisymmetry</td>
|
||||
|
||||
<td valign="top"><tt>x < y</tt> implies !(y < x) <a href=
|
||||
"#n2">[2]</a></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Transitivity</td>
|
||||
|
||||
<td valign="top"><tt>x < y</tt> and <tt>y < z</tt> implies <tt>x
|
||||
< z</tt> <a href="#n3">[3]</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3>Models</h3>
|
||||
|
||||
<ul>
|
||||
<li>int</li>
|
||||
</ul>
|
||||
|
||||
<h3>Notes</h3>
|
||||
|
||||
<p><a name="n1" id="n1">[1]</a> Only <tt>operator<</tt> is fundamental;
|
||||
the other inequality operators are essentially syntactic sugar.</p>
|
||||
|
||||
<p><a name="n2" id="n2">[2]</a> Antisymmetry is a theorem, not an axiom: it
|
||||
follows from irreflexivity and transitivity.</p>
|
||||
|
||||
<p><a name="n3" id="n3">[3]</a> Because of irreflexivity and transitivity,
|
||||
<tt>operator<</tt> always satisfies the definition of a <i>partial
|
||||
ordering</i>. The definition of a <i>strict weak ordering</i> is stricter,
|
||||
and the definition of a <i>total ordering</i> is stricter still.</p>
|
||||
|
||||
<h3>See also</h3>
|
||||
|
||||
<p><a href=
|
||||
"http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</a>,
|
||||
<a href=
|
||||
"http://www.sgi.com/tech/stl/StrictWeakOrdering.html">StrictWeakOrdering</a><br>
|
||||
</p>
|
||||
<hr>
|
||||
|
||||
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
|
||||
"../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
|
||||
height="31" width="88"></a></p>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->05
|
||||
December, 2006<!--webbot bot="Timestamp" endspan i-checksum="38516" --></p>
|
||||
|
||||
<table summary="">
|
||||
<tr valign="top">
|
||||
<td nowrap><i>Copyright © 2000</i></td>
|
||||
|
||||
<td><i><a href="http://www.lsc.nd.edu/~jsiek">Jeremy Siek</a>, Univ.of
|
||||
Notre Dame (<a href=
|
||||
"mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</a>)</i></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p><i>Distributed under the Boost Software License, Version 1.0. (See
|
||||
accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or
|
||||
copy at <a href=
|
||||
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="./doc/html/index.html">./doc/html/index.html</a>
|
||||
<hr>
|
||||
<tt>
|
||||
Boost.Utility<br>
|
||||
<br>
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||
<br>
|
||||
</tt>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,95 +1,19 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Language" content="en-us">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
|
||||
|
||||
<title>MultiPassInputIterator</title>
|
||||
<title>Boost.Utility</title>
|
||||
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
|
||||
"#FF0000">
|
||||
<img src="../../boost.png" alt="C++ Boost" width="277" height=
|
||||
"86"><br clear="none">
|
||||
|
||||
<h2><a name="concept:MultiPassInputIterator" id=
|
||||
"concept:MultiPassInputIterator"></a> Multi-Pass Input Iterator</h2>
|
||||
|
||||
<p>This concept is a refinement of <a href=
|
||||
"http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>, adding
|
||||
the requirements that the iterator can be used to make multiple passes
|
||||
through a range, and that if <tt>it1 == it2</tt> and <tt>it1</tt> is
|
||||
dereferenceable then <tt>++it1 == ++it2</tt>. The Multi-Pass Input Iterator
|
||||
is very similar to the <a href=
|
||||
"http://www.sgi.com/tech/stl/ForwardIterator.html">Forward Iterator</a>.
|
||||
The only difference is that a <a href=
|
||||
"http://www.sgi.com/tech/stl/ForwardIterator.html">Forward Iterator</a>
|
||||
requires the <tt>reference</tt> type to be <tt>value_type&</tt>,
|
||||
whereas MultiPassInputIterator is like <a href=
|
||||
"http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a> in that
|
||||
the <tt>reference</tt> type merely has to be convertible to
|
||||
<tt>value_type</tt>.</p>
|
||||
|
||||
<h3>Design Notes</h3>
|
||||
|
||||
<p>comments by Valentin Bonnard:</p>
|
||||
|
||||
<p>I think that introducing Multi-Pass Input Iterator isn't the right
|
||||
solution. Do you also want to define Multi-Pass Bidirectionnal Iterator and
|
||||
Multi-Pass Random Access Iterator ? I don't, definitly. It only confuses
|
||||
the issue. The problem lies into the existing hierarchy of iterators, which
|
||||
mixes movabillity, modifiabillity and lvalue-ness, and these are clearly
|
||||
independant.</p>
|
||||
|
||||
<p>The terms Forward, Bidirectionnal and Random Access are about
|
||||
movabillity and shouldn't be used to mean anything else. In a completly
|
||||
orthogonal way, iterators can be immutable, mutable, or neither. Lvalueness
|
||||
of iterators is also orthogonal with immutabillity. With these clean
|
||||
concepts, your Multi-Pass Input Iterator is just called a Forward
|
||||
Iterator.</p>
|
||||
|
||||
<p>Other translations are:<br>
|
||||
std::Forward Iterator -> ForwardIterator & Lvalue Iterator<br>
|
||||
std::Bidirectionnal Iterator -> Bidirectionnal Iterator & Lvalue
|
||||
Iterator<br>
|
||||
std::Random Access Iterator -> Random Access Iterator & Lvalue
|
||||
Iterator<br></p>
|
||||
|
||||
<p>Note that in practice the only operation not allowed on my Forward
|
||||
Iterator which is allowed on std::Forward Iterator is <tt>&*it</tt>. I
|
||||
think that <tt>&*</tt> is rarely needed in generic code.</p>
|
||||
|
||||
<p>reply by Jeremy Siek:</p>
|
||||
|
||||
<p>The above analysis by Valentin is right on. Of course, there is the
|
||||
problem with backward compatibility. The current STL implementations are
|
||||
based on the old definition of Forward Iterator. The right course of action
|
||||
is to get Forward Iterator, etc. changed in the C++ standard. Once that is
|
||||
done we can drop Multi-Pass Input Iterator.<br></p>
|
||||
<hr>
|
||||
|
||||
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
|
||||
"../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
|
||||
height="31" width="88"></a></p>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->05
|
||||
December, 2006<!--webbot bot="Timestamp" endspan i-checksum="38516" --></p>
|
||||
|
||||
<table summary="">
|
||||
<tr valign="top">
|
||||
<td nowrap><i>Copyright © 2000</i></td>
|
||||
|
||||
<td><i><a href="http://www.lsc.nd.edu/~jsiek">Jeremy Siek</a>, Univ.of
|
||||
Notre Dame (<a href=
|
||||
"mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</a>)</i></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p><i>Distributed under the Boost Software License, Version 1.0. (See
|
||||
accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or
|
||||
copy at <a href=
|
||||
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="./doc/html/index.html">./doc/html/index.html</a>
|
||||
<hr>
|
||||
<tt>
|
||||
Boost.Utility<br>
|
||||
<br>
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||
<br>
|
||||
</tt>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,164 +1,19 @@
|
||||
<HTML>
|
||||
<Head>
|
||||
<Title>OptionalPointee Concept</Title>
|
||||
</HEAD>
|
||||
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
|
||||
ALINK="#ff0000">
|
||||
<IMG SRC="../../boost.png"
|
||||
ALT="C++ Boost" width="277" height="86">
|
||||
<!--end header-->
|
||||
<BR Clear>
|
||||
<H1>Concept: OptionalPointee</H1>
|
||||
|
||||
<h3>Description</h3>
|
||||
A type is a model of <i>OptionalPointee</i> if it points to (or refers to) a value
|
||||
that may not exist. That is, if it has a <b>pointee</b> which might be <b>valid</b>
|
||||
(existent) or <b>invalid</b> (inexistent); and it is possible to test whether the
|
||||
pointee is valid or not.
|
||||
This model does <u>not</u> imply pointer semantics: i.e., it does not imply shallow copy nor
|
||||
aliasing.
|
||||
<h3>Notation</h3>
|
||||
<Table>
|
||||
<TR>
|
||||
<TD VAlign=top> <tt>T</tt> </TD>
|
||||
<TD VAlign=top> is a type that is a model of OptionalPointee</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top> <tt>t</tt> </TD>
|
||||
<TD VAlign=top> is an object of type <tt>T</tt> or possibly <tt>const T</tt></TD>
|
||||
</tr>
|
||||
</table>
|
||||
<h3>Definitions</h3>
|
||||
<h3>Valid expressions</h3>
|
||||
<Table border>
|
||||
<TR>
|
||||
<TH> Name </TH>
|
||||
<TH> Expression </TH>
|
||||
<TH> Return type </TH>
|
||||
<TH> Semantics </TH>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top>Value Access</TD>
|
||||
<TD VAlign=top> <tt>*t</tt></TD>
|
||||
<TD VAlign=top> <tt>T&</tt></TD>
|
||||
<TD VAlign=top>If the pointee is valid returns a reference to
|
||||
the pointee.<br>
|
||||
If the pointee is invalid the result is <i>undefined</i>.</TD>
|
||||
<TD VAlign=top> </TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top>Value Access</TD>
|
||||
<TD VAlign=top> <tt>t-><i>xyz</i></tt></TD>
|
||||
<TD VAlign=top> <tt>T*</tt></TD>
|
||||
<TD VAlign=top>If the pointee is valid returns a builtin pointer to the pointee.<br>
|
||||
If the pointee is invalid the result is <i>undefined</i> (It might not even return NULL).<br>
|
||||
</TD>
|
||||
<TD VAlign=top> </TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top>Validity Test</TD>
|
||||
<TD VAlign=top> <tt>t</tt><br>
|
||||
<tt>t != 0</tt><br>
|
||||
<tt>!!t</tt>
|
||||
</TD>
|
||||
<TD VAlign=top> bool </TD>
|
||||
<TD VAlign=top>If the pointee is valid returns true.<br>
|
||||
If the pointee is invalid returns false.</TD>
|
||||
<TD VAlign=top></TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top>Invalidity Test</TD>
|
||||
<TD VAlign=top> <tt>t == 0</tt><br>
|
||||
<tt>!t</tt>
|
||||
</TD>
|
||||
<TD VAlign=top> bool </TD>
|
||||
<TD VAlign=top>If the pointee is valid returns false.<br>
|
||||
If the pointee is invalid returns true.</TD>
|
||||
<TD VAlign=top></TD>
|
||||
</TR>
|
||||
</table>
|
||||
|
||||
|
||||
<h3>Models</h3>
|
||||
|
||||
<UL>
|
||||
<LI><tt>pointers, both builtin and smart.</tt>
|
||||
<LI><tt>boost::optional<></tt>
|
||||
</UL>
|
||||
|
||||
<HR>
|
||||
<h3>OptionalPointee and relational operations</h3>
|
||||
<p>This concept does not define any particular semantic for relational operations, therefore,
|
||||
a type which models this concept might have either shallow or deep relational semantics.<br>
|
||||
For instance, pointers, which are models of OptionalPointee, have shallow relational operators:
|
||||
comparisons of pointers do not involve comparisons of pointees.
|
||||
This makes sense for pointers because they have shallow copy semantics.<br>
|
||||
But boost::optional<T>, on the other hand, which is also a model of OptionalPointee, has
|
||||
deep-copy and deep-relational semantics.<br>
|
||||
If generic code is written for this concept, it is important not to use relational
|
||||
operators directly because the semantics might be different depending on the actual type.<br>
|
||||
Still, the concept itsef can be used to define <i>deep</i> relational tests that can
|
||||
be used in generic code with any type which models OptionalPointee:</p>
|
||||
<a name="equal"></a>
|
||||
<p><u>Equivalence relation:</u></p>
|
||||
<pre>template<class OptionalPointee>
|
||||
inline
|
||||
bool equal_pointees ( OptionalPointee const& x, OptionalPointee const& y )
|
||||
{
|
||||
return (!x) != (!y) ? false : ( !x ? true : (*x) == (*y) ) ;
|
||||
}
|
||||
template<class OptionalPointee>
|
||||
struct equal_pointees_t : std::binary_function<OptionalPointee,OptionalPointee,bool>
|
||||
{
|
||||
bool operator() ( OptionalPointee const& x, OptionalPointee const& y ) const
|
||||
{ return equal_pointees(x,y) ; }
|
||||
} ;
|
||||
</pre>
|
||||
<p>The preceding generic function and function object have the following semantics:<br>
|
||||
If both <b>x</b> and <b>y</b> have valid pointees, it compares values via <code>(*x == *y)</code>.<br>
|
||||
If only one has a valid pointee, returns <code>false</code>.<br>
|
||||
If both have invalid pointees, returns <code>true</code>.</p>
|
||||
<a name="less"></a>
|
||||
<p><u>Less-than relation:</u></p>
|
||||
<pre>template<class OptionalPointee>
|
||||
inline
|
||||
bool less_pointees ( OptionalPointee const& x, OptionalPointee const& y )
|
||||
{
|
||||
return !y ? false : ( !x ? true : (*x) < (*y) ) ;
|
||||
}
|
||||
template<class OptionalPointee>
|
||||
struct less_pointees_t : std::binary_function<OptionalPointee,OptionalPointee,bool>
|
||||
{
|
||||
bool operator() ( OptionalPointee const& x, OptionalPointee const& y ) const
|
||||
{ return less_pointees(x,y) ; }
|
||||
} ;
|
||||
</pre>
|
||||
<p>The preceding generic function and function object have the following semantics:<br>
|
||||
If <b>y</b> has an invalid pointee, returns <code>false</code>.<br>
|
||||
Else, if <b>x</b> has an invalid pointee, returns <code>true</code>.<br>
|
||||
Else, ( <b>x</b> and <b>y</b> have valid pointees), compares values via <code>(*x <
|
||||
*y).</code></p>
|
||||
<p><br>
|
||||
All these functions and function
|
||||
objects are is implemented in <a href="../../boost/utility/compare_pointees.hpp">compare_pointees.hpp</a></p>
|
||||
<p>Notice that OptionalPointee does not imply aliasing (and optional<> for instance does not alias);
|
||||
so direct usage of relational operators with the implied aliasing of shallow semantics
|
||||
-as with pointers- should not be used with generic code written for this concept.</p>
|
||||
|
||||
<h3>Acknowledgements</h3>
|
||||
<p>Based on the original concept developed by Augustus Saunders.
|
||||
|
||||
<br>
|
||||
</p>
|
||||
<HR>
|
||||
<TABLE>
|
||||
<TR valign=top>
|
||||
<TD nowrap>Copyright © 2003</TD><TD>
|
||||
<A HREF="mailto:fernando_cacciola@hotmail.com">Fernando Cacciola</A>
|
||||
</TD></TR></TABLE>
|
||||
|
||||
<p>Distributed under the Boost Software License, Version 1.0. See
|
||||
<a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a></p>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Boost.Utility</title>
|
||||
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="./doc/html/index.html">./doc/html/index.html</a>
|
||||
<hr>
|
||||
<tt>
|
||||
Boost.Utility<br>
|
||||
<br>
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||
<br>
|
||||
</tt>
|
||||
</body>
|
||||
</html>
|
||||
|
26
README.md
Normal file
26
README.md
Normal file
@ -0,0 +1,26 @@
|
||||
# 
|
||||
|
||||
Boost.Utility, part of collection of the [Boost C++ Libraries](https://github.com/boostorg), provides a number of smaller components, too small to be called libraries in their own right. See the documentation for the list of components.
|
||||
|
||||
### Directories
|
||||
|
||||
* **doc** - Documentation sources
|
||||
* **include** - Interface headers of Boost.Utility
|
||||
* **test** - Boost.Utility unit tests
|
||||
|
||||
### More information
|
||||
|
||||
* [Documentation](https://boost.org/libs/utility)
|
||||
* [Report bugs](https://github.com/boostorg/utility/issues/new). Be sure to mention Boost version, Boost.Utility component, platform and compiler you're using. A small compilable code sample to reproduce the problem is always good as well.
|
||||
* Submit your patches as pull requests against **develop** branch. Note that by submitting patches you agree to license your modifications under the [Boost Software License, Version 1.0](https://www.boost.org/LICENSE_1_0.txt).
|
||||
|
||||
### Build status
|
||||
|
||||
Branch | GitHub Actions | AppVeyor | Test Matrix | Dependencies |
|
||||
:-------------: | -------------- | -------- | ----------- | ------------ |
|
||||
[`master`](https://github.com/boostorg/utility/tree/master) | [](https://github.com/boostorg/utility/actions?query=branch%3Amaster) | [](https://ci.appveyor.com/project/Lastique/utility/branch/master) | [](http://www.boost.org/development/tests/master/developer/utility.html) | [](https://pdimov.github.io/boostdep-report/master/utility.html)
|
||||
[`develop`](https://github.com/boostorg/utility/tree/develop) | [](https://github.com/boostorg/utility/actions?query=branch%3Adevelop) | [](https://ci.appveyor.com/project/Lastique/utility/branch/develop) | [](http://www.boost.org/development/tests/develop/developer/utility.html) | [](https://pdimov.github.io/boostdep-report/develop/utility.html)
|
||||
|
||||
### License
|
||||
|
||||
Distributed under the [Boost Software License, Version 1.0](https://www.boost.org/LICENSE_1_0.txt).
|
@ -1,76 +0,0 @@
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(disable: 4786) // identifier truncated in debug info
|
||||
#pragma warning(disable: 4710) // function not inlined
|
||||
#pragma warning(disable: 4711) // function selected for automatic inline expansion
|
||||
#pragma warning(disable: 4514) // unreferenced inline removed
|
||||
#endif
|
||||
|
||||
// addressof_fn_test.cpp: addressof( f )
|
||||
//
|
||||
// Copyright (c) 2008, 2009 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/utility/addressof.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
|
||||
void f0()
|
||||
{
|
||||
}
|
||||
|
||||
void f1(int)
|
||||
{
|
||||
}
|
||||
|
||||
void f2(int, int)
|
||||
{
|
||||
}
|
||||
|
||||
void f3(int, int, int)
|
||||
{
|
||||
}
|
||||
|
||||
void f4(int, int, int, int)
|
||||
{
|
||||
}
|
||||
|
||||
void f5(int, int, int, int, int)
|
||||
{
|
||||
}
|
||||
|
||||
void f6(int, int, int, int, int, int)
|
||||
{
|
||||
}
|
||||
|
||||
void f7(int, int, int, int, int, int, int)
|
||||
{
|
||||
}
|
||||
|
||||
void f8(int, int, int, int, int, int, int, int)
|
||||
{
|
||||
}
|
||||
|
||||
void f9(int, int, int, int, int, int, int, int, int)
|
||||
{
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
BOOST_TEST( boost::addressof( f0 ) == &f0 );
|
||||
BOOST_TEST( boost::addressof( f1 ) == &f1 );
|
||||
BOOST_TEST( boost::addressof( f2 ) == &f2 );
|
||||
BOOST_TEST( boost::addressof( f3 ) == &f3 );
|
||||
BOOST_TEST( boost::addressof( f4 ) == &f4 );
|
||||
BOOST_TEST( boost::addressof( f5 ) == &f5 );
|
||||
BOOST_TEST( boost::addressof( f6 ) == &f6 );
|
||||
BOOST_TEST( boost::addressof( f7 ) == &f7 );
|
||||
BOOST_TEST( boost::addressof( f8 ) == &f8 );
|
||||
BOOST_TEST( boost::addressof( f9 ) == &f9 );
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
@ -1,94 +0,0 @@
|
||||
// Copyright (C) 2002 Brad King (brad.king@kitware.com)
|
||||
// Douglas Gregor (gregod@cs.rpi.edu)
|
||||
//
|
||||
// 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 http://www.boost.org
|
||||
|
||||
|
||||
#include <boost/utility/addressof.hpp>
|
||||
|
||||
#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)
|
||||
#pragma warning(push, 3)
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
template<class T> void scalar_test( T * = 0 )
|
||||
{
|
||||
T* px = new T();
|
||||
|
||||
T& x = *px;
|
||||
BOOST_TEST( boost::addressof(x) == px );
|
||||
|
||||
const T& cx = *px;
|
||||
const T* pcx = boost::addressof(cx);
|
||||
BOOST_TEST( pcx == px );
|
||||
|
||||
volatile T& vx = *px;
|
||||
volatile T* pvx = boost::addressof(vx);
|
||||
BOOST_TEST( pvx == px );
|
||||
|
||||
const volatile T& cvx = *px;
|
||||
const volatile T* pcvx = boost::addressof(cvx);
|
||||
BOOST_TEST( pcvx == px );
|
||||
|
||||
delete px;
|
||||
}
|
||||
|
||||
template<class T> void array_test( T * = 0 )
|
||||
{
|
||||
T nrg[3] = {1,2,3};
|
||||
T (*pnrg)[3] = &nrg;
|
||||
BOOST_TEST( boost::addressof(nrg) == pnrg );
|
||||
|
||||
T const cnrg[3] = {1,2,3};
|
||||
T const (*pcnrg)[3] = &cnrg;
|
||||
BOOST_TEST( boost::addressof(cnrg) == pcnrg );
|
||||
}
|
||||
|
||||
struct addressable
|
||||
{
|
||||
addressable( int = 0 )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct useless_type {};
|
||||
|
||||
class nonaddressable {
|
||||
public:
|
||||
|
||||
nonaddressable( int = 0 )
|
||||
{
|
||||
}
|
||||
|
||||
void dummy(); // Silence GCC warning: all member of class are private
|
||||
|
||||
private:
|
||||
|
||||
useless_type operator&() const;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
scalar_test<char>();
|
||||
scalar_test<int>();
|
||||
scalar_test<addressable>();
|
||||
scalar_test<nonaddressable>();
|
||||
|
||||
array_test<char>();
|
||||
array_test<int>();
|
||||
array_test<addressable>();
|
||||
array_test<nonaddressable>();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
// Copyright (C) 2002 Brad King (brad.king@kitware.com)
|
||||
// Douglas Gregor (gregod@cs.rpi.edu)
|
||||
//
|
||||
// Copyright 2009 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)
|
||||
|
||||
// For more information, see http://www.boost.org
|
||||
|
||||
|
||||
#include <boost/utility/addressof.hpp>
|
||||
|
||||
#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)
|
||||
#pragma warning(push, 3)
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
template<class T> void scalar_test( T * = 0 )
|
||||
{
|
||||
T* px = new T();
|
||||
|
||||
T& x = *px;
|
||||
BOOST_TEST( boost::addressof(x) == px );
|
||||
|
||||
const T& cx = *px;
|
||||
const T* pcx = boost::addressof(cx);
|
||||
BOOST_TEST( pcx == px );
|
||||
|
||||
volatile T& vx = *px;
|
||||
volatile T* pvx = boost::addressof(vx);
|
||||
BOOST_TEST( pvx == px );
|
||||
|
||||
const volatile T& cvx = *px;
|
||||
const volatile T* pcvx = boost::addressof(cvx);
|
||||
BOOST_TEST( pcvx == px );
|
||||
|
||||
delete px;
|
||||
}
|
||||
|
||||
template<class T> void array_test( T * = 0 )
|
||||
{
|
||||
T nrg[3] = {1,2,3};
|
||||
T (*pnrg)[3] = &nrg;
|
||||
BOOST_TEST( boost::addressof(nrg) == pnrg );
|
||||
|
||||
T const cnrg[3] = {1,2,3};
|
||||
T const (*pcnrg)[3] = &cnrg;
|
||||
BOOST_TEST( boost::addressof(cnrg) == pcnrg );
|
||||
}
|
||||
|
||||
class convertible {
|
||||
public:
|
||||
|
||||
convertible( int = 0 )
|
||||
{
|
||||
}
|
||||
|
||||
template<class U> operator U () const
|
||||
{
|
||||
return U();
|
||||
}
|
||||
};
|
||||
|
||||
class convertible2 {
|
||||
public:
|
||||
|
||||
convertible2( int = 0 )
|
||||
{
|
||||
}
|
||||
|
||||
operator convertible2* () const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
scalar_test<convertible>();
|
||||
scalar_test<convertible2>();
|
||||
|
||||
array_test<convertible>();
|
||||
array_test<convertible2>();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
104
appveyor.yml
Normal file
104
appveyor.yml
Normal file
@ -0,0 +1,104 @@
|
||||
# Copyright 2016-2019 Peter Dimov
|
||||
# Copyright 2019, 2022 Andrey Semashev
|
||||
# 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)
|
||||
|
||||
version: 1.0.{build}-{branch}
|
||||
|
||||
shallow_clone: true
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- develop
|
||||
- /feature\/.*/
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- TOOLSET: msvc-9.0,msvc-10.0,msvc-11.0
|
||||
ADDRMD: 32
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
- TOOLSET: msvc-12.0,msvc-14.0
|
||||
ADDRMD: 32,64
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
- TOOLSET: msvc-14.1
|
||||
CXXSTD: 14,17,latest
|
||||
ADDRMD: 32,64
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
- TOOLSET: msvc-14.2
|
||||
ADDRMD: 32,64
|
||||
CXXSTD: 14,17,20,latest
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
- TOOLSET: msvc-14.3
|
||||
ADDRMD: 32,64
|
||||
CXXSTD: 14,17,20,latest
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
|
||||
- TOOLSET: clang-win
|
||||
ADDRMD: 32
|
||||
CXXSTD: 14,17,latest
|
||||
ENV_SCRIPT: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars32.bat
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
- TOOLSET: clang-win
|
||||
ADDRMD: 64
|
||||
CXXSTD: 14,17,latest
|
||||
ENV_SCRIPT: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
- TOOLSET: gcc
|
||||
CXXSTD: 03,11,14,1z
|
||||
ADDPATH: C:\cygwin\bin;
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
- TOOLSET: gcc
|
||||
CXXSTD: 03,11,14,1z
|
||||
ADDPATH: C:\cygwin64\bin;
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
- TOOLSET: gcc
|
||||
CXXSTD: 03,11,14,1z
|
||||
ADDPATH: C:\mingw\bin;
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
- TOOLSET: gcc
|
||||
CXXSTD: 03,11,14,1z
|
||||
ADDPATH: C:\mingw-w64\x86_64-6.3.0-posix-seh-rt_v5-rev1\mingw64\bin;
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
- TOOLSET: gcc
|
||||
CXXSTD: 03,11,14,17
|
||||
ADDPATH: C:\mingw-w64\x86_64-7.3.0-posix-seh-rt_v5-rev0\mingw64\bin;
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
- TOOLSET: gcc
|
||||
CXXSTD: 03,11,14,17,2a
|
||||
ADDPATH: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin;
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
|
||||
install:
|
||||
- set GIT_FETCH_JOBS=8
|
||||
- set BOOST_BRANCH=develop
|
||||
- if "%APPVEYOR_REPO_BRANCH%" == "master" set BOOST_BRANCH=master
|
||||
- cd ..
|
||||
- git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root
|
||||
- cd boost-root
|
||||
- git submodule init tools/build
|
||||
- git submodule init tools/boost_install
|
||||
- git submodule init libs/headers
|
||||
- git submodule init libs/assert
|
||||
- git submodule init libs/config
|
||||
- git submodule init libs/core
|
||||
- git submodule init libs/io
|
||||
- git submodule init libs/preprocessor
|
||||
- git submodule init libs/static_assert
|
||||
- git submodule init libs/throw_exception
|
||||
- git submodule init libs/type_traits
|
||||
- git submodule init libs/container_hash
|
||||
- git submodule init libs/integer
|
||||
- git submodule init libs/detail
|
||||
- git submodule update --jobs %GIT_FETCH_JOBS%
|
||||
- xcopy /s /e /q %APPVEYOR_BUILD_FOLDER% libs\utility\
|
||||
- cmd /c bootstrap
|
||||
- b2 -d0 headers
|
||||
|
||||
build: off
|
||||
|
||||
test_script:
|
||||
- PATH=%ADDPATH%%PATH%
|
||||
- if not "%ENV_SCRIPT%" == "" call "%ENV_SCRIPT%"
|
||||
- if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD%
|
||||
- if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD%
|
||||
- b2 -j %NUMBER_OF_PROCESSORS% libs/utility/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release
|
115
assert.html
115
assert.html
@ -1,115 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Boost: assert.hpp documentation</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
</head>
|
||||
<body bgcolor="white" style="MARGIN-LEFT: 5%; MARGIN-RIGHT: 5%">
|
||||
<table border="0" width="100%">
|
||||
<tr>
|
||||
<td width="277"><A href="../../index.htm"> <img src="../../boost.png" alt="boost.png (6897 bytes)" width="277" height="86" border="0"></A>
|
||||
</td>
|
||||
<td align="center">
|
||||
<h1>assert.hpp</h1>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" height="64"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>
|
||||
<a href="#BOOST_ASSERT">BOOST_ASSERT</a><br>
|
||||
<a href="#BOOST_ASSERT_MSG">BOOST_ASSERT_MSG</a><br>
|
||||
<a href="#BOOST_VERIFY">BOOST_VERIFY</a></p>
|
||||
|
||||
<h2><a name="BOOST_ASSERT">BOOST_ASSERT</a></h2>
|
||||
<p>
|
||||
The header <STRONG><boost/assert.hpp></STRONG> defines the macro <b>BOOST_ASSERT</b>,
|
||||
which is similar to the standard <STRONG>assert</STRONG> macro defined in <STRONG><cassert></STRONG>.
|
||||
The macro is intended to be used in both Boost libraries and user
|
||||
code.
|
||||
</p>
|
||||
<P>By default, <tt>BOOST_ASSERT(expr)</tt> is equivalent to <tt>assert(expr)</tt>.</P>
|
||||
<P>If the macro <STRONG>BOOST_DISABLE_ASSERTS</STRONG> is defined when <STRONG><boost/assert.hpp></STRONG>
|
||||
is included, <tt>BOOST_ASSERT(expr)</tt> is defined as <tt>((void)0)</tt>. This
|
||||
allows users to selectively disable <STRONG>BOOST_ASSERT</STRONG> without
|
||||
affecting the definition of the standard <STRONG>assert</STRONG>.</P>
|
||||
<P>If the macro <STRONG>BOOST_ENABLE_ASSERT_HANDLER</STRONG> is defined when <STRONG><boost/assert.hpp></STRONG>
|
||||
is included, <tt>BOOST_ASSERT(expr)</tt> evaluates <b>expr</b> and, if the
|
||||
result is false, evaluates the expression</P>
|
||||
<blockquote>
|
||||
<P><tt>::boost::assertion_failed(#expr, <a href="current_function.html">BOOST_CURRENT_FUNCTION</a>,
|
||||
__FILE__, __LINE__)</tt></P>
|
||||
</blockquote>
|
||||
<P><STRONG>assertion_failed</STRONG> is declared in <STRONG><boost/assert.hpp></STRONG>
|
||||
as</P>
|
||||
<blockquote>
|
||||
<pre>namespace boost
|
||||
{
|
||||
void assertion_failed(char const * expr, char const * function, char const * file, long line);
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>but it is never defined. The user is expected to supply an appropriate
|
||||
definition.</p>
|
||||
<P>As is the case with <STRONG><cassert></STRONG>, <STRONG><boost/assert.hpp></STRONG>
|
||||
can be included multiple times in a single translation unit. <STRONG>BOOST_ASSERT</STRONG>
|
||||
will be redefined each time as specified above.</P>
|
||||
|
||||
<h2><a name="BOOST_ASSERT_MSG">BOOST_ASSERT_MSG</a></h2>
|
||||
<p>
|
||||
The header <STRONG><boost/assert.hpp></STRONG> defines the macro <b>BOOST_ASSERT_MSG</b>,
|
||||
which is similar to the standard <STRONG>assert</STRONG> macro defined in <STRONG><cassert></STRONG>,
|
||||
but with an additional macro parameter supplying an error message. The macro is intended to be used in both Boost libraries
|
||||
and user code.
|
||||
</p>
|
||||
<P> <tt>BOOST_ASSERT_MSG(expr, msg)</tt> is equivalent to <code>
|
||||
((void)0)</code> if <b>BOOST_DISABLE_ASSERTS</b> or <b>NDEBUG</b> are
|
||||
defined or <code>expr</code> evaluates to <code>true</code>. If those
|
||||
macros and <STRONG>BOOST_ENABLE_ASSERT_HANDLER</STRONG> are not
|
||||
defined, and <code>expr</code> evaluates to <code>false</code>, an error
|
||||
message that includes <tt>#expr</tt>, <tt>msg</tt>, <tt> <a href="current_function.html">BOOST_CURRENT_FUNCTION</a></tt>, <tt>
|
||||
__FILE__</tt>, and <tt>__LINE__</tt> is sent to output stream <b>
|
||||
BOOST_ASSERT_MSG_OSTREAM</b>
|
||||
and <code>std::abort()</code> is called.</P>
|
||||
<P> <b>BOOST_ASSERT_MSG_OSTREAM</b> defines the output stream. It defaults to <code>std::cerr</code>.
|
||||
Integrated development environments (IDE's) like Microsoft Visual Studio
|
||||
may produce easier to understand output if messages go to a different
|
||||
stream, such as <code>std::cout</code>. Users may define <b>BOOST_ASSERT_MSG_OSTREAM</b> before including <STRONG><boost/assert.hpp></STRONG>
|
||||
to specify a different output stream. </P>
|
||||
<P>If the macro <STRONG>BOOST_ENABLE_ASSERT_HANDLER</STRONG> is defined when <STRONG><boost/assert.hpp></STRONG>
|
||||
is included, instead of sending a error message to an output
|
||||
stream, this expression is evaluated</P>
|
||||
<blockquote>
|
||||
<P><tt>::boost::assertion_failed_msg(#expr, msg, <a href="current_function.html">BOOST_CURRENT_FUNCTION</a>,
|
||||
__FILE__, __LINE__)</tt></P>
|
||||
</blockquote>
|
||||
<P><STRONG>assertion_failed_msg</STRONG> is declared in <STRONG><boost/assert.hpp></STRONG>
|
||||
as</P>
|
||||
<blockquote>
|
||||
<pre>namespace boost
|
||||
{
|
||||
void assertion_failed_msg(char const * expr, char const * msg, char const * function, char const * file, long line);
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>but it is never defined. The user is expected to supply an appropriate
|
||||
definition.</p>
|
||||
<P>As is the case with <STRONG><cassert></STRONG>, <STRONG><boost/assert.hpp></STRONG>
|
||||
can be included multiple times in a single translation unit. <STRONG>BOOST_ASSERT_MSG</STRONG>
|
||||
will be redefined each time as specified above.</P>
|
||||
|
||||
<h2><a name="BOOST_VERIFY">BOOST_VERIFY</a></h2>
|
||||
<p><STRONG><boost/assert.hpp></STRONG> also defines the macro <STRONG>BOOST_VERIFY</STRONG>.
|
||||
It has exactly the same behavior as <STRONG>BOOST_ASSERT</STRONG>, except that
|
||||
the expression that is passed to <STRONG>BOOST_VERIFY</STRONG> is always
|
||||
evaluated. This is useful when the asserted expression has desirable side
|
||||
effects; it can also help suppress warnings about unused variables when the
|
||||
only use of the variable is inside an assertion.</p>
|
||||
<p><br>
|
||||
<small>Copyright <20> 2002, 2007 by Peter Dimov. Copyright <20> 2011
|
||||
by Beman Dawes. Distributed under the Boost Software
|
||||
License, Version 1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A>
|
||||
or copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
|
||||
</body>
|
||||
</html>
|
153
assert_test.cpp
153
assert_test.cpp
@ -1,153 +0,0 @@
|
||||
//
|
||||
// assert_test.cpp - a test for boost/assert.hpp
|
||||
//
|
||||
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
|
||||
// Copyright (2) Beman Dawes 2011
|
||||
//
|
||||
// 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/detail/lightweight_test.hpp>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
void test_default()
|
||||
{
|
||||
int x = 1;
|
||||
|
||||
BOOST_ASSERT(1);
|
||||
BOOST_ASSERT(x);
|
||||
BOOST_ASSERT(x == 1);
|
||||
BOOST_ASSERT(&x);
|
||||
|
||||
BOOST_ASSERT_MSG(1, "msg");
|
||||
BOOST_ASSERT_MSG(x, "msg");
|
||||
BOOST_ASSERT_MSG(x == 1, "msg");
|
||||
BOOST_ASSERT_MSG(&x, "msg");
|
||||
}
|
||||
|
||||
#define BOOST_DISABLE_ASSERTS
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
void test_disabled()
|
||||
{
|
||||
int x = 1;
|
||||
|
||||
BOOST_ASSERT(1);
|
||||
BOOST_ASSERT(x);
|
||||
BOOST_ASSERT(x == 1);
|
||||
BOOST_ASSERT(&x);
|
||||
|
||||
BOOST_ASSERT_MSG(1, "msg");
|
||||
BOOST_ASSERT_MSG(x, "msg");
|
||||
BOOST_ASSERT_MSG(x == 1, "msg");
|
||||
BOOST_ASSERT_MSG(&x, "msg");
|
||||
|
||||
BOOST_ASSERT(0);
|
||||
BOOST_ASSERT(!x);
|
||||
BOOST_ASSERT(x == 0);
|
||||
|
||||
BOOST_ASSERT_MSG(0, "msg");
|
||||
BOOST_ASSERT_MSG(!x, "msg");
|
||||
BOOST_ASSERT_MSG(x == 0, "msg");
|
||||
|
||||
void * p = 0;
|
||||
|
||||
BOOST_ASSERT(p);
|
||||
BOOST_ASSERT_MSG(p, "msg");
|
||||
|
||||
// supress warnings
|
||||
p = &x;
|
||||
p = &p;
|
||||
}
|
||||
|
||||
#undef BOOST_DISABLE_ASSERTS
|
||||
|
||||
#define BOOST_ENABLE_ASSERT_HANDLER
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <cstdio>
|
||||
|
||||
int handler_invoked = 0;
|
||||
int msg_handler_invoked = 0;
|
||||
|
||||
void boost::assertion_failed(char const * expr, char const * function, char const * file, long line)
|
||||
{
|
||||
#if !defined(BOOST_NO_STDC_NAMESPACE)
|
||||
using std::printf;
|
||||
#endif
|
||||
|
||||
printf("Expression: %s\nFunction: %s\nFile: %s\nLine: %ld\n\n", expr, function, file, line);
|
||||
++handler_invoked;
|
||||
}
|
||||
|
||||
void boost::assertion_failed_msg(char const * expr, char const * msg, char const * function,
|
||||
char const * file, long line)
|
||||
{
|
||||
#if !defined(BOOST_NO_STDC_NAMESPACE)
|
||||
using std::printf;
|
||||
#endif
|
||||
|
||||
printf("Expression: %s Message: %s\nFunction: %s\nFile: %s\nLine: %ld\n\n",
|
||||
expr, msg, function, file, line);
|
||||
++msg_handler_invoked;
|
||||
}
|
||||
|
||||
struct X
|
||||
{
|
||||
static void f()
|
||||
{
|
||||
BOOST_ASSERT(0);
|
||||
BOOST_ASSERT_MSG(0, "msg f()");
|
||||
}
|
||||
};
|
||||
|
||||
void test_handler()
|
||||
{
|
||||
int x = 1;
|
||||
|
||||
BOOST_ASSERT(1);
|
||||
BOOST_ASSERT(x);
|
||||
BOOST_ASSERT(x == 1);
|
||||
BOOST_ASSERT(&x);
|
||||
|
||||
BOOST_ASSERT_MSG(1, "msg2");
|
||||
BOOST_ASSERT_MSG(x, "msg3");
|
||||
BOOST_ASSERT_MSG(x == 1, "msg4");
|
||||
BOOST_ASSERT_MSG(&x, "msg5");
|
||||
|
||||
BOOST_ASSERT(0);
|
||||
BOOST_ASSERT(!x);
|
||||
BOOST_ASSERT(x == 0);
|
||||
|
||||
BOOST_ASSERT_MSG(0,"msg 0");
|
||||
BOOST_ASSERT_MSG(!x, "msg !x");
|
||||
BOOST_ASSERT_MSG(x == 0, "msg x == 0");
|
||||
|
||||
void * p = 0;
|
||||
|
||||
BOOST_ASSERT(p);
|
||||
BOOST_ASSERT_MSG(p, "msg p");
|
||||
|
||||
X::f();
|
||||
|
||||
BOOST_ASSERT(handler_invoked == 5);
|
||||
BOOST_TEST(handler_invoked == 5);
|
||||
|
||||
BOOST_ASSERT_MSG(msg_handler_invoked == 5, "msg_handler_invoked count is wrong");
|
||||
BOOST_TEST(msg_handler_invoked == 5);
|
||||
}
|
||||
|
||||
#undef BOOST_ENABLE_ASSERT_HANDLER
|
||||
#undef BOOST_ENABLE_ASSERT_MSG_HANDLER
|
||||
|
||||
int main()
|
||||
{
|
||||
test_default();
|
||||
test_disabled();
|
||||
test_handler();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
@ -1,398 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Boost: Base-from-Member Idiom Documentation</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="white" link="blue" text="black" vlink="purple" alink="red">
|
||||
<h1><img src="../../boost.png" alt="C++ Boost" align="middle"
|
||||
width="277" height="86">Base-from-Member Idiom</h1>
|
||||
|
||||
<p>The class template <code>boost::base_from_member</code> provides
|
||||
a workaround for a class that needs to initialize a base class with a
|
||||
member. The class template is in <cite><a
|
||||
href="../../boost/utility/base_from_member.hpp">boost/utility/base_from_member.hpp</a></cite>
|
||||
which is included in <i><a href="../../boost/utility.hpp">boost/utility.hpp</a></i>.</p>
|
||||
|
||||
<p>There is test/example code in <cite><a
|
||||
href="base_from_member_test.cpp">base_from_member_test.cpp</a></cite>.</p>
|
||||
|
||||
<h2><a name="contents">Contents</a></h2>
|
||||
|
||||
<ul>
|
||||
<li><a href="#contents">Contents</a></li>
|
||||
<li><a href="#rationale">Rationale</a></li>
|
||||
<li><a href="#synopsis">Synopsis</a></li>
|
||||
<li><a href="#usage">Usage</a></li>
|
||||
<li><a href="#example">Example</a></li>
|
||||
<li><a href="#credits">Credits</a>
|
||||
<ul>
|
||||
<li><a href="#contributors">Contributors</a></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
|
||||
<h2><a name="rationale">Rationale</a></h2>
|
||||
|
||||
<p>When developing a class, sometimes a base class needs to be
|
||||
initialized with a member of the current class. As a naïve
|
||||
example:</p>
|
||||
|
||||
<blockquote><pre>
|
||||
#include <streambuf> <i>// for std::streambuf</i>
|
||||
#include <ostream> <i>// for std::ostream</i>
|
||||
|
||||
class fdoutbuf
|
||||
: public std::streambuf
|
||||
{
|
||||
public:
|
||||
explicit fdoutbuf( int fd );
|
||||
//...
|
||||
};
|
||||
|
||||
class fdostream
|
||||
: public std::ostream
|
||||
{
|
||||
protected:
|
||||
fdoutbuf buf;
|
||||
public:
|
||||
explicit fdostream( int fd )
|
||||
: buf( fd ), std::ostream( &buf )
|
||||
{}
|
||||
//...
|
||||
};
|
||||
</pre></blockquote>
|
||||
|
||||
<p>This is undefined because C++'s initialization order mandates that
|
||||
the base class is initialized before the member it uses. <a
|
||||
href="http://www.moocat.org">R. Samuel Klatchko</a> developed a way
|
||||
around this by using the initialization order in his favor. Base
|
||||
classes are intialized in order of declaration, so moving the desired
|
||||
member to another base class, that is initialized before the desired
|
||||
base class, can ensure proper initialization.</p>
|
||||
|
||||
<p>A custom base class can be made for this idiom:</p>
|
||||
|
||||
<blockquote><pre>
|
||||
#include <streambuf> <i>// for std::streambuf</i>
|
||||
#include <ostream> <i>// for std::ostream</i>
|
||||
|
||||
class fdoutbuf
|
||||
: public std::streambuf
|
||||
{
|
||||
public:
|
||||
explicit fdoutbuf( int fd );
|
||||
//...
|
||||
};
|
||||
|
||||
struct fdostream_pbase
|
||||
{
|
||||
fdoutbuf sbuffer;
|
||||
|
||||
explicit fdostream_pbase( int fd )
|
||||
: sbuffer( fd )
|
||||
{}
|
||||
};
|
||||
|
||||
class fdostream
|
||||
: private fdostream_pbase
|
||||
, public std::ostream
|
||||
{
|
||||
typedef fdostream_pbase pbase_type;
|
||||
typedef std::ostream base_type;
|
||||
|
||||
public:
|
||||
explicit fdostream( int fd )
|
||||
: pbase_type( fd ), base_type( &sbuffer )
|
||||
{}
|
||||
//...
|
||||
};
|
||||
</pre></blockquote>
|
||||
|
||||
<p>Other projects can use similar custom base classes. The technique
|
||||
is basic enough to make a template, with a sample template class in
|
||||
this library. The main template parameter is the type of the enclosed
|
||||
member. The template class has several (explicit) constructor member
|
||||
templates, which implicitly type the constructor arguments and pass them
|
||||
to the member. The template class uses implicit copy construction and
|
||||
assignment, cancelling them if the enclosed member is non-copyable.</p>
|
||||
|
||||
<p>Manually coding a base class may be better if the construction
|
||||
and/or copying needs are too complex for the supplied template class,
|
||||
or if the compiler is not advanced enough to use it.</p>
|
||||
|
||||
<p>Since base classes are unnamed, a class cannot have multiple (direct)
|
||||
base classes of the same type. The supplied template class has an
|
||||
extra template parameter, an integer, that exists solely to provide type
|
||||
differentiation. This parameter has a default value so a single use of a
|
||||
particular member type does not need to concern itself with the integer.</p>
|
||||
|
||||
<h2><a name="synopsis">Synopsis</a></h2>
|
||||
|
||||
<blockquote><pre>
|
||||
#include <type_traits> <i>// exposition only</i>
|
||||
|
||||
#ifndef BOOST_BASE_FROM_MEMBER_MAX_ARITY
|
||||
#define BOOST_BASE_FROM_MEMBER_MAX_ARITY 10
|
||||
#endif
|
||||
|
||||
template < typename MemberType, int UniqueID = 0 >
|
||||
class boost::base_from_member
|
||||
{
|
||||
protected:
|
||||
MemberType member;
|
||||
|
||||
#if <i>C++2011 is in use</i>
|
||||
template< typename ...T >
|
||||
explicit constexpr base_from_member( T&& ...x )
|
||||
noexcept( std::is_nothrow_constructible<MemberType, T...>::value );
|
||||
#else
|
||||
base_from_member();
|
||||
|
||||
template< typename T1 >
|
||||
explicit base_from_member( T1 x1 );
|
||||
|
||||
template< typename T1, typename T2 >
|
||||
base_from_member( T1 x1, T2 x2 );
|
||||
|
||||
//...
|
||||
|
||||
template< typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6, typename T7, typename T8, typename T9,
|
||||
typename T10 >
|
||||
base_from_member( T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, T6 x6, T7 x7,
|
||||
T8 x8, T9 x9, T10 x10 );
|
||||
#endif
|
||||
};
|
||||
</pre></blockquote>
|
||||
|
||||
<p>The class template has a first template parameter
|
||||
<var>MemberType</var> representing the type of the based-member.
|
||||
It has a last template parameter <var>UniqueID</var>, that is an
|
||||
<code>int</code>, to differentiate between multiple base classes that use
|
||||
the same based-member type. The last template parameter has a default
|
||||
value of zero if it is omitted. The class template has a protected
|
||||
data member called <var>member</var> that the derived class can use
|
||||
for later base classes (or itself).</p>
|
||||
|
||||
<p>If the appropriate features of C++2011 are present, there will be a single
|
||||
constructor template. It implements "perfect forwarding" to the best
|
||||
constructor call of <code>member</code> (if any). The constructor template is
|
||||
marked both <code>constexpr</code> and <code>explicit</code>. The former will
|
||||
be ignored if the corresponding inner constructor call (of <code>member</code>)
|
||||
does not have the marker. The latter binds the other way; always taking
|
||||
effect, even when the inner constructor call does not have the marker. The
|
||||
constructor template propagates the <code>noexcept</code> status of the inner
|
||||
constructor call. (The constructor template has a trailing parameter with a
|
||||
default value that disables the template when its signature is too close to the
|
||||
signatures of the automatically-defined non-template copy- and/or
|
||||
move-constructors of <code>base_from_member</code>.)</p>
|
||||
|
||||
<p>On earlier-standard compilers, there is a default constructor and several
|
||||
constructor member templates. These constructor templates can take as many
|
||||
arguments (currently up to ten) as possible and pass them to a constructor of
|
||||
the data member.</p>
|
||||
|
||||
<p>Since C++ does not allow any way to explicitly state
|
||||
the template parameters of a templated constructor, make sure that
|
||||
the arguments are already close as possible to the actual type used in
|
||||
the data member's desired constructor. Explicit conversions may be
|
||||
necessary.</p>
|
||||
|
||||
<p>The <var>BOOST_BASE_FROM_MEMBER_MAX_ARITY</var> macro constant specifies
|
||||
the maximum argument length for the constructor templates. The constant
|
||||
may be overridden if more (or less) argument configurations are needed. The
|
||||
constant may be read for code that is expandable like the class template and
|
||||
needs to maintain the same maximum size. (Example code would be a class that
|
||||
uses this class template as a base class for a member with a flexible set of
|
||||
constructors.) This constant is ignored when C++2011 features are present.</p>
|
||||
|
||||
<h2><a name="usage">Usage</a></h2>
|
||||
|
||||
<p>With the starting example, the <code>fdoutbuf</code> sub-object needs
|
||||
to be encapsulated in a base class that is inheirited before
|
||||
<code>std::ostream</code>.</p>
|
||||
|
||||
<blockquote><pre>
|
||||
#include <boost/utility/base_from_member.hpp>
|
||||
|
||||
#include <streambuf> <i>// for std::streambuf</i>
|
||||
#include <ostream> <i>// for std::ostream</i>
|
||||
|
||||
class fdoutbuf
|
||||
: public std::streambuf
|
||||
{
|
||||
public:
|
||||
explicit fdoutbuf( int fd );
|
||||
//...
|
||||
};
|
||||
|
||||
class fdostream
|
||||
: private boost::base_from_member<fdoutbuf>
|
||||
, public std::ostream
|
||||
{
|
||||
// Helper typedef's
|
||||
typedef boost::base_from_member<fdoutbuf> pbase_type;
|
||||
typedef std::ostream base_type;
|
||||
|
||||
public:
|
||||
explicit fdostream( int fd )
|
||||
: pbase_type( fd ), base_type( &member )
|
||||
{}
|
||||
//...
|
||||
};
|
||||
</pre></blockquote>
|
||||
|
||||
<p>The base-from-member idiom is an implementation detail, so it
|
||||
should not be visible to the clients (or any derived classes) of
|
||||
<code>fdostream</code>. Due to the initialization order, the
|
||||
<code>fdoutbuf</code> sub-object will get initialized before the
|
||||
<code>std::ostream</code> sub-object does, making the former
|
||||
sub-object safe to use in the latter sub-object's construction. Since the
|
||||
<code>fdoutbuf</code> sub-object of the final type is the only sub-object
|
||||
with the name "member," that name can be used
|
||||
unqualified within the final class.</p>
|
||||
|
||||
<h2><a name="example">Example</a></h2>
|
||||
|
||||
<p>The base-from-member class templates should commonly involve
|
||||
only one base-from-member sub-object, usually for attaching a
|
||||
stream-buffer to an I/O stream. The next example demonstrates how
|
||||
to use multiple base-from-member sub-objects and the resulting
|
||||
qualification issues.</p>
|
||||
|
||||
<blockquote><pre>
|
||||
#include <boost/utility/base_from_member.hpp>
|
||||
|
||||
#include <cstddef> <i>// for NULL</i>
|
||||
|
||||
struct an_int
|
||||
{
|
||||
int y;
|
||||
|
||||
an_int( float yf );
|
||||
};
|
||||
|
||||
class switcher
|
||||
{
|
||||
public:
|
||||
switcher();
|
||||
switcher( double, int * );
|
||||
//...
|
||||
};
|
||||
|
||||
class flow_regulator
|
||||
{
|
||||
public:
|
||||
flow_regulator( switcher &, switcher & );
|
||||
//...
|
||||
};
|
||||
|
||||
template < unsigned Size >
|
||||
class fan
|
||||
{
|
||||
public:
|
||||
explicit fan( switcher );
|
||||
//...
|
||||
};
|
||||
|
||||
class system
|
||||
: private boost::base_from_member<an_int>
|
||||
, private boost::base_from_member<switcher>
|
||||
, private boost::base_from_member<switcher, 1>
|
||||
, private boost::base_from_member<switcher, 2>
|
||||
, protected flow_regulator
|
||||
, public fan<6>
|
||||
{
|
||||
// Helper typedef's
|
||||
typedef boost::base_from_member<an_int> pbase0_type;
|
||||
typedef boost::base_from_member<switcher> pbase1_type;
|
||||
typedef boost::base_from_member<switcher, 1> pbase2_type;
|
||||
typedef boost::base_from_member<switcher, 2> pbase3_type;
|
||||
|
||||
typedef flow_regulator base1_type;
|
||||
typedef fan<6> base2_type;
|
||||
|
||||
public:
|
||||
system( double x );
|
||||
//...
|
||||
};
|
||||
|
||||
system::system( double x )
|
||||
: pbase0_type( 0.2 )
|
||||
, pbase1_type()
|
||||
, pbase2_type( -16, &this->pbase0_type::member )
|
||||
, pbase3_type( x, static_cast<int *>(NULL) )
|
||||
, base1_type( pbase3_type::member, pbase1_type::member )
|
||||
, base2_type( pbase2_type::member )
|
||||
{
|
||||
//...
|
||||
}
|
||||
</pre></blockquote>
|
||||
|
||||
<p>The final class has multiple sub-objects with the name
|
||||
"member," so any use of that name needs qualification by
|
||||
a name of the appropriate base type. (Using <code>typedef</code>s
|
||||
ease mentioning the base types.) However, the fix introduces a new
|
||||
problem when a pointer is needed. Using the address operator with
|
||||
a sub-object qualified with its class's name results in a pointer-to-member
|
||||
(here, having a type of <code>an_int boost::base_from_member<an_int,
|
||||
0> :: *</code>) instead of a pointer to the member (having a type of
|
||||
<code>an_int *</code>). The new problem is fixed by qualifying the
|
||||
sub-object with "<code>this-></code>," and is needed just
|
||||
for pointers, and not for references or values.</p>
|
||||
|
||||
<p>There are some argument conversions in the initialization. The
|
||||
constructor argument for <code>pbase0_type</code> is converted from
|
||||
<code>double</code> to <code>float</code>. The first constructor
|
||||
argument for <code>pbase2_type</code> is converted from <code>int</code>
|
||||
to <code>double</code>. The second constructor argument for
|
||||
<code>pbase3_type</code> is a special case of necessary conversion; all
|
||||
forms of the null-pointer literal in C++ (except <code>nullptr</code> from
|
||||
C++2011) also look like compile-time integral expressions, so C++ always
|
||||
interprets such code as an integer when it has overloads that can take either
|
||||
an integer or a pointer. The last conversion is necessary for the compiler to
|
||||
call a constructor form with the exact pointer type used in
|
||||
<code>switcher</code>'s constructor. (If C++2011's <code>nullptr</code> is
|
||||
used, it still needs a conversion if multiple pointer types can be accepted in
|
||||
a constructor call but <code>std::nullptr_t</code> cannot.)</p>
|
||||
|
||||
<h2><a name="credits">Credits</a></h2>
|
||||
|
||||
<h3><a name="contributors">Contributors</a></h3>
|
||||
|
||||
<dl>
|
||||
<dt><a href="http://www.boost.org/people/ed_brey.htm">Ed Brey</a>
|
||||
<dd>Suggested some interface changes.
|
||||
|
||||
<dt><a href="http://www.moocat.org">R. Samuel Klatchko</a> (<a
|
||||
href="mailto:rsk@moocat.org">rsk@moocat.org</a>, <a
|
||||
href="mailto:rsk@brightmail.com">rsk@brightmail.com</a>)
|
||||
<dd>Invented the idiom of how to use a class member for initializing
|
||||
a base class.
|
||||
|
||||
<dt><a href="http://www.boost.org/people/dietmar_kuehl.htm">Dietmar Kuehl</a>
|
||||
<dd>Popularized the base-from-member idiom in his
|
||||
<a href="http://www.informatik.uni-konstanz.de/~kuehl/c++/iostream/">IOStream
|
||||
example classes</a>.
|
||||
|
||||
<dt>Jonathan Turkanis
|
||||
<dd>Supplied an implementation of generating the constructor templates that
|
||||
can be controlled and automated with macros. The implementation uses
|
||||
the <a href="../preprocessor/index.html">Preprocessor library</a>.
|
||||
|
||||
<dt><a href="http://www.boost.org/people/daryle_walker.html">Daryle Walker</a>
|
||||
<dd>Started the library. Contributed the test file <cite><a
|
||||
href="base_from_member_test.cpp">base_from_member_test.cpp</a></cite>.
|
||||
</dl>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised: 16 February 2012</p>
|
||||
|
||||
<p>Copyright 2001, 2003, 2004, 2012 Daryle Walker. Use, modification, and distribution
|
||||
are subject to the Boost Software License, Version 1.0. (See accompanying
|
||||
file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or a copy at <<a
|
||||
href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>>.)</p>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,258 +0,0 @@
|
||||
// (C) Copyright David Abrahams 2000.
|
||||
// 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 <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <climits>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
#include <stdlib.h> // for rand(). Would use cstdlib but VC6.4 doesn't put it in std::
|
||||
#include <list>
|
||||
#include <algorithm>
|
||||
#include <boost/detail/binary_search.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
#if defined(__SGI_STL_PORT) ? defined(__SGI_STL_OWN_IOSTREAMS) : (!defined(__GNUC__) || __GNUC__ > 2)
|
||||
# define USE_SSTREAM
|
||||
#endif
|
||||
|
||||
#ifdef USE_SSTREAM
|
||||
# include <sstream>
|
||||
#else
|
||||
# include <strstream>
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
// In order to get ADL to find the comparison operators defined below, they have
|
||||
struct mystring : std::string
|
||||
{
|
||||
typedef std::string base;
|
||||
|
||||
mystring(std::string const& x)
|
||||
: base(x) {}
|
||||
};
|
||||
|
||||
typedef std::vector<mystring> string_vector;
|
||||
|
||||
const std::size_t sequence_length = 1000;
|
||||
|
||||
unsigned random_number()
|
||||
{
|
||||
return static_cast<unsigned>(::rand()) % sequence_length;
|
||||
}
|
||||
|
||||
# ifndef USE_SSTREAM
|
||||
class unfreezer {
|
||||
public:
|
||||
unfreezer(std::ostrstream& s) : m_stream(s) {}
|
||||
~unfreezer() { m_stream.freeze(false); }
|
||||
private:
|
||||
std::ostrstream& m_stream;
|
||||
};
|
||||
# endif
|
||||
|
||||
template <class T>
|
||||
void push_back_random_number_string(T& seq)
|
||||
{
|
||||
unsigned value = random_number();
|
||||
# if defined(__SGI_STL_PORT) ? defined(__SGI_STL_OWN_IOSTREAMS) : (!defined(__GNUC__) || __GNUC__ > 2)
|
||||
std::ostringstream s;
|
||||
s << value;
|
||||
seq.push_back(s.str());
|
||||
# else
|
||||
std::ostrstream s;
|
||||
auto unfreezer unfreeze(s);
|
||||
s << value << char(0);
|
||||
seq.push_back(std::string(s.str()));
|
||||
# endif
|
||||
}
|
||||
|
||||
inline unsigned to_int(unsigned x) { return x; }
|
||||
inline unsigned to_int(const std::string& x) { return atoi(x.c_str()); }
|
||||
|
||||
struct cmp
|
||||
{
|
||||
template <class A1, class A2>
|
||||
inline bool operator()(const A1& a1, const A2& a2) const
|
||||
{
|
||||
return to_int(a1) < to_int(a2);
|
||||
}
|
||||
};
|
||||
|
||||
inline bool operator<(const mystring& x, const unsigned y)
|
||||
{
|
||||
return to_int(x) < y;
|
||||
}
|
||||
|
||||
inline bool operator<(const unsigned y, const mystring& x)
|
||||
{
|
||||
return y < to_int(x);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void sort_by_value(T& x);
|
||||
|
||||
template <class T>
|
||||
void sort_by_value_(T& v, long)
|
||||
{
|
||||
std::sort(v.begin(), v.end(), cmp());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void random_sorted_sequence(T& seq)
|
||||
{
|
||||
seq.clear();
|
||||
for (std::size_t i = 0; i < sequence_length; ++i)
|
||||
{
|
||||
push_back_random_number_string(seq);
|
||||
}
|
||||
sort_by_value(seq);
|
||||
}
|
||||
|
||||
template <class T, class A>
|
||||
void sort_by_value_(std::list<T,A>& l, int)
|
||||
{
|
||||
# if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) && !defined(__SGI_STL_PORT)
|
||||
// VC6's standard lib doesn't have a template member function for list::sort()
|
||||
std::vector<T> seq;
|
||||
seq.reserve(sequence_length);
|
||||
std::copy(l.begin(), l.end(), std::back_inserter(seq));
|
||||
sort_by_value(seq);
|
||||
std::copy(seq.begin(), seq.end(), l.begin());
|
||||
# else
|
||||
l.sort(cmp());
|
||||
# endif
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void sort_by_value(T& x)
|
||||
{
|
||||
(sort_by_value_)(x, 1);
|
||||
}
|
||||
|
||||
// A way to select the comparisons with/without a Compare parameter for testing.
|
||||
template <class Compare> struct searches
|
||||
{
|
||||
template <class Iterator, class Key>
|
||||
static Iterator lower_bound(Iterator start, Iterator finish, Key key, Compare cmp)
|
||||
{ return boost::detail::lower_bound(start, finish, key, cmp); }
|
||||
|
||||
template <class Iterator, class Key>
|
||||
static Iterator upper_bound(Iterator start, Iterator finish, Key key, Compare cmp)
|
||||
{ return boost::detail::upper_bound(start, finish, key, cmp); }
|
||||
|
||||
template <class Iterator, class Key>
|
||||
static std::pair<Iterator, Iterator> equal_range(Iterator start, Iterator finish, Key key, Compare cmp)
|
||||
{ return boost::detail::equal_range(start, finish, key, cmp); }
|
||||
|
||||
template <class Iterator, class Key>
|
||||
static bool binary_search(Iterator start, Iterator finish, Key key, Compare cmp)
|
||||
{ return boost::detail::binary_search(start, finish, key, cmp); }
|
||||
};
|
||||
|
||||
struct no_compare {};
|
||||
|
||||
template <> struct searches<no_compare>
|
||||
{
|
||||
template <class Iterator, class Key>
|
||||
static Iterator lower_bound(Iterator start, Iterator finish, Key key, no_compare)
|
||||
{ return boost::detail::lower_bound(start, finish, key); }
|
||||
|
||||
template <class Iterator, class Key>
|
||||
static Iterator upper_bound(Iterator start, Iterator finish, Key key, no_compare)
|
||||
{ return boost::detail::upper_bound(start, finish, key); }
|
||||
|
||||
template <class Iterator, class Key>
|
||||
static std::pair<Iterator, Iterator> equal_range(Iterator start, Iterator finish, Key key, no_compare)
|
||||
{ return boost::detail::equal_range(start, finish, key); }
|
||||
|
||||
template <class Iterator, class Key>
|
||||
static bool binary_search(Iterator start, Iterator finish, Key key, no_compare)
|
||||
{ return boost::detail::binary_search(start, finish, key); }
|
||||
};
|
||||
|
||||
template <class Sequence, class Compare>
|
||||
void test_loop(Sequence& x, Compare cmp, unsigned long test_count)
|
||||
{
|
||||
typedef typename Sequence::const_iterator const_iterator;
|
||||
|
||||
for (unsigned long i = 0; i < test_count; ++i)
|
||||
{
|
||||
random_sorted_sequence(x);
|
||||
const const_iterator start = x.begin();
|
||||
const const_iterator finish = x.end();
|
||||
|
||||
unsigned key = random_number();
|
||||
const const_iterator l = searches<Compare>::lower_bound(start, finish, key, cmp);
|
||||
const const_iterator u = searches<Compare>::upper_bound(start, finish, key, cmp);
|
||||
|
||||
bool found_l = false;
|
||||
bool found_u = false;
|
||||
std::size_t index = 0;
|
||||
std::size_t count = 0;
|
||||
unsigned last_value = 0;
|
||||
for (const_iterator p = start; p != finish; ++p)
|
||||
{
|
||||
if (p == l)
|
||||
found_l = true;
|
||||
|
||||
if (p == u)
|
||||
{
|
||||
assert(found_l);
|
||||
found_u = true;
|
||||
}
|
||||
|
||||
unsigned value = to_int(*p);
|
||||
assert(value >= last_value);
|
||||
last_value = value;
|
||||
|
||||
if (!found_l)
|
||||
{
|
||||
++index;
|
||||
assert(to_int(*p) < key);
|
||||
}
|
||||
else if (!found_u)
|
||||
{
|
||||
++count;
|
||||
assert(to_int(*p) == key);
|
||||
}
|
||||
else
|
||||
assert(to_int(*p) > key);
|
||||
}
|
||||
assert(found_l || l == finish);
|
||||
assert(found_u || u == finish);
|
||||
|
||||
std::pair<const_iterator, const_iterator>
|
||||
range = searches<Compare>::equal_range(start, finish, key, cmp);
|
||||
assert(range.first == l);
|
||||
assert(range.second == u);
|
||||
|
||||
bool found = searches<Compare>::binary_search(start, finish, key, cmp);
|
||||
assert(found == (u != l));
|
||||
std::cout << "found " << count << " copies of " << key << " at index " << index << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
string_vector x;
|
||||
std::cout << "=== testing random-access iterators with <: ===\n";
|
||||
test_loop(x, no_compare(), 25);
|
||||
std::cout << "=== testing random-access iterators with compare: ===\n";
|
||||
test_loop(x, cmp(), 25);
|
||||
|
||||
std::list<mystring> y;
|
||||
std::cout << "=== testing bidirectional iterators with <: ===\n";
|
||||
test_loop(y, no_compare(), 25);
|
||||
std::cout << "=== testing bidirectional iterators with compare: ===\n";
|
||||
test_loop(y, cmp(), 25);
|
||||
std::cerr << "******TEST PASSED******\n";
|
||||
return 0;
|
||||
}
|
762
call_traits.htm
762
call_traits.htm
@ -1,755 +1,19 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type"
|
||||
content="text/html; charset=iso-8859-1">
|
||||
<meta name="Template"
|
||||
content="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage Express 2.0">
|
||||
<title>Call Traits</title>
|
||||
<title>Boost.Utility</title>
|
||||
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF"
|
||||
vlink="#800080">
|
||||
|
||||
<h1><img src="../../boost.png" width="276" height="86">Header
|
||||
<<a href="../../boost/detail/call_traits.hpp">boost/call_traits.hpp</a>></h1>
|
||||
|
||||
<p>All of the contents of <boost/call_traits.hpp> are
|
||||
defined inside namespace boost.</p>
|
||||
|
||||
<p>The template class call_traits<T> encapsulates the
|
||||
"best" method to pass a parameter of some type T to or
|
||||
from a function, and consists of a collection of typedefs defined
|
||||
as in the table below. The purpose of call_traits is to ensure
|
||||
that problems like "<a href="#refs">references to references</a>"
|
||||
never occur, and that parameters are passed in the most efficient
|
||||
manner possible (see <a href="#examples">examples</a>). In each
|
||||
case if your existing practice is to use the type defined on the
|
||||
left, then replace it with the call_traits defined type on the
|
||||
right. </p>
|
||||
|
||||
<p>Note that for compilers that do not support either partial
|
||||
specialization or member templates, no benefit will occur from
|
||||
using call_traits: the call_traits defined types will always be
|
||||
the same as the existing practice in this case. In addition if
|
||||
only member templates and not partial template specialisation is
|
||||
support by the compiler (for example Visual C++ 6) then
|
||||
call_traits can not be used with array types (although it can be
|
||||
used to solve the reference to reference problem).</p>
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="1" width="797">
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#008080"><p
|
||||
align="center">Existing practice</p>
|
||||
</td>
|
||||
<td valign="top" width="35%" bgcolor="#008080"><p
|
||||
align="center">call_traits equivalent</p>
|
||||
</td>
|
||||
<td valign="top" width="32%" bgcolor="#008080"><p
|
||||
align="center">Description</p>
|
||||
</td>
|
||||
<td valign="top" width="16%" bgcolor="#008080"><p
|
||||
align="center">Notes</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%"><p align="center">T<br>
|
||||
(return by value)</p>
|
||||
</td>
|
||||
<td valign="top" width="35%"><p align="center"><code>call_traits<T>::value_type</code></p>
|
||||
</td>
|
||||
<td valign="top" width="32%">Defines a type that
|
||||
represents the "value" of type T. Use this for
|
||||
functions that return by value, or possibly for stored
|
||||
values of type T.</td>
|
||||
<td valign="top" width="16%"><p align="center">2</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%"><p align="center">T&<br>
|
||||
(return value)</p>
|
||||
</td>
|
||||
<td valign="top" width="35%"><p align="center"><code>call_traits<T>::reference</code></p>
|
||||
</td>
|
||||
<td valign="top" width="32%">Defines a type that
|
||||
represents a reference to type T. Use for functions that
|
||||
would normally return a T&.</td>
|
||||
<td valign="top" width="16%"><p align="center">1</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%"><p align="center">const
|
||||
T&<br>
|
||||
(return value)</p>
|
||||
</td>
|
||||
<td valign="top" width="35%"><p align="center"><code>call_traits<T>::const_reference</code></p>
|
||||
</td>
|
||||
<td valign="top" width="32%">Defines a type that
|
||||
represents a constant reference to type T. Use for
|
||||
functions that would normally return a const T&.</td>
|
||||
<td valign="top" width="16%"><p align="center">1</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%"><p align="center">const
|
||||
T&<br>
|
||||
(function parameter)</p>
|
||||
</td>
|
||||
<td valign="top" width="35%"><p align="center"><code>call_traits<T>::param_type</code></p>
|
||||
</td>
|
||||
<td valign="top" width="32%">Defines a type that
|
||||
represents the "best" way to pass a parameter
|
||||
of type T to a function.</td>
|
||||
<td valign="top" width="16%"><p align="center">1,3</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>Notes:</p>
|
||||
|
||||
<ol>
|
||||
<li>If T is already reference type, then call_traits is
|
||||
defined such that <a href="#refs">references to
|
||||
references</a> do not occur (requires partial
|
||||
specialization).</li>
|
||||
<li>If T is an array type, then call_traits defines <code>value_type</code>
|
||||
as a "constant pointer to type" rather than an
|
||||
"array of type" (requires partial
|
||||
specialization). Note that if you are using value_type as
|
||||
a stored value then this will result in storing a "constant
|
||||
pointer to an array" rather than the array itself.
|
||||
This may or may not be a good thing depending upon what
|
||||
you actually need (in other words take care!).</li>
|
||||
<li>If T is a small built in type or a pointer, then <code>param_type</code>
|
||||
is defined as <code>T const</code>, instead of <code>T
|
||||
const&</code>. This can improve the ability of the
|
||||
compiler to optimize loops in the body of the function if
|
||||
they depend upon the passed parameter, the semantics of
|
||||
the passed parameter is otherwise unchanged (requires
|
||||
partial specialization).</li>
|
||||
</ol>
|
||||
|
||||
<p> </p>
|
||||
|
||||
<h3>Copy constructibility</h3>
|
||||
|
||||
<p>The following table defines which call_traits types can always
|
||||
be copy-constructed from which other types, those entries marked
|
||||
with a '?' are true only if and only if T is copy constructible:</p>
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="1" width="766">
|
||||
<tr>
|
||||
<td valign="top" width="17%"> </td>
|
||||
<td valign="top" colspan="5" width="85%"
|
||||
bgcolor="#008080"><p align="center">To:</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#008080">From:</td>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">T</p>
|
||||
</td>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">value_type</p>
|
||||
</td>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">reference</p>
|
||||
</td>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">const_reference</p>
|
||||
</td>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">param_type</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0">T</td>
|
||||
<td valign="top" width="17%"><p align="center">?</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">?</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0">value_type</td>
|
||||
<td valign="top" width="17%"><p align="center">?</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">?</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">N</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">N</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0">reference</td>
|
||||
<td valign="top" width="17%"><p align="center">?</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">?</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0">const_reference</td>
|
||||
<td valign="top" width="17%"><p align="center">?</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">N</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">N</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0">param_type</td>
|
||||
<td valign="top" width="17%"><p align="center">?</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">?</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">N</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">N</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p> </p>
|
||||
|
||||
<p>If T is an assignable type the following assignments are
|
||||
possible:</p>
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="1" width="766">
|
||||
<tr>
|
||||
<td valign="top" width="17%"> </td>
|
||||
<td valign="top" colspan="5" width="85%"
|
||||
bgcolor="#008080"><p align="center">To:</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#008080">From:</td>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">T</p>
|
||||
</td>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">value_type</p>
|
||||
</td>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">reference</p>
|
||||
</td>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">const_reference</p>
|
||||
</td>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">param_type</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0">T</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">-</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">-</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">-</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0">value_type</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">-</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">-</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">-</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0">reference</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">-</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">-</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">-</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0">const_reference</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">-</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">-</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">-</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0">param_type</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">Y</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">-</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">-</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">-</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p> </p>
|
||||
|
||||
<h3><a name="examples"></a>Examples</h3>
|
||||
|
||||
<p>The following table shows the effect that call_traits has on
|
||||
various types, the table assumes that the compiler supports
|
||||
partial specialization: if it doesn't then all types behave in
|
||||
the same way as the entry for "myclass", and
|
||||
call_traits can not be used with reference or array types.</p>
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="1" width="766">
|
||||
<tr>
|
||||
<td valign="top" width="17%"> </td>
|
||||
<td valign="top" colspan="5" width="85%"
|
||||
bgcolor="#008080"><p align="center">Call_traits type:</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#008080"><p
|
||||
align="center">Original type T</p>
|
||||
</td>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">value_type</p>
|
||||
</td>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">reference</p>
|
||||
</td>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">const_reference</p>
|
||||
</td>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">param_type</p>
|
||||
</td>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">Applies to:</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">myclass</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">myclass</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">myclass&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const
|
||||
myclass&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">myclass
|
||||
const&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">All user
|
||||
defined types.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">int</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">int</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">int&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const
|
||||
int&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">int const</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">All small
|
||||
built-in types.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">int*</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">int*</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">int*&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">int*const&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">int* const</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">All
|
||||
pointer types.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">int&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">int&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">int&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const
|
||||
int&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">int&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">All
|
||||
reference types.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">const int&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const
|
||||
int&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const
|
||||
int&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const
|
||||
int&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const
|
||||
int&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">All
|
||||
constant-references.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">int[3]</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const int*</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">int(&)[3]</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const int(&)[3]</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const int*
|
||||
const</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">All array
|
||||
types.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||
align="center">const int[3]</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const int*</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const int(&)[3]</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const int(&)[3]</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const int*
|
||||
const</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">All
|
||||
constant-array types.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p> </p>
|
||||
|
||||
<h4>Example 1:</h4>
|
||||
|
||||
<p>The following class is a trivial class that stores some type T
|
||||
by value (see the <a href="call_traits_test.cpp">call_traits_test.cpp</a>
|
||||
file), the aim is to illustrate how each of the available
|
||||
call_traits typedefs may be used:</p>
|
||||
|
||||
<pre>template <class T>
|
||||
struct contained
|
||||
{
|
||||
// define our typedefs first, arrays are stored by value
|
||||
// so value_type is not the same as result_type:
|
||||
typedef typename boost::call_traits<T>::param_type param_type;
|
||||
typedef typename boost::call_traits<T>::reference reference;
|
||||
typedef typename boost::call_traits<T>::const_reference const_reference;
|
||||
typedef T value_type;
|
||||
typedef typename boost::call_traits<T>::value_type result_type;
|
||||
|
||||
// stored value:
|
||||
value_type v_;
|
||||
|
||||
// constructors:
|
||||
contained() {}
|
||||
contained(param_type p) : v_(p){}
|
||||
// return byval:
|
||||
result_type value() { return v_; }
|
||||
// return by_ref:
|
||||
reference get() { return v_; }
|
||||
const_reference const_get()const { return v_; }
|
||||
// pass value:
|
||||
void call(param_type p){}
|
||||
|
||||
};</pre>
|
||||
|
||||
<h4><a name="refs"></a>Example 2 (the reference to reference
|
||||
problem):</h4>
|
||||
|
||||
<p>Consider the definition of std::binder1st:</p>
|
||||
|
||||
<pre>template <class Operation>
|
||||
class binder1st :
|
||||
public unary_function<typename Operation::second_argument_type, typename Operation::result_type>
|
||||
{
|
||||
protected:
|
||||
Operation op;
|
||||
typename Operation::first_argument_type value;
|
||||
public:
|
||||
binder1st(const Operation& x, const typename Operation::first_argument_type& y);
|
||||
typename Operation::result_type operator()(const typename Operation::second_argument_type& x) const;
|
||||
}; </pre>
|
||||
|
||||
<p>Now consider what happens in the relatively common case that
|
||||
the functor takes its second argument as a reference, that
|
||||
implies that <code>Operation::second_argument_type</code> is a
|
||||
reference type, <code>operator()</code> will now end up taking a
|
||||
reference to a reference as an argument, and that is not
|
||||
currently legal. The solution here is to modify <code>operator()</code>
|
||||
to use call_traits:</p>
|
||||
|
||||
<pre>typename Operation::result_type operator()(typename call_traits<typename Operation::second_argument_type>::param_type x) const;</pre>
|
||||
|
||||
<p>Now in the case that <code>Operation::second_argument_type</code>
|
||||
is a reference type, the argument is passed as a reference, and
|
||||
the no "reference to reference" occurs.</p>
|
||||
|
||||
<h4><a name="ex3"></a>Example 3 (the make_pair problem):</h4>
|
||||
|
||||
<p>If we pass the name of an array as one (or both) arguments to <code>std::make_pair</code>,
|
||||
then template argument deduction deduces the passed parameter as
|
||||
"const reference to array of T", this also applies to
|
||||
string literals (which are really array literals). Consequently
|
||||
instead of returning a pair of pointers, it tries to return a
|
||||
pair of arrays, and since an array type is not copy-constructible
|
||||
the code fails to compile. One solution is to explicitly cast the
|
||||
arguments to make_pair to pointers, but call_traits provides a
|
||||
better (i.e. automatic) solution (and one that works safely even
|
||||
in generic code where the cast might do the wrong thing):</p>
|
||||
|
||||
<pre>template <class T1, class T2>
|
||||
std::pair<
|
||||
typename boost::call_traits<T1>::value_type,
|
||||
typename boost::call_traits<T2>::value_type>
|
||||
make_pair(const T1& t1, const T2& t2)
|
||||
{
|
||||
return std::pair<
|
||||
typename boost::call_traits<T1>::value_type,
|
||||
typename boost::call_traits<T2>::value_type>(t1, t2);
|
||||
}</pre>
|
||||
|
||||
<p>Here, the deduced argument types will be automatically
|
||||
degraded to pointers if the deduced types are arrays, similar
|
||||
situations occur in the standard binders and adapters: in
|
||||
principle in any function that "wraps" a temporary
|
||||
whose type is deduced. Note that the function arguments to
|
||||
make_pair are not expressed in terms of call_traits: doing so
|
||||
would prevent template argument deduction from functioning.</p>
|
||||
|
||||
<h4><a name="ex4"></a>Example 4 (optimising fill):</h4>
|
||||
|
||||
<p>The call_traits template will "optimize" the passing
|
||||
of a small built-in type as a function parameter, this mainly has
|
||||
an effect when the parameter is used within a loop body. In the
|
||||
following example (see <a
|
||||
href="../type_traits/examples/fill_example.cpp">fill_example.cpp</a>),
|
||||
a version of std::fill is optimized in two ways: if the type
|
||||
passed is a single byte built-in type then std::memset is used to
|
||||
effect the fill, otherwise a conventional C++ implemention is
|
||||
used, but with the passed parameter "optimized" using
|
||||
call_traits:</p>
|
||||
|
||||
<pre>namespace detail{
|
||||
|
||||
template <bool opt>
|
||||
struct filler
|
||||
{
|
||||
template <typename I, typename T>
|
||||
static void do_fill(I first, I last, typename boost::call_traits<T>::param_type val)
|
||||
{
|
||||
while(first != last)
|
||||
{
|
||||
*first = val;
|
||||
++first;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct filler<true>
|
||||
{
|
||||
template <typename I, typename T>
|
||||
static void do_fill(I first, I last, T val)
|
||||
{
|
||||
memset(first, val, last-first);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <class I, class T>
|
||||
inline void fill(I first, I last, const T& val)
|
||||
{
|
||||
enum{ can_opt = boost::is_pointer<I>::value
|
||||
&& boost::is_arithmetic<T>::value
|
||||
&& (sizeof(T) == 1) };
|
||||
typedef detail::filler<can_opt> filler_t;
|
||||
filler_t::template do_fill<I,T>(first, last, val);
|
||||
}</pre>
|
||||
|
||||
<p>Footnote: the reason that this is "optimal" for
|
||||
small built-in types is that with the value passed as "T
|
||||
const" instead of "const T&" the compiler is
|
||||
able to tell both that the value is constant and that it is free
|
||||
of aliases. With this information the compiler is able to cache
|
||||
the passed value in a register, unroll the loop, or use
|
||||
explicitly parallel instructions: if any of these are supported.
|
||||
Exactly how much mileage you will get from this depends upon your
|
||||
compiler - we could really use some accurate benchmarking
|
||||
software as part of boost for cases like this.</p>
|
||||
|
||||
<p>Note that the function arguments to fill are not expressed in
|
||||
terms of call_traits: doing so would prevent template argument
|
||||
deduction from functioning. Instead fill acts as a "thin
|
||||
wrapper" that is there to perform template argument
|
||||
deduction, the compiler will optimise away the call to fill all
|
||||
together, replacing it with the call to filler<>::do_fill,
|
||||
which does use call_traits.</p>
|
||||
|
||||
<h3>Rationale</h3>
|
||||
|
||||
<p>The following notes are intended to briefly describe the
|
||||
rational behind choices made in call_traits.</p>
|
||||
|
||||
<p>All user-defined types follow "existing practice"
|
||||
and need no comment.</p>
|
||||
|
||||
<p>Small built-in types (what the standard calls fundamental
|
||||
types [3.9.1]) differ from existing practice only in the <i>param_type</i>
|
||||
typedef. In this case passing "T const" is compatible
|
||||
with existing practice, but may improve performance in some cases
|
||||
(see <a href="#ex4">Example 4</a>), in any case this should never
|
||||
be any worse than existing practice.</p>
|
||||
|
||||
<p>Pointers follow the same rational as small built-in types.</p>
|
||||
|
||||
<p>For reference types the rational follows <a href="#refs">Example
|
||||
2</a> - references to references are not allowed, so the
|
||||
call_traits members must be defined such that these problems do
|
||||
not occur. There is a proposal to modify the language such that
|
||||
"a reference to a reference is a reference" (issue #106,
|
||||
submitted by Bjarne Stroustrup), call_traits<T>::value_type
|
||||
and call_traits<T>::param_type both provide the same effect
|
||||
as that proposal, without the need for a language change (in
|
||||
other words it's a workaround).</p>
|
||||
|
||||
<p>For array types, a function that takes an array as an argument
|
||||
will degrade the array type to a pointer type: this means that
|
||||
the type of the actual parameter is different from its declared
|
||||
type, something that can cause endless problems in template code
|
||||
that relies on the declared type of a parameter. For example:</p>
|
||||
|
||||
<pre>template <class T>
|
||||
struct A
|
||||
{
|
||||
void foo(T t);
|
||||
};</pre>
|
||||
|
||||
<p><font face="Times New Roman">In this case if we instantiate
|
||||
A<int[2]> then the declared type of the parameter passed to
|
||||
member function foo is int[2], but it's actual type is const int*,
|
||||
if we try to use the type T within the function body, then there
|
||||
is a strong likelyhood that our code will not compile:</font></p>
|
||||
|
||||
<pre>template <class T>
|
||||
void A<T>::foo(T t)
|
||||
{
|
||||
T dup(t); // doesn't compile for case that T is an array.
|
||||
}</pre>
|
||||
|
||||
<p>By using call_traits the degradation from array to pointer is
|
||||
explicit, and the type of the parameter is the same as it's
|
||||
declared type:</p>
|
||||
|
||||
<pre>template <class T>
|
||||
struct A
|
||||
{
|
||||
void foo(typename call_traits<T>::value_type t);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void A<T>::foo(typename call_traits<T>::value_type t)
|
||||
{
|
||||
typename call_traits<T>::value_type dup(t); // OK even if T is an array type.
|
||||
}</pre>
|
||||
|
||||
<p>For value_type (return by value), again only a pointer may be
|
||||
returned, not a copy of the whole array, and again call_traits
|
||||
makes the degradation explicit. The value_type member is useful
|
||||
whenever an array must be explicitly degraded to a pointer - <a
|
||||
href="#ex3">Example 3</a> provides the test case (Footnote: the
|
||||
array specialisation for call_traits is the least well understood
|
||||
of all the call_traits specialisations, if the given semantics
|
||||
cause specific problems for you, or don't solve a particular
|
||||
array-related problem, then I would be interested to hear about
|
||||
it. Most people though will probably never need to use this
|
||||
specialisation).</p>
|
||||
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="./doc/html/utility/utilities/call_traits.html">./doc/html/utility/utilities/call_traits.html</a>
|
||||
<hr>
|
||||
|
||||
<p>Revised 01 September 2000</p>
|
||||
|
||||
<p>
|
||||
Copyright 2000 Steve Cleary, Beman Dawes, Howard
|
||||
Hinnant and John Maddock. <br/>
|
||||
Use, modification and distribution are subject to the
|
||||
Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt
|
||||
or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
|
||||
http://www.boost.org/LICENSE_1_0.txt
|
||||
</a>).
|
||||
</p>
|
||||
<tt>
|
||||
Boost.Utility<br>
|
||||
<br>
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||
<br>
|
||||
</tt>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -1,122 +1,19 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Boost: checked_delete.hpp documentation</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
</head>
|
||||
<body bgcolor="white" style="MARGIN-LEFT: 5%; MARGIN-RIGHT: 5%">
|
||||
<table border="0" width="100%">
|
||||
<tr>
|
||||
<td width="277"><A href="../../index.htm"> <img src="../../boost.png" alt="boost.png (6897 bytes)" width="277" height="86" border="0"></A>
|
||||
</td>
|
||||
<td align="center">
|
||||
<h1>checked_delete.hpp</h1>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" height="64"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>
|
||||
The header <STRONG><boost/checked_delete.hpp></STRONG> defines two
|
||||
function templates, <STRONG>checked_delete</STRONG> and <STRONG>checked_array_delete</STRONG>,
|
||||
and two class templates, <STRONG>checked_deleter</STRONG> and <STRONG>checked_array_deleter</STRONG>.
|
||||
</p>
|
||||
<P>The C++ Standard allows, in 5.3.5/5, pointers to incomplete class types to be
|
||||
deleted with a <EM>delete-expression</EM>. When the class has a non-trivial
|
||||
destructor, or a class-specific operator delete, the behavior is undefined.
|
||||
Some compilers issue a warning when an incomplete type is deleted, but
|
||||
unfortunately, not all do, and programmers sometimes ignore or disable
|
||||
warnings.</P>
|
||||
<P>A particularly troublesome case is when a smart pointer's destructor, such as <STRONG>
|
||||
boost::scoped_ptr<T>::~scoped_ptr</STRONG>, is instantiated with an
|
||||
incomplete type. This can often lead to silent, hard to track failures.</P>
|
||||
<P>The supplied function and class templates can be used to prevent these problems,
|
||||
as they require a complete type, and cause a compilation error otherwise.</P>
|
||||
<h3><a name="Synopsis">Synopsis</a></h3>
|
||||
<pre>
|
||||
namespace boost
|
||||
{
|
||||
|
||||
template<class T> void checked_delete(T * p);
|
||||
template<class T> void checked_array_delete(T * p);
|
||||
template<class T> struct checked_deleter;
|
||||
template<class T> struct checked_array_deleter;
|
||||
|
||||
}
|
||||
</pre>
|
||||
<h3>checked_delete</h3>
|
||||
<h4><a name="checked_delete">template<class T> void checked_delete(T * p);</a></h4>
|
||||
<blockquote>
|
||||
<p>
|
||||
<b>Requires:</b> <b>T</b> must be a complete type. The expression <tt>delete p</tt>
|
||||
must be well-formed.
|
||||
</p>
|
||||
<p>
|
||||
<b>Effects:</b> <tt>delete p;</tt>
|
||||
</p>
|
||||
</blockquote>
|
||||
<h3>checked_array_delete</h3>
|
||||
<h4><a name="checked_array_delete">template<class T> void checked_array_delete(T
|
||||
* p);</a></h4>
|
||||
<blockquote>
|
||||
<p>
|
||||
<b>Requires:</b> <b>T</b> must be a complete type. The expression <tt>delete [] p</tt>
|
||||
must be well-formed.
|
||||
</p>
|
||||
<p>
|
||||
<b>Effects:</b> <tt>delete [] p;</tt>
|
||||
</p>
|
||||
</blockquote>
|
||||
<h3>checked_deleter</h3>
|
||||
<pre>
|
||||
template<class T> struct checked_deleter
|
||||
{
|
||||
typedef void result_type;
|
||||
typedef T * argument_type;
|
||||
void operator()(T * p) const;
|
||||
};
|
||||
</pre>
|
||||
<h4>void checked_deleter<T>::operator()(T * p) const;</h4>
|
||||
<blockquote>
|
||||
<p>
|
||||
<b>Requires:</b> <b>T</b> must be a complete type. The expression <tt>delete p</tt>
|
||||
must be well-formed.
|
||||
</p>
|
||||
<p>
|
||||
<b>Effects:</b> <tt>delete p;</tt>
|
||||
</p>
|
||||
</blockquote>
|
||||
<h3>checked_array_deleter</h3>
|
||||
<pre>
|
||||
template<class T> struct checked_array_deleter
|
||||
{
|
||||
typedef void result_type;
|
||||
typedef T * argument_type;
|
||||
void operator()(T * p) const;
|
||||
};
|
||||
</pre>
|
||||
<h4>void checked_array_deleter<T>::operator()(T * p) const;</h4>
|
||||
<blockquote>
|
||||
<p>
|
||||
<b>Requires:</b> <b>T</b> must be a complete type. The expression <tt>delete [] p</tt>
|
||||
must be well-formed.
|
||||
</p>
|
||||
<p>
|
||||
<b>Effects:</b> <tt>delete [] p;</tt>
|
||||
</p>
|
||||
</blockquote>
|
||||
<h3><a name="Acknowledgements">Acknowledgements</a></h3>
|
||||
<p>
|
||||
The function templates <STRONG>checked_delete</STRONG> and <STRONG>checked_array_delete</STRONG>
|
||||
were originally part of <STRONG><boost/utility.hpp></STRONG>, and the
|
||||
documentation acknowledged Beman Dawes, Dave Abrahams, Vladimir Prus, Rainer
|
||||
Deyke, John Maddock, and others as contributors.
|
||||
</p>
|
||||
<p>
|
||||
<br>
|
||||
<small>Copyright <20> 2002 by Peter Dimov. Distributed under the Boost Software License, Version
|
||||
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
|
||||
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
|
||||
</body>
|
||||
<head>
|
||||
<title>Boost.Utility</title>
|
||||
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="../core/doc/html/core/checked_delete.html">../core/doc/html/core/checked_delete.html</a>
|
||||
<hr>
|
||||
<tt>
|
||||
Boost.Utility<br>
|
||||
<br>
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||
<br>
|
||||
</tt>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,28 +0,0 @@
|
||||
// Boost checked_delete test program ---------------------------------------//
|
||||
|
||||
// Copyright Beman Dawes 2001. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See http://www.boost.org/libs/utility for documentation.
|
||||
|
||||
// Revision History
|
||||
// 21 May 01 Initial version (Beman Dawes)
|
||||
|
||||
#include <boost/checked_delete.hpp> // for checked_delete
|
||||
|
||||
// This program demonstrates compiler errors when trying to delete an
|
||||
// incomplete type.
|
||||
|
||||
namespace
|
||||
{
|
||||
class Incomplete;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
Incomplete * p = 0;
|
||||
boost::checked_delete(p); // should cause compile time error
|
||||
boost::checked_array_delete(p); // should cause compile time error
|
||||
return 0;
|
||||
} // main
|
@ -1,76 +1,19 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Header </title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Template" content="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
|
||||
<boostcompressed_pair.hpp>
|
||||
</head>
|
||||
<body bgcolor="#ffffff" text="#000000" link="#0000ff" vlink="#800080">
|
||||
<h2><img src="../../boost.png" width="276" height="86">Header <<a href="../../boost/detail/compressed_pair.hpp">boost/compressed_pair.hpp</a>></h2>
|
||||
<p>All of the contents of <boost/compressed_pair.hpp> are defined inside
|
||||
namespace boost.</p>
|
||||
<p>The class compressed pair is very similar to std::pair, but if either of the
|
||||
template arguments are empty classes, then the "empty base-class optimisation"
|
||||
is applied to compress the size of the pair.</p>
|
||||
<pre>template <class T1, class T2>
|
||||
class compressed_pair
|
||||
{
|
||||
public:
|
||||
typedef T1 first_type;
|
||||
typedef T2 second_type;
|
||||
typedef typename call_traits<first_type>::param_type first_param_type;
|
||||
typedef typename call_traits<second_type>::param_type second_param_type;
|
||||
typedef typename call_traits<first_type>::reference first_reference;
|
||||
typedef typename call_traits<second_type>::reference second_reference;
|
||||
typedef typename call_traits<first_type>::const_reference first_const_reference;
|
||||
typedef typename call_traits<second_type>::const_reference second_const_reference;
|
||||
|
||||
compressed_pair() : base() {}
|
||||
compressed_pair(first_param_type x, second_param_type y);
|
||||
explicit compressed_pair(first_param_type x);
|
||||
explicit compressed_pair(second_param_type y);
|
||||
|
||||
compressed_pair& operator=(const compressed_pair&);
|
||||
|
||||
first_reference first();
|
||||
first_const_reference first() const;
|
||||
|
||||
second_reference second();
|
||||
second_const_reference second() const;
|
||||
|
||||
void swap(compressed_pair& y);
|
||||
};</pre>
|
||||
<p>The two members of the pair can be accessed using the member functions first()
|
||||
and second(). Note that not all member functions can be instantiated for all
|
||||
template parameter types. In particular compressed_pair can be instantiated for
|
||||
reference and array types, however in these cases the range of constructors
|
||||
that can be used are limited. If types T1 and T2 are the same type, then there
|
||||
is only one version of the single-argument constructor, and this constructor
|
||||
initialises both values in the pair to the passed value.</p>
|
||||
<P>Note that if either member is a POD type, then that member is not
|
||||
zero-initialized by the compressed_pair default constructor: it's up to you to
|
||||
supply an initial value for these types if you want them to have a default
|
||||
value.</P>
|
||||
<p>Note that compressed_pair can not be instantiated if either of the template
|
||||
arguments is a union type, unless there is compiler support for
|
||||
boost::is_union, or if boost::is_union is specialised for the union type.</p>
|
||||
<p>Finally, a word of caution for Visual C++ 6 users: if either argument is an
|
||||
empty type, then assigning to that member will produce memory corruption,
|
||||
unless the empty type has a "do nothing" assignment operator defined. This is
|
||||
due to a bug in the way VC6 generates implicit assignment operators.</p>
|
||||
<h3>Acknowledgements</h3>
|
||||
<p>Based on contributions by Steve Cleary, Beman Dawes, Howard Hinnant and John
|
||||
Maddock.</p>
|
||||
<p>Maintained by <a href="mailto:john@johnmaddock.co.uk">John Maddock</a>, the
|
||||
latest version of this file can be found at <a href="http://www.boost.org">www.boost.org</a>,
|
||||
and the boost discussion list at <a href="http://www.yahoogroups.com/list/boost">www.yahoogroups.com/list/boost</a>.</p>
|
||||
<hr>
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->07 November 2007<!--webbot bot="Timestamp" endspan i-checksum="40338" --></p>
|
||||
<p><EFBFBD> Copyright Beman Dawes, 2000.</p>
|
||||
<p>Distributed under the Boost Software License, Version 1.0. See
|
||||
<a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a></p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
<head>
|
||||
<title>Boost.Utility</title>
|
||||
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="./doc/html/utility/utilities/compressed_pair.html">./doc/html/utility/utilities/compressed_pair.html</a>
|
||||
<hr>
|
||||
<tt>
|
||||
Boost.Utility<br>
|
||||
<br>
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||
<br>
|
||||
</tt>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,36 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Boost: current_function.hpp documentation</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
</head>
|
||||
<body bgcolor="white" style="MARGIN-LEFT: 5%; MARGIN-RIGHT: 5%">
|
||||
<table border="0" width="100%">
|
||||
<tr>
|
||||
<td width="277"><A href="../../index.htm"> <img src="../../boost.png" alt="boost.png (6897 bytes)" width="277" height="86" border="0"></A>
|
||||
</td>
|
||||
<td align="center">
|
||||
<h1>current_function.hpp</h1>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" height="64"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>
|
||||
The header <STRONG><boost/current_function.hpp></STRONG> defines a single
|
||||
macro, <STRONG>BOOST_CURRENT_FUNCTION</STRONG>,<STRONG> </STRONG>similar to the
|
||||
C99 predefined identifier <STRONG>__func__</STRONG>.
|
||||
</p>
|
||||
<P><STRONG>BOOST_CURRENT_FUNCTION</STRONG> expands to a string literal containing
|
||||
the (fully qualified, if possible) name of the enclosing function. If there is
|
||||
no enclosing function, the behavior is undefined.</P>
|
||||
<p>Some compilers do not provide a way to obtain the name of the current enclosing
|
||||
function. On such compilers, the string literal has an unspecified value.</p>
|
||||
<p>
|
||||
<br>
|
||||
<small>Copyright <20> 2002 by Peter Dimov. Distributed under the Boost Software License, Version
|
||||
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
|
||||
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
|
||||
</body>
|
||||
</html>
|
@ -1,40 +0,0 @@
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(disable: 4786) // identifier truncated in debug info
|
||||
#pragma warning(disable: 4710) // function not inlined
|
||||
#pragma warning(disable: 4711) // function selected for automatic inline expansion
|
||||
#pragma warning(disable: 4514) // unreferenced inline removed
|
||||
#endif
|
||||
|
||||
//
|
||||
// current_function_test.cpp - a test for boost/current_function.hpp
|
||||
//
|
||||
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
|
||||
//
|
||||
// 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/current_function.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <cstdio>
|
||||
|
||||
void message(char const * file, long line, char const * func, char const * msg)
|
||||
{
|
||||
#if !defined(BOOST_NO_STDC_NAMESPACE)
|
||||
using std::printf;
|
||||
#endif
|
||||
|
||||
printf("%s(%ld): %s in function '%s'\n", file, line, msg, func);
|
||||
}
|
||||
|
||||
#define MESSAGE(msg) message(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, msg)
|
||||
|
||||
int main()
|
||||
{
|
||||
MESSAGE("assertion failed");
|
||||
|
||||
return 0;
|
||||
}
|
4
doc/.gitignore
vendored
Normal file
4
doc/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
html
|
||||
xml
|
||||
temp
|
||||
out.txt
|
81
doc/BOOST_BINARY.qbk
Normal file
81
doc/BOOST_BINARY.qbk
Normal file
@ -0,0 +1,81 @@
|
||||
[/
|
||||
/ Copyright (c) 2012 Marshall Clow
|
||||
/ Copyright (c) 2021, Alan Freitas
|
||||
/ 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)
|
||||
/]
|
||||
|
||||
[/===============]
|
||||
[#sec:BOOST_BINARY]
|
||||
[section Binary Integer Literals]
|
||||
[/===============]
|
||||
|
||||
[section Introduction]
|
||||
|
||||
The macro `BOOST_BINARY` is used for the representation of binary
|
||||
literals. It takes as an argument a binary number arranged as an
|
||||
arbitrary amount of 1s and 0s in groupings of length 1 to 8, with
|
||||
groups separated by spaces. The macro serves as a replacement for
|
||||
[@https://en.cppreference.com/w/cpp/language/integer_literal binary integer literals],
|
||||
adopted in C++14.
|
||||
|
||||
The type of the literal yielded is determined by the same rules as
|
||||
those of [@https://en.cppreference.com/w/cpp/language/integer_literal hex and octal literals].
|
||||
By implementation, this macro expands directly to an octal literal during preprocessing, so
|
||||
there is no overhead at runtime and the result is usable in any place that an octal literal
|
||||
would be.
|
||||
|
||||
In order to directly support binary literals with suffixes,
|
||||
additional macros of the form `BOOST_BINARY_XXX` are also
|
||||
provided, where `XXX` is a standard integer suffix in all capital
|
||||
letters.
|
||||
|
||||
In addition, LL and ULL suffixes may be used for representing
|
||||
`long long` and `unsigned long long` types in compilers which provide
|
||||
them as an extension.
|
||||
|
||||
The `BOOST_BINARY` family of macros resides in the header
|
||||
[@../../../../boost/utility/binary.hpp <boost/utility/binary.hpp>].
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Example]
|
||||
|
||||
```
|
||||
void foo( int );
|
||||
|
||||
void foo( unsigned long );
|
||||
|
||||
void bar()
|
||||
{
|
||||
int value1 = BOOST_BINARY( 100 111000 01 1 110 );
|
||||
|
||||
unsigned long value2 = BOOST_BINARY_UL( 100 001 ); // unsigned long
|
||||
|
||||
long long value3 = BOOST_BINARY_LL( 11 000 ); // long long if supported
|
||||
|
||||
__assert__( BOOST_BINARY( 10010 )
|
||||
& BOOST_BINARY( 11000 )
|
||||
== BOOST_BINARY( 10000 )
|
||||
);
|
||||
|
||||
foo( BOOST_BINARY( 1010 ) ); // calls the first foo
|
||||
|
||||
foo( BOOST_BINARY_LU( 1010 ) ); // calls the second foo
|
||||
}
|
||||
```
|
||||
|
||||
[endsect]
|
||||
|
||||
[/===============]
|
||||
[xinclude tmp/boost_binary_reference.xml]
|
||||
[/===============]
|
||||
|
||||
|
||||
[section Acknowledgments]
|
||||
|
||||
Contributed by Matt Calabrese.
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
483
doc/Jamfile.v2
483
doc/Jamfile.v2
@ -1,100 +1,413 @@
|
||||
|
||||
# Copyright John Maddock 2005. 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)
|
||||
|
||||
project : requirements
|
||||
# Path for links to Boost:
|
||||
<xsl:param>boost.root=../../../..
|
||||
import project ;
|
||||
import doxygen ;
|
||||
import quickbook ;
|
||||
|
||||
# Some general style settings:
|
||||
<xsl:param>table.footnote.number.format=1
|
||||
<xsl:param>footnote.number.format=1
|
||||
|
||||
# HTML options first:
|
||||
# Use graphics not text for navigation:
|
||||
<xsl:param>navig.graphics=1
|
||||
# PDF Options:
|
||||
# TOC Generation: this is needed for FOP-0.9 and later:
|
||||
<xsl:param>fop1.extensions=0
|
||||
<xsl:param>xep.extensions=1
|
||||
# TOC generation: this is needed for FOP 0.2, but must not be set to zero for FOP-0.9!
|
||||
<xsl:param>fop.extensions=0
|
||||
# No indent on body text:
|
||||
<xsl:param>body.start.indent=0pt
|
||||
# Margin size:
|
||||
<xsl:param>page.margin.inner=0.5in
|
||||
# Margin size:
|
||||
<xsl:param>page.margin.outer=0.5in
|
||||
# Paper type = A4
|
||||
<xsl:param>paper.type=A4
|
||||
# Yes, we want graphics for admonishments:
|
||||
<xsl:param>admon.graphics=1
|
||||
# Set this one for PDF generation *only*:
|
||||
# default pnd graphics are awful in PDF form,
|
||||
# better use SVG's instead:
|
||||
<format>pdf:<xsl:param>admon.graphics.extension=".svg"
|
||||
<format>pdf:<xsl:param>admon.graphics.path=$(boost-images)/
|
||||
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/libs/utility/doc/html
|
||||
;
|
||||
|
||||
using quickbook ;
|
||||
project boost/libs/utility/doc ;
|
||||
|
||||
path-constant INCLUDES : ../../.. ;
|
||||
path-constant boost-images : ../../../doc/src/images ;
|
||||
|
||||
xml declval : declval.qbk ;
|
||||
boostbook standalone_declval
|
||||
# Generate XML doxygen reference for base_from_member component in base_from_member_reference.xml
|
||||
doxygen base_from_member_reference
|
||||
:
|
||||
$(INCLUDES)/boost/utility/base_from_member.hpp
|
||||
:
|
||||
<location>tmp
|
||||
<doxygen:param>ENABLE_PREPROCESSING=YES
|
||||
<doxygen:param>EXPAND_ONLY_PREDEF=YES
|
||||
<doxygen:param>EXTRACT_ALL=NO
|
||||
<doxygen:param>EXTRACT_PRIVATE=NO
|
||||
<doxygen:param>HIDE_UNDOC_MEMBERS=YES
|
||||
<doxygen:param>MACRO_EXPANSION=YES
|
||||
<doxygen:param>"PREDEFINED= \\
|
||||
BOOST_UTILITY_DOCS \\
|
||||
BOOST_SYMBOL_VISIBLE= \\
|
||||
BOOST_FORCEINLINE=inline \\
|
||||
BOOST_GPU_ENABLED= \\
|
||||
BOOST_STATIC_ASSERT(x)= \\
|
||||
BOOST_STATIC_ASSERT_MSG(x,y)= \\
|
||||
BOOST_STATIC_CONSTANT(x,y)=\"static constexpr x y\" \\
|
||||
BOOST_RV_REF(x)=\"x&&\" \\
|
||||
BOOST_NESTED_TEMPLATE=template \\
|
||||
BOOST_CONSTEXPR=constexpr \\
|
||||
BOOST_CXX14_CONSTEXPR=constexpr \\
|
||||
BOOST_OPERATORS_CONSTEXPR=constexpr \\
|
||||
BOOST_CONSTEXPR_OR_CONST=constexpr \\
|
||||
BOOST_NOEXCEPT=noexcept \\
|
||||
BOOST_NOEXCEPT_IF(x)=noexcept(x) \\
|
||||
BOOST_NOEXCEPT_OR_NOTHROW=noexcept \\
|
||||
BOOST_COPY_ASSIGN_REF(x)=\"x const&\" \\
|
||||
BOOST_DEFAULTED_FUNCTION(x,y)=\"x = default;\" \\
|
||||
BOOST_DELETED_FUNCTION(x)=\"x = delete;\" \\
|
||||
BOOST_EXPLICIT_OPERATOR_BOOL()=\"explicit operator bool() const;\" \\
|
||||
BOOST_REF_CONST=const"
|
||||
<doxygen:param>"EXCLUDE_SYMBOLS= \\
|
||||
detail \\
|
||||
F \\
|
||||
result_of_has_result_type_impl \\
|
||||
conditional \\
|
||||
boost::operators_impl"
|
||||
<xsl:param>"boost.doxygen.reftitle=Reference"
|
||||
<xsl:param>"boost.doxygen.refid=base_from_member.reference"
|
||||
;
|
||||
|
||||
# Generate XML doxygen reference for boost_binary component in boost_binary_reference.xml
|
||||
doxygen boost_binary_reference
|
||||
:
|
||||
$(INCLUDES)/boost/utility/binary.hpp
|
||||
:
|
||||
<location>tmp
|
||||
<doxygen:param>ENABLE_PREPROCESSING=YES
|
||||
<doxygen:param>EXPAND_ONLY_PREDEF=YES
|
||||
<doxygen:param>EXTRACT_ALL=NO
|
||||
<doxygen:param>EXTRACT_PRIVATE=NO
|
||||
<doxygen:param>HIDE_UNDOC_MEMBERS=YES
|
||||
<doxygen:param>MACRO_EXPANSION=YES
|
||||
<doxygen:param>"PREDEFINED= \\
|
||||
BOOST_UTILITY_DOCS \\
|
||||
BOOST_SYMBOL_VISIBLE= \\
|
||||
BOOST_FORCEINLINE=inline \\
|
||||
BOOST_GPU_ENABLED= \\
|
||||
BOOST_STATIC_ASSERT(x)= \\
|
||||
BOOST_STATIC_ASSERT_MSG(x,y)= \\
|
||||
BOOST_STATIC_CONSTANT(x,y)=\"static constexpr x y\" \\
|
||||
BOOST_RV_REF(x)=\"x&&\" \\
|
||||
BOOST_NESTED_TEMPLATE=template \\
|
||||
BOOST_CONSTEXPR=constexpr \\
|
||||
BOOST_CXX14_CONSTEXPR=constexpr \\
|
||||
BOOST_OPERATORS_CONSTEXPR=constexpr \\
|
||||
BOOST_CONSTEXPR_OR_CONST=constexpr \\
|
||||
BOOST_NOEXCEPT=noexcept \\
|
||||
BOOST_NOEXCEPT_IF(x)=noexcept(x) \\
|
||||
BOOST_NOEXCEPT_OR_NOTHROW=noexcept \\
|
||||
BOOST_COPY_ASSIGN_REF(x)=\"x const&\" \\
|
||||
BOOST_DEFAULTED_FUNCTION(x,y)=\"x = default;\" \\
|
||||
BOOST_DELETED_FUNCTION(x)=\"x = delete;\" \\
|
||||
BOOST_EXPLICIT_OPERATOR_BOOL()=\"explicit operator bool() const;\" \\
|
||||
BOOST_REF_CONST=const"
|
||||
<doxygen:param>"EXCLUDE_SYMBOLS= \\
|
||||
detail \\
|
||||
F \\
|
||||
result_of_has_result_type_impl \\
|
||||
conditional \\
|
||||
boost::operators_impl"
|
||||
<xsl:param>"boost.doxygen.reftitle=Reference"
|
||||
<xsl:param>"boost.doxygen.refid=boost_binary.reference"
|
||||
;
|
||||
|
||||
# Generate XML doxygen reference for call_traits component in call_traits_reference.xml
|
||||
doxygen call_traits_reference
|
||||
:
|
||||
$(INCLUDES)/boost/call_traits.hpp
|
||||
$(INCLUDES)/boost/detail/call_traits.hpp
|
||||
:
|
||||
<location>tmp
|
||||
<doxygen:param>ENABLE_PREPROCESSING=YES
|
||||
<doxygen:param>EXPAND_ONLY_PREDEF=YES
|
||||
<doxygen:param>EXTRACT_ALL=NO
|
||||
<doxygen:param>EXTRACT_PRIVATE=NO
|
||||
<doxygen:param>HIDE_UNDOC_MEMBERS=YES
|
||||
<doxygen:param>MACRO_EXPANSION=YES
|
||||
<doxygen:param>"PREDEFINED= \\
|
||||
BOOST_UTILITY_DOCS \\
|
||||
BOOST_SYMBOL_VISIBLE= \\
|
||||
BOOST_FORCEINLINE=inline \\
|
||||
BOOST_GPU_ENABLED= \\
|
||||
BOOST_STATIC_ASSERT(x)= \\
|
||||
BOOST_STATIC_ASSERT_MSG(x,y)= \\
|
||||
BOOST_STATIC_CONSTANT(x,y)=\"static constexpr x y\" \\
|
||||
BOOST_RV_REF(x)=\"x&&\" \\
|
||||
BOOST_NESTED_TEMPLATE=template \\
|
||||
BOOST_CONSTEXPR=constexpr \\
|
||||
BOOST_CXX14_CONSTEXPR=constexpr \\
|
||||
BOOST_OPERATORS_CONSTEXPR=constexpr \\
|
||||
BOOST_CONSTEXPR_OR_CONST=constexpr \\
|
||||
BOOST_NOEXCEPT=noexcept \\
|
||||
BOOST_NOEXCEPT_IF(x)=noexcept(x) \\
|
||||
BOOST_NOEXCEPT_OR_NOTHROW=noexcept \\
|
||||
BOOST_COPY_ASSIGN_REF(x)=\"x const&\" \\
|
||||
BOOST_DEFAULTED_FUNCTION(x,y)=\"x = default;\" \\
|
||||
BOOST_DELETED_FUNCTION(x)=\"x = delete;\" \\
|
||||
BOOST_EXPLICIT_OPERATOR_BOOL()=\"explicit operator bool() const;\" \\
|
||||
BOOST_REF_CONST=const"
|
||||
<doxygen:param>"EXCLUDE_SYMBOLS= \\
|
||||
detail \\
|
||||
F \\
|
||||
result_of_has_result_type_impl \\
|
||||
conditional \\
|
||||
boost::operators_impl"
|
||||
<xsl:param>"boost.doxygen.reftitle=Reference"
|
||||
<xsl:param>"boost.doxygen.refid=call_traits.reference"
|
||||
;
|
||||
|
||||
# Generate XML doxygen reference for compressed_pair component in compressed_pair_reference.xml
|
||||
doxygen compressed_pair_reference
|
||||
:
|
||||
$(INCLUDES)/boost/compressed_pair.hpp
|
||||
$(INCLUDES)/boost/detail/compressed_pair.hpp
|
||||
:
|
||||
<location>tmp
|
||||
<doxygen:param>ENABLE_PREPROCESSING=YES
|
||||
<doxygen:param>EXPAND_ONLY_PREDEF=YES
|
||||
<doxygen:param>EXTRACT_ALL=NO
|
||||
<doxygen:param>EXTRACT_PRIVATE=NO
|
||||
<doxygen:param>HIDE_UNDOC_MEMBERS=YES
|
||||
<doxygen:param>MACRO_EXPANSION=YES
|
||||
<doxygen:param>"PREDEFINED= \\
|
||||
BOOST_UTILITY_DOCS \\
|
||||
BOOST_SYMBOL_VISIBLE= \\
|
||||
BOOST_FORCEINLINE=inline \\
|
||||
BOOST_GPU_ENABLED= \\
|
||||
BOOST_STATIC_ASSERT(x)= \\
|
||||
BOOST_STATIC_ASSERT_MSG(x,y)= \\
|
||||
BOOST_STATIC_CONSTANT(x,y)=\"static constexpr x y\" \\
|
||||
BOOST_RV_REF(x)=\"x&&\" \\
|
||||
BOOST_NESTED_TEMPLATE=template \\
|
||||
BOOST_CONSTEXPR=constexpr \\
|
||||
BOOST_CXX14_CONSTEXPR=constexpr \\
|
||||
BOOST_OPERATORS_CONSTEXPR=constexpr \\
|
||||
BOOST_CONSTEXPR_OR_CONST=constexpr \\
|
||||
BOOST_NOEXCEPT=noexcept \\
|
||||
BOOST_NOEXCEPT_IF(x)=noexcept(x) \\
|
||||
BOOST_NOEXCEPT_OR_NOTHROW=noexcept \\
|
||||
BOOST_COPY_ASSIGN_REF(x)=\"x const&\" \\
|
||||
BOOST_DEFAULTED_FUNCTION(x,y)=\"x = default;\" \\
|
||||
BOOST_DELETED_FUNCTION(x)=\"x = delete;\" \\
|
||||
BOOST_EXPLICIT_OPERATOR_BOOL()=\"explicit operator bool() const;\" \\
|
||||
BOOST_REF_CONST=const"
|
||||
<doxygen:param>"EXCLUDE_SYMBOLS= \\
|
||||
detail \\
|
||||
F \\
|
||||
result_of_has_result_type_impl \\
|
||||
conditional \\
|
||||
boost::operators_impl"
|
||||
<xsl:param>"boost.doxygen.reftitle=Reference"
|
||||
<xsl:param>"boost.doxygen.refid=compressed_pair.reference"
|
||||
;
|
||||
|
||||
# Generate XML doxygen reference for in_place_factory component in in_place_factory_reference.xml
|
||||
doxygen in_place_factory_reference
|
||||
:
|
||||
$(INCLUDES)/boost/utility/in_place_factory.hpp
|
||||
$(INCLUDES)/boost/utility/typed_in_place_factory.hpp
|
||||
:
|
||||
<location>tmp
|
||||
<doxygen:param>ENABLE_PREPROCESSING=YES
|
||||
<doxygen:param>EXPAND_ONLY_PREDEF=YES
|
||||
<doxygen:param>EXTRACT_ALL=NO
|
||||
<doxygen:param>EXTRACT_PRIVATE=NO
|
||||
<doxygen:param>HIDE_UNDOC_MEMBERS=YES
|
||||
<doxygen:param>MACRO_EXPANSION=YES
|
||||
<doxygen:param>"PREDEFINED= \\
|
||||
BOOST_UTILITY_DOCS \\
|
||||
BOOST_SYMBOL_VISIBLE= \\
|
||||
BOOST_FORCEINLINE=inline \\
|
||||
BOOST_GPU_ENABLED= \\
|
||||
BOOST_STATIC_ASSERT(x)= \\
|
||||
BOOST_STATIC_ASSERT_MSG(x,y)= \\
|
||||
BOOST_STATIC_CONSTANT(x,y)=\"static constexpr x y\" \\
|
||||
BOOST_RV_REF(x)=\"x&&\" \\
|
||||
BOOST_NESTED_TEMPLATE=template \\
|
||||
BOOST_CONSTEXPR=constexpr \\
|
||||
BOOST_CXX14_CONSTEXPR=constexpr \\
|
||||
BOOST_OPERATORS_CONSTEXPR=constexpr \\
|
||||
BOOST_CONSTEXPR_OR_CONST=constexpr \\
|
||||
BOOST_NOEXCEPT=noexcept \\
|
||||
BOOST_NOEXCEPT_IF(x)=noexcept(x) \\
|
||||
BOOST_NOEXCEPT_OR_NOTHROW=noexcept \\
|
||||
BOOST_COPY_ASSIGN_REF(x)=\"x const&\" \\
|
||||
BOOST_DEFAULTED_FUNCTION(x,y)=\"x = default;\" \\
|
||||
BOOST_DELETED_FUNCTION(x)=\"x = delete;\" \\
|
||||
BOOST_EXPLICIT_OPERATOR_BOOL()=\"explicit operator bool() const;\" \\
|
||||
BOOST_REF_CONST=const"
|
||||
<doxygen:param>"EXCLUDE_SYMBOLS= \\
|
||||
detail \\
|
||||
F \\
|
||||
result_of_has_result_type_impl \\
|
||||
conditional \\
|
||||
boost::operators_impl"
|
||||
<xsl:param>"boost.doxygen.reftitle=Reference"
|
||||
<xsl:param>"boost.doxygen.refid=in_place_factory.reference"
|
||||
;
|
||||
|
||||
# Generate XML doxygen reference for operators component in operators_reference.xml
|
||||
# we skip operators_reference because operators.hpp is not adapted for doxygen
|
||||
|
||||
# Generate XML doxygen reference for result_of component in result_of_reference.xml
|
||||
doxygen result_of_reference
|
||||
:
|
||||
$(INCLUDES)/boost/utility/result_of.hpp
|
||||
:
|
||||
<location>tmp
|
||||
<doxygen:param>ENABLE_PREPROCESSING=YES
|
||||
<doxygen:param>EXPAND_ONLY_PREDEF=YES
|
||||
<doxygen:param>EXTRACT_ALL=NO
|
||||
<doxygen:param>EXTRACT_PRIVATE=NO
|
||||
<doxygen:param>HIDE_UNDOC_MEMBERS=YES
|
||||
<doxygen:param>MACRO_EXPANSION=YES
|
||||
<doxygen:param>"PREDEFINED= \\
|
||||
BOOST_UTILITY_DOCS \\
|
||||
BOOST_SYMBOL_VISIBLE= \\
|
||||
BOOST_FORCEINLINE=inline \\
|
||||
BOOST_GPU_ENABLED= \\
|
||||
BOOST_STATIC_ASSERT(x)= \\
|
||||
BOOST_STATIC_ASSERT_MSG(x,y)= \\
|
||||
BOOST_STATIC_CONSTANT(x,y)=\"static constexpr x y\" \\
|
||||
BOOST_RV_REF(x)=\"x&&\" \\
|
||||
BOOST_NESTED_TEMPLATE=template \\
|
||||
BOOST_CONSTEXPR=constexpr \\
|
||||
BOOST_CXX14_CONSTEXPR=constexpr \\
|
||||
BOOST_OPERATORS_CONSTEXPR=constexpr \\
|
||||
BOOST_CONSTEXPR_OR_CONST=constexpr \\
|
||||
BOOST_NOEXCEPT=noexcept \\
|
||||
BOOST_NOEXCEPT_IF(x)=noexcept(x) \\
|
||||
BOOST_NOEXCEPT_OR_NOTHROW=noexcept \\
|
||||
BOOST_COPY_ASSIGN_REF(x)=\"x const&\" \\
|
||||
BOOST_DEFAULTED_FUNCTION(x,y)=\"x = default;\" \\
|
||||
BOOST_DELETED_FUNCTION(x)=\"x = delete;\" \\
|
||||
BOOST_EXPLICIT_OPERATOR_BOOL()=\"explicit operator bool() const;\" \\
|
||||
BOOST_REF_CONST=const"
|
||||
<doxygen:param>"EXCLUDE_SYMBOLS= \\
|
||||
detail \\
|
||||
F \\
|
||||
result_of_has_result_type_impl \\
|
||||
conditional \\
|
||||
boost::operators_impl"
|
||||
<xsl:param>"boost.doxygen.reftitle=Reference"
|
||||
<xsl:param>"boost.doxygen.refid=result_of.reference"
|
||||
;
|
||||
|
||||
# Generate XML doxygen reference for string_view component in string_view_reference.xml
|
||||
doxygen string_view_reference
|
||||
:
|
||||
$(INCLUDES)/boost/utility/string_view.hpp
|
||||
:
|
||||
<location>tmp
|
||||
<doxygen:param>ENABLE_PREPROCESSING=YES
|
||||
<doxygen:param>EXPAND_ONLY_PREDEF=YES
|
||||
<doxygen:param>EXTRACT_ALL=NO
|
||||
<doxygen:param>EXTRACT_PRIVATE=NO
|
||||
<doxygen:param>HIDE_UNDOC_MEMBERS=YES
|
||||
<doxygen:param>MACRO_EXPANSION=YES
|
||||
<doxygen:param>"PREDEFINED= \\
|
||||
BOOST_UTILITY_DOCS \\
|
||||
BOOST_SYMBOL_VISIBLE= \\
|
||||
BOOST_FORCEINLINE=inline \\
|
||||
BOOST_GPU_ENABLED= \\
|
||||
BOOST_STATIC_ASSERT(x)= \\
|
||||
BOOST_STATIC_ASSERT_MSG(x,y)= \\
|
||||
BOOST_STATIC_CONSTANT(x,y)=\"static constexpr x y\" \\
|
||||
BOOST_RV_REF(x)=\"x&&\" \\
|
||||
BOOST_NESTED_TEMPLATE=template \\
|
||||
BOOST_CONSTEXPR=constexpr \\
|
||||
BOOST_CXX14_CONSTEXPR=constexpr \\
|
||||
BOOST_OPERATORS_CONSTEXPR=constexpr \\
|
||||
BOOST_CONSTEXPR_OR_CONST=constexpr \\
|
||||
BOOST_NOEXCEPT=noexcept \\
|
||||
BOOST_NOEXCEPT_IF(x)=noexcept(x) \\
|
||||
BOOST_NOEXCEPT_OR_NOTHROW=noexcept \\
|
||||
BOOST_COPY_ASSIGN_REF(x)=\"x const&\" \\
|
||||
BOOST_DEFAULTED_FUNCTION(x,y)=\"x = default;\" \\
|
||||
BOOST_DELETED_FUNCTION(x)=\"x = delete;\" \\
|
||||
BOOST_EXPLICIT_OPERATOR_BOOL()=\"explicit operator bool() const;\" \\
|
||||
BOOST_REF_CONST=const"
|
||||
<doxygen:param>"EXCLUDE_SYMBOLS= \\
|
||||
detail \\
|
||||
F \\
|
||||
result_of_has_result_type_impl \\
|
||||
conditional \\
|
||||
boost::operators_impl"
|
||||
<xsl:param>"boost.doxygen.reftitle=Reference"
|
||||
<xsl:param>"boost.doxygen.refid=string_view.reference"
|
||||
;
|
||||
|
||||
# Generate XML doxygen reference for value_init component in value_init_reference.xml
|
||||
doxygen value_init_reference
|
||||
:
|
||||
$(INCLUDES)/boost/utility/value_init.hpp
|
||||
:
|
||||
<location>tmp
|
||||
<doxygen:param>ENABLE_PREPROCESSING=YES
|
||||
<doxygen:param>EXPAND_ONLY_PREDEF=YES
|
||||
<doxygen:param>EXTRACT_ALL=NO
|
||||
<doxygen:param>EXTRACT_PRIVATE=NO
|
||||
<doxygen:param>HIDE_UNDOC_MEMBERS=YES
|
||||
<doxygen:param>MACRO_EXPANSION=YES
|
||||
<doxygen:param>"PREDEFINED= \\
|
||||
BOOST_UTILITY_DOCS \\
|
||||
BOOST_SYMBOL_VISIBLE= \\
|
||||
BOOST_FORCEINLINE=inline \\
|
||||
BOOST_GPU_ENABLED= \\
|
||||
BOOST_STATIC_ASSERT(x)= \\
|
||||
BOOST_STATIC_ASSERT_MSG(x,y)= \\
|
||||
BOOST_STATIC_CONSTANT(x,y)=\"static constexpr x y\" \\
|
||||
BOOST_RV_REF(x)=\"x&&\" \\
|
||||
BOOST_NESTED_TEMPLATE=template \\
|
||||
BOOST_CONSTEXPR=constexpr \\
|
||||
BOOST_CXX14_CONSTEXPR=constexpr \\
|
||||
BOOST_OPERATORS_CONSTEXPR=constexpr \\
|
||||
BOOST_CONSTEXPR_OR_CONST=constexpr \\
|
||||
BOOST_NOEXCEPT=noexcept \\
|
||||
BOOST_NOEXCEPT_IF(x)=noexcept(x) \\
|
||||
BOOST_NOEXCEPT_OR_NOTHROW=noexcept \\
|
||||
BOOST_COPY_ASSIGN_REF(x)=\"x const&\" \\
|
||||
BOOST_DEFAULTED_FUNCTION(x,y)=\"x = default;\" \\
|
||||
BOOST_DELETED_FUNCTION(x)=\"x = delete;\" \\
|
||||
BOOST_EXPLICIT_OPERATOR_BOOL()=\"explicit operator bool() const;\" \\
|
||||
BOOST_REF_CONST=const"
|
||||
<doxygen:param>"EXCLUDE_SYMBOLS= \\
|
||||
detail \\
|
||||
F \\
|
||||
result_of_has_result_type_impl \\
|
||||
conditional \\
|
||||
boost::operators_impl"
|
||||
<xsl:param>"boost.doxygen.reftitle=Reference"
|
||||
<xsl:param>"boost.doxygen.refid=value_init.reference"
|
||||
;
|
||||
|
||||
# Generate main.xml boostbook documentation from main.qbk quickbook documentation
|
||||
xml main : main.qbk ;
|
||||
|
||||
# Generate ./html documentation from main.xml boostbook documentation
|
||||
# Each doxygen reference in quickbook files with [xinclude tmp/<component>_reference.xml] becomes:
|
||||
# <xi:include href="../../../../libs/utility/doc/tmp/<component>_reference.xml"/>
|
||||
# in boostbook.
|
||||
# All of these <xi:include> commands give the reference the id "utility.reference"
|
||||
boostbook standalone_main
|
||||
:
|
||||
declval
|
||||
main
|
||||
:
|
||||
<dependency>base_from_member_reference
|
||||
<dependency>boost_binary_reference
|
||||
<dependency>call_traits_reference
|
||||
<dependency>compressed_pair_reference
|
||||
<dependency>in_place_factory_reference
|
||||
<dependency>result_of_reference
|
||||
<dependency>string_view_reference
|
||||
<dependency>value_init_reference
|
||||
# File name of HTML output:
|
||||
<xsl:param>root.filename=declval
|
||||
# How far down we chunk nested sections, basically all of them:
|
||||
<xsl:param>chunk.section.depth=0
|
||||
# <xsl:param>root.filename=main
|
||||
<xsl:param>boost.root=../../../..
|
||||
<format>pdf:<xsl:param>"boost.url.prefix=http://www.boost.org/doc/libs/release/libs/utility/doc/html"
|
||||
# How far down we chunk nested sections: no more than two so utility component pages include their reference
|
||||
<xsl:param>chunk.section.depth=2 # 8
|
||||
# Don't put the first section on the same page as the TOC:
|
||||
<xsl:param>chunk.first.sections=0
|
||||
# How far down sections get TOC's
|
||||
<xsl:param>toc.section.depth=1
|
||||
# Max depth in each TOC:
|
||||
<xsl:param>toc.max.depth=1
|
||||
# How far down we go with TOC's
|
||||
<xsl:param>generate.section.toc.level=1
|
||||
<xsl:param>chunk.first.sections=1 # 1
|
||||
# How far down sections get TOC: 2 so we show each Utility component in main page but no more than that
|
||||
<xsl:param>toc.section.depth=2 # 2
|
||||
# Max depth in each TOC: 2 so we show each Utility component in main page but no more than that
|
||||
<xsl:param>toc.max.depth=2 # 2
|
||||
# How far down we go with TOC's in main page: 2 so each Utility component page has 1 level TOC
|
||||
<xsl:param>generate.section.toc.level=2 # 2
|
||||
;
|
||||
|
||||
xml string_ref : string_ref.qbk ;
|
||||
boostbook standalone_string_ref
|
||||
:
|
||||
string_ref
|
||||
:
|
||||
# File name of HTML output:
|
||||
<xsl:param>root.filename=string_ref
|
||||
# How far down we chunk nested sections, basically all of them:
|
||||
<xsl:param>chunk.section.depth=0
|
||||
# Don't put the first section on the same page as the TOC:
|
||||
<xsl:param>chunk.first.sections=0
|
||||
# How far down sections get TOC's
|
||||
<xsl:param>toc.section.depth=1
|
||||
# Max depth in each TOC:
|
||||
<xsl:param>toc.max.depth=1
|
||||
# How far down we go with TOC's
|
||||
<xsl:param>generate.section.toc.level=1
|
||||
;
|
||||
###############################################################################
|
||||
alias boostdoc ;
|
||||
explicit boostdoc ;
|
||||
|
||||
xml explicit_operator_bool : explicit_operator_bool.qbk ;
|
||||
boostbook standalone_explicit_operator_bool
|
||||
:
|
||||
explicit_operator_bool
|
||||
:
|
||||
# File name of HTML output:
|
||||
<xsl:param>root.filename=explicit_operator_bool
|
||||
# How far down we chunk nested sections, basically all of them:
|
||||
<xsl:param>chunk.section.depth=0
|
||||
# Don't put the first section on the same page as the TOC:
|
||||
<xsl:param>chunk.first.sections=0
|
||||
# How far down sections get TOC's
|
||||
<xsl:param>toc.section.depth=1
|
||||
# Max depth in each TOC:
|
||||
<xsl:param>toc.max.depth=1
|
||||
# How far down we go with TOC's
|
||||
<xsl:param>generate.section.toc.level=1
|
||||
;
|
||||
alias boostrelease : standalone_main ;
|
||||
explicit boostrelease ;
|
||||
|
376
doc/base_from_member.qbk
Normal file
376
doc/base_from_member.qbk
Normal file
@ -0,0 +1,376 @@
|
||||
[/
|
||||
Copyright 2001, 2003, 2004, 2012 Daryle Walker.
|
||||
Copyright (c) 2021, Alan Freitas
|
||||
|
||||
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
|
||||
]
|
||||
|
||||
[section:base_from_member Base from Member]
|
||||
[block'''<?dbhtml stop-chunking?>''']
|
||||
|
||||
[section Introduction]
|
||||
|
||||
The class templates __base_from_member__ support the base-from-member idiom.
|
||||
When developing a class, sometimes a base class needs to be initialized
|
||||
with a member of the current class. As a na\u00EFve example:
|
||||
|
||||
```
|
||||
#include <streambuf> /* for std::streambuf */
|
||||
#include <ostream> /* for std::ostream */
|
||||
|
||||
class fdoutbuf
|
||||
: public __std_streambuf__
|
||||
{
|
||||
public:
|
||||
explicit fdoutbuf( int fd );
|
||||
//...
|
||||
};
|
||||
|
||||
class fdostream
|
||||
: public __std_ostream__
|
||||
{
|
||||
protected:
|
||||
fdoutbuf buf;
|
||||
public:
|
||||
explicit fdostream( int fd )
|
||||
: buf( fd ), __std_ostream__( &buf ) {}
|
||||
//...
|
||||
};
|
||||
```
|
||||
|
||||
This is undefined because C++'s initialization order mandates that the base
|
||||
class is initialized before the member it uses. [@http://www.moocat.org R.
|
||||
Samuel Klatchko] developed a way around this by using the initialization
|
||||
order in his favor. Base classes are initialized in order of declaration, so
|
||||
moving the desired member to another base class, that is initialized before
|
||||
the desired base class, can ensure proper initialization.
|
||||
|
||||
A custom base class can be made for this idiom:
|
||||
|
||||
#include <streambuf> /* for std::streambuf */
|
||||
#include <ostream> /* for std::ostream */
|
||||
|
||||
class fdoutbuf
|
||||
: public __std_streambuf__
|
||||
{
|
||||
public:
|
||||
explicit fdoutbuf( int fd );
|
||||
//...
|
||||
};
|
||||
|
||||
struct fdostream_pbase
|
||||
{
|
||||
fdoutbuf sbuffer;
|
||||
|
||||
explicit fdostream_pbase( int fd )
|
||||
: sbuffer( fd ) {}
|
||||
};
|
||||
|
||||
class fdostream
|
||||
: private fdostream_pbase
|
||||
, public __std_ostream__
|
||||
{
|
||||
typedef fdostream_pbase pbase_type;
|
||||
typedef __std_ostream__ base_type;
|
||||
|
||||
public:
|
||||
explicit fdostream( int fd )
|
||||
: pbase_type( fd ), base_type( &sbuffer ) {}
|
||||
//...
|
||||
};
|
||||
|
||||
Other projects can use similar custom base classes. The technique is basic
|
||||
enough to make a template, with a sample template class in this library.
|
||||
The main template parameter is the type of the enclosed member. The
|
||||
template class has several (explicit) constructor member templates, which
|
||||
implicitly type the constructor arguments and pass them to the member. The
|
||||
template class uses implicit copy construction and assignment, cancelling
|
||||
them if the enclosed member is non-copyable.
|
||||
|
||||
Manually coding a base class may be better if the construction and/or
|
||||
copying needs are too complex for the supplied template class, or if the
|
||||
compiler is not advanced enough to use it.
|
||||
|
||||
Since base classes are unnamed, a class cannot have multiple (direct) base
|
||||
classes of the same type. The supplied template class has an extra template
|
||||
parameter, an integer, that exists solely to provide type differentiation.
|
||||
This parameter has a default value so a single use of a particular member
|
||||
type does not need to concern itself with the integer.
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Synopsis]
|
||||
|
||||
#include <type_traits> /* exposition only */
|
||||
|
||||
#ifndef BOOST_BASE_FROM_MEMBER_MAX_ARITY
|
||||
#define BOOST_BASE_FROM_MEMBER_MAX_ARITY 10
|
||||
#endif
|
||||
|
||||
template < typename MemberType, int UniqueID = 0 >
|
||||
class __base_from_member__
|
||||
{
|
||||
protected:
|
||||
MemberType member;
|
||||
|
||||
#if ``['C++11 is in use]``
|
||||
template< typename ...T >
|
||||
explicit constexpr __base_from_member__( T&& ...x )
|
||||
noexcept( __std_is_nothrow_constructible__<MemberType, T...>::value );
|
||||
#else
|
||||
__base_from_member__();
|
||||
|
||||
template< typename T1 >
|
||||
explicit __base_from_member__( T1 x1 );
|
||||
|
||||
template< typename T1, typename T2 >
|
||||
__base_from_member__( T1 x1, T2 x2 );
|
||||
|
||||
//...
|
||||
|
||||
template< typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6, typename T7, typename T8, typename T9,
|
||||
typename T10 >
|
||||
__base_from_member__( T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, T6 x6, T7 x7,
|
||||
T8 x8, T9 x9, T10 x10 );
|
||||
#endif
|
||||
};
|
||||
|
||||
template < typename MemberType, int UniqueID >
|
||||
class __base_from_member__<MemberType&, UniqueID>
|
||||
{
|
||||
protected:
|
||||
MemberType& member;
|
||||
|
||||
explicit constexpr __base_from_member__( MemberType& x )
|
||||
noexcept;
|
||||
};
|
||||
|
||||
The class template has a first template parameter `MemberType` representing
|
||||
the type of the based-member. It has a last template parameter `UniqueID`,
|
||||
that is an `int`, to differentiate between multiple base classes that use
|
||||
the same based-member type. The last template parameter has a default value
|
||||
of zero if it is omitted. The class template has a protected data member
|
||||
called `member` that the derived class can use for later base classes or
|
||||
itself.
|
||||
|
||||
If the appropriate features of C++11 are present, there will be a single
|
||||
constructor template. It implements ['perfect forwarding] to the best
|
||||
constructor call of `member` if any. The constructor template is marked
|
||||
both `constexpr` and `explicit`. The former will be ignored if the
|
||||
corresponding inner constructor call of `member` does not have the marker.
|
||||
The latter binds the other way; always taking effect, even when the inner
|
||||
constructor call does not have the marker. The constructor template
|
||||
propagates the `noexcept` status of the inner constructor call. The
|
||||
constructor template has a trailing parameter with a default value that
|
||||
disables the template when its signature is too close to the signatures of
|
||||
the automatically-defined non-template copy- and/or move-constructors of
|
||||
__base_from_member__.
|
||||
|
||||
On earlier-standard compilers, there is a default constructor and several
|
||||
constructor member templates. These constructor templates can take as many
|
||||
arguments (currently up to ten) as possible and pass them to a constructor
|
||||
of the data member.
|
||||
|
||||
A specialization for member references offers a single constructor taking
|
||||
a `MemberType&`, which is the only way to initialize a reference.
|
||||
|
||||
Since C++ does not allow any way to explicitly state the template parameters
|
||||
of a templated constructor, make sure that the arguments are already close
|
||||
as possible to the actual type used in the data member's desired constructor.
|
||||
Explicit conversions may be necessary.
|
||||
|
||||
The `BOOST_BASE_FROM_MEMBER_MAX_ARITY` macro constant specifies the maximum
|
||||
argument length for the constructor templates. The constant may be overridden
|
||||
if more (or less) argument configurations are needed. The constant may be
|
||||
read for code that is expandable like the class template and needs to
|
||||
maintain the same maximum size. (Example code would be a class that uses
|
||||
this class template as a base class for a member with a flexible set of
|
||||
constructors.) This constant is ignored when C++11 features are present.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Basic Usage]
|
||||
|
||||
With the starting example, the `fdoutbuf` sub-object needs to be
|
||||
encapsulated in a base class that is inherited before `__std_ostream__`.
|
||||
|
||||
```
|
||||
#include <boost/utility/base_from_member.hpp>
|
||||
|
||||
#include <streambuf> // for std::streambuf
|
||||
#include <ostream> // for __std_ostream__
|
||||
|
||||
class fdoutbuf
|
||||
: public __std_streambuf__
|
||||
{
|
||||
public:
|
||||
explicit fdoutbuf( int fd );
|
||||
//...
|
||||
};
|
||||
|
||||
class fdostream
|
||||
: private __boost_base_from_member__<fdoutbuf>
|
||||
, public __std_ostream__
|
||||
{
|
||||
// Helper typedef's
|
||||
typedef __boost_base_from_member__<fdoutbuf> pbase_type;
|
||||
typedef __std_ostream__ base_type;
|
||||
|
||||
public:
|
||||
explicit fdostream( int fd )
|
||||
: pbase_type( fd ), base_type( &member ){}
|
||||
//...
|
||||
};
|
||||
```
|
||||
|
||||
The base-from-member idiom is an implementation detail, so it should not
|
||||
be visible to the clients (or any derived classes) of `fdostream`. Due to
|
||||
the initialization order, the `fdoutbuf` sub-object will get initialized
|
||||
before the `__std_ostream__` sub-object does, making the former sub-object
|
||||
safe to use in the latter sub-object's construction. Since the `fdoutbuf`
|
||||
sub-object of the final type is the only sub-object with the name `member`
|
||||
that name can be used unqualified within the final class.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Multiple Sub-Objects]
|
||||
|
||||
The base-from-member class templates should commonly involve only one
|
||||
base-from-member sub-object, usually for attaching a stream-buffer to an
|
||||
I/O stream. The next example demonstrates how to use multiple
|
||||
base-from-member sub-objects and the resulting qualification issues.
|
||||
|
||||
```
|
||||
#include <boost/utility/base_from_member.hpp>
|
||||
|
||||
#include <cstddef> /* for NULL */
|
||||
|
||||
struct an_int
|
||||
{
|
||||
int y;
|
||||
|
||||
an_int( float yf );
|
||||
};
|
||||
|
||||
class switcher
|
||||
{
|
||||
public:
|
||||
switcher();
|
||||
switcher( double, int * );
|
||||
//...
|
||||
};
|
||||
|
||||
class flow_regulator
|
||||
{
|
||||
public:
|
||||
flow_regulator( switcher &, switcher & );
|
||||
//...
|
||||
};
|
||||
|
||||
template < unsigned Size >
|
||||
class fan
|
||||
{
|
||||
public:
|
||||
explicit fan( switcher );
|
||||
//...
|
||||
};
|
||||
|
||||
class system
|
||||
: private __boost_base_from_member__<an_int>
|
||||
, private __boost_base_from_member__<switcher>
|
||||
, private __boost_base_from_member__<switcher, 1>
|
||||
, private __boost_base_from_member__<switcher, 2>
|
||||
, protected flow_regulator
|
||||
, public fan<6>
|
||||
{
|
||||
// Helper typedef's
|
||||
typedef __boost_base_from_member__<an_int> pbase0_type;
|
||||
typedef __boost_base_from_member__<switcher> pbase1_type;
|
||||
typedef __boost_base_from_member__<switcher, 1> pbase2_type;
|
||||
typedef __boost_base_from_member__<switcher, 2> pbase3_type;
|
||||
|
||||
typedef flow_regulator base1_type;
|
||||
typedef fan<6> base2_type;
|
||||
|
||||
public:
|
||||
system( double x );
|
||||
//...
|
||||
};
|
||||
|
||||
system::system( double x )
|
||||
: pbase0_type( 0.2 )
|
||||
, pbase1_type()
|
||||
, pbase2_type( -16, &this->pbase0_type::member.y )
|
||||
, pbase3_type( x, static_cast<int *>(NULL) )
|
||||
, base1_type( pbase3_type::member, pbase1_type::member )
|
||||
, base2_type( pbase2_type::member )
|
||||
{
|
||||
//...
|
||||
}
|
||||
```
|
||||
|
||||
The final class has multiple sub-objects with the name `member`, so any
|
||||
use of that name needs qualification by a name of the appropriate base
|
||||
type. Using `typedef`s ease mentioning the base types.
|
||||
|
||||
However, the fix introduces a new problem when a pointer is needed. Using the
|
||||
address operator with a sub-object qualified with its class's name results in a
|
||||
pointer-to-member (here, having a type of `an_int __boost_base_from_member__<an_int, 0>::*`)
|
||||
instead of a pointer to the member (having a type of `an_int*`).
|
||||
The new problem is fixed by qualifying the sub-object with `this->` and is needed
|
||||
just for pointers, and not for references or values.
|
||||
|
||||
There are some argument conversions in the initialization. The constructor
|
||||
argument for `pbase0_type` is converted from `double` to `float`. The first
|
||||
constructor argument for `pbase2_type` is converted from `int` to `double`.
|
||||
|
||||
The second constructor argument for `pbase3_type` is a special case of
|
||||
necessary conversion; all forms of the null-pointer literal in C++ (except
|
||||
`nullptr` from C++11) also look like compile-time integral expressions, so
|
||||
C++ always interprets such code as an integer when it has overloads that can
|
||||
take either an integer or a pointer.
|
||||
|
||||
The last conversion is necessary for the compiler to call a constructor form
|
||||
with the exact pointer type used in `switcher`'s constructor. (If C++11's
|
||||
__nullptr__ is used, it still needs a conversion if multiple pointer types can
|
||||
be accepted in a constructor call but `__std_nullptr_t__` cannot.)
|
||||
|
||||
[endsect]
|
||||
|
||||
[/===============]
|
||||
[xinclude tmp/base_from_member_reference.xml]
|
||||
[/===============]
|
||||
|
||||
[section Acknowledgments]
|
||||
|
||||
Author: Walker, Daryle
|
||||
|
||||
Copyright 2001, 2003, 2004, 2012 Daryle Walker
|
||||
|
||||
* [@http://www.boost.org/people/ed_brey.htm Ed Brey] suggested some interface
|
||||
changes.
|
||||
|
||||
* [@http://www.moocat.org R. Samuel Klatchko] ([@mailto:rsk@moocat.org
|
||||
rsk@moocat.org], [@mailto:rsk@brightmail.com rsk@brightmail.com]) invented
|
||||
the idiom of how to use a class member for initializing a base class.
|
||||
|
||||
* [@http://www.boost.org/people/dietmar_kuehl.htm Dietmar Kuehl] popularized the
|
||||
base-from-member idiom in his [@http://www.informatik.uni-konstanz.de/~kuehl/c++/iostream/
|
||||
IOStream example classes].
|
||||
|
||||
* Jonathan Turkanis supplied an implementation of generating the constructor
|
||||
templates that can be controlled and automated with macros. The
|
||||
implementation uses the [@boost:/libs/preprocessor/index.html Preprocessor library].
|
||||
|
||||
* [@http://www.boost.org/people/daryle_walker.html">Daryle Walker] started the
|
||||
library. Contributed the test file [@../../../test/base_from_member_test.cpp
|
||||
base_from_member_test.cpp].
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
443
doc/call_traits.qbk
Normal file
443
doc/call_traits.qbk
Normal file
@ -0,0 +1,443 @@
|
||||
[/
|
||||
/ Copyright (c) 2012 Marshall Clow
|
||||
/ Copyright (c) 2021, Alan Freitas
|
||||
/
|
||||
/ 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 Call Traits]
|
||||
[/===============]
|
||||
|
||||
[section Introduction]
|
||||
|
||||
All of the contents of [@../../../../boost/call_traits.hpp `<boost/call_traits.hpp>`] are
|
||||
defined inside `namespace boost`.
|
||||
|
||||
The template class __call_traits_T__ encapsulates the
|
||||
"best" method to pass a parameter of some type `T` to or
|
||||
from a function, and consists of a collection of `typedef`s defined
|
||||
as in the table below. The purpose of __call_traits__ is to ensure
|
||||
that problems like [link sec:refs "references to references"]
|
||||
never occur, and that parameters are passed in the most efficient
|
||||
manner possible, as in the [link sec:examples examples]. In each
|
||||
case, if your existing practice is to use the type defined on the
|
||||
left, then replace it with the __call_traits__ defined type on the
|
||||
right.
|
||||
|
||||
Note that for compilers that do not support either partial
|
||||
specialization or member templates, no benefit will occur from
|
||||
using __call_traits__: the __call_traits__ defined types will always be
|
||||
the same as the existing practice in this case. In addition if
|
||||
only member templates and not partial template specialisation is
|
||||
support by the compiler (for example Visual C++ 6) then
|
||||
__call_traits__ cannot be used with array types, although it can still be
|
||||
used to solve the reference to reference problem.
|
||||
|
||||
[table __call_traits__ types
|
||||
[[Existing practice] [__call_traits__ equivalent] [Description] [Notes]]
|
||||
[
|
||||
[`T`
|
||||
|
||||
(return by value)
|
||||
]
|
||||
[
|
||||
__call_traits_T__`::value_type`
|
||||
]
|
||||
[
|
||||
Defines a type that represents the "value" of type `T`.
|
||||
|
||||
Use this for functions that return by value, or possibly for stored values of type `T`.
|
||||
]
|
||||
[2]
|
||||
]
|
||||
[
|
||||
[`T&`
|
||||
|
||||
(return value)
|
||||
]
|
||||
[
|
||||
__call_traits_T__`::reference`
|
||||
]
|
||||
[
|
||||
Defines a type that represents a reference to type `T`.
|
||||
|
||||
Use for functions that would normally return a `T&`.
|
||||
]
|
||||
[1]
|
||||
]
|
||||
[
|
||||
[`const T&`
|
||||
|
||||
(return value)
|
||||
]
|
||||
[
|
||||
__call_traits_T__`::const_reference`
|
||||
]
|
||||
[
|
||||
Defines a type that represents a constant reference to type `T`.
|
||||
|
||||
Use for functions that would normally return a `const T&`.
|
||||
]
|
||||
[1]
|
||||
]
|
||||
[
|
||||
[`const T&`
|
||||
|
||||
(function parameter)
|
||||
]
|
||||
[
|
||||
__call_traits_T__`::param_type`
|
||||
]
|
||||
[
|
||||
Defines a type that represents the "best" way to pass a parameter of type `T` to a function.
|
||||
]
|
||||
[1,3]
|
||||
]
|
||||
]
|
||||
|
||||
Notes:
|
||||
|
||||
# If `T` is already reference type, then __call_traits__ is
|
||||
defined such that [link sec:refs "references to references"]
|
||||
do not occur (requires partial specialization).
|
||||
# If `T` is an array type, then __call_traits__ defines `value_type`
|
||||
as a "constant pointer to type" rather than an
|
||||
"array of type" (requires partial specialization).
|
||||
Note that if you are using `value_type` as a stored value
|
||||
then this will result in storing a "constant pointer to
|
||||
an array" rather than the array itself. This may or may
|
||||
not be a good thing depending upon what you actually
|
||||
need (in other words take care!).
|
||||
# If `T` is a small built in type or a pointer, then `param_type`
|
||||
is defined as `T const`, instead of `T const&`. This can
|
||||
improve the ability of the compiler to optimize loops in
|
||||
the body of the function if they depend upon the passed
|
||||
parameter, the semantics of the passed parameter is
|
||||
otherwise unchanged (requires partial specialization).
|
||||
|
||||
|
||||
[endsect]
|
||||
[section Copy constructibility]
|
||||
|
||||
The following table defines which __call_traits__ types can always
|
||||
be copy-constructed from which other types:
|
||||
|
||||
[table Which __call_traits__ types can always be copy-constructed from which other types
|
||||
[[] [To `T`] [To `value_type`] [To `reference`] [To `const_reference`] [To `param_type`]]
|
||||
[[From `T`] [iff `T` is copy constructible] [iff `T` is copy constructible] [Yes] [Yes] [Yes]]
|
||||
[[From `value_type`] [iff `T` is copy constructible] [iff `T` is copy constructible] [No] [No] [Yes]]
|
||||
[[From `reference`] [iff `T` is copy constructible] [iff `T` is copy constructible] [Yes] [Yes] [Yes]]
|
||||
[[From `const_reference`] [iff `T` is copy constructible] [No] [No] [Yes] [Yes]]
|
||||
[[From `param_type`] [iff `T` is copy constructible] [iff `T` is copy constructible] [No] [No] [Yes]]
|
||||
]
|
||||
|
||||
If `T` is an assignable type the following assignments are possible:
|
||||
|
||||
[table Which __call_traits__ types are assignable from which other types
|
||||
[[] [To `T`] [To `value_type`] [To `reference`] [To `const_reference`] [To `param_type`]]
|
||||
[[From `T`] [Yes] [Yes] [-] [-] [-]]
|
||||
[[From `value_type`] [Yes] [Yes] [-] [-] [-]]
|
||||
[[From `reference`] [Yes] [Yes] [-] [-] [-]]
|
||||
[[From `const_reference`] [Yes] [Yes] [-] [-] [-]]
|
||||
[[From `param_type`] [Yes] [Yes] [-] [-] [-]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[#sec:examples]
|
||||
[section Examples]
|
||||
|
||||
The following table shows the effect that __call_traits__ has on
|
||||
various types.
|
||||
|
||||
[table Examples of __call_traits__ types
|
||||
[[] [__call_traits__::`value_type`] [__call_traits__::`reference`] [__call_traits__::`const_reference`] [__call_traits__::`param_type`] [Applies to:]]
|
||||
[[From `my_class`] [`my_class`] [`my_class&`] [`const my_class&`] [`my_class const&`] [All user-defined types]]
|
||||
[[From `int`] [`int`] [`int&`] [`const int&`] [`int const`] [All small built-in types]]
|
||||
[[From `int*`] [`int*`] [`int*&`] [`int* const &`] [`int* const`] [All pointer types]]
|
||||
[[From `int&`] [`int&`] [`int&`] [`const int&`] [`int&`] [All reference types]]
|
||||
[[From `const int&`] [`const int&`] [`const int&`] [`const int&`] [`const int&`] [All constant reference types]]
|
||||
[[From `int[3]`] [`const int*`] [`int(&)[3]`] [`const int(&)[3]`] [`const int* const`] [All array types]]
|
||||
[[From `const int[3]`] [`const int*`] [`const int(&)[3]`] [`const int(&)[3]`] [`const int* const`] [All constant array types]]
|
||||
]
|
||||
|
||||
The table assumes the compiler supports partial
|
||||
specialization: if it does not then all types behave in
|
||||
the same way as the entry for "`my_class`", and
|
||||
__call_traits__ can not be used with reference or array types.
|
||||
|
||||
[section Example 1:]
|
||||
|
||||
The following class is a trivial class that stores some type `T`
|
||||
by value (see the [@../../../test/call_traits_test.cpp `call_traits_test.cpp`]
|
||||
file). The aim is to illustrate how each of the available
|
||||
__call_traits__ `typedef`s may be used:
|
||||
|
||||
```
|
||||
template <class T>
|
||||
struct contained
|
||||
{
|
||||
// define our typedefs first, arrays are stored by value
|
||||
// so value_type is not the same as result_type:
|
||||
typedef typename __boost_call_traits__<T>::param_type param_type;
|
||||
typedef typename __boost_call_traits__<T>::reference reference;
|
||||
typedef typename __boost_call_traits__<T>::const_reference const_reference;
|
||||
typedef T value_type;
|
||||
typedef typename __boost_call_traits__<T>::value_type result_type;
|
||||
|
||||
// stored value:
|
||||
value_type v_;
|
||||
|
||||
// constructors:
|
||||
contained() {}
|
||||
contained(param_type p) : v_(p){}
|
||||
// return byval:
|
||||
result_type value() { return v_; }
|
||||
// return by_ref:
|
||||
reference get() { return v_; }
|
||||
const_reference const_get()const { return v_; }
|
||||
// pass value:
|
||||
void call(param_type p){}
|
||||
|
||||
};
|
||||
```
|
||||
[endsect]
|
||||
|
||||
[#sec:refs]
|
||||
[section Example 2 (the reference to reference problem):]
|
||||
|
||||
Consider the definition of __std_binder1st__:
|
||||
|
||||
```
|
||||
template <class Operation>
|
||||
class binder1st :
|
||||
public __std_unary_function__<typename Operation::second_argument_type, typename Operation::result_type>
|
||||
{
|
||||
protected:
|
||||
Operation op;
|
||||
typename Operation::first_argument_type value;
|
||||
public:
|
||||
binder1st(const Operation& x, const typename Operation::first_argument_type& y);
|
||||
typename Operation::result_type operator()(const typename Operation::second_argument_type& x) const;
|
||||
};
|
||||
```
|
||||
|
||||
Now consider what happens in the relatively common case that
|
||||
the functor takes its second argument as a reference, that
|
||||
implies that `Operation::second_argument_type` is a
|
||||
reference type, `operator()` will now end up taking a
|
||||
reference to a reference as an argument, and that is not
|
||||
currently legal. The solution here is to modify `operator()`
|
||||
to use __call_traits__:
|
||||
|
||||
```
|
||||
typename Operation::result_type operator()(typename __call_traits__<typename Operation::second_argument_type>::param_type x) const;
|
||||
```
|
||||
|
||||
Now in the case that `Operation::second_argument_type`
|
||||
is a reference type, the argument is passed as a reference, and
|
||||
the no "reference to reference" occurs.
|
||||
|
||||
[endsect]
|
||||
|
||||
[#sec:example3]
|
||||
[section Example 3 (the `make_pair` problem):]
|
||||
|
||||
If we pass the name of an array as one (or both) arguments to `__std_make_pair__`,
|
||||
then template argument deduction deduces the passed parameter as
|
||||
"const reference to array of `T`", this also applies to
|
||||
string literals (which are really array literals). Consequently
|
||||
instead of returning a pair of pointers, it tries to return a
|
||||
pair of arrays, and since an array type is not copy-constructible
|
||||
the code fails to compile. One solution is to explicitly cast the
|
||||
arguments to __std_make_pair__ to pointers, but __call_traits__ provides a
|
||||
better automatic solution that works safely even in generic code where the
|
||||
cast might do the wrong thing:
|
||||
|
||||
```
|
||||
template <class T1, class T2>
|
||||
__std_pair__<
|
||||
typename __boost_call_traits__<T1>::value_type,
|
||||
typename __boost_call_traits__<T2>::value_type>
|
||||
make_pair(const T1& t1, const T2& t2)
|
||||
{
|
||||
return __std_pair__<
|
||||
typename __boost_call_traits__<T1>::value_type,
|
||||
typename __boost_call_traits__<T2>::value_type>(t1, t2);
|
||||
}
|
||||
```
|
||||
|
||||
Here, the deduced argument types will be automatically
|
||||
degraded to pointers if the deduced types are arrays, similar
|
||||
situations occur in the standard binders and adapters: in
|
||||
principle in any function that "wraps" a temporary
|
||||
whose type is deduced. Note that the function arguments to
|
||||
__std_make_pair__ are not expressed in terms of __call_traits__: doing so
|
||||
would prevent template argument deduction from functioning.
|
||||
[endsect]
|
||||
|
||||
[#sec:example4]
|
||||
[section Example 4 (optimising fill):]
|
||||
|
||||
The __call_traits__ template will "optimize" the passing
|
||||
of a small built-in type as a function parameter. This mainly has
|
||||
an effect when the parameter is used within a loop body.
|
||||
|
||||
In the following example (see [@boost:/libs/type_traits/examples/fill_example.cpp `fill_example.cpp`]),
|
||||
a version of __std_fill__ is optimized in two ways: if the type
|
||||
passed is a single byte built-in type then __std_memset__ is used to
|
||||
effect the fill, otherwise a conventional C++ implementation is
|
||||
used, but with the passed parameter "optimized" using
|
||||
__call_traits__:
|
||||
|
||||
```
|
||||
template <bool opt>
|
||||
struct filler
|
||||
{
|
||||
template <typename I, typename T>
|
||||
static void do_fill(I first, I last, typename __boost_call_traits__<T>::param_type val)
|
||||
{
|
||||
while(first != last)
|
||||
{
|
||||
*first = val;
|
||||
++first;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct filler<true>
|
||||
{
|
||||
template <typename I, typename T>
|
||||
static void do_fill(I first, I last, T val)
|
||||
{
|
||||
__std_memset__(first, val, last-first);
|
||||
}
|
||||
};
|
||||
|
||||
template <class I, class T>
|
||||
inline void fill(I first, I last, const T& val)
|
||||
{
|
||||
enum { can_opt = boost::is_pointer<I>::value
|
||||
&& boost::is_arithmetic<T>::value
|
||||
&& (sizeof(T) == 1) };
|
||||
typedef filler<can_opt> filler_t;
|
||||
filler_t::template do_fill<I,T>(first, last, val);
|
||||
}
|
||||
```
|
||||
|
||||
The reason that this is "optimal" for small built-in types is that
|
||||
with the value passed as `T const` instead of `const T&` the compiler is
|
||||
able to tell both that the value is constant and that it is free
|
||||
of aliases. With this information the compiler is able to cache
|
||||
the passed value in a register, unroll the loop, or use
|
||||
explicitly parallel instructions: if any of these are supported.
|
||||
Exactly how much mileage you will get from this depends upon your
|
||||
compiler - we could really use some accurate benchmarking
|
||||
software as part of boost for cases like this.
|
||||
|
||||
Note that the function arguments to fill are not expressed in
|
||||
terms of __call_traits__: doing so would prevent template argument
|
||||
deduction from functioning. Instead fill acts as a "thin
|
||||
wrapper" that is there to perform template argument
|
||||
deduction, the compiler will optimise away the call to fill all
|
||||
together, replacing it with the call to `filler<>::do_fill`,
|
||||
which does use __call_traits__.
|
||||
|
||||
[endsect]
|
||||
[endsect]
|
||||
|
||||
[section Rationale]
|
||||
|
||||
The following notes are intended to briefly describe the
|
||||
rationale behind choices made in __call_traits__.
|
||||
|
||||
All user-defined types follow "existing practice" and need no comment.
|
||||
|
||||
Small built-in types, what the standard calls [@https://en.cppreference.com/w/cpp/language/types fundamental
|
||||
types], differ from existing practice only in the `param_type`
|
||||
`typedef`. In this case passing `T const` is compatible
|
||||
with existing practice, but may improve performance in some cases
|
||||
(see [link sec:example4 Example 4]). In any case this should never
|
||||
be any worse than existing practice.
|
||||
|
||||
Pointers follow the same rationale as small built-in types.
|
||||
|
||||
For reference types the rationale follows [link sec:refs Example 2]
|
||||
- references to references are not allowed, so the __call_traits__
|
||||
members must be defined such that these problems do
|
||||
not occur. There is a proposal to modify the language such that
|
||||
"a reference to a reference is a reference" (issue #106,
|
||||
submitted by Bjarne Stroustrup). __call_traits_T__`::value_type`
|
||||
and __call_traits_T__`::param_type` both provide the same effect
|
||||
as that proposal, without the need for a language change. In
|
||||
other words, it's a workaround.
|
||||
|
||||
For array types, a function that takes an array as an argument
|
||||
will degrade the array type to a pointer type: this means that
|
||||
the type of the actual parameter is different from its declared
|
||||
type, something that can cause endless problems in template code
|
||||
that relies on the declared type of a parameter.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
template <class T>
|
||||
struct A
|
||||
{
|
||||
void foo(T t);
|
||||
};
|
||||
```
|
||||
|
||||
In this case if we instantiate `A<int[2]>` then the declared type of
|
||||
the parameter passed to member function `foo` is `int[2]`, but its
|
||||
actual type is `const int*`. If we try to use the type `T` within the
|
||||
function body, then there is a strong likelihood that our code will not compile:
|
||||
|
||||
```
|
||||
template <class T>
|
||||
void A<T>::foo(T t)
|
||||
{
|
||||
T dup(t); // doesn't compile for case that T is an array.
|
||||
}
|
||||
```
|
||||
|
||||
By using __call_traits__ the degradation from array to pointer is
|
||||
explicit, and the type of the parameter is the same as it's
|
||||
declared type:
|
||||
|
||||
```
|
||||
template <class T>
|
||||
struct A
|
||||
{
|
||||
void foo(typename __call_traits__<T>::value_type t);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void A<T>::foo(typename __call_traits__<T>::value_type t)
|
||||
{
|
||||
typename __call_traits__<T>::value_type dup(t); // OK even if T is an array type.
|
||||
}
|
||||
```
|
||||
|
||||
For `value_type` (return by value), again only a pointer may be
|
||||
returned, not a copy of the whole array, and again __call_traits__
|
||||
makes the degradation explicit. The `value_type` member is useful
|
||||
whenever an array must be explicitly degraded to a pointer -
|
||||
[link sec:example3 Example 3] provides the test case.
|
||||
|
||||
Footnote: the array specialisation for __call_traits__ is the least
|
||||
well understood of all the __call_traits__ specialisations. If the given
|
||||
semantics cause specific problems for you, or does not solve a particular
|
||||
array-related problem, then I would be interested to hear about
|
||||
it. Most people though will probably never need to use this
|
||||
specialisation.
|
||||
|
||||
[endsect]
|
||||
|
||||
[/===============]
|
||||
[xinclude tmp/call_traits_reference.xml]
|
||||
[/===============]
|
||||
|
||||
[endsect]
|
98
doc/compressed_pair.qbk
Normal file
98
doc/compressed_pair.qbk
Normal file
@ -0,0 +1,98 @@
|
||||
[/
|
||||
Copyright 2000 Beman Dawes & John Maddock.
|
||||
Copyright (c) 2021, Alan Freitas
|
||||
|
||||
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
|
||||
]
|
||||
|
||||
[section Compressed Pair]
|
||||
|
||||
[section Introduction]
|
||||
|
||||
All of the contents of [@../../../../boost/compressed_pair.hpp `<boost/compressed_pair.hpp>`] are defined inside
|
||||
`namespace boost`.
|
||||
|
||||
The class __compressed_pair__ is very similar to __std_pair__. However, if either of
|
||||
the template arguments are empty classes, then the
|
||||
[@https://en.cppreference.com/w/cpp/language/ebo ['empty base-class optimisation]]
|
||||
is applied to compress the size of the pair.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Synopsis]
|
||||
|
||||
```cpp
|
||||
template <class T1, class T2>
|
||||
class __compressed_pair__
|
||||
{
|
||||
public:
|
||||
typedef T1 first_type;
|
||||
typedef T2 second_type;
|
||||
typedef typename __call_traits__<first_type>::param_type first_param_type;
|
||||
typedef typename __call_traits__<second_type>::param_type second_param_type;
|
||||
typedef typename __call_traits__<first_type>::reference first_reference;
|
||||
typedef typename __call_traits__<second_type>::reference second_reference;
|
||||
typedef typename __call_traits__<first_type>::const_reference first_const_reference;
|
||||
typedef typename __call_traits__<second_type>::const_reference second_const_reference;
|
||||
|
||||
compressed_pair() : base() {}
|
||||
compressed_pair(first_param_type x, second_param_type y);
|
||||
explicit compressed_pair(first_param_type x);
|
||||
explicit compressed_pair(second_param_type y);
|
||||
|
||||
compressed_pair& operator=(const compressed_pair&);
|
||||
|
||||
first_reference first();
|
||||
first_const_reference first() const;
|
||||
|
||||
second_reference second();
|
||||
second_const_reference second() const;
|
||||
|
||||
void swap(compressed_pair& y);
|
||||
};
|
||||
```
|
||||
|
||||
The two members of the pair can be accessed using the member functions
|
||||
`first()` and `second()`. Note that not all member functions can be
|
||||
instantiated for all template parameter types. In particular
|
||||
__compressed_pair__ can be instantiated for reference and array types,
|
||||
however in these cases the range of constructors that can be used is
|
||||
limited. If types `T1` and `T2` are the same type, then there is only
|
||||
one version of the single-argument constructor, and this constructor
|
||||
initialises both values in the pair to the passed value.
|
||||
|
||||
Note that if either member is a [@https://en.cppreference.com/w/cpp/named_req/PODType POD]
|
||||
type, then that member is not zero-initialized by the __compressed_pair__ default constructor:
|
||||
it is up to you to supply an initial value for these types if you want them to have
|
||||
a default value.
|
||||
|
||||
Note that __compressed_pair__ can not be instantiated if either of the
|
||||
template arguments is a union type, unless there is compiler support for
|
||||
[@boost:/libs/type_traits/index.html `boost::is_union`], or
|
||||
if [@boost:/libs/type_traits/index.html `boost::is_union`] is
|
||||
specialised for the union type.
|
||||
|
||||
Finally, a word of caution for Visual C++ 6 users: if either argument is an
|
||||
empty type, then assigning to that member will produce memory corruption,
|
||||
unless the empty type has a "do nothing" assignment operator defined. This
|
||||
is due to a bug in the way VC6 generates implicit assignment operators.
|
||||
|
||||
[endsect]
|
||||
|
||||
[/===============]
|
||||
[xinclude tmp/compressed_pair_reference.xml]
|
||||
[/===============]
|
||||
|
||||
[section Acknowledgments]
|
||||
|
||||
Based on contributions by Steve Cleary, Beman Dawes, Howard Hinnant and
|
||||
John Maddock.
|
||||
|
||||
Maintained by [@mailto:john@johnmaddock.co.uk John Maddock].
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
115
doc/declval.qbk
115
doc/declval.qbk
@ -1,115 +0,0 @@
|
||||
[/
|
||||
/ Copyright (c) 2008 Howard Hinnant
|
||||
/ Copyright (c) 2009-20012 Vicente J. Botet Escriba
|
||||
/
|
||||
/ 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)
|
||||
/]
|
||||
|
||||
[article Declval
|
||||
[quickbook 1.5]
|
||||
[authors [Hinnant, Howard]]
|
||||
[authors [Botet Escriba, Vicente J.]]
|
||||
[copyright 2008 Howard Hinnant]
|
||||
[copyright 2009-2012 Vicente J. Botet Escriba]
|
||||
[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 Overview]
|
||||
[/===============]
|
||||
|
||||
The motivation for `declval` was introduced in [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2958.html#Value N2958:
|
||||
Moving Swap Forward]. Here follows a rewording of this chapter.
|
||||
|
||||
With the provision of decltype, late-specified return types, and default template-arguments for function templates a
|
||||
new generation of SFINAE patterns will emerge to at least partially compensate the lack of concepts on the C++0x timescale.
|
||||
Using this technique, it is sometimes necessary to obtain an object of a known type in a non-using context, e.g. given the declaration
|
||||
|
||||
template<class T>
|
||||
T&& declval(); // not used
|
||||
|
||||
as part of the function template declaration
|
||||
|
||||
template<class To, class From>
|
||||
decltype(static_cast<To>(declval<From>())) convert(From&&);
|
||||
|
||||
or as part of a class template definition
|
||||
|
||||
template<class> class result_of;
|
||||
|
||||
template<class Fn, class... ArgTypes>
|
||||
struct result_of<Fn(ArgTypes...)>
|
||||
{
|
||||
typedef decltype(declval<Fn>()(declval<ArgTypes>()...)) type;
|
||||
};
|
||||
|
||||
The role of the function template declval() is a transformation of a type T into a value without using or evaluating this function.
|
||||
The name is supposed to direct the reader's attention to the fact that the expression `declval<T>()` is an lvalue if and only if
|
||||
T is an lvalue-reference, otherwise an rvalue. To extend the domain of this function we can do a bit better by changing its declaration to
|
||||
|
||||
template<class T>
|
||||
typename std::add_rvalue_reference<T>::type declval(); // not used
|
||||
|
||||
which ensures that we can also use cv void as template parameter. The careful reader might have noticed that `declval()`
|
||||
already exists under the name create() as part of the definition of the semantics of the type trait is_convertible in the C++0x standard.
|
||||
|
||||
The provision of a new library component that allows the production of values in unevaluated expressions is considered
|
||||
important to realize constrained templates in C++0x where concepts are not available.
|
||||
This extremely light-weight function is expected to be part of the daily tool-box of the C++0x programmer.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[/=================]
|
||||
[section:reference Reference ]
|
||||
[/=================]
|
||||
|
||||
`#include <boost/utility/declval.hpp>`
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <typename T>
|
||||
typename add_rvalue_reference<T>::type declval() noexcept; // as unevaluated operand
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
The library provides the function template declval to simplify the definition of expressions which occur as unevaluated operands.
|
||||
|
||||
template <typename T>
|
||||
typename add_rvalue_reference<T>::type declval();
|
||||
|
||||
[*Remarks:] If this function is used, the program is ill-formed.
|
||||
|
||||
[*Remarks:] The template parameter T of declval may be an incomplete type.
|
||||
|
||||
[*Example:]
|
||||
|
||||
template <class To, class From>
|
||||
decltype(static_cast<To>(declval<From>())) convert(From&&);
|
||||
|
||||
Declares a function template convert which only participates in overloading if the type From can be explicitly converted to type To.
|
||||
|
||||
[endsect]
|
||||
|
||||
[/===============]
|
||||
[section History]
|
||||
[/===============]
|
||||
|
||||
[heading boost 1.50]
|
||||
|
||||
Fixes:
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/6570 #6570] Adding noexcept to boost::declval.
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
|
||||
|
@ -1,68 +0,0 @@
|
||||
[/
|
||||
/ Copyright (c) 2013 Andrey Semashev
|
||||
/
|
||||
/ 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)
|
||||
/]
|
||||
|
||||
[article BOOST_EXPLICIT_OPERATOR_BOOL and BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL
|
||||
[quickbook 1.5]
|
||||
[authors [Semashev, Andrey]]
|
||||
[copyright 2013 Andrey Semashev]
|
||||
[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 Overview]
|
||||
[/===============]
|
||||
|
||||
`BOOST_EXPLICIT_OPERATOR_BOOL()` and `BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL()` are compatibility helper macros that expand to an explicit conversion operator to `bool`. For compilers not supporting explicit conversion operators introduced in C++11 the macros expand to a conversion operator that implements the [@http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Safe_bool safe bool idiom]. In case if the compiler is not able to handle safe bool idiom well the macros expand to a regular conversion operator to `bool`.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[/===============]
|
||||
[section Examples]
|
||||
[/===============]
|
||||
|
||||
Both macros are intended to be placed within a user's class definition. The generated conversion operators will be implemented in terms of `operator!()` that should be defined by user in this class. In case of `BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL()` the generated conversion operator will be declared `constexpr` which requires the corresponding `operator!()` to also be `constexpr`.
|
||||
|
||||
template< typename T >
|
||||
class my_ptr
|
||||
{
|
||||
T* m_p;
|
||||
|
||||
public:
|
||||
BOOST_EXPLICIT_OPERATOR_BOOL()
|
||||
|
||||
bool operator!() const
|
||||
{
|
||||
return !m_p;
|
||||
}
|
||||
};
|
||||
|
||||
Now `my_ptr` can be used in conditional expressions, similarly to a regular pointer:
|
||||
|
||||
my_ptr< int > p;
|
||||
if (p)
|
||||
std::cout << "true" << std::endl;
|
||||
|
||||
[endsect]
|
||||
|
||||
[/===============]
|
||||
[section History]
|
||||
[/===============]
|
||||
|
||||
[heading boost 1.55]
|
||||
|
||||
* The macro was extracted from Boost.Log.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
|
||||
|
@ -1,176 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
|
||||
<title>Declval</title>
|
||||
<link rel="stylesheet" href="../../../../doc/src/boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.76.0">
|
||||
<link rel="home" href="declval.html" title="Declval">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr>
|
||||
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../index.html">Home</a></td>
|
||||
<td align="center"><a href="../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../more/index.htm">More</a></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav"></div>
|
||||
<div class="article">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div><h2 class="title">
|
||||
<a name="declval"></a>Declval</h2></div>
|
||||
<div><div class="authorgroup">
|
||||
<div class="author"><h3 class="author">
|
||||
<span class="firstname">Howard</span> <span class="surname">Hinnant</span>
|
||||
</h3></div>
|
||||
<div class="author"><h3 class="author">
|
||||
<span class="firstname">Vicente J.</span> <span class="surname">Botet Escriba</span>
|
||||
</h3></div>
|
||||
</div></div>
|
||||
<div><p class="copyright">Copyright © 2008 Howard Hinnant</p></div>
|
||||
<div><p class="copyright">Copyright © 2009 -2012 Vicente J. Botet Escriba</p></div>
|
||||
<div><div class="legalnotice">
|
||||
<a name="idp13456288"></a><p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</div></div>
|
||||
</div>
|
||||
<hr>
|
||||
</div>
|
||||
<div class="toc">
|
||||
<p><b>Table of Contents</b></p>
|
||||
<dl>
|
||||
<dt><span class="section"><a href="declval.html#declval.overview">Overview</a></span></dt>
|
||||
<dt><span class="section"><a href="declval.html#declval.reference">Reference </a></span></dt>
|
||||
<dt><span class="section"><a href="declval.html#declval.history">History</a></span></dt>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="section declval_overview">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="declval.overview"></a><a class="link" href="declval.html#declval.overview" title="Overview">Overview</a>
|
||||
</h2></div></div></div>
|
||||
<p>
|
||||
The motivation for <code class="computeroutput"><span class="identifier">declval</span></code>
|
||||
was introduced in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2958.html#Value" target="_top">N2958:
|
||||
Moving Swap Forward</a>. Here follows a rewording of this chapter.
|
||||
</p>
|
||||
<p>
|
||||
With the provision of decltype, late-specified return types, and default template-arguments
|
||||
for function templates a new generation of SFINAE patterns will emerge to at
|
||||
least partially compensate the lack of concepts on the C++0x timescale. Using
|
||||
this technique, it is sometimes necessary to obtain an object of a known type
|
||||
in a non-using context, e.g. given the declaration
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
|
||||
<span class="identifier">T</span><span class="special">&&</span> <span class="identifier">declval</span><span class="special">();</span> <span class="comment">// not used
|
||||
</span></pre>
|
||||
<p>
|
||||
as part of the function template declaration
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">To</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">From</span><span class="special">></span>
|
||||
<span class="identifier">decltype</span><span class="special">(</span><span class="keyword">static_cast</span><span class="special"><</span><span class="identifier">To</span><span class="special">>(</span><span class="identifier">declval</span><span class="special"><</span><span class="identifier">From</span><span class="special">>()))</span> <span class="identifier">convert</span><span class="special">(</span><span class="identifier">From</span><span class="special">&&);</span>
|
||||
</pre>
|
||||
<p>
|
||||
or as part of a class template definition
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span><span class="special">></span> <span class="keyword">class</span> <span class="identifier">result_of</span><span class="special">;</span>
|
||||
|
||||
<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">Fn</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">ArgTypes</span><span class="special">></span>
|
||||
<span class="keyword">struct</span> <span class="identifier">result_of</span><span class="special"><</span><span class="identifier">Fn</span><span class="special">(</span><span class="identifier">ArgTypes</span><span class="special">...)></span>
|
||||
<span class="special">{</span>
|
||||
<span class="keyword">typedef</span> <span class="identifier">decltype</span><span class="special">(</span><span class="identifier">declval</span><span class="special"><</span><span class="identifier">Fn</span><span class="special">>()(</span><span class="identifier">declval</span><span class="special"><</span><span class="identifier">ArgTypes</span><span class="special">>()...))</span> <span class="identifier">type</span><span class="special">;</span>
|
||||
<span class="special">};</span>
|
||||
</pre>
|
||||
<p>
|
||||
The role of the function template declval() is a transformation of a type T
|
||||
into a value without using or evaluating this function. The name is supposed
|
||||
to direct the reader's attention to the fact that the expression <code class="computeroutput"><span class="identifier">declval</span><span class="special"><</span><span class="identifier">T</span><span class="special">>()</span></code> is
|
||||
an lvalue if and only if T is an lvalue-reference, otherwise an rvalue. To
|
||||
extend the domain of this function we can do a bit better by changing its declaration
|
||||
to
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
|
||||
<span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">add_rvalue_reference</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">type</span> <span class="identifier">declval</span><span class="special">();</span> <span class="comment">// not used
|
||||
</span></pre>
|
||||
<p>
|
||||
which ensures that we can also use cv void as template parameter. The careful
|
||||
reader might have noticed that <code class="computeroutput"><span class="identifier">declval</span><span class="special">()</span></code> already exists under the name create() as
|
||||
part of the definition of the semantics of the type trait is_convertible in
|
||||
the C++0x standard.
|
||||
</p>
|
||||
<p>
|
||||
The provision of a new library component that allows the production of values
|
||||
in unevaluated expressions is considered important to realize constrained templates
|
||||
in C++0x where concepts are not available. This extremely light-weight function
|
||||
is expected to be part of the daily tool-box of the C++0x programmer.
|
||||
</p>
|
||||
</div>
|
||||
<div class="section declval_reference">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="declval.reference"></a><a class="link" href="declval.html#declval.reference" title="Reference">Reference </a>
|
||||
</h2></div></div></div>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">utility</span><span class="special">/</span><span class="identifier">declval</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span></code>
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span>
|
||||
|
||||
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span>
|
||||
<span class="keyword">typename</span> <span class="identifier">add_rvalue_reference</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">type</span> <span class="identifier">declval</span><span class="special">()</span> <span class="identifier">noexcept</span><span class="special">;</span> <span class="comment">// as unevaluated operand
|
||||
</span>
|
||||
<span class="special">}</span> <span class="comment">// namespace boost
|
||||
</span></pre>
|
||||
<p>
|
||||
The library provides the function template declval to simplify the definition
|
||||
of expressions which occur as unevaluated operands.
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span>
|
||||
<span class="keyword">typename</span> <span class="identifier">add_rvalue_reference</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">type</span> <span class="identifier">declval</span><span class="special">();</span>
|
||||
</pre>
|
||||
<p>
|
||||
<span class="bold"><strong>Remarks:</strong></span> If this function is used, the program
|
||||
is ill-formed.
|
||||
</p>
|
||||
<p>
|
||||
<span class="bold"><strong>Remarks:</strong></span> The template parameter T of declval
|
||||
may be an incomplete type.
|
||||
</p>
|
||||
<p>
|
||||
<span class="bold"><strong>Example:</strong></span>
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">class</span> <span class="identifier">To</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">From</span><span class="special">></span>
|
||||
<span class="identifier">decltype</span><span class="special">(</span><span class="keyword">static_cast</span><span class="special"><</span><span class="identifier">To</span><span class="special">>(</span><span class="identifier">declval</span><span class="special"><</span><span class="identifier">From</span><span class="special">>()))</span> <span class="identifier">convert</span><span class="special">(</span><span class="identifier">From</span><span class="special">&&);</span>
|
||||
</pre>
|
||||
<p>
|
||||
Declares a function template convert which only participates in overloading
|
||||
if the type From can be explicitly converted to type To.
|
||||
</p>
|
||||
</div>
|
||||
<div class="section declval_history">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="declval.history"></a><a class="link" href="declval.html#declval.history" title="History">History</a>
|
||||
</h2></div></div></div>
|
||||
<a name="declval.history.boost_1_50"></a><h4>
|
||||
<a name="idp13559952"></a>
|
||||
<a class="link" href="declval.html#declval.history.boost_1_50">boost 1.50</a>
|
||||
</h4>
|
||||
<p>
|
||||
New Features:
|
||||
</p>
|
||||
<div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">
|
||||
<a href="http://svn.boost.org/trac/boost/ticket/6570" target="_top">#6570</a>
|
||||
Adding noexcept to boost::declval.
|
||||
</li></ul></div>
|
||||
</div>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"><p><small>Last revised: March 25, 2012 at 18:26:23 GMT</small></p></td>
|
||||
<td align="right"><div class="copyright-footer"></div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav"></div>
|
||||
</body>
|
||||
</html>
|
@ -1,280 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
|
||||
<title>String_Ref</title>
|
||||
<link rel="stylesheet" href="../../../../doc/src/boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
|
||||
<link rel="home" href="string_ref.html" title="String_Ref">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr>
|
||||
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../index.html">Home</a></td>
|
||||
<td align="center"><a href="../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../more/index.htm">More</a></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav"></div>
|
||||
<div class="article">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div><h2 class="title">
|
||||
<a name="string_ref"></a>String_Ref</h2></div>
|
||||
<div><div class="authorgroup"><div class="author"><h3 class="author">
|
||||
<span class="firstname">Marshall</span> <span class="surname">Clow</span>
|
||||
</h3></div></div></div>
|
||||
<div><p class="copyright">Copyright © 2012 Marshall Clow</p></div>
|
||||
<div><div class="legalnotice">
|
||||
<a name="string_ref.legal"></a><p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</div></div>
|
||||
</div>
|
||||
<hr>
|
||||
</div>
|
||||
<div class="toc">
|
||||
<p><b>Table of Contents</b></p>
|
||||
<dl>
|
||||
<dt><span class="section"><a href="string_ref.html#string_ref.overview">Overview</a></span></dt>
|
||||
<dt><span class="section"><a href="string_ref.html#string_ref.examples">Examples</a></span></dt>
|
||||
<dt><span class="section"><a href="string_ref.html#string_ref.reference">Reference </a></span></dt>
|
||||
<dt><span class="section"><a href="string_ref.html#string_ref.history">History</a></span></dt>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="section string_ref_overview">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="string_ref.overview"></a><a class="link" href="string_ref.html#string_ref.overview" title="Overview">Overview</a>
|
||||
</h2></div></div></div>
|
||||
<p>
|
||||
Boost.StringRef is an implementation of Jeffrey Yaskin's <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html" target="_top">N3442:
|
||||
string_ref: a non-owning reference to a string</a>.
|
||||
</p>
|
||||
<p>
|
||||
When you are parsing/processing strings from some external source, frequently
|
||||
you want to pass a piece of text to a procedure for specialized processing.
|
||||
The canonical way to do this is as a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>,
|
||||
but that has certain drawbacks:
|
||||
</p>
|
||||
<p>
|
||||
1) If you are processing a buffer of text (say a HTTP response or the contents
|
||||
of a file), then you have to create the string from the text you want to pass,
|
||||
which involves memory allocation and copying of data.
|
||||
</p>
|
||||
<p>
|
||||
2) if a routine receives a constant <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>
|
||||
and wants to pass a portion of that string to another routine, then it must
|
||||
create a new string of that substring.
|
||||
</p>
|
||||
<p>
|
||||
3) A routine receives a constant <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>
|
||||
and wants to return a portion of the string, then it must create a new string
|
||||
to return.
|
||||
</p>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">string_ref</span></code> is designed to solve
|
||||
these efficiency problems. A <code class="computeroutput"><span class="identifier">string_ref</span></code>
|
||||
is a read-only reference to a contiguous sequence of characters, and provides
|
||||
much of the functionality of <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>.
|
||||
A <code class="computeroutput"><span class="identifier">string_ref</span></code> is cheap to create,
|
||||
copy and pass by value, because it does not actually own the storage that it
|
||||
points to.
|
||||
</p>
|
||||
<p>
|
||||
A <code class="computeroutput"><span class="identifier">string_ref</span></code> is implemented
|
||||
as a small struct that contains a pointer to the start of the character data
|
||||
and a count. A <code class="computeroutput"><span class="identifier">string_ref</span></code> is
|
||||
cheap to create and cheap to copy.
|
||||
</p>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">string_ref</span></code> acts as a container;
|
||||
it includes all the methods that you would expect in a container, including
|
||||
iteration support, <code class="computeroutput"><span class="keyword">operator</span> <span class="special">[]</span></code>,
|
||||
<code class="computeroutput"><span class="identifier">at</span></code> and <code class="computeroutput"><span class="identifier">size</span></code>.
|
||||
It can be used with any of the iterator-based algorithms in the STL - as long
|
||||
as you don't need to change the underlying data (<code class="computeroutput"><span class="identifier">sort</span></code>
|
||||
and <code class="computeroutput"><span class="identifier">remove</span></code>, for example, will
|
||||
not work)
|
||||
</p>
|
||||
<p>
|
||||
Besides generic container functionality, <code class="computeroutput"><span class="identifier">string_ref</span></code>
|
||||
provides a subset of the interface of <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>.
|
||||
This makes it easy to replace parameters of type <code class="computeroutput"><span class="keyword">const</span>
|
||||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">&</span></code>
|
||||
with <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">string_ref</span></code>. Like <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>,
|
||||
<code class="computeroutput"><span class="identifier">string_ref</span></code> has a static member
|
||||
variable named <code class="computeroutput"><span class="identifier">npos</span></code> to denote
|
||||
the result of failed searches, and to mean "the end".
|
||||
</p>
|
||||
<p>
|
||||
Because a <code class="computeroutput"><span class="identifier">string_ref</span></code> does not
|
||||
own the data that it "points to", it introduces lifetime issues into
|
||||
code that uses it. The programmer must ensure that the data that a <code class="computeroutput"><span class="identifier">string_ref</span></code> refers to exists as long as the
|
||||
<code class="computeroutput"><span class="identifier">string_ref</span></code> does.
|
||||
</p>
|
||||
</div>
|
||||
<div class="section string_ref_examples">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="string_ref.examples"></a><a class="link" href="string_ref.html#string_ref.examples" title="Examples">Examples</a>
|
||||
</h2></div></div></div>
|
||||
<p>
|
||||
Integrating <code class="computeroutput"><span class="identifier">string_ref</span></code> into
|
||||
your code is fairly simple. Wherever you pass a <code class="computeroutput"><span class="keyword">const</span>
|
||||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">&</span></code>
|
||||
or <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code> as a parameter, that's a candidate
|
||||
for passing a <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">string_ref</span></code>.
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">extract_part</span> <span class="special">(</span> <span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">&</span><span class="identifier">bar</span> <span class="special">)</span> <span class="special">{</span>
|
||||
<span class="keyword">return</span> <span class="identifier">bar</span><span class="special">.</span><span class="identifier">substr</span> <span class="special">(</span> <span class="number">2</span><span class="special">,</span> <span class="number">3</span> <span class="special">);</span>
|
||||
<span class="special">}</span>
|
||||
|
||||
<span class="keyword">if</span> <span class="special">(</span> <span class="identifier">extract_part</span> <span class="special">(</span> <span class="string">"ABCDEFG"</span> <span class="special">).</span><span class="identifier">front</span><span class="special">()</span> <span class="special">==</span> <span class="string">"C"</span> <span class="special">)</span> <span class="special">{</span> <span class="comment">/* do something */</span> <span class="special">}</span>
|
||||
</pre>
|
||||
<p>
|
||||
Let's figure out what happens in this (contrived) example.
|
||||
</p>
|
||||
<p>
|
||||
First, a temporary string is created from the string literal <code class="computeroutput"><span class="string">"ABCDEFG"</span></code>, and it is passed (by reference)
|
||||
to the routine <code class="computeroutput"><span class="identifier">extract_part</span></code>.
|
||||
Then a second string is created in the call <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">::</span><span class="identifier">substr</span></code>
|
||||
and returned to <code class="computeroutput"><span class="identifier">extract_part</span></code>
|
||||
(this copy may be elided by RVO). Then <code class="computeroutput"><span class="identifier">extract_part</span></code>
|
||||
returns that string back to the caller (again this copy may be elided). The
|
||||
first temporary string is deallocated, and <code class="computeroutput"><span class="identifier">front</span></code>
|
||||
is called on the second string, and then it is deallocated as well.
|
||||
</p>
|
||||
<p>
|
||||
Two <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>s are created, and two copy operations.
|
||||
That's (potentially) four memory allocations and deallocations, and the associated
|
||||
copying of data.
|
||||
</p>
|
||||
<p>
|
||||
Now let's look at the same code with <code class="computeroutput"><span class="identifier">string_ref</span></code>:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">string_ref</span> <span class="identifier">extract_part</span> <span class="special">(</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">string_ref</span> <span class="identifier">bar</span> <span class="special">)</span> <span class="special">{</span>
|
||||
<span class="keyword">return</span> <span class="identifier">bar</span><span class="special">.</span><span class="identifier">substr</span> <span class="special">(</span> <span class="number">2</span><span class="special">,</span> <span class="number">3</span> <span class="special">);</span>
|
||||
<span class="special">}</span>
|
||||
|
||||
<span class="keyword">if</span> <span class="special">(</span> <span class="identifier">extract_part</span> <span class="special">(</span> <span class="string">"ABCDEFG"</span> <span class="special">).</span><span class="identifier">front</span><span class="special">()</span> <span class="special">==</span> <span class="string">"C"</span> <span class="special">)</span> <span class="special">{</span> <span class="comment">/* do something */</span> <span class="special">}</span>
|
||||
</pre>
|
||||
<p>
|
||||
No memory allocations. No copying of character data. No changes to the code
|
||||
other than the types. There are two <code class="computeroutput"><span class="identifier">string_ref</span></code>s
|
||||
created, and two <code class="computeroutput"><span class="identifier">string_ref</span></code>s
|
||||
copied, but those are cheap operations.
|
||||
</p>
|
||||
</div>
|
||||
<div class="section string_ref_reference">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="string_ref.reference"></a><a class="link" href="string_ref.html#string_ref.reference" title="Reference">Reference </a>
|
||||
</h2></div></div></div>
|
||||
<p>
|
||||
The header file "string_ref.hpp" defines a template <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">basic_string_ref</span></code>,
|
||||
and four specializations - for <code class="computeroutput"><span class="keyword">char</span></code>
|
||||
/ <code class="computeroutput"><span class="keyword">wchar_t</span></code> / <code class="computeroutput"><span class="identifier">char16_t</span></code>
|
||||
/ <code class="computeroutput"><span class="identifier">char32_t</span></code> .
|
||||
</p>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">utility</span><span class="special">/</span><span class="identifier">string_ref</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span></code>
|
||||
</p>
|
||||
<p>
|
||||
Construction and copying:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">basic_string_ref</span> <span class="special">();</span> <span class="comment">// Constructs an empty string_ref</span>
|
||||
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">basic_string_ref</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">charT</span><span class="special">*</span> <span class="identifier">str</span><span class="special">);</span> <span class="comment">// Constructs from a NULL-terminated string</span>
|
||||
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">basic_string_ref</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">charT</span><span class="special">*</span> <span class="identifier">str</span><span class="special">,</span> <span class="identifier">size_type</span> <span class="identifier">len</span><span class="special">);</span> <span class="comment">// Constructs from a pointer, length pair</span>
|
||||
<span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Allocator</span><span class="special">></span>
|
||||
<span class="identifier">basic_string_ref</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span> <span class="identifier">traits</span><span class="special">,</span> <span class="identifier">Allocator</span><span class="special">>&</span> <span class="identifier">str</span><span class="special">);</span> <span class="comment">// Constructs from a std::string</span>
|
||||
<span class="identifier">basic_string_ref</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">basic_string_ref</span> <span class="special">&</span><span class="identifier">rhs</span><span class="special">);</span>
|
||||
<span class="identifier">basic_string_ref</span><span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span><span class="keyword">const</span> <span class="identifier">basic_string_ref</span> <span class="special">&</span><span class="identifier">rhs</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">string_ref</span></code> does not define
|
||||
a move constructor nor a move-assignment operator because copying a <code class="computeroutput"><span class="identifier">string_ref</span></code> is just a cheap as moving one.
|
||||
</p>
|
||||
<p>
|
||||
Basic container-like functions:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">size_type</span> <span class="identifier">size</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">size_type</span> <span class="identifier">length</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">size_type</span> <span class="identifier">max_size</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">BOOST_CONSTEXPR</span> <span class="keyword">bool</span> <span class="identifier">empty</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
|
||||
<span class="comment">// All iterators are const_iterators</span>
|
||||
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">const_iterator</span> <span class="identifier">begin</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">const_iterator</span> <span class="identifier">cbegin</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">const_iterator</span> <span class="identifier">end</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">const_iterator</span> <span class="identifier">cend</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">const_reverse_iterator</span> <span class="identifier">rbegin</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">const_reverse_iterator</span> <span class="identifier">crbegin</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">const_reverse_iterator</span> <span class="identifier">rend</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">const_reverse_iterator</span> <span class="identifier">crend</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
</pre>
|
||||
<p>
|
||||
Access to the individual elements (all of which are const):
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">BOOST_CONSTEXPR</span> <span class="keyword">const</span> <span class="identifier">charT</span><span class="special">&</span> <span class="keyword">operator</span><span class="special">[](</span><span class="identifier">size_type</span> <span class="identifier">pos</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="keyword">const</span> <span class="identifier">charT</span><span class="special">&</span> <span class="identifier">at</span><span class="special">(</span><span class="identifier">size_t</span> <span class="identifier">pos</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">BOOST_CONSTEXPR</span> <span class="keyword">const</span> <span class="identifier">charT</span><span class="special">&</span> <span class="identifier">front</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">BOOST_CONSTEXPR</span> <span class="keyword">const</span> <span class="identifier">charT</span><span class="special">&</span> <span class="identifier">back</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">BOOST_CONSTEXPR</span> <span class="keyword">const</span> <span class="identifier">charT</span><span class="special">*</span> <span class="identifier">data</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
</pre>
|
||||
<p>
|
||||
Modifying the <code class="computeroutput"><span class="identifier">string_ref</span></code> (but
|
||||
not the underlying data):
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">clear</span><span class="special">();</span>
|
||||
<span class="keyword">void</span> <span class="identifier">remove_prefix</span><span class="special">(</span><span class="identifier">size_type</span> <span class="identifier">n</span><span class="special">);</span>
|
||||
<span class="keyword">void</span> <span class="identifier">remove_suffix</span><span class="special">(</span><span class="identifier">size_type</span> <span class="identifier">n</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p>
|
||||
Searching:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">size_type</span> <span class="identifier">find</span><span class="special">(</span><span class="identifier">basic_string_ref</span> <span class="identifier">s</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">size_type</span> <span class="identifier">find</span><span class="special">(</span><span class="identifier">charT</span> <span class="identifier">c</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">size_type</span> <span class="identifier">rfind</span><span class="special">(</span><span class="identifier">basic_string_ref</span> <span class="identifier">s</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">size_type</span> <span class="identifier">rfind</span><span class="special">(</span><span class="identifier">charT</span> <span class="identifier">c</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">size_type</span> <span class="identifier">find_first_of</span><span class="special">(</span><span class="identifier">charT</span> <span class="identifier">c</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">size_type</span> <span class="identifier">find_last_of</span> <span class="special">(</span><span class="identifier">charT</span> <span class="identifier">c</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
|
||||
<span class="identifier">size_type</span> <span class="identifier">find_first_of</span><span class="special">(</span><span class="identifier">basic_string_ref</span> <span class="identifier">s</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">size_type</span> <span class="identifier">find_last_of</span><span class="special">(</span><span class="identifier">basic_string_ref</span> <span class="identifier">s</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">size_type</span> <span class="identifier">find_first_not_of</span><span class="special">(</span><span class="identifier">basic_string_ref</span> <span class="identifier">s</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">size_type</span> <span class="identifier">find_first_not_of</span><span class="special">(</span><span class="identifier">charT</span> <span class="identifier">c</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">size_type</span> <span class="identifier">find_last_not_of</span><span class="special">(</span><span class="identifier">basic_string_ref</span> <span class="identifier">s</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="identifier">size_type</span> <span class="identifier">find_last_not_of</span><span class="special">(</span><span class="identifier">charT</span> <span class="identifier">c</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
</pre>
|
||||
<p>
|
||||
String-like operations:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">basic_string_ref</span> <span class="identifier">substr</span><span class="special">(</span><span class="identifier">size_type</span> <span class="identifier">pos</span><span class="special">,</span> <span class="identifier">size_type</span> <span class="identifier">n</span><span class="special">=</span><span class="identifier">npos</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span> <span class="comment">// Creates a new string_ref</span>
|
||||
<span class="keyword">bool</span> <span class="identifier">starts_with</span><span class="special">(</span><span class="identifier">charT</span> <span class="identifier">c</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="keyword">bool</span> <span class="identifier">starts_with</span><span class="special">(</span><span class="identifier">basic_string_ref</span> <span class="identifier">x</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="keyword">bool</span> <span class="identifier">ends_with</span><span class="special">(</span><span class="identifier">charT</span> <span class="identifier">c</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
<span class="keyword">bool</span> <span class="identifier">ends_with</span><span class="special">(</span><span class="identifier">basic_string_ref</span> <span class="identifier">x</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section string_ref_history">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="string_ref.history"></a><a class="link" href="string_ref.html#string_ref.history" title="History">History</a>
|
||||
</h2></div></div></div>
|
||||
<h4>
|
||||
<a name="string_ref.history.h0"></a>
|
||||
<span><a name="string_ref.history.boost_1_53"></a></span><a class="link" href="string_ref.html#string_ref.history.boost_1_53">boost
|
||||
1.53</a>
|
||||
</h4>
|
||||
<div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">
|
||||
Introduced
|
||||
</li></ul></div>
|
||||
</div>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"><p><small>Last revised: January 14, 2013 at 16:24:14 GMT</small></p></td>
|
||||
<td align="right"><div class="copyright-footer"></div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav"></div>
|
||||
</body>
|
||||
</html>
|
308
doc/in_place_factory.qbk
Normal file
308
doc/in_place_factory.qbk
Normal file
@ -0,0 +1,308 @@
|
||||
[/
|
||||
/ Copyright (c) 2012 Marshall Clow
|
||||
/ Copyright (c) 2021, Alan Freitas
|
||||
/
|
||||
/ 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)
|
||||
/]
|
||||
|
||||
[/===============]
|
||||
[#sec:in_place_factory]
|
||||
[section In-place Factory]
|
||||
[/===============]
|
||||
|
||||
[section Introduction]
|
||||
|
||||
Suppose we have a class
|
||||
|
||||
```
|
||||
struct X
|
||||
{
|
||||
X ( int, __std_string__ ) ;
|
||||
};
|
||||
```
|
||||
|
||||
And a container for it which supports an empty state. That is, a container which can contain zero objects:
|
||||
|
||||
```
|
||||
struct C
|
||||
{
|
||||
C() : contained_(0) {}
|
||||
~C() { delete contained_ ; }
|
||||
X* contained_ ;
|
||||
};
|
||||
```
|
||||
|
||||
A container designed to support an empty state typically does not require the contained type to be
|
||||
__DefaultConstructible__, but it typically requires it to be __CopyConstructible__ as a mechanism to
|
||||
initialize the object to store:
|
||||
|
||||
```
|
||||
struct C
|
||||
{
|
||||
C() : contained_(0) {}
|
||||
C ( X const& v ) : contained_ ( new X(v) ) {}
|
||||
~C() { delete contained_ ; }
|
||||
X* contained_ ;
|
||||
};
|
||||
```
|
||||
|
||||
There is a subtle problem with this: since the mechanism used to initialize the stored object is copy construction,
|
||||
there must exist a previously constructed source object to copy from. This object is likely to be temporary and serve
|
||||
no purpose besides being the source:
|
||||
|
||||
```
|
||||
void foo()
|
||||
{
|
||||
// Temporary object created.
|
||||
C c( X(123,"hello") ) ;
|
||||
}
|
||||
```
|
||||
|
||||
A solution to this problem is to support direct construction of the contained
|
||||
object right in the container's storage.
|
||||
|
||||
In this scheme, the user supplies the arguments for the `X` constructor
|
||||
directly to the container:
|
||||
|
||||
```
|
||||
struct C
|
||||
{
|
||||
C() : contained_(0) {}
|
||||
C ( X const& v ) : contained_ ( new X(v) ) {}
|
||||
C ( int a0, __std_string__ a1 ) : contained_ ( new X(a0,a1) ) {}
|
||||
~C() { delete contained_ ; }
|
||||
X* contained_ ;
|
||||
};
|
||||
```
|
||||
|
||||
```
|
||||
void foo()
|
||||
{
|
||||
// Wrapped object constructed in-place
|
||||
// No temporary created.
|
||||
C c(123,"hello");
|
||||
}
|
||||
```
|
||||
|
||||
Clearly, this solution does not scale well since the container must duplicate all the constructor overloads
|
||||
from the contained type, or at least all those which are to be supported directly in the container.
|
||||
|
||||
[endsect]
|
||||
[section Framework]
|
||||
|
||||
This library proposes a framework to allow some containers to directly construct contained objects in-place without requiring
|
||||
the entire set of constructor overloads from the contained type. It also allows the container to remove the __CopyConstructible__
|
||||
requirement from the contained type since objects can be directly constructed in-place without need of a copy.
|
||||
|
||||
The only requirement on the container is that it must provide proper storage. That is, the container should be
|
||||
correctly aligned and sized. Naturally, the container will typically support uninitialized storage to avoid the
|
||||
in-place construction to override a fully-constructed object, as this would defeat the purpose of in-place construction.
|
||||
|
||||
For this purpose, the framework provides two concepts called: InPlaceFactories and TypedInPlaceFactories.
|
||||
Helpers to declare these classes are declared in [@../../../../boost/utility/in_place_factory.hpp `<boost/utility/in_place_factory.hpp>`]
|
||||
and [@../../../../boost/utility/typed_in_place_factory.hpp `<boost/utility/typed_in_place_factory.hpp>`].
|
||||
|
||||
Essentially, these classes hold a sequence of actual parameters and a method to construct an object in place using these parameters.
|
||||
Each member of the family differs only in the number and type of the parameter list. The first family
|
||||
takes the type of the object to construct directly in method provided for that
|
||||
purpose, whereas the second family incorporates that type in the factory class
|
||||
itself. From the container point of view, using the framework amounts to calling the
|
||||
factory's method to contruct the object in place. From the user point of view, it amounts to creating
|
||||
the right factory object to hold the parameters and pass it to the container.
|
||||
|
||||
The following simplified example shows the basic idea. A complete example follows the formal specification of the framework:
|
||||
|
||||
```
|
||||
struct C
|
||||
{
|
||||
template <class InPlaceFactory>
|
||||
C ( InPlaceFactory const& aFactory )
|
||||
:
|
||||
contained_ ( uninitialized_storage() )
|
||||
{
|
||||
aFactory.template apply<X>(contained_);
|
||||
}
|
||||
|
||||
~C()
|
||||
{
|
||||
contained_ -> X::~X();
|
||||
delete[] contained_ ;
|
||||
}
|
||||
|
||||
char* uninitialized_storage() { return new char[sizeof(X)] ; }
|
||||
|
||||
char* contained_ ;
|
||||
};
|
||||
|
||||
void foo()
|
||||
{
|
||||
C c( in_place(123,"hello") ) ;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
[endsect]
|
||||
[section Specification]
|
||||
|
||||
The following is the first member of the family of `InPlaceFactory` classes, along with its corresponding helper template function.
|
||||
The rest of the family varies only in the number and type of template and constructor parameters.
|
||||
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
|
||||
struct __in_place_factory_base__ {};
|
||||
|
||||
template<class A0>
|
||||
class in_place_factory : public __in_place_factory_base__
|
||||
{
|
||||
public:
|
||||
in_place_factory ( A0 const& a0 ) : m_a0(a0) {}
|
||||
|
||||
template< class T >
|
||||
void apply ( void* address ) const
|
||||
{
|
||||
new (address) T(m_a0);
|
||||
}
|
||||
|
||||
private:
|
||||
A0 const& m_a0 ;
|
||||
};
|
||||
|
||||
template<class A0>
|
||||
in_place_factory<A0> in_place ( A0 const& a0 )
|
||||
{
|
||||
return in_place_factory<A0>(a0);
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Similarly, the following is the first member of the family of `typed_in_place_factory` classes, along with its corresponding
|
||||
helper template function. The rest of the family varies only in the number and type of template and constructor parameters.
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
|
||||
struct __typed_in_place_factory_base__ {};
|
||||
|
||||
template<class T, class A0>
|
||||
class typed_in_place_factory : public __typed_in_place_factory_base__
|
||||
{
|
||||
public:
|
||||
typed_in_place_factory ( A0 const& a0 ) : m_a0(a0) {}
|
||||
|
||||
void apply ( void* address ) const
|
||||
{
|
||||
new (address) T(m_a0);
|
||||
}
|
||||
|
||||
private:
|
||||
A0 const& m_a0 ;
|
||||
};
|
||||
|
||||
template<class T, class A0>
|
||||
typed_in_place_factory<A0> in_place ( A0 const& a0 )
|
||||
{
|
||||
return typed_in_place_factory<T,A0>(a0);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
As you can see, the `in_place_factory` and `typed_in_place_factory` template classes vary only in the way they specify
|
||||
the target type: in the first family, the type is given as a template argument to the apply member function while in the
|
||||
second it is given directly as part of the factory class.
|
||||
|
||||
When the container holds a unique non-polymorphic type, such as the case of [@boost:/libs/optional/index.html Boost.Optional],
|
||||
it knows the exact dynamic-type of the contained object and can pass it to the `apply()` method of a non-typed factory.
|
||||
In this case, end users can use an `in_place_factory` instance which can be constructed without the type of the object to construct.
|
||||
|
||||
However, if the container holds heterogeneous or polymorphic objects, such as the case of [@boost:/libs/variant/index.html Boost.Variant],
|
||||
the dynamic-type of the object to be constructed must be known by the factory. In this case, end users must use a `typed_in_place_factory`
|
||||
instead.
|
||||
|
||||
[endsect]
|
||||
[section Container-side Usage]
|
||||
|
||||
As shown in the introductory simplified example, the container class must contain methods that accept an instance of
|
||||
these factories and pass the object's storage to the factory's apply method.
|
||||
|
||||
However, the type of the factory class cannot be completely specified in the container class because that would
|
||||
defeat the whole purpose of the factories which is to allow the container to accept a variadic argument list
|
||||
for the constructor of its contained object.
|
||||
|
||||
The correct function overload must be based on the only distinctive and common
|
||||
characteristic of all the classes in each family: the base class.
|
||||
|
||||
Depending on the container class, you can use `enable_if` to generate the right overload, or use the following
|
||||
dispatch technique, which is used in the [@boost:/libs/optional/index.html Boost.Optional] class:
|
||||
|
||||
|
||||
```
|
||||
struct C
|
||||
{
|
||||
C() : contained_(0) {}
|
||||
C ( X const& v ) : contained_ ( new X(v) ) {}
|
||||
|
||||
template <class Expr>
|
||||
C ( Expr const& expr )
|
||||
:
|
||||
contained_ ( uninitialized_storage() )
|
||||
{
|
||||
construct(expr,&expr);
|
||||
}
|
||||
|
||||
~C() { delete contained_ ; }
|
||||
|
||||
template<class InPlaceFactory>
|
||||
void construct ( InPlaceFactory const& aFactory, boost::__in_place_factory_base__* )
|
||||
{
|
||||
aFactory.template apply<X>(contained_);
|
||||
}
|
||||
|
||||
template<class TypedInPlaceFactory>
|
||||
void construct ( TypedInPlaceFactory const& aFactory, boost::__typed_in_place_factory_base__* )
|
||||
{
|
||||
aFactory.apply(contained_);
|
||||
}
|
||||
|
||||
X* uninitialized_storage() { return static_cast<X*>(new char[sizeof(X)]) ; }
|
||||
|
||||
X* contained_ ;
|
||||
};
|
||||
```
|
||||
|
||||
[endsect]
|
||||
[section User-side Usage]
|
||||
|
||||
End users pass to the container an instance of a factory object holding the actual parameters needed to construct the
|
||||
contained object directly within the container. For this, the helper template function `in_place` is used.
|
||||
|
||||
The call `in_place(a0,a1,a2,...,an)` constructs a (non-typed) `in_place_factory` instance with the given argument list.
|
||||
|
||||
The call `in_place<T>(a0,a1,a2,...,an)` constructs a `typed_in_place_factory` instance with the given argument list for the
|
||||
type `T`.
|
||||
|
||||
```
|
||||
void foo()
|
||||
{
|
||||
C a( in_place(123, "hello") ) ; // in_place_factory passed
|
||||
C b( in_place<X>(456, "world") ) ; // typed_in_place_factory passed
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
[endsect]
|
||||
|
||||
[/===============]
|
||||
[#boost.typed_in_place_factory_base]
|
||||
[xinclude tmp/in_place_factory_reference.xml]
|
||||
[/===============]
|
||||
|
||||
[section Acknowledgments]
|
||||
|
||||
Copyright Fernando Luis Cacciola Carballal, 2004
|
||||
|
||||
[endsect]
|
||||
[endsect]
|
BIN
doc/logo.png
Normal file
BIN
doc/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
539
doc/logo.svg
Normal file
539
doc/logo.svg
Normal file
@ -0,0 +1,539 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="744.09448819"
|
||||
height="1052.3622047"
|
||||
id="svg6858"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="utility.svg">
|
||||
<defs
|
||||
id="defs6860">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4453-7-8-6-7-3-5"
|
||||
id="linearGradient10687-2-5"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="753.02301"
|
||||
y1="3132.0801"
|
||||
x2="1146.25"
|
||||
y2="3132.0801" />
|
||||
<linearGradient
|
||||
id="linearGradient4453-7-8-6-7-3-5">
|
||||
<stop
|
||||
style="stop-color:#aac4dd;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4455-61-8-7-1-2-8" />
|
||||
<stop
|
||||
style="stop-color:#c2dbe9;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4457-4-1-9-1-12-1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4453-7-8-6-7-3-5"
|
||||
id="linearGradient10685-2-2"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="753.02301"
|
||||
y1="3132.0801"
|
||||
x2="1146.25"
|
||||
y2="3132.0801" />
|
||||
<linearGradient
|
||||
id="linearGradient6749">
|
||||
<stop
|
||||
style="stop-color:#aac4dd;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop6751" />
|
||||
<stop
|
||||
style="stop-color:#c2dbe9;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop6753" />
|
||||
</linearGradient>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath3387-3-6-4-2-8-4">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 862.109,3289.75 -109.086,-190.45 69.122,-124.42 164.511,-0.47 c 0,0 111.044,188.28 116.564,197.63 7.66,0 43.03,0 43.03,0 l -67.03,117.71 -217.111,0 z"
|
||||
id="path3389-2-0-7-7-8-9" />
|
||||
</clipPath>
|
||||
<linearGradient
|
||||
y2="3132.0801"
|
||||
x2="1146.25"
|
||||
y1="3132.0801"
|
||||
x1="753.02301"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient4492-8-8"
|
||||
xlink:href="#linearGradient4453-7-8-6-7-3-5"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
id="linearGradient6758">
|
||||
<stop
|
||||
style="stop-color:#aac4dd;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop6760" />
|
||||
<stop
|
||||
style="stop-color:#c2dbe9;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop6762" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4453-7-8-6-7-3-5"
|
||||
id="linearGradient10691-7-8"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="1026.6899"
|
||||
y1="2937.73"
|
||||
x2="1463.14"
|
||||
y2="2937.73" />
|
||||
<linearGradient
|
||||
id="linearGradient6765">
|
||||
<stop
|
||||
style="stop-color:#aac4dd;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop6767" />
|
||||
<stop
|
||||
style="stop-color:#c2dbe9;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop6769" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4453-7-8-6-7-3-5"
|
||||
id="linearGradient10689-4-2"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="1026.6899"
|
||||
y1="2937.73"
|
||||
x2="1463.14"
|
||||
y2="2937.73" />
|
||||
<linearGradient
|
||||
id="linearGradient6772">
|
||||
<stop
|
||||
style="stop-color:#aac4dd;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop6774" />
|
||||
<stop
|
||||
style="stop-color:#c2dbe9;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop6776" />
|
||||
</linearGradient>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath3369-1-5-6-1-0-7">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 1131.64,3128.5 -104.95,-181.12 116.38,-200.42 208.05,0.94 112.02,191.63 -112.08,188.97 -219.42,0 z"
|
||||
id="path3371-89-4-1-6-0-1" />
|
||||
</clipPath>
|
||||
<linearGradient
|
||||
y2="2937.73"
|
||||
x2="1463.14"
|
||||
y1="2937.73"
|
||||
x1="1026.6899"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient4498-5-7"
|
||||
xlink:href="#linearGradient4453-7-8-6-7-3-5"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
id="linearGradient6781">
|
||||
<stop
|
||||
style="stop-color:#aac4dd;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop6783" />
|
||||
<stop
|
||||
style="stop-color:#c2dbe9;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop6785" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4459-1-2-8-9-9-5"
|
||||
id="linearGradient10695-9-9"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="646.55499"
|
||||
y1="2736.25"
|
||||
x2="1088.27"
|
||||
y2="2736.25" />
|
||||
<linearGradient
|
||||
id="linearGradient4459-1-2-8-9-9-5">
|
||||
<stop
|
||||
id="stop4461-2-1-5-2-5-0"
|
||||
offset="0"
|
||||
style="stop-color:#839bc2;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop4463-3-2-8-7-30-3"
|
||||
offset="1"
|
||||
style="stop-color:#9fb6d4;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4459-1-2-8-9-9-5"
|
||||
id="linearGradient10693-9-4"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="646.55499"
|
||||
y1="2736.25"
|
||||
x2="1088.27"
|
||||
y2="2736.25" />
|
||||
<linearGradient
|
||||
id="linearGradient6792">
|
||||
<stop
|
||||
id="stop6794"
|
||||
offset="0"
|
||||
style="stop-color:#839bc2;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop6796"
|
||||
offset="1"
|
||||
style="stop-color:#9fb6d4;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath3351-4-7-3-5-95-0">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 757.242,2926.25 -110.687,-189.11 110.656,-190.89 219.437,0 111.622,189.1 -111.59,190.9 -219.438,0 z"
|
||||
id="path3353-1-9-3-4-1-1" />
|
||||
</clipPath>
|
||||
<linearGradient
|
||||
y2="2736.25"
|
||||
x2="1088.27"
|
||||
y1="2736.25"
|
||||
x1="646.55499"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient4510-1-5"
|
||||
xlink:href="#linearGradient4459-1-2-8-9-9-5"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
id="linearGradient6801">
|
||||
<stop
|
||||
id="stop6803"
|
||||
offset="0"
|
||||
style="stop-color:#839bc2;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop6805"
|
||||
offset="1"
|
||||
style="stop-color:#9fb6d4;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#radialGradient3327-8-4-8-0-2-4"
|
||||
id="radialGradient10699-1-3"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cx="997.46997"
|
||||
cy="2896.25"
|
||||
fx="997.46997"
|
||||
fy="2896.25"
|
||||
r="583.73999" />
|
||||
<radialGradient
|
||||
fx="0"
|
||||
fy="0"
|
||||
cx="0"
|
||||
cy="0"
|
||||
r="1"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(58.375,0,0,-58.375,99.75,289.625)"
|
||||
spreadMethod="pad"
|
||||
id="radialGradient3327-8-4-8-0-2-4">
|
||||
<stop
|
||||
style="stop-opacity:1;stop-color:#aeaeb3"
|
||||
offset="0"
|
||||
id="stop3329-7-0-1-0-33-2" />
|
||||
<stop
|
||||
style="stop-opacity:1;stop-color:#ffffff"
|
||||
offset="0.949438"
|
||||
id="stop3331-4-3-0-0-97-3" />
|
||||
<stop
|
||||
style="stop-opacity:1;stop-color:#ffffff"
|
||||
offset="1"
|
||||
id="stop3333-2-4-9-7-2-2" />
|
||||
</radialGradient>
|
||||
<radialGradient
|
||||
r="583.73999"
|
||||
fy="2896.25"
|
||||
fx="997.46997"
|
||||
cy="2896.25"
|
||||
cx="997.46997"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient13050"
|
||||
xlink:href="#radialGradient3327-8-4-8-0-2-4"
|
||||
inkscape:collect="always" />
|
||||
<radialGradient
|
||||
fx="0"
|
||||
fy="0"
|
||||
cx="0"
|
||||
cy="0"
|
||||
r="1"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(58.375,0,0,-58.375,99.75,289.625)"
|
||||
spreadMethod="pad"
|
||||
id="radialGradient6813">
|
||||
<stop
|
||||
style="stop-opacity:1;stop-color:#aeaeb3"
|
||||
offset="0"
|
||||
id="stop6815" />
|
||||
<stop
|
||||
style="stop-opacity:1;stop-color:#ffffff"
|
||||
offset="0.949438"
|
||||
id="stop6817" />
|
||||
<stop
|
||||
style="stop-opacity:1;stop-color:#ffffff"
|
||||
offset="1"
|
||||
id="stop6819" />
|
||||
</radialGradient>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath3323-7-2-4-5-3-4">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 997.469,2312.51 c -322.379,0 -583.739,261.36 -583.739,583.74 0,322.38 261.36,583.74 583.739,583.74 322.381,0 583.741,-261.36 583.741,-583.74 0,-322.38 -261.36,-583.74 -583.741,-583.74"
|
||||
id="path3325-9-2-9-5-04-9" />
|
||||
</clipPath>
|
||||
<radialGradient
|
||||
r="583.73999"
|
||||
fy="2896.25"
|
||||
fx="997.46997"
|
||||
cy="2896.25"
|
||||
cx="997.46997"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient4516-8-2"
|
||||
xlink:href="#radialGradient3327-8-4-8-0-2-4"
|
||||
inkscape:collect="always" />
|
||||
<radialGradient
|
||||
fx="0"
|
||||
fy="0"
|
||||
cx="0"
|
||||
cy="0"
|
||||
r="1"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(58.375,0,0,-58.375,99.75,289.625)"
|
||||
spreadMethod="pad"
|
||||
id="radialGradient6824">
|
||||
<stop
|
||||
style="stop-opacity:1;stop-color:#aeaeb3"
|
||||
offset="0"
|
||||
id="stop6826" />
|
||||
<stop
|
||||
style="stop-opacity:1;stop-color:#ffffff"
|
||||
offset="0.949438"
|
||||
id="stop6828" />
|
||||
<stop
|
||||
style="stop-opacity:1;stop-color:#ffffff"
|
||||
offset="1"
|
||||
id="stop6830" />
|
||||
</radialGradient>
|
||||
<radialGradient
|
||||
r="583.73999"
|
||||
fy="2896.25"
|
||||
fx="997.46997"
|
||||
cy="2896.25"
|
||||
cx="997.46997"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient6856"
|
||||
xlink:href="#radialGradient3327-8-4-8-0-2-4"
|
||||
inkscape:collect="always" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.4"
|
||||
inkscape:cx="234.05635"
|
||||
inkscape:cy="581.46313"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1680"
|
||||
inkscape:window-height="982"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3066" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata6863">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<g
|
||||
id="g3319-1-2-5-1-4-4"
|
||||
transform="matrix(0.10419818,0,0,-0.10419818,137.10955,897.00327)"
|
||||
style="fill:url(#radialGradient10699-1-3);fill-opacity:1"
|
||||
inkscape:export-filename="C:\Users\Adam\Desktop\bg_logo1.png"
|
||||
inkscape:export-xdpi="63.625523"
|
||||
inkscape:export-ydpi="63.625523">
|
||||
<g
|
||||
clip-path="url(#clipPath3323-7-2-4-5-3-4)"
|
||||
id="g3321-9-2-7-4-3-9"
|
||||
style="fill:url(#radialGradient6856);fill-opacity:1">
|
||||
<path
|
||||
id="path3335-8-7-3-8-92-0"
|
||||
style="fill:url(#radialGradient4516-8-2);fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 997.469,2312.51 c -322.379,0 -583.739,261.36 -583.739,583.74 0,322.38 261.36,583.74 583.739,583.74 322.381,0 583.741,-261.36 583.741,-583.74 0,-322.38 -261.36,-583.74 -583.741,-583.74"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="g3347-6-8-3-7-4-4"
|
||||
transform="matrix(0.125,0,0,-0.125,112.08304,959.82207)"
|
||||
style="fill:url(#linearGradient10695-9-9);fill-opacity:1"
|
||||
inkscape:export-filename="C:\Users\Adam\Desktop\bg_logo1.png"
|
||||
inkscape:export-xdpi="63.625523"
|
||||
inkscape:export-ydpi="63.625523">
|
||||
<g
|
||||
clip-path="url(#clipPath3351-4-7-3-5-95-0)"
|
||||
id="g3349-5-5-4-7-9-4"
|
||||
style="fill:url(#linearGradient10693-9-4);fill-opacity:1">
|
||||
<path
|
||||
id="path3361-0-8-2-9-0-9"
|
||||
style="fill:url(#linearGradient4510-1-5);fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 757.242,2926.25 -110.687,-189.11 110.656,-190.89 219.437,0 111.622,189.1 -111.59,190.9 -219.438,0"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
<path
|
||||
id="path3363-6-9-0-1-5-8"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 194.34816,617.68335 13.106,-22.3925 25.99649,0 13.21487,22.60874 -13.21487,22.39125 -25.99649,0 -13.106,-22.60749 z m 40.53761,-24.8925 -28.86524,0 -0.72412,1.23749 -13.106,22.39251 -0.73575,1.25625 0.73087,1.26 13.106,22.60744 0.72263,1.24634 28.86374,0 0.72512,-1.22884 13.215,-22.39119 0.74625,-1.265 -0.74,-1.26751 -13.21537,-22.60875 -0.72313,-1.23874"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:export-filename="C:\Users\Adam\Desktop\bg_logo1.png"
|
||||
inkscape:export-xdpi="63.625523"
|
||||
inkscape:export-ydpi="63.625523" />
|
||||
<g
|
||||
id="g3365-0-4-1-9-7-5"
|
||||
transform="matrix(0.125,0,0,-0.125,112.08304,959.82207)"
|
||||
style="fill:url(#linearGradient10691-7-8);fill-opacity:1"
|
||||
inkscape:export-filename="C:\Users\Adam\Desktop\bg_logo1.png"
|
||||
inkscape:export-xdpi="63.625523"
|
||||
inkscape:export-ydpi="63.625523">
|
||||
<g
|
||||
clip-path="url(#clipPath3369-1-5-6-1-0-7)"
|
||||
id="g3367-2-4-2-8-4-3"
|
||||
style="fill:url(#linearGradient10689-4-2);fill-opacity:1">
|
||||
<path
|
||||
id="path3379-4-6-7-6-7-2"
|
||||
style="fill:url(#linearGradient4498-5-7);fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 1131.64,3128.5 -104.95,-181.12 116.38,-200.42 208.05,0.94 112.02,191.63 -112.08,188.97 -219.42,0"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
<path
|
||||
id="path3381-6-8-0-0-66-3"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 241.86427,591.39959 12.3925,-21.38999 25.99625,0 13.27125,22.37625 -13.27125,22.7025 -24.56875,0.11 -13.82,-23.79876 z m 39.8125,-23.88999 -28.86125,0 -0.7225,1.24625 -12.3925,21.39 -0.72625,1.255 0.7275,1.25374 13.82,23.79876 0.7275,1.25125 1.44625,-0.006 24.56875,-0.11 1.4275,-0.006 0.72,-1.2325 13.27125,-22.7025 0.7425,-1.27 -0.75125,-1.26625 -13.27125,-22.37625 -0.72625,-1.225"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:export-filename="C:\Users\Adam\Desktop\bg_logo1.png"
|
||||
inkscape:export-xdpi="63.625523"
|
||||
inkscape:export-ydpi="63.625523" />
|
||||
<g
|
||||
id="g3383-5-5-2-2-3-0"
|
||||
transform="matrix(0.125,0,0,-0.125,112.08304,959.82207)"
|
||||
style="fill:url(#linearGradient10687-2-5);fill-opacity:1"
|
||||
inkscape:export-filename="C:\Users\Adam\Desktop\bg_logo1.png"
|
||||
inkscape:export-xdpi="63.625523"
|
||||
inkscape:export-ydpi="63.625523">
|
||||
<g
|
||||
clip-path="url(#clipPath3387-3-6-4-2-8-4)"
|
||||
id="g3385-0-6-4-8-0-1"
|
||||
style="fill:url(#linearGradient10685-2-2);fill-opacity:1">
|
||||
<path
|
||||
id="path3397-9-6-1-6-9-7"
|
||||
style="fill:url(#linearGradient4492-8-8);fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 862.109,3289.75 -109.086,-190.45 69.122,-124.42 164.511,-0.47 c 0,0 111.044,188.28 116.564,197.63 7.66,0 43.03,0 43.03,0 l -67.03,117.71 -217.111,0"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
<path
|
||||
id="path3399-6-7-3-2-0-1"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 207.64603,572.41959 12.92424,-22.56624 25.68775,0 6.95625,12.21375 -3.94375,0 -14.56837,24.7025 -19.11525,-0.055 -7.94087,-14.295 z m 40.06574,-25.06624 -28.59012,0 -0.71975,1.2575 -12.92537,22.56625 -0.70112,1.22375 0.68512,1.23249 7.94137,14.295 0.71087,1.2825 1.46638,0.004 19.11525,0.055 1.43212,0.004 0.729,-1.23375 13.84375,-23.47249 6.81625,0 -2.12875,-3.7375 -6.95625,-12.21375 -0.71875,-1.2625"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:export-filename="C:\Users\Adam\Desktop\bg_logo1.png"
|
||||
inkscape:export-xdpi="63.625523"
|
||||
inkscape:export-ydpi="63.625523" />
|
||||
<g
|
||||
transform="matrix(1.25,0,0,-1.25,105.02062,972.84257)"
|
||||
id="g3465-0-8-9"
|
||||
inkscape:export-filename="C:\Users\Adam\Desktop\bg_logo1.png"
|
||||
inkscape:export-xdpi="63.625523"
|
||||
inkscape:export-ydpi="63.625523">
|
||||
<text
|
||||
id="text3467-9-0-8"
|
||||
transform="matrix(1,0,-0.17627963,-1,0,0)"
|
||||
x="116.98372"
|
||||
y="-267.77499"
|
||||
style="font-size:11.81779194px">
|
||||
<tspan
|
||||
sodipodi:role="line"
|
||||
style="font-size:46.39999771px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#49608a;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:Denmark;-inkscape-font-specification:Denmark"
|
||||
x="116.98372"
|
||||
y="-267.77499"
|
||||
id="tspan13239">UTILITY</tspan>
|
||||
<tspan
|
||||
sodipodi:role="line"
|
||||
style="font-size:46.39999771px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#49608a;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:Denmark;-inkscape-font-specification:Denmark"
|
||||
x="116.98372"
|
||||
y="-209.77499"
|
||||
id="tspan11278-3" />
|
||||
</text>
|
||||
<text
|
||||
id="text3471-0-51-2"
|
||||
transform="matrix(0.99235617,0,-0.17763746,-1.0077027,0,0)"
|
||||
style="font-size:38.40000153px"
|
||||
x="112.74373"
|
||||
y="-306.75479">
|
||||
<tspan
|
||||
id="tspan3473-6-0-9"
|
||||
sodipodi:role="line"
|
||||
style="font-size:38.40000153px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#49608a;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:Denmark;-inkscape-font-specification:Denmark"
|
||||
x="112.74373"
|
||||
y="-306.75479">boost</tspan>
|
||||
</text>
|
||||
</g>
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none"
|
||||
d="m 201.43967,613.81579 4.64114,4.2175 3.3738,-3.71306 -0.92817,-0.84354 1.68708,-1.85636 20.53445,20.81026 4.2175,-4.64111 -22.22144,-18.95384 c 0,0 1.69594,-1.83698 2.53062,-2.78454 2.53905,-2.76559 5.98925,-4.72587 5.98925,-4.72587 0,0 -6.03647,0.58224 -8.76507,2.21476 -0.84428,0.92751 -6.75676,7.40649 -6.75676,7.40649 l -0.92819,-0.84355 -3.37382,3.71308"
|
||||
id="path13283"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccccccccc" />
|
||||
<g
|
||||
id="g3086"
|
||||
transform="matrix(0.99872217,-0.05053738,0.05053738,0.99872217,-31.539183,11.181538)">
|
||||
<path
|
||||
sodipodi:nodetypes="ccccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path13243"
|
||||
d="m 227.74101,611.16418 -15.09943,12.783 2.55659,3.01989 15.09944,-12.78302 c 3.56324,2.16769 7.58975,-1.2411 7.0464,-5.96538 l -4.02652,3.40879 -2.55659,-3.01989 4.02652,-3.40879 c -3.56324,-2.16769 -8.59639,2.0933 -7.04641,5.9654 z"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path13243-1"
|
||||
d="m 215.25729,626.9851 15.08951,-12.7947 -2.55893,-3.01791 -15.08952,12.79471 c -3.56492,-2.16491 -7.58878,1.24699 -7.04177,5.97085 l 4.02388,-3.41192 2.55892,3.01791 -4.02387,3.41192 c 3.56491,2.16492 8.59476,-2.09997 7.04178,-5.97086 z"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 20 KiB |
234
doc/main.qbk
Normal file
234
doc/main.qbk
Normal file
@ -0,0 +1,234 @@
|
||||
[/
|
||||
Copyright (c) 2021, Alan Freitas
|
||||
|
||||
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)
|
||||
|
||||
Official repository: https://github.com/boostorg/utility
|
||||
]
|
||||
|
||||
[/#############################################
|
||||
DOCUMENT INFO
|
||||
###############################################]
|
||||
|
||||
[library Boost.Utility
|
||||
[id utility]
|
||||
[quickbook 1.6]
|
||||
[copyright 2001 Beman Dawes]
|
||||
[purpose Utility Library]
|
||||
[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])
|
||||
]
|
||||
[authors [Dawes, Beman]]
|
||||
[category template]
|
||||
[category generic]
|
||||
]
|
||||
|
||||
[template mdash[]'''—''']
|
||||
[template ndash[]'''–''']
|
||||
[template sect[]'''§''']
|
||||
[template hellip[]'''…''']
|
||||
|
||||
[template indexterm1[term1]'''<indexterm><primary>'''[term1]'''</primary></indexterm>''']
|
||||
[template indexterm2[term1 term2]'''<indexterm><primary>'''[term1]'''</primary><secondary>'''[term2]'''</secondary></indexterm>''']
|
||||
|
||||
[template include_file[path][^<'''<ulink url="https://github.com/boostorg/utility/blob/master/include/'''[path]'''">'''[path]'''</ulink>'''>]]
|
||||
[template issue[n]'''<ulink url="https://github.com/boostorg/utility/issues/'''[n]'''">#'''[n]'''</ulink>''']
|
||||
|
||||
[/ Named Requirements ]
|
||||
|
||||
[def __Handler__ ['Handler]]
|
||||
[def __Allocator__ [@https://en.cppreference.com/w/cpp/named_req/Allocator ['Allocator]]]
|
||||
[def __CopyAssignable__ [@https://en.cppreference.com/w/cpp/named_req/CopyAssignable ['CopyAssignable]]]
|
||||
[def __CopyConstructible__ [@https://en.cppreference.com/w/cpp/named_req/CopyConstructible ['CopyConstructible]]]
|
||||
[def __Copyable__ [@https://en.cppreference.com/w/cpp/concepts/copyable ['Copyable]]]
|
||||
[def __DefaultConstructible__ [@https://en.cppreference.com/w/cpp/named_req/DefaultConstructible ['DefaultConstructible]]]
|
||||
[def __Hash__ [@https://en.cppreference.com/w/cpp/named_req/Hash ['Hash]]]
|
||||
[def __InputIterator__ [@https://en.cppreference.com/w/cpp/named_req/InputIterator ['InputIterator]]]
|
||||
[def __MoveAssignable__ [@https://en.cppreference.com/w/cpp/named_req/MoveAssignable ['MoveAssignable]]]
|
||||
[def __MoveConstructible__ [@https://en.cppreference.com/w/cpp/named_req/MoveConstructible ['MoveConstructible]]]
|
||||
[def __RandomAccessIterator__ [@https://en.cppreference.com/w/cpp/named_req/RandomAccessIterator ['RandomAccessIterator]]]
|
||||
[def __Regular__ [@https://en.cppreference.com/w/cpp/concepts/regular ['Regular]]]
|
||||
[def __Swappable__ [@https://en.cppreference.com/w/cpp/named_req/Swappable ['Swappable]]]
|
||||
|
||||
[/ Boost types ]
|
||||
[/ (Macros are defined here because these macros are often referenced in other components) ]
|
||||
[/ (operators macros link to the a table of operators because there's no doxygen reference for the operators) ]
|
||||
|
||||
[def __BOOST_BINARY__ [link sec:BOOST_BINARY `BOOST_BINARY`]]
|
||||
[def __in_place_factory__ [link sec:in_place_factory `in_place_factory`]]
|
||||
|
||||
[def __boost_base_from_member__ [link boost.base_from_member `boost::base_from_member`]]
|
||||
[def __boost_call_traits__ [link boost.call_traits `boost::call_traits`]]
|
||||
[def __boost_result_of__ [link boost.result_of `boost::result_of`]]
|
||||
[def __boost_tr1_result_of__ [link boost.tr1_result_of `boost::tr1_result_of`]]
|
||||
[def __boost_string_view__ [link boost.basic_string_view `boost::string_view`]]
|
||||
[def __boost_basic_string_view__ [link boost.basic_string_view `boost::basic_string_view`]]
|
||||
|
||||
[def __additive1__ [link sec:arithmetic `additive1`]]
|
||||
[def __additive2__ [link sec:arithmetic `additive2`]]
|
||||
[def __arithmetic1__ [link sec:arithmetic `arithmetic1`]]
|
||||
[def __arithmetic2__ [link sec:arithmetic `arithmetic2`]]
|
||||
[def __base_from_member__ [link boost.base_from_member `base_from_member`]]
|
||||
[def __basic_string_ref__ [link boost.basic_string_view `basic_string_ref`]]
|
||||
[def __basic_string_view__ [link boost.basic_string_view `basic_string_view`]]
|
||||
[def __bidirectional_iteratable__ [link sec:arithmetic `bidirectional_iteratable`]]
|
||||
[def __bidirectional_iterator_helper__ [link sec:arithmetic `bidirectional_iterator_helper`]]
|
||||
[def __bitwise1__ [link sec:arithmetic `bitwise1`]]
|
||||
[def __bitwise2__ [link sec:arithmetic `bitwise2`]]
|
||||
[def __call_traits__ [link boost.call_traits `call_traits`]]
|
||||
[def __call_traits_T__ [link boost.call_traits `call_traits<T>`]]
|
||||
[def __call_traits_lt__T___ [link boost.call_traits `call_traits<T&>`]]
|
||||
[def __call_traits_lt__T_lb_N_rb__gt___ [link boost.call_traits `call_traits< T[N]>`]]
|
||||
[def __call_traits_lt__const_T_lb_N_rb__gt___ [link boost.call_traits `call_traits< const T[N]>`]]
|
||||
[def __compressed_pair__ [link boost.compressed_pair `compressed_pair`]]
|
||||
[def __decrementable__ [link sec:arithmetic `decrementable`]]
|
||||
[def __dereferenceable__ [link sec:arithmetic `dereferenceable`]]
|
||||
[def __equal_pointees__ [link sec:arithmetic `equal_pointees`]]
|
||||
[def __equal_pointees_t__ [link sec:arithmetic `equal_pointees_t`]]
|
||||
[def __equality_comparable1__ [link sec:arithmetic `equality_comparable1`]]
|
||||
[def __equality_comparable2__ [link sec:arithmetic `equality_comparable2`]]
|
||||
[def __equivalent1__ [link sec:arithmetic `equivalent1`]]
|
||||
[def __equivalent2__ [link sec:arithmetic `equivalent2`]]
|
||||
[def __euclidean_ring_operators1__ [link sec:arithmetic `euclidean_ring_operators1`]]
|
||||
[def __euclidean_ring_operators2__ [link sec:arithmetic `euclidean_ring_operators2`]]
|
||||
[def __field_operators1__ [link sec:arithmetic `field_operators1`]]
|
||||
[def __field_operators2__ [link sec:arithmetic `field_operators2`]]
|
||||
[def __forward_iteratable__ [link sec:arithmetic `forward_iteratable`]]
|
||||
[def __forward_iterator_helper__ [link sec:arithmetic `forward_iterator_helper`]]
|
||||
[def __get__ [link boost.get `get`]]
|
||||
[def __hash_range__ [link boost.hash_range `hash_range`]]
|
||||
[def __hash_value__ [link boost.hash_value `hash_value`]]
|
||||
[def __in_place_factory_base__ [link boost.in_place_factory_base `in_place_factory_base`]]
|
||||
[def __incrementable__ [link sec:arithmetic `incrementable`]]
|
||||
[def __indexable__ [link sec:arithmetic `indexable`]]
|
||||
[def __initialized__ [link boost.initialized `initialized`]]
|
||||
[def __initialized_value__ [link boost.initialized_value `initialized_value`]]
|
||||
[def __initialized_value_t__ [link boost.initialized_value_t `initialized_value_t`]]
|
||||
[def __input_iteratable__ [link sec:arithmetic `input_iteratable`]]
|
||||
[def __input_iterator_helper__ [link sec:arithmetic `input_iterator_helper`]]
|
||||
[def __integer_arithmetic1__ [link sec:arithmetic `integer_arithmetic1`]]
|
||||
[def __integer_arithmetic2__ [link sec:arithmetic `integer_arithmetic2`]]
|
||||
[def __integer_multiplicative1__ [link sec:arithmetic `integer_multiplicative1`]]
|
||||
[def __integer_multiplicative2__ [link sec:arithmetic `integer_multiplicative2`]]
|
||||
[def __is_chained_base__ [link sec:arithmetic `is_chained_base`]]
|
||||
[def __less_pointees__ [link boost.less_pointees `less_pointees`]]
|
||||
[def __less_pointees_t__ [link boost.less_pointees_t `less_pointees_t`]]
|
||||
[def __less_than_comparable1__ [link sec:arithmetic `less_than_comparable1`]]
|
||||
[def __less_than_comparable2__ [link sec:arithmetic `less_than_comparable2`]]
|
||||
[def __multiplicative1__ [link sec:arithmetic `multiplicative1`]]
|
||||
[def __multiplicative2__ [link sec:arithmetic `multiplicative2`]]
|
||||
[def __operator_eq__eq__ [link sec:arithmetic `operator==`]]
|
||||
[def __operator_gt__ [link sec:arithmetic `operator_gt_`]]
|
||||
[def __operator_gt__eq__ [link sec:arithmetic `operator>`]]
|
||||
[def __operator_lt__ [link sec:arithmetic `operator<`]]
|
||||
[def __operator_lt__eq__ [link sec:arithmetic `operator<=`]]
|
||||
[def __operator_lt__lt__ [link sec:arithmetic `operator<<`]]
|
||||
[def __operator_not__eq__ [link sec:arithmetic `operator!=`]]
|
||||
[def __operators2__ [link sec:arithmetic `operators2`]]
|
||||
[def __operators__ [link sec:arithmetic `operators`]]
|
||||
[def __operators_lt_T__ [link sec:arithmetic `operators<T,T>`]]
|
||||
[def __ordered_euclidean_ring_operators1__ [link sec:arithmetic `ordered_euclidean_ring_operators1`]]
|
||||
[def __ordered_euclidean_ring_operators2__ [link sec:arithmetic `ordered_euclidean_ring_operators2`]]
|
||||
[def __ordered_euclidian_ring_operators1__ [link sec:arithmetic `ordered_euclidian_ring_operators1`]]
|
||||
[def __ordered_euclidian_ring_operators2__ [link sec:arithmetic `ordered_euclidian_ring_operators2`]]
|
||||
[def __ordered_field_operators1__ [link sec:arithmetic `ordered_field_operators1`]]
|
||||
[def __ordered_field_operators2__ [link sec:arithmetic `ordered_field_operators2`]]
|
||||
[def __ordered_ring_operators1__ [link sec:arithmetic `ordered_ring_operators1`]]
|
||||
[def __ordered_ring_operators2__ [link sec:arithmetic `ordered_ring_operators2`]]
|
||||
[def __output_iteratable__ [link sec:arithmetic `output_iteratable`]]
|
||||
[def __output_iterator_helper__ [link sec:arithmetic `output_iterator_helper`]]
|
||||
[def __partially_ordered1__ [link sec:arithmetic `partially_ordered1`]]
|
||||
[def __partially_ordered2__ [link sec:arithmetic `partially_ordered2`]]
|
||||
[def __random_access_iteratable__ [link sec:arithmetic `random_access_iteratable`]]
|
||||
[def __random_access_iterator_helper__ [link sec:arithmetic `random_access_iterator_helper`]]
|
||||
[def __result_of__ [link boost.result_of `result_of`]]
|
||||
[def __ring_operators1__ [link sec:arithmetic `ring_operators1`]]
|
||||
[def __ring_operators2__ [link sec:arithmetic `ring_operators2`]]
|
||||
[def __shiftable1__ [link sec:arithmetic `shiftable1`]]
|
||||
[def __shiftable2__ [link sec:arithmetic `shiftable2`]]
|
||||
[def __string_ref__ [link boost.basic_string_view `string_ref`]]
|
||||
[def __string_view__ [link boost.basic_string_view `string_view`]]
|
||||
[def __swap__ [link sec:arithmetic `swap`]]
|
||||
[def __totally_ordered1__ [link sec:arithmetic `totally_ordered1`]]
|
||||
[def __totally_ordered2__ [link sec:arithmetic `totally_ordered2`]]
|
||||
[def __tr1_result_of__ [link boost.tr1_result_of `tr1_result_of`]]
|
||||
[def __typed_in_place_factory_base__ [link boost.typed_in_place_factory_base `typed_in_place_factory_base`]]
|
||||
[def __u16string_ref__ [link boost.basic_string_view `u16string_ref`]]
|
||||
[def __u16string_view__ [link boost.basic_string_view `u16string_view`]]
|
||||
[def __u32string_ref__ [link boost.basic_string_view `u32string_ref`]]
|
||||
[def __u32string_view__ [link boost.basic_string_view `u32string_view`]]
|
||||
[def __unit_steppable__ [link sec:arithmetic `unit_steppable`]]
|
||||
[def __value_initialized__ [link boost.value_initialized `value_initialized`]]
|
||||
[def __wstring_ref__ [link boost.basic_string_view `wstring_ref`]]
|
||||
[def __wstring_view__ [link boost.basic_string_view `wstring_view`]]
|
||||
|
||||
[/ std:: types ]
|
||||
|
||||
[def __assert__ [@https://en.cppreference.com/w/cpp/error/assert `assert`]]
|
||||
[def __decltype__ [@https://en.cppreference.com/w/cpp/language/decltype `decltype`]]
|
||||
[def __initializer_list__ [@https://en.cppreference.com/w/cpp/utility/initializer_list `std::initializer_list`]]
|
||||
[def __nullptr__ [@https://en.cppreference.com/w/cpp/language/nullptr `nullptr`]]
|
||||
[def __std_addressof__ [@https://en.cppreference.com/w/cpp/memory/addressof `std::addressof`]]
|
||||
[def __std_array__ [@https://en.cppreference.com/w/cpp/container/array `std::array`]]
|
||||
[def __std_basic_string__ [@https://en.cppreference.com/w/cpp/string/basic_string `std::basic_string`]]
|
||||
[def __std_basic_string_view__ [@https://en.cppreference.com/w/cpp/string/basic_string_view `std::basic_string_view`]]
|
||||
[def __std_binder1st__ [@https://en.cppreference.com/w/cpp/utility/functional/binder12 `std::binder1st`]]
|
||||
[def __std_complex__ [@https://en.cppreference.com/w/cpp/numeric/complex `std::complex`]]
|
||||
[def __std_declval__ [@https://en.cppreference.com/w/cpp/utility/declval `std::declval`]]
|
||||
[def __std_enable_if__ [@https://en.cppreference.com/w/cpp/types/enable_if `std::enable_if`]]
|
||||
[def __std_enable_if_t__ [@https://en.cppreference.com/w/cpp/types/enable_if `std::enable_if_t`]]
|
||||
[def __std_fill__ [@https://en.cppreference.com/w/cpp/algorithm/fill `std::fill`]]
|
||||
[def __std_hash__ [@https://en.cppreference.com/w/cpp/utility/hash `std::hash`]]
|
||||
[def __std_initializer_list__ [@https://en.cppreference.com/w/cpp/utility/initializer_list `std::initializer_list`]]
|
||||
[def __std_is_nothrow_constructible__ [@https://en.cppreference.com/w/cpp/types/is_constructible `std::is_nothrow_constructible`]]
|
||||
[def __std_make_pair__ [@https://en.cppreference.com/w/cpp/utility/pair/make_pair `std::make_pair`]]
|
||||
[def __std_memory_resource__ [@https://en.cppreference.com/w/cpp/memory/memory_resource `std::pmr::memory_resource`]]
|
||||
[def __std_memset__ [@https://en.cppreference.com/w/cpp/string/byte/memset `std::memset`]]
|
||||
[def __std_next__ [@https://en.cppreference.com/w/cpp/iterator/next `std::next`]]
|
||||
[def __std_nullptr_t__ [@https://en.cppreference.com/w/cpp/types/nullptr_t `std::nullptr_t`]]
|
||||
[def __std_ostream__ [@https://en.cppreference.com/w/cpp/io/basic_ostream `std::ostream`]]
|
||||
[def __std_ostream__ [@https://en.cppreference.com/w/cpp/io/basic_ostream `__std_ostream__`]]
|
||||
[def __std_pair__ [@https://en.cppreference.com/w/cpp/utility/pair `std::pair`]]
|
||||
[def __std_polymorphic_allocator__ [@https://en.cppreference.com/w/cpp/memory/polymorphic_allocator `std::pmr::polymorphic_allocator`]]
|
||||
[def __std_prev__ [@https://en.cppreference.com/w/cpp/iterator/prev `std::prev`]]
|
||||
[def __std_ptrdiff_t__ [@https://en.cppreference.com/w/cpp/types/ptrdiff_t `std::ptrdiff_t`]]
|
||||
[def __std_remove__ [@https://en.cppreference.com/w/cpp/algorithm/remove `std::remove`]]
|
||||
[def __std_result_of__ [@https://en.cppreference.com/w/cpp/types/result_of `std::result_of`]]
|
||||
[def __std_sort__ [@https://en.cppreference.com/w/cpp/algorithm/sort `std::sort`]]
|
||||
[def __std_streambuf__ [@https://en.cppreference.com/w/cpp/header/streambuf `std::streambuf`]]
|
||||
[def __std_string__ [@https://en.cppreference.com/w/cpp/string/basic_string `std::string`]]
|
||||
[def __std_string_view__ [@https://en.cppreference.com/w/cpp/string/basic_string_view `std::string_view`]]
|
||||
[def __std_unary_function__ [@https://en.cppreference.com/w/cpp/utility/functional/unary_function `std::unary_function`]]
|
||||
[def __std_unordered_map__ [@https://en.cppreference.com/w/cpp/container/unordered_map `std::unordered_map`]]
|
||||
[def __std_uses_allocator__ [@https://en.cppreference.com/w/cpp/memory/uses_allocator `std::uses_allocator`]]
|
||||
[def __std_vector__ [@https://en.cppreference.com/w/cpp/container/vector `std::vector`]]
|
||||
|
||||
[/ Dingbats ]
|
||||
|
||||
[def __good__ [role green \u2714]]
|
||||
[def __bad__ [role red \u2718]]
|
||||
|
||||
[/-----------------------------------------------------------------------------]
|
||||
|
||||
[include overview.qbk]
|
||||
|
||||
[include utilities.qbk]
|
||||
|
||||
[include other.qbk]
|
||||
|
||||
[#sec:reference]
|
||||
[section:ref Quick Reference]
|
||||
|
||||
[/ Reference table ]
|
||||
[xinclude quickref.xml]
|
||||
|
||||
[/ Generated reference files ]
|
||||
[/ [include reference.qbk] ]
|
||||
|
||||
[/ Generated index ]
|
||||
[/ [xinclude index.xml] ]
|
||||
|
||||
[endsect]
|
2008
doc/operators.qbk
Normal file
2008
doc/operators.qbk
Normal file
File diff suppressed because it is too large
Load Diff
29
doc/other.qbk
Normal file
29
doc/other.qbk
Normal file
@ -0,0 +1,29 @@
|
||||
[/
|
||||
Copyright (c) 2021 Alan de Freitas (alandefreitas@gmail.com)
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
Official repository: https://github.com/boostorg/utility
|
||||
]
|
||||
|
||||
[section:utilities More Utilities]
|
||||
|
||||
Some utilities have been moved from Boost.Utilities to more appropriate Boost libraries:
|
||||
|
||||
# Moved to [@boost:/libs/core/index.html Boost.Core]
|
||||
# [@boost:/libs/core/doc/html/core/addressof.html addressof]
|
||||
# [@boost:/libs/core/doc/html/core/checked_delete.html checked_delete]
|
||||
# [@boost:/libs/core/doc/html/core/enable_if.html enable_if]
|
||||
# [@boost:/libs/core/doc/html/core/noncopyable.html noncopyable]
|
||||
# Moved to [@boost:/libs/type_traits/index.html Boost.TypeTraits]
|
||||
# [@boost:/libs/type_traits/doc/html/boost_typetraits/reference/declval.html declval]
|
||||
# Moved to [@boost:/libs/iterator/index.html Boost.Iterator]
|
||||
# [@boost:/libs/iterator/doc/generator_iterator.htm generator iterator adaptors]
|
||||
# [@boost:/libs/iterator/doc/html/iterator/algorithms/next_prior.html next/prior]
|
||||
# Moved to [@boost:/libs/io/index.html Boost.IO]
|
||||
# [@boost:/libs/io/doc/html/io.html ostream_string]
|
||||
# Moved to [@boost:/libs/throw_exception/index.html Boost.ThrowException]
|
||||
# [@boost:/libs/throw_exception/doc/html/throw_exception.html#using_boost_throw_exception throw_exception]
|
||||
|
||||
[endsect]
|
46
doc/overview.qbk
Normal file
46
doc/overview.qbk
Normal file
@ -0,0 +1,46 @@
|
||||
[/
|
||||
Copyright (c) 2021 Alan de Freitas (alandefreitas@gmail.com)
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
Official repository: https://github.com/boostorg/utility
|
||||
]
|
||||
|
||||
[section Overview]
|
||||
[block'''<?dbhtml stop-chunking?>''']
|
||||
|
||||
Boost.Utility is a collection of small, useful, and general-purpose components for language support.
|
||||
|
||||
Over time,
|
||||
|
||||
* several components have been moved to more appropriate Boost libraries and
|
||||
* many of these components had variants accepted into the C++ standard
|
||||
|
||||
When the component has moved to another Boost library, Boost.Utility headers still lead to the appropriate headers
|
||||
in other libraries.
|
||||
|
||||
[table:id Components
|
||||
[[Boost.Utility] [Moved to Boost] [C++ Standard variant]]
|
||||
[[[@boost:/libs/core/doc/html/core/addressof.html `addressof`]] [[@boost:/libs/core/index.html Boost.Core]] [C++11 __std_addressof__]]
|
||||
[[__base_from_member__] [] []]
|
||||
[[__BOOST_BINARY__] [] [C++14 [@https://en.cppreference.com/w/cpp/language/integer_literal Binary integer literal]]]
|
||||
[[__call_traits__] [] []]
|
||||
[[[@boost:/libs/core/doc/html/core/checked_delete.html `checked_delete`]] [[@boost:/libs/core/index.html Boost.Core]] []]
|
||||
[[__compressed_pair__] [] []]
|
||||
[[[@boost:/libs/type_traits/doc/html/boost_typetraits/reference/declval.html `declval`]] [[@boost:/libs/type_traits/index.html Boost.TypeTraits]] [C++11 __std_declval__]]
|
||||
[[[@boost:/libs/core/doc/html/core/enable_if.html `enable_if`]] [[@boost:/libs/core/index.html Boost.Core]] [C++11 __std_enable_if__]]
|
||||
[[[@boost:/libs/iterator/doc/generator_iterator.htm generator iterator adaptors]] [[@boost:/libs/iterator/index.html Boost.Iterator]] []]
|
||||
[[__in_place_factory__] [] []]
|
||||
[[[@boost:/libs/iterator/index.html `iterator_adaptors`]] [[@boost:/libs/iterator/index.html Boost.Iterator]] []]
|
||||
[[[@boost:/libs/iterator/doc/html/iterator/algorithms/next_prior.html `next` / `prior`]] [[@boost:/libs/iterator/index.html Boost.Iterator]] [C++11 __std_next__ / __std_prev__]]
|
||||
[[[@boost:/libs/core/doc/html/core/noncopyable.html `noncopyable`]] [[@boost:/libs/core/index.html Boost.Core]] []]
|
||||
[[[link sec:operators `operators`]] [] []]
|
||||
[[[@boost:/libs/io/doc/html/io.html `ostream_string`]] [[@boost:/libs/io/index.html Boost.IO]] []]
|
||||
[[__result_of__] [] [C++11 __std_result_of__]]
|
||||
[[__string_view__] [] [C++17 __std_string_view__]]
|
||||
[[[@boost:/libs/throw_exception/doc/html/throw_exception.html#using_boost_throw_exception `throw_exception`]] [[@boost:/libs/throw_exception/index.html Boost.ThrowException]] []]
|
||||
[[[link sec:value_init `value_init`]] [] [C++11 [@https://en.cppreference.com/w/cpp/language/list_initialization List initialization]]]
|
||||
]
|
||||
|
||||
[endsect]
|
497
doc/quickref.xml
Normal file
497
doc/quickref.xml
Normal file
@ -0,0 +1,497 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "../../../tools/boostbook/dtd/boostbook.dtd">
|
||||
|
||||
<!--
|
||||
Copyright (c) 2021, Alan Freitas
|
||||
|
||||
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
|
||||
-->
|
||||
|
||||
<!-- See also https://tdg.docbook.org/tdg/5.1/ -->
|
||||
|
||||
<!-- Doxygen reference -->
|
||||
<informaltable frame="all">
|
||||
<tgroup cols="4">
|
||||
<colspec colname="a"/>
|
||||
<colspec colname="b"/>
|
||||
<colspec colname="c"/>
|
||||
<colspec colname="d"/>
|
||||
|
||||
<thead>
|
||||
<row>
|
||||
<entry valign="center" namest="a" nameend="a">
|
||||
<bridgehead renderas="sect2">Base from Member</bridgehead>
|
||||
</entry>
|
||||
<entry valign="center" namest="b" nameend="b">
|
||||
<bridgehead renderas="sect2">Call Traits</bridgehead>
|
||||
</entry>
|
||||
<entry valign="center" namest="c" nameend="c">
|
||||
<bridgehead renderas="sect2">Compressed Pair</bridgehead>
|
||||
</entry>
|
||||
<entry valign="center" namest="d" nameend="d">
|
||||
<bridgehead renderas="sect2">In-place Factory</bridgehead>
|
||||
</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<!-- base_from_member -->
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Classes</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="boost.base_from_member">base_from_member</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
|
||||
<!-- call_traits -->
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Type Traits</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="boost.call_traits">call_traits</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="boost.call_traits">call_traits<T&></link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="boost.call_traits">call_traits<T[N]>
|
||||
</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="boost.call_traits">call_traits<const
|
||||
T[N]>
|
||||
</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
|
||||
<!-- compressed_pair -->
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Classes</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="boost.compressed_pair">compressed_pair</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
|
||||
<bridgehead renderas="sect3">Functions</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="header.boost.detail.compressed_pair_hpp">swap</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
|
||||
<!-- in_place_factory -->
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Classes</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="boost.in_place_factory_base">in_place_factory_base</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="boost.typed_in_place_factory_base">typed_in_place_factory_base
|
||||
</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
|
||||
<tgroup cols="5">
|
||||
<colspec colname="a"/>
|
||||
<colspec colname="b"/>
|
||||
<colspec colname="c"/>
|
||||
<colspec colname="d"/>
|
||||
<colspec colname="e"/>
|
||||
|
||||
<thead>
|
||||
<row>
|
||||
<entry valign="center" namest="a" nameend="e">
|
||||
<bridgehead renderas="sect2">Operators</bridgehead>
|
||||
</entry>
|
||||
</row>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<row>
|
||||
<entry valign="top">
|
||||
<!-- 13 classes per cell -->
|
||||
<bridgehead renderas="sect3">Classes (1 of 5)</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">additive1</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">additive2</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">arithmetic1</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">arithmetic2</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">bidirectional_iteratable</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">
|
||||
bidirectional_iterator_helper
|
||||
</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">bitwise1</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">bitwise2</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">decrementable</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">dereferenceable</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">equality_comparable1</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">equality_comparable2</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">equivalent1</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Classes (2 of 5)</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">equivalent2</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">euclidean_ring_operators1
|
||||
</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">euclidean_ring_operators2
|
||||
</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">field_operators1</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">field_operators2</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">forward_iteratable</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">forward_iterator_helper</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">incrementable</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">indexable</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">input_iteratable</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">input_iterator_helper</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">integer_arithmetic1</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">integer_arithmetic2</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Classes (3 of 5)</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">integer_multiplicative1</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">integer_multiplicative2</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">is_chained_base</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">less_than_comparable1</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">less_than_comparable2</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">multiplicative1</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">multiplicative2</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">operators</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">operators2</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">operators<T,T></link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">
|
||||
ordered_euclidean_ring_operators1
|
||||
</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">
|
||||
ordered_euclidean_ring_operators2
|
||||
</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">
|
||||
ordered_euclidian_ring_operators1
|
||||
</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Classes (4 of 5)</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">
|
||||
ordered_euclidian_ring_operators2
|
||||
</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">ordered_field_operators1</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">ordered_field_operators2</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">ordered_ring_operators1</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">ordered_ring_operators2</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">output_iteratable</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">output_iterator_helper</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">partially_ordered1</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">partially_ordered2</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">random_access_iteratable</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">
|
||||
random_access_iterator_helper
|
||||
</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">ring_operators1</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">ring_operators2</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Classes (5 of 5)</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">shiftable1</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">shiftable2</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">totally_ordered1</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">totally_ordered2</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">unit_steppable</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
<bridgehead renderas="sect3">Type Traits</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="sec:arithmetic">is_chained_base</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
|
||||
<tgroup cols="5">
|
||||
<colspec colname="a"/>
|
||||
<colspec colname="b"/>
|
||||
<colspec colname="c"/>
|
||||
<colspec colname="d"/>
|
||||
<colspec colname="e"/>
|
||||
|
||||
<thead>
|
||||
<row>
|
||||
<entry valign="center" namest="a" nameend="a">
|
||||
<bridgehead renderas="sect2">Result of</bridgehead>
|
||||
</entry>
|
||||
<entry valign="center" namest="b" nameend="d">
|
||||
<bridgehead renderas="sect2">String View</bridgehead>
|
||||
</entry>
|
||||
<entry valign="center" namest="e" nameend="e">
|
||||
<bridgehead renderas="sect2">Value Init</bridgehead>
|
||||
</entry>
|
||||
</row>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<row>
|
||||
<!-- result_of -->
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Type Traits</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="boost.result_of">result_of</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="boost.tr1_result_of">tr1_result_of</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
|
||||
<!-- string_view -->
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Aliases</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="boost.basic_string_view">string_view</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="boost.basic_string_view">u16string_ref</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="boost.basic_string_view">u16string_view</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="boost.basic_string_view">u32string_ref</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="boost.basic_string_view">u32string_view</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="boost.basic_string_view">wstring_ref</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="boost.basic_string_view">wstring_view</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="boost.basic_string_view">string_ref</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Classes</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="boost.basic_string_view">basic_string_ref</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="boost.basic_string_view">basic_string_view</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
<bridgehead renderas="sect3">Functions</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="boost.hash_range">hash_range</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="boost.hash_value">hash_value</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Operators</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="header.boost.utility.string_view_hpp">operator==</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="header.boost.utility.string_view_hpp">operator!=</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="header.boost.utility.string_view_hpp">operator<</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="header.boost.utility.string_view_hpp">operator<=</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="header.boost.utility.string_view_hpp">operator></link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="header.boost.utility.string_view_hpp">operator>=</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="header.boost.utility.string_view_hpp">operator<<</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
|
||||
<!-- value_init -->
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Classes</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="boost.initialized">initialized</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="boost.initialized_value_t">initialized_value_t</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="boost.value_initialized">value_initialized</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
<bridgehead renderas="sect3">Functions</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="header.boost.utility.value_init_hpp">get</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="header.boost.utility.value_init_hpp">swap</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
<bridgehead renderas="sect3">Constants</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member>
|
||||
<link linkend="boost.initialized_value">initialized_value</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
421
doc/result_of.qbk
Normal file
421
doc/result_of.qbk
Normal file
@ -0,0 +1,421 @@
|
||||
[/
|
||||
/ Copyright (c) 2012 Marshall Clow
|
||||
/ Copyright (c) 2021, Alan Freitas
|
||||
/
|
||||
/ 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 Result of]
|
||||
[/===============]
|
||||
|
||||
[section Introduction]
|
||||
|
||||
The class template __result_of__ helps determine the type of a
|
||||
call expression. For example, given an lvalue `f` of type `F`
|
||||
and lvalues `t1`,`t2`, ..., `tN` of types `T1`, `T2`, ..., `TN`,
|
||||
respectively, the type __result_of__`<F(T1, T2, ..., TN)>::type` defines
|
||||
the result type of the expression `f(t1, t2, ...,tN)`.
|
||||
|
||||
This implementation permits the type `F` to be a function pointer,
|
||||
function reference, member function pointer, or class type. By default,
|
||||
N may be any value between 0 and 16. To change the upper limit, define
|
||||
the macro `BOOST_RESULT_OF_NUM_ARGS` to the maximum value for N. Class
|
||||
template __result_of__ resides in the header
|
||||
[@../../../../boost/utility/result_of.hpp `<boost/utility/result_of.hpp>`].
|
||||
|
||||
If your compiler's support for __decltype__ is adequate, __result_of__
|
||||
automatically uses it to deduce the type of the call expression, in
|
||||
which case __result_of__`<F(T1, T2, ..., TN)>::type` names the type
|
||||
__decltype__`(boost::declval<F>()(boost::declval<T1>(),
|
||||
boost::declval<T2>(), ..., boost::declval<TN>()))`, as in the
|
||||
following example.
|
||||
|
||||
```
|
||||
struct functor {
|
||||
template<class T>
|
||||
T operator()(T x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
||||
typedef __boost_result_of__<functor(int)>::type type; // type is int
|
||||
```
|
||||
|
||||
You can test whether __result_of__ is using __decltype__ by checking if
|
||||
the macro `BOOST_RESULT_OF_USE_DECLTYPE` is defined after
|
||||
including `result_of.hpp`. You can also force __result_of__ to use
|
||||
__decltype__ by defining `BOOST_RESULT_OF_USE_DECLTYPE` prior
|
||||
to including `result_of.hpp`.
|
||||
|
||||
If __decltype__ is not used, then automatic result type deduction of function
|
||||
objects is not possible. Instead, __result_of__ uses the following protocol
|
||||
to allow the programmer to specify a type. When `F` is a class type with a
|
||||
member type `result_type`, `result_of<F(T1, T2, ..., TN)>::type` is
|
||||
`F::result_type`. When `F` does not contain `result_type`,
|
||||
`result_of<F(T1, T2, ..., TN)>::type` is
|
||||
`F::result<F(T1, T2, ..., TN)>::type` when
|
||||
`N > 0` or `void` when `N = 0`.
|
||||
|
||||
Note that it is the responsibility of the programmer to ensure that
|
||||
function objects accurately advertise their result
|
||||
type via this protocol, as in the following example.
|
||||
|
||||
```
|
||||
struct functor {
|
||||
template <class> struct result;
|
||||
|
||||
template<class F, class T>
|
||||
struct result<F(T)> {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
T operator()(T x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
||||
typedef __boost_result_of__<functor(int)>::type type; // type is int
|
||||
```
|
||||
|
||||
Since __decltype__ is a language feature standardized in C++11, if you are
|
||||
writing a function object to be used with __result_of__, for maximum
|
||||
portability, you might consider following the above protocol
|
||||
even if your compiler has proper __decltype__ support.
|
||||
|
||||
If you wish to continue to use the protocol on compilers that
|
||||
support __decltype__, there are two options:
|
||||
|
||||
* You can use __boost_tr1_result_of__, which is also defined in
|
||||
[@../../../boost/utility/result_of.hpp `<boost/utility/result_of.hpp>`].
|
||||
|
||||
* Alternatively, you can define the macro `BOOST_RESULT_OF_USE_TR1`,
|
||||
which causes __result_of__ to use the protocol described above instead
|
||||
of __decltype__. If you choose to follow the protocol, take care to
|
||||
ensure that the `result_type` and `result<>` members accurately
|
||||
represent the return type of `operator()` given a call expression.
|
||||
|
||||
Additionally, __boost_result_of__ provides a third mode of operation,
|
||||
which some users may find convenient. When
|
||||
`BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK` is defined,
|
||||
__boost_result_of__ behaves as follows. If the function object has a member
|
||||
type `result_type` or member template `result<>`, then __boost_result_of__
|
||||
will use the TR1 protocol.
|
||||
|
||||
Otherwise, __boost_result_of__ will use __decltype__. Using TR1 with
|
||||
a __decltype__ fallback may workaround certain problems at the cost of portability.
|
||||
For example:
|
||||
|
||||
* Deficient compiler: If your code requires __boost_result_of__ to work
|
||||
with incomplete return types but your compiler's __decltype__ implementation
|
||||
does not support incomplete return types, then you can use the TR1 protocol
|
||||
as a workaround. Support for incomplete return types was added late in the
|
||||
C++11 standardization process
|
||||
(see [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3276.pdf N3276])
|
||||
and is not implemented by some compilers.
|
||||
|
||||
* Deficient legacy code: If your existing TR1 function object advertises a different type than
|
||||
the actual result type deduced by __decltype__, then using TR1 with a __decltype__ fallback
|
||||
will allow you to work with both your existing TR1 function objects and new C++11
|
||||
function object. This situation could occur if your legacy function objects
|
||||
misused the TR1 protocol. See the documentation on known [link sec:result_of_tr1_diff differences]
|
||||
between __boost_result_of__ and TR1.
|
||||
|
||||
* [#BOOST_NO_RESULT_OF] This implementation of __result_of__ requires class template
|
||||
partial specialization, the ability to parse function types properly, and support
|
||||
for SFINAE. If __result_of__ is not supported by your compiler, including the header
|
||||
[@../../../boost/utility/result_of.hpp `<boost/utility/result_of.hpp>`] will define
|
||||
the macro `BOOST_NO_RESULT_OF`.
|
||||
|
||||
For additional information about __result_of__, see the C++ Library
|
||||
Technical Report, [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf N1836],
|
||||
or, for motivation and design rationale, the __result_of__
|
||||
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1454.html proposal].
|
||||
|
||||
[endsect]
|
||||
|
||||
[#sec:result_of_guidelines]
|
||||
[section Usage guidelines for __boost_result_of__]
|
||||
|
||||
The following are general suggestions about when and how to use __boost_result_of__.
|
||||
|
||||
# If you are targeting C++11 and are not concerned about portability to
|
||||
non-compliant compilers or previous versions of the standard, then use
|
||||
`__std_result_of__`. If `__std_result_of__` meets your needs, then
|
||||
there's no reason to stop using it.
|
||||
|
||||
# If you are targeting C++11 but may port your code to legacy compilers
|
||||
at some time in the future, then use __boost_result_of__ with __decltype__.
|
||||
When __decltype__ is used __boost_result_of__ and `__std_result_of__` are usually
|
||||
interchangeable. See the documentation on known [link sec:result_of_cxx11_diff differences]
|
||||
between __boost_result_of__ and C++11 __std_result_of__.
|
||||
|
||||
# If compiler portability is required, use __boost_result_of__ with the TR1 protocol
|
||||
|
||||
Regardless of how you configure __boost_result_of__, it is
|
||||
important to bear in mind that the return type of a
|
||||
function may change depending on its arguments, and
|
||||
additionally, the return type of a member function may
|
||||
change depending on the cv-qualification of the
|
||||
object. __boost_result_of__ must be passed
|
||||
the appropriately cv-qualified types in order to
|
||||
deduce the corresponding return type.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
struct functor {
|
||||
int& operator()(int);
|
||||
int const& operator()(int) const;
|
||||
|
||||
float& operator()(float&);
|
||||
float const& operator()(float const&);
|
||||
};
|
||||
|
||||
typedef __boost_result_of__<
|
||||
functor(int)
|
||||
>::type type1; // type1 is int &
|
||||
|
||||
typedef __boost_result_of__<
|
||||
const functor(int)
|
||||
>::type type2; // type2 is int const &
|
||||
|
||||
typedef __boost_result_of__<
|
||||
functor(float&)
|
||||
>::type type3; // type3 is float &
|
||||
|
||||
typedef __boost_result_of__<
|
||||
functor(float const&)
|
||||
>::type type4; // type4 is float const &
|
||||
```
|
||||
|
||||
[endsect]
|
||||
|
||||
[#sec:result_of_tr1_protocol_guidelines]
|
||||
[section Usage guidelines for the TR1 result_of protocol]
|
||||
|
||||
On compliant C++11 compilers, __boost_result_of__ can
|
||||
use __decltype__ to deduce the type of any
|
||||
call expression, including calls to function
|
||||
objects. However, on pre-C++11 compilers or on
|
||||
compilers without adequate decltype support,
|
||||
additional scaffolding is needed from function
|
||||
objects as described above. The following are
|
||||
suggestions about how to use the TR1 protocol.
|
||||
|
||||
* When the return type does not depend on the
|
||||
argument types or the cv-qualification of the
|
||||
function object, simply
|
||||
define `result_type`. There is no need
|
||||
to use the `result` template unless the
|
||||
return type varies.</li>
|
||||
|
||||
* Use the protocol specified type when defining
|
||||
function prototypes. This can help ensure the
|
||||
actual return type does not get out of sync with
|
||||
the protocol specification. For example:
|
||||
|
||||
```
|
||||
struct functor {
|
||||
typedef int result_type;
|
||||
result_type operator()(int);
|
||||
};
|
||||
```
|
||||
|
||||
* Always specify the `result` specialization near the corresponding
|
||||
`operator()` overload. This can make it easier to keep the specializations
|
||||
in sync with the overloads. For example:
|
||||
|
||||
```
|
||||
struct functor {
|
||||
template<class> struct result;
|
||||
|
||||
template<class F>
|
||||
struct result<F(int)> {
|
||||
typedef int& type;
|
||||
};
|
||||
result<functor(int)>::type operator()(int);
|
||||
|
||||
template<class F>
|
||||
struct result<const F(int)> {
|
||||
typedef int const& type;
|
||||
};
|
||||
result<const functor(int)>::type operator()(int) const;
|
||||
};
|
||||
```
|
||||
|
||||
* Use type transformations to simplify
|
||||
the `result` template specialization. For
|
||||
example, the following uses [@../type_traits/doc/html/index.html Boost.TypeTraits]
|
||||
to specialize the `result` template for
|
||||
a single `operator()` that can be called on
|
||||
both a const and non-const function object with
|
||||
either an lvalue or rvalue argument.
|
||||
|
||||
```
|
||||
struct functor {
|
||||
template<class> struct result;
|
||||
|
||||
template<class F, class T>
|
||||
struct result<F(T)>
|
||||
: boost::remove_cv<
|
||||
typename boost::remove_reference<T>::type
|
||||
>
|
||||
{};
|
||||
|
||||
template<class T>
|
||||
T operator()(T const& x) const;
|
||||
};
|
||||
```
|
||||
|
||||
[endsect]
|
||||
|
||||
[#sec:result_of_tr1_diff]
|
||||
[section Known differences between __boost_result_of__ and __boost_tr1_result_of__]
|
||||
|
||||
When using __decltype__, __boost_result_of__ ignores the TR1 protocol and instead deduces the
|
||||
return type of function objects directly via __decltype__. In most situations, users
|
||||
will not notice a difference, so long as they use the protocol correctly. The following are situations in
|
||||
which the type deduced by __boost_result_of__ is known to differ depending on whether
|
||||
__decltype__ or the TR1 protocol is used.
|
||||
|
||||
TR1 protocol misusage: When using the TR1 protocol, __boost_result_of__ cannot
|
||||
detect whether the actual type of a call to a function object is the same as the
|
||||
type specified by the protocol, which allows for the possibility of inadvertent
|
||||
mismatches between the specified type and the actual type. When using __decltype__,
|
||||
these subtle bugs may result in compilation errors. For example:
|
||||
|
||||
```
|
||||
struct functor {
|
||||
typedef short result_type;
|
||||
int operator()(short);
|
||||
};
|
||||
|
||||
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<__boost_result_of__<functor(short)>::type, int>::value
|
||||
));
|
||||
|
||||
#else
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<__boost_result_of__<functor(short)>::type, short>::value
|
||||
));
|
||||
|
||||
#endif
|
||||
```
|
||||
|
||||
Note that the user can force __boost_result_of__ to use the TR1
|
||||
protocol even on platforms that support __decltype__ by
|
||||
defining `BOOST_RESULT_OF_USE_TR1`.
|
||||
|
||||
Nullary function objects: When using the TR1 protocol, __boost_result_of__
|
||||
cannot always deduce the type of calls to nullary function objects, in which case the
|
||||
type defaults to void. When using __decltype__, __boost_result_of__ always gives the
|
||||
actual type of the call expression. For example:
|
||||
|
||||
```
|
||||
struct functor {
|
||||
template<class> struct result {
|
||||
typedef int type;
|
||||
};
|
||||
int operator()();
|
||||
};
|
||||
|
||||
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<__boost_result_of__<functor()>::type, int>::value
|
||||
));
|
||||
|
||||
#else
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<__boost_result_of__<functor()>::type, void>::value
|
||||
));
|
||||
|
||||
#endif
|
||||
```
|
||||
|
||||
Note that there are some workarounds for the nullary function problem.
|
||||
So long as the return type does not vary, `result_type` can always be used to
|
||||
specify the return type regardless of arity. If the return type does vary,
|
||||
then the user can specialize __boost_result_of__ itself for nullary calls.
|
||||
|
||||
Non-class prvalues and cv-qualification: When using the TR1 protocol, __boost_result_of__ will
|
||||
report the cv-qualified type specified by `result_type` or the `result` template regardless of
|
||||
the actual cv-qualification of the call expression. When using __decltype__, __boost_result_of__
|
||||
will report the actual type of the call expression, which is not cv-qualified when the expression
|
||||
is a non-class prvalue. For example:
|
||||
|
||||
```
|
||||
struct functor {
|
||||
template<class> struct result;
|
||||
template<class F, class T> struct result<F(const T)> {
|
||||
typedef const T type;
|
||||
};
|
||||
|
||||
const short operator()(const short);
|
||||
int const & operator()(int const &);
|
||||
};
|
||||
|
||||
// Non-prvalue call expressions work the same with or without decltype.
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<
|
||||
__boost_result_of__<functor(int const &)>::type,
|
||||
int const &
|
||||
::value
|
||||
));
|
||||
|
||||
// Non-class prvalue call expressions are not actually cv-qualified,
|
||||
// but only the decltype-based result_of reports this accurately.
|
||||
|
||||
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<
|
||||
__boost_result_of__<functor(const short)>::type,
|
||||
short
|
||||
::value
|
||||
));
|
||||
|
||||
#else
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<
|
||||
__boost_result_of__<functor(const short)>::type,
|
||||
const short
|
||||
::value
|
||||
));
|
||||
|
||||
#endif
|
||||
```
|
||||
|
||||
[endsect]
|
||||
|
||||
[#sec:result_of_cxx11_diff]
|
||||
[section Known differences between __boost_result_of__ and C++11 result_of]
|
||||
|
||||
When using __decltype__, __boost_result_of__ implements most of the C++11 __std_result_of__
|
||||
specification. One known exception is that __boost_result_of__ does not implement the
|
||||
requirements regarding pointers to member data.
|
||||
|
||||
[endsect]
|
||||
|
||||
[/===============]
|
||||
[xinclude tmp/result_of_reference.xml]
|
||||
[/===============]
|
||||
|
||||
[section Acknowledgments]
|
||||
|
||||
Created by Doug Gregor. Contributions from Daniel Walker, Eric Niebler, Michel Morin and others.
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
@ -1,167 +0,0 @@
|
||||
[/
|
||||
/ Copyright (c) 2012 Marshall Clow
|
||||
/
|
||||
/ 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)
|
||||
/]
|
||||
|
||||
[article String_Ref
|
||||
[quickbook 1.5]
|
||||
[authors [Clow, Marshall]]
|
||||
[copyright 2012 Marshall Clow]
|
||||
[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 Overview]
|
||||
[/===============]
|
||||
|
||||
Boost.StringRef is an implementation of Jeffrey Yaskin's [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html N3442:
|
||||
string_ref: a non-owning reference to a string].
|
||||
|
||||
When you are parsing/processing strings from some external source, frequently you want to pass a piece of text to a procedure for specialized processing. The canonical way to do this is as a `std::string`, but that has certain drawbacks:
|
||||
|
||||
1) If you are processing a buffer of text (say a HTTP response or the contents of a file), then you have to create the string from the text you want to pass, which involves memory allocation and copying of data.
|
||||
|
||||
2) if a routine receives a constant `std::string` and wants to pass a portion of that string to another routine, then it must create a new string of that substring.
|
||||
|
||||
3) A routine receives a constant `std::string` and wants to return a portion of the string, then it must create a new string to return.
|
||||
|
||||
`string_ref` is designed to solve these efficiency problems. A `string_ref` is a read-only reference to a contiguous sequence of characters, and provides much of the functionality of `std::string`. A `string_ref` is cheap to create, copy and pass by value, because it does not actually own the storage that it points to.
|
||||
|
||||
A `string_ref` is implemented as a small struct that contains a pointer to the start of the character data and a count. A `string_ref` is cheap to create and cheap to copy.
|
||||
|
||||
`string_ref` acts as a container; it includes all the methods that you would expect in a container, including iteration support, `operator []`, `at` and `size`. It can be used with any of the iterator-based algorithms in the STL - as long as you don't need to change the underlying data (`sort` and `remove`, for example, will not work)
|
||||
|
||||
Besides generic container functionality, `string_ref` provides a subset of the interface of `std::string`. This makes it easy to replace parameters of type `const std::string &` with `boost::string_ref`. Like `std::string`, `string_ref` has a static member variable named `npos` to denote the result of failed searches, and to mean "the end".
|
||||
|
||||
Because a `string_ref` does not own the data that it "points to", it introduces lifetime issues into code that uses it. The programmer must ensure that the data that a `string_ref` refers to exists as long as the `string_ref` does.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[/===============]
|
||||
[section Examples]
|
||||
[/===============]
|
||||
|
||||
Integrating `string_ref` into your code is fairly simple. Wherever you pass a `const std::string &` or `std::string` as a parameter, that's a candidate for passing a `boost::string_ref`.
|
||||
|
||||
std::string extract_part ( const std::string &bar ) {
|
||||
return bar.substr ( 2, 3 );
|
||||
}
|
||||
|
||||
if ( extract_part ( "ABCDEFG" ).front() == 'C' ) { /* do something */ }
|
||||
|
||||
Let's figure out what happens in this (contrived) example.
|
||||
|
||||
First, a temporary string is created from the string literal `"ABCDEFG"`, and it is passed (by reference) to the routine `extract_part`. Then a second string is created in the call `std::string::substr` and returned to `extract_part` (this copy may be elided by RVO). Then `extract_part` returns that string back to the caller (again this copy may be elided). The first temporary string is deallocated, and `front` is called on the second string, and then it is deallocated as well.
|
||||
|
||||
Two `std::string`s are created, and two copy operations. That's (potentially) four memory allocations and deallocations, and the associated copying of data.
|
||||
|
||||
Now let's look at the same code with `string_ref`:
|
||||
|
||||
boost::string_ref extract_part ( boost::string_ref bar ) {
|
||||
return bar.substr ( 2, 3 );
|
||||
}
|
||||
|
||||
if ( extract_part ( "ABCDEFG" ).front() == "C" ) { /* do something */ }
|
||||
|
||||
No memory allocations. No copying of character data. No changes to the code other than the types. There are two `string_ref`s created, and two `string_ref`s copied, but those are cheap operations.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[/=================]
|
||||
[section:reference Reference ]
|
||||
[/=================]
|
||||
|
||||
The header file "string_ref.hpp" defines a template `boost::basic_string_ref`, and four specializations - for `char` / `wchar_t` / `char16_t` / `char32_t` .
|
||||
|
||||
`#include <boost/utility/string_ref.hpp>`
|
||||
|
||||
Construction and copying:
|
||||
|
||||
BOOST_CONSTEXPR basic_string_ref (); // Constructs an empty string_ref
|
||||
BOOST_CONSTEXPR basic_string_ref(const charT* str); // Constructs from a NULL-terminated string
|
||||
BOOST_CONSTEXPR basic_string_ref(const charT* str, size_type len); // Constructs from a pointer, length pair
|
||||
template<typename Allocator>
|
||||
basic_string_ref(const std::basic_string<charT, traits, Allocator>& str); // Constructs from a std::string
|
||||
basic_string_ref (const basic_string_ref &rhs);
|
||||
basic_string_ref& operator=(const basic_string_ref &rhs);
|
||||
|
||||
`string_ref` does not define a move constructor nor a move-assignment operator because copying a `string_ref` is just a cheap as moving one.
|
||||
|
||||
Basic container-like functions:
|
||||
|
||||
BOOST_CONSTEXPR size_type size() const ;
|
||||
BOOST_CONSTEXPR size_type length() const ;
|
||||
BOOST_CONSTEXPR size_type max_size() const ;
|
||||
BOOST_CONSTEXPR bool empty() const ;
|
||||
|
||||
// All iterators are const_iterators
|
||||
BOOST_CONSTEXPR const_iterator begin() const ;
|
||||
BOOST_CONSTEXPR const_iterator cbegin() const ;
|
||||
BOOST_CONSTEXPR const_iterator end() const ;
|
||||
BOOST_CONSTEXPR const_iterator cend() const ;
|
||||
const_reverse_iterator rbegin() const ;
|
||||
const_reverse_iterator crbegin() const ;
|
||||
const_reverse_iterator rend() const ;
|
||||
const_reverse_iterator crend() const ;
|
||||
|
||||
Access to the individual elements (all of which are const):
|
||||
|
||||
BOOST_CONSTEXPR const charT& operator[](size_type pos) const ;
|
||||
const charT& at(size_t pos) const ;
|
||||
BOOST_CONSTEXPR const charT& front() const ;
|
||||
BOOST_CONSTEXPR const charT& back() const ;
|
||||
BOOST_CONSTEXPR const charT* data() const ;
|
||||
|
||||
Modifying the `string_ref` (but not the underlying data):
|
||||
|
||||
void clear();
|
||||
void remove_prefix(size_type n);
|
||||
void remove_suffix(size_type n);
|
||||
|
||||
Searching:
|
||||
|
||||
size_type find(basic_string_ref s) const ;
|
||||
size_type find(charT c) const ;
|
||||
size_type rfind(basic_string_ref s) const ;
|
||||
size_type rfind(charT c) const ;
|
||||
size_type find_first_of(charT c) const ;
|
||||
size_type find_last_of (charT c) const ;
|
||||
|
||||
size_type find_first_of(basic_string_ref s) const ;
|
||||
size_type find_last_of(basic_string_ref s) const ;
|
||||
size_type find_first_not_of(basic_string_ref s) const ;
|
||||
size_type find_first_not_of(charT c) const ;
|
||||
size_type find_last_not_of(basic_string_ref s) const ;
|
||||
size_type find_last_not_of(charT c) const ;
|
||||
|
||||
String-like operations:
|
||||
|
||||
BOOST_CONSTEXPR basic_string_ref substr(size_type pos, size_type n=npos) const ; // Creates a new string_ref
|
||||
bool starts_with(charT c) const ;
|
||||
bool starts_with(basic_string_ref x) const ;
|
||||
bool ends_with(charT c) const ;
|
||||
bool ends_with(basic_string_ref x) const ;
|
||||
|
||||
[endsect]
|
||||
|
||||
[/===============]
|
||||
[section History]
|
||||
[/===============]
|
||||
|
||||
[heading boost 1.53]
|
||||
* Introduced
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
|
||||
|
209
doc/string_view.qbk
Normal file
209
doc/string_view.qbk
Normal file
@ -0,0 +1,209 @@
|
||||
[/
|
||||
/ Copyright (c) 2012 Marshall Clow
|
||||
/ Copyright (c) 2021, Alan Freitas
|
||||
/
|
||||
/ 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 String View]
|
||||
[/===============]
|
||||
|
||||
[section Introduction]
|
||||
|
||||
The class __boost_string_view__ and other classes derived from __basic_string_view__ represent references to strings or substrings. When you are parsing/processing strings from some external source, frequently you want to pass a piece of text to a procedure for specialized processing. Before __std_string_view__, the canonical way to do this used to be a __std_string__, but that has certain drawbacks:
|
||||
|
||||
1) If you are processing a buffer of text (say a HTTP response or the contents of a file), then you have to create the string from the text you want to pass, which involves memory allocation and copying of data.
|
||||
|
||||
2) If a routine receives a constant __std_string__ and wants to pass a portion of that string to another routine, then it must create a new string of that substring.
|
||||
|
||||
3) If a routine receives a constant __std_string__ and wants to return a portion of the string, then it must create a new string to return.
|
||||
|
||||
__boost_string_view__ is designed to solve these efficiency problems. A __boost_string_view__ is a read-only reference to a contiguous sequence of characters, and provides much of the functionality of __std_string__. A __boost_string_view__ is cheap to create, copy and pass by value, because it does not actually own the storage that it points to.
|
||||
|
||||
A __boost_string_view__ is implemented as a small struct that contains a pointer to the start of the character `data` and a `count`. A __boost_string_view__ is cheap to create and cheap to copy.
|
||||
|
||||
__boost_string_view__ acts as a container; it includes all the methods that you would expect in a container, including iteration support, `operator[]`, `at` and `size`. It can be used with any of the iterator-based algorithms in the STL - as long as you do not need to change the underlying data. For example, __std_sort__ and __std_remove__ will not work.
|
||||
|
||||
Besides generic container functionality, __boost_string_view__ provides a subset of the interface of __std_string__. This makes it easy to replace parameters of type `const __std_string__ &` with __boost_string_view__. Like __std_string__, __boost_string_view__ has a static member variable named `npos` to denote the result of failed searches, and to mean "the end".
|
||||
|
||||
[caution Because a __boost_string_view__ does not own the data that it refers to, it introduces lifetime issues into code that uses it. The programmer must ensure that the data that a __string_view__ refers to exists as long as the __string_view__ does.]
|
||||
|
||||
[note
|
||||
|
||||
Boost.Utility also includes the class __string_ref__:
|
||||
|
||||
- __string_ref__ is the initial implementation of Jeffrey Yaskin's [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html N3442:
|
||||
string_ref: a non-owning reference to a string].
|
||||
|
||||
- __string_view__ is an updated implementation to reflect the Library Fundamentals TS [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html N4480: \[string.view\]].
|
||||
|
||||
Please prefer __string_view__ / __basic_string_view__ over __string_ref__ / __basic_string_ref__:
|
||||
|
||||
- The __basic_string_view__ class better matches __std_basic_string_view__.
|
||||
|
||||
- __basic_string_view__ has WAY more constexpr support.
|
||||
|
||||
- Code that uses __basic_string_ref__ should continue to work.
|
||||
|
||||
- Not much code depends on __basic_string_ref__ anymore.
|
||||
|
||||
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[/===============]
|
||||
[section Examples]
|
||||
[/===============]
|
||||
|
||||
Integrating __string_view__ into your code is fairly simple. Wherever you pass a `const __std_string__ &` or __std_string__ as a parameter, that's a candidate for passing a __boost_string_view__.
|
||||
|
||||
```
|
||||
__std_string__ extract_part ( const __std_string__ &bar ) {
|
||||
return bar.substr ( 2, 3 );
|
||||
}
|
||||
|
||||
if ( extract_part ( "ABCDEFG" ).front() == 'C' ) { /* do something */ }
|
||||
```
|
||||
|
||||
Let's figure out what happens in this contrived example.
|
||||
|
||||
* First, a temporary string is created from the string literal `"ABCDEFG"`, and it is passed (by reference) to the routine `extract_part`.
|
||||
* Then a second string is created in the call `__std_string__::substr` and returned to `extract_part` (this copy may be elided by RVO).
|
||||
* Then `extract_part` returns that string back to the caller (again this copy may be elided).
|
||||
* The first temporary string is deallocated, and `front` is called on the second string, and then it is deallocated as well.
|
||||
|
||||
Two __std_string__ s are created, and two copy operations. That is potentially four memory allocations and deallocations, and the associated copying of data.
|
||||
|
||||
Now let's look at the same code with __string_view__:
|
||||
|
||||
```
|
||||
__boost_string_view__ extract_part ( __boost_string_view__ bar ) {
|
||||
return bar.substr ( 2, 3 );
|
||||
}
|
||||
|
||||
if ( extract_part ( "ABCDEFG" ).front() == "C" ) { /* do something */ }
|
||||
```
|
||||
|
||||
No memory allocations. No copying of character data. No changes to the code other than the types. There are two __string_view__ s created, and two __string_view__ s copied, but those are cheap operations.
|
||||
[endsect]
|
||||
|
||||
[/=================]
|
||||
[section:reference Synopsis]
|
||||
[/=================]
|
||||
|
||||
The header file [@../../../../boost/utility/string_view.hpp `<boost/utility/string_view.hpp>`] defines a template __boost_basic_string_view__, and four specializations __string_view__, __wstring_view__, __u16string_view__, __u32string_view__ - for `char` / `wchar_t` / `char16_t` / `char32_t`.
|
||||
|
||||
`#include <boost/utility/string_view.hpp>`
|
||||
|
||||
Construction and copying:
|
||||
|
||||
```
|
||||
constexpr basic_string_view (); // Constructs an empty string_view
|
||||
constexpr basic_string_view(const charT* str); // Constructs from a NULL-terminated string
|
||||
constexpr basic_string_view(const charT* str, size_type len); // Constructs from a pointer, length pair
|
||||
template<typename Allocator>
|
||||
basic_string_view(const __std_basic_string__<charT, traits, Allocator>& str); // Constructs from a std::string
|
||||
basic_string_view (const basic_string_view &rhs);
|
||||
basic_string_view& operator=(const basic_string_view &rhs);
|
||||
```
|
||||
|
||||
__string_view__ does not define a move constructor nor a move-assignment operator because copying a __string_view__ is just a cheap as moving one.
|
||||
|
||||
Basic container-like functions:
|
||||
|
||||
```
|
||||
constexpr size_type size() const ;
|
||||
constexpr size_type length() const ;
|
||||
constexpr size_type max_size() const ;
|
||||
constexpr bool empty() const ;
|
||||
|
||||
// All iterators are const_iterators
|
||||
constexpr const_iterator begin() const ;
|
||||
constexpr const_iterator cbegin() const ;
|
||||
constexpr const_iterator end() const ;
|
||||
constexpr const_iterator cend() const ;
|
||||
const_reverse_iterator rbegin() const ;
|
||||
const_reverse_iterator crbegin() const ;
|
||||
const_reverse_iterator rend() const ;
|
||||
const_reverse_iterator crend() const ;
|
||||
```
|
||||
|
||||
Access to the individual elements (all of which are const):
|
||||
|
||||
```
|
||||
constexpr const charT& operator[](size_type pos) const ;
|
||||
const charT& at(size_t pos) const ;
|
||||
constexpr const charT& front() const ;
|
||||
constexpr const charT& back() const ;
|
||||
constexpr const charT* data() const ;
|
||||
```
|
||||
|
||||
Modifying the __string_view__ (but not the underlying data):
|
||||
|
||||
```
|
||||
void clear();
|
||||
void remove_prefix(size_type n);
|
||||
void remove_suffix(size_type n);
|
||||
```
|
||||
|
||||
Searching:
|
||||
|
||||
```
|
||||
size_type find(basic_string_view s) const ;
|
||||
size_type find(charT c) const ;
|
||||
size_type rfind(basic_string_view s) const ;
|
||||
size_type rfind(charT c) const ;
|
||||
size_type find_first_of(charT c) const ;
|
||||
size_type find_last_of (charT c) const ;
|
||||
|
||||
size_type find_first_of(basic_string_view s) const ;
|
||||
size_type find_last_of(basic_string_view s) const ;
|
||||
size_type find_first_not_of(basic_string_view s) const ;
|
||||
size_type find_first_not_of(charT c) const ;
|
||||
size_type find_last_not_of(basic_string_view s) const ;
|
||||
size_type find_last_not_of(charT c) const ;
|
||||
```
|
||||
|
||||
String-like operations:
|
||||
|
||||
```
|
||||
constexpr basic_string_view substr(size_type pos, size_type n=npos) const ; // Creates a new string_view
|
||||
bool starts_with(charT c) const ;
|
||||
bool starts_with(basic_string_view x) const ;
|
||||
bool ends_with(charT c) const ;
|
||||
bool ends_with(basic_string_view x) const ;
|
||||
```
|
||||
[endsect]
|
||||
|
||||
|
||||
[/===============]
|
||||
[section History]
|
||||
[/===============]
|
||||
|
||||
[h5 boost 1.71]
|
||||
* Glen Fernandes updated the implementation of the stream insertion operator to
|
||||
write directly to the `basic_streambuf` and refactored that functionality into
|
||||
a common utility.
|
||||
|
||||
[h5 boost 1.53]
|
||||
* Introduced
|
||||
|
||||
[endsect]
|
||||
|
||||
[/===============]
|
||||
[xinclude tmp/string_view_reference.xml]
|
||||
[/===============]
|
||||
|
||||
[/===============]
|
||||
[section Acknowledgments]
|
||||
[/===============]
|
||||
|
||||
Author: Clow, Marshall
|
||||
|
||||
Copyright 2012 Marshall Clow
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
2
doc/tmp/.gitignore
vendored
Normal file
2
doc/tmp/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*.qbk
|
||||
*.xml
|
32
doc/utilities.qbk
Normal file
32
doc/utilities.qbk
Normal file
@ -0,0 +1,32 @@
|
||||
[/
|
||||
Copyright (c) 2021 Alan de Freitas (alandefreitas@gmail.com)
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
Official repository: https://github.com/boostorg/utility
|
||||
]
|
||||
|
||||
[section:utilities Utilities]
|
||||
|
||||
The entire contents of Boost.Utility are in `namespace boost`.
|
||||
|
||||
[warning
|
||||
|
||||
Direct use of the header [@../../../../boost/utility.hpp `<boost/utility.hpp>`] is discouraged and it will be deprecated.
|
||||
|
||||
Please include the headers relative to individual components instead.
|
||||
|
||||
]
|
||||
|
||||
[include base_from_member.qbk]
|
||||
[include BOOST_BINARY.qbk]
|
||||
[include call_traits.qbk]
|
||||
[include compressed_pair.qbk]
|
||||
[include in_place_factory.qbk]
|
||||
[include operators.qbk]
|
||||
[include result_of.qbk]
|
||||
[include string_view.qbk]
|
||||
[include value_init.qbk]
|
||||
|
||||
[endsect]
|
584
doc/value_init.qbk
Normal file
584
doc/value_init.qbk
Normal file
@ -0,0 +1,584 @@
|
||||
[/
|
||||
/ Copyright (c) 2012 Marshall Clow
|
||||
/ Copyright (c) 2021, Alan Freitas
|
||||
/
|
||||
/ 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)
|
||||
/]
|
||||
|
||||
[/===============]
|
||||
[#sec:value_init]
|
||||
[section Value Init]
|
||||
|
||||
[/===============]
|
||||
|
||||
[section Introduction]
|
||||
|
||||
Constructing and initializing objects in a generic way is difficult in
|
||||
C++. The problem is that there are several different rules that apply
|
||||
for initialization. Depending on the type, the value of a newly constructed
|
||||
object can be zero-initialized (logically 0), default-constructed (using
|
||||
the default constructor), or indeterminate. When writing generic code,
|
||||
this problem must be addressed. The template __value_initialized__ provides
|
||||
a solution with consistent syntax for value initialization of scalar,
|
||||
union and class types. Moreover, __value_initialized__ offers a workaround to various
|
||||
compiler issues regarding value-initialization.
|
||||
|
||||
Furthermore, a `const` object __initialized_value__ is provided,
|
||||
to avoid repeating the type name when retrieving the value from a
|
||||
`__value_initialized__<T>` object.
|
||||
|
||||
There are various ways to initialize a variable, in C++. The following
|
||||
declarations all ['may] have a local variable initialized to its default
|
||||
value:
|
||||
|
||||
```
|
||||
T1 var1;
|
||||
T2 var2 = 0;
|
||||
T3 var3 = {};
|
||||
T4 var4 = T4();
|
||||
```
|
||||
|
||||
Unfortunately, whether or not any of those declarations correctly
|
||||
initialize the variable very much depends on its type. The first
|
||||
declaration is valid for any __DefaultConstructible__ type by definition.
|
||||
|
||||
However, it does not always do an initialization. It correctly initializes
|
||||
the variable when it's an instance of a class, and the author of the class
|
||||
has provided a proper default constructor. On the other hand, the value of
|
||||
`var1` is ['indeterminate] when its type is an arithmetic type, like `int`,
|
||||
`float`, or `char`.
|
||||
|
||||
An arithmetic variable is of course initialized properly by the second declaration,
|
||||
`T2 var2 = 0`. But this initialization form will not usually work for a
|
||||
class type, unless the class was especially written to support being
|
||||
initialized that way.
|
||||
|
||||
The third form, `T3 var3 = {}`, initializes an aggregate, typically a "C-style"
|
||||
`struct` or a "C-style" array. However, at the time this library was developed,
|
||||
the syntax did not allow for a class that has an explicitly declared constructor.
|
||||
|
||||
The fourth form is the most generic form of them, as it can be used to initialize
|
||||
arithmetic types, class types, aggregates, pointers, and other types.
|
||||
The declaration, `T4 var4 = T4()`, should be read as follows: First a temporary
|
||||
object is created, by `T4()`. This object is [link sec:valueinit value-initialized].
|
||||
Next the temporary object is copied to the named variable, `var4`. Afterwards,
|
||||
the temporary is destroyed. While the copying and the destruction are likely to
|
||||
be optimized away, C++ still requires the type `T4` to be __CopyConstructible__.
|
||||
So `T4` needs to be ['both] __DefaultConstructible__ ['and] __CopyConstructible__.
|
||||
|
||||
A class may not be CopyConstructible, for example because it may have a
|
||||
private and undefined copy constructor, or because it may be derived from
|
||||
`boost::noncopyable`. Scott Meyers \[[link sec:references 2]\] explains why a
|
||||
class would be defined like that.
|
||||
|
||||
There is another, less obvious disadvantage to the fourth form, `T4 var4 = T4()`:
|
||||
It suffers from various [link sec:compiler_issues compiler issues], causing
|
||||
a variable to be left uninitialized in some compiler specific cases.
|
||||
|
||||
The template __value_initialized__ offers a generic way to initialize
|
||||
an object, like `T4 var4 = T4()`, but without requiring its type
|
||||
to be __CopyConstructible__. And it offers a workaround to those compiler issues
|
||||
regarding value-initialization as well. It allows getting an initialized
|
||||
variable of any type; it ['only] requires the type to be __DefaultConstructible__.
|
||||
A properly ['value-initialized] object of type `T` is constructed by the following
|
||||
declaration:
|
||||
|
||||
```
|
||||
value_initialized<T> var;
|
||||
```
|
||||
|
||||
The template __initialized__ offers both value-initialization and direct-initialization.
|
||||
It is especially useful as a data member type, allowing the very same object
|
||||
to be either direct-initialized or value-initialized.
|
||||
|
||||
The `const` object __initialized_value__ allows value-initializing a variable as follows:
|
||||
|
||||
```
|
||||
T var = initialized_value;
|
||||
```
|
||||
|
||||
This form of initialization is semantically equivalent to `T4 var4 = T4()`,
|
||||
but robust against the aforementioned compiler issues.
|
||||
|
||||
[endsect]
|
||||
|
||||
[#sec:details]
|
||||
[section Details]
|
||||
|
||||
The C++ standard \[[link sec:references 3]\] contains the definitions
|
||||
of `zero-initialization` and `default-initialization`. Informally, zero-initialization
|
||||
means that the object is given the initial value `0` converted to the type and
|
||||
default-initialization means that [@https://en.cppreference.com/w/cpp/named_req/PODType POD] \[[link sec:references 4]\] types are zero-initialized,
|
||||
while non-POD class types are initialized with their corresponding default constructors.
|
||||
|
||||
A ['declaration] can contain an ['initializer], which specifies the
|
||||
object's initial value. The initializer can be just '()', which states that
|
||||
the object shall be value-initialized (but see below). However, if a ['declaration]
|
||||
has no ['initializer] and it is of a non-`const`, non-`static` POD type, the
|
||||
initial value is indeterminate: (see [sect]8.5, \[dcl.init\], for the
|
||||
accurate definitions).
|
||||
|
||||
```
|
||||
int x; // no initializer. x value is indeterminate.
|
||||
__std_string__ s; // no initializer, s is default-constructed.
|
||||
|
||||
int y = int();
|
||||
// y is initialized using copy-initialization
|
||||
// but the temporary uses an empty set of parentheses as the initializer,
|
||||
// so it is default-constructed.
|
||||
// A default constructed POD type is zero-initialized,
|
||||
// therefore, y == 0.
|
||||
|
||||
void foo ( __std_string__ ) ;
|
||||
foo ( __std_string__() ) ;
|
||||
// the temporary string is default constructed
|
||||
// as indicated by the initializer ()
|
||||
```
|
||||
|
||||
[#sec:valueinit]
|
||||
[h5 value-initialization]
|
||||
|
||||
The first [@http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html Technical
|
||||
Corrigendum for the C++ Standard] (TC1), whose draft was released to the public in
|
||||
November 2001, introduced [@http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#178 Core
|
||||
Issue 178], among many other issues.
|
||||
|
||||
That issue introduced the new concept of `value-initialization`, and also fixed the
|
||||
wording for zero-initialization. Informally, value-initialization is similar to
|
||||
default-initialization with the exception that in some cases non-static data members
|
||||
and base class sub-objects are also value-initialized.
|
||||
|
||||
The difference is that an object that is value-initialized will not have, or at least
|
||||
is less likely to have, indeterminate values for data members and base class sub-objects;
|
||||
unlike the case of an object default constructed (see Core Issue 178 for a
|
||||
normative description).
|
||||
|
||||
In order to specify value-initialization of an object we need to use the
|
||||
empty-set initializer: `()`.
|
||||
|
||||
As before, a declaration with no initializer specifies default-initialization,
|
||||
and a declaration with a non-empty initializer specifies copy (`=xxx`) or
|
||||
direct (`xxx`) initialization.
|
||||
|
||||
```
|
||||
template<class T> void eat(T);
|
||||
|
||||
int x ; // indeterminate initial value.
|
||||
|
||||
__std_string__ s; // default-initialized.
|
||||
|
||||
eat ( int() ) ; // value-initialized
|
||||
|
||||
eat ( __std_string__() ) ; // value-initialized
|
||||
```
|
||||
|
||||
[#sec:valueinitsyn]
|
||||
[h5 value-initialization syntax]
|
||||
|
||||
Value initialization is specified using `()`. However, the empty set of
|
||||
parentheses is not permitted by the syntax of initializers because it is
|
||||
parsed as the declaration of a function taking no arguments:
|
||||
|
||||
```
|
||||
int x() ; // declares function int(*)()
|
||||
```
|
||||
|
||||
Thus, the empty `()` must be put in some other initialization context.
|
||||
|
||||
One alternative is to use copy-initialization syntax:
|
||||
|
||||
```
|
||||
int x = int();
|
||||
```
|
||||
|
||||
This works perfectly fine for POD types. But for non-POD class types,
|
||||
copy-initialization searches for a suitable constructor, which could be,
|
||||
for instance, the copy-constructor. It also searches for a suitable conversion
|
||||
sequence but this does not apply in this context.
|
||||
|
||||
For an arbitrary unknown type, using this syntax may not have the
|
||||
value-initialization effect intended because we don't know if a copy
|
||||
from a default constructed object is exactly the same as a default
|
||||
constructed object, and the compiler is allowed, in
|
||||
some cases, but never required to, optimize the copy away.
|
||||
|
||||
One possible generic solution is to use value-initialization of a non static
|
||||
data member:
|
||||
|
||||
```
|
||||
template<class T>
|
||||
struct W
|
||||
{
|
||||
// value-initialization of 'data' here.
|
||||
W() : data() {}
|
||||
|
||||
T data;
|
||||
};
|
||||
|
||||
W<int> w;
|
||||
// w.data is value-initialized for any type.
|
||||
```
|
||||
|
||||
This is the solution as it was supplied by earlier versions of the
|
||||
`__value_initialized__<T>` template class. Unfortunately this approach
|
||||
suffered from various compiler issues.
|
||||
|
||||
[#sec:compiler_issues]
|
||||
[h5 Compiler issues]
|
||||
|
||||
Various compilers have not yet fully implemented value-initialization.
|
||||
So when an object should be ['value-initialized] according to the C++ Standard,
|
||||
it ['may] in practice still be left uninitialized, because of those
|
||||
compiler issues. It is hard to make a general statement on what those issues
|
||||
are like, because they depend on the compiler you are using, its version number,
|
||||
and the type of object you would like to have value-initialized.
|
||||
|
||||
All compilers we have tested so far support value-initialization for arithmetic types properly.
|
||||
However, various compilers may leave some types of ['aggregates] uninitialized, when they
|
||||
should be value-initialized. Value-initialization of objects of a pointer-to-member type may also
|
||||
go wrong on various compilers.
|
||||
|
||||
At the moment of writing, May 2010, the following reported issues regarding
|
||||
value-initialization are still there in current compiler releases:
|
||||
|
||||
|
||||
|
||||
* [@https://connect.microsoft.com/VisualStudio/feedback/details/100744 Microsoft Visual Studio Feedback ID 100744, Value-initialization in new-expression]: Reported by Pavel Kuznetsov (MetaCommunications Engineering), 2005.
|
||||
* [@http://connect.microsoft.com/VisualStudio/feedback/details/484295 Microsoft Visual Studio Feedback ID 484295, VC++ does not value-initialize members of derived classes without user-declared constructor] Reported by Sylvester Hesp, 2009.
|
||||
* [@https://connect.microsoft.com/VisualStudio/feedback/details/499606 Microsoft Visual Studio Feedback ID 499606, Presence of copy constructor breaks member class initialization] Reported by Alex Vakulenko, 2009
|
||||
* [@http://qc.embarcadero.com/wc/qcmain.aspx?d=83751 Embarcadero/C++Builder Report 83751, Value-initialization: arrays should have each element value-initialized] Reported by Niels Dekker (LKEB), 2010.
|
||||
* [@http://qc.embarcadero.com/wc/qcmain.aspx?d=83851 Embarcadero/C++Builder Report 83851, Value-initialized temporary triggers internal backend error C1798] Reported by Niels Dekker, 2010.
|
||||
* [@http://qc.embarcadero.com/wc/qcmain.aspx?d=84279 Embarcadero/C++Builder Report 84279, Internal compiler error (F1004), value-initializing member function pointer by "new T()"] Reported by Niels Dekker, 2010
|
||||
* Sun CR 6947016, Sun 5.10 may fail to value-initialize an object of a non-POD aggregate. Reported to Steve Clamage by Niels Dekker, 2010.
|
||||
* IBM's XL V10.1 and V11.1 may fail to value-initialize a temporary of a non-POD aggregate. Reported to Michael Wong by Niels Dekker, 2010.
|
||||
* Intel support issue 589832, Attempt to value-initialize pointer-to-member triggers internal error on Intel 11.1. Reported by John Maddock, 2010.
|
||||
|
||||
Note that all known GCC issues regarding value-initialization are fixed with GCC version 4.4, including
|
||||
[@http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30111 GCC Bug 30111]. Clang also has completely implemented
|
||||
value-initialization, as far as we know, now that [@http://llvm.org/bugs/show_bug.cgi?id=7139 Clang Bug 7139]
|
||||
is fixed.
|
||||
|
||||
New versions of __value_initialized__ (Boost release version 1.35 or higher) offer a workaround to these
|
||||
issues: __value_initialized__ may now clear its internal data, prior to constructing the object that it
|
||||
contains. It will do so for those compilers that need to have such a workaround, based on the
|
||||
[@boost:/libs/config/doc/html/boost_config/boost_macro_reference.html#boost_config.boost_macro_reference.macros_that_describe_defects
|
||||
compiler defect macro] `BOOST_NO_COMPLETE_VALUE_INITIALIZATION`.
|
||||
|
||||
[endsect]
|
||||
|
||||
[#sec:types]
|
||||
[section Types and objects]
|
||||
|
||||
[#sec:val_init]
|
||||
[section `template class value_initialized<T>`]
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
|
||||
template<class T>
|
||||
class __value_initialized__
|
||||
{
|
||||
|
||||
public :
|
||||
|
||||
__value_initialized__() : x() {}
|
||||
|
||||
operator T const &() const { return x ; }
|
||||
|
||||
operator T&() { return x ; }
|
||||
|
||||
T const &data() const { return x ; }
|
||||
|
||||
T& data() { return x ; }
|
||||
|
||||
void swap( __value_initialized__& );
|
||||
|
||||
private :
|
||||
|
||||
[unspecified] x ;
|
||||
|
||||
} ;
|
||||
|
||||
template<class T>
|
||||
|
||||
T const& get ( __value_initialized__<T> const& x )
|
||||
{
|
||||
return x.data();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T& get ( __value_initialized__<T>& x )
|
||||
{
|
||||
return x.data();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void swap ( __value_initialized__<T>& lhs, __value_initialized__<T>& rhs )
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
```
|
||||
|
||||
An object of this template class is a `T`-wrapper convertible to `'T&'` whose
|
||||
wrapped object (data member of type `T`) is [link sec:valueinit value-initialized] upon default-initialization
|
||||
of this wrapper class:
|
||||
|
||||
```
|
||||
int zero = 0;
|
||||
__value_initialized__<int> x;
|
||||
assert( x == zero ) ;
|
||||
|
||||
__std_string__ def;
|
||||
__value_initialized__< __std_string__ > y;
|
||||
assert( y == def ) ;
|
||||
```
|
||||
|
||||
The purpose of this wrapper is to provide a consistent syntax for value initialization
|
||||
of scalar, union and class types (POD and non-POD) since the correct syntax for value
|
||||
initialization varies (see [link sec:valueinitsyn value-initialization syntax]).
|
||||
|
||||
The wrapped object can be accessed either through the conversion operator
|
||||
`T&`, the member function `data()`, or the non-member function `get()`:
|
||||
|
||||
```
|
||||
void watch(int);
|
||||
|
||||
__value_initialized__<int> x;
|
||||
|
||||
watch(x) ; // operator T& used.
|
||||
watch(x.data());
|
||||
watch( get(x) ) // function get() used
|
||||
```
|
||||
|
||||
Both `const` and non-`const` objects can be wrapped. Mutable objects can be
|
||||
modified directly from within the wrapper but constant objects cannot:
|
||||
|
||||
When `T` is a __Swappable__ type, `__value_initialized__<T>`
|
||||
is swappable as well, by calling its `swap` member function
|
||||
as well as by calling `boost::swap`.
|
||||
|
||||
```
|
||||
__value_initialized__<int> x;
|
||||
static_cast<int&>(x) = 1 ; // OK
|
||||
get(x) = 1 ; // OK
|
||||
|
||||
__value_initialized__<int const> y ;
|
||||
static_cast<int&>(y) = 1 ; // ERROR: cannot cast to int&
|
||||
static_cast<int const&>(y) = 1 ; // ERROR: cannot modify a const value
|
||||
get(y) = 1 ; // ERROR: cannot modify a const value
|
||||
```
|
||||
|
||||
[warning
|
||||
|
||||
The __value_initialized__ implementation of Boost version 1.40.0 and older
|
||||
allowed ['non-const] access to the wrapped object, from a constant wrapper,
|
||||
both by its conversion operator and its `data()` member function.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
__value_initialized__<int> const x_c;
|
||||
int& xr = x_c ; // OK, conversion to int& available even though x_c is itself const.
|
||||
xr = 2 ;
|
||||
```
|
||||
|
||||
The reason for this obscure behavior was that some compilers did not accept the following valid code:
|
||||
|
||||
```
|
||||
struct X
|
||||
{
|
||||
operator int&() ;
|
||||
operator int const&() const ;
|
||||
};
|
||||
X x ;
|
||||
(x == 1) ; // ERROR HERE!
|
||||
```
|
||||
|
||||
The current version of __value_initialized__ no longer has this obscure behavior.
|
||||
As compilers nowadays widely support overloading the conversion operator by having a `const`
|
||||
and a `non-const` version, we have decided to fix the issue accordingly. So the current version
|
||||
supports the idea of logical constness.
|
||||
|
||||
]
|
||||
|
||||
[h5 Recommended practice: The non-member get() idiom]
|
||||
|
||||
The obscure behavior of being able to modify a non-`const`
|
||||
wrapped object from within a constant wrapper (as was supported by previous
|
||||
versions of __value_initialized__) can be avoided if access to the wrapped object
|
||||
is always performed with the `get()` idiom:
|
||||
|
||||
```
|
||||
value_initialized<int> x;
|
||||
get(x) = 1; // OK
|
||||
value_initialized<int const> cx;
|
||||
get(x) = 1; // ERROR: Cannot modify a const object
|
||||
|
||||
value_initialized<int> const x_c;
|
||||
get(x_c) = 1; // ERROR: Cannot modify a const object
|
||||
|
||||
value_initialized<int const> const cx_c;
|
||||
get(cx_c) = 1; // ERROR: Cannot modify a const object
|
||||
```
|
||||
|
||||
[endsect]
|
||||
|
||||
[#sec:initialized]
|
||||
[section `template class initialized<T>`]
|
||||
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
|
||||
template<class T>
|
||||
class __initialized__
|
||||
{
|
||||
|
||||
public :
|
||||
|
||||
__initialized__() : x() {}
|
||||
|
||||
explicit __initialized__(T const & arg) : x(arg) {}
|
||||
|
||||
operator T const &() const;
|
||||
|
||||
operator T&();
|
||||
|
||||
T const &data() const;
|
||||
|
||||
T& data();
|
||||
|
||||
void swap( __initialized__& );
|
||||
|
||||
private :
|
||||
|
||||
[unspecified] x ;
|
||||
|
||||
};
|
||||
|
||||
template<class T>
|
||||
T const& get ( __initialized__<T> const& x );
|
||||
|
||||
template<class T>
|
||||
T& get ( __initialized__<T>& x );
|
||||
|
||||
template<class T>
|
||||
void swap ( __initialized__<T>& lhs, __initialized__<T>& rhs );
|
||||
|
||||
} // namespace boost
|
||||
```
|
||||
|
||||
The template class `boost::__initialized__<T>` supports both value-initialization
|
||||
and direct-initialization, so its interface is a superset of the interface
|
||||
of `__value_initialized__<T>`: Its default-constructor value-initializes the
|
||||
wrapped object just like the default-constructor of `__value_initialized__<T>`,
|
||||
but `boost::__initialized__<T>` also offers an extra `explicit`
|
||||
constructor, which direct-initializes the wrapped object by the specified value.
|
||||
|
||||
`__initialized__<T>` is especially useful when the wrapped
|
||||
object must be either value-initialized or direct-initialized, depending on
|
||||
runtime conditions. For example, `__initialized__<T>` could
|
||||
hold the value of a data member that may be value-initialized by some
|
||||
constructors, and direct-initialized by others.
|
||||
|
||||
On the other hand, if it is known beforehand that the
|
||||
object must ['always] be value-initialized, `__value_initialized__<T>`
|
||||
may be preferable. And if the object must always be
|
||||
direct-initialized, none of the two wrappers really needs to be used.
|
||||
|
||||
[endsect]
|
||||
|
||||
[#sec:initialized_value]
|
||||
[section `initialized_value`]
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
class __initialized_value_t__
|
||||
{
|
||||
public :
|
||||
template <class T> operator T() const ;
|
||||
};
|
||||
|
||||
__initialized_value_t__ const initialized_value = {} ;
|
||||
|
||||
} // namespace boost
|
||||
```
|
||||
|
||||
__initialized_value__ provides a convenient way to get
|
||||
an initialized value: its conversion operator provides an appropriate
|
||||
['value-initialized] object for any __CopyConstructible__ type.
|
||||
|
||||
Suppose you need to have an initialized variable of type `T`.
|
||||
You could do it as follows:
|
||||
|
||||
```
|
||||
T var = T();
|
||||
```
|
||||
|
||||
But as mentioned before, this form suffers from various compiler issues.
|
||||
The template __value_initialized__ offers a workaround:
|
||||
|
||||
```
|
||||
T var = get( __value_initialized__<T>() );
|
||||
```
|
||||
|
||||
Unfortunately both forms repeat the type name, which
|
||||
is rather short now (`T`), but could of course be
|
||||
more like `Namespace::Template<Arg>::Type`.
|
||||
|
||||
Instead, one could use __initialized_value__ as follows:
|
||||
|
||||
```
|
||||
T var = __initialized_value__;
|
||||
```
|
||||
|
||||
[endsect]
|
||||
[endsect]
|
||||
|
||||
[#sec:references]
|
||||
[section References]
|
||||
|
||||
# Bjarne Stroustrup, Gabriel Dos Reis, and J. Stephen Adamczyk wrote various papers,
|
||||
proposing to extend the support for brace-enclosed ['initializer lists]
|
||||
in C++. This [@https://en.cppreference.com/w/cpp/language/list_initialization feature] has
|
||||
now been available since C++11. This would allow a variable `var` of any __DefaultConstructible__ type
|
||||
`T` to be ['value-initialized] by doing `T var = {}`. The papers are listed at Bjarne's web page,
|
||||
[@http://www.research.att.com/~bs/WG21.html My C++ Standards committee papers].
|
||||
|
||||
# Scott Meyers, Effective C++, Third Edition, item 6, ['Explicitly disallow the use of
|
||||
compiler-generated functions you do not want], [@http://www.aristeia.com/books.html Scott Meyers: Books and CDs]
|
||||
|
||||
# The C++ Standard, Second edition (2003), ISO/IEC 14882:2003
|
||||
|
||||
# POD stands for [@https://en.cppreference.com/w/cpp/named_req/PODType "Plain Old Data"]
|
||||
|
||||
[endsect]
|
||||
|
||||
[/===============]
|
||||
[xinclude tmp/value_init_reference.xml]
|
||||
[/===============]
|
||||
|
||||
[#sec:acknowledgements]
|
||||
[section Acknowledgements]
|
||||
|
||||
__value_initialized__ was developed by Fernando Cacciola, with help and suggestions
|
||||
from David Abrahams and Darin Adler.
|
||||
|
||||
Special thanks to Bjorn Karlsson who carefully edited and completed this documentation.
|
||||
|
||||
__value_initialized__ was reimplemented by Fernando Cacciola and Niels Dekker
|
||||
for Boost release version 1.35 (2008), offering a workaround to various compiler issues.
|
||||
|
||||
`boost::__initialized__` was very much inspired by feedback from Edward Diener and Jeffrey Hellrung.
|
||||
|
||||
__initialized_value__ was written by Niels Dekker, and added to Boost release version 1.36 (2008).
|
||||
|
||||
Developed by [@mailto:fernando_cacciola@hotmail.com Fernando Cacciola]. The latest version of
|
||||
this file can be found at [@http://www.boost.org www.boost.org].
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
483
enable_if.html
483
enable_if.html
@ -1,464 +1,19 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/REC-html40/loose.dtd">
|
||||
<HTML>
|
||||
<HEAD><TITLE>enable_if</TITLE>
|
||||
|
||||
<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<META name="GENERATOR" content="Microsoft FrontPage 5.0">
|
||||
</HEAD>
|
||||
<BODY >
|
||||
<!--HEVEA command line is: hevea -nosymb -noiso -pedantic -v enable_if_docs_for_boost.tex -->
|
||||
<!--HTMLHEAD-->
|
||||
<!--ENDHTML-->
|
||||
<!--PREFIX <ARG ></ARG>-->
|
||||
<!--CUT DEF section 1 -->
|
||||
<BR>
|
||||
<BR>
|
||||
|
||||
|
||||
<h1>
|
||||
<img border="0" src="../../boost.png" align="center" width="277" height="86">enable_if</h1>
|
||||
<BR>
|
||||
<BR>
|
||||
Copyright 2003 Jaakko Järvi, Jeremiah Willcock, Andrew Lumsdaine.<BR>
|
||||
Copyright 2011 Matt Calabrese.<BR>
|
||||
<BR>
|
||||
<!--TOC section Introduction-->
|
||||
|
||||
<H2><A NAME="htoc1">1</A> Introduction</H2><!--SEC END -->
|
||||
|
||||
<A NAME="introduction"></A>
|
||||
The <TT>enable_if</TT> family of templates is a set of tools to allow a function template or a class template specialization
|
||||
to include or exclude itself from a set of matching functions or specializations
|
||||
based on properties of its template arguments.
|
||||
For example, one can define function templates that
|
||||
are only enabled for, and thus only match, an arbitrary set of types
|
||||
defined by a traits class. The <TT>enable_if</TT> templates can also be
|
||||
applied to enable class template specializations. Applications of
|
||||
<TT>enable_if</TT> are discussed in length
|
||||
in [<A HREF="#jarvi:03:cuj_arbitrary_overloading"><CITE>1</CITE></A>] and [<A HREF="#jarvi:03:c++typeclasses"><CITE>2</CITE></A>].<BR>
|
||||
<BR>
|
||||
<!--TOC subsection Synopsis-->
|
||||
|
||||
<H3><A NAME="htoc2">1.1</A> Synopsis</H3><!--SEC END -->
|
||||
|
||||
<A NAME="sec:synopsis"></A>
|
||||
<PRE>namespace boost {
|
||||
template <class Cond, class T = void> struct enable_if;
|
||||
template <class Cond, class T = void> struct disable_if;
|
||||
template <class Cond, class T> struct lazy_enable_if;
|
||||
template <class Cond, class T> struct lazy_disable_if;
|
||||
|
||||
template <bool B, class T = void> struct enable_if_c;
|
||||
template <bool B, class T = void> struct disable_if_c;
|
||||
template <bool B, class T> struct lazy_enable_if_c;
|
||||
template <bool B, class T> struct lazy_disable_if_c;
|
||||
}
|
||||
</PRE>
|
||||
<!--TOC subsection Background-->
|
||||
|
||||
<H3><A NAME="htoc3">1.2</A> Background</H3><!--SEC END -->
|
||||
|
||||
<A NAME="sec:background"></A>
|
||||
Sensible operation of template function overloading in C++ relies
|
||||
on the <EM>SFINAE</EM> (substitution-failure-is-not-an-error)
|
||||
principle [<A HREF="#vandevoorde2002:templates"><CITE>3</CITE></A>]: if an invalid argument
|
||||
or return type is formed during the instantiation of a function
|
||||
template, the instantiation is removed from the overload resolution
|
||||
set instead of causing a compilation error. The following example,
|
||||
taken from [<A HREF="#jarvi:03:cuj_arbitrary_overloading"><CITE>1</CITE></A>],
|
||||
demonstrates why this is important:
|
||||
<PRE>int negate(int i) { return -i; }
|
||||
|
||||
template <class F>
|
||||
typename F::result_type negate(const F& f) { return -f(); }
|
||||
|
||||
</PRE>
|
||||
Suppose the compiler encounters the call <TT>negate(1)</TT>. The first
|
||||
definition is obviously a better match, but the compiler must
|
||||
nevertheless consider (and instantiate the prototypes) of both
|
||||
definitions to find this out. Instantiating the latter definition with
|
||||
<TT>F</TT> as <TT>int</TT> would result in:
|
||||
<PRE>int::result_type negate(const int&);
|
||||
|
||||
</PRE>
|
||||
where the return type is invalid. If this were an error, adding an unrelated function template
|
||||
(that was never called) could break otherwise valid code.
|
||||
Due to the SFINAE principle the above example is not, however, erroneous.
|
||||
The latter definition of <TT>negate</TT> is simply removed from the overload resolution set.<BR>
|
||||
<BR>
|
||||
The <TT>enable_if</TT> templates are tools for controlled creation of the SFINAE
|
||||
conditions.<BR>
|
||||
<BR>
|
||||
<!--TOC section The <TT>enable_if</TT> templates-->
|
||||
|
||||
<H2><A NAME="htoc4">2</A> The <TT>enable_if</TT> templates</H2><!--SEC END -->
|
||||
|
||||
<A NAME="enable_if"></A>
|
||||
The names of the <TT>enable_if</TT> templates have three parts: an optional <TT>lazy_</TT> tag,
|
||||
either <TT>enable_if</TT> or <TT>disable_if</TT>, and an optional <TT>_c</TT> tag.
|
||||
All eight combinations of these parts are supported.
|
||||
The meaning of the <TT>lazy_</TT> tag is described in Section <A HREF="#sec:enable_if_lazy">3.3</A>.
|
||||
The second part of the name indicates whether a true condition argument should
|
||||
enable or disable the current overload.
|
||||
The third part of the name indicates whether the condition argument is a <TT>bool</TT> value
|
||||
(<TT>_c</TT> suffix), or a type containing a static <TT>bool</TT> constant named <TT>value</TT> (no suffix).
|
||||
The latter version interoperates with Boost.MPL. <BR>
|
||||
<BR>
|
||||
The definitions of <TT>enable_if_c</TT> and <TT>enable_if</TT> are as follows (we use <TT>enable_if</TT> templates
|
||||
unqualified but they are in the <TT>boost</TT> namespace).
|
||||
<PRE>template <bool B, class T = void>
|
||||
struct enable_if_c {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct enable_if_c<false, T> {};
|
||||
|
||||
template <class Cond, class T = void>
|
||||
struct enable_if : public enable_if_c<Cond::value, T> {};
|
||||
|
||||
</PRE>
|
||||
An instantiation of the <TT>enable_if_c</TT> template with the parameter
|
||||
<TT>B</TT> as <TT>true</TT> contains a member type <TT>type</TT>, defined
|
||||
to be <TT>T</TT>. If <TT>B</TT> is
|
||||
<TT>false</TT>, no such member is defined. Thus
|
||||
<TT>enable_if_c<B, T>::type</TT> is either a valid or an invalid type
|
||||
expression, depending on the value of <TT>B</TT>.
|
||||
When valid, <TT>enable_if_c<B, T>::type</TT> equals <TT>T</TT>.
|
||||
The <TT>enable_if_c</TT> template can thus be used for controlling when functions are considered for
|
||||
overload resolution and when they are not.
|
||||
For example, the following function is defined for all arithmetic types (according to the
|
||||
classification of the <A HREF="../type_traits/index.html">Boost type_traits library</A>):
|
||||
<PRE>template <class T>
|
||||
typename enable_if_c<boost::is_arithmetic<T>::value, T>::type
|
||||
foo(T t) { return t; }
|
||||
|
||||
</PRE>
|
||||
The <TT>disable_if_c</TT> template is provided as well, and has the
|
||||
same functionality as <TT>enable_if_c</TT> except for the negated condition. The following
|
||||
function is enabled for all non-arithmetic types.
|
||||
<PRE>template <class T>
|
||||
typename disable_if_c<boost::is_arithmetic<T>::value, T>::type
|
||||
bar(T t) { return t; }
|
||||
|
||||
</PRE>
|
||||
For easier syntax in some cases and interoperation with Boost.MPL we provide versions of
|
||||
the <TT>enable_if</TT> templates taking any type with a <TT>bool</TT> member constant named
|
||||
<TT>value</TT> as the condition argument.
|
||||
The MPL <TT>bool_</TT>, <TT>and_</TT>, <TT>or_</TT>, and <TT>not_</TT> templates are likely to be
|
||||
useful for creating such types. Also, the traits classes in the Boost.Type_traits library
|
||||
follow this convention.
|
||||
For example, the above example function <TT>foo</TT> can be alternatively written as:
|
||||
<PRE>template <class T>
|
||||
typename enable_if<boost::is_arithmetic<T>, T>::type
|
||||
foo(T t) { return t; }
|
||||
|
||||
</PRE>
|
||||
|
||||
<!--TOC section Using <TT>enable_if</TT>-->
|
||||
|
||||
<H2><A NAME="htoc5">3</A> Using <TT>enable_if</TT></H2><!--SEC END -->
|
||||
|
||||
<A NAME="sec:using_enable_if"></A>
|
||||
The <TT>enable_if</TT> templates are defined in
|
||||
<TT>boost/utility/enable_if.hpp</TT>, which is included by <TT>boost/utility.hpp</TT>.<BR>
|
||||
<BR>
|
||||
With respect to function templates, <TT>enable_if</TT> can be used in multiple different ways:
|
||||
|
||||
<UL>
|
||||
<LI>As the return type of an instantiatied function
|
||||
<LI>As an extra parameter of an instantiated function
|
||||
<LI>As an extra template parameter (useful only in a compiler that supports C++0x default
|
||||
arguments for function template parameters, see <A href="#sec:enable_if_0x">Enabling function
|
||||
templates in C++0x</a> for details)
|
||||
</UL>
|
||||
|
||||
In the previous section, the return type form of <TT>enable_if</TT> was shown. As an example
|
||||
of using the form of <TT>enable_if</TT> that works via an extra function parameter, the
|
||||
<TT>foo</TT> function in the previous section could also be written
|
||||
as:
|
||||
<PRE>template <class T>
|
||||
T foo(T t, typename enable_if<boost::is_arithmetic<T> >::type* dummy = 0);
|
||||
|
||||
</PRE>Hence, an extra parameter of type <TT>void*</TT> is added, but it is given
|
||||
a default value to keep the parameter hidden from client code.
|
||||
Note that the second template argument was not given to <TT>enable_if</TT>, as the default
|
||||
<TT>void</TT> gives the desired behavior.<BR>
|
||||
<BR>
|
||||
Which way to write the enabler is largely a matter of taste, but for certain functions, only a
|
||||
subset of the options is possible:
|
||||
<UL><LI>
|
||||
Many operators have a fixed number of arguments, thus <TT>enable_if</TT> must be used either in the
|
||||
return type or in an extra template parameter.
|
||||
<LI>Functions that have a variadic parameter list must use either the return type form or an extra
|
||||
template parameter.
|
||||
<LI>Constructors do not have a return type so you must use either an extra function parameter or an
|
||||
extra template parameter.
|
||||
<LI>Constructors that have a variadic parameter list must an extra template parameter.
|
||||
<LI>Conversion operators can only be written with an extra template parameter.
|
||||
</UL>
|
||||
<!--TOC subsection Enabling function templates in C++0x-->
|
||||
|
||||
<A NAME="sec:enable_if_0x"></A>
|
||||
<H3><A NAME="htoc7">3.1</A> Enabling function templates in C++0x</H3><!--SEC END -->
|
||||
|
||||
In a compiler which supports C++0x default arguments for function template parameters, you can
|
||||
enable and disable function templates by adding an additional template parameter. This approach
|
||||
works in all situations where you would use either the return type form of <TT>enable_if</TT> or
|
||||
the function parameter form, including operators, constructors, variadic function templates, and
|
||||
even overloaded conversion operations.
|
||||
|
||||
As an example:
|
||||
|
||||
<PRE>#include <boost/type_traits/is_arithmetic.hpp>
|
||||
#include <boost/type_traits/is_pointer.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
class test
|
||||
{
|
||||
public:
|
||||
// A constructor that works for any argument list of size 10
|
||||
template< class... T
|
||||
, typename boost::enable_if_c< sizeof...( T ) == 10, int >::type = 0
|
||||
>
|
||||
test( T&&... );
|
||||
|
||||
// A conversion operation that can convert to any arithmetic type
|
||||
template< class T
|
||||
, typename boost::enable_if< boost::is_arithmetic< T >, int >::type = 0
|
||||
>
|
||||
operator T() const;
|
||||
|
||||
// A conversion operation that can convert to any pointer type
|
||||
template< class T
|
||||
, typename boost::enable_if< boost::is_pointer< T >, int >::type = 0
|
||||
>
|
||||
operator T() const;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
// Works
|
||||
test test_( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 );
|
||||
|
||||
// Fails as expected
|
||||
test fail_construction( 1, 2, 3, 4, 5 );
|
||||
|
||||
// Works by calling the conversion operator enabled for arithmetic types
|
||||
int arithmetic_object = test_;
|
||||
|
||||
// Works by calling the conversion operator enabled for pointer types
|
||||
int* pointer_object = test_;
|
||||
|
||||
// Fails as expected
|
||||
struct {} fail_conversion = test_;
|
||||
}
|
||||
|
||||
</PRE>
|
||||
|
||||
<!--TOC subsection Enabling template class specializations-->
|
||||
|
||||
<H3><A NAME="htoc7">3.2</A> Enabling template class specializations</H3><!--SEC END -->
|
||||
|
||||
<A NAME="sec:enable_if_classes"></A>
|
||||
Class template specializations can be enabled or disabled with <TT>enable_if</TT>.
|
||||
One extra template parameter needs to be added for the enabler expressions.
|
||||
This parameter has the default value <TT>void</TT>.
|
||||
For example:
|
||||
<PRE>template <class T, class Enable = void>
|
||||
class A { ... };
|
||||
|
||||
template <class T>
|
||||
class A<T, typename enable_if<is_integral<T> >::type> { ... };
|
||||
|
||||
template <class T>
|
||||
class A<T, typename enable_if<is_float<T> >::type> { ... };
|
||||
|
||||
</PRE>Instantiating <TT>A</TT> with any integral type matches the first specialization,
|
||||
whereas any floating point type matches the second one. All other types
|
||||
match the primary template.
|
||||
The condition can be any compile-time boolean expression that depends on the
|
||||
template arguments of the class.
|
||||
Note that again, the second argument to <TT>enable_if</TT> is not needed; the default (<TT>void</TT>)
|
||||
is the correct value.<BR>
|
||||
<BR>
|
||||
<!--TOC subsection Overlapping enabler conditions-->
|
||||
|
||||
<H3><A NAME="htoc8">3.3</A> Overlapping enabler conditions</H3><!--SEC END -->
|
||||
|
||||
<A NAME="sec:overlapping_conditions"></A>
|
||||
Once the compiler has examined the enabling conditions and included the
|
||||
function into the overload resolution set, normal C++ overload resolution
|
||||
rules are used to select the best matching function.
|
||||
In particular, there is no ordering between enabling conditions.
|
||||
Function templates with enabling conditions that are not mutually exclusive can
|
||||
lead to ambiguities. For example:
|
||||
<PRE>template <class T>
|
||||
typename enable_if<boost::is_integral<T>, void>::type
|
||||
foo(T t) {}
|
||||
|
||||
template <class T>
|
||||
typename enable_if<boost::is_arithmetic<T>, void>::type
|
||||
foo(T t) {}
|
||||
|
||||
</PRE>
|
||||
All integral types are also arithmetic. Therefore, say, for the call <TT>foo(1)</TT>,
|
||||
both conditions are true and both functions are thus in the overload resolution set.
|
||||
They are both equally good matches and thus ambiguous.
|
||||
Of course, more than one enabling condition can be simultaneously true as long as
|
||||
other arguments disambiguate the functions.<BR>
|
||||
<BR>
|
||||
The above discussion applies to using <TT>enable_if</TT> in class template
|
||||
partial specializations as well.<BR>
|
||||
<BR>
|
||||
<!--TOC subsection Lazy <TT>enable_if</TT>-->
|
||||
|
||||
<H3><A NAME="htoc9">3.4</A> Lazy <TT>enable_if</TT></H3><!--SEC END -->
|
||||
|
||||
<A NAME="sec:enable_if_lazy"></A>
|
||||
In some cases it is necessary to avoid instantiating part of a
|
||||
function signature unless an enabling condition is true. For example:
|
||||
<PRE>template <class T, class U> class mult_traits;
|
||||
|
||||
template <class T, class U>
|
||||
typename enable_if<is_multipliable<T, U>, typename mult_traits<T, U>::type>::type
|
||||
operator*(const T& t, const U& u) { ... }
|
||||
|
||||
</PRE>Assume the class template <TT>mult_traits</TT> is a traits class defining
|
||||
the resulting type of a multiplication operator. The <TT>is_multipliable</TT> traits
|
||||
class specifies for which types to enable the operator. Whenever
|
||||
<TT>is_multipliable<A, B>::value</TT> is <TT>true</TT> for some types <TT>A</TT> and <TT>B</TT>,
|
||||
then <TT>mult_traits<A, B>::type</TT> is defined.<BR>
|
||||
<BR>
|
||||
Now, trying to invoke (some other overload) of <TT>operator*</TT> with, say, operand types <TT>C</TT> and <TT>D</TT>
|
||||
for which <TT>is_multipliable<C, D>::value</TT> is <TT>false</TT>
|
||||
and <TT>mult_traits<C, D>::type</TT> is not defined is an error on some compilers.
|
||||
The SFINAE principle is not applied because
|
||||
the invalid type occurs as an argument to another template. The <TT>lazy_enable_if</TT>
|
||||
and <TT>lazy_disable_if</TT> templates (and their <TT>_c</TT> versions) can be used in such
|
||||
situations:
|
||||
<PRE>template<class T, class U>
|
||||
typename lazy_enable_if<is_multipliable<T, U>, mult_traits<T, U> >::type
|
||||
operator*(const T& t, const U& u) { ... }
|
||||
|
||||
</PRE>The second argument of <TT>lazy_enable_if</TT> must be a class type
|
||||
that defines a nested type named <TT>type</TT> whenever the first
|
||||
parameter (the condition) is true.<BR>
|
||||
<BR>
|
||||
<!--TOC paragraph Note-->
|
||||
|
||||
<H5>Note</H5><!--SEC END -->
|
||||
|
||||
Referring to one member type or static constant in a traits class
|
||||
causes all of the members (type and static constant) of that
|
||||
specialization to be instantiated. Therefore, if your traits classes
|
||||
can sometimes contain invalid types, you should use two distinct
|
||||
templates for describing the conditions and the type mappings. In the
|
||||
above example, <TT>is_multipliable<T, U>::value</TT> defines when
|
||||
<TT>mult_traits<T, U>::type</TT> is valid.<BR>
|
||||
<BR>
|
||||
<!--TOC subsection Compiler workarounds-->
|
||||
|
||||
<H3><A NAME="htoc10">3.5</A> Compiler workarounds</H3><!--SEC END -->
|
||||
|
||||
<A NAME="sec:workarounds"></A>
|
||||
Some compilers flag functions as ambiguous if the only distinguishing factor is a different
|
||||
condition in an enabler (even though the functions could never be ambiguous). For example,
|
||||
some compilers (e.g. GCC 3.2) diagnose the following two functions as ambiguous:
|
||||
<PRE>template <class T>
|
||||
typename enable_if<boost::is_arithmetic<T>, T>::type
|
||||
foo(T t);
|
||||
|
||||
template <class T>
|
||||
typename disable_if<boost::is_arithmetic<T>, T>::type
|
||||
foo(T t);
|
||||
|
||||
</PRE>Two workarounds can be applied:
|
||||
<UL><LI>
|
||||
Use an extra dummy parameter which disambiguates the functions. Use a default value for
|
||||
it to hide the parameter from the caller. For example:
|
||||
<PRE>template <int> struct dummy { dummy(int) {} };
|
||||
|
||||
template <class T>
|
||||
typename enable_if<boost::is_arithmetic<T>, T>::type
|
||||
foo(T t, dummy<0> = 0);
|
||||
|
||||
template <class T>
|
||||
typename disable_if<boost::is_arithmetic<T>, T>::type
|
||||
foo(T t, dummy<1> = 0);
|
||||
</PRE><BR>
|
||||
<BR>
|
||||
<LI>Define the functions in different namespaces and bring them into a common
|
||||
namespace with <TT>using</TT> declarations:
|
||||
<PRE>namespace A {
|
||||
template <class T>
|
||||
typename enable_if<boost::is_arithmetic<T>, T>::type
|
||||
foo(T t);
|
||||
}
|
||||
|
||||
namespace B {
|
||||
template <class T>
|
||||
typename disable_if<boost::is_arithmetic<T>, T>::type
|
||||
foo(T t);
|
||||
}
|
||||
|
||||
using A::foo;
|
||||
using B::foo;
|
||||
|
||||
</PRE>
|
||||
Note that the second workaround above cannot be used for member
|
||||
templates. On the other hand, operators do not accept extra arguments,
|
||||
which makes the first workaround unusable. As the net effect,
|
||||
neither of the workarounds are of assistance for templated operators that
|
||||
need to be defined as member functions (assignment and
|
||||
subscript operators).
|
||||
</UL>
|
||||
<!--TOC section Acknowledgements-->
|
||||
|
||||
<H2><A NAME="htoc10">4</A> Acknowledgements</H2><!--SEC END -->
|
||||
|
||||
We are grateful to Howard Hinnant, Jason Shirk, Paul Mensonides, and Richard
|
||||
Smith whose findings have influenced the library.<BR>
|
||||
<BR>
|
||||
<!--TOC section References-->
|
||||
|
||||
<H2>References</H2><!--SEC END -->
|
||||
<DL COMPACT=compact><DT><A NAME="jarvi:03:cuj_arbitrary_overloading"><FONT COLOR=purple>[1]</FONT></A><DD>
|
||||
Jaakko Järvi, Jeremiah Willcock, Howard Hinnant, and Andrew Lumsdaine.
|
||||
Function overloading based on arbitrary properties of types.
|
||||
<EM>C/C++ Users Journal</EM>, 21(6):25--32, June 2003.<BR>
|
||||
<BR>
|
||||
<DT><A NAME="jarvi:03:c++typeclasses"><FONT COLOR=purple>[2]</FONT></A><DD>
|
||||
Jaakko Järvi, Jeremiah Willcock, and Andrew Lumsdaine.
|
||||
Concept-controlled polymorphism.
|
||||
In Frank Pfennig and Yannis Smaragdakis, editors, <EM>Generative
|
||||
Programming and Component Engineering</EM>, volume 2830 of <EM>LNCS</EM>, pages
|
||||
228--244. Springer Verlag, September 2003.<BR>
|
||||
<BR>
|
||||
<DT><A NAME="vandevoorde2002:templates"><FONT COLOR=purple>[3]</FONT></A><DD>
|
||||
David Vandevoorde and Nicolai M. Josuttis.
|
||||
<EM>C++ Templates: The Complete Guide</EM>.
|
||||
Addison-Wesley, 2002.</DL>
|
||||
|
||||
<hr/>
|
||||
<p>Copyright Jaakko Järvi<sup>*</sup>, Jeremiah Willcock<sup>*</sup>, Andrew Lumsdaine<sup>*</sup>, Matt Calabrese<BR>
|
||||
<EM>{jajarvi|jewillco|lums}@osl.iu.edu, rivorus@gmail.com</EM><BR>
|
||||
<sup>*</sup>Indiana University<BR>
|
||||
Open Systems Lab<br/>
|
||||
Use, modification and distribution are subject to the
|
||||
Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt
|
||||
or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
|
||||
http://www.boost.org/LICENSE_1_0.txt
|
||||
</a>).
|
||||
</p>
|
||||
<!--HTMLFOOT-->
|
||||
<!--ENDHTML-->
|
||||
<!--FOOTER-->
|
||||
<HR SIZE=2>
|
||||
<BLOCKQUOTE><EM>This document was translated from L<sup>A</sup>T<sub>E</sub>X by
|
||||
</EM><A HREF="http://pauillac.inria.fr/~maranget/hevea/index.html"><EM>H<FONT SIZE=2><sup>E</sup></FONT>V<FONT SIZE=2><sup>E</sup></FONT>A</EM></A><EM>.
|
||||
</EM></BLOCKQUOTE>
|
||||
</BODY>
|
||||
</HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Boost.Utility</title>
|
||||
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="../core/doc/html/core/enable_if.html">../core/doc/html/core/enable_if.html</a>
|
||||
<hr>
|
||||
<tt>
|
||||
Boost.Utility<br>
|
||||
<br>
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||
<br>
|
||||
</tt>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,23 +0,0 @@
|
||||
# Copyright David Abrahams 2003.
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
# For more information, see http://www.boost.org/
|
||||
|
||||
project
|
||||
: requirements <library>/boost/test//boost_test_exec_monitor
|
||||
;
|
||||
|
||||
test-suite utility/enable_if
|
||||
:
|
||||
[ run constructors.cpp ]
|
||||
[ run dummy_arg_disambiguation.cpp ]
|
||||
[ run lazy.cpp ]
|
||||
[ run lazy_test.cpp ]
|
||||
[ run member_templates.cpp ]
|
||||
[ run namespace_disambiguation.cpp ]
|
||||
[ run no_disambiguation.cpp ]
|
||||
[ run partial_specializations.cpp ]
|
||||
;
|
||||
|
@ -1,62 +0,0 @@
|
||||
// Boost enable_if library
|
||||
|
||||
// Copyright 2003 (c) 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: Jaakko Jarvi (jajarvi at osl.iu.edu)
|
||||
// Jeremiah Willcock (jewillco at osl.iu.edu)
|
||||
// Andrew Lumsdaine (lums at osl.iu.edu)
|
||||
|
||||
#include <boost/test/minimal.hpp>
|
||||
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
|
||||
using boost::enable_if;
|
||||
using boost::disable_if;
|
||||
using boost::is_arithmetic;
|
||||
|
||||
struct container {
|
||||
bool my_value;
|
||||
|
||||
template <class T>
|
||||
container(const T&, const typename enable_if<is_arithmetic<T>, T>::type * = 0):
|
||||
my_value(true) {}
|
||||
|
||||
template <class T>
|
||||
container(const T&, const typename disable_if<is_arithmetic<T>, T>::type * = 0):
|
||||
my_value(false) {}
|
||||
};
|
||||
|
||||
// example from Howard Hinnant (tests enable_if template members of a templated class)
|
||||
template <class charT>
|
||||
struct xstring
|
||||
{
|
||||
template <class It>
|
||||
xstring(It begin, It end, typename
|
||||
disable_if<is_arithmetic<It> >::type* = 0)
|
||||
: data(end-begin) {}
|
||||
|
||||
int data;
|
||||
};
|
||||
|
||||
|
||||
int test_main(int, char*[])
|
||||
{
|
||||
|
||||
BOOST_CHECK(container(1).my_value);
|
||||
BOOST_CHECK(container(1.0).my_value);
|
||||
|
||||
BOOST_CHECK(!container("1").my_value);
|
||||
BOOST_CHECK(!container(static_cast<void*>(0)).my_value);
|
||||
|
||||
char sa[] = "123456";
|
||||
BOOST_CHECK(xstring<char>(sa, sa+6).data == 6);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,46 +0,0 @@
|
||||
// Boost enable_if library
|
||||
|
||||
// Copyright 2003 (c) 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: Jaakko Jarvi (jajarvi at osl.iu.edu)
|
||||
// Jeremiah Willcock (jewillco at osl.iu.edu)
|
||||
// Andrew Lumsdaine (lums at osl.iu.edu)
|
||||
|
||||
#include <boost/test/minimal.hpp>
|
||||
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits/is_arithmetic.hpp>
|
||||
|
||||
using boost::enable_if;
|
||||
using boost::disable_if;
|
||||
using boost::is_arithmetic;
|
||||
|
||||
template <int N> struct dummy {
|
||||
dummy(int) {};
|
||||
};
|
||||
|
||||
template<class T>
|
||||
typename enable_if<is_arithmetic<T>, bool>::type
|
||||
arithmetic_object(T t, dummy<0> = 0) { return true; }
|
||||
|
||||
template<class T>
|
||||
typename disable_if<is_arithmetic<T>, bool>::type
|
||||
arithmetic_object(T t, dummy<1> = 0) { return false; }
|
||||
|
||||
|
||||
int test_main(int, char*[])
|
||||
{
|
||||
|
||||
BOOST_CHECK(arithmetic_object(1));
|
||||
BOOST_CHECK(arithmetic_object(1.0));
|
||||
|
||||
BOOST_CHECK(!arithmetic_object("1"));
|
||||
BOOST_CHECK(!arithmetic_object(static_cast<void*>(0)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,82 +0,0 @@
|
||||
// Boost enable_if library
|
||||
|
||||
// Copyright 2003 (c) 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: Jaakko Jarvi (jajarvi at osl.iu.edu)
|
||||
// Jeremiah Willcock (jewillco at osl.iu.edu)
|
||||
// Andrew Lumsdaine (lums at osl.iu.edu)
|
||||
|
||||
#include <boost/test/minimal.hpp>
|
||||
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
using boost::enable_if_c;
|
||||
using boost::lazy_enable_if_c;
|
||||
|
||||
// This class provides a reduced example of a traits class for
|
||||
// computing the result of multiplying two types. The member typedef
|
||||
// 'type' in this traits class defines the return type of this
|
||||
// operator. The return type member is invalid unless both arguments
|
||||
// for mult_traits are values that mult_traits expects (ints in this
|
||||
// case). This kind of situation may arise if a traits class only
|
||||
// makes sense for some set of types, not all C++ types.
|
||||
|
||||
template <class T> struct is_int {
|
||||
BOOST_STATIC_CONSTANT(bool, value = (boost::is_same<T, int>::value));
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
struct mult_traits {
|
||||
typedef typename T::does_not_exist type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct mult_traits<int, int> {
|
||||
typedef int type;
|
||||
};
|
||||
|
||||
|
||||
// Next, a forwarding function mult() is defined. It is enabled only
|
||||
// when both arguments are of type int. The first version, using
|
||||
// non-lazy enable_if_c does not work.
|
||||
|
||||
#if 0
|
||||
template <class T, class U>
|
||||
typename enable_if_c<
|
||||
is_int<T>::value && is_int<U>::value,
|
||||
typename mult_traits<T, U>::type
|
||||
>::type
|
||||
mult(const T& x, const U& y) {return x * y;}
|
||||
#endif
|
||||
|
||||
// A correct version uses lazy_enable_if_c.
|
||||
// This template removes compiler errors from invalid code used as an
|
||||
// argument to enable_if_c.
|
||||
|
||||
#if 1
|
||||
template <class T, class U>
|
||||
typename lazy_enable_if_c<
|
||||
is_int<T>::value & is_int<U>::value,
|
||||
mult_traits<T, U>
|
||||
>::type
|
||||
mult(const T& x, const U& y) {return x * y;}
|
||||
#endif
|
||||
|
||||
double mult(int i, double d) { return (double)i * d; }
|
||||
|
||||
int test_main(int, char*[])
|
||||
{
|
||||
|
||||
|
||||
BOOST_CHECK(mult(1, 2) == 2);
|
||||
|
||||
BOOST_CHECK(mult(1, 3.0) == 3.0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,100 +0,0 @@
|
||||
// Boost enable_if library
|
||||
|
||||
// Copyright 2003 (c) 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: Jaakko Jarvi (jajarvi at osl.iu.edu)
|
||||
// Jeremiah Willcock (jewillco at osl.iu.edu)
|
||||
// Andrew Lumsdaine (lums at osl.iu.edu)
|
||||
|
||||
// Testing all variations of lazy_enable_if.
|
||||
|
||||
#include <boost/test/minimal.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
using boost::lazy_enable_if;
|
||||
using boost::lazy_disable_if;
|
||||
|
||||
using boost::lazy_enable_if_c;
|
||||
using boost::lazy_disable_if_c;
|
||||
|
||||
|
||||
template <class T>
|
||||
struct is_int_or_double {
|
||||
BOOST_STATIC_CONSTANT(bool,
|
||||
value = (boost::is_same<T, int>::value ||
|
||||
boost::is_same<T, double>::value));
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct some_traits {
|
||||
typedef typename T::does_not_exist type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct some_traits<int> {
|
||||
typedef bool type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct some_traits<double> {
|
||||
typedef bool type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct make_bool {
|
||||
typedef bool type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct make_bool<int> {};
|
||||
|
||||
template <>
|
||||
struct make_bool<double> {};
|
||||
|
||||
namespace A {
|
||||
|
||||
template<class T>
|
||||
typename lazy_enable_if<is_int_or_double<T>, some_traits<T> >::type
|
||||
foo(T t) { return true; }
|
||||
|
||||
template<class T>
|
||||
typename lazy_enable_if_c<is_int_or_double<T>::value, some_traits<T> >::type
|
||||
foo2(T t) { return true; }
|
||||
}
|
||||
|
||||
namespace B {
|
||||
template<class T>
|
||||
typename lazy_disable_if<is_int_or_double<T>, make_bool<T> >::type
|
||||
foo(T t) { return false; }
|
||||
|
||||
template<class T>
|
||||
typename lazy_disable_if_c<is_int_or_double<T>::value, make_bool<T> >::type
|
||||
foo2(T t) { return false; }
|
||||
}
|
||||
|
||||
int test_main(int, char*[])
|
||||
{
|
||||
using namespace A;
|
||||
using namespace B;
|
||||
BOOST_CHECK(foo(1));
|
||||
BOOST_CHECK(foo(1.0));
|
||||
|
||||
BOOST_CHECK(!foo("1"));
|
||||
BOOST_CHECK(!foo(static_cast<void*>(0)));
|
||||
|
||||
BOOST_CHECK(foo2(1));
|
||||
BOOST_CHECK(foo2(1.0));
|
||||
|
||||
BOOST_CHECK(!foo2("1"));
|
||||
BOOST_CHECK(!foo2(static_cast<void*>(0)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,43 +0,0 @@
|
||||
// Boost enable_if library
|
||||
|
||||
// Copyright 2003 (c) 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: Jaakko Jarvi (jajarvi at osl.iu.edu)
|
||||
// Jeremiah Willcock (jewillco at osl.iu.edu)
|
||||
// Andrew Lumsdaine (lums at osl.iu.edu)
|
||||
|
||||
#include <boost/test/minimal.hpp>
|
||||
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits/is_arithmetic.hpp>
|
||||
|
||||
using boost::enable_if;
|
||||
using boost::disable_if;
|
||||
using boost::is_arithmetic;
|
||||
|
||||
struct container {
|
||||
template <class T>
|
||||
typename enable_if<is_arithmetic<T>, bool>::type
|
||||
arithmetic_object(const T&, const int* /* disambiguate */ = 0) {return true;}
|
||||
|
||||
template <class T>
|
||||
typename disable_if<is_arithmetic<T>, bool>::type
|
||||
arithmetic_object(const T&) {return false;}
|
||||
};
|
||||
|
||||
int test_main(int, char*[])
|
||||
{
|
||||
|
||||
BOOST_CHECK(container().arithmetic_object(1));
|
||||
BOOST_CHECK(container().arithmetic_object(1.0));
|
||||
|
||||
BOOST_CHECK(!container().arithmetic_object("1"));
|
||||
BOOST_CHECK(!container().arithmetic_object(static_cast<void*>(0)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,47 +0,0 @@
|
||||
// Boost enable_if library
|
||||
|
||||
// Copyright 2003 (c) 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: Jaakko Jarvi (jajarvi at osl.iu.edu)
|
||||
// Jeremiah Willcock (jewillco at osl.iu.edu)
|
||||
// Andrew Lumsdaine (lums at osl.iu.edu)
|
||||
|
||||
#include <boost/test/minimal.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits/is_arithmetic.hpp>
|
||||
|
||||
using boost::enable_if;
|
||||
using boost::mpl::not_;
|
||||
using boost::is_arithmetic;
|
||||
|
||||
namespace A {
|
||||
template<class T>
|
||||
typename enable_if<is_arithmetic<T>, bool>::type
|
||||
arithmetic_object(T t) { return true; }
|
||||
}
|
||||
|
||||
namespace B {
|
||||
template<class T>
|
||||
typename enable_if<not_<is_arithmetic<T> >, bool>::type
|
||||
arithmetic_object(T t) { return false; }
|
||||
}
|
||||
|
||||
int test_main(int, char*[])
|
||||
{
|
||||
using namespace A;
|
||||
using namespace B;
|
||||
BOOST_CHECK(arithmetic_object(1));
|
||||
BOOST_CHECK(arithmetic_object(1.0));
|
||||
|
||||
BOOST_CHECK(!arithmetic_object("1"));
|
||||
BOOST_CHECK(!arithmetic_object(static_cast<void*>(0)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,43 +0,0 @@
|
||||
// Boost enable_if library
|
||||
|
||||
// Copyright 2003 (c) 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: Jaakko Jarvi (jajarvi at osl.iu.edu)
|
||||
// Jeremiah Willcock (jewillco at osl.iu.edu)
|
||||
// Andrew Lumsdaine (lums at osl.iu.edu)
|
||||
|
||||
#include <boost/test/minimal.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits/is_arithmetic.hpp>
|
||||
|
||||
using boost::mpl::not_;
|
||||
using boost::enable_if;
|
||||
using boost::is_arithmetic;
|
||||
|
||||
template<class T>
|
||||
typename enable_if<is_arithmetic<T>, bool>::type
|
||||
arithmetic_object(T t) { return true; }
|
||||
|
||||
template<class T>
|
||||
typename enable_if<not_<is_arithmetic<T> >, bool>::type
|
||||
arithmetic_object(T t) { return false; }
|
||||
|
||||
|
||||
int test_main(int, char*[])
|
||||
{
|
||||
|
||||
BOOST_CHECK(arithmetic_object(1));
|
||||
BOOST_CHECK(arithmetic_object(1.0));
|
||||
|
||||
BOOST_CHECK(!arithmetic_object("1"));
|
||||
BOOST_CHECK(!arithmetic_object(static_cast<void*>(0)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,67 +0,0 @@
|
||||
// Boost enable_if library
|
||||
|
||||
// Copyright 2003 (c) 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: Jaakko Jarvi (jajarvi at osl.iu.edu)
|
||||
// Jeremiah Willcock (jewillco at osl.iu.edu)
|
||||
// Andrew Lumsdaine (lums at osl.iu.edu)
|
||||
|
||||
#include <boost/test/minimal.hpp>
|
||||
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits/is_arithmetic.hpp>
|
||||
|
||||
using boost::enable_if_c;
|
||||
using boost::disable_if_c;
|
||||
using boost::enable_if;
|
||||
using boost::disable_if;
|
||||
using boost::is_arithmetic;
|
||||
|
||||
template <class T, class Enable = void>
|
||||
struct tester;
|
||||
|
||||
template <class T>
|
||||
struct tester<T, typename enable_if_c<is_arithmetic<T>::value>::type> {
|
||||
BOOST_STATIC_CONSTANT(bool, value = true);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct tester<T, typename disable_if_c<is_arithmetic<T>::value>::type> {
|
||||
BOOST_STATIC_CONSTANT(bool, value = false);
|
||||
};
|
||||
|
||||
template <class T, class Enable = void>
|
||||
struct tester2;
|
||||
|
||||
template <class T>
|
||||
struct tester2<T, typename enable_if<is_arithmetic<T> >::type> {
|
||||
BOOST_STATIC_CONSTANT(bool, value = true);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct tester2<T, typename disable_if<is_arithmetic<T> >::type> {
|
||||
BOOST_STATIC_CONSTANT(bool, value = false);
|
||||
};
|
||||
|
||||
int test_main(int, char*[])
|
||||
{
|
||||
|
||||
BOOST_CHECK(tester<int>::value);
|
||||
BOOST_CHECK(tester<double>::value);
|
||||
|
||||
BOOST_CHECK(!tester<char*>::value);
|
||||
BOOST_CHECK(!tester<void*>::value);
|
||||
|
||||
BOOST_CHECK(tester2<int>::value);
|
||||
BOOST_CHECK(tester2<double>::value);
|
||||
|
||||
BOOST_CHECK(!tester2<char*>::value);
|
||||
BOOST_CHECK(!tester2<void*>::value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,163 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Language" content="en-us">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
|
||||
|
||||
<title>Generator Iterator Adaptor Documentation</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
<img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle"
|
||||
width="277" height="86">
|
||||
|
||||
<h1>Generator Iterator Adaptor</h1>
|
||||
|
||||
<p>Defined in header <a href=
|
||||
"../../boost/generator_iterator.hpp">boost/generator_iterator.hpp</a></p>
|
||||
|
||||
<p>The generator iterator adaptor makes it easier to create custom input
|
||||
iterators from 0-ary functions and function objects. The adaptor takes a
|
||||
<a href="http://www.sgi.com/tech/stl/Generator.html">Generator</a> and
|
||||
creates a model of <a href=
|
||||
"http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>. Each
|
||||
increment retrieves an item from the generator and makes it available to be
|
||||
retrieved by dereferencing. The motivation for this iterator is that some
|
||||
concepts can be more naturally expressed as a generator, while most STL
|
||||
algorithms expect an iterator. An example is the <a href=
|
||||
"../random/index.html">Random Number</a> library.</p>
|
||||
|
||||
<h2>Synopsis</h2>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
namespace boost {
|
||||
template <class Generator>
|
||||
class generator_iterator_policies;
|
||||
|
||||
template <class Generator>
|
||||
class generator_iterator_generator;
|
||||
|
||||
template <class Generator>
|
||||
typename generator_iterator_generator<Generator>::type
|
||||
make_generator_iterator(Generator & gen);
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
<hr>
|
||||
|
||||
<h2>The Generator Iterator Generator Class</h2>
|
||||
|
||||
<p>The class generator_iterator_generator is a helper class whose purpose
|
||||
is to construct a generator iterator type. The template parameter for this
|
||||
class is the Generator function object type that is being wrapped. The
|
||||
generator iterator adaptor only holds a reference (or pointer) to the
|
||||
function object, therefore the function object must outlive the generator
|
||||
iterator adaptor constructed from it.</p>
|
||||
<pre>
|
||||
template <class Generator>
|
||||
class generator_iterator_generator
|
||||
{
|
||||
public:
|
||||
typedef <i>unspecified</i> type; // the resulting generator iterator type
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3>Template Parameters</h3>
|
||||
|
||||
<table border summary="">
|
||||
<tr>
|
||||
<th>Parameter</th>
|
||||
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><tt><a href=
|
||||
"http://www.sgi.com/tech/stl/Generator.html">Generator</a></tt></td>
|
||||
|
||||
<td>The generator (0-ary function object) type being wrapped. The
|
||||
return type of the function must be defined as
|
||||
<tt>Generator::result_type</tt>. The function object must be a model of
|
||||
<a href=
|
||||
"http://www.sgi.com/tech/stl/Generator.html">Generator</a>.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3>Concept Model</h3>
|
||||
|
||||
<p>The generator iterator class is a model of <a href=
|
||||
"http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>.</p>
|
||||
|
||||
<h3>Members</h3>
|
||||
|
||||
<p>The generator iterator implements the member functions and operators
|
||||
required of the <a href=
|
||||
"http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>
|
||||
concept.<br></p>
|
||||
<hr>
|
||||
|
||||
<h2><a name="make_generator_iterator" id="make_generator_iterator">The
|
||||
Generator Iterator Object Generator</a></h2>
|
||||
|
||||
<p>The <tt>make_generator_iterator()</tt> function provides a convenient
|
||||
way to create generator iterator objects. The function saves the user the
|
||||
trouble of explicitly writing out the iterator types.</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
template <class Generator>
|
||||
typename generator_iterator_generator<Generator>::type
|
||||
make_generator_iterator(Generator & gen);
|
||||
</pre>
|
||||
</blockquote>
|
||||
<hr>
|
||||
|
||||
<h3>Example</h3>
|
||||
|
||||
<p>The following program shows how <code>generator_iterator</code>
|
||||
transforms a generator into an input iterator.</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
#include <iostream>
|
||||
#include <boost/generator_iterator.hpp>
|
||||
|
||||
class my_generator
|
||||
{
|
||||
public:
|
||||
typedef int result_type;
|
||||
my_generator() : state(0) { }
|
||||
int operator()() { return ++state; }
|
||||
private:
|
||||
int state;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
my_generator gen;
|
||||
boost::generator_iterator_generator<my_generator>::type it = boost::make_generator_iterator(gen);
|
||||
for(int i = 0; i < 10; ++i, ++it)
|
||||
std::cout << *it << std::endl;
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
<hr>
|
||||
|
||||
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
|
||||
"../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
|
||||
height="31" width="88"></a></p>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->05 December, 2006<!--webbot bot="Timestamp" endspan i-checksum="38516" --></p>
|
||||
|
||||
<p><i>Copyright © 2001 <a href=
|
||||
"http://www.boost.org/people/jens_maurer.htm">Jens Maurer</a></i></p>
|
||||
|
||||
<p><i>Distributed under the Boost Software License, Version 1.0. (See
|
||||
accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or
|
||||
copy at <a href=
|
||||
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
|
||||
</body>
|
||||
</html>
|
@ -6,7 +6,7 @@
|
||||
<body>
|
||||
Automatic redirection failed, click this
|
||||
<a href="doc/html/index.html">link</a> <hr>
|
||||
<p><EFBFBD> Copyright Lorenzo Caminiti, 2009-2012</p>
|
||||
<p>Copyright © Lorenzo Caminiti, 2009-2012</p>
|
||||
<p>Distributed under the Boost Software License, Version 1.0 (see
|
||||
accompanying file <a href="../../../LICENSE_1_0.txt">
|
||||
LICENSE_1_0.txt</a> or a copy at
|
||||
|
@ -1,296 +1,19 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//SoftQuad Software//DTD HoTMetaL PRO 5.0::19981217::extensions to HTML 4.0//EN" "hmpro5.dtd">
|
||||
|
||||
<HTML>
|
||||
|
||||
<HEAD>
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252">
|
||||
<TITLE>In_place_factory Documentation</TITLE>
|
||||
</HEAD>
|
||||
|
||||
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#800080">
|
||||
<H2 align="left"><IMG SRC="../../boost.png" WIDTH="276" HEIGHT="86"></H2>
|
||||
|
||||
<blockquote>
|
||||
<blockquote>
|
||||
<blockquote>
|
||||
<blockquote>
|
||||
<blockquote>
|
||||
<blockquote>
|
||||
<H2 align="left">Header <<A
|
||||
HREF="../../boost/utility/in_place_factory.hpp">boost/utility/in_place_factory.hpp</A>> </H2>
|
||||
|
||||
<H2 align="left">Header <<A
|
||||
HREF="../../boost/utility/typed_in_place_factory.hpp">boost/utility/typed_in_place_factory.hpp</A>> </H2>
|
||||
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
<p> </p>
|
||||
|
||||
<H2>Contents</H2>
|
||||
<DL CLASS="page-index">
|
||||
<DT><A HREF="#mot">Motivation</A></DT>
|
||||
<DT><A HREF="#framework">Framework</A></DT>
|
||||
<DT><A HREF="#specification">Specification</A></DT>
|
||||
<DT><A HREF="#container-usage">Container-side Usage</A></DT>
|
||||
<DT><A HREF="#user-usage">User-side Usage</A></DT>
|
||||
</DL>
|
||||
|
||||
<HR>
|
||||
|
||||
<H2><A NAME="mot"></A>Motivation</H2>
|
||||
|
||||
<p>Suppose we have a class</p>
|
||||
<pre>struct X
|
||||
{
|
||||
X ( int, std::string ) ;
|
||||
} ;</pre>
|
||||
<p>And a container for it which supports an empty state (that is, which can contain zero objects):</p>
|
||||
<pre>struct C
|
||||
{
|
||||
C() : contained_(0) {}
|
||||
~C() { delete contained_ ; }
|
||||
X* contained_ ;
|
||||
} ;</pre>
|
||||
<p>A container designed to support an empty state typically doesn't require the contained type to be DefaultConstructible,
|
||||
but it typically requires it to be CopyConstructible as a mechanism to
|
||||
initialize the object to store:</p>
|
||||
<pre>struct C
|
||||
{
|
||||
C() : contained_(0) {}
|
||||
C ( X const& v ) : contained_ ( new X(v) ) {}
|
||||
~C() { delete contained_ ; }
|
||||
X* contained_ ;
|
||||
} ;</pre>
|
||||
<p>There is a subtle problem with this: since the mechanism used to initialize the stored object is copy construction,
|
||||
there must exist a previously constructed source object to copy from. This
|
||||
object is likely to be temporary and serve no purpose besides being the source</p>
|
||||
<pre>void foo()
|
||||
{
|
||||
// Temporary object created.
|
||||
C c( X(123,"hello") ) ;
|
||||
}
|
||||
</pre>
|
||||
<p>A solution to this problem is to support direct construction of the contained
|
||||
object right in the container's storage.<br>
|
||||
In this scheme, the user supplies the arguments for the X constructor
|
||||
directly to the container:</p>
|
||||
<pre>struct C
|
||||
{
|
||||
C() : contained_(0) {}
|
||||
C ( X const& v ) : contained_ ( new X(v) ) {}
|
||||
C ( int a0, std::string a1 ) : contained_ ( new X(a0,a1) ) {}
|
||||
~C() { delete contained_ ; }
|
||||
X* contained_ ;
|
||||
} ;</pre>
|
||||
<pre>void foo()
|
||||
{
|
||||
// Wrapped object constructed in-place
|
||||
// No temporary created.
|
||||
C c(123,"hello") ;
|
||||
}
|
||||
</pre>
|
||||
<p>Clearly, this solution doesn't scale well since the container must duplicate all the constructor overloads from the contained type
|
||||
(at least all those which are to be supported directly in the container).</p>
|
||||
|
||||
<H2><A NAME="framework"></A>Framework</H2>
|
||||
<p>
|
||||
This library proposes a framework to allow some containers to directly contruct contained objects in-place without requiring
|
||||
the entire set of constructor overloads from the contained type. It also allows the container to remove the CopyConstuctible
|
||||
requirement from the contained type since objects can be directly constructed in-place without need of a copy.<br>
|
||||
The only requirement on the container is that it must provide proper storage (that is, correctly aligned and sized).
|
||||
Naturally, the container will typically support uninitialized storage to avoid the in-place construction to override
|
||||
a fully-constructed object (as this would defeat the purpose of in-place construction)
|
||||
</p>
|
||||
<p>For this purpose, the framework provides two families of classes collectively called: InPlaceFactories and TypedInPlaceFactories.<br>
|
||||
Essentially, these classes hold a sequence of actual parameters and a method to contruct an object in place using these parameters.
|
||||
Each member of the family differs only in the number (and type) of the parameter list. The first family
|
||||
takes the type of the object to construct directly in method provided for that
|
||||
purpose, whereas the second family incorporates that type in the factory class
|
||||
itself..</p>
|
||||
<p>From the container POV, using the framework amounts to calling the factory's method to contruct the object in place.
|
||||
From the user POV, it amounts to creating the right factory object to hold the parameters and pass it to the container.<br>
|
||||
The following simplified example shows the basic idea. A complete example follows the formal specification of the framework:</p>
|
||||
<pre>struct C
|
||||
{
|
||||
template<class InPlaceFactory>
|
||||
C ( InPlaceFactory const& aFactory )
|
||||
:
|
||||
contained_ ( uninitialized_storage() )
|
||||
{
|
||||
aFactory.template apply<X>(contained_);
|
||||
}
|
||||
|
||||
~C()
|
||||
{
|
||||
contained_ -> X::~X();
|
||||
delete[] contained_ ;
|
||||
}
|
||||
|
||||
char* uninitialized_storage() { return new char[sizeof(X)] ; }
|
||||
|
||||
char* contained_ ;
|
||||
} ;
|
||||
|
||||
void foo()
|
||||
{
|
||||
C c( in_place(123,"hello") ) ;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<HR>
|
||||
|
||||
<H2><A NAME="specification">Specification</A></H2>
|
||||
|
||||
<p>The following is the first member of the family of 'in_place_factory' classes, along with its corresponding helper template function.
|
||||
The rest of the family varies only in the number and type of template (and constructor) parameters.</p>
|
||||
<PRE>namespace boost {
|
||||
|
||||
struct in_place_factory_base {} ;
|
||||
|
||||
template<class A0>
|
||||
class in_place_factory : public in_place_factory_base
|
||||
{
|
||||
public:</PRE>
|
||||
|
||||
<PRE> in_place_factory ( A0 const& a0 ) : m_a0(a0) {}
|
||||
|
||||
template< class T >
|
||||
void apply ( void* address ) const
|
||||
{
|
||||
new (address) T(m_a0);
|
||||
}
|
||||
|
||||
private:</PRE>
|
||||
|
||||
<PRE> A0 const& m_a0 ;
|
||||
} ;
|
||||
|
||||
template<class A0>
|
||||
in_place_factory<A0> in_place ( A0 const& a0 )
|
||||
{
|
||||
return in_place_factory<A0>(a0);
|
||||
}
|
||||
</PRE>
|
||||
|
||||
<p>Similarly, the following is the first member of the family of 'typed_in_place_factory' classes, along with its corresponding
|
||||
helper template function. The rest of the family varies only in the number and type of template (and constructor) parameters.</p>
|
||||
<PRE>namespace boost {
|
||||
|
||||
struct typed_in_place_factory_base {} ;
|
||||
|
||||
template<class T, class A0>
|
||||
class typed_in_place_factory : public typed_in_place_factory_base
|
||||
{
|
||||
public:</PRE>
|
||||
|
||||
<PRE> typed_in_place_factory ( A0 const& a0 ) : m_a0(a0) {}
|
||||
|
||||
void apply ( void* address ) const
|
||||
{
|
||||
new (address) T(m_a0);
|
||||
}
|
||||
|
||||
private:</PRE>
|
||||
|
||||
<PRE> A0 const& m_a0 ;
|
||||
} ;
|
||||
|
||||
template<class T, class A0>
|
||||
typed_in_place_factory<A0> in_place ( A0 const& a0 )
|
||||
{
|
||||
return typed_in_place_factory<T,A0>(a0);
|
||||
}</PRE>
|
||||
|
||||
<PRE>}
|
||||
</PRE>
|
||||
|
||||
<p>As you can see, the 'in_place_factory' and 'typed_in_place_factory' template classes varies only in the way they specify
|
||||
the target type: in the first family, the type is given as a template argument to the apply member function while in the
|
||||
second it is given directly as part of the factory class.<br>
|
||||
When the container holds a unique non-polymorphic type (such as the case of Boost.Optional), it knows the exact dynamic-type
|
||||
of the contained object and can pass it to the apply() method of a (non-typed) factory.
|
||||
In this case, end users can use an 'in_place_factory' instance which can be constructed without the type of the object to construct.<br>
|
||||
However, if the container holds heterogeneous or polymorphic objects (such as the case of Boost.Variant), the dynamic-type
|
||||
of the object to be constructed must be known by the factory itslef. In this case, end users must use a 'typed_in_place_factory'
|
||||
instead.</p>
|
||||
|
||||
<HR>
|
||||
|
||||
<h2><A NAME="container-usage">Container-side Usage</a></h2>
|
||||
|
||||
<p>As shown in the introductory simplified example, the container class must
|
||||
contain methods that accept an instance of
|
||||
these factories and pass the object's storage to the factory's apply method.<br>
|
||||
However, the type of the factory class cannot be completly specified in the container class because that would
|
||||
defeat the whole purpose of the factories which is to allow the container to accept a variadic argument list
|
||||
for the constructor of its contained object.<br>
|
||||
The correct function overload must be based on the only distinctive and common
|
||||
characteristic of all the classes in each family, the base class.<br>
|
||||
Depending on the container class, you can use 'enable_if' to generate the right overload, or use the following
|
||||
dispatch technique (used in the Boost.Optional class):
|
||||
</p>
|
||||
<pre>struct C
|
||||
{
|
||||
C() : contained_(0) {}
|
||||
C ( X const& v ) : contained_ ( new X(v) ) {}
|
||||
|
||||
template<class Expr>
|
||||
C ( Expr const& expr )
|
||||
:
|
||||
contained_ ( uninitialized_storage() )
|
||||
{
|
||||
construct(expr,&expr)
|
||||
}
|
||||
|
||||
~C() { delete contained_ ; }
|
||||
|
||||
template<class InPlaceFactory>
|
||||
void construct ( InPlaceFactory const& aFactory, boost::in_place_factory_base* )
|
||||
{
|
||||
aFactory.template apply<X>(contained_);
|
||||
}
|
||||
|
||||
template<class TypedInPlaceFactory>
|
||||
void construct ( TypedInPlaceFactory const& aFactory, boost::typed_in_place_factory_base* )
|
||||
{
|
||||
aFactory.apply(contained_);
|
||||
}
|
||||
|
||||
X* uninitialized_storage() { return static_cast<X*>(new char[sizeof(X)]) ; }
|
||||
|
||||
X* contained_ ;
|
||||
} ;
|
||||
</pre>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Boost.Utility</title>
|
||||
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="./doc/html/utility/utilities/in_place_factory.html">./doc/html/utility/utilities/in_place_factory.html</a>
|
||||
<hr>
|
||||
|
||||
<h2><A NAME="user-usage">User-side Usage</a></h2>
|
||||
|
||||
<p>End users pass to the container an instance of a factory object holding the actual parameters needed to construct the
|
||||
contained object directly within the container. For this, the helper template function 'in_place' is used.<br>
|
||||
The call 'in_place(a0,a1,a2,...,an)' constructs a (non-typed) 'in_place_factory' instance with the given argument list.<br>
|
||||
The call 'in_place<T>(a0,a1,a2,...,an)' constructs a 'typed_in_place_factory' instance with the given argument list for the
|
||||
type 'T'.</p>
|
||||
<pre>void foo()
|
||||
{
|
||||
C a( in_place(123,"hello") ) ; // in_place_factory passed
|
||||
C b( in_place<X>(456,"world") ) ; // typed_in_place_factory passed
|
||||
}
|
||||
</pre>
|
||||
|
||||
<P>Revised September 17, 2004</P>
|
||||
<p><EFBFBD> Copyright Fernando Luis Cacciola Carballal, 2004</p>
|
||||
<p> Use, modification, and distribution are subject to the Boost Software
|
||||
License, Version 1.0. (See accompanying file <a href="../../LICENSE_1_0.txt">
|
||||
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
|
||||
www.boost.org/LICENSE_1_0.txt</a>)</p>
|
||||
<P>Developed by <A HREF="mailto:fernando_cacciola@hotmail.com">Fernando Cacciola</A>,
|
||||
the latest version of this file can be found at <A
|
||||
HREF="http://www.boost.org">www.boost.org</A>, and the boost
|
||||
<A HREF="http://www.boost.org/more/mailing_lists.htm#main">discussion lists</A></P>
|
||||
</BODY>
|
||||
</HTML>
|
||||
<tt>
|
||||
Boost.Utility<br>
|
||||
<br>
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||
<br>
|
||||
</tt>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,141 +0,0 @@
|
||||
//
|
||||
// boost/assert.hpp - BOOST_ASSERT(expr)
|
||||
// BOOST_ASSERT_MSG(expr, msg)
|
||||
// BOOST_VERIFY(expr)
|
||||
//
|
||||
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
|
||||
// Copyright (c) 2007 Peter Dimov
|
||||
// Copyright (c) Beman Dawes 2011
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
// Note: There are no include guards. This is intentional.
|
||||
//
|
||||
// See http://www.boost.org/libs/utility/assert.html for documentation.
|
||||
//
|
||||
|
||||
//
|
||||
// Stop inspect complaining about use of 'assert':
|
||||
//
|
||||
// boostinspect:naassert_macro
|
||||
//
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
// BOOST_ASSERT //
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#undef BOOST_ASSERT
|
||||
|
||||
#if defined(BOOST_DISABLE_ASSERTS)
|
||||
|
||||
# define BOOST_ASSERT(expr) ((void)0)
|
||||
|
||||
#elif defined(BOOST_ENABLE_ASSERT_HANDLER)
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/current_function.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
void assertion_failed(char const * expr,
|
||||
char const * function, char const * file, long line); // user defined
|
||||
} // namespace boost
|
||||
|
||||
#define BOOST_ASSERT(expr) (BOOST_LIKELY(!!(expr)) \
|
||||
? ((void)0) \
|
||||
: ::boost::assertion_failed(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
|
||||
|
||||
#else
|
||||
# include <assert.h> // .h to support old libraries w/o <cassert> - effect is the same
|
||||
# define BOOST_ASSERT(expr) assert(expr)
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
// BOOST_ASSERT_MSG //
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# undef BOOST_ASSERT_MSG
|
||||
|
||||
#if defined(BOOST_DISABLE_ASSERTS) || defined(NDEBUG)
|
||||
|
||||
#define BOOST_ASSERT_MSG(expr, msg) ((void)0)
|
||||
|
||||
#elif defined(BOOST_ENABLE_ASSERT_HANDLER)
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/current_function.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
void assertion_failed_msg(char const * expr, char const * msg,
|
||||
char const * function, char const * file, long line); // user defined
|
||||
} // namespace boost
|
||||
|
||||
#define BOOST_ASSERT_MSG(expr, msg) (BOOST_LIKELY(!!(expr)) \
|
||||
? ((void)0) \
|
||||
: ::boost::assertion_failed_msg(#expr, msg, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
|
||||
|
||||
#else
|
||||
#ifndef BOOST_ASSERT_HPP
|
||||
#define BOOST_ASSERT_HPP
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/current_function.hpp>
|
||||
|
||||
// IDE's like Visual Studio perform better if output goes to std::cout or
|
||||
// some other stream, so allow user to configure output stream:
|
||||
#ifndef BOOST_ASSERT_MSG_OSTREAM
|
||||
# define BOOST_ASSERT_MSG_OSTREAM std::cerr
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace assertion
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
// Note: The template is needed to make the function non-inline and avoid linking errors
|
||||
template< typename CharT >
|
||||
BOOST_NOINLINE void assertion_failed_msg(CharT const * expr, char const * msg, char const * function,
|
||||
char const * file, long line)
|
||||
{
|
||||
BOOST_ASSERT_MSG_OSTREAM
|
||||
<< "***** Internal Program Error - assertion (" << expr << ") failed in "
|
||||
<< function << ":\n"
|
||||
<< file << '(' << line << "): " << msg << std::endl;
|
||||
#ifdef UNDER_CE
|
||||
// The Windows CE CRT library does not have abort() so use exit(-1) instead.
|
||||
std::exit(-1);
|
||||
#else
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
} // detail
|
||||
} // assertion
|
||||
} // detail
|
||||
#endif
|
||||
|
||||
#define BOOST_ASSERT_MSG(expr, msg) (BOOST_LIKELY(!!(expr)) \
|
||||
? ((void)0) \
|
||||
: ::boost::assertion::detail::assertion_failed_msg(#expr, msg, \
|
||||
BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
// BOOST_VERIFY //
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#undef BOOST_VERIFY
|
||||
|
||||
#if defined(BOOST_DISABLE_ASSERTS) || ( !defined(BOOST_ENABLE_ASSERT_HANDLER) && defined(NDEBUG) )
|
||||
|
||||
# define BOOST_VERIFY(expr) ((void)(expr))
|
||||
|
||||
#else
|
||||
|
||||
# define BOOST_VERIFY(expr) BOOST_ASSERT(expr)
|
||||
|
||||
#endif
|
@ -5,7 +5,7 @@
|
||||
//
|
||||
// See http://www.boost.org/libs/utility for most recent version including documentation.
|
||||
|
||||
// See boost/detail/call_traits.hpp and boost/detail/ob_call_traits.hpp
|
||||
// See boost/detail/call_traits.hpp
|
||||
// for full copyright notices.
|
||||
|
||||
#ifndef BOOST_CALL_TRAITS_HPP
|
||||
@ -15,10 +15,6 @@
|
||||
#include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
#include <boost/detail/ob_call_traits.hpp>
|
||||
#else
|
||||
#include <boost/detail/call_traits.hpp>
|
||||
#endif
|
||||
|
||||
#endif // BOOST_CALL_TRAITS_HPP
|
||||
|
@ -1,69 +0,0 @@
|
||||
#ifndef BOOST_CHECKED_DELETE_HPP_INCLUDED
|
||||
#define BOOST_CHECKED_DELETE_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// boost/checked_delete.hpp
|
||||
//
|
||||
// Copyright (c) 2002, 2003 Peter Dimov
|
||||
// Copyright (c) 2003 Daniel Frey
|
||||
// Copyright (c) 2003 Howard Hinnant
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/utility/checked_delete.html for documentation.
|
||||
//
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
// verify that types are complete for increased safety
|
||||
|
||||
template<class T> inline void checked_delete(T * x)
|
||||
{
|
||||
// intentionally complex - simplification causes regressions
|
||||
typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
|
||||
(void) sizeof(type_must_be_complete);
|
||||
delete x;
|
||||
}
|
||||
|
||||
template<class T> inline void checked_array_delete(T * x)
|
||||
{
|
||||
typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
|
||||
(void) sizeof(type_must_be_complete);
|
||||
delete [] x;
|
||||
}
|
||||
|
||||
template<class T> struct checked_deleter
|
||||
{
|
||||
typedef void result_type;
|
||||
typedef T * argument_type;
|
||||
|
||||
void operator()(T * x) const
|
||||
{
|
||||
// boost:: disables ADL
|
||||
boost::checked_delete(x);
|
||||
}
|
||||
};
|
||||
|
||||
template<class T> struct checked_array_deleter
|
||||
{
|
||||
typedef void result_type;
|
||||
typedef T * argument_type;
|
||||
|
||||
void operator()(T * x) const
|
||||
{
|
||||
boost::checked_array_delete(x);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_CHECKED_DELETE_HPP_INCLUDED
|
@ -5,7 +5,7 @@
|
||||
//
|
||||
// See http://www.boost.org/libs/utility for most recent version including documentation.
|
||||
|
||||
// See boost/detail/compressed_pair.hpp and boost/detail/ob_compressed_pair.hpp
|
||||
// See boost/detail/compressed_pair.hpp
|
||||
// for full copyright notices.
|
||||
|
||||
#ifndef BOOST_COMPRESSED_PAIR_HPP
|
||||
@ -15,10 +15,6 @@
|
||||
#include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
#include <boost/detail/ob_compressed_pair.hpp>
|
||||
#else
|
||||
#include <boost/detail/compressed_pair.hpp>
|
||||
#endif
|
||||
|
||||
#endif // BOOST_COMPRESSED_PAIR_HPP
|
||||
|
@ -1,68 +0,0 @@
|
||||
#ifndef BOOST_CURRENT_FUNCTION_HPP_INCLUDED
|
||||
#define BOOST_CURRENT_FUNCTION_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// boost/current_function.hpp - BOOST_CURRENT_FUNCTION
|
||||
//
|
||||
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
// http://www.boost.org/libs/utility/current_function.html
|
||||
//
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
inline void current_function_helper()
|
||||
{
|
||||
|
||||
#if defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) || (defined(__ICC) && (__ICC >= 600)) || defined(__ghs__)
|
||||
|
||||
# define BOOST_CURRENT_FUNCTION __PRETTY_FUNCTION__
|
||||
|
||||
#elif defined(__DMC__) && (__DMC__ >= 0x810)
|
||||
|
||||
# define BOOST_CURRENT_FUNCTION __PRETTY_FUNCTION__
|
||||
|
||||
#elif defined(__FUNCSIG__)
|
||||
|
||||
# define BOOST_CURRENT_FUNCTION __FUNCSIG__
|
||||
|
||||
#elif (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 600)) || (defined(__IBMCPP__) && (__IBMCPP__ >= 500))
|
||||
|
||||
# define BOOST_CURRENT_FUNCTION __FUNCTION__
|
||||
|
||||
#elif defined(__BORLANDC__) && (__BORLANDC__ >= 0x550)
|
||||
|
||||
# define BOOST_CURRENT_FUNCTION __FUNC__
|
||||
|
||||
#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)
|
||||
|
||||
# define BOOST_CURRENT_FUNCTION __func__
|
||||
|
||||
#else
|
||||
|
||||
# define BOOST_CURRENT_FUNCTION "(unknown)"
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_CURRENT_FUNCTION_HPP_INCLUDED
|
||||
|
@ -100,7 +100,7 @@ struct call_traits<T&>
|
||||
typedef T& param_type; // hh removed const
|
||||
};
|
||||
|
||||
#if BOOST_WORKAROUND( __BORLANDC__, < 0x5A0 )
|
||||
#if BOOST_WORKAROUND( BOOST_BORLANDC, < 0x5A0 )
|
||||
// these are illegal specialisations; cv-qualifies applied to
|
||||
// references have no effect according to [8.3.2p1],
|
||||
// C++ Builder requires them though as it treats cv-qualified
|
||||
|
@ -6,7 +6,7 @@
|
||||
// See http://www.boost.org/libs/utility for most recent version including documentation.
|
||||
|
||||
// compressed_pair: pair that "compresses" empty members
|
||||
// (see libs/utility/compressed_pair.htm)
|
||||
// (see libs/utility/doc/html/compressed_pair.html)
|
||||
//
|
||||
// JM changes 25 Jan 2004:
|
||||
// For the case where T1 == T2 and both are empty, then first() and second()
|
||||
@ -24,6 +24,7 @@
|
||||
|
||||
#include <boost/type_traits/remove_cv.hpp>
|
||||
#include <boost/type_traits/is_empty.hpp>
|
||||
#include <boost/type_traits/is_final.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/call_traits.hpp>
|
||||
|
||||
@ -42,6 +43,14 @@ class compressed_pair;
|
||||
|
||||
namespace details
|
||||
{
|
||||
template<class T, bool E = boost::is_final<T>::value>
|
||||
struct compressed_pair_empty
|
||||
: ::boost::false_type { };
|
||||
|
||||
template<class T>
|
||||
struct compressed_pair_empty<T, false>
|
||||
: ::boost::is_empty<T> { };
|
||||
|
||||
// JM altered 26 Jan 2000:
|
||||
template <class T1, class T2, bool IsSame, bool FirstEmpty, bool SecondEmpty>
|
||||
struct compressed_pair_switch;
|
||||
@ -338,13 +347,15 @@ namespace details
|
||||
|
||||
template <class T1, class T2>
|
||||
class compressed_pair
|
||||
: private ::boost::details::compressed_pair_imp<T1, T2,
|
||||
#ifndef BOOST_UTILITY_DOCS
|
||||
: private ::boost::details::compressed_pair_imp<T1, T2,
|
||||
::boost::details::compressed_pair_switch<
|
||||
T1,
|
||||
T2,
|
||||
::boost::is_same<typename remove_cv<T1>::type, typename remove_cv<T2>::type>::value,
|
||||
::boost::is_empty<T1>::value,
|
||||
::boost::is_empty<T2>::value>::value>
|
||||
::boost::details::compressed_pair_empty<T1>::value,
|
||||
::boost::details::compressed_pair_empty<T2>::value>::value>
|
||||
#endif // BOOST_UTILITY_DOCS
|
||||
{
|
||||
private:
|
||||
typedef details::compressed_pair_imp<T1, T2,
|
||||
@ -352,8 +363,8 @@ private:
|
||||
T1,
|
||||
T2,
|
||||
::boost::is_same<typename remove_cv<T1>::type, typename remove_cv<T2>::type>::value,
|
||||
::boost::is_empty<T1>::value,
|
||||
::boost::is_empty<T2>::value>::value> base;
|
||||
::boost::details::compressed_pair_empty<T1>::value,
|
||||
::boost::details::compressed_pair_empty<T2>::value>::value> base;
|
||||
public:
|
||||
typedef T1 first_type;
|
||||
typedef T2 second_type;
|
||||
@ -383,13 +394,15 @@ public:
|
||||
//
|
||||
template <class T>
|
||||
class compressed_pair<T, T>
|
||||
#ifndef BOOST_UTILITY_DOCS
|
||||
: private details::compressed_pair_imp<T, T,
|
||||
::boost::details::compressed_pair_switch<
|
||||
T,
|
||||
T,
|
||||
::boost::is_same<typename remove_cv<T>::type, typename remove_cv<T>::type>::value,
|
||||
::boost::is_empty<T>::value,
|
||||
::boost::is_empty<T>::value>::value>
|
||||
::boost::details::compressed_pair_empty<T>::value,
|
||||
::boost::details::compressed_pair_empty<T>::value>::value>
|
||||
#endif // BOOST_UTILITY_DOCS
|
||||
{
|
||||
private:
|
||||
typedef details::compressed_pair_imp<T, T,
|
||||
@ -397,8 +410,8 @@ private:
|
||||
T,
|
||||
T,
|
||||
::boost::is_same<typename remove_cv<T>::type, typename remove_cv<T>::type>::value,
|
||||
::boost::is_empty<T>::value,
|
||||
::boost::is_empty<T>::value>::value> base;
|
||||
::boost::details::compressed_pair_empty<T>::value,
|
||||
::boost::details::compressed_pair_empty<T>::value>::value> base;
|
||||
public:
|
||||
typedef T first_type;
|
||||
typedef T second_type;
|
||||
|
@ -1,168 +0,0 @@
|
||||
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
|
||||
// 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).
|
||||
//
|
||||
// See http://www.boost.org/libs/utility for most recent version including documentation.
|
||||
//
|
||||
// Crippled version for crippled compilers:
|
||||
// see libs/utility/call_traits.htm
|
||||
//
|
||||
|
||||
/* Release notes:
|
||||
01st October 2000:
|
||||
Fixed call_traits on VC6, using "poor man's partial specialisation",
|
||||
using ideas taken from "Generative programming" by Krzysztof Czarnecki
|
||||
& Ulrich Eisenecker.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_OB_CALL_TRAITS_HPP
|
||||
#define BOOST_OB_CALL_TRAITS_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
#include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_ARITHMETIC_TYPE_TRAITS_HPP
|
||||
#include <boost/type_traits/arithmetic_traits.hpp>
|
||||
#endif
|
||||
#ifndef BOOST_COMPOSITE_TYPE_TRAITS_HPP
|
||||
#include <boost/type_traits/composite_traits.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost{
|
||||
|
||||
#ifdef BOOST_MSVC6_MEMBER_TEMPLATES
|
||||
//
|
||||
// use member templates to emulate
|
||||
// partial specialisation:
|
||||
//
|
||||
namespace detail{
|
||||
|
||||
template <class T>
|
||||
struct standard_call_traits
|
||||
{
|
||||
typedef T value_type;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef const T& param_type;
|
||||
};
|
||||
template <class T>
|
||||
struct simple_call_traits
|
||||
{
|
||||
typedef T value_type;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef const T param_type;
|
||||
};
|
||||
template <class T>
|
||||
struct reference_call_traits
|
||||
{
|
||||
typedef T value_type;
|
||||
typedef T reference;
|
||||
typedef T const_reference;
|
||||
typedef T param_type;
|
||||
};
|
||||
|
||||
template <bool pointer, bool arithmetic, bool reference>
|
||||
struct call_traits_chooser
|
||||
{
|
||||
template <class T>
|
||||
struct rebind
|
||||
{
|
||||
typedef standard_call_traits<T> type;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct call_traits_chooser<true, false, false>
|
||||
{
|
||||
template <class T>
|
||||
struct rebind
|
||||
{
|
||||
typedef simple_call_traits<T> type;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct call_traits_chooser<false, false, true>
|
||||
{
|
||||
template <class T>
|
||||
struct rebind
|
||||
{
|
||||
typedef reference_call_traits<T> type;
|
||||
};
|
||||
};
|
||||
|
||||
template <bool size_is_small>
|
||||
struct call_traits_sizeof_chooser2
|
||||
{
|
||||
template <class T>
|
||||
struct small_rebind
|
||||
{
|
||||
typedef simple_call_traits<T> small_type;
|
||||
};
|
||||
};
|
||||
|
||||
template<>
|
||||
struct call_traits_sizeof_chooser2<false>
|
||||
{
|
||||
template <class T>
|
||||
struct small_rebind
|
||||
{
|
||||
typedef standard_call_traits<T> small_type;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct call_traits_chooser<false, true, false>
|
||||
{
|
||||
template <class T>
|
||||
struct rebind
|
||||
{
|
||||
enum { sizeof_choice = (sizeof(T) <= sizeof(void*)) };
|
||||
typedef call_traits_sizeof_chooser2<(sizeof(T) <= sizeof(void*))> chooser;
|
||||
typedef typename chooser::template small_rebind<T> bound_type;
|
||||
typedef typename bound_type::small_type type;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
template <typename T>
|
||||
struct call_traits
|
||||
{
|
||||
private:
|
||||
typedef detail::call_traits_chooser<
|
||||
::boost::is_pointer<T>::value,
|
||||
::boost::is_arithmetic<T>::value,
|
||||
::boost::is_reference<T>::value
|
||||
> chooser;
|
||||
typedef typename chooser::template rebind<T> bound_type;
|
||||
typedef typename bound_type::type call_traits_type;
|
||||
public:
|
||||
typedef typename call_traits_type::value_type value_type;
|
||||
typedef typename call_traits_type::reference reference;
|
||||
typedef typename call_traits_type::const_reference const_reference;
|
||||
typedef typename call_traits_type::param_type param_type;
|
||||
};
|
||||
|
||||
#else
|
||||
//
|
||||
// sorry call_traits is completely non-functional
|
||||
// blame your broken compiler:
|
||||
//
|
||||
|
||||
template <typename T>
|
||||
struct call_traits
|
||||
{
|
||||
typedef T value_type;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef const T& param_type;
|
||||
};
|
||||
|
||||
#endif // member templates
|
||||
|
||||
}
|
||||
|
||||
#endif // BOOST_OB_CALL_TRAITS_HPP
|
@ -20,10 +20,11 @@
|
||||
- John Maddock Jan 2000.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BOOST_UTILITY_DOCS
|
||||
#ifndef BOOST_OB_COMPRESSED_PAIR_HPP
|
||||
#define BOOST_OB_COMPRESSED_PAIR_HPP
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#ifndef BOOST_OBJECT_TYPE_TRAITS_HPP
|
||||
#include <boost/type_traits/object_traits.hpp>
|
||||
@ -167,17 +168,6 @@ public:
|
||||
compressed_pair_1(const ::boost::compressed_pair<T1,T2>& x)
|
||||
: T2(x.second()), _first(x.first()) {}
|
||||
|
||||
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
|
||||
// Total weirdness. If the assignment to _first is moved after
|
||||
// the call to the inherited operator=, then this breaks graph/test/graph.cpp
|
||||
// by way of iterator_adaptor.
|
||||
compressed_pair_1& operator=(const compressed_pair_1& x) {
|
||||
_first = x._first;
|
||||
T2::operator=(x);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
first_reference first() { return _first; }
|
||||
first_const_reference first() const { return _first; }
|
||||
|
||||
@ -505,6 +495,4 @@ inline void swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
|
||||
} // boost
|
||||
|
||||
#endif // BOOST_OB_COMPRESSED_PAIR_HPP
|
||||
|
||||
|
||||
|
||||
#endif // BOOST_UTILITY_DOCS
|
||||
|
@ -1,80 +0,0 @@
|
||||
// (C) Copyright Jens Maurer 2001.
|
||||
// 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)
|
||||
//
|
||||
// Revision History:
|
||||
|
||||
// 15 Nov 2001 Jens Maurer
|
||||
// created.
|
||||
|
||||
// See http://www.boost.org/libs/utility/iterator_adaptors.htm for documentation.
|
||||
|
||||
#ifndef BOOST_ITERATOR_ADAPTOR_GENERATOR_ITERATOR_HPP
|
||||
#define BOOST_ITERATOR_ADAPTOR_GENERATOR_ITERATOR_HPP
|
||||
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template<class Generator>
|
||||
class generator_iterator
|
||||
: public iterator_facade<
|
||||
generator_iterator<Generator>
|
||||
, typename Generator::result_type
|
||||
, single_pass_traversal_tag
|
||||
, typename Generator::result_type const&
|
||||
>
|
||||
{
|
||||
typedef iterator_facade<
|
||||
generator_iterator<Generator>
|
||||
, typename Generator::result_type
|
||||
, single_pass_traversal_tag
|
||||
, typename Generator::result_type const&
|
||||
> super_t;
|
||||
|
||||
public:
|
||||
generator_iterator() {}
|
||||
generator_iterator(Generator* g) : m_g(g), m_value((*m_g)()) {}
|
||||
|
||||
void increment()
|
||||
{
|
||||
m_value = (*m_g)();
|
||||
}
|
||||
|
||||
const typename Generator::result_type&
|
||||
dereference() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
bool equal(generator_iterator const& y) const
|
||||
{
|
||||
return this->m_g == y.m_g && this->m_value == y.m_value;
|
||||
}
|
||||
|
||||
private:
|
||||
Generator* m_g;
|
||||
typename Generator::result_type m_value;
|
||||
};
|
||||
|
||||
template<class Generator>
|
||||
struct generator_iterator_generator
|
||||
{
|
||||
typedef generator_iterator<Generator> type;
|
||||
};
|
||||
|
||||
template <class Generator>
|
||||
inline generator_iterator<Generator>
|
||||
make_generator_iterator(Generator & gen)
|
||||
{
|
||||
typedef generator_iterator<Generator> result_t;
|
||||
return result_t(&gen);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_ITERATOR_ADAPTOR_GENERATOR_ITERATOR_HPP
|
||||
|
@ -1,51 +0,0 @@
|
||||
// Boost next_prior.hpp header file ---------------------------------------//
|
||||
|
||||
// (C) Copyright Dave Abrahams and Daniel Walker 1999-2003. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See http://www.boost.org/libs/utility for documentation.
|
||||
|
||||
// Revision History
|
||||
// 13 Dec 2003 Added next(x, n) and prior(x, n) (Daniel Walker)
|
||||
|
||||
#ifndef BOOST_NEXT_PRIOR_HPP_INCLUDED
|
||||
#define BOOST_NEXT_PRIOR_HPP_INCLUDED
|
||||
|
||||
#include <iterator>
|
||||
|
||||
namespace boost {
|
||||
|
||||
// Helper functions for classes like bidirectional iterators not supporting
|
||||
// operator+ and operator-
|
||||
//
|
||||
// Usage:
|
||||
// const std::list<T>::iterator p = get_some_iterator();
|
||||
// const std::list<T>::iterator prev = boost::prior(p);
|
||||
// const std::list<T>::iterator next = boost::next(prev, 2);
|
||||
|
||||
// Contributed by Dave Abrahams
|
||||
|
||||
template <class T>
|
||||
inline T next(T x) { return ++x; }
|
||||
|
||||
template <class T, class Distance>
|
||||
inline T next(T x, Distance n)
|
||||
{
|
||||
std::advance(x, n);
|
||||
return x;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T prior(T x) { return --x; }
|
||||
|
||||
template <class T, class Distance>
|
||||
inline T prior(T x, Distance n)
|
||||
{
|
||||
std::advance(x, -n);
|
||||
return x;
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_NEXT_PRIOR_HPP_INCLUDED
|
@ -1,48 +0,0 @@
|
||||
// Boost noncopyable.hpp header file --------------------------------------//
|
||||
|
||||
// (C) Copyright Beman Dawes 1999-2003. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See http://www.boost.org/libs/utility for documentation.
|
||||
|
||||
#ifndef BOOST_NONCOPYABLE_HPP_INCLUDED
|
||||
#define BOOST_NONCOPYABLE_HPP_INCLUDED
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
// Private copy constructor and copy assignment ensure classes derived from
|
||||
// class noncopyable cannot be copied.
|
||||
|
||||
// Contributed by Dave Abrahams
|
||||
|
||||
namespace noncopyable_ // protection from unintended ADL
|
||||
{
|
||||
class noncopyable
|
||||
{
|
||||
protected:
|
||||
#ifndef BOOST_NO_DEFAULTED_FUNCTIONS
|
||||
BOOST_CONSTEXPR noncopyable() = default;
|
||||
~noncopyable() = default;
|
||||
#else
|
||||
noncopyable() {}
|
||||
~noncopyable() {}
|
||||
#endif
|
||||
#ifndef BOOST_NO_DELETED_FUNCTIONS
|
||||
noncopyable( const noncopyable& ) = delete;
|
||||
noncopyable& operator=( const noncopyable& ) = delete;
|
||||
#else
|
||||
private: // emphasize the following members are private
|
||||
noncopyable( const noncopyable& );
|
||||
noncopyable& operator=( const noncopyable& );
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
typedef noncopyable_::noncopyable noncopyable;
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_NONCOPYABLE_HPP_INCLUDED
|
File diff suppressed because it is too large
Load Diff
951
include/boost/operators_v1.hpp
Normal file
951
include/boost/operators_v1.hpp
Normal file
@ -0,0 +1,951 @@
|
||||
// Boost operators.hpp header file ----------------------------------------//
|
||||
|
||||
// (C) Copyright David Abrahams, Jeremy Siek, Daryle Walker 1999-2001.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See http://www.boost.org/libs/utility/operators.htm for documentation.
|
||||
|
||||
// Revision History
|
||||
// 22 Feb 16 Preserve old work-arounds. (Daniel Frey)
|
||||
// 16 Dec 10 Limit warning suppression for 4284 to older versions of VC++
|
||||
// (Matthew Bradbury, fixes #4432)
|
||||
// 07 Aug 08 Added "euclidean" spelling. (Daniel Frey)
|
||||
// 03 Apr 08 Make sure "convertible to bool" is sufficient
|
||||
// for T::operator<, etc. (Daniel Frey)
|
||||
// 24 May 07 Changed empty_base to depend on T, see
|
||||
// http://svn.boost.org/trac/boost/ticket/979
|
||||
// 21 Oct 02 Modified implementation of operators to allow compilers with a
|
||||
// correct named return value optimization (NRVO) to produce optimal
|
||||
// code. (Daniel Frey)
|
||||
// 02 Dec 01 Bug fixed in random_access_iteratable. (Helmut Zeisel)
|
||||
// 28 Sep 01 Factored out iterator operator groups. (Daryle Walker)
|
||||
// 27 Aug 01 'left' form for non commutative operators added;
|
||||
// additional classes for groups of related operators added;
|
||||
// workaround for empty base class optimization
|
||||
// bug of GCC 3.0 (Helmut Zeisel)
|
||||
// 25 Jun 01 output_iterator_helper changes: removed default template
|
||||
// parameters, added support for self-proxying, additional
|
||||
// documentation and tests (Aleksey Gurtovoy)
|
||||
// 29 May 01 Added operator classes for << and >>. Added input and output
|
||||
// iterator helper classes. Added classes to connect equality and
|
||||
// relational operators. Added classes for groups of related
|
||||
// operators. Reimplemented example operator and iterator helper
|
||||
// classes in terms of the new groups. (Daryle Walker, with help
|
||||
// from Alexy Gurtovoy)
|
||||
// 11 Feb 01 Fixed bugs in the iterator helpers which prevented explicitly
|
||||
// supplied arguments from actually being used (Dave Abrahams)
|
||||
// 04 Jul 00 Fixed NO_OPERATORS_IN_NAMESPACE bugs, major cleanup and
|
||||
// refactoring of compiler workarounds, additional documentation
|
||||
// (Alexy Gurtovoy and Mark Rodgers with some help and prompting from
|
||||
// Dave Abrahams)
|
||||
// 28 Jun 00 General cleanup and integration of bugfixes from Mark Rodgers and
|
||||
// Jeremy Siek (Dave Abrahams)
|
||||
// 20 Jun 00 Changes to accommodate Borland C++Builder 4 and Borland C++ 5.5
|
||||
// (Mark Rodgers)
|
||||
// 20 Jun 00 Minor fixes to the prior revision (Aleksey Gurtovoy)
|
||||
// 10 Jun 00 Support for the base class chaining technique was added
|
||||
// (Aleksey Gurtovoy). See documentation and the comments below
|
||||
// for the details.
|
||||
// 12 Dec 99 Initial version with iterator operators (Jeremy Siek)
|
||||
// 18 Nov 99 Change name "divideable" to "dividable", remove unnecessary
|
||||
// specializations of dividable, subtractable, modable (Ed Brey)
|
||||
// 17 Nov 99 Add comments (Beman Dawes)
|
||||
// Remove unnecessary specialization of operators<> (Ed Brey)
|
||||
// 15 Nov 99 Fix less_than_comparable<T,U> second operand type for first two
|
||||
// operators.(Beman Dawes)
|
||||
// 12 Nov 99 Add operators templates (Ed Brey)
|
||||
// 11 Nov 99 Add single template parameter version for compilers without
|
||||
// partial specialization (Beman Dawes)
|
||||
// 10 Nov 99 Initial version
|
||||
|
||||
// 10 Jun 00:
|
||||
// An additional optional template parameter was added to most of
|
||||
// operator templates to support the base class chaining technique (see
|
||||
// documentation for the details). Unfortunately, a straightforward
|
||||
// implementation of this change would have broken compatibility with the
|
||||
// previous version of the library by making it impossible to use the same
|
||||
// template name (e.g. 'addable') for both the 1- and 2-argument versions of
|
||||
// an operator template. This implementation solves the backward-compatibility
|
||||
// issue at the cost of some simplicity.
|
||||
//
|
||||
// One of the complications is an existence of special auxiliary class template
|
||||
// 'is_chained_base<>' (see 'detail' namespace below), which is used
|
||||
// to determine whether its template parameter is a library's operator template
|
||||
// or not. You have to specialize 'is_chained_base<>' for each new
|
||||
// operator template you add to the library.
|
||||
//
|
||||
// However, most of the non-trivial implementation details are hidden behind
|
||||
// several local macros defined below, and as soon as you understand them,
|
||||
// you understand the whole library implementation.
|
||||
|
||||
#ifndef BOOST_OPERATORS_V1_HPP
|
||||
#define BOOST_OPERATORS_V1_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
#if defined(__sgi) && !defined(__GNUC__)
|
||||
# pragma set woff 1234
|
||||
#endif
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, < 1600)
|
||||
# pragma warning( disable : 4284 ) // complaint about return type of
|
||||
#endif // operator-> not begin a UDT
|
||||
|
||||
namespace boost {
|
||||
namespace detail {
|
||||
|
||||
template <typename T> class empty_base {};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace boost
|
||||
|
||||
// In this section we supply the xxxx1 and xxxx2 forms of the operator
|
||||
// templates, which are explicitly targeted at the 1-type-argument and
|
||||
// 2-type-argument operator forms, respectively. Some compilers get confused
|
||||
// when inline friend functions are overloaded in namespaces other than the
|
||||
// global namespace. When BOOST_NO_OPERATORS_IN_NAMESPACE is defined, all of
|
||||
// these templates must go in the global namespace.
|
||||
|
||||
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||
namespace boost
|
||||
{
|
||||
#endif
|
||||
|
||||
// Basic operator classes (contributed by Dave Abrahams) ------------------//
|
||||
|
||||
// Note that friend functions defined in a class are implicitly inline.
|
||||
// See the C++ std, 11.4 [class.friend] paragraph 5
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct less_than_comparable2 : B
|
||||
{
|
||||
friend bool operator<=(const T& x, const U& y) { return !static_cast<bool>(x > y); }
|
||||
friend bool operator>=(const T& x, const U& y) { return !static_cast<bool>(x < y); }
|
||||
friend bool operator>(const U& x, const T& y) { return y < x; }
|
||||
friend bool operator<(const U& x, const T& y) { return y > x; }
|
||||
friend bool operator<=(const U& x, const T& y) { return !static_cast<bool>(y < x); }
|
||||
friend bool operator>=(const U& x, const T& y) { return !static_cast<bool>(y > x); }
|
||||
};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct less_than_comparable1 : B
|
||||
{
|
||||
friend bool operator>(const T& x, const T& y) { return y < x; }
|
||||
friend bool operator<=(const T& x, const T& y) { return !static_cast<bool>(y < x); }
|
||||
friend bool operator>=(const T& x, const T& y) { return !static_cast<bool>(x < y); }
|
||||
};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct equality_comparable2 : B
|
||||
{
|
||||
friend bool operator==(const U& y, const T& x) { return x == y; }
|
||||
friend bool operator!=(const U& y, const T& x) { return !static_cast<bool>(x == y); }
|
||||
friend bool operator!=(const T& y, const U& x) { return !static_cast<bool>(y == x); }
|
||||
};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct equality_comparable1 : B
|
||||
{
|
||||
friend bool operator!=(const T& x, const T& y) { return !static_cast<bool>(x == y); }
|
||||
};
|
||||
|
||||
// A macro which produces "name_2left" from "name".
|
||||
#define BOOST_OPERATOR2_LEFT(name) name##2##_##left
|
||||
|
||||
// NRVO-friendly implementation (contributed by Daniel Frey) ---------------//
|
||||
|
||||
#if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
|
||||
|
||||
// This is the optimal implementation for ISO/ANSI C++,
|
||||
// but it requires the compiler to implement the NRVO.
|
||||
// If the compiler has no NRVO, this is the best symmetric
|
||||
// implementation available.
|
||||
|
||||
#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
|
||||
struct NAME##2 : B \
|
||||
{ \
|
||||
friend T operator OP( const T& lhs, const U& rhs ) \
|
||||
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
|
||||
friend T operator OP( const U& lhs, const T& rhs ) \
|
||||
{ T nrv( rhs ); nrv OP##= lhs; return nrv; } \
|
||||
}; \
|
||||
\
|
||||
template <class T, class B = ::boost::detail::empty_base<T> > \
|
||||
struct NAME##1 : B \
|
||||
{ \
|
||||
friend T operator OP( const T& lhs, const T& rhs ) \
|
||||
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
|
||||
};
|
||||
|
||||
#define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
|
||||
struct NAME##2 : B \
|
||||
{ \
|
||||
friend T operator OP( const T& lhs, const U& rhs ) \
|
||||
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
|
||||
}; \
|
||||
\
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
|
||||
struct BOOST_OPERATOR2_LEFT(NAME) : B \
|
||||
{ \
|
||||
friend T operator OP( const U& lhs, const T& rhs ) \
|
||||
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
|
||||
}; \
|
||||
\
|
||||
template <class T, class B = ::boost::detail::empty_base<T> > \
|
||||
struct NAME##1 : B \
|
||||
{ \
|
||||
friend T operator OP( const T& lhs, const T& rhs ) \
|
||||
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
|
||||
};
|
||||
|
||||
#else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
|
||||
|
||||
// For compilers without NRVO the following code is optimal, but not
|
||||
// symmetric! Note that the implementation of
|
||||
// BOOST_OPERATOR2_LEFT(NAME) only looks cool, but doesn't provide
|
||||
// optimization opportunities to the compiler :)
|
||||
|
||||
#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
|
||||
struct NAME##2 : B \
|
||||
{ \
|
||||
friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
|
||||
friend T operator OP( const U& lhs, T rhs ) { return rhs OP##= lhs; } \
|
||||
}; \
|
||||
\
|
||||
template <class T, class B = ::boost::detail::empty_base<T> > \
|
||||
struct NAME##1 : B \
|
||||
{ \
|
||||
friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
|
||||
};
|
||||
|
||||
#define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
|
||||
struct NAME##2 : B \
|
||||
{ \
|
||||
friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
|
||||
}; \
|
||||
\
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
|
||||
struct BOOST_OPERATOR2_LEFT(NAME) : B \
|
||||
{ \
|
||||
friend T operator OP( const U& lhs, const T& rhs ) \
|
||||
{ return T( lhs ) OP##= rhs; } \
|
||||
}; \
|
||||
\
|
||||
template <class T, class B = ::boost::detail::empty_base<T> > \
|
||||
struct NAME##1 : B \
|
||||
{ \
|
||||
friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
|
||||
};
|
||||
|
||||
#endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
|
||||
|
||||
BOOST_BINARY_OPERATOR_COMMUTATIVE( multipliable, * )
|
||||
BOOST_BINARY_OPERATOR_COMMUTATIVE( addable, + )
|
||||
BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( subtractable, - )
|
||||
BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( dividable, / )
|
||||
BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( modable, % )
|
||||
BOOST_BINARY_OPERATOR_COMMUTATIVE( xorable, ^ )
|
||||
BOOST_BINARY_OPERATOR_COMMUTATIVE( andable, & )
|
||||
BOOST_BINARY_OPERATOR_COMMUTATIVE( orable, | )
|
||||
|
||||
#undef BOOST_BINARY_OPERATOR_COMMUTATIVE
|
||||
#undef BOOST_BINARY_OPERATOR_NON_COMMUTATIVE
|
||||
#undef BOOST_OPERATOR2_LEFT
|
||||
|
||||
// incrementable and decrementable contributed by Jeremy Siek
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct incrementable : B
|
||||
{
|
||||
friend T operator++(T& x, int)
|
||||
{
|
||||
incrementable_type nrv(x);
|
||||
++x;
|
||||
return nrv;
|
||||
}
|
||||
private: // The use of this typedef works around a Borland bug
|
||||
typedef T incrementable_type;
|
||||
};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct decrementable : B
|
||||
{
|
||||
friend T operator--(T& x, int)
|
||||
{
|
||||
decrementable_type nrv(x);
|
||||
--x;
|
||||
return nrv;
|
||||
}
|
||||
private: // The use of this typedef works around a Borland bug
|
||||
typedef T decrementable_type;
|
||||
};
|
||||
|
||||
// Iterator operator classes (contributed by Jeremy Siek) ------------------//
|
||||
|
||||
template <class T, class P, class B = ::boost::detail::empty_base<T> >
|
||||
struct dereferenceable : B
|
||||
{
|
||||
P operator->() const
|
||||
{
|
||||
return &*static_cast<const T&>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class I, class R, class B = ::boost::detail::empty_base<T> >
|
||||
struct indexable : B
|
||||
{
|
||||
R operator[](I n) const
|
||||
{
|
||||
return *(static_cast<const T&>(*this) + n);
|
||||
}
|
||||
};
|
||||
|
||||
// More operator classes (contributed by Daryle Walker) --------------------//
|
||||
// (NRVO-friendly implementation contributed by Daniel Frey) ---------------//
|
||||
|
||||
#if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
|
||||
|
||||
#define BOOST_BINARY_OPERATOR( NAME, OP ) \
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
|
||||
struct NAME##2 : B \
|
||||
{ \
|
||||
friend T operator OP( const T& lhs, const U& rhs ) \
|
||||
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
|
||||
}; \
|
||||
\
|
||||
template <class T, class B = ::boost::detail::empty_base<T> > \
|
||||
struct NAME##1 : B \
|
||||
{ \
|
||||
friend T operator OP( const T& lhs, const T& rhs ) \
|
||||
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
|
||||
};
|
||||
|
||||
#else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
|
||||
|
||||
#define BOOST_BINARY_OPERATOR( NAME, OP ) \
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
|
||||
struct NAME##2 : B \
|
||||
{ \
|
||||
friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
|
||||
}; \
|
||||
\
|
||||
template <class T, class B = ::boost::detail::empty_base<T> > \
|
||||
struct NAME##1 : B \
|
||||
{ \
|
||||
friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
|
||||
};
|
||||
|
||||
#endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
|
||||
|
||||
BOOST_BINARY_OPERATOR( left_shiftable, << )
|
||||
BOOST_BINARY_OPERATOR( right_shiftable, >> )
|
||||
|
||||
#undef BOOST_BINARY_OPERATOR
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct equivalent2 : B
|
||||
{
|
||||
friend bool operator==(const T& x, const U& y)
|
||||
{
|
||||
return !static_cast<bool>(x < y) && !static_cast<bool>(x > y);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct equivalent1 : B
|
||||
{
|
||||
friend bool operator==(const T&x, const T&y)
|
||||
{
|
||||
return !static_cast<bool>(x < y) && !static_cast<bool>(y < x);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct partially_ordered2 : B
|
||||
{
|
||||
friend bool operator<=(const T& x, const U& y)
|
||||
{ return static_cast<bool>(x < y) || static_cast<bool>(x == y); }
|
||||
friend bool operator>=(const T& x, const U& y)
|
||||
{ return static_cast<bool>(x > y) || static_cast<bool>(x == y); }
|
||||
friend bool operator>(const U& x, const T& y)
|
||||
{ return y < x; }
|
||||
friend bool operator<(const U& x, const T& y)
|
||||
{ return y > x; }
|
||||
friend bool operator<=(const U& x, const T& y)
|
||||
{ return static_cast<bool>(y > x) || static_cast<bool>(y == x); }
|
||||
friend bool operator>=(const U& x, const T& y)
|
||||
{ return static_cast<bool>(y < x) || static_cast<bool>(y == x); }
|
||||
};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct partially_ordered1 : B
|
||||
{
|
||||
friend bool operator>(const T& x, const T& y)
|
||||
{ return y < x; }
|
||||
friend bool operator<=(const T& x, const T& y)
|
||||
{ return static_cast<bool>(x < y) || static_cast<bool>(x == y); }
|
||||
friend bool operator>=(const T& x, const T& y)
|
||||
{ return static_cast<bool>(y < x) || static_cast<bool>(x == y); }
|
||||
};
|
||||
|
||||
// Combined operator classes (contributed by Daryle Walker) ----------------//
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct totally_ordered2
|
||||
: less_than_comparable2<T, U
|
||||
, equality_comparable2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct totally_ordered1
|
||||
: less_than_comparable1<T
|
||||
, equality_comparable1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct additive2
|
||||
: addable2<T, U
|
||||
, subtractable2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct additive1
|
||||
: addable1<T
|
||||
, subtractable1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct multiplicative2
|
||||
: multipliable2<T, U
|
||||
, dividable2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct multiplicative1
|
||||
: multipliable1<T
|
||||
, dividable1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct integer_multiplicative2
|
||||
: multiplicative2<T, U
|
||||
, modable2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct integer_multiplicative1
|
||||
: multiplicative1<T
|
||||
, modable1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct arithmetic2
|
||||
: additive2<T, U
|
||||
, multiplicative2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct arithmetic1
|
||||
: additive1<T
|
||||
, multiplicative1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct integer_arithmetic2
|
||||
: additive2<T, U
|
||||
, integer_multiplicative2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct integer_arithmetic1
|
||||
: additive1<T
|
||||
, integer_multiplicative1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct bitwise2
|
||||
: xorable2<T, U
|
||||
, andable2<T, U
|
||||
, orable2<T, U, B
|
||||
> > > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct bitwise1
|
||||
: xorable1<T
|
||||
, andable1<T
|
||||
, orable1<T, B
|
||||
> > > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct unit_steppable
|
||||
: incrementable<T
|
||||
, decrementable<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct shiftable2
|
||||
: left_shiftable2<T, U
|
||||
, right_shiftable2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct shiftable1
|
||||
: left_shiftable1<T
|
||||
, right_shiftable1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct ring_operators2
|
||||
: additive2<T, U
|
||||
, subtractable2_left<T, U
|
||||
, multipliable2<T, U, B
|
||||
> > > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct ring_operators1
|
||||
: additive1<T
|
||||
, multipliable1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct ordered_ring_operators2
|
||||
: ring_operators2<T, U
|
||||
, totally_ordered2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct ordered_ring_operators1
|
||||
: ring_operators1<T
|
||||
, totally_ordered1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct field_operators2
|
||||
: ring_operators2<T, U
|
||||
, dividable2<T, U
|
||||
, dividable2_left<T, U, B
|
||||
> > > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct field_operators1
|
||||
: ring_operators1<T
|
||||
, dividable1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct ordered_field_operators2
|
||||
: field_operators2<T, U
|
||||
, totally_ordered2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct ordered_field_operators1
|
||||
: field_operators1<T
|
||||
, totally_ordered1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct euclidian_ring_operators2
|
||||
: ring_operators2<T, U
|
||||
, dividable2<T, U
|
||||
, dividable2_left<T, U
|
||||
, modable2<T, U
|
||||
, modable2_left<T, U, B
|
||||
> > > > > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct euclidian_ring_operators1
|
||||
: ring_operators1<T
|
||||
, dividable1<T
|
||||
, modable1<T, B
|
||||
> > > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct ordered_euclidian_ring_operators2
|
||||
: totally_ordered2<T, U
|
||||
, euclidian_ring_operators2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct ordered_euclidian_ring_operators1
|
||||
: totally_ordered1<T
|
||||
, euclidian_ring_operators1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct euclidean_ring_operators2
|
||||
: ring_operators2<T, U
|
||||
, dividable2<T, U
|
||||
, dividable2_left<T, U
|
||||
, modable2<T, U
|
||||
, modable2_left<T, U, B
|
||||
> > > > > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct euclidean_ring_operators1
|
||||
: ring_operators1<T
|
||||
, dividable1<T
|
||||
, modable1<T, B
|
||||
> > > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> >
|
||||
struct ordered_euclidean_ring_operators2
|
||||
: totally_ordered2<T, U
|
||||
, euclidean_ring_operators2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct ordered_euclidean_ring_operators1
|
||||
: totally_ordered1<T
|
||||
, euclidean_ring_operators1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class P, class B = ::boost::detail::empty_base<T> >
|
||||
struct input_iteratable
|
||||
: equality_comparable1<T
|
||||
, incrementable<T
|
||||
, dereferenceable<T, P, B
|
||||
> > > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base<T> >
|
||||
struct output_iteratable
|
||||
: incrementable<T, B
|
||||
> {};
|
||||
|
||||
template <class T, class P, class B = ::boost::detail::empty_base<T> >
|
||||
struct forward_iteratable
|
||||
: input_iteratable<T, P, B
|
||||
> {};
|
||||
|
||||
template <class T, class P, class B = ::boost::detail::empty_base<T> >
|
||||
struct bidirectional_iteratable
|
||||
: forward_iteratable<T, P
|
||||
, decrementable<T, B
|
||||
> > {};
|
||||
|
||||
// To avoid repeated derivation from equality_comparable,
|
||||
// which is an indirect base class of bidirectional_iterable,
|
||||
// random_access_iteratable must not be derived from totally_ordered1
|
||||
// but from less_than_comparable1 only. (Helmut Zeisel, 02-Dec-2001)
|
||||
template <class T, class P, class D, class R, class B = ::boost::detail::empty_base<T> >
|
||||
struct random_access_iteratable
|
||||
: bidirectional_iteratable<T, P
|
||||
, less_than_comparable1<T
|
||||
, additive2<T, D
|
||||
, indexable<T, D, R, B
|
||||
> > > > {};
|
||||
|
||||
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||
} // namespace boost
|
||||
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||
|
||||
|
||||
// BOOST_IMPORT_TEMPLATE1 .. BOOST_IMPORT_TEMPLATE4 -
|
||||
//
|
||||
// When BOOST_NO_OPERATORS_IN_NAMESPACE is defined we need a way to import an
|
||||
// operator template into the boost namespace. BOOST_IMPORT_TEMPLATE1 is used
|
||||
// for one-argument forms of operator templates; BOOST_IMPORT_TEMPLATE2 for
|
||||
// two-argument forms. Note that these macros expect to be invoked from within
|
||||
// boost.
|
||||
|
||||
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||
|
||||
// The template is already in boost so we have nothing to do.
|
||||
# define BOOST_IMPORT_TEMPLATE4(template_name)
|
||||
# define BOOST_IMPORT_TEMPLATE3(template_name)
|
||||
# define BOOST_IMPORT_TEMPLATE2(template_name)
|
||||
# define BOOST_IMPORT_TEMPLATE1(template_name)
|
||||
|
||||
#else // BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||
|
||||
# ifndef BOOST_NO_USING_TEMPLATE
|
||||
|
||||
// Bring the names in with a using-declaration
|
||||
// to avoid stressing the compiler.
|
||||
# define BOOST_IMPORT_TEMPLATE4(template_name) using ::template_name;
|
||||
# define BOOST_IMPORT_TEMPLATE3(template_name) using ::template_name;
|
||||
# define BOOST_IMPORT_TEMPLATE2(template_name) using ::template_name;
|
||||
# define BOOST_IMPORT_TEMPLATE1(template_name) using ::template_name;
|
||||
|
||||
# else
|
||||
|
||||
// Otherwise, because a Borland C++ 5.5 bug prevents a using declaration
|
||||
// from working, we are forced to use inheritance for that compiler.
|
||||
# define BOOST_IMPORT_TEMPLATE4(template_name) \
|
||||
template <class T, class U, class V, class W, class B = ::boost::detail::empty_base<T> > \
|
||||
struct template_name : ::template_name<T, U, V, W, B> {};
|
||||
|
||||
# define BOOST_IMPORT_TEMPLATE3(template_name) \
|
||||
template <class T, class U, class V, class B = ::boost::detail::empty_base<T> > \
|
||||
struct template_name : ::template_name<T, U, V, B> {};
|
||||
|
||||
# define BOOST_IMPORT_TEMPLATE2(template_name) \
|
||||
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
|
||||
struct template_name : ::template_name<T, U, B> {};
|
||||
|
||||
# define BOOST_IMPORT_TEMPLATE1(template_name) \
|
||||
template <class T, class B = ::boost::detail::empty_base<T> > \
|
||||
struct template_name : ::template_name<T, B> {};
|
||||
|
||||
# endif // BOOST_NO_USING_TEMPLATE
|
||||
|
||||
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||
|
||||
//
|
||||
// Here's where we put it all together, defining the xxxx forms of the templates
|
||||
// in namespace boost. We also define specializations of is_chained_base<> for
|
||||
// the xxxx, xxxx1, and xxxx2 templates, importing them into boost:: as
|
||||
// necessary.
|
||||
//
|
||||
|
||||
// is_chained_base<> - a traits class used to distinguish whether an operator
|
||||
// template argument is being used for base class chaining, or is specifying a
|
||||
// 2nd argument type.
|
||||
|
||||
namespace boost {
|
||||
// A type parameter is used instead of a plain bool because Borland's compiler
|
||||
// didn't cope well with the more obvious non-type template parameter.
|
||||
namespace detail {
|
||||
struct true_t {};
|
||||
struct false_t {};
|
||||
} // namespace detail
|
||||
|
||||
// Unspecialized version assumes that most types are not being used for base
|
||||
// class chaining. We specialize for the operator templates defined in this
|
||||
// library.
|
||||
template<class T> struct is_chained_base {
|
||||
typedef ::boost::detail::false_t value;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
// Import a 4-type-argument operator template into boost (if necessary) and
|
||||
// provide a specialization of 'is_chained_base<>' for it.
|
||||
# define BOOST_OPERATOR_TEMPLATE4(template_name4) \
|
||||
BOOST_IMPORT_TEMPLATE4(template_name4) \
|
||||
template<class T, class U, class V, class W, class B> \
|
||||
struct is_chained_base< ::boost::template_name4<T, U, V, W, B> > { \
|
||||
typedef ::boost::detail::true_t value; \
|
||||
};
|
||||
|
||||
// Import a 3-type-argument operator template into boost (if necessary) and
|
||||
// provide a specialization of 'is_chained_base<>' for it.
|
||||
# define BOOST_OPERATOR_TEMPLATE3(template_name3) \
|
||||
BOOST_IMPORT_TEMPLATE3(template_name3) \
|
||||
template<class T, class U, class V, class B> \
|
||||
struct is_chained_base< ::boost::template_name3<T, U, V, B> > { \
|
||||
typedef ::boost::detail::true_t value; \
|
||||
};
|
||||
|
||||
// Import a 2-type-argument operator template into boost (if necessary) and
|
||||
// provide a specialization of 'is_chained_base<>' for it.
|
||||
# define BOOST_OPERATOR_TEMPLATE2(template_name2) \
|
||||
BOOST_IMPORT_TEMPLATE2(template_name2) \
|
||||
template<class T, class U, class B> \
|
||||
struct is_chained_base< ::boost::template_name2<T, U, B> > { \
|
||||
typedef ::boost::detail::true_t value; \
|
||||
};
|
||||
|
||||
// Import a 1-type-argument operator template into boost (if necessary) and
|
||||
// provide a specialization of 'is_chained_base<>' for it.
|
||||
# define BOOST_OPERATOR_TEMPLATE1(template_name1) \
|
||||
BOOST_IMPORT_TEMPLATE1(template_name1) \
|
||||
template<class T, class B> \
|
||||
struct is_chained_base< ::boost::template_name1<T, B> > { \
|
||||
typedef ::boost::detail::true_t value; \
|
||||
};
|
||||
|
||||
// BOOST_OPERATOR_TEMPLATE(template_name) defines template_name<> such that it
|
||||
// can be used for specifying both 1-argument and 2-argument forms. Requires the
|
||||
// existence of two previously defined class templates named '<template_name>1'
|
||||
// and '<template_name>2' which must implement the corresponding 1- and 2-
|
||||
// argument forms.
|
||||
//
|
||||
// The template type parameter O == is_chained_base<U>::value is used to
|
||||
// distinguish whether the 2nd argument to <template_name> is being used for
|
||||
// base class chaining from another boost operator template or is describing a
|
||||
// 2nd operand type. O == true_t only when U is actually an another operator
|
||||
// template from the library. Partial specialization is used to select an
|
||||
// implementation in terms of either '<template_name>1' or '<template_name>2'.
|
||||
//
|
||||
|
||||
# define BOOST_OPERATOR_TEMPLATE(template_name) \
|
||||
template <class T \
|
||||
,class U = T \
|
||||
,class B = ::boost::detail::empty_base<T> \
|
||||
,class O = typename is_chained_base<U>::value \
|
||||
> \
|
||||
struct template_name : template_name##2<T, U, B> {}; \
|
||||
\
|
||||
template<class T, class U, class B> \
|
||||
struct template_name<T, U, B, ::boost::detail::true_t> \
|
||||
: template_name##1<T, U> {}; \
|
||||
\
|
||||
template <class T, class B> \
|
||||
struct template_name<T, T, B, ::boost::detail::false_t> \
|
||||
: template_name##1<T, B> {}; \
|
||||
\
|
||||
template<class T, class U, class B, class O> \
|
||||
struct is_chained_base< ::boost::template_name<T, U, B, O> > { \
|
||||
typedef ::boost::detail::true_t value; \
|
||||
}; \
|
||||
\
|
||||
BOOST_OPERATOR_TEMPLATE2(template_name##2) \
|
||||
BOOST_OPERATOR_TEMPLATE1(template_name##1)
|
||||
|
||||
|
||||
|
||||
namespace boost {
|
||||
|
||||
BOOST_OPERATOR_TEMPLATE(less_than_comparable)
|
||||
BOOST_OPERATOR_TEMPLATE(equality_comparable)
|
||||
BOOST_OPERATOR_TEMPLATE(multipliable)
|
||||
BOOST_OPERATOR_TEMPLATE(addable)
|
||||
BOOST_OPERATOR_TEMPLATE(subtractable)
|
||||
BOOST_OPERATOR_TEMPLATE2(subtractable2_left)
|
||||
BOOST_OPERATOR_TEMPLATE(dividable)
|
||||
BOOST_OPERATOR_TEMPLATE2(dividable2_left)
|
||||
BOOST_OPERATOR_TEMPLATE(modable)
|
||||
BOOST_OPERATOR_TEMPLATE2(modable2_left)
|
||||
BOOST_OPERATOR_TEMPLATE(xorable)
|
||||
BOOST_OPERATOR_TEMPLATE(andable)
|
||||
BOOST_OPERATOR_TEMPLATE(orable)
|
||||
|
||||
BOOST_OPERATOR_TEMPLATE1(incrementable)
|
||||
BOOST_OPERATOR_TEMPLATE1(decrementable)
|
||||
|
||||
BOOST_OPERATOR_TEMPLATE2(dereferenceable)
|
||||
BOOST_OPERATOR_TEMPLATE3(indexable)
|
||||
|
||||
BOOST_OPERATOR_TEMPLATE(left_shiftable)
|
||||
BOOST_OPERATOR_TEMPLATE(right_shiftable)
|
||||
BOOST_OPERATOR_TEMPLATE(equivalent)
|
||||
BOOST_OPERATOR_TEMPLATE(partially_ordered)
|
||||
|
||||
BOOST_OPERATOR_TEMPLATE(totally_ordered)
|
||||
BOOST_OPERATOR_TEMPLATE(additive)
|
||||
BOOST_OPERATOR_TEMPLATE(multiplicative)
|
||||
BOOST_OPERATOR_TEMPLATE(integer_multiplicative)
|
||||
BOOST_OPERATOR_TEMPLATE(arithmetic)
|
||||
BOOST_OPERATOR_TEMPLATE(integer_arithmetic)
|
||||
BOOST_OPERATOR_TEMPLATE(bitwise)
|
||||
BOOST_OPERATOR_TEMPLATE1(unit_steppable)
|
||||
BOOST_OPERATOR_TEMPLATE(shiftable)
|
||||
BOOST_OPERATOR_TEMPLATE(ring_operators)
|
||||
BOOST_OPERATOR_TEMPLATE(ordered_ring_operators)
|
||||
BOOST_OPERATOR_TEMPLATE(field_operators)
|
||||
BOOST_OPERATOR_TEMPLATE(ordered_field_operators)
|
||||
BOOST_OPERATOR_TEMPLATE(euclidian_ring_operators)
|
||||
BOOST_OPERATOR_TEMPLATE(ordered_euclidian_ring_operators)
|
||||
BOOST_OPERATOR_TEMPLATE(euclidean_ring_operators)
|
||||
BOOST_OPERATOR_TEMPLATE(ordered_euclidean_ring_operators)
|
||||
BOOST_OPERATOR_TEMPLATE2(input_iteratable)
|
||||
BOOST_OPERATOR_TEMPLATE1(output_iteratable)
|
||||
BOOST_OPERATOR_TEMPLATE2(forward_iteratable)
|
||||
BOOST_OPERATOR_TEMPLATE2(bidirectional_iteratable)
|
||||
BOOST_OPERATOR_TEMPLATE4(random_access_iteratable)
|
||||
|
||||
#undef BOOST_OPERATOR_TEMPLATE
|
||||
#undef BOOST_OPERATOR_TEMPLATE4
|
||||
#undef BOOST_OPERATOR_TEMPLATE3
|
||||
#undef BOOST_OPERATOR_TEMPLATE2
|
||||
#undef BOOST_OPERATOR_TEMPLATE1
|
||||
#undef BOOST_IMPORT_TEMPLATE1
|
||||
#undef BOOST_IMPORT_TEMPLATE2
|
||||
#undef BOOST_IMPORT_TEMPLATE3
|
||||
#undef BOOST_IMPORT_TEMPLATE4
|
||||
|
||||
// The following 'operators' classes can only be used portably if the derived class
|
||||
// declares ALL of the required member operators.
|
||||
template <class T, class U>
|
||||
struct operators2
|
||||
: totally_ordered2<T,U
|
||||
, integer_arithmetic2<T,U
|
||||
, bitwise2<T,U
|
||||
> > > {};
|
||||
|
||||
template <class T, class U = T>
|
||||
struct operators : operators2<T, U> {};
|
||||
|
||||
template <class T> struct operators<T, T>
|
||||
: totally_ordered<T
|
||||
, integer_arithmetic<T
|
||||
, bitwise<T
|
||||
, unit_steppable<T
|
||||
> > > > {};
|
||||
|
||||
// Iterator helper classes (contributed by Jeremy Siek) -------------------//
|
||||
// (Input and output iterator helpers contributed by Daryle Walker) -------//
|
||||
// (Changed to use combined operator classes by Daryle Walker) ------------//
|
||||
template <class T,
|
||||
class V,
|
||||
class D = std::ptrdiff_t,
|
||||
class P = V const *,
|
||||
class R = V const &>
|
||||
struct input_iterator_helper
|
||||
: input_iteratable<T, P
|
||||
, std::iterator<std::input_iterator_tag, V, D, P, R
|
||||
> > {};
|
||||
|
||||
template<class T>
|
||||
struct output_iterator_helper
|
||||
: output_iteratable<T
|
||||
, std::iterator<std::output_iterator_tag, void, void, void, void
|
||||
> >
|
||||
{
|
||||
T& operator*() { return static_cast<T&>(*this); }
|
||||
T& operator++() { return static_cast<T&>(*this); }
|
||||
};
|
||||
|
||||
template <class T,
|
||||
class V,
|
||||
class D = std::ptrdiff_t,
|
||||
class P = V*,
|
||||
class R = V&>
|
||||
struct forward_iterator_helper
|
||||
: forward_iteratable<T, P
|
||||
, std::iterator<std::forward_iterator_tag, V, D, P, R
|
||||
> > {};
|
||||
|
||||
template <class T,
|
||||
class V,
|
||||
class D = std::ptrdiff_t,
|
||||
class P = V*,
|
||||
class R = V&>
|
||||
struct bidirectional_iterator_helper
|
||||
: bidirectional_iteratable<T, P
|
||||
, std::iterator<std::bidirectional_iterator_tag, V, D, P, R
|
||||
> > {};
|
||||
|
||||
template <class T,
|
||||
class V,
|
||||
class D = std::ptrdiff_t,
|
||||
class P = V*,
|
||||
class R = V&>
|
||||
struct random_access_iterator_helper
|
||||
: random_access_iteratable<T, P, D, R
|
||||
, std::iterator<std::random_access_iterator_tag, V, D, P, R
|
||||
> >
|
||||
{
|
||||
friend D requires_difference_operator(const T& x, const T& y) {
|
||||
return x - y;
|
||||
}
|
||||
}; // random_access_iterator_helper
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#if defined(__sgi) && !defined(__GNUC__)
|
||||
#pragma reset woff 1234
|
||||
#endif
|
||||
|
||||
#endif // BOOST_OPERATORS_V1_HPP
|
@ -1,189 +0,0 @@
|
||||
#ifndef BOOST_REF_HPP_INCLUDED
|
||||
#define BOOST_REF_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/utility/addressof.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
//
|
||||
// ref.hpp - ref/cref, useful helper functions
|
||||
//
|
||||
// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
|
||||
// Copyright (C) 2001, 2002 Peter Dimov
|
||||
// Copyright (C) 2002 David Abrahams
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/bind/ref.html for documentation.
|
||||
//
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
template<class T> class reference_wrapper
|
||||
{
|
||||
public:
|
||||
typedef T type;
|
||||
|
||||
#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, < 1300 )
|
||||
|
||||
explicit reference_wrapper(T& t): t_(&t) {}
|
||||
|
||||
#else
|
||||
|
||||
explicit reference_wrapper(T& t): t_(boost::addressof(t)) {}
|
||||
|
||||
#endif
|
||||
|
||||
operator T& () const { return *t_; }
|
||||
|
||||
T& get() const { return *t_; }
|
||||
|
||||
T* get_pointer() const { return t_; }
|
||||
|
||||
private:
|
||||
|
||||
T* t_;
|
||||
};
|
||||
|
||||
# if defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0x581) )
|
||||
# define BOOST_REF_CONST
|
||||
# else
|
||||
# define BOOST_REF_CONST const
|
||||
# endif
|
||||
|
||||
template<class T> inline reference_wrapper<T> BOOST_REF_CONST ref(T & t)
|
||||
{
|
||||
return reference_wrapper<T>(t);
|
||||
}
|
||||
|
||||
template<class T> inline reference_wrapper<T const> BOOST_REF_CONST cref(T const & t)
|
||||
{
|
||||
return reference_wrapper<T const>(t);
|
||||
}
|
||||
|
||||
# undef BOOST_REF_CONST
|
||||
|
||||
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
template<typename T>
|
||||
class is_reference_wrapper
|
||||
: public mpl::false_
|
||||
{
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class unwrap_reference
|
||||
{
|
||||
public:
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
# define AUX_REFERENCE_WRAPPER_METAFUNCTIONS_DEF(X) \
|
||||
template<typename T> \
|
||||
class is_reference_wrapper< X > \
|
||||
: public mpl::true_ \
|
||||
{ \
|
||||
}; \
|
||||
\
|
||||
template<typename T> \
|
||||
class unwrap_reference< X > \
|
||||
{ \
|
||||
public: \
|
||||
typedef T type; \
|
||||
}; \
|
||||
/**/
|
||||
|
||||
AUX_REFERENCE_WRAPPER_METAFUNCTIONS_DEF(reference_wrapper<T>)
|
||||
#if !defined(BOOST_NO_CV_SPECIALIZATIONS)
|
||||
AUX_REFERENCE_WRAPPER_METAFUNCTIONS_DEF(reference_wrapper<T> const)
|
||||
AUX_REFERENCE_WRAPPER_METAFUNCTIONS_DEF(reference_wrapper<T> volatile)
|
||||
AUX_REFERENCE_WRAPPER_METAFUNCTIONS_DEF(reference_wrapper<T> const volatile)
|
||||
#endif
|
||||
|
||||
# undef AUX_REFERENCE_WRAPPER_METAFUNCTIONS_DEF
|
||||
|
||||
# else // no partial specialization
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/type.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
typedef char (&yes_reference_wrapper_t)[1];
|
||||
typedef char (&no_reference_wrapper_t)[2];
|
||||
|
||||
no_reference_wrapper_t is_reference_wrapper_test(...);
|
||||
|
||||
template<typename T>
|
||||
yes_reference_wrapper_t is_reference_wrapper_test(type< reference_wrapper<T> >);
|
||||
|
||||
template<bool wrapped>
|
||||
struct reference_unwrapper
|
||||
{
|
||||
template <class T>
|
||||
struct apply
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
};
|
||||
|
||||
template<>
|
||||
struct reference_unwrapper<true>
|
||||
{
|
||||
template <class T>
|
||||
struct apply
|
||||
{
|
||||
typedef typename T::type type;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
class is_reference_wrapper
|
||||
{
|
||||
public:
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, value = (
|
||||
sizeof(detail::is_reference_wrapper_test(type<T>()))
|
||||
== sizeof(detail::yes_reference_wrapper_t)));
|
||||
|
||||
typedef ::boost::mpl::bool_<value> type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class unwrap_reference
|
||||
: public detail::reference_unwrapper<
|
||||
is_reference_wrapper<T>::value
|
||||
>::template apply<T>
|
||||
{};
|
||||
|
||||
# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
template <class T> inline typename unwrap_reference<T>::type&
|
||||
unwrap_ref(T& t)
|
||||
{
|
||||
return t;
|
||||
}
|
||||
|
||||
template<class T> inline T* get_pointer( reference_wrapper<T> const & r )
|
||||
{
|
||||
return r.get_pointer();
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_REF_HPP_INCLUDED
|
@ -1,12 +0,0 @@
|
||||
// Copyright (C) 2007 Joseph Gauterin
|
||||
//
|
||||
// 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_SWAP_HPP
|
||||
#define BOOST_SWAP_HPP
|
||||
|
||||
#include "boost/utility/swap.hpp"
|
||||
|
||||
#endif
|
@ -9,13 +9,16 @@
|
||||
#ifndef BOOST_UTILITY_HPP
|
||||
#define BOOST_UTILITY_HPP
|
||||
|
||||
#include <boost/utility/addressof.hpp>
|
||||
// Use of this header is discouraged and it will be deprecated.
|
||||
// Please include one or more of the headers below instead.
|
||||
|
||||
#include <boost/utility/base_from_member.hpp>
|
||||
#include <boost/utility/binary.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/utility/identity_type.hpp>
|
||||
#include <boost/checked_delete.hpp>
|
||||
#include <boost/next_prior.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
#include <boost/core/addressof.hpp>
|
||||
#include <boost/core/enable_if.hpp>
|
||||
#include <boost/core/checked_delete.hpp>
|
||||
#include <boost/core/noncopyable.hpp>
|
||||
|
||||
#endif // BOOST_UTILITY_HPP
|
||||
|
@ -1,102 +0,0 @@
|
||||
// Copyright (C) 2002 Brad King (brad.king@kitware.com)
|
||||
// Douglas Gregor (gregod@cs.rpi.edu)
|
||||
//
|
||||
// Copyright (C) 2002, 2008 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)
|
||||
|
||||
// For more information, see http://www.boost.org
|
||||
|
||||
#ifndef BOOST_UTILITY_ADDRESSOF_HPP
|
||||
# define BOOST_UTILITY_ADDRESSOF_HPP
|
||||
|
||||
# include <boost/config.hpp>
|
||||
# include <boost/detail/workaround.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<class T> struct addr_impl_ref
|
||||
{
|
||||
T & v_;
|
||||
|
||||
inline addr_impl_ref( T & v ): v_( v ) {}
|
||||
inline operator T& () const { return v_; }
|
||||
|
||||
private:
|
||||
addr_impl_ref & operator=(const addr_impl_ref &);
|
||||
};
|
||||
|
||||
template<class T> struct addressof_impl
|
||||
{
|
||||
static inline T * f( T & v, long )
|
||||
{
|
||||
return reinterpret_cast<T*>(
|
||||
&const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
|
||||
}
|
||||
|
||||
static inline T * f( T * v, int )
|
||||
{
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<class T> T * addressof( T & v )
|
||||
{
|
||||
#if (defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x610 ) ) ) || defined( __SUNPRO_CC )
|
||||
|
||||
return boost::detail::addressof_impl<T>::f( v, 0 );
|
||||
|
||||
#else
|
||||
|
||||
return boost::detail::addressof_impl<T>::f( boost::detail::addr_impl_ref<T>( v ), 0 );
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined( __SUNPRO_CC ) && BOOST_WORKAROUND( __SUNPRO_CC, BOOST_TESTED_AT( 0x590 ) )
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<class T> struct addressof_addp
|
||||
{
|
||||
typedef T * type;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template< class T, std::size_t N >
|
||||
typename detail::addressof_addp< T[N] >::type addressof( T (&t)[N] )
|
||||
{
|
||||
return &t;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Borland doesn't like casting an array reference to a char reference
|
||||
// but these overloads work around the problem.
|
||||
#if defined( __BORLANDC__ ) && BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||
template<typename T,std::size_t N>
|
||||
T (*addressof(T (&t)[N]))[N]
|
||||
{
|
||||
return reinterpret_cast<T(*)[N]>(&t);
|
||||
}
|
||||
|
||||
template<typename T,std::size_t N>
|
||||
const T (*addressof(const T (&t)[N]))[N]
|
||||
{
|
||||
return reinterpret_cast<const T(*)[N]>(&t);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_UTILITY_ADDRESSOF_HPP
|
@ -47,13 +47,14 @@
|
||||
// {}
|
||||
// This macro should only persist within this file.
|
||||
|
||||
#define BOOST_PRIVATE_CTR_DEF( z, n, data ) \
|
||||
template < BOOST_PP_ENUM_PARAMS(n, typename T) > \
|
||||
explicit base_from_member( BOOST_PP_ENUM_BINARY_PARAMS(n, T, x) ) \
|
||||
: member( BOOST_PP_ENUM_PARAMS(n, x) ) \
|
||||
{} \
|
||||
#ifndef BOOST_UTILITY_DOCS
|
||||
#define BOOST_PRIVATE_CTR_DEF( z, n, data ) \
|
||||
template < BOOST_PP_ENUM_PARAMS(n, typename T) > \
|
||||
base_from_member( BOOST_PP_ENUM_BINARY_PARAMS(n, T, x) ) \
|
||||
: member( BOOST_PP_ENUM_PARAMS(n, x) ) \
|
||||
{} \
|
||||
/**/
|
||||
|
||||
#endif // BOOST_UTILITY_DOCS
|
||||
|
||||
namespace boost
|
||||
{
|
||||
@ -142,12 +143,26 @@ protected:
|
||||
: member()
|
||||
{}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO( 1, BOOST_PP_INC(BOOST_BASE_FROM_MEMBER_MAX_ARITY),
|
||||
template < typename T0 > explicit base_from_member( T0 x0 ) : member( x0 ) {}
|
||||
BOOST_PP_REPEAT_FROM_TO( 2, BOOST_PP_INC(BOOST_BASE_FROM_MEMBER_MAX_ARITY),
|
||||
BOOST_PRIVATE_CTR_DEF, _ )
|
||||
#endif
|
||||
|
||||
}; // boost::base_from_member
|
||||
|
||||
template < typename MemberType, int UniqueID >
|
||||
class base_from_member<MemberType&, UniqueID>
|
||||
{
|
||||
protected:
|
||||
MemberType& member;
|
||||
|
||||
explicit BOOST_CONSTEXPR base_from_member( MemberType& x )
|
||||
BOOST_NOEXCEPT
|
||||
: member( x )
|
||||
{}
|
||||
|
||||
}; // boost::base_from_member
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
|
@ -68,6 +68,7 @@
|
||||
( (0) BOOST_DETAIL_CREATE_BINARY_LITERAL_OCTAL_SEQUENCE( d, bit_groupings ) \
|
||||
)
|
||||
|
||||
#ifndef BOOST_UTILITY_DOCS
|
||||
#define BOOST_DETAIL_CREATE_BINARY_LITERAL_OCTAL_SEQUENCE( d, bit_groupings ) \
|
||||
BOOST_PP_SEQ_TRANSFORM \
|
||||
( BOOST_DETAIL_TRIPLE_TO_OCTAL_OPERATION \
|
||||
@ -703,6 +704,6 @@
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11111100 (1)(1)(1)(1)(1)(1)(0)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11111101 (1)(1)(1)(1)(1)(1)(0)(1),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11111110 (1)(1)(1)(1)(1)(1)(1)(0),
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11111111 (1)(1)(1)(1)(1)(1)(1)(1),
|
||||
|
||||
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11111111 (1)(1)(1)(1)(1)(1)(1)(1),
|
||||
#endif // BOOST_UTILITY_DOCS
|
||||
#endif
|
||||
|
@ -33,8 +33,12 @@ bool equal_pointees ( OptionalPointee const& x, OptionalPointee const& y )
|
||||
}
|
||||
|
||||
template<class OptionalPointee>
|
||||
struct equal_pointees_t : std::binary_function<OptionalPointee,OptionalPointee,bool>
|
||||
struct equal_pointees_t
|
||||
{
|
||||
typedef bool result_type;
|
||||
typedef OptionalPointee first_argument_type;
|
||||
typedef OptionalPointee second_argument_type;
|
||||
|
||||
bool operator() ( OptionalPointee const& x, OptionalPointee const& y ) const
|
||||
{ return equal_pointees(x,y) ; }
|
||||
} ;
|
||||
@ -56,8 +60,12 @@ bool less_pointees ( OptionalPointee const& x, OptionalPointee const& y )
|
||||
}
|
||||
|
||||
template<class OptionalPointee>
|
||||
struct less_pointees_t : std::binary_function<OptionalPointee,OptionalPointee,bool>
|
||||
struct less_pointees_t
|
||||
{
|
||||
typedef bool result_type;
|
||||
typedef OptionalPointee first_argument_type;
|
||||
typedef OptionalPointee second_argument_type;
|
||||
|
||||
bool operator() ( OptionalPointee const& x, OptionalPointee const& y ) const
|
||||
{ return less_pointees(x,y) ; }
|
||||
} ;
|
||||
|
@ -1,44 +0,0 @@
|
||||
// declval.hpp -------------------------------------------------------------//
|
||||
|
||||
// Copyright 2010 Vicente J. Botet Escriba
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// See http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_UTILITY_DECLVAL_HPP
|
||||
#define BOOST_UTILITY_DECLVAL_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#include <boost/type_traits/add_rvalue_reference.hpp>
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// C++03 implementation of //
|
||||
// 20.2.4 Function template declval [declval] //
|
||||
// Written by Vicente J. Botet Escriba //
|
||||
// //
|
||||
// 1 The library provides the function template declval to simplify the
|
||||
// definition of expressions which occur as unevaluated operands.
|
||||
// 2 Remarks: If this function is used, the program is ill-formed.
|
||||
// 3 Remarks: The template parameter T of declval may be an incomplete type.
|
||||
// [ Example:
|
||||
//
|
||||
// template <class To, class From>
|
||||
// decltype(static_cast<To>(declval<From>())) convert(From&&);
|
||||
//
|
||||
// declares a function template convert which only participates in overloading
|
||||
// if the type From can be explicitly converted to type To. For another example
|
||||
// see class template common_type (20.9.7.6). -end example ]
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <typename T>
|
||||
typename add_rvalue_reference<T>::type declval() BOOST_NOEXCEPT; // as unevaluated operand
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_UTILITY_DECLVAL_HPP
|
58
include/boost/utility/detail/minstd_rand.hpp
Normal file
58
include/boost/utility/detail/minstd_rand.hpp
Normal file
@ -0,0 +1,58 @@
|
||||
#ifndef BOOST_UTILITY_DETAIL_MINSTD_RAND_HPP_INCLUDED
|
||||
#define BOOST_UTILITY_DETAIL_MINSTD_RAND_HPP_INCLUDED
|
||||
|
||||
// Copyright 2017 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
|
||||
//
|
||||
// An implementation of minstd_rand that does not require
|
||||
// the Random library
|
||||
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class minstd_rand
|
||||
{
|
||||
private:
|
||||
|
||||
boost::uint_least32_t x_;
|
||||
|
||||
enum { a = 48271, m = 2147483647 };
|
||||
|
||||
public:
|
||||
|
||||
minstd_rand(): x_( 1 )
|
||||
{
|
||||
}
|
||||
|
||||
explicit minstd_rand( boost::uint_least32_t x ): x_( x % m )
|
||||
{
|
||||
if( x_ == 0 )
|
||||
{
|
||||
x_ = 1;
|
||||
}
|
||||
}
|
||||
|
||||
boost::uint_least32_t operator()()
|
||||
{
|
||||
boost::uint_least64_t y = x_;
|
||||
|
||||
y = ( a * y ) % m;
|
||||
|
||||
x_ = static_cast<boost::uint_least32_t>( y );
|
||||
|
||||
return x_;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_UTILITY_DETAIL_MINSTD_RAND_HPP_INCLUDED
|
@ -22,19 +22,19 @@
|
||||
# define BOOST_RESULT_OF_ARGS BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)
|
||||
#endif
|
||||
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
|
||||
#if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x551))
|
||||
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct tr1_result_of<F(BOOST_RESULT_OF_ARGS)>
|
||||
: mpl::if_<
|
||||
mpl::or_< is_pointer<F>, is_member_function_pointer<F> >
|
||||
: conditional<
|
||||
is_pointer<F>::value || is_member_function_pointer<F>::value
|
||||
, boost::detail::tr1_result_of_impl<
|
||||
typename remove_cv<F>::type,
|
||||
typename remove_cv<F>::type(BOOST_RESULT_OF_ARGS),
|
||||
(boost::detail::has_result_type<F>::value)>
|
||||
(boost::detail::result_of_has_result_type<F>::value)>
|
||||
, boost::detail::tr1_result_of_impl<
|
||||
F,
|
||||
F(BOOST_RESULT_OF_ARGS),
|
||||
(boost::detail::has_result_type<F>::value)> >::type { };
|
||||
(boost::detail::result_of_has_result_type<F>::value)> >::type { };
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
|
||||
@ -46,7 +46,7 @@ struct result_of<F(BOOST_RESULT_OF_ARGS)>
|
||||
#ifdef BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK
|
||||
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct result_of<F(BOOST_RESULT_OF_ARGS)>
|
||||
: mpl::if_<mpl::or_<detail::has_result_type<F>, detail::has_result<F> >,
|
||||
: conditional<detail::result_of_has_result_type<F>::value || detail::result_of_has_result<F>::value,
|
||||
tr1_result_of<F(BOOST_RESULT_OF_ARGS)>,
|
||||
detail::cpp0x_result_of<F(BOOST_RESULT_OF_ARGS)> >::type { };
|
||||
#endif // BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK
|
||||
@ -57,8 +57,8 @@ namespace detail {
|
||||
|
||||
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct cpp0x_result_of<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T))>
|
||||
: mpl::if_<
|
||||
is_member_function_pointer<F>
|
||||
: conditional<
|
||||
is_member_function_pointer<F>::value
|
||||
, detail::tr1_result_of_impl<
|
||||
typename remove_cv<F>::type,
|
||||
typename remove_cv<F>::type(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), false
|
||||
@ -82,25 +82,22 @@ struct BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION())<R(BOOST_PP_
|
||||
};
|
||||
|
||||
template<typename F>
|
||||
struct BOOST_PP_CAT(result_of_callable_fun_, BOOST_PP_ITERATION());
|
||||
struct BOOST_PP_CAT(result_of_callable_fun_, BOOST_PP_ITERATION())
|
||||
: BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION())<F>
|
||||
{};
|
||||
|
||||
template<typename F>
|
||||
struct BOOST_PP_CAT(result_of_callable_fun_, BOOST_PP_ITERATION())<F *>
|
||||
: BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION())<F>
|
||||
{};
|
||||
|
||||
template<typename F>
|
||||
struct BOOST_PP_CAT(result_of_callable_fun_, BOOST_PP_ITERATION())<F &>
|
||||
: BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION())<F>
|
||||
{};
|
||||
|
||||
template<typename F>
|
||||
struct BOOST_PP_CAT(result_of_select_call_wrapper_type_, BOOST_PP_ITERATION())
|
||||
: mpl::eval_if<
|
||||
is_class<typename remove_reference<F>::type>,
|
||||
: conditional<
|
||||
is_class<typename remove_reference<F>::type>::value,
|
||||
result_of_wrap_callable_class<F>,
|
||||
mpl::identity<BOOST_PP_CAT(result_of_callable_fun_, BOOST_PP_ITERATION())<typename remove_cv<F>::type> >
|
||||
>
|
||||
type_identity<BOOST_PP_CAT(result_of_callable_fun_, BOOST_PP_ITERATION())<typename remove_cv<typename remove_reference<F>::type>::type> >
|
||||
>::type
|
||||
{};
|
||||
|
||||
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), typename T)>
|
||||
@ -111,7 +108,7 @@ struct BOOST_PP_CAT(result_of_is_callable_, BOOST_PP_ITERATION()) {
|
||||
(boost::declval<wrapper_t>()(BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval<T, >() BOOST_PP_INTERCEPT)), result_of_weird_type())
|
||||
))
|
||||
);
|
||||
typedef mpl::bool_<value> type;
|
||||
typedef integral_constant<bool, value> type;
|
||||
};
|
||||
|
||||
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
@ -154,7 +151,7 @@ struct cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)),
|
||||
|
||||
#else // defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)
|
||||
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
|
||||
#if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x551))
|
||||
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct result_of<F(BOOST_RESULT_OF_ARGS)>
|
||||
: tr1_result_of<F(BOOST_RESULT_OF_ARGS)> { };
|
||||
@ -180,7 +177,7 @@ struct tr1_result_of_impl<R (&)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), F
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
|
||||
#if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x551))
|
||||
template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct tr1_result_of_impl<R (T0::*)
|
||||
(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T)),
|
||||
|
190
include/boost/utility/detail/result_of_variadic.hpp
Normal file
190
include/boost/utility/detail/result_of_variadic.hpp
Normal file
@ -0,0 +1,190 @@
|
||||
// Boost result_of library
|
||||
|
||||
// Copyright Douglas Gregor 2004. 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)
|
||||
|
||||
// Copyright Daniel Walker, Eric Niebler, Michel Morin 2008-2012.
|
||||
// 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)
|
||||
|
||||
// For more information, see http://www.boost.org/libs/utility
|
||||
|
||||
#ifndef BOOST_RESULT_OF_HPP
|
||||
# error Boost result_of - do not include this file!
|
||||
#endif
|
||||
|
||||
template<typename F, typename... Args>
|
||||
struct tr1_result_of<F(Args...)>
|
||||
: conditional<
|
||||
is_pointer<F>::value || is_member_function_pointer<F>::value
|
||||
, boost::detail::tr1_result_of_impl<
|
||||
typename remove_cv<F>::type,
|
||||
typename remove_cv<F>::type(Args...),
|
||||
(boost::detail::result_of_has_result_type<F>::value)>
|
||||
, boost::detail::tr1_result_of_impl<
|
||||
F,
|
||||
F(Args...),
|
||||
(boost::detail::result_of_has_result_type<F>::value)> >::type { };
|
||||
|
||||
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
|
||||
template<typename F, typename... Args>
|
||||
struct result_of<F(Args...)>
|
||||
: detail::cpp0x_result_of<F(Args...)> { };
|
||||
#endif // BOOST_RESULT_OF_USE_DECLTYPE
|
||||
|
||||
#ifdef BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK
|
||||
template<typename F, typename... Args>
|
||||
struct result_of<F(Args...)>
|
||||
: conditional<detail::result_of_has_result_type<F>::value || detail::result_of_has_result<F>::value,
|
||||
tr1_result_of<F(Args...)>,
|
||||
detail::cpp0x_result_of<F(Args...)> >::type { };
|
||||
#endif // BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK
|
||||
|
||||
#if defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename F, typename... Args>
|
||||
struct cpp0x_result_of<F(Args...)>
|
||||
: conditional<
|
||||
is_member_function_pointer<F>::value
|
||||
, detail::tr1_result_of_impl<
|
||||
typename remove_cv<F>::type,
|
||||
typename remove_cv<F>::type(Args...), false
|
||||
>
|
||||
, detail::cpp0x_result_of_impl<
|
||||
F(Args...)
|
||||
>
|
||||
>::type
|
||||
{};
|
||||
|
||||
#ifdef BOOST_NO_SFINAE_EXPR
|
||||
|
||||
template<typename F>
|
||||
struct result_of_callable_fun_2;
|
||||
|
||||
template<typename R, typename... Args>
|
||||
struct result_of_callable_fun_2<R(Args...)> {
|
||||
R operator()(Args...) const;
|
||||
typedef result_of_private_type const &(*pfn_t)(...);
|
||||
operator pfn_t() const volatile;
|
||||
};
|
||||
|
||||
template<typename F>
|
||||
struct result_of_callable_fun
|
||||
: result_of_callable_fun_2<F>
|
||||
{};
|
||||
|
||||
template<typename F>
|
||||
struct result_of_callable_fun<F *>
|
||||
: result_of_callable_fun_2<F>
|
||||
{};
|
||||
|
||||
template<typename F>
|
||||
struct result_of_select_call_wrapper_type
|
||||
: conditional<
|
||||
is_class<typename remove_reference<F>::type>::value,
|
||||
result_of_wrap_callable_class<F>,
|
||||
type_identity<result_of_callable_fun<typename remove_cv<typename remove_reference<F>::type>::type> >
|
||||
>::type
|
||||
{};
|
||||
|
||||
template<typename F, typename... Args>
|
||||
struct result_of_is_callable {
|
||||
typedef typename result_of_select_call_wrapper_type<F>::type wrapper_t;
|
||||
static const bool value = (
|
||||
sizeof(result_of_no_type) == sizeof(detail::result_of_is_private_type(
|
||||
(boost::declval<wrapper_t>()(boost::declval<Args>()...), result_of_weird_type())
|
||||
))
|
||||
);
|
||||
typedef integral_constant<bool, value> type;
|
||||
};
|
||||
|
||||
template<typename F, typename... Args>
|
||||
struct cpp0x_result_of_impl<F(Args...), true>
|
||||
: lazy_enable_if<
|
||||
result_of_is_callable<F, Args...>
|
||||
, cpp0x_result_of_impl<F(Args...), false>
|
||||
>
|
||||
{};
|
||||
|
||||
template<typename F, typename... Args>
|
||||
struct cpp0x_result_of_impl<F(Args...), false>
|
||||
{
|
||||
typedef decltype(
|
||||
boost::declval<F>()(
|
||||
boost::declval<Args>()...
|
||||
)
|
||||
) type;
|
||||
};
|
||||
|
||||
#else // BOOST_NO_SFINAE_EXPR
|
||||
|
||||
template<typename F, typename... Args>
|
||||
struct cpp0x_result_of_impl<F(Args...),
|
||||
typename result_of_always_void<decltype(
|
||||
boost::declval<F>()(
|
||||
boost::declval<Args>()...
|
||||
)
|
||||
)>::type> {
|
||||
typedef decltype(
|
||||
boost::declval<F>()(
|
||||
boost::declval<Args>()...
|
||||
)
|
||||
) type;
|
||||
};
|
||||
|
||||
#endif // BOOST_NO_SFINAE_EXPR
|
||||
|
||||
} // namespace detail
|
||||
|
||||
#else // defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)
|
||||
|
||||
template<typename F, typename... Args>
|
||||
struct result_of<F(Args...)>
|
||||
: tr1_result_of<F(Args...)> { };
|
||||
|
||||
#endif // defined(BOOST_RESULT_OF_USE_DECLTYPE)
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename R, typename FArgs, typename... Args>
|
||||
struct tr1_result_of_impl<R (*)(Args...), FArgs, false>
|
||||
{
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
template<typename R, typename FArgs, typename... Args>
|
||||
struct tr1_result_of_impl<R (&)(Args...), FArgs, false>
|
||||
{
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
template<typename R, typename FArgs, typename C, typename... Args>
|
||||
struct tr1_result_of_impl<R (C::*)(Args...), FArgs, false>
|
||||
{
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
template<typename R, typename FArgs, typename C, typename... Args>
|
||||
struct tr1_result_of_impl<R (C::*)(Args...) const, FArgs, false>
|
||||
{
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
template<typename R, typename FArgs, typename C, typename... Args>
|
||||
struct tr1_result_of_impl<R (C::*)(Args...) volatile, FArgs, false>
|
||||
{
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
template<typename R, typename FArgs, typename C, typename... Args>
|
||||
struct tr1_result_of_impl<R (C::*)(Args...) const volatile, FArgs, false>
|
||||
{
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright Andrey Semashev 2007 - 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)
|
||||
*/
|
||||
/*!
|
||||
* \file empty_deleter.hpp
|
||||
* \author Andrey Semashev
|
||||
* \date 22.04.2007
|
||||
*
|
||||
* This header contains an \c empty_deleter implementation. This is an empty
|
||||
* function object that receives a pointer and does nothing with it.
|
||||
* Such empty deletion strategy may be convenient, for example, when
|
||||
* constructing <tt>shared_ptr</tt>s that point to some object that should not be
|
||||
* deleted (i.e. a variable on the stack or some global singleton, like <tt>std::cout</tt>).
|
||||
*/
|
||||
|
||||
#ifndef BOOST_UTILITY_EMPTY_DELETER_HPP_INCLUDED_
|
||||
#define BOOST_UTILITY_EMPTY_DELETER_HPP_INCLUDED_
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
//! A function object that does nothing and can be used as an empty deleter for \c shared_ptr
|
||||
struct empty_deleter
|
||||
{
|
||||
//! Function object result type
|
||||
typedef void result_type;
|
||||
/*!
|
||||
* Does nothing
|
||||
*/
|
||||
void operator() (const volatile void*) const BOOST_NOEXCEPT {}
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_UTILITY_EMPTY_DELETER_HPP_INCLUDED_
|
@ -1,119 +0,0 @@
|
||||
// Boost enable_if library
|
||||
|
||||
// Copyright 2003 (c) 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: Jaakko Jarvi (jajarvi at osl.iu.edu)
|
||||
// Jeremiah Willcock (jewillco at osl.iu.edu)
|
||||
// Andrew Lumsdaine (lums at osl.iu.edu)
|
||||
|
||||
|
||||
#ifndef BOOST_UTILITY_ENABLE_IF_HPP
|
||||
#define BOOST_UTILITY_ENABLE_IF_HPP
|
||||
|
||||
#include "boost/config.hpp"
|
||||
|
||||
// Even the definition of enable_if causes problems on some compilers,
|
||||
// so it's macroed out for all compilers that do not support SFINAE
|
||||
|
||||
#ifndef BOOST_NO_SFINAE
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
template <bool B, class T = void>
|
||||
struct enable_if_c {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct enable_if_c<false, T> {};
|
||||
|
||||
template <class Cond, class T = void>
|
||||
struct enable_if : public enable_if_c<Cond::value, T> {};
|
||||
|
||||
template <bool B, class T>
|
||||
struct lazy_enable_if_c {
|
||||
typedef typename T::type type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct lazy_enable_if_c<false, T> {};
|
||||
|
||||
template <class Cond, class T>
|
||||
struct lazy_enable_if : public lazy_enable_if_c<Cond::value, T> {};
|
||||
|
||||
|
||||
template <bool B, class T = void>
|
||||
struct disable_if_c {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct disable_if_c<true, T> {};
|
||||
|
||||
template <class Cond, class T = void>
|
||||
struct disable_if : public disable_if_c<Cond::value, T> {};
|
||||
|
||||
template <bool B, class T>
|
||||
struct lazy_disable_if_c {
|
||||
typedef typename T::type type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct lazy_disable_if_c<true, T> {};
|
||||
|
||||
template <class Cond, class T>
|
||||
struct lazy_disable_if : public lazy_disable_if_c<Cond::value, T> {};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#else
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail { typedef void enable_if_default_T; }
|
||||
|
||||
template <typename T>
|
||||
struct enable_if_does_not_work_on_this_compiler;
|
||||
|
||||
template <bool B, class T = detail::enable_if_default_T>
|
||||
struct enable_if_c : enable_if_does_not_work_on_this_compiler<T>
|
||||
{ };
|
||||
|
||||
template <bool B, class T = detail::enable_if_default_T>
|
||||
struct disable_if_c : enable_if_does_not_work_on_this_compiler<T>
|
||||
{ };
|
||||
|
||||
template <bool B, class T = detail::enable_if_default_T>
|
||||
struct lazy_enable_if_c : enable_if_does_not_work_on_this_compiler<T>
|
||||
{ };
|
||||
|
||||
template <bool B, class T = detail::enable_if_default_T>
|
||||
struct lazy_disable_if_c : enable_if_does_not_work_on_this_compiler<T>
|
||||
{ };
|
||||
|
||||
template <class Cond, class T = detail::enable_if_default_T>
|
||||
struct enable_if : enable_if_does_not_work_on_this_compiler<T>
|
||||
{ };
|
||||
|
||||
template <class Cond, class T = detail::enable_if_default_T>
|
||||
struct disable_if : enable_if_does_not_work_on_this_compiler<T>
|
||||
{ };
|
||||
|
||||
template <class Cond, class T = detail::enable_if_default_T>
|
||||
struct lazy_enable_if : enable_if_does_not_work_on_this_compiler<T>
|
||||
{ };
|
||||
|
||||
template <class Cond, class T = detail::enable_if_default_T>
|
||||
struct lazy_disable_if : enable_if_does_not_work_on_this_compiler<T>
|
||||
{ };
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_NO_SFINAE
|
||||
|
||||
#endif
|
@ -1,128 +0,0 @@
|
||||
/*
|
||||
* Copyright Andrey Semashev 2007 - 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)
|
||||
*/
|
||||
/*!
|
||||
* \file explicit_operator_bool.hpp
|
||||
* \author Andrey Semashev
|
||||
* \date 08.03.2009
|
||||
*
|
||||
* This header defines a compatibility macro that implements an unspecified
|
||||
* \c bool operator idiom, which is superseded with explicit conversion operators in
|
||||
* C++11.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_UTILITY_EXPLICIT_OPERATOR_BOOL_HPP_INCLUDED_
|
||||
#define BOOST_UTILITY_EXPLICIT_OPERATOR_BOOL_HPP_INCLUDED_
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
|
||||
|
||||
/*!
|
||||
* \brief The macro defines an explicit operator of conversion to \c bool
|
||||
*
|
||||
* The macro should be used inside the definition of a class that has to
|
||||
* support the conversion. The class should also implement <tt>operator!</tt>,
|
||||
* in terms of which the conversion operator will be implemented.
|
||||
*/
|
||||
#define BOOST_EXPLICIT_OPERATOR_BOOL()\
|
||||
BOOST_FORCEINLINE explicit operator bool () const\
|
||||
{\
|
||||
return !this->operator! ();\
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief The macro defines a constexpr explicit operator of conversion to \c bool
|
||||
*
|
||||
* The macro should be used inside the definition of a class that has to
|
||||
* support the conversion. The class should also implement <tt>operator!</tt>,
|
||||
* in terms of which the conversion operator will be implemented.
|
||||
*/
|
||||
#define BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL()\
|
||||
BOOST_FORCEINLINE BOOST_CONSTEXPR explicit operator bool () const\
|
||||
{\
|
||||
return !this->operator! ();\
|
||||
}
|
||||
|
||||
#else // !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
|
||||
|
||||
#if (defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530)) && !defined(BOOST_NO_COMPILER_CONFIG)
|
||||
// Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it
|
||||
#define BOOST_NO_UNSPECIFIED_BOOL
|
||||
#endif // (defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530)) && !defined(BOOST_NO_COMPILER_CONFIG)
|
||||
|
||||
#if !defined(BOOST_NO_UNSPECIFIED_BOOL)
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
|
||||
#if !defined(_MSC_VER) && !defined(__IBMCPP__)
|
||||
|
||||
struct unspecified_bool
|
||||
{
|
||||
// NOTE TO THE USER: If you see this in error messages then you tried
|
||||
// to apply an unsupported operator on the object that supports
|
||||
// explicit conversion to bool.
|
||||
struct OPERATORS_NOT_ALLOWED;
|
||||
static void true_value(OPERATORS_NOT_ALLOWED*) {}
|
||||
};
|
||||
typedef void (*unspecified_bool_type)(unspecified_bool::OPERATORS_NOT_ALLOWED*);
|
||||
|
||||
#else
|
||||
|
||||
// MSVC and VACPP are too eager to convert pointer to function to void* even though they shouldn't
|
||||
struct unspecified_bool
|
||||
{
|
||||
// NOTE TO THE USER: If you see this in error messages then you tried
|
||||
// to apply an unsupported operator on the object that supports
|
||||
// explicit conversion to bool.
|
||||
struct OPERATORS_NOT_ALLOWED;
|
||||
void true_value(OPERATORS_NOT_ALLOWED*) {}
|
||||
};
|
||||
typedef void (unspecified_bool::*unspecified_bool_type)(unspecified_bool::OPERATORS_NOT_ALLOWED*);
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#define BOOST_EXPLICIT_OPERATOR_BOOL()\
|
||||
BOOST_FORCEINLINE operator boost::detail::unspecified_bool_type () const\
|
||||
{\
|
||||
return (!this->operator! () ? &boost::detail::unspecified_bool::true_value : (boost::detail::unspecified_bool_type)0);\
|
||||
}
|
||||
|
||||
#define BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL()\
|
||||
BOOST_FORCEINLINE BOOST_CONSTEXPR operator boost::detail::unspecified_bool_type () const\
|
||||
{\
|
||||
return (!this->operator! () ? &boost::detail::unspecified_bool::true_value : (boost::detail::unspecified_bool_type)0);\
|
||||
}
|
||||
|
||||
#else // !defined(BOOST_NO_UNSPECIFIED_BOOL)
|
||||
|
||||
#define BOOST_EXPLICIT_OPERATOR_BOOL()\
|
||||
BOOST_FORCEINLINE operator bool () const\
|
||||
{\
|
||||
return !this->operator! ();\
|
||||
}
|
||||
|
||||
#define BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL()\
|
||||
BOOST_FORCEINLINE BOOST_CONSTEXPR operator bool () const\
|
||||
{\
|
||||
return !this->operator! ();\
|
||||
}
|
||||
|
||||
#endif // !defined(BOOST_NO_UNSPECIFIED_BOOL)
|
||||
|
||||
#endif // !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
|
||||
|
||||
#endif // BOOST_UTILITY_EXPLICIT_OPERATOR_BOOL_HPP_INCLUDED_
|
@ -19,15 +19,21 @@ namespace boost {
|
||||
|
||||
class in_place_factory_base {} ;
|
||||
|
||||
#ifndef BOOST_UTILITY_DOCS
|
||||
#define BOOST_PP_ITERATION_LIMITS (0, BOOST_MAX_INPLACE_FACTORY_ARITY)
|
||||
#define BOOST_PP_FILENAME_1 <boost/utility/in_place_factory.hpp>
|
||||
#endif // BOOST_UTILITY_DOCS
|
||||
|
||||
#include BOOST_PP_ITERATE()
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/utility/detail/in_place_factory_suffix.hpp>
|
||||
|
||||
#ifndef BOOST_UTILITY_DOCS
|
||||
#define BOOST_UTILITY_INPLACE_FACTORY_04APR2007_HPP
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define N BOOST_PP_ITERATION()
|
||||
|
||||
@ -48,15 +54,13 @@ public:
|
||||
{}
|
||||
|
||||
template<class T>
|
||||
void* apply(void* address
|
||||
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) const
|
||||
void* apply(void* address) const
|
||||
{
|
||||
return new(address) T( BOOST_PP_ENUM_PARAMS(N, m_a) );
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void* apply(void* address, std::size_t n
|
||||
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) const
|
||||
void* apply(void* address, std::size_t n) const
|
||||
{
|
||||
for(char* next = address = this->BOOST_NESTED_TEMPLATE apply<T>(address);
|
||||
!! --n;)
|
||||
|
@ -10,31 +10,37 @@
|
||||
#define BOOST_RESULT_OF_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
#include <boost/preprocessor/iteration/iterate.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_shifted_params.hpp>
|
||||
#include <boost/preprocessor/facilities/intercept.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/mpl/has_xxx.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/eval_if.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
#include <boost/mpl/or.hpp>
|
||||
#include <boost/type_traits/is_class.hpp>
|
||||
#include <boost/type_traits/is_pointer.hpp>
|
||||
#include <boost/type_traits/is_member_function_pointer.hpp>
|
||||
#include <boost/type_traits/remove_cv.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/utility/declval.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits/declval.hpp>
|
||||
#include <boost/type_traits/conditional.hpp>
|
||||
#include <boost/type_traits/type_identity.hpp>
|
||||
#include <boost/type_traits/integral_constant.hpp>
|
||||
#include <boost/core/enable_if.hpp>
|
||||
|
||||
#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
|
||||
# undef BOOST_RESULT_OF_NO_VARIADIC_TEMPLATES
|
||||
# define BOOST_RESULT_OF_NO_VARIADIC_TEMPLATES
|
||||
#endif
|
||||
#ifdef BOOST_RESULT_OF_NO_VARIADIC_TEMPLATES
|
||||
# include <boost/preprocessor/cat.hpp>
|
||||
# include <boost/preprocessor/iteration/iterate.hpp>
|
||||
# include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
# include <boost/preprocessor/repetition/enum_trailing_params.hpp>
|
||||
# include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
# include <boost/preprocessor/repetition/enum_shifted_params.hpp>
|
||||
# include <boost/preprocessor/facilities/intercept.hpp>
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_UTILITY_DOCS
|
||||
#ifndef BOOST_RESULT_OF_NUM_ARGS
|
||||
# define BOOST_RESULT_OF_NUM_ARGS 16
|
||||
#endif
|
||||
#endif // BOOST_UTILITY_DOCS
|
||||
|
||||
// Use the decltype-based version of result_of by default if the compiler
|
||||
// supports N3276 <http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2011/n3276.pdf>.
|
||||
@ -47,10 +53,7 @@
|
||||
BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK cannot be defined at the same time.
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK) && defined(BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE)
|
||||
# error Cannot fallback to decltype if BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE is not defined.
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_UTILITY_DOCS
|
||||
#ifndef BOOST_RESULT_OF_USE_TR1
|
||||
# ifndef BOOST_RESULT_OF_USE_DECLTYPE
|
||||
# ifndef BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK
|
||||
@ -62,18 +65,51 @@
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
#endif // BOOST_UTILITY_DOCS
|
||||
|
||||
namespace boost {
|
||||
|
||||
template<typename F> struct result_of;
|
||||
template<typename F> struct tr1_result_of; // a TR1-style implementation of result_of
|
||||
|
||||
#if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||
#if !defined(BOOST_NO_SFINAE)
|
||||
namespace detail {
|
||||
|
||||
BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type)
|
||||
typedef char result_of_yes_type; // sizeof(result_of_yes_type) == 1
|
||||
typedef char (&result_of_no_type)[2]; // sizeof(result_of_no_type) == 2
|
||||
|
||||
BOOST_MPL_HAS_XXX_TEMPLATE_DEF(result)
|
||||
template<class T> struct result_of_has_type {};
|
||||
|
||||
template<class T> struct result_of_has_result_type_impl
|
||||
{
|
||||
template<class U> static result_of_yes_type f( result_of_has_type<typename U::result_type>* );
|
||||
template<class U> static result_of_no_type f( ... );
|
||||
|
||||
typedef boost::integral_constant<bool, sizeof(f<T>(0)) == sizeof(result_of_yes_type)> type;
|
||||
};
|
||||
|
||||
template<class T> struct result_of_has_result_type: result_of_has_result_type_impl<T>::type
|
||||
{
|
||||
};
|
||||
|
||||
// Work around a nvcc bug by only defining has_result when it's needed.
|
||||
#ifdef BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK
|
||||
|
||||
template<template<class> class C> struct result_of_has_template {};
|
||||
|
||||
template<class T> struct result_of_has_result_impl
|
||||
{
|
||||
template<class U> static result_of_yes_type f( result_of_has_template<U::template result>* );
|
||||
template<class U> static result_of_no_type f( ... );
|
||||
|
||||
typedef boost::integral_constant<bool, sizeof(f<T>(0)) == sizeof(result_of_yes_type)> type;
|
||||
};
|
||||
|
||||
template<class T> struct result_of_has_result: result_of_has_result_impl<T>::type
|
||||
{
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
template<typename F, typename FArgs, bool HasResultType> struct tr1_result_of_impl;
|
||||
|
||||
@ -83,8 +119,8 @@ template<typename F> struct cpp0x_result_of;
|
||||
|
||||
// There doesn't seem to be any other way to turn this off such that the presence of
|
||||
// the user-defined operator,() below doesn't cause spurious warning all over the place,
|
||||
// so unconditionally turn it off.
|
||||
#if BOOST_MSVC
|
||||
// so unconditionally and globally turn it off. (https://svn.boost.org/trac10/ticket/7663)
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(disable: 4913) // user defined binary operator ',' exists but no overload could convert all operands, default built-in binary operator ',' used
|
||||
#endif
|
||||
|
||||
@ -94,19 +130,23 @@ struct result_of_weird_type {
|
||||
friend result_of_private_type operator,(result_of_private_type, result_of_weird_type);
|
||||
};
|
||||
|
||||
typedef char result_of_yes_type; // sizeof(result_of_yes_type) == 1
|
||||
typedef char (&result_of_no_type)[2]; // sizeof(result_of_no_type) == 2
|
||||
|
||||
template<typename T>
|
||||
result_of_no_type result_of_is_private_type(T const &);
|
||||
result_of_yes_type result_of_is_private_type(result_of_private_type);
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4512) // assignment operator could not be generated.
|
||||
#endif
|
||||
template<typename C>
|
||||
struct result_of_callable_class : C {
|
||||
result_of_callable_class();
|
||||
typedef result_of_private_type const &(*pfn_t)(...);
|
||||
operator pfn_t() const volatile;
|
||||
};
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
template<typename C>
|
||||
struct result_of_wrap_callable_class {
|
||||
@ -177,10 +217,10 @@ struct tr1_result_of_impl<F, FArgs, true>
|
||||
};
|
||||
|
||||
template<typename FArgs>
|
||||
struct is_function_with_no_args : mpl::false_ {};
|
||||
struct is_function_with_no_args : false_type {};
|
||||
|
||||
template<typename F>
|
||||
struct is_function_with_no_args<F(void)> : mpl::true_ {};
|
||||
struct is_function_with_no_args<F(void)> : true_type {};
|
||||
|
||||
template<typename F, typename FArgs>
|
||||
struct result_of_nested_result : F::template result<FArgs>
|
||||
@ -188,15 +228,24 @@ struct result_of_nested_result : F::template result<FArgs>
|
||||
|
||||
template<typename F, typename FArgs>
|
||||
struct tr1_result_of_impl<F, FArgs, false>
|
||||
: mpl::if_<is_function_with_no_args<FArgs>,
|
||||
: conditional<is_function_with_no_args<FArgs>::value,
|
||||
result_of_void_impl<F>,
|
||||
result_of_nested_result<F, FArgs> >::type
|
||||
{};
|
||||
|
||||
} // end namespace detail
|
||||
|
||||
#define BOOST_PP_ITERATION_PARAMS_1 (3,(0,BOOST_RESULT_OF_NUM_ARGS,<boost/utility/detail/result_of_iterate.hpp>))
|
||||
#include BOOST_PP_ITERATE()
|
||||
#ifndef BOOST_RESULT_OF_NO_VARIADIC_TEMPLATES
|
||||
# include <boost/utility/detail/result_of_variadic.hpp>
|
||||
#else
|
||||
# define BOOST_PP_ITERATION_PARAMS_1 (3,(0,BOOST_RESULT_OF_NUM_ARGS,<boost/utility/detail/result_of_iterate.hpp>))
|
||||
# include BOOST_PP_ITERATE()
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
// inform dependency trackers, as they can't see through macro includes
|
||||
#include <boost/utility/detail/result_of_iterate.hpp>
|
||||
#endif
|
||||
|
||||
#else
|
||||
# define BOOST_NO_RESULT_OF 1
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2012-2012.
|
||||
Copyright (c) Marshall Clow 2012-2015.
|
||||
Copyright (c) Glen Joseph Fernandes 2019 (glenjofe@gmail.com)
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@ -17,6 +18,7 @@
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/io/ostream_put.hpp>
|
||||
#include <boost/utility/string_ref_fwd.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
@ -27,6 +29,11 @@
|
||||
#include <string>
|
||||
#include <iosfwd>
|
||||
|
||||
#if defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || (defined(BOOST_GCC) && ((BOOST_GCC+0) / 100) <= 406)
|
||||
// GCC 4.6 cannot handle a defaulted function with noexcept specifier
|
||||
#define BOOST_STRING_REF_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
@ -57,37 +64,55 @@ namespace boost {
|
||||
static BOOST_CONSTEXPR_OR_CONST size_type npos = size_type(-1);
|
||||
|
||||
// construct/copy
|
||||
BOOST_CONSTEXPR basic_string_ref ()
|
||||
BOOST_CONSTEXPR basic_string_ref () BOOST_NOEXCEPT
|
||||
: ptr_(NULL), len_(0) {}
|
||||
|
||||
BOOST_CONSTEXPR basic_string_ref (const basic_string_ref &rhs)
|
||||
// by defaulting these functions, basic_string_ref becomes
|
||||
// trivially copy/move constructible.
|
||||
BOOST_CONSTEXPR basic_string_ref (const basic_string_ref &rhs) BOOST_NOEXCEPT
|
||||
#ifndef BOOST_STRING_REF_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS
|
||||
= default;
|
||||
#else
|
||||
: ptr_(rhs.ptr_), len_(rhs.len_) {}
|
||||
#endif
|
||||
|
||||
basic_string_ref& operator=(const basic_string_ref &rhs) {
|
||||
basic_string_ref& operator=(const basic_string_ref &rhs) BOOST_NOEXCEPT
|
||||
#ifndef BOOST_STRING_REF_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS
|
||||
= default;
|
||||
#else
|
||||
{
|
||||
ptr_ = rhs.ptr_;
|
||||
len_ = rhs.len_;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
basic_string_ref(const charT* str)
|
||||
basic_string_ref(const charT* str) BOOST_NOEXCEPT
|
||||
: ptr_(str), len_(traits::length(str)) {}
|
||||
|
||||
template<typename Allocator>
|
||||
basic_string_ref(const std::basic_string<charT, traits, Allocator>& str)
|
||||
: ptr_(str.data()), len_(str.length()) {}
|
||||
|
||||
BOOST_CONSTEXPR basic_string_ref(const charT* str, size_type len)
|
||||
// #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
|
||||
// // Constructing a string_ref from a temporary string is a bad idea
|
||||
// template<typename Allocator>
|
||||
// basic_string_ref( std::basic_string<charT, traits, Allocator>&&)
|
||||
// = delete;
|
||||
// #endif
|
||||
|
||||
BOOST_CONSTEXPR basic_string_ref(const charT* str, size_type len) BOOST_NOEXCEPT
|
||||
: ptr_(str), len_(len) {}
|
||||
|
||||
#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
|
||||
template<typename Allocator>
|
||||
explicit operator std::basic_string<charT, traits, Allocator>() const {
|
||||
return std::basic_string<charT, traits, Allocator> ( ptr_, len_ );
|
||||
return std::basic_string<charT, traits, Allocator> ( begin(), end());
|
||||
}
|
||||
#endif
|
||||
|
||||
std::basic_string<charT, traits> to_string () const {
|
||||
return std::basic_string<charT, traits> ( ptr_, len_ );
|
||||
return std::basic_string<charT, traits> ( begin(), end());
|
||||
}
|
||||
|
||||
// iterators
|
||||
@ -103,13 +128,13 @@ namespace boost {
|
||||
// capacity
|
||||
BOOST_CONSTEXPR size_type size() const { return len_; }
|
||||
BOOST_CONSTEXPR size_type length() const { return len_; }
|
||||
BOOST_CONSTEXPR size_type max_size() const { return len_; }
|
||||
BOOST_CONSTEXPR size_type max_size() const { return ~static_cast<size_type>(0) / (sizeof(value_type) * 2u); }
|
||||
BOOST_CONSTEXPR bool empty() const { return len_ == 0; }
|
||||
|
||||
// element access
|
||||
BOOST_CONSTEXPR const charT& operator[](size_type pos) const { return ptr_[pos]; }
|
||||
|
||||
const charT& at(size_t pos) const {
|
||||
const charT& at(size_type pos) const {
|
||||
if ( pos >= len_ )
|
||||
BOOST_THROW_EXCEPTION( std::out_of_range ( "boost::string_ref::at" ) );
|
||||
return ptr_[pos];
|
||||
@ -136,12 +161,14 @@ namespace boost {
|
||||
|
||||
|
||||
// basic_string_ref string operations
|
||||
basic_string_ref substr() const {
|
||||
return basic_string_ref(data(), size());
|
||||
}
|
||||
|
||||
basic_string_ref substr(size_type pos, size_type n=npos) const {
|
||||
if ( pos > size())
|
||||
BOOST_THROW_EXCEPTION( std::out_of_range ( "string_ref::substr" ) );
|
||||
if ( n == npos || pos + n > size())
|
||||
n = size () - pos;
|
||||
return basic_string_ref ( data() + pos, n );
|
||||
return basic_string_ref(data() + pos, (std::min)(size() - pos, n));
|
||||
}
|
||||
|
||||
int compare(basic_string_ref x) const {
|
||||
@ -160,6 +187,7 @@ namespace boost {
|
||||
}
|
||||
|
||||
size_type find(basic_string_ref s) const {
|
||||
if (s.empty()) return 0;
|
||||
const_iterator iter = std::search ( this->cbegin (), this->cend (),
|
||||
s.cbegin (), s.cend (), traits::eq );
|
||||
return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
|
||||
@ -172,15 +200,16 @@ namespace boost {
|
||||
}
|
||||
|
||||
size_type rfind(basic_string_ref s) const {
|
||||
if (s.empty()) return 0;
|
||||
const_reverse_iterator iter = std::search ( this->crbegin (), this->crend (),
|
||||
s.crbegin (), s.crend (), traits::eq );
|
||||
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter );
|
||||
return iter == this->crend () ? npos : (std::distance(iter, this->crend()) - s.size());
|
||||
}
|
||||
|
||||
size_type rfind(charT c) const {
|
||||
const_reverse_iterator iter = std::find_if ( this->crbegin (), this->crend (),
|
||||
detail::string_ref_traits_eq<charT, traits> ( c ));
|
||||
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter );
|
||||
return iter == this->crend () ? npos : (this->size() - 1 - std::distance(this->crbegin(), iter));
|
||||
}
|
||||
|
||||
size_type find_first_of(charT c) const { return find (c); }
|
||||
@ -195,7 +224,7 @@ namespace boost {
|
||||
size_type find_last_of(basic_string_ref s) const {
|
||||
const_reverse_iterator iter = std::find_first_of
|
||||
( this->crbegin (), this->crend (), s.cbegin (), s.cend (), traits::eq );
|
||||
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter);
|
||||
return iter == this->crend () ? npos : (this->size() - 1 - std::distance(this->crbegin(), iter));
|
||||
}
|
||||
|
||||
size_type find_first_not_of(basic_string_ref s) const {
|
||||
@ -212,21 +241,17 @@ namespace boost {
|
||||
|
||||
size_type find_last_not_of(basic_string_ref s) const {
|
||||
const_reverse_iterator iter = find_not_of ( this->crbegin (), this->crend (), s );
|
||||
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter );
|
||||
return iter == this->crend () ? npos : (this->size() - 1 - std::distance(this->crbegin(), iter));
|
||||
}
|
||||
|
||||
size_type find_last_not_of(charT c) const {
|
||||
for ( const_reverse_iterator iter = this->crbegin (); iter != this->crend (); ++iter )
|
||||
if ( !traits::eq ( c, *iter ))
|
||||
return reverse_distance ( this->crbegin (), iter );
|
||||
return this->size() - 1 - std::distance(this->crbegin(), iter);
|
||||
return npos;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename r_iter>
|
||||
size_type reverse_distance ( r_iter first, r_iter last ) const {
|
||||
return len_ - 1 - std::distance ( first, last );
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
Iterator find_not_of ( Iterator first, Iterator last, basic_string_ref s ) const {
|
||||
@ -402,52 +427,11 @@ namespace boost {
|
||||
return basic_string_ref<charT, traits>(x) >= y;
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class charT, class traits>
|
||||
inline void insert_fill_chars(std::basic_ostream<charT, traits>& os, std::size_t n) {
|
||||
enum { chunk_size = 8 };
|
||||
charT fill_chars[chunk_size];
|
||||
std::fill_n(fill_chars, static_cast< std::size_t >(chunk_size), os.fill());
|
||||
for (; n >= chunk_size && os.good(); n -= chunk_size)
|
||||
os.write(fill_chars, static_cast< std::size_t >(chunk_size));
|
||||
if (n > 0 && os.good())
|
||||
os.write(fill_chars, n);
|
||||
}
|
||||
|
||||
template<class charT, class traits>
|
||||
void insert_aligned(std::basic_ostream<charT, traits>& os, const basic_string_ref<charT,traits>& str) {
|
||||
const std::size_t size = str.size();
|
||||
const std::size_t alignment_size = static_cast< std::size_t >(os.width()) - size;
|
||||
const bool align_left = (os.flags() & std::basic_ostream<charT, traits>::adjustfield) == std::basic_ostream<charT, traits>::left;
|
||||
if (!align_left) {
|
||||
detail::insert_fill_chars(os, alignment_size);
|
||||
if (os.good())
|
||||
os.write(str.data(), size);
|
||||
}
|
||||
else {
|
||||
os.write(str.data(), size);
|
||||
if (os.good())
|
||||
detail::insert_fill_chars(os, alignment_size);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// Inserter
|
||||
template<class charT, class traits>
|
||||
inline std::basic_ostream<charT, traits>&
|
||||
operator<<(std::basic_ostream<charT, traits>& os, const basic_string_ref<charT,traits>& str) {
|
||||
if (os.good()) {
|
||||
const std::size_t size = str.size();
|
||||
const std::size_t w = static_cast< std::size_t >(os.width());
|
||||
if (w <= size)
|
||||
os.write(str.data(), size);
|
||||
else
|
||||
detail::insert_aligned(os, str);
|
||||
os.width(0);
|
||||
}
|
||||
return os;
|
||||
return boost::io::ostream_put(os, str.data(), str.size());
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
689
include/boost/utility/string_view.hpp
Normal file
689
include/boost/utility/string_view.hpp
Normal file
@ -0,0 +1,689 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2012-2015.
|
||||
Copyright (c) Beman Dawes 2015
|
||||
Copyright (c) Glen Joseph Fernandes 2019 (glenjofe@gmail.com)
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
For more information, see http://www.boost.org
|
||||
|
||||
Based on the StringRef implementation in LLVM (http://llvm.org) and
|
||||
N3422 by Jeffrey Yasskin
|
||||
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html
|
||||
Updated July 2015 to reflect the Library Fundamentals TS
|
||||
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html
|
||||
*/
|
||||
|
||||
#ifndef BOOST_STRING_VIEW_HPP
|
||||
#define BOOST_STRING_VIEW_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/io/ostream_put.hpp>
|
||||
#include <boost/utility/string_view_fwd.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <iosfwd>
|
||||
|
||||
#if defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || (defined(BOOST_GCC) && ((BOOST_GCC+0) / 100) <= 406)
|
||||
// GCC 4.6 cannot handle a defaulted function with noexcept specifier
|
||||
#define BOOST_STRING_VIEW_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
// A helper functor because sometimes we don't have lambdas
|
||||
template <typename charT, typename traits>
|
||||
class string_view_traits_eq {
|
||||
public:
|
||||
string_view_traits_eq ( charT ch ) : ch_(ch) {}
|
||||
bool operator()( charT val ) const { return traits::eq (ch_, val); }
|
||||
charT ch_;
|
||||
};
|
||||
}
|
||||
|
||||
template<typename charT, typename traits> // traits defaulted in string_view_fwd.hpp
|
||||
class basic_string_view {
|
||||
public:
|
||||
// types
|
||||
typedef traits traits_type;
|
||||
typedef charT value_type;
|
||||
typedef charT* pointer;
|
||||
typedef const charT* const_pointer;
|
||||
typedef charT& reference;
|
||||
typedef const charT& const_reference;
|
||||
typedef const_pointer const_iterator; // impl-defined
|
||||
typedef const_iterator iterator;
|
||||
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
||||
typedef const_reverse_iterator reverse_iterator;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
static BOOST_CONSTEXPR_OR_CONST size_type npos = size_type(-1);
|
||||
|
||||
// construct/copy
|
||||
BOOST_CONSTEXPR basic_string_view() BOOST_NOEXCEPT
|
||||
: ptr_(NULL), len_(0) {}
|
||||
|
||||
// by defaulting these functions, basic_string_ref becomes
|
||||
// trivially copy/move constructible.
|
||||
BOOST_CONSTEXPR basic_string_view(const basic_string_view &rhs) BOOST_NOEXCEPT
|
||||
#ifndef BOOST_STRING_VIEW_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS
|
||||
= default;
|
||||
#else
|
||||
: ptr_(rhs.ptr_), len_(rhs.len_) {}
|
||||
#endif
|
||||
|
||||
basic_string_view& operator=(const basic_string_view &rhs) BOOST_NOEXCEPT
|
||||
#ifndef BOOST_STRING_VIEW_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS
|
||||
= default;
|
||||
#else
|
||||
{
|
||||
ptr_ = rhs.ptr_;
|
||||
len_ = rhs.len_;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename Allocator>
|
||||
basic_string_view(const std::basic_string<charT, traits, Allocator>& str) BOOST_NOEXCEPT
|
||||
: ptr_(str.data()), len_(str.length()) {}
|
||||
|
||||
// #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
|
||||
// // Constructing a string_view from a temporary string is a bad idea
|
||||
// template<typename Allocator>
|
||||
// basic_string_view( std::basic_string<charT, traits, Allocator>&&)
|
||||
// = delete;
|
||||
// #endif
|
||||
|
||||
BOOST_CONSTEXPR basic_string_view(const charT* str)
|
||||
: ptr_(str), len_(traits::length(str)) {}
|
||||
|
||||
BOOST_CONSTEXPR basic_string_view(const charT* str, size_type len)
|
||||
: ptr_(str), len_(len) {}
|
||||
|
||||
// iterators
|
||||
BOOST_CONSTEXPR const_iterator begin() const BOOST_NOEXCEPT { return ptr_; }
|
||||
BOOST_CONSTEXPR const_iterator cbegin() const BOOST_NOEXCEPT { return ptr_; }
|
||||
BOOST_CONSTEXPR const_iterator end() const BOOST_NOEXCEPT { return ptr_ + len_; }
|
||||
BOOST_CONSTEXPR const_iterator cend() const BOOST_NOEXCEPT { return ptr_ + len_; }
|
||||
const_reverse_iterator rbegin() const BOOST_NOEXCEPT { return const_reverse_iterator(end()); }
|
||||
const_reverse_iterator crbegin() const BOOST_NOEXCEPT { return const_reverse_iterator(end()); }
|
||||
const_reverse_iterator rend() const BOOST_NOEXCEPT { return const_reverse_iterator(begin()); }
|
||||
const_reverse_iterator crend() const BOOST_NOEXCEPT { return const_reverse_iterator(begin()); }
|
||||
|
||||
// capacity
|
||||
BOOST_CONSTEXPR size_type size() const BOOST_NOEXCEPT { return len_; }
|
||||
BOOST_CONSTEXPR size_type length() const BOOST_NOEXCEPT { return len_; }
|
||||
BOOST_CONSTEXPR size_type max_size() const BOOST_NOEXCEPT { return ~static_cast<size_type>(0) / (sizeof(value_type) * 2u); }
|
||||
BOOST_CONSTEXPR bool empty() const BOOST_NOEXCEPT { return len_ == 0; }
|
||||
|
||||
// element access
|
||||
BOOST_CONSTEXPR const_reference operator[](size_type pos) const BOOST_NOEXCEPT { return ptr_[pos]; }
|
||||
|
||||
BOOST_CONSTEXPR const_reference at(size_type pos) const {
|
||||
return pos >= len_ ? BOOST_THROW_EXCEPTION(std::out_of_range("boost::string_view::at")), ptr_[0] : ptr_[pos];
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR const_reference front() const { return ptr_[0]; }
|
||||
BOOST_CONSTEXPR const_reference back() const { return ptr_[len_-1]; }
|
||||
BOOST_CONSTEXPR const_pointer data() const BOOST_NOEXCEPT { return ptr_; }
|
||||
|
||||
// modifiers
|
||||
void clear() BOOST_NOEXCEPT { len_ = 0; } // Boost extension
|
||||
|
||||
BOOST_CXX14_CONSTEXPR void remove_prefix(size_type n) {
|
||||
if ( n > len_ )
|
||||
n = len_;
|
||||
ptr_ += n;
|
||||
len_ -= n;
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR void remove_suffix(size_type n) {
|
||||
if ( n > len_ )
|
||||
n = len_;
|
||||
len_ -= n;
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR void swap(basic_string_view& s) BOOST_NOEXCEPT {
|
||||
std::swap(ptr_, s.ptr_);
|
||||
std::swap(len_, s.len_);
|
||||
}
|
||||
|
||||
// basic_string_view string operations
|
||||
#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
|
||||
template<typename Allocator>
|
||||
explicit operator std::basic_string<charT, traits, Allocator>() const {
|
||||
return std::basic_string<charT, traits, Allocator>(begin(), end());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS
|
||||
template<typename Allocator = std::allocator<charT> >
|
||||
std::basic_string<charT, traits, Allocator> to_string(const Allocator& a = Allocator()) const {
|
||||
return std::basic_string<charT, traits, Allocator>(begin(), end(), a);
|
||||
}
|
||||
#else
|
||||
std::basic_string<charT, traits> to_string() const {
|
||||
return std::basic_string<charT, traits>(begin(), end());
|
||||
}
|
||||
|
||||
template<typename Allocator>
|
||||
std::basic_string<charT, traits, Allocator> to_string(const Allocator& a) const {
|
||||
return std::basic_string<charT, traits, Allocator>(begin(), end(), a);
|
||||
}
|
||||
#endif
|
||||
|
||||
size_type copy(charT* s, size_type n, size_type pos=0) const {
|
||||
if (pos > size())
|
||||
BOOST_THROW_EXCEPTION(std::out_of_range("string_view::copy" ));
|
||||
size_type rlen = (std::min)(n, len_ - pos);
|
||||
traits_type::copy(s, data() + pos, rlen);
|
||||
return rlen;
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR basic_string_view substr() const {
|
||||
return basic_string_view(data(), size());
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR basic_string_view substr(size_type pos, size_type n=npos) const {
|
||||
if ( pos > size())
|
||||
BOOST_THROW_EXCEPTION( std::out_of_range ( "string_view::substr" ) );
|
||||
return basic_string_view(data() + pos, (std::min)(size() - pos, n));
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR int compare(basic_string_view x) const BOOST_NOEXCEPT {
|
||||
const int cmp = traits::compare(ptr_, x.ptr_, (std::min)(len_, x.len_));
|
||||
return cmp != 0 ? cmp : (len_ == x.len_ ? 0 : len_ < x.len_ ? -1 : 1);
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR int compare(size_type pos1, size_type n1, basic_string_view x)
|
||||
const {
|
||||
return substr(pos1, n1).compare(x);
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR int compare(size_type pos1, size_type n1,
|
||||
basic_string_view x, size_type pos2, size_type n2) const {
|
||||
return substr(pos1, n1).compare(x.substr(pos2, n2));
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR int compare(const charT* x) const {
|
||||
return compare(basic_string_view(x));
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR int compare(size_type pos1, size_type n1, const charT* x) const {
|
||||
return substr(pos1, n1).compare(basic_string_view(x));
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR int compare(size_type pos1, size_type n1,
|
||||
const charT* x, size_type n2) const {
|
||||
return substr(pos1, n1).compare(basic_string_view(x, n2));
|
||||
}
|
||||
|
||||
// Searches
|
||||
BOOST_CONSTEXPR bool starts_with(charT c) const BOOST_NOEXCEPT { // Boost extension
|
||||
return !empty() && traits::eq(c, front());
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR bool starts_with(basic_string_view x) const BOOST_NOEXCEPT { // Boost extension
|
||||
return len_ >= x.len_ && traits::compare(ptr_, x.ptr_, x.len_) == 0;
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR bool ends_with(charT c) const BOOST_NOEXCEPT { // Boost extension
|
||||
return !empty() && traits::eq(c, back());
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR bool ends_with(basic_string_view x) const BOOST_NOEXCEPT { // Boost extension
|
||||
return len_ >= x.len_ &&
|
||||
traits::compare(ptr_ + len_ - x.len_, x.ptr_, x.len_) == 0;
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR bool contains(basic_string_view s) const BOOST_NOEXCEPT {
|
||||
return find(s) != npos;
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR bool contains(charT c) const BOOST_NOEXCEPT {
|
||||
return find(c) != npos;
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR bool contains(const charT* s) const BOOST_NOEXCEPT {
|
||||
return find(s) != npos;
|
||||
}
|
||||
|
||||
// find
|
||||
BOOST_CXX14_CONSTEXPR size_type find(basic_string_view s, size_type pos = 0) const BOOST_NOEXCEPT {
|
||||
if (pos > size())
|
||||
return npos;
|
||||
if (s.empty())
|
||||
return pos;
|
||||
if (s.size() > size() - pos)
|
||||
return npos;
|
||||
const charT* cur = ptr_ + pos;
|
||||
const charT* last = cend() - s.size() + 1;
|
||||
for (; cur != last ; ++cur) {
|
||||
cur = traits::find(cur, last - cur, s[0]);
|
||||
if (!cur)
|
||||
return npos;
|
||||
if (traits::compare(cur, s.cbegin(), s.size()) == 0)
|
||||
return cur - ptr_;
|
||||
}
|
||||
return npos;
|
||||
}
|
||||
BOOST_CXX14_CONSTEXPR size_type find(charT c, size_type pos = 0) const BOOST_NOEXCEPT {
|
||||
if (pos > size())
|
||||
return npos;
|
||||
const charT* ret_ptr = traits::find(ptr_ + pos, len_ - pos, c);
|
||||
if (ret_ptr)
|
||||
return ret_ptr - ptr_;
|
||||
return npos;
|
||||
}
|
||||
BOOST_CXX14_CONSTEXPR size_type find(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT
|
||||
{ return find(basic_string_view(s, n), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find(const charT* s, size_type pos = 0) const BOOST_NOEXCEPT
|
||||
{ return find(basic_string_view(s), pos); }
|
||||
|
||||
// rfind
|
||||
BOOST_CXX14_CONSTEXPR size_type rfind(basic_string_view s, size_type pos = npos) const BOOST_NOEXCEPT {
|
||||
if (len_ < s.len_)
|
||||
return npos;
|
||||
if (pos > len_ - s.len_)
|
||||
pos = len_ - s.len_;
|
||||
if (s.len_ == 0u) // an empty string is always found
|
||||
return pos;
|
||||
for (const charT* cur = ptr_ + pos; ; --cur) {
|
||||
if (traits::compare(cur, s.ptr_, s.len_) == 0)
|
||||
return cur - ptr_;
|
||||
if (cur == ptr_)
|
||||
return npos;
|
||||
};
|
||||
}
|
||||
BOOST_CXX14_CONSTEXPR size_type rfind(charT c, size_type pos = npos) const BOOST_NOEXCEPT
|
||||
{ return rfind(basic_string_view(&c, 1), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type rfind(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT
|
||||
{ return rfind(basic_string_view(s, n), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type rfind(const charT* s, size_type pos = npos) const BOOST_NOEXCEPT
|
||||
{ return rfind(basic_string_view(s), pos); }
|
||||
|
||||
// find_first_of
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_of(basic_string_view s, size_type pos = 0) const BOOST_NOEXCEPT {
|
||||
if (pos >= len_ || s.len_ == 0)
|
||||
return npos;
|
||||
const_iterator iter = std::find_first_of
|
||||
(this->cbegin () + pos, this->cend (), s.cbegin (), s.cend (), traits::eq);
|
||||
return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
|
||||
}
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_of(charT c, size_type pos = 0) const BOOST_NOEXCEPT
|
||||
{ return find(c, pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_of(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT
|
||||
{ return find_first_of(basic_string_view(s, n), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_of(const charT* s, size_type pos = 0) const BOOST_NOEXCEPT
|
||||
{ return find_first_of(basic_string_view(s), pos); }
|
||||
|
||||
// find_last_of
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_of(basic_string_view s, size_type pos = npos) const BOOST_NOEXCEPT {
|
||||
if (s.len_ == 0u)
|
||||
return npos;
|
||||
if (pos >= len_)
|
||||
pos = 0;
|
||||
else
|
||||
pos = len_ - (pos+1);
|
||||
const_reverse_iterator iter = std::find_first_of
|
||||
( this->crbegin () + pos, this->crend (), s.cbegin (), s.cend (), traits::eq );
|
||||
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter);
|
||||
}
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_of(charT c, size_type pos = npos) const BOOST_NOEXCEPT
|
||||
{ return find_last_of(basic_string_view(&c, 1), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_of(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT
|
||||
{ return find_last_of(basic_string_view(s, n), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_of(const charT* s, size_type pos = npos) const BOOST_NOEXCEPT
|
||||
{ return find_last_of(basic_string_view(s), pos); }
|
||||
|
||||
// find_first_not_of
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_not_of(basic_string_view s, size_type pos = 0) const BOOST_NOEXCEPT {
|
||||
if (pos >= len_)
|
||||
return npos;
|
||||
if (s.len_ == 0)
|
||||
return pos;
|
||||
const_iterator iter = find_not_of ( this->cbegin () + pos, this->cend (), s );
|
||||
return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
|
||||
}
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_not_of(charT c, size_type pos = 0) const BOOST_NOEXCEPT
|
||||
{ return find_first_not_of(basic_string_view(&c, 1), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_not_of(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT
|
||||
{ return find_first_not_of(basic_string_view(s, n), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_not_of(const charT* s, size_type pos = 0) const BOOST_NOEXCEPT
|
||||
{ return find_first_not_of(basic_string_view(s), pos); }
|
||||
|
||||
// find_last_not_of
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_not_of(basic_string_view s, size_type pos = npos) const BOOST_NOEXCEPT {
|
||||
if (pos >= len_)
|
||||
pos = len_ - 1;
|
||||
if (s.len_ == 0u)
|
||||
return pos;
|
||||
pos = len_ - (pos+1);
|
||||
const_reverse_iterator iter = find_not_of ( this->crbegin () + pos, this->crend (), s );
|
||||
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter );
|
||||
}
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_not_of(charT c, size_type pos = npos) const BOOST_NOEXCEPT
|
||||
{ return find_last_not_of(basic_string_view(&c, 1), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_not_of(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT
|
||||
{ return find_last_not_of(basic_string_view(s, n), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_not_of(const charT* s, size_type pos = npos) const BOOST_NOEXCEPT
|
||||
{ return find_last_not_of(basic_string_view(s), pos); }
|
||||
|
||||
private:
|
||||
template <typename r_iter>
|
||||
size_type reverse_distance(r_iter first, r_iter last) const BOOST_NOEXCEPT {
|
||||
// Portability note here: std::distance is not NOEXCEPT, but calling it with a string_view::reverse_iterator will not throw.
|
||||
return len_ - 1 - std::distance ( first, last );
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
Iterator find_not_of(Iterator first, Iterator last, basic_string_view s) const BOOST_NOEXCEPT {
|
||||
for (; first != last ; ++first)
|
||||
if ( 0 == traits::find(s.ptr_, s.len_, *first))
|
||||
return first;
|
||||
return last;
|
||||
}
|
||||
|
||||
const charT *ptr_;
|
||||
std::size_t len_;
|
||||
};
|
||||
|
||||
|
||||
// Comparison operators
|
||||
// Equality
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator==(basic_string_view<charT, traits> x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
if (x.size () != y.size ()) return false;
|
||||
return x.compare(y) == 0;
|
||||
}
|
||||
|
||||
// Inequality
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator!=(basic_string_view<charT, traits> x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
if ( x.size () != y.size ()) return true;
|
||||
return x.compare(y) != 0;
|
||||
}
|
||||
|
||||
// Less than
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator<(basic_string_view<charT, traits> x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return x.compare(y) < 0;
|
||||
}
|
||||
|
||||
// Greater than
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator>(basic_string_view<charT, traits> x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return x.compare(y) > 0;
|
||||
}
|
||||
|
||||
// Less than or equal to
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator<=(basic_string_view<charT, traits> x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return x.compare(y) <= 0;
|
||||
}
|
||||
|
||||
// Greater than or equal to
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator>=(basic_string_view<charT, traits> x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return x.compare(y) >= 0;
|
||||
}
|
||||
|
||||
// "sufficient additional overloads of comparison functions"
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator==(basic_string_view<charT, traits> x,
|
||||
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
|
||||
return x == basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator==(const std::basic_string<charT, traits, Allocator> & x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) == y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator==(basic_string_view<charT, traits> x,
|
||||
const charT * y) BOOST_NOEXCEPT {
|
||||
return x == basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator==(const charT * x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) == y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator!=(basic_string_view<charT, traits> x,
|
||||
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
|
||||
return x != basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator!=(const std::basic_string<charT, traits, Allocator> & x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) != y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator!=(basic_string_view<charT, traits> x,
|
||||
const charT * y) BOOST_NOEXCEPT {
|
||||
return x != basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator!=(const charT * x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) != y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator<(basic_string_view<charT, traits> x,
|
||||
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
|
||||
return x < basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator<(const std::basic_string<charT, traits, Allocator> & x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) < y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator<(basic_string_view<charT, traits> x,
|
||||
const charT * y) BOOST_NOEXCEPT {
|
||||
return x < basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator<(const charT * x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) < y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator>(basic_string_view<charT, traits> x,
|
||||
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
|
||||
return x > basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator>(const std::basic_string<charT, traits, Allocator> & x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) > y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator>(basic_string_view<charT, traits> x,
|
||||
const charT * y) BOOST_NOEXCEPT {
|
||||
return x > basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator>(const charT * x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) > y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator<=(basic_string_view<charT, traits> x,
|
||||
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
|
||||
return x <= basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator<=(const std::basic_string<charT, traits, Allocator> & x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) <= y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator<=(basic_string_view<charT, traits> x,
|
||||
const charT * y) BOOST_NOEXCEPT {
|
||||
return x <= basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator<=(const charT * x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) <= y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator>=(basic_string_view<charT, traits> x,
|
||||
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
|
||||
return x >= basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator>=(const std::basic_string<charT, traits, Allocator> & x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) >= y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator>=(basic_string_view<charT, traits> x,
|
||||
const charT * y) BOOST_NOEXCEPT {
|
||||
return x >= basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline BOOST_CXX14_CONSTEXPR bool operator>=(const charT * x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) >= y;
|
||||
}
|
||||
|
||||
// Inserter
|
||||
template<class charT, class traits>
|
||||
inline std::basic_ostream<charT, traits>&
|
||||
operator<<(std::basic_ostream<charT, traits>& os,
|
||||
const basic_string_view<charT,traits>& str) {
|
||||
return boost::io::ostream_put(os, str.data(), str.size());
|
||||
}
|
||||
|
||||
#if 0
|
||||
// numeric conversions
|
||||
//
|
||||
// These are short-term implementations.
|
||||
// In a production environment, I would rather avoid the copying.
|
||||
//
|
||||
inline int stoi (string_view str, size_t* idx=0, int base=10) {
|
||||
return std::stoi ( std::string(str), idx, base );
|
||||
}
|
||||
|
||||
inline long stol (string_view str, size_t* idx=0, int base=10) {
|
||||
return std::stol ( std::string(str), idx, base );
|
||||
}
|
||||
|
||||
inline unsigned long stoul (string_view str, size_t* idx=0, int base=10) {
|
||||
return std::stoul ( std::string(str), idx, base );
|
||||
}
|
||||
|
||||
inline long long stoll (string_view str, size_t* idx=0, int base=10) {
|
||||
return std::stoll ( std::string(str), idx, base );
|
||||
}
|
||||
|
||||
inline unsigned long long stoull (string_view str, size_t* idx=0, int base=10) {
|
||||
return std::stoull ( std::string(str), idx, base );
|
||||
}
|
||||
|
||||
inline float stof (string_view str, size_t* idx=0) {
|
||||
return std::stof ( std::string(str), idx );
|
||||
}
|
||||
|
||||
inline double stod (string_view str, size_t* idx=0) {
|
||||
return std::stod ( std::string(str), idx );
|
||||
}
|
||||
|
||||
inline long double stold (string_view str, size_t* idx=0) {
|
||||
return std::stold ( std::string(str), idx );
|
||||
}
|
||||
|
||||
inline int stoi (wstring_view str, size_t* idx=0, int base=10) {
|
||||
return std::stoi ( std::wstring(str), idx, base );
|
||||
}
|
||||
|
||||
inline long stol (wstring_view str, size_t* idx=0, int base=10) {
|
||||
return std::stol ( std::wstring(str), idx, base );
|
||||
}
|
||||
|
||||
inline unsigned long stoul (wstring_view str, size_t* idx=0, int base=10) {
|
||||
return std::stoul ( std::wstring(str), idx, base );
|
||||
}
|
||||
|
||||
inline long long stoll (wstring_view str, size_t* idx=0, int base=10) {
|
||||
return std::stoll ( std::wstring(str), idx, base );
|
||||
}
|
||||
|
||||
inline unsigned long long stoull (wstring_view str, size_t* idx=0, int base=10) {
|
||||
return std::stoull ( std::wstring(str), idx, base );
|
||||
}
|
||||
|
||||
inline float stof (wstring_view str, size_t* idx=0) {
|
||||
return std::stof ( std::wstring(str), idx );
|
||||
}
|
||||
|
||||
inline double stod (wstring_view str, size_t* idx=0) {
|
||||
return std::stod ( std::wstring(str), idx );
|
||||
}
|
||||
|
||||
inline long double stold (wstring_view str, size_t* idx=0) {
|
||||
return std::stold ( std::wstring(str), idx );
|
||||
}
|
||||
#endif
|
||||
|
||||
// Forward declaration of Boost.ContainerHash function
|
||||
template <class It> std::size_t hash_range(It, It);
|
||||
|
||||
template <class charT, class traits>
|
||||
std::size_t hash_value(basic_string_view<charT, traits> s) {
|
||||
return boost::hash_range(s.begin(), s.end());
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
namespace std {
|
||||
// Hashing
|
||||
template<> struct hash<boost::string_view>;
|
||||
template<> struct hash<boost::u16string_view>;
|
||||
template<> struct hash<boost::u32string_view>;
|
||||
template<> struct hash<boost::wstring_view>;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
39
include/boost/utility/string_view_fwd.hpp
Normal file
39
include/boost/utility/string_view_fwd.hpp
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2012-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)
|
||||
|
||||
For more information, see http://www.boost.org
|
||||
|
||||
Based on the StringRef implementation in LLVM (http://llvm.org) and
|
||||
N3422 by Jeffrey Yasskin
|
||||
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html
|
||||
Updated July 2015 to reflect the Library Fundamentals TS
|
||||
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html
|
||||
|
||||
*/
|
||||
|
||||
#ifndef BOOST_STRING_VIEW_FWD_HPP
|
||||
#define BOOST_STRING_VIEW_FWD_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template<typename charT, typename traits = std::char_traits<charT> > class basic_string_view;
|
||||
typedef basic_string_view<char, std::char_traits<char> > string_view;
|
||||
typedef basic_string_view<wchar_t, std::char_traits<wchar_t> > wstring_view;
|
||||
|
||||
#ifndef BOOST_NO_CXX11_CHAR16_T
|
||||
typedef basic_string_view<char16_t, std::char_traits<char16_t> > u16string_view;
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_CXX11_CHAR32_T
|
||||
typedef basic_string_view<char32_t, std::char_traits<char32_t> > u32string_view;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -1,55 +0,0 @@
|
||||
// Copyright (C) 2007, 2008 Steven Watanabe, Joseph Gauterin, Niels Dekker
|
||||
//
|
||||
// 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 http://www.boost.org
|
||||
|
||||
|
||||
#ifndef BOOST_UTILITY_SWAP_HPP
|
||||
#define BOOST_UTILITY_SWAP_HPP
|
||||
|
||||
// Note: the implementation of this utility contains various workarounds:
|
||||
// - swap_impl is put outside the boost namespace, to avoid infinite
|
||||
// recursion (causing stack overflow) when swapping objects of a primitive
|
||||
// type.
|
||||
// - swap_impl has a using-directive, rather than a using-declaration,
|
||||
// because some compilers (including MSVC 7.1, Borland 5.9.3, and
|
||||
// Intel 8.1) don't do argument-dependent lookup when it has a
|
||||
// using-declaration instead.
|
||||
// - boost::swap has two template arguments, instead of one, to
|
||||
// avoid ambiguity when swapping objects of a Boost type that does
|
||||
// not have its own boost::swap overload.
|
||||
|
||||
#include <algorithm> //for std::swap
|
||||
#include <cstddef> //for std::size_t
|
||||
|
||||
namespace boost_swap_impl
|
||||
{
|
||||
template<class T>
|
||||
void swap_impl(T& left, T& right)
|
||||
{
|
||||
using namespace std;//use std::swap if argument dependent lookup fails
|
||||
swap(left,right);
|
||||
}
|
||||
|
||||
template<class T, std::size_t N>
|
||||
void swap_impl(T (& left)[N], T (& right)[N])
|
||||
{
|
||||
for (std::size_t i = 0; i < N; ++i)
|
||||
{
|
||||
::boost_swap_impl::swap_impl(left[i], right[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template<class T1, class T2>
|
||||
void swap(T1& left, T2& right)
|
||||
{
|
||||
::boost_swap_impl::swap_impl(left, right);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -19,15 +19,20 @@ namespace boost {
|
||||
|
||||
class typed_in_place_factory_base {} ;
|
||||
|
||||
#ifndef BOOST_UTILITY_DOCS
|
||||
#define BOOST_PP_ITERATION_LIMITS (0, BOOST_MAX_INPLACE_FACTORY_ARITY)
|
||||
#define BOOST_PP_FILENAME_1 <boost/utility/typed_in_place_factory.hpp>
|
||||
#include BOOST_PP_ITERATE()
|
||||
#endif // BOOST_UTILITY_DOCS
|
||||
|
||||
#include BOOST_PP_ITERATE()
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/utility/detail/in_place_factory_suffix.hpp>
|
||||
|
||||
#ifndef BOOST_UTILITY_DOCS
|
||||
#define BOOST_UTILITY_TYPED_INPLACE_FACTORY_04APR2007_HPP
|
||||
#endif // BOOST_UTILITY_DOCS
|
||||
|
||||
#else
|
||||
#define N BOOST_PP_ITERATION()
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
// (C) Copyright 2002-2008, Fernando Luis Cacciola Carballal.
|
||||
// Copyright 2020 Peter Dimov
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -21,19 +22,13 @@
|
||||
// issues, by clearing the bytes of T, before constructing the T object it
|
||||
// contains. More details on these issues are at libs/utility/value_init.htm
|
||||
|
||||
#include <boost/aligned_storage.hpp>
|
||||
#include <boost/config.hpp> // For BOOST_NO_COMPLETE_VALUE_INITIALIZATION.
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_traits/cv_traits.hpp>
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
#include <boost/swap.hpp>
|
||||
#include <boost/core/swap.hpp>
|
||||
#include <cstring>
|
||||
#include <new>
|
||||
#include <cstddef>
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push)
|
||||
#if _MSC_VER >= 1310
|
||||
// It is safe to ignore the following warning from MSVC 7.1 or higher:
|
||||
// "warning C4351: new behavior: elements of array will be default initialized"
|
||||
#pragma warning(disable: 4351)
|
||||
@ -41,7 +36,8 @@
|
||||
// a const type: "warning C4512: assignment operator could not be generated".
|
||||
#pragma warning(disable: 4512)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_UTILITY_DOCS
|
||||
|
||||
#ifdef BOOST_NO_COMPLETE_VALUE_INITIALIZATION
|
||||
// Implementation detail: The macro BOOST_DETAIL_VALUE_INIT_WORKAROUND_SUGGESTED
|
||||
@ -60,116 +56,100 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // BOOST_UTILITY_DOCS
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
|
||||
struct zero_init
|
||||
{
|
||||
zero_init()
|
||||
{
|
||||
}
|
||||
|
||||
zero_init( void * p, std::size_t n )
|
||||
{
|
||||
std::memset( p, 0, n );
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<class T>
|
||||
class initialized
|
||||
#if BOOST_DETAIL_VALUE_INIT_WORKAROUND
|
||||
: detail::zero_init
|
||||
#endif
|
||||
{
|
||||
private :
|
||||
struct wrapper
|
||||
{
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592))
|
||||
typename
|
||||
#endif
|
||||
remove_const<T>::type data;
|
||||
private:
|
||||
|
||||
wrapper()
|
||||
:
|
||||
data()
|
||||
{
|
||||
}
|
||||
|
||||
wrapper(T const & arg)
|
||||
:
|
||||
data(arg)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
mutable
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592))
|
||||
typename
|
||||
#endif
|
||||
aligned_storage<sizeof(wrapper), alignment_of<wrapper>::value>::type x;
|
||||
|
||||
wrapper * wrapper_address() const
|
||||
{
|
||||
return static_cast<wrapper *>( static_cast<void*>(&x));
|
||||
}
|
||||
T data_;
|
||||
|
||||
public :
|
||||
|
||||
initialized()
|
||||
{
|
||||
BOOST_GPU_ENABLED
|
||||
initialized():
|
||||
#if BOOST_DETAIL_VALUE_INIT_WORKAROUND
|
||||
std::memset(&x, 0, sizeof(x));
|
||||
zero_init( &const_cast< char& >( reinterpret_cast<char const volatile&>( data_ ) ), sizeof( data_ ) ),
|
||||
#endif
|
||||
new (wrapper_address()) wrapper();
|
||||
}
|
||||
|
||||
initialized(initialized const & arg)
|
||||
data_()
|
||||
{
|
||||
new (wrapper_address()) wrapper( static_cast<wrapper const &>(*(arg.wrapper_address())));
|
||||
}
|
||||
|
||||
explicit initialized(T const & arg)
|
||||
BOOST_GPU_ENABLED
|
||||
explicit initialized(T const & arg): data_( arg )
|
||||
{
|
||||
new (wrapper_address()) wrapper(arg);
|
||||
}
|
||||
|
||||
initialized & operator=(initialized const & arg)
|
||||
{
|
||||
// Assignment is only allowed when T is non-const.
|
||||
BOOST_STATIC_ASSERT( ! is_const<T>::value );
|
||||
*wrapper_address() = static_cast<wrapper const &>(*(arg.wrapper_address()));
|
||||
return *this;
|
||||
}
|
||||
|
||||
~initialized()
|
||||
{
|
||||
wrapper_address()->wrapper::~wrapper();
|
||||
}
|
||||
|
||||
BOOST_GPU_ENABLED
|
||||
T const & data() const
|
||||
{
|
||||
return wrapper_address()->data;
|
||||
return data_;
|
||||
}
|
||||
|
||||
BOOST_GPU_ENABLED
|
||||
T& data()
|
||||
{
|
||||
return wrapper_address()->data;
|
||||
return data_;
|
||||
}
|
||||
|
||||
BOOST_GPU_ENABLED
|
||||
void swap(initialized & arg)
|
||||
{
|
||||
::boost::swap( this->data(), arg.data() );
|
||||
}
|
||||
|
||||
BOOST_GPU_ENABLED
|
||||
operator T const &() const
|
||||
{
|
||||
return wrapper_address()->data;
|
||||
return data_;
|
||||
}
|
||||
|
||||
BOOST_GPU_ENABLED
|
||||
operator T&()
|
||||
{
|
||||
return wrapper_address()->data;
|
||||
return data_;
|
||||
}
|
||||
|
||||
} ;
|
||||
|
||||
template<class T>
|
||||
BOOST_GPU_ENABLED
|
||||
T const& get ( initialized<T> const& x )
|
||||
{
|
||||
return x.data() ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
BOOST_GPU_ENABLED
|
||||
T& get ( initialized<T>& x )
|
||||
{
|
||||
return x.data() ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
BOOST_GPU_ENABLED
|
||||
void swap ( initialized<T> & lhs, initialized<T> & rhs )
|
||||
{
|
||||
lhs.swap(rhs) ;
|
||||
@ -185,31 +165,37 @@ class value_initialized
|
||||
|
||||
public :
|
||||
|
||||
BOOST_GPU_ENABLED
|
||||
value_initialized()
|
||||
:
|
||||
m_data()
|
||||
{ }
|
||||
|
||||
BOOST_GPU_ENABLED
|
||||
T const & data() const
|
||||
{
|
||||
return m_data.data();
|
||||
}
|
||||
|
||||
BOOST_GPU_ENABLED
|
||||
T& data()
|
||||
{
|
||||
return m_data.data();
|
||||
}
|
||||
|
||||
BOOST_GPU_ENABLED
|
||||
void swap(value_initialized & arg)
|
||||
{
|
||||
m_data.swap(arg.m_data);
|
||||
}
|
||||
|
||||
BOOST_GPU_ENABLED
|
||||
operator T const &() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
BOOST_GPU_ENABLED
|
||||
operator T&()
|
||||
{
|
||||
return m_data;
|
||||
@ -218,18 +204,21 @@ class value_initialized
|
||||
|
||||
|
||||
template<class T>
|
||||
BOOST_GPU_ENABLED
|
||||
T const& get ( value_initialized<T> const& x )
|
||||
{
|
||||
return x.data() ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
BOOST_GPU_ENABLED
|
||||
T& get ( value_initialized<T>& x )
|
||||
{
|
||||
return x.data() ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
BOOST_GPU_ENABLED
|
||||
void swap ( value_initialized<T> & lhs, value_initialized<T> & rhs )
|
||||
{
|
||||
lhs.swap(rhs) ;
|
||||
@ -240,7 +229,7 @@ class initialized_value_t
|
||||
{
|
||||
public :
|
||||
|
||||
template <class T> operator T() const
|
||||
template <class T> BOOST_GPU_ENABLED operator T() const
|
||||
{
|
||||
return initialized<T>().data();
|
||||
}
|
||||
|
67
index.html
67
index.html
@ -1,52 +1,19 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Language" content="en-us">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<title>Boost Utility Library</title>
|
||||
</head>
|
||||
<body bgcolor="#FFFFFF">
|
||||
<h1><IMG SRC="../../boost.png" WIDTH="276" HEIGHT="86" align="center">Boost
|
||||
Utility Library</h1>
|
||||
<p>The Boost Utility Library isn't really a single library at all. It is just a
|
||||
collection for components too small to be called libraries in their own right.</p>
|
||||
<p>But that doesn't mean there isn't useful stuff here. Take a look:</p>
|
||||
<blockquote>
|
||||
<p>
|
||||
<a href="utility.htm#addressof">addressof</a><br>
|
||||
<a href="assert.html">assert</a><br>
|
||||
<a href="base_from_member.html">base_from_member</a><br>
|
||||
<a href="utility.htm#BOOST_BINARY">BOOST_BINARY</a><br>
|
||||
<a href="call_traits.htm">call_traits</a><br>
|
||||
<a href="checked_delete.html">checked_delete</a><br>
|
||||
<a href="compressed_pair.htm">compressed_pair</a><br>
|
||||
<a href="current_function.html">current_function</a><br>
|
||||
<a href="doc/html/declval.html">declval</a><br>
|
||||
<a href="enable_if.html">enable_if</a><br>
|
||||
<a href="in_place_factories.html">in_place_factory</a><br>
|
||||
<a href="iterator_adaptors.htm">iterator_adaptors</a><br>
|
||||
<a href="generator_iterator.htm">generator iterator adaptors</a><br>
|
||||
<a href="utility.htm#functions_next_prior">next/prior</a><br>
|
||||
<a href="utility.htm#Class_noncopyable">noncopyable</a><br>
|
||||
<a href="operators.htm">operators</a><br>
|
||||
<a href="utility.htm#result_of">result_of</a><br>
|
||||
<a href="swap.html">swap</a><br>
|
||||
<a href="throw_exception.html">throw_exception</a><br>
|
||||
<a href="utility.htm">utility</a><br>
|
||||
<a href="doc/html/string_ref.html">string_ref</a><br>
|
||||
<a href="value_init.htm">value_init</a>
|
||||
<a href="doc/html/explicit_operator_bool.html">BOOST_EXPLICIT_OPERATOR_BOOL and BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL</a><br>
|
||||
</p>
|
||||
</blockquote>
|
||||
<hr>
|
||||
<p>© Copyright Beman Dawes, 2001</p>
|
||||
<p>Distributed under the Boost Software License, Version 1.0. (See
|
||||
accompanying file <a href="../../LICENSE_1_0.txt">
|
||||
LICENSE_1_0.txt</a> or copy at
|
||||
<a href="http://www.boost.org/LICENSE_1_0.txt">
|
||||
www.boost.org/LICENSE_1_0.txt</a>)</p>
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->07 November, 2006<!--webbot bot="Timestamp" endspan i-checksum="39368" --></p>
|
||||
</body>
|
||||
<head>
|
||||
<title>Boost.Utility</title>
|
||||
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="./doc/html/index.html">./doc/html/index.html</a>
|
||||
<hr>
|
||||
<tt>
|
||||
Boost.Utility<br>
|
||||
<br>
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||
<br>
|
||||
</tt>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,11 +1,19 @@
|
||||
<!-- Copyright David Abrahams 2004. 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) -->
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="0; URL=../iterator/doc/index.html">
|
||||
<title>Boost.Utility</title>
|
||||
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||
</head>
|
||||
<body>
|
||||
This documentation moved to <a href="../iterator/doc/index.html">../iterator/doc/index.html</a>.
|
||||
Automatic redirection failed, please go to
|
||||
<a href="../iterator/doc/generator_iterator.htm">../iterator/doc/generator_iterator.htm</a>
|
||||
<hr>
|
||||
<tt>
|
||||
Boost.Utility<br>
|
||||
<br>
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||
<br>
|
||||
</tt>
|
||||
</body>
|
||||
</html>
|
||||
|
135
meta/libraries.json
Normal file
135
meta/libraries.json
Normal file
@ -0,0 +1,135 @@
|
||||
[
|
||||
{
|
||||
"key": "utility",
|
||||
"name": "Utility",
|
||||
"authors": [
|
||||
"Dave Abrahams and others"
|
||||
],
|
||||
"description": "Class noncopyable plus checked_delete(), checked_array_delete(), next(), prior() function templates, plus base-from-member idiom.",
|
||||
"documentation": "utility.htm",
|
||||
"category": [
|
||||
"Algorithms",
|
||||
"Function-objects",
|
||||
"Memory",
|
||||
"Miscellaneous",
|
||||
"Patterns"
|
||||
],
|
||||
"cxxstd": "03"
|
||||
},
|
||||
{
|
||||
"key": "utility/call_traits",
|
||||
"name": "Call Traits",
|
||||
"authors": [
|
||||
"John Maddock, Howard Hinnant, et al"
|
||||
],
|
||||
"description": "Defines types for passing parameters.",
|
||||
"documentation": "call_traits.htm",
|
||||
"category": [
|
||||
"Generic"
|
||||
],
|
||||
"cxxstd": "03"
|
||||
},
|
||||
{
|
||||
"key": "utility/compressed_pair",
|
||||
"name": "Compressed Pair",
|
||||
"authors": [
|
||||
"John Maddock, Howard Hinnant, et al"
|
||||
],
|
||||
"description": "Empty member optimization.",
|
||||
"documentation": "compressed_pair.htm",
|
||||
"category": [
|
||||
"Data",
|
||||
"Patterns"
|
||||
],
|
||||
"cxxstd": "03"
|
||||
},
|
||||
{
|
||||
"key": "utility/identity_type",
|
||||
"name": "Identity Type",
|
||||
"authors": [
|
||||
"Lorenzo Caminiti"
|
||||
],
|
||||
"description": "Wrap types within round parenthesis so they can always be passed as macro parameters.",
|
||||
"documentation": "identity_type/",
|
||||
"category": [
|
||||
"Preprocessor"
|
||||
],
|
||||
"maintainers": [
|
||||
"Lorenzo Caminiti <lorcaminiti -at- gmail.com>"
|
||||
],
|
||||
"cxxstd": "03"
|
||||
},
|
||||
{
|
||||
"key": "utility/in_place_factories",
|
||||
"name": "In Place Factory, Typed In Place Factory",
|
||||
"authors": [
|
||||
"Fernando Cacciola"
|
||||
],
|
||||
"description": "Generic in-place construction of contained objects with a variadic argument-list.",
|
||||
"documentation": "in_place_factories.html",
|
||||
"category": [
|
||||
"Generic"
|
||||
],
|
||||
"cxxstd": "03"
|
||||
},
|
||||
{
|
||||
"key": "utility/operators",
|
||||
"name": "Operators",
|
||||
"authors": [
|
||||
"Dave Abrahams",
|
||||
"Jeremy Siek"
|
||||
],
|
||||
"description": "Templates ease arithmetic classes and iterators.",
|
||||
"documentation": "operators.htm",
|
||||
"category": [
|
||||
"Generic",
|
||||
"Iterators",
|
||||
"Math"
|
||||
],
|
||||
"maintainers": [
|
||||
"Daniel Frey <d.frey -at- gmx.de>"
|
||||
],
|
||||
"cxxstd": "03"
|
||||
},
|
||||
{
|
||||
"key": "utility/result_of",
|
||||
"name": "Result Of",
|
||||
"description": "Determines the type of a function call expression.",
|
||||
"documentation": "utility.htm#result_of",
|
||||
"category": [
|
||||
"Function-objects"
|
||||
],
|
||||
"authors": "",
|
||||
"maintainers": [
|
||||
"Daniel Walker <daniel.j.walker -at- gmail.com>"
|
||||
],
|
||||
"cxxstd": "03"
|
||||
},
|
||||
{
|
||||
"key": "utility/string_ref",
|
||||
"name": "String Ref",
|
||||
"description": "String view templates.",
|
||||
"documentation": "doc/html/string_ref.html",
|
||||
"category": [
|
||||
"Containers"
|
||||
],
|
||||
"authors": "Marshall Clow",
|
||||
"maintainers": [
|
||||
"Marshall Clow <marshall -at- idio.com>"
|
||||
],
|
||||
"cxxstd": "03"
|
||||
},
|
||||
{
|
||||
"key": "utility/value_initialized",
|
||||
"name": "Value Initialized",
|
||||
"authors": [
|
||||
"Fernando Cacciola"
|
||||
],
|
||||
"description": "Wrapper for uniform-syntax value initialization, based on the original idea of David Abrahams.",
|
||||
"documentation": "value_init.htm",
|
||||
"category": [
|
||||
"Miscellaneous"
|
||||
],
|
||||
"cxxstd": "03"
|
||||
}
|
||||
]
|
@ -1,36 +0,0 @@
|
||||
// boost class noncopyable test program ------------------------------------//
|
||||
|
||||
// (C) Copyright Beman Dawes 1999. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
// Revision History
|
||||
// 9 Jun 99 Add unnamed namespace
|
||||
// 2 Jun 99 Initial Version
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <iostream>
|
||||
|
||||
// This program demonstrates compiler errors resulting from trying to copy
|
||||
// construct or copy assign a class object derived from class noncopyable.
|
||||
|
||||
namespace
|
||||
{
|
||||
class DontTreadOnMe : private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
DontTreadOnMe() { std::cout << "defanged!" << std::endl; }
|
||||
}; // DontTreadOnMe
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
int main()
|
||||
{
|
||||
DontTreadOnMe object1;
|
||||
DontTreadOnMe object2(object1);
|
||||
object1 = object2;
|
||||
return 0;
|
||||
} // main
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user