forked from boostorg/concept_check
Compare commits
194 Commits
boost-1.30
...
esp-idf-co
Author | SHA1 | Date | |
---|---|---|---|
e8c2d8a124 | |||
5656ffe0ac | |||
3b2dbfea08 | |||
772c1b40c8 | |||
9c89e99629 | |||
e34c735a1a | |||
85fd1e434f | |||
99901a98fd | |||
c5ecc3bb3a | |||
affc79e045 | |||
feb8accc6e | |||
a8cf003d4a | |||
e69c81326d | |||
db1f9c73a4 | |||
b9c73e191b | |||
bc2482b38f | |||
7dbaa85413 | |||
eeeb60b797 | |||
c2723f984c | |||
0d65b45953 | |||
0381c5fc54 | |||
64e72828d7 | |||
bd8faa928d | |||
8847e4b104 | |||
ee943d0f7c | |||
bbf48ff290 | |||
7226a74471 | |||
5e14874d04 | |||
376201b10d | |||
ed0a0ebd72 | |||
db9894fa8b | |||
8deb5d203c | |||
00496f2010 | |||
df4ced9aae | |||
3df02ba00e | |||
06b61f5407 | |||
3397b4df48 | |||
b65104932a | |||
463edb00e4 | |||
28b219981e | |||
c7d61df2af | |||
ec560ba5b0 | |||
6284402a2d | |||
504ea0b18d | |||
a2e63dad4c | |||
671bbfdb0f | |||
80cfac7881 | |||
acc3cd0ea2 | |||
bdcd06c4cc | |||
89eb7b4cdc | |||
bb9257a37e | |||
92a156c79d | |||
0d5bfc869c | |||
b708baa8ed | |||
50574588ae | |||
d6a527bb21 | |||
f2c369a6c3 | |||
e7ca7744c4 | |||
6784696095 | |||
cde699f812 | |||
90b0397f54 | |||
d2d56f6de8 | |||
389bf0d089 | |||
ccd9f52467 | |||
229e3055a0 | |||
36701c51ab | |||
dd7163b7f0 | |||
724b43f885 | |||
168e60aa3d | |||
9521991561 | |||
590fed825c | |||
38154ae6cf | |||
da5ab9b807 | |||
60b5eb331c | |||
52adefee9a | |||
d78b6bae1c | |||
a16e4a65da | |||
d66a39d4fc | |||
7dec68923d | |||
15afb20c84 | |||
b4ff615db8 | |||
807fcd7b97 | |||
45d722b5c3 | |||
f81493caa1 | |||
a1772df31b | |||
d4658af6d7 | |||
570d5a6f92 | |||
7e0926d77f | |||
def441d02d | |||
3f1842a89e | |||
0eac9e329b | |||
1f226e2dc9 | |||
e8bd11887b | |||
c12ec71acb | |||
08250885bf | |||
199cb1692b | |||
2d21b2041f | |||
d9282dbe8c | |||
9ceeae9e9f | |||
533211c4ad | |||
e234ae22f6 | |||
deea7c6a58 | |||
8842c10761 | |||
2c2d720874 | |||
dc164705ad | |||
a37267f181 | |||
2fbf9d1375 | |||
3dcaf09ecf | |||
30dc63f52f | |||
80de3d1903 | |||
eb4c1f2587 | |||
63c674c575 | |||
5c06a2ea0b | |||
b3fc10803f | |||
cc5dcdfb33 | |||
b15e7d804b | |||
e7fbe05ee2 | |||
29f82069d9 | |||
a61d139751 | |||
2364f0f02a | |||
624e9d53c2 | |||
997b34b581 | |||
92ae569516 | |||
d9ae976994 | |||
7dd50ca8f2 | |||
96d6053a52 | |||
6ed3c013bb | |||
2134db9324 | |||
9ef681483e | |||
6f04bb5004 | |||
fe5e093f53 | |||
d0c4fe7914 | |||
bee3ccbb6c | |||
cf9b413943 | |||
c1709f6794 | |||
a88c1d6a69 | |||
ac6415fac2 | |||
949c2b1b28 | |||
6b4d01994b | |||
b11b270a56 | |||
178e7549ce | |||
fb99b2546a | |||
b087894c08 | |||
14450b3d5d | |||
4e524d6c6a | |||
ba2a75c1f9 | |||
79017f985a | |||
f00741c14f | |||
8c32f7a5e2 | |||
bfb6428417 | |||
80cbd76189 | |||
3bce136d94 | |||
3c2a976d2a | |||
24326c9df5 | |||
d4ecb93adb | |||
3e56a7c4ec | |||
940df353e8 | |||
8414234a2a | |||
4a7d05206e | |||
842160c38c | |||
d51a7bf94a | |||
6f59ef904b | |||
3cd0be21a7 | |||
e63353698b | |||
ce3fb4f640 | |||
166e3207b7 | |||
87f5b1ab63 | |||
9ef32e2e8d | |||
1ff77e789e | |||
bc8f520895 | |||
daad09ad49 | |||
ad5f1d47d8 | |||
1731989798 | |||
a29797eadc | |||
9678d4a3f2 | |||
1b8f363e90 | |||
061ed8019a | |||
cc25398b06 | |||
6547eb9803 | |||
8a403e7859 | |||
ab0a5086b5 | |||
308df430d2 | |||
7f5d7a5c54 | |||
b4d624d61f | |||
a50c9fca5c | |||
669e6938cc | |||
5741cdc2dc | |||
0ecc9d31b5 | |||
60e6cc268c | |||
47ae00bff5 | |||
f2abb5931b | |||
358b14915b | |||
ce92fda5ba | |||
538b271d24 |
125
.appveyor.yml
Normal file
125
.appveyor.yml
Normal file
@ -0,0 +1,125 @@
|
||||
# Copyright 2016, 2017 Peter Dimov
|
||||
# Copyright 2017 - 2019 James E. King III
|
||||
# Copyright 2019 - 2021 Alexander Grund
|
||||
# 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)
|
||||
|
||||
#
|
||||
# Generic Appveyor build script for boostorg repositories
|
||||
# See: https://github.com/boostorg/boost-ci/
|
||||
#
|
||||
# Instructions for customizing this script for your library:
|
||||
#
|
||||
# 1. Customize the compilers and language levels you want.
|
||||
# 2. If you have more than include/, src/, test/, example/, examples/,
|
||||
# benchmark/ or tools/ directories, set the environment variable DEPINST.
|
||||
# For example if your build uses code in "bench/" and "fog/" directories:
|
||||
# - DEPINST: --include bench --include fog
|
||||
# 3. Enable pull request builds in your boostorg/<library> account.
|
||||
#
|
||||
# That's it - the script will do everything else for you.
|
||||
#
|
||||
|
||||
version: 1.0.{build}-{branch}
|
||||
|
||||
shallow_clone: true
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- develop
|
||||
- /bugfix\/.*/
|
||||
- /feature\/.*/
|
||||
- /fix\/.*/
|
||||
- /pr\/.*/
|
||||
|
||||
matrix:
|
||||
fast_finish: false
|
||||
# Adding MAYFAIL to any matrix job allows it to fail but the build stays green:
|
||||
allow_failures:
|
||||
- MAYFAIL: true
|
||||
|
||||
environment:
|
||||
global:
|
||||
B2_CI_VERSION: 1
|
||||
GIT_FETCH_JOBS: 4
|
||||
# see: http://www.boost.org/build/doc/html/bbv2/overview/invocation.html#bbv2.overview.invocation.properties
|
||||
# to use the default for a given environment, comment it out; recommend you build debug and release however:
|
||||
# on Windows it is important to exercise all the possibilities, especially shared vs static, however most
|
||||
# libraries that care about this exercise it in their Jamfiles...
|
||||
B2_ADDRESS_MODEL: 32,64
|
||||
B2_LINK: shared,static
|
||||
# B2_THREADING: threading=multi,single
|
||||
B2_VARIANT: release
|
||||
|
||||
matrix:
|
||||
- FLAVOR: Visual Studio 2017 C++2a Strict
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
B2_CXXFLAGS: -permissive-
|
||||
B2_CXXSTD: 2a
|
||||
B2_TOOLSET: msvc-14.1
|
||||
|
||||
- FLAVOR: Visual Studio 2017 C++14/17
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
B2_CXXSTD: 14,17
|
||||
B2_TOOLSET: msvc-14.1
|
||||
|
||||
- FLAVOR: clang-cl
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
B2_ADDRESS_MODEL: 64
|
||||
B2_CXXSTD: 11,14,17
|
||||
B2_TOOLSET: clang-win
|
||||
|
||||
- FLAVOR: Visual Studio 2015, 2013
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
B2_TOOLSET: msvc-12.0,msvc-14.0
|
||||
|
||||
- FLAVOR: Visual Studio 2008, 2010, 2012
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
B2_TOOLSET: msvc-9.0,msvc-10.0,msvc-11.0
|
||||
B2_ADDRESS_MODEL: 32 # No 64bit support
|
||||
|
||||
- FLAVOR: cygwin (32-bit)
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
ADDPATH: C:\cygwin\bin;
|
||||
B2_ADDRESS_MODEL: 32
|
||||
B2_CXXSTD: 03,11,14,1z
|
||||
B2_TOOLSET: gcc
|
||||
|
||||
- FLAVOR: cygwin (64-bit)
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
ADDPATH: C:\cygwin64\bin;
|
||||
B2_ADDRESS_MODEL: 64
|
||||
B2_CXXSTD: 03,11,14,1z
|
||||
B2_TOOLSET: gcc
|
||||
|
||||
- FLAVOR: mingw32
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
B2_ADDRESS_MODEL: 32
|
||||
ADDPATH: C:\mingw\bin;
|
||||
B2_CXXSTD: 03,11,14,1z
|
||||
B2_TOOLSET: gcc
|
||||
|
||||
- FLAVOR: mingw64
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
ADDPATH: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin;
|
||||
B2_ADDRESS_MODEL: 64
|
||||
B2_CXXSTD: 03,11,14,17,2a
|
||||
B2_TOOLSET: gcc
|
||||
|
||||
install:
|
||||
- git clone --depth 1 https://github.com/boostorg/boost-ci.git C:\boost-ci-cloned
|
||||
# Copy ci folder if not testing Boost.CI
|
||||
- if NOT "%APPVEYOR_PROJECT_NAME%" == "boost-ci" xcopy /s /e /q /i /y C:\boost-ci-cloned\ci .\ci
|
||||
- rmdir /s /q C:\boost-ci-cloned
|
||||
- ci\appveyor\install.bat
|
||||
|
||||
build: off
|
||||
|
||||
test_script: ci\build.bat
|
||||
|
||||
for:
|
||||
# CodeCov coverage build
|
||||
- matrix:
|
||||
only: [COVERAGE: true]
|
||||
test_script: [ps: ci\codecov.ps1]
|
31
.codecov.yml
Normal file
31
.codecov.yml
Normal file
@ -0,0 +1,31 @@
|
||||
# Copyright 2019 - 2021 Alexander Grund
|
||||
# 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)
|
||||
#
|
||||
# Sample codecov configuration file. Edit as required
|
||||
|
||||
codecov:
|
||||
max_report_age: off
|
||||
require_ci_to_pass: yes
|
||||
notify:
|
||||
# Increase this if you have multiple coverage collection jobs
|
||||
after_n_builds: 2
|
||||
wait_for_ci: yes
|
||||
|
||||
parsers:
|
||||
gcov:
|
||||
branch_detection:
|
||||
conditional: yes
|
||||
loop: yes
|
||||
method: no
|
||||
macro: no
|
||||
|
||||
# Change how pull request comments look
|
||||
comment:
|
||||
layout: "reach,diff,flags,files,footer"
|
||||
|
||||
# Ignore specific files or folders. Glob patterns are supported.
|
||||
# See https://docs.codecov.com/docs/ignoring-paths
|
||||
ignore:
|
||||
- libs/concept_check/test/
|
||||
- test/
|
336
.github/workflows/ci.yml
vendored
Normal file
336
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,336 @@
|
||||
# Copyright 2020-2021 Peter Dimov
|
||||
# Copyright 2021 Andrey Semashev
|
||||
# Copyright 2021 Alexander Grund
|
||||
# Copyright 2022 James E. King III
|
||||
#
|
||||
# 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
|
||||
- bugfix/**
|
||||
- feature/**
|
||||
- fix/**
|
||||
- pr/**
|
||||
|
||||
concurrency:
|
||||
group: ${{format('{0}:{1}', github.repository, github.ref)}}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
ASAN_OPTIONS: allocator_may_return_null=1
|
||||
GIT_FETCH_JOBS: 8
|
||||
NET_RETRY_COUNT: 5
|
||||
B2_CI_VERSION: 1
|
||||
B2_VARIANT: debug,release
|
||||
B2_LINK: shared,static
|
||||
LCOV_BRANCH_COVERAGE: 0
|
||||
CODECOV_NAME: Github Actions
|
||||
|
||||
jobs:
|
||||
posix:
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
# Linux, gcc
|
||||
- { compiler: gcc-4.4, cxxstd: '98,0x', os: ubuntu-20.04, container: 'ubuntu:16.04' }
|
||||
- { compiler: gcc-4.6, cxxstd: '03,0x', os: ubuntu-20.04, container: 'ubuntu:16.04' }
|
||||
- { compiler: gcc-4.7, cxxstd: '03,11', os: ubuntu-20.04, container: 'ubuntu:16.04' }
|
||||
- { compiler: gcc-4.8, cxxstd: '03,11', os: ubuntu-18.04 }
|
||||
- { compiler: gcc-4.9, cxxstd: '03,11', os: ubuntu-20.04, container: 'ubuntu:16.04' }
|
||||
- { compiler: gcc-5, cxxstd: '03,11,14,1z', os: ubuntu-18.04 }
|
||||
- { compiler: gcc-6, cxxstd: '03,11,14,17', os: ubuntu-18.04 }
|
||||
- { compiler: gcc-7, cxxstd: '03,11,14,17', os: ubuntu-18.04 }
|
||||
- { compiler: gcc-8, cxxstd: '03,11,14,17,2a', os: ubuntu-18.04 }
|
||||
- { compiler: gcc-9, cxxstd: '03,11,14,17,2a', os: ubuntu-18.04 }
|
||||
- { compiler: gcc-10, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 }
|
||||
- { compiler: gcc-11, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 }
|
||||
- { name: GCC w/ sanitizers, sanitize: yes,
|
||||
compiler: gcc-11, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 }
|
||||
- { name: Collect coverage, coverage: yes,
|
||||
compiler: gcc-10, cxxstd: '03,11', os: ubuntu-20.04, install: 'g++-10-multilib', address-model: '32,64' }
|
||||
|
||||
# Linux, clang
|
||||
- { compiler: clang-3.5, cxxstd: '03,11', os: ubuntu-20.04, container: 'ubuntu:16.04' }
|
||||
- { compiler: clang-3.6, cxxstd: '03,11,14', os: ubuntu-20.04, container: 'ubuntu:16.04' }
|
||||
- { compiler: clang-3.7, cxxstd: '03,11,14', os: ubuntu-20.04, container: 'ubuntu:16.04' }
|
||||
- { compiler: clang-3.8, cxxstd: '03,11,14', os: ubuntu-20.04, container: 'ubuntu:16.04' }
|
||||
- { compiler: clang-3.9, cxxstd: '03,11,14', os: ubuntu-18.04 }
|
||||
- { compiler: clang-4.0, cxxstd: '03,11,14', os: ubuntu-18.04 }
|
||||
- { compiler: clang-5.0, cxxstd: '03,11,14,1z', os: ubuntu-18.04 }
|
||||
- { compiler: clang-6.0, cxxstd: '03,11,14,17', os: ubuntu-18.04 }
|
||||
- { compiler: clang-7, cxxstd: '03,11,14,17', os: ubuntu-18.04 }
|
||||
# Note: clang-8 does not fully support C++20, so it is not compatible with some libstdc++ versions in this mode
|
||||
- { compiler: clang-8, cxxstd: '03,11,14,17,2a', os: ubuntu-18.04, install: 'clang-8 g++-7', gcc_toolchain: 7 }
|
||||
- { compiler: clang-9, cxxstd: '03,11,14,17,2a', os: ubuntu-20.04 }
|
||||
- { compiler: clang-10, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 }
|
||||
- { compiler: clang-11, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 }
|
||||
- { name: Clang w/ valgrind, valgrind: yes,
|
||||
compiler: clang-12, cxxstd: '03,11,14,17,20', os: ubuntu-20.04, install: 'valgrind' }
|
||||
|
||||
# libc++
|
||||
- { compiler: clang-6.0, cxxstd: '03,11,14', os: ubuntu-18.04, stdlib: libc++, install: 'clang-6.0 libc++-dev libc++abi-dev' }
|
||||
- { compiler: clang-12, cxxstd: '03,11,14,17,20', os: ubuntu-20.04, stdlib: libc++, install: 'clang-12 libc++-12-dev libc++abi-12-dev' }
|
||||
- { name: Clang w/ sanitizers, sanitize: yes,
|
||||
compiler: clang-12, cxxstd: '03,11,14,17,20', os: ubuntu-20.04, stdlib: libc++, install: 'clang-12 libc++-12-dev libc++abi-12-dev' }
|
||||
|
||||
# OSX, clang
|
||||
- { compiler: clang, cxxstd: '03,11,14,17,2a', os: macos-10.15, sanitize: yes }
|
||||
|
||||
# Coverity Scan
|
||||
# requires two github secrets in repo to activate; see ci/github/coverity.sh
|
||||
# does not run on pull requests, only on pushes into develop and master
|
||||
- { name: Coverity, coverity: yes,
|
||||
compiler: clang-10, cxxstd: '17', os: ubuntu-20.04, ccache: no }
|
||||
|
||||
# multiarch (bigendian testing) - does not support coverage yet
|
||||
- { name: Big-endian, multiarch: yes,
|
||||
compiler: clang, cxxstd: '17', os: ubuntu-20.04, ccache: no, distro: fedora, edition: 34, arch: s390x }
|
||||
|
||||
|
||||
timeout-minutes: 120
|
||||
runs-on: ${{matrix.os}}
|
||||
container: ${{matrix.container}}
|
||||
env: {B2_USE_CCACHE: 1}
|
||||
|
||||
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}}" ] && [ -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
|
||||
# Need (newer) git
|
||||
for i in {1..${NET_RETRY_COUNT:-3}}; do sudo -E add-apt-repository -y ppa:git-core/ppa && break || sleep 10; done
|
||||
apt-get -o Acquire::Retries=$NET_RETRY_COUNT update
|
||||
apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y g++ python libpython-dev git
|
||||
fi
|
||||
# multiple job types are not compatible with ccache, they use "ccache: no" in the matrix
|
||||
if [[ "${{ matrix.ccache }}" == "no" ]]; then
|
||||
echo "B2_USE_CCACHE=0" >> $GITHUB_ENV
|
||||
fi
|
||||
if [[ "${{ matrix.valgrind }}" == "yes" ]]; then
|
||||
echo "B2_DEFINES=BOOST_NO_STRESS_TEST=1" >> $GITHUB_ENV
|
||||
echo "B2_TESTFLAGS=testing.launcher=valgrind" >> $GITHUB_ENV
|
||||
echo "B2_FLAGS=define=BOOST_USE_VALGRIND=1" >> $GITHUB_ENV
|
||||
echo "VALGRIND_OPTS=--error-exitcode=1" >> $GITHUB_ENV
|
||||
fi
|
||||
git config --global pack.threads 0
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
# For coverage builds fetch the whole history, else only 1 commit using a 'fake ternary'
|
||||
fetch-depth: ${{ matrix.coverage && '0' || '1' }}
|
||||
|
||||
- name: Cache ccache
|
||||
uses: actions/cache@v2
|
||||
if: env.B2_USE_CCACHE
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ${{matrix.os}}-${{matrix.container}}-${{matrix.compiler}}
|
||||
|
||||
- name: Fetch Boost.CI
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: boostorg/boost-ci
|
||||
ref: master
|
||||
path: boost-ci-cloned
|
||||
|
||||
- name: Get CI scripts folder
|
||||
run: |
|
||||
# Copy ci folder if not testing Boost.CI
|
||||
[[ "$GITHUB_REPOSITORY" =~ "boost-ci" ]] || cp -r boost-ci-cloned/ci .
|
||||
rm -rf boost-ci-cloned
|
||||
|
||||
- name: Install packages
|
||||
if: startsWith(matrix.os, 'ubuntu')
|
||||
run: |
|
||||
SOURCE_KEYS=(${{join(matrix.source_keys, ' ')}})
|
||||
SOURCES=(${{join(matrix.sources, ' ')}})
|
||||
# Add this by default
|
||||
SOURCES+=(ppa:ubuntu-toolchain-r/test)
|
||||
for key in "${SOURCE_KEYS[@]}"; do
|
||||
for i in {1..$NET_RETRY_COUNT}; do
|
||||
wget -O - "$key" | sudo apt-key add - && break || sleep 10
|
||||
done
|
||||
done
|
||||
for source in "${SOURCES[@]}"; do
|
||||
for i in {1..$NET_RETRY_COUNT}; do
|
||||
sudo add-apt-repository $source && break || sleep 10
|
||||
done
|
||||
done
|
||||
sudo apt-get -o Acquire::Retries=$NET_RETRY_COUNT update
|
||||
if [[ -z "${{matrix.install}}" ]]; then
|
||||
pkgs="${{matrix.compiler}}"
|
||||
pkgs="${pkgs/gcc-/g++-}"
|
||||
else
|
||||
pkgs="${{matrix.install}}"
|
||||
fi
|
||||
sudo apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y $pkgs
|
||||
|
||||
- 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 multiarch
|
||||
if: matrix.multiarch
|
||||
run: |
|
||||
sudo apt-get install --no-install-recommends -y binfmt-support qemu-user-static
|
||||
sudo docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
||||
git clone https://github.com/jeking3/bdde.git
|
||||
echo "$(pwd)/bdde/bin/linux" >> ${GITHUB_PATH}
|
||||
echo "BDDE_DISTRO=${{ matrix.distro }}" >> ${GITHUB_ENV}
|
||||
echo "BDDE_EDITION=${{ matrix.edition }}" >> ${GITHUB_ENV}
|
||||
echo "BDDE_ARCH=${{ matrix.arch }}" >> ${GITHUB_ENV}
|
||||
echo "B2_DEFINES=BOOST_NO_STRESS_TEST=1" >> ${GITHUB_ENV}
|
||||
echo "B2_WRAPPER=bdde" >> ${GITHUB_ENV}
|
||||
|
||||
- name: Setup Boost
|
||||
env:
|
||||
B2_ADDRESS_MODEL: ${{matrix.address-model}}
|
||||
B2_COMPILER: ${{matrix.compiler}}
|
||||
B2_CXXSTD: ${{matrix.cxxstd}}
|
||||
B2_SANITIZE: ${{matrix.sanitize}}
|
||||
B2_STDLIB: ${{matrix.stdlib}}
|
||||
run: source ci/github/install.sh
|
||||
|
||||
- name: Setup coverage collection
|
||||
if: matrix.coverage
|
||||
run: ci/github/codecov.sh "setup"
|
||||
|
||||
- name: Run tests
|
||||
if: '!matrix.coverity'
|
||||
run: ci/build.sh
|
||||
|
||||
- name: Upload coverage
|
||||
if: matrix.coverage
|
||||
run: ci/codecov.sh "upload"
|
||||
|
||||
- name: Run coverity
|
||||
if: matrix.coverity && github.event_name == 'push' && (github.ref_name == 'develop' || github.ref_name == 'master')
|
||||
run: ci/github/coverity.sh
|
||||
env:
|
||||
COVERITY_SCAN_NOTIFICATION_EMAIL: ${{ secrets.COVERITY_SCAN_NOTIFICATION_EMAIL }}
|
||||
COVERITY_SCAN_TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
|
||||
|
||||
windows:
|
||||
defaults:
|
||||
run:
|
||||
shell: cmd
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- { toolset: msvc-14.2, cxxstd: '14,17,20', addrmd: '32,64', os: windows-2019 }
|
||||
- { name: Collect coverage, coverage: yes,
|
||||
toolset: msvc-14.3, cxxstd: '14,17,20', addrmd: '32,64', os: windows-2022 }
|
||||
- { toolset: gcc, cxxstd: '03,11,14,17,2a', addrmd: '64', os: windows-2019 }
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Fetch Boost.CI
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: boostorg/boost-ci
|
||||
ref: master
|
||||
path: boost-ci-cloned
|
||||
- name: Get CI scripts folder
|
||||
run: |
|
||||
REM Copy ci folder if not testing Boost.CI
|
||||
if "%GITHUB_REPOSITORY%" == "%GITHUB_REPOSITORY:boost-ci=%" xcopy /s /e /q /i /y boost-ci-cloned\ci .\ci
|
||||
rmdir /s /q boost-ci-cloned
|
||||
|
||||
- name: Setup Boost
|
||||
run: ci\github\install.bat
|
||||
|
||||
- name: Run tests
|
||||
if: '!matrix.coverage'
|
||||
run: ci\build.bat
|
||||
env:
|
||||
B2_TOOLSET: ${{matrix.toolset}}
|
||||
B2_CXXSTD: ${{matrix.cxxstd}}
|
||||
B2_ADDRESS_MODEL: ${{matrix.addrmd}}
|
||||
|
||||
- name: Collect coverage
|
||||
shell: powershell
|
||||
if: matrix.coverage
|
||||
run: ci\opencppcoverage.ps1
|
||||
env:
|
||||
B2_TOOLSET: ${{matrix.toolset}}
|
||||
B2_CXXSTD: ${{matrix.cxxstd}}
|
||||
B2_ADDRESS_MODEL: ${{matrix.addrmd}}
|
||||
|
||||
- name: Upload coverage
|
||||
if: matrix.coverage
|
||||
uses: codecov/codecov-action@v2
|
||||
with:
|
||||
files: __out/cobertura.xml
|
||||
|
||||
CMake:
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- { os: ubuntu-20.04, build_shared: ON, build_type: Release, generator: 'Unix Makefiles' }
|
||||
- { os: ubuntu-20.04, build_shared: OFF, build_type: Debug, generator: 'Unix Makefiles' }
|
||||
- { os: windows-2019, build_shared: ON, build_type: Release, generator: 'Visual Studio 16 2019' }
|
||||
- { os: windows-2019, build_shared: OFF, build_type: Debug, generator: 'Visual Studio 16 2019' }
|
||||
|
||||
timeout-minutes: 120
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Fetch Boost.CI
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: boostorg/boost-ci
|
||||
ref: master
|
||||
path: boost-ci-cloned
|
||||
|
||||
- name: Get CI scripts folder
|
||||
run: |
|
||||
# Copy ci folder if not testing Boost.CI
|
||||
[[ "$GITHUB_REPOSITORY" =~ "boost-ci" ]] || cp -r boost-ci-cloned/ci .
|
||||
rm -rf boost-ci-cloned
|
||||
|
||||
- name: Setup Boost
|
||||
env: {B2_DONT_BOOTSTRAP: 1}
|
||||
run: source ci/github/install.sh
|
||||
|
||||
- name: Run CMake
|
||||
run: |
|
||||
cd "$BOOST_ROOT"
|
||||
mkdir __build_cmake_test__ && cd __build_cmake_test__
|
||||
cmake -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE=${{matrix.build_type}} -DBOOST_INCLUDE_LIBRARIES=$SELF -DBUILD_SHARED_LIBS=${{matrix.build_shared}} -DBUILD_TESTING=ON -DBoost_VERBOSE=ON ..
|
||||
cmake --build . --config ${{matrix.build_type}}
|
42
CMakeLists.txt
Normal file
42
CMakeLists.txt
Normal file
@ -0,0 +1,42 @@
|
||||
# Copyright 2018 Glen Joseph Fernandes
|
||||
# (glenjofe@gmail.com)
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
if(NOT DEFINED IDF_TARGET)
|
||||
|
||||
cmake_minimum_required(VERSION 3.5...3.20)
|
||||
|
||||
project(boost_concept_check VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX)
|
||||
|
||||
add_library(boost_concept_check INTERFACE)
|
||||
|
||||
add_library(Boost::concept_check ALIAS boost_concept_check)
|
||||
|
||||
target_include_directories(boost_concept_check INTERFACE include)
|
||||
|
||||
target_link_libraries(boost_concept_check INTERFACE
|
||||
Boost::config
|
||||
Boost::preprocessor
|
||||
Boost::static_assert
|
||||
Boost::type_traits
|
||||
)
|
||||
|
||||
else()
|
||||
|
||||
FILE(GLOB_RECURSE headers include/*.h include/*.hpp)
|
||||
|
||||
idf_component_register(
|
||||
SRCS
|
||||
${headers}
|
||||
INCLUDE_DIRS
|
||||
include
|
||||
REQUIRES
|
||||
boost_config
|
||||
boost_preprocessor
|
||||
boost_static_assert
|
||||
boost_type_traits
|
||||
)
|
||||
|
||||
endif()
|
18
Jamfile
18
Jamfile
@ -1,10 +1,10 @@
|
||||
subproject libs/concept_check ;
|
||||
# Boost.ConceptCheck Library Jamfile
|
||||
#
|
||||
# Copyright (c) 2018 James E. King III
|
||||
#
|
||||
# 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)
|
||||
|
||||
SEARCH on testing.jam = $(BOOST_BUILD_PATH) ;
|
||||
include testing.jam ;
|
||||
|
||||
compile stl_concept_covering.cpp ;
|
||||
compile concept_check_test.cpp ;
|
||||
compile class_concept_check_test.cpp ;
|
||||
link-fail concept_check_fail_expected.cpp ;
|
||||
link-fail class_concept_fail_expected.cpp ;
|
||||
# please order by name to ease maintenance
|
||||
build-project test ;
|
||||
|
23
LICENSE
Normal file
23
LICENSE
Normal file
@ -0,0 +1,23 @@
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
34
README.md
Normal file
34
README.md
Normal file
@ -0,0 +1,34 @@
|
||||
ConceptCheck, part of collection of the [Boost C++ Libraries](http://github.com/boostorg),
|
||||
allows one to add explicit statement and checking of concepts in the style of the proposed C++ language extension.
|
||||
|
||||
### License
|
||||
|
||||
Distributed under the [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt).
|
||||
|
||||
### Properties
|
||||
|
||||
* C++03
|
||||
* Header-only
|
||||
|
||||
### Build Status
|
||||
|
||||
Branch | GHA CI | Appveyor | Coverity Scan | codecov.io | Deps | Docs | Tests |
|
||||
:-------------: | ------ | -------- | ------------- | ---------- | ---- | ---- | ----- |
|
||||
[`master`](https://github.com/boostorg/concept_check/tree/master) | [](https://github.com/boostorg/concept_check/actions?query=branch:master) | [](https://ci.appveyor.com/project/jeking3/concept_check-gp9xw/branch/master) | [](https://scan.coverity.com/projects/boostorg-concept_check) | [](https://codecov.io/gh/boostorg/concept_check/branch/master)| [](https://pdimov.github.io/boostdep-report/master/concept_check.html) | [](https://www.boost.org/doc/libs/master/libs/concept_check/doc/html) | [](http://www.boost.org/development/tests/master/developer/concept_check.html)
|
||||
[`develop`](https://github.com/boostorg/concept_check/tree/develop) | [](https://github.com/boostorg/concept_check/actions?query=branch:develop)| [](https://ci.appveyor.com/project/jeking3/concept_check-gp9xw/branch/develop) | [](https://scan.coverity.com/projects/boostorg-concept_check) | [](https://codecov.io/gh/boostorg/concept_check/branch/develop) | [](https://pdimov.github.io/boostdep-report/develop/concept_check.html) | [](https://www.boost.org/doc/libs/develop/libs/concept_check/doc/html) | [](http://www.boost.org/development/tests/develop/developer/concept_check.html)
|
||||
|
||||
### Directories
|
||||
|
||||
| Name | Purpose |
|
||||
| ----------- | ------------------------------ |
|
||||
| `doc` | documentation |
|
||||
| `include` | headers |
|
||||
| `test` | unit tests |
|
||||
|
||||
### More information
|
||||
|
||||
* [Ask questions](http://stackoverflow.com/questions/ask?tags=c%2B%2B,boost,boost-concept_check)
|
||||
* [Report bugs](https://github.com/boostorg/concept_check/issues): Be sure to mention Boost version, 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](http://www.boost.org/LICENSE_1_0.txt).
|
||||
* Discussions about the library are held on the [Boost developers mailing list](http://www.boost.org/community/groups.html#main). Be sure to read the [discussion policy](http://www.boost.org/community/policy.html) before posting and add the `[concept_check]` tag at the beginning of the subject line.
|
||||
|
@ -1,14 +1,14 @@
|
||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#include <vector>
|
||||
#include <complex>
|
||||
#include "algorithm"
|
||||
|
||||
#include <list>
|
||||
#include <algorithm>
|
||||
|
||||
int main() {
|
||||
std::list<int> v;
|
||||
std::stable_sort(v.begin(), v.end());
|
||||
return 0;
|
||||
int main()
|
||||
{
|
||||
std::vector<std::complex<float> > v;
|
||||
std_::stable_sort(v.begin(), v.end());
|
||||
}
|
||||
|
||||
// (C) Copyright Jeremy Siek 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)
|
||||
|
@ -1,20 +1,13 @@
|
||||
<HTML>
|
||||
<!--
|
||||
-- Copyright (c) Jeremy Siek 2000
|
||||
--
|
||||
-- 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) Jeremy Siek 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) -->
|
||||
<Head>
|
||||
<Title>Boost Graph Library: Bibliography</Title>
|
||||
<Title>Boost Concept Checking Library: Bibliography</Title>
|
||||
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
|
||||
ALINK="#ff0000">
|
||||
<IMG SRC="../../c++boost.gif"
|
||||
<IMG SRC="../../boost.png"
|
||||
ALT="C++ Boost" width="277" height="86">
|
||||
|
||||
<BR Clear>
|
||||
@ -63,7 +56,7 @@ A. A. Stepanov and M. Lee
|
||||
<TABLE>
|
||||
<TR valign=top>
|
||||
<TD nowrap>Copyright © 2000</TD><TD>
|
||||
<A HREF="../../people/jeremy_siek.htm">Jeremy Siek</A>(<A
|
||||
<A HREF="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</A>(<A
|
||||
HREF="mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</A>)
|
||||
Andrew Lumsdaine</A>(<A HREF="mailto:lums@osl.iu.edu">lums@osl.iu.edu</A>)
|
||||
</TD></TR></TABLE>
|
||||
|
@ -1,70 +0,0 @@
|
||||
<HTML>
|
||||
<!--
|
||||
-- Copyright (c) Jeremy Siek 2000
|
||||
--
|
||||
-- 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.
|
||||
-->
|
||||
<Head>
|
||||
<Title>Boost Graph Library: Bibliography</Title>
|
||||
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
|
||||
ALINK="#ff0000">
|
||||
<IMG SRC="../../c++boost.gif"
|
||||
ALT="C++ Boost" width="277" height="86">
|
||||
|
||||
<BR Clear>
|
||||
|
||||
|
||||
<H2>Bibliography</H2>
|
||||
|
||||
<DL COMMapCT>
|
||||
|
||||
<DD><P></P><DT><a name="alexandrescu99:_better_templ_error_messag">1</a>
|
||||
<DD>Andrei Alexandrescu<BR>
|
||||
<EM>Better Template Error Messages</EM>.<BR>
|
||||
C/C++ Users Journal, March, 1999.
|
||||
|
||||
|
||||
<DD><P></P><DT><a name="stroustrup94:_design_evolution">2</a>
|
||||
<DD>Bjarne Stroustrup<BR>
|
||||
<EM>Design and Evolution of C++</EM>.<BR>
|
||||
Addison-Wesley, 1994
|
||||
|
||||
<P></P><DT><A NAME="austern99:_gener_progr_stl">3</A>
|
||||
<DD>
|
||||
M. H. Austern.
|
||||
<BR><EM>Generic Programming and the STL</EM>.
|
||||
<BR>Professional computing series. Addison-Wesley, 1999.
|
||||
|
||||
<P></P><DT><A NAME="IB-H965502">4</A>
|
||||
<DD>
|
||||
David R. Musser and Atul Saini
|
||||
<BR><EM>STL Tutorial and Reference Guide</EM>.
|
||||
<BR>Professional computing series. Addison-Wesley, 1996.
|
||||
|
||||
<P></P><DT><A NAME="stepa.lee-1994:the.s:TR">5</A>
|
||||
<DD>
|
||||
A. A. Stepanov and M. Lee
|
||||
<BR><EM>The Standard Template Library</EM>.
|
||||
<BR>ISO Programming Language C++ Project, May 1994.
|
||||
<BR>X3J16/94-0095, WG21/N0482
|
||||
|
||||
|
||||
|
||||
</DL>
|
||||
|
||||
<br>
|
||||
<HR>
|
||||
<TABLE>
|
||||
<TR valign=top>
|
||||
<TD nowrap>Copyright © 2000</TD><TD>
|
||||
<A HREF=http://www.boost.org/people/jeremy_siek.htm>Jeremy Siek</A>, Univ.of Notre Dame (<A HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>)
|
||||
</TD></TR></TABLE>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
@ -1,35 +0,0 @@
|
||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
#include <boost/concept_check.hpp>
|
||||
|
||||
/*
|
||||
|
||||
This file verifies that the BOOST_CLASS_REQUIRE macro of the Boost
|
||||
Concept Checking Library does not cause errors when it is not suppose
|
||||
to.
|
||||
|
||||
*/
|
||||
|
||||
struct foo { bool operator()(int) { return true; } };
|
||||
struct bar { bool operator()(int, char) { return true; } };
|
||||
|
||||
class class_requires_test
|
||||
{
|
||||
BOOST_CLASS_REQUIRE(int, boost, EqualityComparableConcept);
|
||||
typedef int* int_ptr; typedef const int* const_int_ptr;
|
||||
BOOST_CLASS_REQUIRE2(int_ptr, const_int_ptr, boost, EqualOpConcept);
|
||||
BOOST_CLASS_REQUIRE3(foo, bool, int, boost, UnaryFunctionConcept);
|
||||
BOOST_CLASS_REQUIRE4(bar, bool, int, char, boost, BinaryFunctionConcept);
|
||||
};
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
class_requires_test x;
|
||||
boost::ignore_unused_variable_warning(x);
|
||||
return 0;
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
#include <boost/pending/concept_checks.hpp>
|
||||
|
||||
/*
|
||||
|
||||
This file verifies that class_requires of the Boost Concept Checking
|
||||
Library catches errors when it is suppose to.
|
||||
|
||||
*/
|
||||
|
||||
struct foo { };
|
||||
|
||||
using namespace boost;
|
||||
|
||||
class class_requires_test
|
||||
{
|
||||
BOOST_CLASS_REQUIRES(foo, EqualityComparableConcept);
|
||||
};
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
class_requires_test x;
|
||||
return 0;
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
#include <boost/pending/concept_checks.hpp>
|
||||
|
||||
/*
|
||||
|
||||
This file verifies that the BOOST_CLASS_REQUIRES macro of the Boost
|
||||
Concept Checking Library does not cause errors when it is not suppose
|
||||
to.
|
||||
|
||||
*/
|
||||
|
||||
struct foo { bool operator()(int) { return true; } };
|
||||
struct bar { bool operator()(int, char) { return true; } };
|
||||
|
||||
using namespace boost;
|
||||
|
||||
class class_requires_test
|
||||
{
|
||||
BOOST_CLASS_REQUIRES(int, EqualityComparableConcept);
|
||||
typedef int* int_ptr; typedef const int* const_int_ptr;
|
||||
BOOST_CLASS_REQUIRES2(int_ptr, const_int_ptr, Comparable2Concept);
|
||||
BOOST_CLASS_REQUIRES3(foo, bool, int, UnaryFunctionConcept);
|
||||
BOOST_CLASS_REQUIRES4(bar, bool, int, char, BinaryFunctionConcept);
|
||||
};
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
class_requires_test x;
|
||||
ignore_unused_variable_warning(x);
|
||||
return 0;
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
//
|
||||
// Change Log:
|
||||
// 20 Jan 2001 - Added warning suppression (David Abrahams)
|
||||
|
||||
#include <boost/concept_check.hpp>
|
||||
|
||||
/*
|
||||
|
||||
This file verifies that class_requires of the Boost Concept Checking
|
||||
Library catches errors when it is suppose to.
|
||||
|
||||
*/
|
||||
|
||||
struct foo { };
|
||||
|
||||
class class_requires_test
|
||||
{
|
||||
BOOST_CLASS_REQUIRE(foo, boost, EqualityComparableConcept);
|
||||
};
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
class_requires_test x;
|
||||
(void)x; // suppress unused variable warning
|
||||
return 0;
|
||||
}
|
@ -1,313 +1,330 @@
|
||||
<HTML>
|
||||
<!--
|
||||
-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 2000
|
||||
--
|
||||
-- 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. We make no
|
||||
-- representations about the suitability of this software for any
|
||||
-- purpose. It is provided "as is" without express or implied warranty.
|
||||
-->
|
||||
<Head>
|
||||
<Title>Concept Check Library</Title>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<!-- Copyright (c) 2000 Jeremy Siek and Andrew Lumsdaine, 2007 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) -->
|
||||
|
||||
<head>
|
||||
<meta name="generator" content=
|
||||
"HTML Tidy for Linux/x86 (vers 1 September 2005), see www.w3.org" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>Concept Check Library</title>
|
||||
<link rel="stylesheet" href="../../rst.css" type="text/css" />
|
||||
</head>
|
||||
|
||||
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
|
||||
ALINK="#ff0000">
|
||||
<IMG SRC="../../c++boost.gif"
|
||||
ALT="C++ Boost" width="277" height="86">
|
||||
<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" />
|
||||
|
||||
<BR Clear>
|
||||
<h1>The Boost Concept Check Library (BCCL)</h1>
|
||||
|
||||
<H1>The Boost Concept Check Library (BCCL)</H1>
|
||||
<blockquote>
|
||||
The Concept Check library allows one to add explicit statement and
|
||||
checking of <a href=
|
||||
"http://www.boost.org/more/generic_programming.html#concept">concepts</a> in the style
|
||||
of the <a href=
|
||||
"http://www.generic-programming.org/languages/conceptcpp/specification/">proposed
|
||||
C++ language extension</a>.
|
||||
</blockquote>
|
||||
|
||||
<h2>
|
||||
<A NAME="sec:concept-checking"></A>
|
||||
header <a href="../../boost/concept_check.hpp">
|
||||
<tt>boost/concept_check.hpp</tt></a>
|
||||
<br>and <a href="../../boost/concept_archetype.hpp">
|
||||
<tt>boost/concept_archetype.hpp</tt></a>
|
||||
</h2>
|
||||
<h2><a name="sec:concept-checking" id="sec:concept-checking"></a>Synopsis</a></h2>
|
||||
|
||||
<p>
|
||||
Generic programming in C++ is characterized by the use of template
|
||||
parameters to represent abstract data types (or ``concepts'').
|
||||
However, the C++ language itself does not provide a mechanism for the
|
||||
writer of a class or function template to explicitly state what
|
||||
concept the user-supplied template argument should model (or conform
|
||||
to). The common practice is to name the template parameter after the
|
||||
required concept as a hint to the user and to state the concept
|
||||
requirements in the documentation. However, often times the
|
||||
requirements are vague, incorrect, or nonexistent, which is quite a
|
||||
problem for the user, since he or she will not know exactly what kind
|
||||
of input is expected by the template. Furthermore, the following
|
||||
problems occur:
|
||||
<p>Generic programming in C++ is characterized by the use of template
|
||||
parameters to represent abstract data types (or “<a href=
|
||||
"http://www.boost.org/more/generic_programming.html#concept">concepts</a>”). However, the
|
||||
C++ language itself does not provide a mechanism for the writer of a class
|
||||
or function template to explicitly state the concept that the user-supplied
|
||||
template argument should model (or conform to). Template parameters are
|
||||
commonly named after the concept they're required to model as a hint to the
|
||||
user, and to make the concept requirements explicit in code. However, the
|
||||
compiler doesn't treat these special names specially: a parameter named
|
||||
<code>RandomAccessIterator</code> is no different to the compiler than one
|
||||
named <code>T</code>. Furthermore,</p>
|
||||
|
||||
<ul>
|
||||
<li>Compiler error messages resulting from incorrect template
|
||||
arguments can be particularly difficult to decipher. Often times
|
||||
the error does not point to the location of the template
|
||||
call-site, but instead exposes the internals of the template, which
|
||||
the user should never have to see.</li>
|
||||
<ul>
|
||||
<li>Compiler error messages resulting from incorrect template arguments
|
||||
can be particularly difficult to decipher. Often times the error does not
|
||||
point to the location of the template call-site, but instead exposes the
|
||||
internals of the template, which the user should never have to see.</li>
|
||||
|
||||
<li>The documented concept requirements may not fully <i>cover</i>
|
||||
the template, meaning the user could get a compiler error even
|
||||
though the supplied template arguments meet the documented
|
||||
requirements.</li>
|
||||
<li>Without checking from the compiler, the documented requirements are
|
||||
oftentimes vague, incorrect, or nonexistent, so a user cannot know
|
||||
exactly what kind of arguments are expected.</li>
|
||||
|
||||
<li>The documented concept requirements may be too stringent,
|
||||
requiring more than is really needed by the template.</li>
|
||||
<li>The documented concept requirements may not fully <i>cover</i> the
|
||||
needs of the actual template, meaning the user could get a compiler error
|
||||
even though the supplied template arguments meet the documented
|
||||
requirements.</li>
|
||||
|
||||
<li>The requirements are not explicitly stated in the code, which
|
||||
makes the code harder to understand. Also, the code may
|
||||
get out-of-sync with the documented requirements.</li>
|
||||
</ul>
|
||||
<li>The documented concept requirements may be too stringent, requiring
|
||||
more than is really needed by the template.</li>
|
||||
|
||||
The Boost Concept Checking Library provides:
|
||||
<li>Concept names in code may drift out-of-sync with the documented
|
||||
requirements.</li>
|
||||
</ul><p>The Boost Concept Checking Library provides:
|
||||
|
||||
<ul>
|
||||
<li>A mechanism for inserting compile-time checks of template
|
||||
parameters.</li>
|
||||
<ul>
|
||||
<li>A mechanism for inserting compile-time checks on template parameters
|
||||
at their point of use.</li>
|
||||
|
||||
<li>A framework for specifying concept requirements though concept
|
||||
checking classes.</li>
|
||||
<li>A framework for specifying concept requirements through concept
|
||||
checking classes.</li>
|
||||
|
||||
<li>A mechanism for verifying that concept requirements cover the template.</li>
|
||||
<li>A mechanism for verifying that concept requirements cover the
|
||||
template.</li>
|
||||
|
||||
<li>A suite of concept checking classes and archetype classes that
|
||||
match the concept requirements in the C++ Standard Library.</li>
|
||||
</ul>
|
||||
<li>A suite of concept checking classes and archetype classes that match
|
||||
the concept requirements in the C++ Standard Library.</li>
|
||||
|
||||
The mechanisms use standard C++ and introduce no run-time
|
||||
overhead. The main cost of using the mechanism is in compile-time.
|
||||
<li>An alternative to the use of traits classes for accessing associated
|
||||
types that mirrors the syntax proposed for the next C++ standard.</li>
|
||||
</ul><p>The mechanisms use standard C++ and introduce no run-time overhead.
|
||||
The main cost of using the mechanism is in compile-time.</p>
|
||||
|
||||
<p>
|
||||
Any programmer writing class or function templates ought to make
|
||||
concept checking a normal part of their code writing routine. A
|
||||
concept check should be inserted for each template parameter in a
|
||||
component's public interface. If the concept is one of the ones from
|
||||
the Standard Library, then simply use the matching concept checking
|
||||
class in the BCCL. If not, then write a new concept checking class -
|
||||
after all, they are typically only a few lines long. For new concepts,
|
||||
a matching archetype class should also be created, which is a minimal
|
||||
skeleton-implementation of the concept
|
||||
<p><strong>Every programmer writing class or function templates ought to
|
||||
make concept checking a normal part of their code writing routine.</strong>
|
||||
A concept check should be inserted for each template parameter in a
|
||||
component's public interface. If the concept is one of the ones from the
|
||||
Standard Library, then simply use the matching concept checking class in
|
||||
the BCCL. If not, then write a new concept checking class - after all, they
|
||||
are typically only a few lines long. For new concepts, a matching archetype
|
||||
class should also be created, which is a minimal skeleton-implementation of
|
||||
the concept</p>
|
||||
|
||||
<p>
|
||||
The documentation is organized into the following sections.
|
||||
<p>The documentation is organized into the following sections.</p>
|
||||
|
||||
<OL>
|
||||
<LI><a href="#introduction">Introduction</a></LI>
|
||||
<LI><a href="#motivating-example">Motivating Example</a></LI>
|
||||
<LI><a href="#history">History</a></LI>
|
||||
<LI><a href="#publications">Publications</a></LI>
|
||||
<LI><a href="#acknowledgements">Acknowledgements</a></LI>
|
||||
<LI><a href="./using_concept_check.htm">Using Concept Checks</a></LI>
|
||||
<LI><a href="creating_concepts.htm">Creating Concept Checking Classes</a></LI>
|
||||
<LI><a href="./concept_covering.htm">Concept Covering and Archetypes</a></LI>
|
||||
<LI><a href="./prog_with_concepts.htm" ">Programming With Concepts</a></LI>
|
||||
<LI><a href="./implementation.htm">Implementation</a></LI>
|
||||
<LI><a href="./reference.htm">Reference</a></LI>
|
||||
</OL>
|
||||
<ol>
|
||||
<li><a href="#introduction">Introduction</a></li>
|
||||
|
||||
<p>
|
||||
<a href="../../people/jeremy_siek.htm">Jeremy Siek</a> contributed
|
||||
this library. <a href="../../people/beman_dawes.html">Beman Dawes</a>
|
||||
managed the formal review.
|
||||
<li><a href="#motivating-example">Motivating Example</a></li>
|
||||
|
||||
<h2><a name="introduction">Introduction</a></h2>
|
||||
|
||||
A <i>concept</i> is a set of requirements (valid expressions,
|
||||
associated types, semantic invariants, complexity guarantees, etc.)
|
||||
that a type must fulfill to be correctly used as arguments in a call
|
||||
to a generic algorithm. In C++, concepts are represented by formal
|
||||
template parameters to function templates (generic algorithms).
|
||||
However, C++ has no explicit mechanism for representing concepts ---
|
||||
template parameters are merely placeholders. By convention, these
|
||||
parameters are given names corresponding to the concept that is
|
||||
required, but a C++ compiler does not enforce compliance to the
|
||||
concept when the template parameter is bound to an actual type.
|
||||
<li><a href="#history">History</a></li>
|
||||
|
||||
<p>
|
||||
Naturally, if a generic algorithm is invoked with a type that does not
|
||||
fulfill at least the syntactic requirements of the concept, a
|
||||
compile-time error will occur. However, this error will not <i>per
|
||||
se</i> reflect the fact that the type did not meet all of the
|
||||
requirements of the concept. Rather, the error may occur deep inside
|
||||
the instantiation hierarchy at the point where an expression is not
|
||||
valid for the type, or where a presumed associated type is not
|
||||
available. The resulting error messages are largely uninformative and
|
||||
basically impenetrable.
|
||||
<li><a href="#publications">Publications</a></li>
|
||||
|
||||
<p>
|
||||
What is required is a mechanism for enforcing ``concept safety'' at
|
||||
(or close to) the point of instantiation. The Boost Concept Checking
|
||||
Library uses some standard C++ constructs to enforce early concept
|
||||
compliance and that provides more informative error messages upon
|
||||
non-compliance.
|
||||
<li><a href="#acknowledgements">Acknowledgements</a></li>
|
||||
|
||||
<p>
|
||||
Note that this technique only addresses the syntactic
|
||||
requirements of concepts (the valid expressions and associated types).
|
||||
We do not address the semantic invariants or complexity guarantees,
|
||||
which are also part of concept requirements..
|
||||
<li><a href="./using_concept_check.htm">Using Concept Checks</a></li>
|
||||
|
||||
<h2><a name="motivating-example">Motivating Example</a></h2>
|
||||
<li><a href="creating_concepts.htm">Creating Concept Checking
|
||||
Classes</a></li>
|
||||
|
||||
We present a simple example to illustrate incorrect usage of a
|
||||
template library and the resulting error messages. In the code below,
|
||||
the generic <tt>std::stable_sort()</tt> algorithm from the Standard
|
||||
Template Library (STL)[<a
|
||||
href="bibliography.htm#austern99:_gener_progr_stl">3</a>, <a
|
||||
href="bibliography.htm#IB-H965502">4</a>,<a
|
||||
href="bibliography.htm#stepa.lee-1994:the.s:TR">5</a>] is applied to
|
||||
a linked list.
|
||||
<li><a href="./concept_covering.htm">Concept Covering and
|
||||
Archetypes</a></li>
|
||||
|
||||
<pre>
|
||||
<li><a href="./prog_with_concepts.htm">Programming With Concepts</a></li>
|
||||
|
||||
<li><a href="./implementation.htm">Implementation</a></li>
|
||||
|
||||
<li><a href="./reference.htm">Reference</a></li>
|
||||
</ol>
|
||||
|
||||
<p><a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</a> contributed this
|
||||
library. <a href="http://www.boost.org/people/beman_dawes.html">Beman Dawes</a> managed
|
||||
the formal review. <a href="http://www.boost.org/people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> contributed a rewrite that updated syntax to be more
|
||||
compatible with proposed syntax for concept support the C++ core
|
||||
language.</p>
|
||||
|
||||
<h2><a name="introduction" id="introduction">Introduction</a></h2><p>A
|
||||
<i>concept</i> is a set of requirements (valid expressions, associated
|
||||
types, semantic invariants, complexity guarantees, etc.) that a type must
|
||||
fulfill to be correctly used as arguments in a call to a generic algorithm.
|
||||
In C++, concepts are represented by formal template parameters to function
|
||||
templates (generic algorithms). However, C++ has no explicit mechanism for
|
||||
representing concepts—template parameters are merely placeholders. By
|
||||
convention, these parameters are given names corresponding to the concept
|
||||
that is required, but a C++ compiler does not enforce compliance to the
|
||||
concept when the template parameter is bound to an actual type.
|
||||
|
||||
<p>Naturally, if a generic algorithm is invoked with a type that does not
|
||||
fulfill at least the syntactic requirements of the concept, a compile-time
|
||||
error will occur. However, this error will not <i>per se</i> reflect the
|
||||
fact that the type did not meet all of the requirements of the concept.
|
||||
Rather, the error may occur deep inside the instantiation hierarchy at the
|
||||
point where an expression is not valid for the type, or where a presumed
|
||||
associated type is not available. The resulting error messages are largely
|
||||
uninformative and basically impenetrable.</p>
|
||||
|
||||
<p>What is required is a mechanism for enforcing
|
||||
“concept safety” at (or close to) the point
|
||||
of instantiation. The Boost Concept Checking Library uses some standard C++
|
||||
constructs to enforce early concept compliance and that provides more
|
||||
informative error messages upon non-compliance.</p>
|
||||
|
||||
<p>Note that this technique only addresses the syntactic requirements of
|
||||
concepts (the valid expressions and associated types). We do not address
|
||||
the semantic invariants or complexity guarantees, which are also part of
|
||||
concept requirements..</p>
|
||||
|
||||
<h2><a name="motivating-example" id="motivating-example">Motivating
|
||||
Example</a></h2>
|
||||
|
||||
<p>We present a simple example to illustrate incorrect usage of a template
|
||||
library and the resulting error messages. In the code below, the generic
|
||||
<tt>std::stable_sort()</tt> algorithm from the Standard Template Library
|
||||
(STL)[<a href="bibliography.htm#austern99:_gener_progr_stl">3</a>, <a href=
|
||||
"bibliography.htm#IB-H965502">4</a>,<a href=
|
||||
"bibliography.htm#stepa.lee-1994:the.s:TR">5</a>] is applied to a linked
|
||||
list.</p>
|
||||
<pre>
|
||||
<a href="./bad_error_eg.cpp">bad_error_eg.cpp</a>:
|
||||
1 #include <list>
|
||||
2 #include <algorithm>
|
||||
3
|
||||
4 int main(int, char*[]) {
|
||||
5 std::list<int> v;
|
||||
6 std::stable_sort(v.begin(), v.end());
|
||||
7 return 0;
|
||||
8 }
|
||||
<font color="gray">1</font> #include <vector>
|
||||
<font color="gray">2</font color="gray"> #include <complex>
|
||||
<font color="gray">3</font color="gray"> #include <algorithm>
|
||||
<font color="gray">4</font color="gray">
|
||||
<font color="gray">5</font color="gray"> int main()
|
||||
<font color="gray">6</font color="gray"> {
|
||||
<font color="gray">7</font color="gray"> std::vector<std::complex<float> > v;
|
||||
<font color="gray">8</font color="gray"> std::stable_sort(v.begin(), v.end());
|
||||
<font color="gray">9</font color="gray"> }
|
||||
</pre>
|
||||
|
||||
Here, the
|
||||
<tt>std::stable_sort()</tt> algorithm is prototyped as follows:
|
||||
<pre>
|
||||
<p>Here, the <tt>std::stable_sort()</tt> algorithm is prototyped as
|
||||
follows:</p>
|
||||
<pre>
|
||||
template <class RandomAccessIterator>
|
||||
void stable_sort(RandomAccessIterator first, RandomAccessIterator last);
|
||||
</pre>
|
||||
|
||||
Attempting to compile this code with Gnu C++ produces the following
|
||||
compiler error. The output from other compilers is listed in the
|
||||
Appendix.
|
||||
|
||||
<pre>
|
||||
stl_algo.h: In function `void __merge_sort_loop<_List_iterator
|
||||
<int,int &,int *>, int *, int>(_List_iterator<int,int &,int *>,
|
||||
_List_iterator<int,int &,int *>, int *, int)':
|
||||
stl_algo.h:1448: instantiated from `__merge_sort_with_buffer
|
||||
<_List_iterator<int,int &,int *>, int *, int>(
|
||||
_List_iterator<int,int &,int *>, _List_iterator<int,int &,int *>,
|
||||
int *, int *)'
|
||||
stl_algo.h:1485: instantiated from `__stable_sort_adaptive<
|
||||
_List_iterator<int,int &,int *>, int *, int>(_List_iterator
|
||||
<int,int &,int *>, _List_iterator<int,int &,int *>, int *, int)'
|
||||
stl_algo.h:1524: instantiated from here
|
||||
stl_algo.h:1377: no match for `_List_iterator<int,int &,int *> & -
|
||||
_List_iterator<int,int &,int *> &'
|
||||
<p>Attempting to compile this code with Gnu C++ produces the following
|
||||
compiler error:</p>
|
||||
<pre>
|
||||
/usr/include/c++/4.1.2/bits/stl_algo.h: In function ‘void std::
|
||||
__insertion_sort(_RandomAccessIterator, _RandomAccessIterator) [with
|
||||
_RandomAccessIterator = __gnu_cxx::__normal_iterator<std::complex<float
|
||||
>*, std::vector<std::complex<float>, std::allocator<std::complex<
|
||||
float> > > >]’:
|
||||
/usr/include/c++/4.1.2/bits/stl_algo.h:3066: instantiated from ‘void
|
||||
std::__inplace_stable_sort(_RandomAccessIterator,
|
||||
_RandomAccessIterator) [with _RandomAccessIterator = __gnu_cxx::
|
||||
__normal_iterator<std::complex<float>*, std::vector<std::complex<
|
||||
float>, std::allocator<std::complex<float> > > >]’
|
||||
/usr/include/c++/4.1.2/bits/stl_algo.h:3776: instantiated from ‘void
|
||||
std::stable_sort(_RandomAccessIterator, _RandomAccessIterator) [with
|
||||
_RandomAccessIterator = __gnu_cxx::__normal_iterator<std::complex<float
|
||||
>*, std::vector<std::complex<float>, std::allocator<std::complex<
|
||||
float> > > >]’
|
||||
bad_error_eg.cpp:8: instantiated from here
|
||||
/usr/include/c++/4.1.2/bits/stl_algo.h:2277: error: no match for
|
||||
‘operator<’ in ‘__val < __first. __gnu_cxx::__normal_iterator<
|
||||
_Iterator, _Container>::operator* [with _Iterator = std::complex<float
|
||||
>*, _Container = std::vector<std::complex<float>, std::allocator<
|
||||
std::complex<float> > >]()’
|
||||
</pre>
|
||||
|
||||
In this case, the fundamental error is that
|
||||
<tt>std:list::iterator</tt> does not model the concept of <a
|
||||
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">
|
||||
RandomAccessIterator</a>. The list iterator is only bidirectional, not
|
||||
fully random access (as would be a vector iterator). Unfortunately,
|
||||
there is nothing in the error message to indicate this to the user.
|
||||
<p>In this case, the fundamental error is
|
||||
that <tt>std:complex<float></tt> does not model the <a href=
|
||||
"http://www.boost.org/sgi/stl/LessThanComparable.html">LessThanComparable</a>
|
||||
concept. Unfortunately, there is nothing in the error message to
|
||||
indicate that to the user.</p>
|
||||
|
||||
<p>
|
||||
To a C++ programmer having enough experience with template libraries
|
||||
the error may be obvious. However, for the uninitiated, there are several
|
||||
reasons why this message would be hard to understand.
|
||||
<p>The error may be obvious to a C++ programmer having enough
|
||||
experience with template libraries, but there are several reasons
|
||||
why this message could be hard for the uninitiated to
|
||||
understand:</p>
|
||||
|
||||
<OL>
|
||||
<LI> The location of the error, line 6 of <tt>bad_error_eg.cpp</tt>
|
||||
is not pointed to by the error message, despite the fact that Gnu C++
|
||||
prints up to 4 levels deep in the instantiation stack.
|
||||
<LI> There is no textual correlation between the error message and the
|
||||
documented requirements for <tt>std::stable_sort()</tt> and for
|
||||
<a
|
||||
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">
|
||||
RandomAccessIterator</a>.
|
||||
<LI> The error message is overly long, listing functions internal
|
||||
to the STL that the user does not (and should not!) know or care
|
||||
about.
|
||||
<LI> With so many internal library functions listed in the error
|
||||
message, the programmer could easily infer that the error is due
|
||||
to the library, rather than to his or her own code.
|
||||
</OL>
|
||||
<ol>
|
||||
<li>There is no textual correlation between the error message and the
|
||||
documented requirements for <tt>std::stable_sort()</tt> and for <a href=
|
||||
"http://www.boost.org/sgi/stl/LessThanComparable.html">LessThanComparable</a>.</li>
|
||||
|
||||
The following is an example of what we might expect from a more
|
||||
informative message (and is in fact what the Boost Concept Checking
|
||||
Library produces):
|
||||
<li>The error message is overly long, listing functions internal
|
||||
to the STL (e.g. <code>__insertion_sort</code>) that the user
|
||||
does not (and should not!) know or care about.</li>
|
||||
|
||||
<pre>
|
||||
boost/concept_check.hpp: In method `void LessThanComparableConcept
|
||||
<_List_iterator<int,int &,int *> >::constraints()':
|
||||
boost/concept_check.hpp:334: instantiated from `RandomAccessIteratorConcept
|
||||
<_List_iterator<int,int &,int *> >::constraints()'
|
||||
bad_error_eg.cpp:6: instantiated from `stable_sort<_List_iterator
|
||||
<int,int &,int *> >(_List_iterator<int,int &,int *>,
|
||||
_List_iterator<int,int &,int *>)'
|
||||
boost/concept_check.hpp:209: no match for `_List_iterator<int,int &,int *> &
|
||||
< _List_iterator<int,int &,int *> &'
|
||||
<li>With so many internal library functions listed in the error message,
|
||||
the programmer could easily infer that the problem is in the library,
|
||||
rather than in his or her own code.</li>
|
||||
</ol>
|
||||
|
||||
<p>The following is an example of what we might expect from a more
|
||||
informative message (and is in fact what the Boost Concept Checking Library
|
||||
produces):</p>
|
||||
<pre>
|
||||
boost/concept_check.hpp: In destructor ‘boost::LessThanComparable<TT>::~
|
||||
LessThanComparable() [with TT = std::complex<float>]’:
|
||||
boost/concept/detail/general.hpp:29: instantiated from ‘static void boost::
|
||||
concepts::requirement<Model>::failed() [with Model = boost::
|
||||
LessThanComparable<std::complex<float> >]’
|
||||
boost/concept/requires.hpp:30: instantiated from ‘boost::_requires_<void
|
||||
(*)(boost::LessThanComparable<std::complex<float> >)>’
|
||||
bad_error_eg.cpp:8: instantiated from here
|
||||
boost/concept_check.hpp:236: error: no match for ‘operator<’ in ‘((boost::
|
||||
LessThanComparable<std::complex<float> >*)this)->boost::
|
||||
LessThanComparable<std::complex<float> >::a < ((boost::
|
||||
LessThanComparable<std::complex<float> >*)this)->boost::
|
||||
LessThanComparable<std::complex<float> >::b’
|
||||
</pre>
|
||||
|
||||
This message rectifies several of the shortcomings of the standard
|
||||
error messages.
|
||||
<p>This message rectifies several of the shortcomings of the standard error
|
||||
messages.</p>
|
||||
|
||||
<UL>
|
||||
<LI> The location of the error, <tt>bad_error_eg.cpp:6</tt> is
|
||||
specified in the error message.
|
||||
<LI> The message refers explicitly to concepts that the user can look
|
||||
up in the STL documentation (<a
|
||||
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">
|
||||
RandomAccessIterator</a>).
|
||||
<LI> The error message is now much shorter and does not reveal
|
||||
internal STL functions.
|
||||
<LI> The presence of <tt>concept_check.hpp</tt> and
|
||||
<tt>constraints()</tt> in the error message alerts the user to the
|
||||
fact that the error lies in the user code and not in the library
|
||||
implementation.
|
||||
</UL>
|
||||
<ul>
|
||||
<li>The message refers explicitly to concepts that the user can look up
|
||||
in the STL documentation (<a href=
|
||||
"http://www.boost.org/sgi/stl/LessThanComparable.html">LessThanComparable</a>).</li>
|
||||
|
||||
<h2><a name="history">History</a></h2>
|
||||
<li>The error message is now much shorter and does not reveal
|
||||
internal STL functions, nor indeed does it even point
|
||||
to <code>std::stable_sort</code>.</li>
|
||||
|
||||
An earlier version of this concept checking system was developed by
|
||||
the author while working at SGI in their C++ compiler and library
|
||||
group. The earlier version is now part of the SGI STL distribution. The
|
||||
boost concept checking library differs from the concept checking in
|
||||
the SGI STL in that the definition of concept checking classes has
|
||||
been greatly simplified, at the price of less helpful verbiage in the
|
||||
error messages.
|
||||
<li>The presence of <tt>concept_check.hpp</tt> in the error message
|
||||
alerts the user to the fact that the error lies in the user code and not
|
||||
in the library implementation.</li>
|
||||
</ul>
|
||||
|
||||
<h2><a name="publications">Publications</a></h2>
|
||||
<h2><a name="history" id="history">History</a></h2>
|
||||
|
||||
<ul>
|
||||
<li><a href="http://www.oonumerics.org/tmpw00/">
|
||||
C++ Template Workshop 2000</a>, Concept Checking</li>
|
||||
</ul>
|
||||
<p>The first version of this concept checking system was developed
|
||||
by Jeremy Siek while working at SGI in their C++ compiler and
|
||||
library group. That version is now part of the SGI STL
|
||||
distribution. The system originally introduced as the boost concept
|
||||
checking library differs from concept checking in the SGI STL in
|
||||
that the definition of concept checking classes was greatly
|
||||
simplified, at the price of less helpful verbiage in the error
|
||||
messages. In 2006 the system was rewritten (preserving backward
|
||||
compatibility) by Dave Abrahams to be easier to use, more similar to
|
||||
the proposed concept support the C++ core language, and to give
|
||||
better error messages.
|
||||
</p>
|
||||
|
||||
<h2><a name="acknowledgements">Acknowledgements</a></h2>
|
||||
<h2><a name="publications" id="publications">Publications</a></h2>
|
||||
|
||||
The idea to use function pointers to cause instantiation is due to
|
||||
Alexander Stepanov. I am not sure of the origin of the idea to use
|
||||
expressions to do up-front checking of templates, but it did appear in
|
||||
D&E[
|
||||
<a href="bibliography.htm#stroustrup94:_design_evolution">2</a>].
|
||||
Thanks to Matt Austern for his excellent documentation and
|
||||
organization of the STL concepts, upon which these concept checks
|
||||
are based. Thanks to Boost members for helpful comments and
|
||||
reviews.
|
||||
<ul>
|
||||
<li><a href="http://www.oonumerics.org/tmpw00/">C++ Template Workshop
|
||||
2000</a>, Concept Checking</li>
|
||||
</ul>
|
||||
|
||||
<h2><a name="acknowledgements" id=
|
||||
"acknowledgements">Acknowledgements</a></h2><p>The idea to use function
|
||||
pointers to cause instantiation is due to Alexander Stepanov. We are not sure
|
||||
of the origin of the idea to use expressions to do up-front checking of
|
||||
templates, but it did appear in D&E[ <a href=
|
||||
"bibliography.htm#stroustrup94:_design_evolution">2</a>]. Thanks to Matt
|
||||
Austern for his excellent documentation and organization of the STL
|
||||
concepts, upon which these concept checks are based. Thanks to Boost
|
||||
members for helpful comments and reviews.
|
||||
|
||||
<p>
|
||||
<a href="./using_concept_check.htm">Next: Using Concept Checks</a>
|
||||
<p><a href="./using_concept_check.htm">Next: Using Concept
|
||||
Checks</a><br /></p>
|
||||
<hr />
|
||||
|
||||
<br>
|
||||
<HR>
|
||||
<TABLE>
|
||||
<TR valign=top>
|
||||
<TD nowrap>Copyright © 2000</TD><TD>
|
||||
<A HREF="../../people/jeremy_siek.htm">Jeremy Siek</A>(<A
|
||||
HREF="mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</A>)
|
||||
Andrew Lumsdaine</A>(<A HREF="mailto:lums@osl.iu.edu">lums@osl.iu.edu</A>)
|
||||
</TD></TR></TABLE>
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td nowrap="nowrap">Copyright © 2000</td>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
<td><a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</a>(<a href=
|
||||
"mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</a>) Andrew
|
||||
Lumsdaine(<a href="mailto:lums@osl.iu.edu">lums@osl.iu.edu</a>),
|
||||
2007 <a href="mailto:dave@boost-consulting.com">David Abrahams</a>.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,23 +0,0 @@
|
||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
#include <boost/concept_check.hpp>
|
||||
|
||||
/*
|
||||
|
||||
This file verifies that function_requires() of the Boost Concept
|
||||
Checking Library catches errors when it is suppose to.
|
||||
|
||||
*/
|
||||
|
||||
struct foo { };
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
boost::function_requires< boost::EqualityComparableConcept<foo> >();
|
||||
return 0;
|
||||
}
|
@ -1,999 +0,0 @@
|
||||
<HTML>
|
||||
<!--
|
||||
-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 2000
|
||||
--
|
||||
-- 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. We make no
|
||||
-- representations about the suitability of this software for any
|
||||
-- purpose. It is provided "as is" without express or implied warranty.
|
||||
-->
|
||||
<Head>
|
||||
<Title>Concept Checking</Title>
|
||||
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
|
||||
ALINK="#ff0000">
|
||||
<IMG SRC="../../c++boost.gif"
|
||||
ALT="C++ Boost" width="277" height="86">
|
||||
|
||||
<BR Clear>
|
||||
|
||||
<H1>
|
||||
<A NAME="sec:concept-checking"></A>
|
||||
header <a href="../../boost/pending/concept_checks.hpp">
|
||||
<tt>boost/concept_checks.hpp</tt></a> and <a href="../../boost/pending/concept_archetypes.hpp">
|
||||
<tt>boost/concept_archetypes.hpp</tt></a>
|
||||
</H1>
|
||||
|
||||
<p>
|
||||
Generic programming in C++ is characterized by the use of template
|
||||
parameters to represent abstract data types (or ``concepts'').
|
||||
However, the C++ language itself does not provide a mechanism for
|
||||
explicitly handling concepts. As a result, it can be difficult to
|
||||
insure that a concrete type meets the requirements of the concept it
|
||||
is supposed to represent. Error messages resulting from incorrect use
|
||||
of a concrete type can be particularly difficult to decipher. The
|
||||
Boost Concept Checking Library provides mechanisms for checking
|
||||
parameters in C++ template libraries. The mechanisms use standard C++
|
||||
and introduce no run-time overhead. The main cost of using the
|
||||
mechanism is in compile-time.
|
||||
|
||||
The documentation is organized into the following sections.
|
||||
|
||||
<OL>
|
||||
<LI><a href="#introduction">Introduction</a></LI>
|
||||
<LI><a href="#motivating-example">Motivating Example</a></LI>
|
||||
<LI><a href="#using-concept-checks">Using Concept Checks</a></LI>
|
||||
<LI><a href="#creating-concept-checks">Creating Concept Checking Classes</a></LI>
|
||||
<LI><a href="#concept-covering">Concept Covering and Archetypes</a></LI>
|
||||
<LI><a href="#programming-with-concepts">Programming With Concepts</a></LI>
|
||||
<LI><a href="#implementation">Implementation</a></LI>
|
||||
<LI><a href="#reference">Reference</a></LI>
|
||||
<OL>
|
||||
<LI><a href="#functions">Functions</a></LI>
|
||||
<LI><a href="#classes">Classes</a></LI>
|
||||
<LI><a href="#basic-concepts">Basic Concept Checking Classes</a></LI>
|
||||
<LI><a href="#iterator-concepts">Iterator Concept Checking Classes</a></LI>
|
||||
<LI><a href="#function-object-concepts">Function Object Concept Checking Classes</a></LI>
|
||||
<LI><a href="#container-concepts">Container Concept Checking Classes</a></LI>
|
||||
<LI><a href="#basic-archetype">Basic Archetype Classes</a></LI>
|
||||
<LI><a href="#iterator-archetype">Iterator Archetype Classes</a></LI>
|
||||
<LI><a href="#function-object-archetype">Function Object Archetype Classes</a></LI>
|
||||
<LI><a href="#container-archetype">Container Archetype Classes</a></LI>
|
||||
</OL>
|
||||
<LI><a href="#history">History</a></LI>
|
||||
<LI><a href="#publications">Publications</a></LI>
|
||||
<LI><a href="#acknowledgements">Acknowledgements</a></LI>
|
||||
</OL>
|
||||
|
||||
<p>
|
||||
<a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</a>
|
||||
contributed this library. X managed the formal review.
|
||||
|
||||
<h2><a name="introduction">Introduction</a></h2>
|
||||
|
||||
A <i>concept</i> is a set of requirements (valid expressions,
|
||||
associated types, semantic invariants, complexity guarantees, etc.)
|
||||
that a type must fulfill to be correctly used as arguments in a call
|
||||
to a generic algorithm. In C++, concepts are represented by formal
|
||||
template parameters to function templates (generic algorithms).
|
||||
However, C++ has no explicit mechanism for representing concepts ---
|
||||
template parameters are merely placeholders. By convention, these
|
||||
parameters are given names corresponding to the concept that is
|
||||
required, but a C++ compiler does not enforce compliance to the
|
||||
concept when the template parameter is bound to an actual type.
|
||||
|
||||
<p>
|
||||
Naturally, if a generic algorithm is invoked with a type that does not
|
||||
fulfill at least the syntactic requirements of the concept, a
|
||||
compile-time error will occur. However, this error will not <i>per
|
||||
se</i> reflect the fact that the type did not meet all of the
|
||||
requirements of the concept. Rather, the error may occur deep inside
|
||||
the instantiation hierarchy at the point where an expression is not
|
||||
valid for the type, or where a presumed associated type is not
|
||||
available. The resulting error messages are largely uninformative and
|
||||
basically impenetrable.
|
||||
|
||||
<p>
|
||||
What is required is a mechanism for enforcing ``concept safety'' at
|
||||
(or close to) the point of instantiation. The Boost Concept Checking
|
||||
Library uses some standard C++ constructs to enforce early concept
|
||||
compliance and that provides more informative error messages upon
|
||||
non-compliance.
|
||||
|
||||
<p>
|
||||
Note that this technique only addresses the syntactic
|
||||
requirements of concepts (the valid expressions and associated types).
|
||||
We do not address the semantic invariants or complexity guarantees,
|
||||
which are also part of concept requirements..
|
||||
|
||||
<h2><a name="motivating-example">Motivating Example</a></h2>
|
||||
|
||||
We present a simple example to illustrate incorrect usage of a
|
||||
template library and the resulting error messages. In the code below,
|
||||
the generic <tt>std::stable_sort()</tt> algorithm from the Standard
|
||||
Template Library (STL)[<a
|
||||
href="bibliography.html#austern99:_gener_progr_stl">3</a>, <a
|
||||
href="bibliography.html#IB-H965502">4</a>,<a
|
||||
href="bibliography.html#stepa.lee-1994:the.s:TR">5</a>] is applied to
|
||||
a linked list.
|
||||
|
||||
<pre>
|
||||
<a href="./bad_error_eg.cpp">bad_error_eg.cpp</a>:
|
||||
1 #include <list>
|
||||
2 #include <algorithm>
|
||||
3
|
||||
4 struct foo {
|
||||
5 bool operator<(const foo&) const { return false; }
|
||||
6 };
|
||||
7 int main(int, char*[]) {
|
||||
8 std::list<foo> v;
|
||||
9 std::stable_sort(v.begin(), v.end());
|
||||
10 return 0;
|
||||
11 }
|
||||
</pre>
|
||||
|
||||
Here, the
|
||||
<tt>std::stable_sort()</tt> algorithm is prototyped as follows:
|
||||
<pre>
|
||||
template <class RandomAccessIterator>
|
||||
void stable_sort(RandomAccessIterator first, RandomAccessIterator last);
|
||||
</pre>
|
||||
|
||||
Attempting to compile this code with Gnu C++ produces the following
|
||||
compiler error. The output from other compilers is listed in the
|
||||
Appendix.
|
||||
|
||||
<pre>
|
||||
stl_algo.h: In function `void __merge_sort_loop<_List_iterator
|
||||
<foo,foo &,foo *>, foo *, int>(_List_iterator<foo,foo &,foo *>,
|
||||
_List_iterator<foo,foo &,foo *>, foo *, int)':
|
||||
stl_algo.h:1448: instantiated from `__merge_sort_with_buffer
|
||||
<_List_iterator<foo,foo &,foo *>, foo *, int>(
|
||||
_List_iterator<foo,foo &,foo *>, _List_iterator<foo,foo &,foo *>,
|
||||
foo *, int *)'
|
||||
stl_algo.h:1485: instantiated from `__stable_sort_adaptive<
|
||||
_List_iterator<foo,foo &,foo *>, foo *, int>(_List_iterator
|
||||
<foo,foo &,foo *>, _List_iterator<foo,foo &,foo *>, foo *, int)'
|
||||
stl_algo.h:1524: instantiated from here
|
||||
stl_algo.h:1377: no match for `_List_iterator<foo,foo &,foo *> & -
|
||||
_List_iterator<foo,foo &,foo *> &'
|
||||
</pre>
|
||||
|
||||
In this case, the fundamental error is that
|
||||
<tt>std:list::iterator</tt> does not model the concept of <a
|
||||
href="http://www.sgi.com/Technology/STL/RandomAccessIterator.html">
|
||||
RandomAccessIterator</a>. The list iterator is only bidirectional, not
|
||||
fully random access (as would be a vector iterator). Unfortunately,
|
||||
there is nothing in the error message to indicate this to the user.
|
||||
|
||||
<p>
|
||||
To a C++ programmer having enough experience with template libraries
|
||||
the error may be obvious. However, for the uninitiated, there are several
|
||||
reasons why this message would be hard to understand.
|
||||
|
||||
<OL>
|
||||
<LI> The location of the error, line 9 of <tt>bad_error_eg.cpp</tt>
|
||||
is not pointed to by the error message, despite the fact that Gnu C++
|
||||
prints up to 4 levels deep in the instantiation stack.
|
||||
<LI> There is no textual correlation between the error message and the
|
||||
documented requirements for <tt>std::stable_sort()</tt> and for
|
||||
<a
|
||||
href="http://www.sgi.com/Technology/STL/RandomAccessIterator.html">
|
||||
RandomAccessIterator</a>.
|
||||
<LI> The error message is overly long, listing functions internal
|
||||
to the STL that the user does not (and should not!) know or care
|
||||
about.
|
||||
<LI> With so many internal library functions listed in the error
|
||||
message, the programmer could easily infer that the error is due
|
||||
to the library, rather than to his or her own code.
|
||||
</OL>
|
||||
|
||||
The following is an example of what we might expect from a more
|
||||
informative message (and is in fact what the Boost Concept Checking
|
||||
Library produces):
|
||||
|
||||
<pre>
|
||||
concept_checks.hpp: In method `void LessThanComparable_concept
|
||||
<_List_iterator<foo,foo &,foo *> >::constraints()':
|
||||
concept_checks.hpp:334: instantiated from `RandomAccessIterator_concept
|
||||
<_List_iterator<foo,foo &,foo *> >::constraints()'
|
||||
bad_error_eg.cpp:9: instantiated from `stable_sort<_List_iterator
|
||||
<foo,foo &,foo *> >(_List_iterator<foo,foo &,foo *>,
|
||||
_List_iterator<foo,foo &,foo *>)'
|
||||
concept_checks.hpp:209: no match for `_List_iterator<foo,foo &,foo *> &
|
||||
< _List_iterator<foo,foo &,foo *> &'
|
||||
</pre>
|
||||
|
||||
This message rectifies several of the shortcomings of the standard
|
||||
error messages.
|
||||
|
||||
<UL>
|
||||
<LI> The location of the error, <tt>bad_error_eg.cpp:9</tt> is
|
||||
specified in the error message.
|
||||
<LI> The message refers explicitly to concepts that the user can look
|
||||
up in the STL documentation (<a
|
||||
href="http://www.sgi.com/Technology/STL/RandomAccessIterator.html">
|
||||
RandomAccessIterator</a>).
|
||||
<LI> The error message is now much shorter and does not reveal
|
||||
internal STL functions.
|
||||
<LI> The presence of <tt>concept_checks.hpp</tt> and
|
||||
<tt>constraints()</tt> in the error message alerts the user to the
|
||||
fact that the error lies in the user code and not in the library
|
||||
implementation.
|
||||
</UL>
|
||||
|
||||
|
||||
<h2><a name="using-concept-checks">Using Concept Checks</a></h2>
|
||||
|
||||
For each concept there is a concept checking class which can be used
|
||||
to make sure that a given type (or set of types) models the concept.
|
||||
The Boost Concept Checking Library includes concept checking classes
|
||||
for all of the concepts used in the C++ standard library and a few
|
||||
more. The <a href="#reference">Reference</a> section below lists these
|
||||
concept checking classes. In addition, other boost libraries come with
|
||||
concept checking classes for the concepts that are particular to those
|
||||
libraries. An example of one of these classes is the
|
||||
<tt>EqualityComparableConcept</tt> class.
|
||||
|
||||
<pre>
|
||||
template <class T> struct EqualityComparableConcept;
|
||||
</pre>
|
||||
|
||||
Each concept checking class has a member function named
|
||||
<tt>constraints()</tt> which contains the valid expressions for the
|
||||
concept. To check whether some type, say <tt>foo</tt>, is
|
||||
EqualityComparable, we need to instantiate the concept checking class
|
||||
with foo: <tt>EqualityComparableConcept<foo></tt> and then find
|
||||
a way to get the compiler to compile the <tt>constraints()</tt>
|
||||
function without actually calling it. The Boost Concept Checking
|
||||
Library defines two utilities that make this easy:
|
||||
<tt>function_requires()</tt> and <tt>BOOST_CLASS_REQUIRES</tt>.
|
||||
<tt>function_requires()</tt> function can be used in function bodies
|
||||
and the <tt>BOOST_CLASS_REQUIRES</tt> macro can be used inside class
|
||||
bodies. The <tt>function_requires()</tt> function takes no arguments,
|
||||
but has a template parameter for the concept checking class. This
|
||||
means that the instantiated concept checking class must be given as an
|
||||
explicit template argument, as shown below.
|
||||
|
||||
<pre>
|
||||
void some_function_using_foo() {
|
||||
function_requires< EqualityComparableConcept<foo> >();
|
||||
// ...
|
||||
};
|
||||
</pre>
|
||||
|
||||
The <tt>BOOST_CLASS_REQUIRES</tt> macro can be used inside a class
|
||||
definition to check whether some type models a concept.
|
||||
|
||||
<pre>
|
||||
struct some_class_using_foo {
|
||||
BOOST_CLASS_REQUIRES(foo, EqualityComparableConcept);
|
||||
};
|
||||
</pre>
|
||||
|
||||
To add concept checks to the <tt>std::stable_sort()</tt> function the
|
||||
library implementor would simply insert <tt>function_requires()</tt>
|
||||
at the top of <tt>std::stable_sort()</tt> to make sure the template
|
||||
parameter type models <a
|
||||
href="http://www.sgi.com/Technology/STL/RandomAccessIterator.html">
|
||||
RandomAccessIterator</a>. In addition, <tt>std::stable_sort()</tt>
|
||||
requires that the <tt>value_type</tt> of the iterators be
|
||||
<a href="http://www.sgi.com/Technology/STL/LessThanComparable.html">
|
||||
LessThanComparable</a>, so we also use <tt>function_requires()</tt> to
|
||||
check this.
|
||||
|
||||
<pre>
|
||||
template <class RandomAccessIter>
|
||||
void stable_sort(RandomAccessIter first, RandomAccessIter last)
|
||||
{
|
||||
function_requires< RandomAccessIteratorConcept<RandomAccessIter> >();
|
||||
typedef typename std::iterator_traits<RandomAccessIter>::value_type value_type;
|
||||
function_requires< LessThanComparableConcept<value_type> >();
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
|
||||
|
||||
|
||||
<!-- There are a few places where the SGI STL documentation differs
|
||||
from the corresponding requirements described in the C++ Standard. In
|
||||
these cases we use the definition from the C++ Standard. -->
|
||||
|
||||
<p>
|
||||
Some concepts deal with more than one type. In this case the
|
||||
corresponding concept checking class will have multiple template
|
||||
parameters. The following example shows how
|
||||
<tt>function_requires()</tt> is used with the <a
|
||||
href="../property_map/ReadWritePropertyMap.html">ReadWritePropertyMap</a>
|
||||
concept which takes two type parameters: a property map and the key
|
||||
type for the map.
|
||||
|
||||
<pre>
|
||||
template <class IncidenceGraph, class Buffer, class BFSVisitor,
|
||||
class ColorMap>
|
||||
void breadth_first_search(IncidenceGraph& g,
|
||||
typename graph_traits<IncidenceGraph>::vertex_descriptor s,
|
||||
Buffer& Q, BFSVisitor vis, ColorMap color)
|
||||
{
|
||||
typedef typename graph_traits<IncidenceGraph>::vertex_descriptor Vertex;
|
||||
function_requires< ReadWritePropertyMap<ColorMap, Vertex> >();
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
|
||||
|
||||
As an example of using <tt>class_requires</tt> we look at a concept
|
||||
check that could be added to <tt>std::vector</tt>. One requirement
|
||||
that is placed on the element type is that it must be <a
|
||||
href="http://www.sgi.com/Technology/STL/Assignable.html">Assignable</a>.
|
||||
We can check this by inserting
|
||||
<tt>class_requires<AssignableConcept<T> ></tt> at the top
|
||||
of the definition for <tt>std::vector</tt>.
|
||||
|
||||
<pre>
|
||||
namespace std {
|
||||
template <class T>
|
||||
struct vector {
|
||||
typedef typename class_requires< AssignableConcept<T> >::check req;
|
||||
...
|
||||
};
|
||||
}
|
||||
</pre>
|
||||
|
||||
|
||||
Although the concept checks are designed for use by generic library
|
||||
implementors, they can also be useful to end users. Sometimes one may
|
||||
not be sure whether some type models a particular concept. This can
|
||||
easily be checked by creating a small program and using
|
||||
<tt>function_requires()</tt> with the type and concept in question.
|
||||
The file <a
|
||||
href="./stl_concept_checks.cpp"><tt>stl_concept_checks.cpp</tt></a>
|
||||
gives and example of applying the concept checks to STL
|
||||
containers. The file is listed here:
|
||||
|
||||
<pre>
|
||||
#include <boost/concept_checks.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <deque>
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
typedef std::vector<int> Vector;
|
||||
typedef std::deque<int> Deque;
|
||||
typedef std::list<int> List;
|
||||
|
||||
function_requires< Mutable_RandomAccessContainer<Vector> >();
|
||||
function_requires< BackInsertionSequence<Vector> >();
|
||||
|
||||
function_requires< Mutable_RandomAccessContainer<Deque> >();
|
||||
function_requires< FrontInsertionSequence<Deque> >();
|
||||
function_requires< BackInsertionSequence<Deque> >();
|
||||
|
||||
function_requires< Mutable_ReversibleContainer<List> >();
|
||||
function_requires< FrontInsertionSequence<List> >();
|
||||
function_requires< BackInsertionSequence<List> >();
|
||||
|
||||
typedef std::set<int> Set;
|
||||
typedef std::multiset<int> MultiSet;
|
||||
typedef std::map<int,int> Map;
|
||||
typedef std::multimap<int,int> MultiMap;
|
||||
|
||||
function_requires< SortedAssociativeContainer<Set> >();
|
||||
function_requires< SimpleAssociativeContainer<Set> >();
|
||||
function_requires< UniqueAssociativeContainer<Set> >();
|
||||
|
||||
function_requires< SortedAssociativeContainer<MultiSet> >();
|
||||
function_requires< SimpleAssociativeContainer<MultiSet> >();
|
||||
function_requires< MultipleAssociativeContainer<MultiSet> >();
|
||||
|
||||
function_requires< SortedAssociativeContainer<Map> >();
|
||||
function_requires< UniqueAssociativeContainer<Map> >();
|
||||
function_requires< PairAssociativeContainer<Map> >();
|
||||
|
||||
function_requires< SortedAssociativeContainer<MultiMap> >();
|
||||
function_requires< MultipleAssociativeContainer<MultiMap> >();
|
||||
function_requires< PairAssociativeContainer<MultiMap> >();
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
|
||||
|
||||
<h2><a name="creating-concept-checks">Creating Concept Checking Classes</a></h2>
|
||||
|
||||
As an example of how to create a concept checking class, we look
|
||||
at how to create the corresponding checks for the
|
||||
<a href="http://www.sgi.com/Technology/STL/RandomAccessIterator.html">
|
||||
RandomAccessIterator</a> concept. First, as a convention we name the
|
||||
concept checking class after the concept, and add the suffix
|
||||
``<tt>_concept</tt>''. Note that the <tt>REQUIRE</tt> macro expects
|
||||
the suffix to be there. Next we must define a member function named
|
||||
<tt>constraints()</tt> in which we will exercise the valid expressions
|
||||
of the concept. The <tt>REQUIRE</tt> macro expects this function's
|
||||
signature to appear exactly as it is appears below: a <tt>void</tt>
|
||||
non-const member function with no parameters.
|
||||
|
||||
<p>
|
||||
The first part of the <tt>constraints()</tt> function includes
|
||||
the requirements that correspond to the <i>refinement</i> relationship
|
||||
between <a href="http://www.sgi.com/Technology/STL/RandomAccessIterator.html">
|
||||
RandomAccessIterator</a> and the concepts which it builds upon:
|
||||
<a href="http://www.sgi.com/Technology/STL/BidirectionalIterator.html">
|
||||
BidirectionalIterator</a> and
|
||||
<a href="http://www.sgi.com/Technology/STL/LessThanComparable.html">
|
||||
LessThanComparable</a>. We could have instead used
|
||||
<tt>CLASS_REQUIRES</tt> and placed these requirements in the class
|
||||
body, however <tt>CLASS_REQUIRES</tt> uses C++ language features that
|
||||
are less portable.
|
||||
|
||||
<p>
|
||||
Next we check that the <tt>iterator_category</tt> of the iterator is
|
||||
either <tt>std::random_access_iterator_tag</tt> or a derived class.
|
||||
After that we write out some code that corresponds to the valid
|
||||
expressions of the <a
|
||||
href="http://www.sgi.com/Technology/STL/RandomAccessIterator.html">
|
||||
RandomAccessIterator</a> concept. Typedefs can also be added to
|
||||
enforce the associated types of the concept.
|
||||
|
||||
<pre>
|
||||
template <class Iter>
|
||||
struct RandomAccessIterator_concept
|
||||
{
|
||||
void constraints() {
|
||||
function_requires< BidirectionalIteratorConcept<Iter> >();
|
||||
function_requires< LessThanComparableConcept<Iter> >();
|
||||
function_requires< ConvertibleConcept<
|
||||
typename std::iterator_traits<Iter>::iterator_category,
|
||||
std::random_access_iterator_tag> >();
|
||||
|
||||
i += n;
|
||||
i = i + n; i = n + i;
|
||||
i -= n;
|
||||
i = i - n;
|
||||
n = i - j;
|
||||
i[n];
|
||||
}
|
||||
Iter a, b;
|
||||
Iter i, j;
|
||||
typename std::iterator_traits<Iter>::difference_type n;
|
||||
};
|
||||
}
|
||||
</pre>
|
||||
|
||||
One potential pitfall in designing concept checking classes is using
|
||||
more expressions in the constraint function than necessary. For
|
||||
example, it is easy to accidentally use the default constructor to
|
||||
create the objects that will be needed in the expressions (and not all
|
||||
concepts require a default constructor). This is the reason we write
|
||||
the constraint function as a member function of a class. The objects
|
||||
involved in the expressions are declared as data members of the class.
|
||||
Since objects of the constraints class template are never
|
||||
instantiated, the default constructor for the concept checking class
|
||||
is never instantiated. Hence the data member's default constructors
|
||||
are never instantiated (C++ Standard Section 14.7.1 9).
|
||||
|
||||
|
||||
<h2><a name="concept-covering">Concept Covering and Archetypes</a></h2>
|
||||
|
||||
We have discussed how it is important to select the minimal
|
||||
requirements (concepts) for the inputs to a component, but it is
|
||||
equally important to verify that the chosen concepts <i>cover</i> the
|
||||
algorithm. That is, any possible user error should be caught by the
|
||||
concept checks and not let slip through. Concept coverage can be
|
||||
verified through the use of <i>archetype classes</i>. An archetype
|
||||
class is an exact implementation of the interface associated with a
|
||||
particular concept. The run-time behavior of the archetype class is
|
||||
not important, the functions can be left empty. A simple test program
|
||||
can then be compiled with the archetype classes as the inputs to the
|
||||
component. If the program compiles then one can be sure that the
|
||||
concepts cover the component.
|
||||
|
||||
The following code shows the archetype class for the <a
|
||||
href="http://www.sgi.com/Technology/STL/trivial.html">TrivialIterator</a>
|
||||
concept. Some care must be taken to ensure that the archetype is an
|
||||
exact match to the concept. For example, the concept states that the
|
||||
return type of <tt>operator*()</tt> must be convertible to the value
|
||||
type. It does not state the more stringent requirement that the return
|
||||
type be <tt>T&</tt> or <tt>const T&</tt>. That means it would be a
|
||||
mistake to use <tt>T&</tt> or <tt>const T&</tt> for the return type
|
||||
of the archetype class. The correct approach is to create an
|
||||
artificial return type that is convertible to <tt>T</tt>, as we have
|
||||
done here with <tt>input_proxy</tt>. The validity of the archetype
|
||||
class test is completely dependent on it being an exact match with the
|
||||
concept, which must be verified by careful (manual) inspection.
|
||||
|
||||
<pre>
|
||||
template <class T>
|
||||
struct input_proxy {
|
||||
operator T() { return t; }
|
||||
static T t;
|
||||
};
|
||||
template <class T>
|
||||
class trivial_iterator_archetype
|
||||
{
|
||||
typedef trivial_iterator_archetype self;
|
||||
public:
|
||||
trivial_iterator_archetype() { }
|
||||
trivial_iterator_archetype(const self&) { }
|
||||
self& operator=(const self&) { return *this; }
|
||||
friend bool operator==(const self&, const self&) { return true; }
|
||||
friend bool operator!=(const self&, const self&) { return true; }
|
||||
input_proxy<T> operator*() { return input_proxy<T>(); }
|
||||
};
|
||||
|
||||
namespace std {
|
||||
template <class T>
|
||||
struct iterator_traits< trivial_iterator_archetype<T> >
|
||||
{
|
||||
typedef T value_type;
|
||||
};
|
||||
}
|
||||
</pre>
|
||||
|
||||
Generic algorithms are often tested by being instantiated with a
|
||||
number of common input types. For example, one might apply
|
||||
<tt>std::stable_sort()</tt> with basic pointer types as the iterators.
|
||||
Though appropriate for testing the run-time behavior of the algorithm,
|
||||
this is not helpful for ensuring concept coverage because C++ types
|
||||
never match particular concepts, they often provide much more than the
|
||||
minimal functionality required by any one concept. That is, even
|
||||
though the function template compiles with a given type, the concept
|
||||
requirements may still fall short of covering the functions actual
|
||||
requirements. This is why it is important to compile with archetype
|
||||
classes in addition to testing with common input types.
|
||||
|
||||
<p>
|
||||
The following is an excerpt from <a
|
||||
href="./stl_concept_covering.cpp"><tt>stl_concept_covering.cpp</tt></a>
|
||||
that shows how archetypes can be used to check the requirement
|
||||
documentation for
|
||||
<a href="http://www.sgi.com/Technology/STL/stable_sort.html">
|
||||
<tt>std::stable_sort()</tt></a>. In this case, it looks like the <a
|
||||
href="../utility/CopyConstructible.html">CopyConstructible</a> and <a
|
||||
href="../utility/Assignable.html">Assignable</a> requirements were
|
||||
forgotten in the SGI STL documentation (try removing those
|
||||
archetypes). The Boost archetype classes have been designed so that
|
||||
they can be layered. In this example the value type of the iterator
|
||||
is composed out of three archetypes. In the archetype class reference
|
||||
below, template parameters named <tt>Base</tt> indicate where the
|
||||
layered archetype can be used.
|
||||
|
||||
<pre>
|
||||
{
|
||||
typedef less_than_comparable_archetype<
|
||||
copy_constructible_archetype<
|
||||
assignable_archetype<> > > ValueType;
|
||||
random_access_iterator_archetype<ValueType> ri;
|
||||
std::stable_sort(ri, ri);
|
||||
}
|
||||
</pre>
|
||||
|
||||
|
||||
<h2><a name="programming-with-concepts">Programming with Concepts</a></h2>
|
||||
|
||||
The process of deciding how to group requirements into concepts and
|
||||
deciding which concepts to use in each algorithm is perhaps the most
|
||||
difficult (yet most important) part of building a generic library.
|
||||
A guiding principle to use during this process is one we
|
||||
call the <i>requirement minimization principle</i>.
|
||||
|
||||
<p>
|
||||
<b>Requirement Minimization Principle:</b> Minimize the requirements
|
||||
on the input parameters of a component to increase its reusability.
|
||||
|
||||
<p>
|
||||
There is natural tension in this statement. By definition, the input
|
||||
parameters must be used by the component in order for the component to
|
||||
accomplish its task (by ``component'' we mean a function or class
|
||||
template). The challenge then is to implement the component in such a
|
||||
way that makes the fewest assumptions (the minimum requirements) about
|
||||
the inputs while still accomplishing the task.
|
||||
|
||||
<p>
|
||||
The traditional notions of <i>abstraction</i> tie in directly to the
|
||||
idea of minimal requirements. The more abstract the input, the fewer
|
||||
the requirements. Thus, concepts are simply the embodiment of generic
|
||||
abstract data types in C++ template programming.
|
||||
|
||||
<p>
|
||||
When designing the concepts for some problem domain it is important to
|
||||
keep in mind their purpose, namely to express the requirements for the
|
||||
input to the components. With respect to the requirement minimization
|
||||
principle, this means we want to minimize concepts.
|
||||
|
||||
<p>
|
||||
It is important to note, however, that
|
||||
minimizing concepts does not mean simply
|
||||
reducing the number of valid expressions
|
||||
in the concept.
|
||||
For example, the
|
||||
<tt>std::stable_sort()</tt> function requires that the value type of
|
||||
the iterator be <a
|
||||
href="http://www.sgi.com/Technology/STL/LessThanComparable.html">
|
||||
LessThanComparable</a>, which not only
|
||||
includes <tt>operator<()</tt>, but also <tt>operator>()</tt>,
|
||||
<tt>operator<=()</tt>, and <tt>operator>=()</tt>.
|
||||
It turns out that <tt>std::stable_sort()</tt> only uses
|
||||
<tt>operator<()</tt>. The question then arises: should
|
||||
<tt>std::stable_sort()</tt> be specified in terms of the concept
|
||||
<a
|
||||
href="http://www.sgi.com/Technology/STL/LessThanComparable.html">
|
||||
LessThanComparable</a> or in terms of a concept that only
|
||||
requires <tt>operator<()</tt>?
|
||||
|
||||
<p>
|
||||
We remark first that the use of <a
|
||||
href="http://www.sgi.com/Technology/STL/LessThanComparable.html">
|
||||
LessThanComparable</a> does not really violate the requirement
|
||||
minimization principle because all of the other operators can be
|
||||
trivially implemented in terms of <tt>operator<()</tt>. By
|
||||
``trivial'' we mean one line of code and a constant run-time cost.
|
||||
More fundamentally, however, the use of <a
|
||||
href="http://www.sgi.com/Technology/STL/LessThanComparable.html">
|
||||
LessThanComparable</a> does not violate the requirement minimization
|
||||
principle because all of the comparison operators (<tt><</tt>,
|
||||
<tt>></tt>, <tt><=</tt>, <tt>>=</tt>) are conceptually equivalent (in
|
||||
a mathematical sense). Adding conceptually equivalent valid
|
||||
expressions is not a violation of the requirement minimization
|
||||
principle because no new semantics are being added --- only new
|
||||
syntax. The added syntax increases re-usability.
|
||||
|
||||
<p>
|
||||
For example,
|
||||
the
|
||||
maintainer of the <tt>std::stable_sort()</tt> may some day change the
|
||||
implementation in places to use <tt>operator>()</tt> instead of
|
||||
<tt>operator<()</tt>, since, after all, they are equivalent. Since the
|
||||
requirements are part of the public interface, such a change could
|
||||
potentially break client code. If instead
|
||||
<a
|
||||
href="http://www.sgi.com/Technology/STL/LessThanComparable.html">
|
||||
LessThanComparable</a> is given as the requirement for
|
||||
<tt>std::stable_sort()</tt>, then the maintainer is given a reasonable
|
||||
amount of flexibility within which to work.
|
||||
|
||||
<p>
|
||||
Minimality in concepts is a property associated with the underlying
|
||||
semantics of the problem domain being represented. In the problem
|
||||
domain of basic containers, requiring traversal in a single direction
|
||||
is a smaller requirement than requiring traversal in both directions
|
||||
(hence the distinction between <a
|
||||
href="http://www.sgi.com/Technology/STL/ForwardIterator.html">
|
||||
ForwardIterator</a> and
|
||||
<a
|
||||
href="http://www.sgi.com/Technology/STL/BidirectionalIterator.html">
|
||||
BidirectionalIterator</a>). The semantic difference can be easily seen
|
||||
in the difference between the set of concrete data structures that
|
||||
have forward iterators versus the set that has bidirectional
|
||||
iterators. For example, singly-linked lists would fall in the set of
|
||||
data structures having forward iterators, but not bidirectional
|
||||
iterators. In addition, the set of algorithms that one can implement
|
||||
using only forward iterators is quite different than the set that can
|
||||
be implemented with bidirectional iterators. Because of this, it is
|
||||
important to factor families of requirements into rather fine-grained
|
||||
concepts. For example, the requirements for iterators are factored
|
||||
into the six STL iterator concepts (trivial, output, input, forward,
|
||||
bidirectional, and random access).
|
||||
|
||||
|
||||
<h2><a name="implementation">Implementation</a></h2>
|
||||
|
||||
Ideally we would like to catch, and indicate, the concept violation at
|
||||
the point of instantiation. As mentioned in D&E[<a
|
||||
href="bibliography.html#stroustrup94:_design_evolution">2</a>], the error
|
||||
can be caught by exercising all of the requirements needed by the
|
||||
function template. Exactly how the requirements (the valid
|
||||
expressions in particular) are exercised is a tricky issue, since we
|
||||
want the code to be compiled --- <i>but not executed</i>. Our
|
||||
approach is to exercise the requirements in a separate function that
|
||||
is assigned to a function pointer. In this case, the compiler will
|
||||
instantiate the function but will not actually invoke it. In
|
||||
addition, an optimizing compiler will remove the pointer assignment as
|
||||
``dead code'' (though the run-time overhead added by the assignment
|
||||
would be trivial in any case). It might be conceivable for a compiler
|
||||
to skip the semantic analysis and compilation of the constraints
|
||||
function in the first place, which would make our function pointer
|
||||
technique ineffective. However, this is unlikely because removal of
|
||||
unnecessary code and functions is typically done in later stages of a
|
||||
compiler. We have successfully used the function pointer technique
|
||||
with GNU C++, Microsoft Visual C++, and several EDG-based compilers
|
||||
(KAI C++, SGI MIPSpro). The following code shows how this technique
|
||||
can be applied to the <tt>std::stable_sort()</tt> function:
|
||||
|
||||
<pre>
|
||||
template <class RandomAccessIterator>
|
||||
void stable_sort_constraints(RandomAccessIterator i) {
|
||||
typename std::iterator_traits<RandomAccessIterator>
|
||||
::difference_type n;
|
||||
i += n; // exercise the requirements for RandomAccessIterator
|
||||
...
|
||||
}
|
||||
template <class RandomAccessIterator>
|
||||
void stable_sort(RandomAccessIterator first, RandomAccessIterator last) {
|
||||
typedef void (*fptr_type)(RandomAccessIterator);
|
||||
fptr_type x = &stable_sort_constraints;
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
|
||||
There is often a large set of requirements that need to be checked,
|
||||
and it would be cumbersome for the library implementor to write
|
||||
constraint functions like <tt>stable_sort_constraints()</tt> for every
|
||||
public function. Instead, we group sets of valid expressions
|
||||
together, according to the definitions of the corresponding concepts.
|
||||
For each concept we define a concept checking class template where the
|
||||
template parameter is for the type to be checked. The class contains
|
||||
a <tt>contraints()</tt> member function which exercises all of the
|
||||
valid expressions of the concept. The objects used in the constraints
|
||||
function, such as <tt>n</tt> and <tt>i</tt>, are declared as data
|
||||
members of the concept checking class.
|
||||
|
||||
<pre>
|
||||
template <class Iter>
|
||||
struct RandomAccessIterator_concept {
|
||||
void constraints() {
|
||||
i += n;
|
||||
...
|
||||
}
|
||||
typename std::iterator_traits<RandomAccessIterator>
|
||||
::difference_type n;
|
||||
Iter i;
|
||||
...
|
||||
};
|
||||
</pre>
|
||||
|
||||
We can still use the function pointer mechanism to cause instantiation
|
||||
of the constraints function, however now it will be a member function
|
||||
pointer. To make it easy for the library implementor to invoke the
|
||||
concept checks, we wrap the member function pointer mechanism in a
|
||||
function named <tt>function_requires()</tt>. The following code
|
||||
snippet shows how to use <tt>function_requires()</tt> to make sure
|
||||
that the iterator is a
|
||||
<a
|
||||
href="http://www.sgi.com/Technology/STL/RandomAccessIterator.html">
|
||||
RandomAccessIterator</a>.
|
||||
|
||||
<pre>
|
||||
template <class RandomAccessIter>
|
||||
void stable_sort(RandomAccessIter first, RandomAccessIter last)
|
||||
{
|
||||
function_requires< RandomAccessIteratorConcept<RandomAccessIter> >();
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
|
||||
The definition of the <tt>function_requires()</tt> is as follows. The
|
||||
<tt>Concept</tt> is the concept checking class that has been
|
||||
instantiated with the modeling type. We assign the address of the
|
||||
constraints member function to the function pointer <tt>x</tt>, which
|
||||
causes the instantiation of the constraints function and checking of
|
||||
the concept's valid expressions. We then assign <tt>x</tt> to
|
||||
<tt>x</tt> to avoid unused variable compiler warnings, and wrap
|
||||
everything in a do-while loop to prevent name collisions.
|
||||
|
||||
<pre>
|
||||
template <class Concept>
|
||||
void function_requires()
|
||||
{
|
||||
void (Concept::*x)() = BOOST_FPTR Concept::constraints;
|
||||
ignore_unused_variable_warning(x);
|
||||
}
|
||||
</pre>
|
||||
|
||||
To check the type parameters of class templates, we provide the
|
||||
<tt>class_requires</tt> class which can be used inside the body of a
|
||||
class definition (whereas <tt>function_requires()</tt> can only be
|
||||
used inside of a function body). <tt>class_requires</tt> declares a
|
||||
nested class template, where the template parameter is a function
|
||||
pointer. We then use the nested class type in a typedef with the
|
||||
function pointer type of the constraint function as the template
|
||||
argument.
|
||||
|
||||
<pre>
|
||||
template <class Concept>
|
||||
class class_requires
|
||||
{
|
||||
typedef void (Concept::* function_pointer)();
|
||||
|
||||
template <function_pointer Fptr>
|
||||
struct dummy_struct { };
|
||||
public:
|
||||
typedef dummy_struct< BOOST_FPTR Concept::constraints > check;
|
||||
};
|
||||
</pre>
|
||||
|
||||
<tt>class_requires</tt> was not used in the implementation of the
|
||||
Boost Concept Checking Library concept checks because several
|
||||
compilers do not implement template parameters of function pointer
|
||||
type.
|
||||
|
||||
|
||||
|
||||
<h2><a name="reference">Reference</a></h2>
|
||||
|
||||
|
||||
<h3><a name="functions">Functions</a></h3>
|
||||
|
||||
<pre>
|
||||
template <class Concept>
|
||||
void function_requires();
|
||||
</pre>
|
||||
|
||||
<h3><a name="classes">Classes</a></h3>
|
||||
<pre>
|
||||
template <class Concept>
|
||||
struct class_requires {
|
||||
typedef ... check;
|
||||
};
|
||||
</pre>
|
||||
|
||||
<pre>
|
||||
// Make sure that <i>Type1</i> and <i>Type2</i> are exactly the same type.
|
||||
// If they are not, then the nested typedef for <tt>type</tt> will
|
||||
// not exist and cause a compiler error.
|
||||
template <class Type1, class Type2>
|
||||
struct require_same {
|
||||
typedef ... type;
|
||||
};
|
||||
// usage example
|
||||
typedef typedef require_same<int,int>::type req1; // this will compile OK
|
||||
typedef typedef require_same<int,float>::type req1; // this will cause a compiler error
|
||||
</pre>
|
||||
|
||||
<h3><a name="basic-concepts">Basic Concept Checking Classes</a></h3>
|
||||
|
||||
<pre>
|
||||
template <class T> struct Integer_concept; // Is T a built-in integer type?
|
||||
template <class T> struct SignedIntegerConcept; // Is T a built-in signed integer type?
|
||||
template <class X, class Y> struct ConvertibleConcept; // Is X convertible to Y?
|
||||
template <class T> struct AssignableConcept;
|
||||
template <class T> struct DefaultConstructibleConcept;
|
||||
template <class T> struct CopyConstructibleConcept;
|
||||
template <class T> struct BooleanConcept;
|
||||
template <class T> struct EqualityComparableConcept;
|
||||
// Is class T equality comparable on the left side with type Left?
|
||||
template <class T, class Left> struct LeftEqualityComparableConcept;
|
||||
template <class T> struct LessThanComparableConcept;
|
||||
</pre>
|
||||
|
||||
<h3><a name="iterator-concepts">Iterator Concept Checking Classes</a></h3>
|
||||
|
||||
<pre>
|
||||
template <class Iter> struct TrivialIteratorConcept;
|
||||
template <class Iter> struct Mutable_TrivialIteratorConcept;
|
||||
template <class Iter> struct InputIteratorConcept;
|
||||
template <class Iter, class T> struct OutputIteratorConcept;
|
||||
template <class Iter> struct ForwardIteratorConcept;
|
||||
template <class Iter> struct Mutable_ForwardIteratorConcept;
|
||||
template <class Iter> struct BidirectionalIteratorConcept;
|
||||
template <class Iter> struct Mutable_BidirectionalIteratorConcept;
|
||||
template <class Iter> struct RandomAccessIteratorConcept;
|
||||
template <class Iter> struct Mutable_RandomAccessIteratorConcept;
|
||||
</pre>
|
||||
|
||||
<h3><a name="function-object-concepts">Function Object Concept Checking Classes</a></h3>
|
||||
|
||||
<pre>
|
||||
template <class Func, class Return> struct GeneratorConcept;
|
||||
template <class Func, class Return, class Arg> struct UnaryFunctionConcept;
|
||||
template <class Func, class Return, class First, class Second> struct BinaryFunctionConcept;
|
||||
template <class Func, class Arg> struct UnaryPredicateConcept;
|
||||
template <class Func, class First, class Second> struct BinaryPredicateConcept;
|
||||
template <class Func, class First, class Second> struct Const_BinaryPredicateConcept {;
|
||||
</pre>
|
||||
|
||||
<h3><a name="container-concepts">Container Concept Checking Classes</a></h3>
|
||||
|
||||
<pre>
|
||||
template <class C> struct ContainerConcept;
|
||||
template <class C> struct Mutable_ContainerConcept;
|
||||
|
||||
template <class C> struct ForwardContainerConcept;
|
||||
template <class C> struct Mutable_ForwardContainerConcept;
|
||||
|
||||
template <class C> struct ReversibleContainerConcept;
|
||||
template <class C> struct Mutable_ReversibleContainerConcept;
|
||||
|
||||
template <class C> struct RandomAccessContainerConcept;
|
||||
template <class C> struct Mutable_RandomAccessContainerConcept;
|
||||
|
||||
template <class C> struct SequenceConcept;
|
||||
template <class C> struct FrontInsertionSequenceConcept;
|
||||
template <class C> struct BackInsertionSequenceConcept;
|
||||
|
||||
template <class C> struct AssociativeContainerConcept;
|
||||
template <class C> struct UniqueAssociativeContainerConcept;
|
||||
template <class C> struct MultipleAssociativeContainerConcept;
|
||||
template <class C> struct SimpleAssociativeContainerConcept;
|
||||
template <class C> struct PairAssociativeContainerConcept;
|
||||
template <class C> struct SortedAssociativeContainerConcept;
|
||||
</pre>
|
||||
|
||||
|
||||
<h3><a name="basic-archetype">Basic Archetype Classes</a></h3>
|
||||
|
||||
<pre>
|
||||
class null_archetype; // A type that models no concepts.
|
||||
template <class Base = null_archetype> class default_constructible_archetype;
|
||||
template <class Base = null_archetype> class assignable_archetype;
|
||||
template <class Base = null_archetype> class copy_constructible_archetype;
|
||||
template <class Left, class Base = null_archetype> class left_equality_comparable_archetype;
|
||||
template <class Base = null_archetype> class equality_comparable_archetype;
|
||||
template <class T, class Base = null_archetype> class convertible_to_archetype;
|
||||
</pre>
|
||||
|
||||
<h3><a name="iterator-archetype">Iterator Archetype Classes</a></h3>
|
||||
|
||||
<pre>
|
||||
template <class ValueType> class trivial_iterator_archetype;
|
||||
template <class ValueType> class mutable_trivial_iterator_archetype;
|
||||
template <class ValueType> class input_iterator_archetype;
|
||||
template <class ValueType> class forward_iterator_archetype;
|
||||
template <class ValueType> class bidirectional_iterator_archetype;
|
||||
template <class ValueType> class random_access_iterator_archetype;
|
||||
</pre>
|
||||
|
||||
<h3><a name="function-object-archetype">Function Object Archetype Classes</a></h3>
|
||||
|
||||
<pre>
|
||||
template <class Arg, class Return> class unary_function_archetype;
|
||||
template <class Arg1, class Arg2, class Return> class binary_function_archetype;
|
||||
template <class Arg> class predicate_archetype;
|
||||
template <class Arg1, class Arg2> class binary_predicate_archetype;
|
||||
</pre>
|
||||
|
||||
<h3><a name="container-archetype">Container Archetype Classes</a></h3>
|
||||
|
||||
<pre>
|
||||
UNDER CONSTRUCTION
|
||||
</pre>
|
||||
|
||||
<h2><a name="history">History</a></h2>
|
||||
|
||||
An earlier version of this concept checking system was developed by
|
||||
the author while working at SGI in their C++ compiler and library
|
||||
group. The earlier version is now part of the SGI STL distribution. The
|
||||
boost concept checking library differs from the concept checking in
|
||||
the SGI STL in that the definition of concept checking classes has
|
||||
been greatly simplified, at the price of less helpful verbiage in the
|
||||
error messages.
|
||||
|
||||
<h2><a name="publications">Publications</a></h2>
|
||||
|
||||
<ul>
|
||||
<li><a href="http://www.oonumerics.org/tmpw00/">
|
||||
C++ Template Workshop 2000</a>, Concept Checking</li>
|
||||
</ul>
|
||||
|
||||
<h2><a name="acknowledgements">Acknowledgements</a></h2>
|
||||
|
||||
The idea to use function pointers to cause instantiation is due to
|
||||
Alexander Stepanov. I am not sure of the origin of the idea to use
|
||||
expressions to do up-front checking of templates, but it did appear in
|
||||
D&E[
|
||||
<a href="bibliography.html#stroustrup94:_design_evolution">2</a>].
|
||||
Thanks to Matt Austern for his excellent documentation and
|
||||
organization of the STL concepts, upon which these concept checks
|
||||
are based. Thanks to Boost members for helpful comments and
|
||||
reviews.
|
||||
|
||||
<br>
|
||||
<HR>
|
||||
<TABLE>
|
||||
<TR valign=top>
|
||||
<TD nowrap>Copyright © 2000</TD><TD>
|
||||
<A HREF=http://www.boost.org/people/jeremy_siek.htm>Jeremy Siek</A>,
|
||||
Univ.of Notre Dame (<A
|
||||
HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>)
|
||||
</TD></TR></TABLE>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
@ -1,23 +0,0 @@
|
||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
#include <boost/pending/concept_checks.hpp>
|
||||
|
||||
/*
|
||||
|
||||
This file verifies that function_requires() of the Boost Concept
|
||||
Checking Library catches errors when it is suppose to.
|
||||
|
||||
*/
|
||||
|
||||
struct foo { };
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
boost::function_requires< boost::EqualityComparableConcept<foo> >();
|
||||
return 0;
|
||||
}
|
@ -1,185 +0,0 @@
|
||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
#include <boost/pending/concept_checks.hpp>
|
||||
#include <boost/pending/concept_archetypes.hpp>
|
||||
|
||||
/*
|
||||
|
||||
This file verifies that the BOOST_FUNCTION_REQUIRES macros of the
|
||||
Boost Concept Checking Library do not cause errors when they are not
|
||||
suppose to and verifies that the concept archetypes meet the
|
||||
requirements of their matching concepts.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
using namespace boost;
|
||||
|
||||
//===========================================================================
|
||||
// Basic Concepts
|
||||
{
|
||||
typedef default_constructible_archetype<> foo;
|
||||
function_requires< DefaultConstructibleConcept<foo> >();
|
||||
}
|
||||
{
|
||||
typedef assignable_archetype<> foo;
|
||||
function_requires< AssignableConcept<foo> >();
|
||||
}
|
||||
{
|
||||
typedef copy_constructible_archetype<> foo;
|
||||
function_requires< CopyConstructibleConcept<foo> >();
|
||||
}
|
||||
{
|
||||
typedef sgi_assignable_archetype<> foo;
|
||||
function_requires< SGIAssignableConcept<foo> >();
|
||||
}
|
||||
{
|
||||
typedef copy_constructible_archetype<> foo;
|
||||
typedef convertible_to_archetype<foo> convertible_to_foo;
|
||||
function_requires< ConvertibleConcept<convertible_to_foo, foo> >();
|
||||
}
|
||||
{
|
||||
function_requires< ConvertibleConcept<boolean_archetype, bool> >();
|
||||
}
|
||||
{
|
||||
typedef equality_comparable_archetype<> foo;
|
||||
function_requires< EqualityComparableConcept<foo> >();
|
||||
}
|
||||
{
|
||||
typedef less_than_comparable_archetype<> foo;
|
||||
function_requires< LessThanComparableConcept<foo> >();
|
||||
}
|
||||
{
|
||||
typedef comparable_archetype<> foo;
|
||||
function_requires< ComparableConcept<foo> >();
|
||||
}
|
||||
{
|
||||
typedef equal_op_first_archetype<> First;
|
||||
typedef equal_op_second_archetype<> Second;
|
||||
function_requires< EqualOpConcept<First, Second> >();
|
||||
}
|
||||
{
|
||||
typedef not_equal_op_first_archetype<> First;
|
||||
typedef not_equal_op_second_archetype<> Second;
|
||||
function_requires< NotEqualOpConcept<First, Second> >();
|
||||
}
|
||||
{
|
||||
typedef less_than_op_first_archetype<> First;
|
||||
typedef less_than_op_second_archetype<> Second;
|
||||
function_requires< LessThanOpConcept<First, Second> >();
|
||||
}
|
||||
{
|
||||
typedef less_equal_op_first_archetype<> First;
|
||||
typedef less_equal_op_second_archetype<> Second;
|
||||
function_requires< LessEqualOpConcept<First, Second> >();
|
||||
}
|
||||
{
|
||||
typedef greater_than_op_first_archetype<> First;
|
||||
typedef greater_than_op_second_archetype<> Second;
|
||||
function_requires< GreaterThanOpConcept<First, Second> >();
|
||||
}
|
||||
{
|
||||
typedef greater_equal_op_first_archetype<> First;
|
||||
typedef greater_equal_op_second_archetype<> Second;
|
||||
function_requires< GreaterEqualOpConcept<First, Second> >();
|
||||
}
|
||||
|
||||
{
|
||||
typedef copy_constructible_archetype<> Return;
|
||||
typedef plus_op_first_archetype<Return> First;
|
||||
typedef plus_op_second_archetype<Return> Second;
|
||||
function_requires< PlusOpConcept<Return, First, Second> >();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Function Object Concepts
|
||||
|
||||
{
|
||||
typedef generator_archetype<null_archetype<> > foo;
|
||||
function_requires< GeneratorConcept<foo, null_archetype<> > >();
|
||||
}
|
||||
{
|
||||
function_requires< GeneratorConcept< void_generator_archetype, void > >();
|
||||
}
|
||||
{
|
||||
typedef unary_function_archetype<int, int> F;
|
||||
function_requires< UnaryFunctionConcept<F, int, int> >();
|
||||
}
|
||||
{
|
||||
typedef binary_function_archetype<int, int, int> F;
|
||||
function_requires< BinaryFunctionConcept<F, int, int, int> >();
|
||||
}
|
||||
{
|
||||
typedef unary_predicate_archetype<int> F;
|
||||
function_requires< UnaryPredicateConcept<F, int> >();
|
||||
}
|
||||
{
|
||||
typedef binary_predicate_archetype<int, int> F;
|
||||
function_requires< BinaryPredicateConcept<F, int, int> >();
|
||||
typedef const_binary_predicate_archetype<int, int> const_F;
|
||||
function_requires< Const_BinaryPredicateConcept<const_F, int, int> >();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Iterator Concepts
|
||||
{
|
||||
typedef trivial_iterator_archetype<null_archetype<> > Iter;
|
||||
function_requires< TrivialIteratorConcept<Iter> >();
|
||||
}
|
||||
{
|
||||
typedef mutable_trivial_iterator_archetype<null_archetype<> > Iter;
|
||||
function_requires< Mutable_TrivialIteratorConcept<Iter> >();
|
||||
}
|
||||
{
|
||||
typedef input_iterator_archetype<null_archetype<> > Iter;
|
||||
function_requires< InputIteratorConcept<Iter> >();
|
||||
}
|
||||
{
|
||||
typedef output_iterator_archetype Iter;
|
||||
function_requires< OutputIteratorConcept<Iter, int> >();
|
||||
}
|
||||
{
|
||||
typedef forward_iterator_archetype<null_archetype<> > Iter;
|
||||
function_requires< ForwardIteratorConcept<Iter> >();
|
||||
}
|
||||
{
|
||||
typedef forward_iterator_archetype<assignable_archetype<> > Iter;
|
||||
function_requires< Mutable_ForwardIteratorConcept<Iter> >();
|
||||
}
|
||||
{
|
||||
typedef bidirectional_iterator_archetype<null_archetype<> > Iter;
|
||||
function_requires< BidirectionalIteratorConcept<Iter> >();
|
||||
}
|
||||
{
|
||||
typedef bidirectional_iterator_archetype<assignable_archetype<> > Iter;
|
||||
function_requires< Mutable_BidirectionalIteratorConcept<Iter> >();
|
||||
}
|
||||
{
|
||||
typedef random_access_iterator_archetype<null_archetype<> > Iter;
|
||||
function_requires< RandomAccessIteratorConcept<Iter> >();
|
||||
}
|
||||
{
|
||||
typedef random_access_iterator_archetype<assignable_archetype<> > Iter;
|
||||
function_requires< Mutable_RandomAccessIteratorConcept<Iter> >();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Container Concepts
|
||||
|
||||
{
|
||||
|
||||
function_requires< ContainerConcept< > >();
|
||||
}
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,131 +1,125 @@
|
||||
<HTML>
|
||||
<!--
|
||||
-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 2000
|
||||
--
|
||||
-- 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. We make no
|
||||
-- representations about the suitability of this software for any
|
||||
-- purpose. It is provided "as is" without express or implied warranty.
|
||||
-->
|
||||
<Head>
|
||||
<Title>Concept Covering and Archetypes</Title>
|
||||
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
|
||||
ALINK="#ff0000">
|
||||
<IMG SRC="../../c++boost.gif"
|
||||
ALT="C++ Boost" width="277" height="86">
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<BR Clear>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<!-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 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) -->
|
||||
|
||||
<h2><a name="concept-covering">Concept Covering and Archetypes</a></h2>
|
||||
<head>
|
||||
<meta name="generator" content=
|
||||
"HTML Tidy for Linux/x86 (vers 1 September 2005), see www.w3.org" />
|
||||
|
||||
We have discussed how it is important to select the minimal
|
||||
requirements (concepts) for the inputs to a component, but it is
|
||||
equally important to verify that the chosen concepts <i>cover</i> the
|
||||
algorithm. That is, any possible user error should be caught by the
|
||||
concept checks and not let slip through. Concept coverage can be
|
||||
verified through the use of <i>archetype classes</i>. An archetype
|
||||
class is an exact implementation of the interface associated with a
|
||||
particular concept. The run-time behavior of the archetype class is
|
||||
not important, the functions can be left empty. A simple test program
|
||||
can then be compiled with the archetype classes as the inputs to the
|
||||
component. If the program compiles then one can be sure that the
|
||||
concepts cover the component.
|
||||
<title>Concept Covering and Archetypes</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<link rel="stylesheet" href="../../rst.css" type="text/css" />
|
||||
</head>
|
||||
|
||||
The following code shows the archetype class for the <a
|
||||
href="http://www.sgi.com/tech/stl/trivial.html">TrivialIterator</a>
|
||||
concept. Some care must be taken to ensure that the archetype is an
|
||||
exact match to the concept. For example, the concept states that the
|
||||
return type of <tt>operator*()</tt> must be convertible to the value
|
||||
type. It does not state the more stringent requirement that the return
|
||||
type be <tt>T&</tt> or <tt>const T&</tt>. That means it would be a
|
||||
mistake to use <tt>T&</tt> or <tt>const T&</tt> for the return type
|
||||
of the archetype class. The correct approach is to create an
|
||||
artificial return type that is convertible to <tt>T</tt>, as we have
|
||||
done here with <tt>input_proxy</tt>. The validity of the archetype
|
||||
class test is completely dependent on it being an exact match with the
|
||||
concept, which must be verified by careful (manual) inspection.
|
||||
<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" />
|
||||
|
||||
<pre>
|
||||
template <class T>
|
||||
struct input_proxy {
|
||||
operator const T&() {
|
||||
return static_object<T>::get(); // Get a reference without constructing
|
||||
}
|
||||
<h2><a name="concept-covering" id="concept-covering">Concept Covering and
|
||||
Archetypes</a></h2>
|
||||
|
||||
<p>We have discussed how it is important to select the minimal requirements
|
||||
(concepts) for the inputs to a component, but it is equally important to
|
||||
verify that the chosen concepts <i>cover</i> the algorithm. That is, any
|
||||
possible user error should be caught by the concept checks and not let slip
|
||||
through. Concept coverage can be verified through the use of <i>archetype
|
||||
classes</i>. An archetype class is an exact implementation of the interface
|
||||
associated with a particular concept. The run-time behavior of the
|
||||
archetype class is not important, the functions can be left empty. A simple
|
||||
test program can then be compiled with the archetype classes as the inputs
|
||||
to the component. If the program compiles then one can be sure that the
|
||||
concepts cover the component. The following code shows the archetype class
|
||||
for the <a href="http://www.boost.org/sgi/stl/InputIterator.html">Input
|
||||
Iterator</a> concept. Some care must be taken to ensure that the archetype
|
||||
is an exact match to the concept. For example, the concept states that the
|
||||
return type of <tt>operator*()</tt> must be convertible to the value type.
|
||||
It does not state the more stringent requirement that the return type be
|
||||
<tt>T&</tt> or <tt>const T&</tt>. That means it would be a mistake
|
||||
to use <tt>T&</tt> or <tt>const T&</tt> for the return type of the
|
||||
archetype class. The correct approach is to create an artificial return
|
||||
type that is convertible to <tt>T</tt>, as we have done here with
|
||||
<tt>reference</tt>. The validity of the archetype class test is completely
|
||||
dependent on it being an exact match with the concept, which must be
|
||||
verified by careful (manual) inspection.</p>
|
||||
<pre>
|
||||
template <class T>
|
||||
class input_iterator_archetype
|
||||
{
|
||||
private:
|
||||
typedef input_iterator_archetype self;
|
||||
public:
|
||||
typedef std::input_iterator_tag iterator_category;
|
||||
typedef T value_type;
|
||||
struct reference {
|
||||
operator const value_type&() const { return static_object<T>::get(); }
|
||||
};
|
||||
template <class T>
|
||||
class trivial_iterator_archetype
|
||||
{
|
||||
typedef trivial_iterator_archetype self;
|
||||
public:
|
||||
trivial_iterator_archetype() { }
|
||||
trivial_iterator_archetype(const self&) { }
|
||||
self& operator=(const self&) { return *this; }
|
||||
friend bool operator==(const self&, const self&) { return true; }
|
||||
friend bool operator!=(const self&, const self&) { return true; }
|
||||
input_proxy<T> operator*() { return input_proxy<T>(); }
|
||||
};
|
||||
|
||||
namespace std {
|
||||
template <class T>
|
||||
struct iterator_traits< trivial_iterator_archetype<T> >
|
||||
{
|
||||
typedef T value_type;
|
||||
};
|
||||
}
|
||||
typedef const T* pointer;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
self& operator=(const self&) { return *this; }
|
||||
bool operator==(const self&) const { return true; }
|
||||
bool operator!=(const self&) const { return true; }
|
||||
reference operator*() const { return reference(); }
|
||||
self& operator++() { return *this; }
|
||||
self operator++(int) { return *this; }
|
||||
};
|
||||
</pre>
|
||||
|
||||
Generic algorithms are often tested by being instantiated with a
|
||||
number of common input types. For example, one might apply
|
||||
<tt>std::stable_sort()</tt> with basic pointer types as the iterators.
|
||||
Though appropriate for testing the run-time behavior of the algorithm,
|
||||
this is not helpful for ensuring concept coverage because C++ types
|
||||
never match particular concepts, they often provide much more than the
|
||||
minimal functionality required by any one concept. That is, even
|
||||
though the function template compiles with a given type, the concept
|
||||
requirements may still fall short of covering the functions actual
|
||||
requirements. This is why it is important to compile with archetype
|
||||
classes in addition to testing with common input types.
|
||||
<p>Generic algorithms are often tested by being instantiated with a number
|
||||
of common input types. For example, one might apply
|
||||
<tt>std::stable_sort()</tt> with basic pointer types as the iterators.
|
||||
Though appropriate for testing the run-time behavior of the algorithm, this
|
||||
is not helpful for ensuring concept coverage because C++ types never match
|
||||
particular concepts exactly. Instead, they often provide more than the
|
||||
minimal functionality required by any one concept. Even though the function
|
||||
template has concept checks, and compiles with a given type, the checks may
|
||||
still fall short of covering all the functionality that is actually used.
|
||||
This is why it is important to compile with archetype classes in addition
|
||||
to testing with common input types.</p>
|
||||
|
||||
<p>
|
||||
The following is an excerpt from <a
|
||||
href="./stl_concept_covering.cpp"><tt>stl_concept_covering.cpp</tt></a>
|
||||
that shows how archetypes can be used to check the requirement
|
||||
documentation for
|
||||
<a href="http://www.sgi.com/tech/stl/stable_sort.html">
|
||||
<tt>std::stable_sort()</tt></a>. In this case, it looks like the <a
|
||||
href="../utility/CopyConstructible.html">CopyConstructible</a> and <a
|
||||
href="../utility/Assignable.html">Assignable</a> requirements were
|
||||
forgotten in the SGI STL documentation (try removing those
|
||||
archetypes). The Boost archetype classes have been designed so that
|
||||
they can be layered. In this example the value type of the iterator
|
||||
is composed out of three archetypes. In the archetype class reference
|
||||
below, template parameters named <tt>Base</tt> indicate where the
|
||||
layered archetype can be used.
|
||||
|
||||
<pre>
|
||||
{
|
||||
typedef less_than_comparable_archetype<
|
||||
sgi_assignable_archetype<> > ValueType;
|
||||
random_access_iterator_archetype<ValueType> ri;
|
||||
std::stable_sort(ri, ri);
|
||||
}
|
||||
<p>The following is an excerpt from <a href=
|
||||
"./stl_concept_covering.cpp"><tt>stl_concept_covering.cpp</tt></a> that
|
||||
shows how archetypes can be used to check the requirement documentation for
|
||||
<a href=
|
||||
"http://www.boost.org/sgi/stl/stable_sort.html"><tt>std::stable_sort()</tt></a>.
|
||||
In this case, it looks like the <a href=
|
||||
"../utility/CopyConstructible.html">CopyConstructible</a> and <a href=
|
||||
"../utility/Assignable.html">Assignable</a> requirements were forgotten in
|
||||
the SGI STL documentation (try removing those archetypes). The Boost
|
||||
archetype classes have been designed so that they can be layered. In this
|
||||
example the value type of the iterator is composed out of three archetypes.
|
||||
In the <a href="reference.htm#basic-archetype">archetype class
|
||||
reference</a>, template parameters named <tt>Base</tt> indicate where the
|
||||
layered archetype paradigm can be used.</p>
|
||||
<pre>
|
||||
{
|
||||
typedef less_than_comparable_archetype<
|
||||
sgi_assignable_archetype<> > ValueType;
|
||||
random_access_iterator_archetype<ValueType> ri;
|
||||
std::stable_sort(ri, ri);
|
||||
}
|
||||
</pre>
|
||||
|
||||
<a href="./prog_with_concepts.htm">Next: Programming with Concepts</a><br>
|
||||
<a href="./creating_concepts.htm">Prev: Creating Concept Checking Classes</a>
|
||||
<p><a href="./prog_with_concepts.htm">Next: Programming with
|
||||
Concepts</a><br />
|
||||
<a href="./creating_concepts.htm">Prev: Creating Concept Checking
|
||||
Classes</a><br />
|
||||
<hr />
|
||||
|
||||
<br>
|
||||
<HR>
|
||||
<TABLE>
|
||||
<TR valign=top>
|
||||
<TD nowrap>Copyright © 2000</TD><TD>
|
||||
<A HREF="../../people/jeremy_siek.htm">Jeremy Siek</A>(<A
|
||||
HREF="mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</A>)
|
||||
Andrew Lumsdaine</A>(<A HREF="mailto:lums@osl.iu.edu">lums@osl.iu.edu</A>)
|
||||
</TD></TR></TABLE>
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td nowrap="nowrap">Copyright © 2000</td>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
<td><a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</a>(<a href=
|
||||
"mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</a>) Andrew
|
||||
Lumsdaine(<a href="mailto:lums@osl.iu.edu">lums@osl.iu.edu</a>),
|
||||
2007 <a href="mailto:dave@boost-consulting.com">David Abrahams</a>.
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,110 +1,157 @@
|
||||
<HTML>
|
||||
<!--
|
||||
-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 2000
|
||||
--
|
||||
-- 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. We make no
|
||||
-- representations about the suitability of this software for any
|
||||
-- purpose. It is provided "as is" without express or implied warranty.
|
||||
-->
|
||||
<Head>
|
||||
<Title>Creating Concept Checking Classes</Title>
|
||||
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
|
||||
ALINK="#ff0000">
|
||||
<IMG SRC="../../c++boost.gif"
|
||||
ALT="C++ Boost" width="277" height="86">
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<BR Clear>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<!-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 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) -->
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content=
|
||||
"HTML Tidy for Linux/x86 (vers 1 September 2005), see www.w3.org" />
|
||||
|
||||
<h2><a name="creating-concept-checks">Creating Concept Checking Classes</a></h2>
|
||||
<title>Creating Concept Checking Classes</title>
|
||||
<link rel="stylesheet" href="../../rst.css" type="text/css" />
|
||||
</head>
|
||||
|
||||
As an example of how to create a concept checking class, we look
|
||||
at how to create the corresponding checks for the
|
||||
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">
|
||||
RandomAccessIterator</a> concept. First, as a convention we name the
|
||||
concept checking class after the concept, and add the suffix
|
||||
``<tt>Concept</tt>''. Next we must define a member function named
|
||||
<tt>constraints()</tt> in which we will exercise the valid expressions
|
||||
of the concept. <tt>function_requires()</tt> expects this function's
|
||||
signature to appear exactly as it is appears below: a <tt>void</tt>
|
||||
non-const member function with no parameters.
|
||||
<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" />
|
||||
|
||||
<p>
|
||||
The first part of the <tt>constraints()</tt> function includes
|
||||
the requirements that correspond to the <i>refinement</i> relationship
|
||||
between <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">
|
||||
RandomAccessIterator</a> and the concepts which it builds upon:
|
||||
<a href="http://www.sgi.com/tech/stl/BidirectionalIterator.html">
|
||||
BidirectionalIterator</a> and
|
||||
<a href="http://www.sgi.com/tech/stl/LessThanComparable.html">
|
||||
LessThanComparable</a>. We could have instead used
|
||||
<tt>BOOST_CLASS_REQUIRE</tt> and placed these requirements in the class
|
||||
body, however <tt>BOOST_CLASS_REQUIRE</tt> uses C++ language features that
|
||||
are less portable.
|
||||
<h2><a name="creating-concept-checks" id="creating-concept-checks">Creating
|
||||
Concept Checking Classes</a></h2>
|
||||
|
||||
<p>
|
||||
Next we check that the <tt>iterator_category</tt> of the iterator is
|
||||
either <tt>std::random_access_iterator_tag</tt> or a derived class.
|
||||
After that we write out some code that corresponds to the valid
|
||||
expressions of the <a
|
||||
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">
|
||||
RandomAccessIterator</a> concept. Typedefs can also be added to
|
||||
enforce the associated types of the concept.
|
||||
<p>As an example of how to create a concept checking class template, we
|
||||
look at how to create the corresponding checks for the <a href=
|
||||
"http://www.boost.org/sgi/stl/InputIterator.html">InputIterator</a> concept.
|
||||
The complete definition is here:</p>
|
||||
<pre>
|
||||
template <class X>
|
||||
struct InputIterator
|
||||
: Assignable<X>, EqualityComparable<X>
|
||||
{
|
||||
private:
|
||||
typedef std::iterator_traits<X> t;
|
||||
public:
|
||||
typedef typename t::value_type value_type;
|
||||
typedef typename t::difference_type difference_type;
|
||||
typedef typename t::reference reference;
|
||||
typedef typename t::pointer pointer;
|
||||
typedef typename t::iterator_category iterator_category;
|
||||
|
||||
<pre>
|
||||
template <class Iter>
|
||||
struct RandomAccessIterator_concept
|
||||
{
|
||||
void constraints() {
|
||||
function_requires< BidirectionalIteratorConcept<Iter> >();
|
||||
function_requires< LessThanComparableConcept<Iter> >();
|
||||
function_requires< ConvertibleConcept<
|
||||
typename std::iterator_traits<Iter>::iterator_category,
|
||||
std::random_access_iterator_tag> >();
|
||||
|
||||
i += n;
|
||||
i = i + n; i = n + i;
|
||||
i -= n;
|
||||
i = i - n;
|
||||
n = i - j;
|
||||
i[n];
|
||||
BOOST_CONCEPT_ASSERT((SignedInteger<difference_type>));
|
||||
BOOST_CONCEPT_ASSERT((Convertible<iterator_category, std::input_iterator_tag>));
|
||||
|
||||
BOOST_CONCEPT_USAGE(InputIterator)
|
||||
{
|
||||
X j(i); <font color=
|
||||
"green">// require copy construction</font>
|
||||
same_type(*i++,v); <font color=
|
||||
"green">// require postincrement-dereference returning value_type</font>
|
||||
X& x = ++j; <font color=
|
||||
"green">// require preincrement returning X&</font>
|
||||
}
|
||||
Iter i, j;
|
||||
typename std::iterator_traits<Iter>::difference_type n;
|
||||
};
|
||||
|
||||
private:
|
||||
X i;
|
||||
value_type v;
|
||||
|
||||
<font color=
|
||||
"green">// Type deduction will fail unless the arguments have the same type.</font>
|
||||
template <typename T>
|
||||
void same_type(T const&, T const&);
|
||||
};
|
||||
</pre>
|
||||
|
||||
<h3>Walkthrough</h3>
|
||||
|
||||
<p>First, as a convention we name the concept checking class after the
|
||||
concept. Next, since InputIterator is a refinement of Assignable and
|
||||
EqualityComparable, we derive its concept checking class from the checking
|
||||
classes for those other concepts. The library will automatically check for
|
||||
conformance to Assignable and EqualityComparable whenever it checks the
|
||||
InputIterator concept.</p>
|
||||
|
||||
<p>Next, we declare the concept's <a href=
|
||||
"http://www.boost.org/more/generic_programming.html#associated_type">associated types</a>
|
||||
as member typedefs. The associated difference type is required to be a
|
||||
signed integer, and the iterator category has to be convertible to
|
||||
std::input_iterator_tag, so we assert those relationships. The syntax for
|
||||
accessing associated types through the concept-checking template mirrors
|
||||
the <a href=
|
||||
"http://www.generic-programming.org/languages/conceptcpp/">proposed</a>
|
||||
syntax for associated type access in C++0x Finally, we use the
|
||||
<code>BOOST_CONCEPT_USAGE</code> macro to declare the function that
|
||||
exercises all the concept's valid expressions. Note that at this point you
|
||||
may sometimes need to be a little creative: for example, to check that
|
||||
<code>*i++</code> returns the iterator's value type, we pass both values to
|
||||
the <code>same_type</code> member function template, which requires both
|
||||
arguments to have the same type, modulo references and cv-qualification.
|
||||
It's an imperfect check, but it's better than nothing.</p>
|
||||
|
||||
<h3>Values for Usage Patterns Should Be Data Members</h3>
|
||||
|
||||
<p>You may be wondering why we declared <code>i</code> and <code>v</code>
|
||||
as data members in the example above. Why didn't we simply write the
|
||||
following?</p>
|
||||
<pre>
|
||||
BOOST_CONCEPT_USAGE(InputIterator)
|
||||
{
|
||||
X i; <font color=
|
||||
"green">// create the values we need</font>
|
||||
value_type v;
|
||||
|
||||
X j(i); <font color=
|
||||
"green">// require copy construction</font>
|
||||
same_type(*i++,v); <font color=
|
||||
"green">// require postincrement-dereference returning value_type</font>
|
||||
X& x = ++j; <font color=
|
||||
"green">// require preincrement returning X&</font>
|
||||
}
|
||||
</pre>
|
||||
|
||||
One potential pitfall in designing concept checking classes is using
|
||||
more expressions in the constraint function than necessary. For
|
||||
example, it is easy to accidentally use the default constructor to
|
||||
create the objects that will be needed in the expressions (and not all
|
||||
concepts require a default constructor). This is the reason we write
|
||||
the constraint function as a member function of a class. The objects
|
||||
involved in the expressions are declared as data members of the class.
|
||||
Since objects of the constraints class template are never
|
||||
instantiated, the default constructor for the concept checking class
|
||||
is never instantiated. Hence the data member's default constructors
|
||||
are never instantiated (C++ Standard Section 14.7.1 9).
|
||||
<p>Unfortunately, that code wouldn't have worked out so well, because it
|
||||
unintentionally imposes the requirement that <code>X</code> and its value
|
||||
type are both default-constructible. On the other hand, since instances of
|
||||
the <code>InputIterator</code> template will never be constructed, the
|
||||
compiler never has to check how its data members will be constructed (C++
|
||||
Standard Section 14.7.1 9). For that reason you should <strong>always
|
||||
declare values needed for usage patterns as data members</strong>.</p>
|
||||
|
||||
<p>
|
||||
<a href="./concept_covering.htm">Next: Concept Covering and Archetypes</a><br>
|
||||
<a href="./using_concept_check.htm">Prev: Using Concept Checks</a>
|
||||
<p>These sorts of errors in concept definitions can be detected by the use
|
||||
of <a href="concept_covering.htm">Concept Archetypes</a>, but it's always
|
||||
better to avoid them pre-emptively.</p>
|
||||
|
||||
<h3>Similarity to Proposed C++0x Language Support for Concepts</h3>
|
||||
|
||||
<br>
|
||||
<HR>
|
||||
<TABLE>
|
||||
<TR valign=top>
|
||||
<TD nowrap>Copyright © 2000</TD><TD>
|
||||
<A HREF="../../people/jeremy_siek.htm">Jeremy Siek</A>(<A
|
||||
HREF="mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</A>)
|
||||
Andrew Lumsdaine</A>(<A HREF="mailto:lums@osl.iu.edu">lums@osl.iu.edu</A>)
|
||||
</TD></TR></TABLE>
|
||||
<p>This library's syntaxes for concept refinement and for access of
|
||||
associated types mirrors the corresponding <a href=
|
||||
"http://www.generic-programming.org/languages/conceptcpp/">proposed</a>
|
||||
syntaxes in C++0x. However, C++0x will use
|
||||
“signatures” rather than usage patterns to
|
||||
describe the valid operations on types participating in a concept, so when
|
||||
converting your concept checking classes into language-supported concepts,
|
||||
you'll need to translate your usage function into a series of
|
||||
signatures.</p>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
<p><a href="./concept_covering.htm">Next: Concept Covering and
|
||||
Archetypes</a><br />
|
||||
<a href="./using_concept_check.htm">Prev: Using Concept
|
||||
Checks</a><br /></p>
|
||||
<hr />
|
||||
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td nowrap="nowrap">Copyright © 2000</td>
|
||||
|
||||
<td><a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</a>(<a href=
|
||||
"mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</a>) Andrew
|
||||
Lumsdaine(<a href="mailto:lums@osl.iu.edu">lums@osl.iu.edu</a>),
|
||||
2007 <a href="mailto:dave@boost-consulting.com">David Abrahams</a>.
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
|
14
doc/Jamfile.v2
Normal file
14
doc/Jamfile.v2
Normal file
@ -0,0 +1,14 @@
|
||||
project boost/concepts ;
|
||||
import boostbook : boostbook ;
|
||||
|
||||
boostbook concepts : reference/concepts.xml
|
||||
:
|
||||
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html
|
||||
<xsl:param>boost.root=../../../..
|
||||
;
|
||||
|
||||
###############################################################################
|
||||
alias boostdoc ;
|
||||
explicit boostdoc ;
|
||||
alias boostrelease : concepts ;
|
||||
explicit boostrelease ;
|
59
doc/reference/Assignable.xml
Normal file
59
doc/reference/Assignable.xml
Normal file
@ -0,0 +1,59 @@
|
||||
<?xml version="1.0"?>
|
||||
<concept name="Assignable" category="Utility"><!--
|
||||
Based on concepts from the SGI Standard Template Library documentation:
|
||||
Copyright (c) 1996-1999
|
||||
Silicon Graphics Computer Systems, Inc.
|
||||
|
||||
Copyright (c) 1994
|
||||
Hewlett-Packard Company
|
||||
--><!--
|
||||
Copyright 2000-2001 University of Notre Dame du Lac.
|
||||
Copyright 2001-2002 Indiana University.
|
||||
Some concepts based on versions from the MTL draft manual and Boost Graph
|
||||
and Property Map documentation:
|
||||
Copyright (c) Jeremy Siek, Lie-Quan Lee, and Andrew Lumsdaine 2000
|
||||
-->
|
||||
<param name="X" role="assignable-type"/>
|
||||
|
||||
<models-sentence>The type <arg num="1"/> must be a model of <self/>.</models-sentence>
|
||||
|
||||
<description>
|
||||
<para>Assignable types must have copy constructors,
|
||||
<code>operator=</code> for assignment, and the <code>swap()</code>
|
||||
function defined.</para>
|
||||
</description>
|
||||
|
||||
<notation variables="x y">
|
||||
<sample-value>
|
||||
<type name="X"/>
|
||||
</sample-value>
|
||||
</notation>
|
||||
|
||||
<refines const="no" concept="CopyConstructible"/>
|
||||
|
||||
<valid-expression name="Assignment">
|
||||
<assign>
|
||||
<sample-value><reference-to><type name="X"/></reference-to></sample-value>
|
||||
<sample-value><const><reference-to><type name="X"/></reference-to></const></sample-value>
|
||||
</assign>
|
||||
<return-type>
|
||||
<require-same-type testable="yes">
|
||||
<reference-to><type name="X"/></reference-to>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
<semantics>Require <code>operator=</code></semantics>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Swap">
|
||||
<apply-function name="swap">
|
||||
<sample-value><reference-to><type name="X"/></reference-to></sample-value>
|
||||
<sample-value><reference-to><type name="X"/></reference-to></sample-value>
|
||||
</apply-function>
|
||||
<return-type><require-same-type><type name="void"/></require-same-type></return-type>
|
||||
<semantics>Require <code>swap()</code> function</semantics>
|
||||
</valid-expression>
|
||||
|
||||
<example-model>
|
||||
<type name="int"/>
|
||||
</example-model>
|
||||
</concept>
|
136
doc/reference/BidirectionalIterator.xml
Normal file
136
doc/reference/BidirectionalIterator.xml
Normal file
@ -0,0 +1,136 @@
|
||||
<?xml version="1.0"?>
|
||||
<concept name="BidirectionalIterator" category="Iterator"><!--
|
||||
Based on concepts from the SGI Standard Template Library documentation:
|
||||
Copyright (c) 1996-1999
|
||||
Silicon Graphics Computer Systems, Inc.
|
||||
|
||||
Copyright (c) 1994
|
||||
Hewlett-Packard Company
|
||||
--><!--
|
||||
Copyright 2000-2001 University of Notre Dame du Lac.
|
||||
Copyright 2001-2002 Indiana University.
|
||||
Some concepts based on versions from the MTL draft manual and Boost Graph
|
||||
and Property Map documentation:
|
||||
Copyright (c) Jeremy Siek, Lie-Quan Lee, and Andrew Lumsdaine 2000
|
||||
-->
|
||||
<param name="Iter" role="iterator-type"/>
|
||||
|
||||
<use-header name="iterator"/>
|
||||
|
||||
<models-sentence>The iterator type <arg num="1"/> must be a model of <self/>.</models-sentence>
|
||||
|
||||
<description>
|
||||
<para>A bidirectional iterator is an iterator that can read through a sequence
|
||||
of values. It can move in either direction through the sequence, and can
|
||||
be either mutable (data pointed to by it can be changed) or not mutable.</para>
|
||||
|
||||
<para>An iterator represents a position in a sequence. Therefore, the
|
||||
iterator can point into the sequence (returning a value when dereferenced
|
||||
and being incrementable), or be off-the-end (and not dereferenceable or
|
||||
incrementable).</para>
|
||||
</description>
|
||||
|
||||
<associated-type name="value_type">
|
||||
<get-member-type name="value_type">
|
||||
<apply-template name="std::iterator_traits">
|
||||
<type name="Iter"/>
|
||||
</apply-template>
|
||||
</get-member-type>
|
||||
<description><simpara>The value type of the iterator</simpara></description>
|
||||
</associated-type>
|
||||
|
||||
<refines const="no" concept="ForwardIterator"/>
|
||||
|
||||
<notation variables="i j">
|
||||
<sample-value>
|
||||
<type name="Iter"/>
|
||||
</sample-value>
|
||||
</notation>
|
||||
|
||||
<associated-type name="category">
|
||||
<get-member-type name="iterator_category">
|
||||
<apply-template name="std::iterator_traits">
|
||||
<type name="Iter"/>
|
||||
</apply-template>
|
||||
</get-member-type>
|
||||
<description><simpara>The category of the iterator</simpara></description>
|
||||
</associated-type>
|
||||
|
||||
<notation variables="x">
|
||||
<sample-value>
|
||||
<type name="value_type"/>
|
||||
</sample-value>
|
||||
</notation>
|
||||
|
||||
<valid-type-expression name="Category tag">
|
||||
<description/>
|
||||
<type name="category"/>
|
||||
<return-type>
|
||||
<derived-from testable="yes">
|
||||
<type name="std::bidirectional_iterator_tag"/>
|
||||
</derived-from>
|
||||
</return-type>
|
||||
</valid-type-expression>
|
||||
|
||||
<valid-expression name="Predecrement">
|
||||
<predecrement>
|
||||
<sample-value><reference-to><type name="Iter"/></reference-to></sample-value>
|
||||
</predecrement>
|
||||
<return-type>
|
||||
<require-same-type testable="yes">
|
||||
<reference-to><type name="Iter"/></reference-to>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
<precondition><code>i</code> is incrementable (not
|
||||
off-the-end) and some dereferenceable iterator <code>j</code> exists
|
||||
such that <code>i == ++j</code></precondition>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Postdecrement">
|
||||
<postdecrement>
|
||||
<sample-value><reference-to><type name="Iter"/></reference-to></sample-value>
|
||||
</postdecrement>
|
||||
<return-type>
|
||||
<require-same-type testable="yes"><type name="Iter"/></require-same-type>
|
||||
</return-type>
|
||||
<precondition>Same as for predecrement</precondition>
|
||||
<semantics>Equivalent to <code>{Iter j = i; --i; return j;}</code></semantics>
|
||||
<postcondition><code>i</code> is dereferenceable or
|
||||
off-the-end</postcondition>
|
||||
</valid-expression>
|
||||
|
||||
<complexity>
|
||||
All iterator operations must take amortized constant time.
|
||||
</complexity>
|
||||
|
||||
<invariant name="Predecrement must return object">
|
||||
<code>&i = &(--i)</code>
|
||||
</invariant>
|
||||
|
||||
<invariant name="Unique path through sequence">
|
||||
<code>i == j</code> implies <code>--i == --j</code>
|
||||
</invariant>
|
||||
|
||||
<invariant name="Increment and decrement are inverses">
|
||||
<code>++i; --i;</code> and <code>--i; ++i;</code> must end up with the
|
||||
value of <code>i</code> unmodified, if <code>i</code> both of the
|
||||
operations in the pair are valid.
|
||||
</invariant>
|
||||
|
||||
<example-model>
|
||||
<pointer-to>
|
||||
<type name="T"/>
|
||||
</pointer-to>
|
||||
</example-model>
|
||||
|
||||
<example-model>
|
||||
<get-member-type name="iterator">
|
||||
<apply-template name="std::list">
|
||||
<type name="T"/>
|
||||
</apply-template>
|
||||
</get-member-type>
|
||||
</example-model>
|
||||
|
||||
<see-also concept="RandomAccessIterator"/>
|
||||
|
||||
</concept>
|
47
doc/reference/CopyConstructible.xml
Normal file
47
doc/reference/CopyConstructible.xml
Normal file
@ -0,0 +1,47 @@
|
||||
<?xml version="1.0"?>
|
||||
<concept name="CopyConstructible" category="Utility"><!--
|
||||
Based on concepts from the SGI Standard Template Library documentation:
|
||||
Copyright (c) 1996-1999
|
||||
Silicon Graphics Computer Systems, Inc.
|
||||
|
||||
Copyright (c) 1994
|
||||
Hewlett-Packard Company
|
||||
--><!--
|
||||
Copyright 2000-2001 University of Notre Dame du Lac.
|
||||
Copyright 2001-2002 Indiana University.
|
||||
Some concepts based on versions from the MTL draft manual and Boost Graph
|
||||
and Property Map documentation:
|
||||
Copyright (c) Jeremy Siek, Lie-Quan Lee, and Andrew Lumsdaine 2000
|
||||
-->
|
||||
<param name="X" role="copy-constructible-type"/>
|
||||
|
||||
<models-sentence>The type <arg num="1"/> must be a model of <self/>.</models-sentence>
|
||||
|
||||
<description>
|
||||
<para>Copy constructible types must be able to be constructed from another
|
||||
member of the type.</para>
|
||||
</description>
|
||||
|
||||
<notation variables="x y">
|
||||
<sample-value>
|
||||
<type name="X"/>
|
||||
</sample-value>
|
||||
</notation>
|
||||
|
||||
<valid-expression name="Copy construction">
|
||||
<construct template-parameters="">
|
||||
<type name="X"/>
|
||||
<sample-value><const><reference-to><type name="X"/></reference-to></const></sample-value>
|
||||
</construct>
|
||||
<return-type>
|
||||
<require-same-type testable="yes">
|
||||
<type name="X"/>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
<semantics>Require copy constructor.</semantics>
|
||||
</valid-expression>
|
||||
|
||||
<example-model>
|
||||
<type name="int"/>
|
||||
</example-model>
|
||||
</concept>
|
40
doc/reference/DefaultConstructible.xml
Normal file
40
doc/reference/DefaultConstructible.xml
Normal file
@ -0,0 +1,40 @@
|
||||
<?xml version="1.0"?>
|
||||
<concept name="DefaultConstructible" category="Utility"><!--
|
||||
Based on concepts from the SGI Standard Template Library documentation:
|
||||
Copyright (c) 1996-1999
|
||||
Silicon Graphics Computer Systems, Inc.
|
||||
|
||||
Copyright (c) 1994
|
||||
Hewlett-Packard Company
|
||||
--><!--
|
||||
Copyright 2000-2001 University of Notre Dame du Lac.
|
||||
Copyright 2001-2002 Indiana University.
|
||||
Some concepts based on versions from the MTL draft manual and Boost Graph
|
||||
and Property Map documentation:
|
||||
Copyright (c) Jeremy Siek, Lie-Quan Lee, and Andrew Lumsdaine 2000
|
||||
-->
|
||||
<param name="X" role="default-constructible-type"/>
|
||||
|
||||
<models-sentence>The type <arg num="1"/> must be a model of <self/>.</models-sentence>
|
||||
|
||||
<description><para>DefaultConstructible objects only need to have a default
|
||||
constructor.</para></description>
|
||||
|
||||
<valid-expression name="Construction">
|
||||
<construct template-parameters="">
|
||||
<type name="X"/>
|
||||
</construct>
|
||||
<return-type><require-same-type testable="yes"><type name="X"/></require-same-type></return-type>
|
||||
<semantics>Construct an instance of the type with default parameters.</semantics>
|
||||
</valid-expression>
|
||||
|
||||
<example-model>
|
||||
<type name="int"/>
|
||||
</example-model>
|
||||
|
||||
<example-model>
|
||||
<apply-template name="std::vector">
|
||||
<type name="double"/>
|
||||
</apply-template>
|
||||
</example-model>
|
||||
</concept>
|
63
doc/reference/EqualityComparable.xml
Normal file
63
doc/reference/EqualityComparable.xml
Normal file
@ -0,0 +1,63 @@
|
||||
<?xml version="1.0"?>
|
||||
<concept name="EqualityComparable" category="Utility"><!--
|
||||
Based on concepts from the SGI Standard Template Library documentation:
|
||||
Copyright (c) 1996-1999
|
||||
Silicon Graphics Computer Systems, Inc.
|
||||
|
||||
Copyright (c) 1994
|
||||
Hewlett-Packard Company
|
||||
--><!--
|
||||
Copyright 2000-2001 University of Notre Dame du Lac.
|
||||
Copyright 2001-2002 Indiana University.
|
||||
Some concepts based on versions from the MTL draft manual and Boost Graph
|
||||
and Property Map documentation:
|
||||
Copyright (c) Jeremy Siek, Lie-Quan Lee, and Andrew Lumsdaine 2000
|
||||
-->
|
||||
<param name="X" role="comparable-type"/>
|
||||
|
||||
<models-sentence>The type <arg num="1"/> must be a model of
|
||||
<self/>.</models-sentence>
|
||||
|
||||
<description><para>Equality Comparable types must have <code>==</code> and
|
||||
<code>!=</code> operators.</para></description>
|
||||
|
||||
<notation variables="x y">
|
||||
<sample-value>
|
||||
<type name="X"/>
|
||||
</sample-value>
|
||||
</notation>
|
||||
|
||||
<valid-expression name="Equality test">
|
||||
<equal-to>
|
||||
<sample-value><type name="X"/></sample-value>
|
||||
<sample-value><type name="X"/></sample-value>
|
||||
</equal-to>
|
||||
<return-type>
|
||||
<convertible-to testable="yes">
|
||||
<type name="bool"/>
|
||||
</convertible-to>
|
||||
</return-type>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Inequality test">
|
||||
<not-equal-to>
|
||||
<sample-value><type name="X"/></sample-value>
|
||||
<sample-value><type name="X"/></sample-value>
|
||||
</not-equal-to>
|
||||
<return-type>
|
||||
<convertible-to testable="yes">
|
||||
<type name="bool"/>
|
||||
</convertible-to>
|
||||
</return-type>
|
||||
</valid-expression>
|
||||
|
||||
<example-model>
|
||||
<type name="int"/>
|
||||
</example-model>
|
||||
|
||||
<example-model>
|
||||
<apply-template name="std::vector">
|
||||
<type name="int"/>
|
||||
</apply-template>
|
||||
</example-model>
|
||||
</concept>
|
174
doc/reference/ForwardIterator.xml
Normal file
174
doc/reference/ForwardIterator.xml
Normal file
@ -0,0 +1,174 @@
|
||||
<?xml version="1.0"?>
|
||||
<concept name="ForwardIterator" category="Iterator"><!--
|
||||
Based on concepts from the SGI Standard Template Library documentation:
|
||||
Copyright (c) 1996-1999
|
||||
Silicon Graphics Computer Systems, Inc.
|
||||
|
||||
Copyright (c) 1994
|
||||
Hewlett-Packard Company
|
||||
--><!--
|
||||
Copyright 2000-2001 University of Notre Dame du Lac.
|
||||
Copyright 2001-2002 Indiana University.
|
||||
Some concepts based on versions from the MTL draft manual and Boost Graph
|
||||
and Property Map documentation:
|
||||
Copyright (c) Jeremy Siek, Lie-Quan Lee, and Andrew Lumsdaine 2000
|
||||
-->
|
||||
<param name="Iter" role="iterator-type"/>
|
||||
|
||||
<use-header name="iterator"/>
|
||||
|
||||
<models-sentence>The iterator type <arg num="1"/> must be a model of <self/>.</models-sentence>
|
||||
|
||||
<description>
|
||||
<para>A forward iterator is an iterator that can read through a sequence of
|
||||
values. It is multi-pass (old values of the iterator can be
|
||||
re-used), and can be either mutable (data pointed to by it can be
|
||||
changed) or not mutable.</para>
|
||||
|
||||
<para>An iterator represents a position in a sequence. Therefore, the
|
||||
iterator can point into the sequence (returning a value when dereferenced
|
||||
and being incrementable), or be off-the-end (and not dereferenceable or
|
||||
incrementable).</para>
|
||||
</description>
|
||||
|
||||
<associated-type name="value_type">
|
||||
<get-member-type name="value_type">
|
||||
<apply-template name="std::iterator_traits">
|
||||
<type name="Iter"/>
|
||||
</apply-template>
|
||||
</get-member-type>
|
||||
<description><simpara>The value type of the iterator</simpara></description>
|
||||
</associated-type>
|
||||
|
||||
<refines const="no" concept="InputIterator"/>
|
||||
<refines const="no" concept="OutputIterator"/>
|
||||
|
||||
<!-- DPG doesn't understand this
|
||||
<models const="no" testable="yes" concept="Input Iterator">
|
||||
<type name="Iter"/>
|
||||
</models>
|
||||
-->
|
||||
<!--
|
||||
<models-when-mutable concept="Output Iterator">
|
||||
<type name="Iter"/>
|
||||
<type name="value_type"/>
|
||||
</models-when-mutable>
|
||||
-->
|
||||
|
||||
<notation variables="i j">
|
||||
<sample-value>
|
||||
<type name="Iter"/>
|
||||
</sample-value>
|
||||
</notation>
|
||||
|
||||
<associated-type name="category">
|
||||
<get-member-type name="iterator_category">
|
||||
<apply-template name="std::iterator_traits">
|
||||
<type name="Iter"/>
|
||||
</apply-template>
|
||||
</get-member-type>
|
||||
<description><simpara>The category of the iterator</simpara></description>
|
||||
</associated-type>
|
||||
|
||||
<notation variables="x">
|
||||
<sample-value>
|
||||
<type name="value_type"/>
|
||||
</sample-value>
|
||||
</notation>
|
||||
|
||||
<valid-type-expression name="Category tag">
|
||||
<description/>
|
||||
<type name="category"/>
|
||||
<return-type>
|
||||
<derived-from testable="yes">
|
||||
<type name="std::forward_iterator_tag"/>
|
||||
</derived-from>
|
||||
</return-type>
|
||||
</valid-type-expression>
|
||||
|
||||
<valid-expression name="Dereference">
|
||||
<dereference>
|
||||
<sample-value><type name="Iter"/></sample-value>
|
||||
</dereference>
|
||||
<return-type>
|
||||
<require-same-type testable="yes">
|
||||
<const-if-not-mutable>
|
||||
<reference-to><type name="value_type"/></reference-to>
|
||||
</const-if-not-mutable>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
<precondition><code>i</code> is incrementable (not
|
||||
off-the-end)</precondition>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Member access">
|
||||
<pointer-member>
|
||||
<sample-value><type name="Iter"/></sample-value>
|
||||
</pointer-member>
|
||||
<return-type>
|
||||
<require-same-type testable="yes">
|
||||
<const-if-not-mutable>
|
||||
<pointer-to><type name="value_type"/></pointer-to>
|
||||
</const-if-not-mutable>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
<precondition><code>i</code> is incrementable (not
|
||||
off-the-end)</precondition>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Preincrement">
|
||||
<preincrement>
|
||||
<sample-value><reference-to><type name="Iter"/></reference-to></sample-value>
|
||||
</preincrement>
|
||||
<return-type>
|
||||
<require-same-type testable="yes">
|
||||
<reference-to><type name="Iter"/></reference-to>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
<precondition><code>i</code> is incrementable (not
|
||||
off-the-end)</precondition>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Postincrement">
|
||||
<postincrement>
|
||||
<sample-value><reference-to><type name="Iter"/></reference-to></sample-value>
|
||||
</postincrement>
|
||||
<return-type>
|
||||
<require-same-type testable="yes"><type name="Iter"/></require-same-type>
|
||||
</return-type>
|
||||
<precondition><code>i</code> is incrementable (not
|
||||
off-the-end)</precondition>
|
||||
<semantics>Equivalent to <code>{Iter j = i; ++i; return j;}</code></semantics>
|
||||
<postcondition><code>i</code> is dereferenceable or
|
||||
off-the-end</postcondition>
|
||||
</valid-expression>
|
||||
|
||||
<complexity>
|
||||
All iterator operations must take amortized constant time.
|
||||
</complexity>
|
||||
|
||||
<invariant name="Predecrement must return object">
|
||||
<code>&i = &(++i)</code>
|
||||
</invariant>
|
||||
|
||||
<invariant name="Unique path through sequence">
|
||||
<code>i == j</code> implies <code>++i == ++j</code>
|
||||
</invariant>
|
||||
|
||||
<example-model>
|
||||
<pointer-to>
|
||||
<type name="T"/>
|
||||
</pointer-to>
|
||||
</example-model>
|
||||
|
||||
<example-model>
|
||||
<get-member-type name="iterator">
|
||||
<apply-template name="std::hash_set">
|
||||
<type name="T"/>
|
||||
</apply-template>
|
||||
</get-member-type>
|
||||
</example-model>
|
||||
|
||||
<see-also concept="BidirectionalIterator"/>
|
||||
|
||||
</concept>
|
168
doc/reference/InputIterator.xml
Normal file
168
doc/reference/InputIterator.xml
Normal file
@ -0,0 +1,168 @@
|
||||
<?xml version="1.0"?>
|
||||
<concept name="InputIterator" category="Iterator"><!--
|
||||
Based on concepts from the SGI Standard Template Library documentation:
|
||||
Copyright (c) 1996-1999
|
||||
Silicon Graphics Computer Systems, Inc.
|
||||
|
||||
Copyright (c) 1994
|
||||
Hewlett-Packard Company
|
||||
--><!--
|
||||
Copyright 2000-2001 University of Notre Dame du Lac.
|
||||
Copyright 2001-2002 Indiana University.
|
||||
Some concepts based on versions from the MTL draft manual and Boost Graph
|
||||
and Property Map documentation:
|
||||
Copyright (c) Jeremy Siek, Lie-Quan Lee, and Andrew Lumsdaine 2000
|
||||
-->
|
||||
<param name="Iter" role="iterator-type"/>
|
||||
|
||||
<use-header name="iterator"/>
|
||||
|
||||
<models-sentence>The iterator type <arg num="1"/> must be a model of <self/>.</models-sentence>
|
||||
|
||||
<description>
|
||||
<para>An input iterator is an iterator that can read through a sequence of
|
||||
values. It is single-pass (old values of the iterator cannot be
|
||||
re-used), and read-only.</para>
|
||||
|
||||
<para>An input iterator represents a position in a sequence. Therefore, the
|
||||
iterator can point into the sequence (returning a value when dereferenced
|
||||
and being incrementable), or be off-the-end (and not dereferenceable or
|
||||
incrementable).</para>
|
||||
</description>
|
||||
|
||||
<refines const="no" concept="Assignable"/>
|
||||
<refines const="no" concept="DefaultConstructible"/>
|
||||
<refines const="no" concept="EqualityComparable"/>
|
||||
|
||||
<notation variables="i j">
|
||||
<sample-value>
|
||||
<type name="Iter"/>
|
||||
</sample-value>
|
||||
</notation>
|
||||
|
||||
<associated-type name="value_type">
|
||||
<get-member-type name="value_type">
|
||||
<apply-template name="std::iterator_traits">
|
||||
<type name="Iter"/>
|
||||
</apply-template>
|
||||
</get-member-type>
|
||||
<description><simpara>The value type of the iterator (not necessarily what
|
||||
<code>*i</code> returns)</simpara></description>
|
||||
</associated-type>
|
||||
|
||||
<associated-type name="difference_type">
|
||||
<get-member-type name="difference_type">
|
||||
<apply-template name="std::iterator_traits">
|
||||
<type name="Iter"/>
|
||||
</apply-template>
|
||||
</get-member-type>
|
||||
<description><simpara>The difference type of the iterator</simpara></description>
|
||||
</associated-type>
|
||||
|
||||
<associated-type name="category">
|
||||
<get-member-type name="iterator_category">
|
||||
<apply-template name="std::iterator_traits">
|
||||
<type name="Iter"/>
|
||||
</apply-template>
|
||||
</get-member-type>
|
||||
<description><simpara>The category of the iterator</simpara></description>
|
||||
</associated-type>
|
||||
|
||||
<notation variables="x">
|
||||
<sample-value>
|
||||
<type name="value_type"/>
|
||||
</sample-value>
|
||||
</notation>
|
||||
|
||||
<valid-type-expression name="Category tag">
|
||||
<description/>
|
||||
<type name="category"/>
|
||||
<return-type>
|
||||
<derived-from testable="yes">
|
||||
<type name="std::input_iterator_tag"/>
|
||||
</derived-from>
|
||||
<models-as-first-arg const="no" testable="yes" concept="DefaultConstructible"/>
|
||||
<models-as-first-arg const="no" testable="yes" concept="CopyConstructible"/>
|
||||
</return-type>
|
||||
</valid-type-expression>
|
||||
|
||||
<valid-type-expression name="Value type copy constructibility">
|
||||
<description/>
|
||||
<type name="value_type"/>
|
||||
<return-type>
|
||||
<models-as-first-arg const="no" testable="yes" concept="CopyConstructible"/>
|
||||
</return-type>
|
||||
</valid-type-expression>
|
||||
|
||||
<valid-type-expression name="Difference type properties">
|
||||
<description/>
|
||||
<type name="difference_type"/>
|
||||
<return-type>
|
||||
<models-as-first-arg const="no" testable="yes" concept="SignedInteger"/>
|
||||
</return-type>
|
||||
</valid-type-expression>
|
||||
|
||||
<valid-expression name="Dereference">
|
||||
<dereference>
|
||||
<sample-value><type name="Iter"/></sample-value>
|
||||
</dereference>
|
||||
<return-type>
|
||||
<convertible-to testable="yes"><type name="value_type"/></convertible-to>
|
||||
</return-type>
|
||||
<precondition><code>i</code> is incrementable (not
|
||||
off-the-end)</precondition>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Preincrement">
|
||||
<preincrement>
|
||||
<sample-value><reference-to><type name="Iter"/></reference-to></sample-value>
|
||||
</preincrement>
|
||||
<return-type>
|
||||
<require-same-type testable="yes">
|
||||
<reference-to><type name="Iter"/></reference-to>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
<precondition><code>i</code> is incrementable (not
|
||||
off-the-end)</precondition>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Postincrement">
|
||||
<postincrement>
|
||||
<sample-value><reference-to><type name="Iter"/></reference-to></sample-value>
|
||||
</postincrement>
|
||||
<return-type/>
|
||||
<precondition><code>i</code> is incrementable (not
|
||||
off-the-end)</precondition>
|
||||
<semantics>Equivalent to <code>(void)(++i)</code></semantics>
|
||||
<postcondition><code>i</code> is dereferenceable or
|
||||
off-the-end</postcondition>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Postincrement and dereference">
|
||||
<dereference>
|
||||
<postincrement>
|
||||
<sample-value><reference-to><type name="Iter"/></reference-to></sample-value>
|
||||
</postincrement>
|
||||
</dereference>
|
||||
<return-type>
|
||||
<convertible-to testable="yes"><type name="value_type"/></convertible-to>
|
||||
</return-type>
|
||||
<precondition><code>i</code> is incrementable (not
|
||||
off-the-end)</precondition>
|
||||
<semantics>Equivalent to <code>{value_type t = *i; ++i; return t;}</code></semantics>
|
||||
<postcondition><code>i</code> is dereferenceable or
|
||||
off-the-end</postcondition>
|
||||
</valid-expression>
|
||||
|
||||
<complexity>
|
||||
All iterator operations must take amortized constant time.
|
||||
</complexity>
|
||||
|
||||
<example-model>
|
||||
<type name="std::istream_iterator"/>
|
||||
</example-model>
|
||||
|
||||
<see-also concept="OutputIterator"/>
|
||||
<see-also concept="ForwardIterator"/>
|
||||
|
||||
</concept>
|
81
doc/reference/LessThanComparable.xml
Normal file
81
doc/reference/LessThanComparable.xml
Normal file
@ -0,0 +1,81 @@
|
||||
<?xml version="1.0"?>
|
||||
<concept name="LessThanComparable" category="Utility"><!--
|
||||
Based on concepts from the SGI Standard Template Library documentation:
|
||||
Copyright (c) 1996-1999
|
||||
Silicon Graphics Computer Systems, Inc.
|
||||
|
||||
Copyright (c) 1994
|
||||
Hewlett-Packard Company
|
||||
--><!--
|
||||
Copyright 2000-2001 University of Notre Dame du Lac.
|
||||
Copyright 2001-2002 Indiana University.
|
||||
Some concepts based on versions from the MTL draft manual and Boost Graph
|
||||
and Property Map documentation:
|
||||
Copyright (c) Jeremy Siek, Lie-Quan Lee, and Andrew Lumsdaine 2000
|
||||
-->
|
||||
<param name="X" role="comparable-type"/>
|
||||
|
||||
<models-sentence>The type <arg num="1"/> must be a model of <self/>.</models-sentence>
|
||||
|
||||
<description><para>LessThanComparable types must have <code><</code>,
|
||||
<code>></code>, <code><=</code>, and <code>>=</code>
|
||||
operators.</para></description>
|
||||
|
||||
<notation variables="x y"><sample-value><type name="X"/></sample-value></notation>
|
||||
|
||||
<valid-expression name="Less than">
|
||||
<less-than>
|
||||
<sample-value><type name="X"/></sample-value>
|
||||
<sample-value><type name="X"/></sample-value>
|
||||
</less-than>
|
||||
<return-type>
|
||||
<convertible-to testable="yes">
|
||||
<type name="bool"/>
|
||||
</convertible-to>
|
||||
</return-type>
|
||||
<semantics>Determine if one value is less than another.</semantics>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Less than or equal">
|
||||
<less-than-or-equal>
|
||||
<sample-value><type name="X"/></sample-value>
|
||||
<sample-value><type name="X"/></sample-value>
|
||||
</less-than-or-equal>
|
||||
<return-type>
|
||||
<convertible-to testable="yes">
|
||||
<type name="bool"/>
|
||||
</convertible-to>
|
||||
</return-type>
|
||||
<semantics>Determine if one value is less than or equal to another.</semantics>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Greater than">
|
||||
<greater-than>
|
||||
<sample-value><type name="X"/></sample-value>
|
||||
<sample-value><type name="X"/></sample-value>
|
||||
</greater-than>
|
||||
<return-type>
|
||||
<convertible-to testable="yes">
|
||||
<type name="bool"/>
|
||||
</convertible-to>
|
||||
</return-type>
|
||||
<semantics>Determine if one value is greater than another.</semantics>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Greater than or equal to">
|
||||
<greater-than-or-equal>
|
||||
<sample-value><type name="X"/></sample-value>
|
||||
<sample-value><type name="X"/></sample-value>
|
||||
</greater-than-or-equal>
|
||||
<return-type>
|
||||
<convertible-to testable="yes">
|
||||
<type name="bool"/>
|
||||
</convertible-to>
|
||||
</return-type>
|
||||
<semantics>Determine if one value is greater than or equal to another.</semantics>
|
||||
</valid-expression>
|
||||
|
||||
<example-model>
|
||||
<type name="int"/>
|
||||
</example-model>
|
||||
</concept>
|
203
doc/reference/OutputIterator.xml
Normal file
203
doc/reference/OutputIterator.xml
Normal file
@ -0,0 +1,203 @@
|
||||
<?xml version="1.0"?>
|
||||
<concept name="OutputIterator" category="Iterator"><!--
|
||||
Based on concepts from the SGI Standard Template Library documentation:
|
||||
Copyright (c) 1996-1999
|
||||
Silicon Graphics Computer Systems, Inc.
|
||||
|
||||
Copyright (c) 1994
|
||||
Hewlett-Packard Company
|
||||
--><!--
|
||||
Copyright 2000-2001 University of Notre Dame du Lac.
|
||||
Copyright 2001-2002 Indiana University.
|
||||
Some concepts based on versions from the MTL draft manual and Boost Graph
|
||||
and Property Map documentation:
|
||||
Copyright (c) Jeremy Siek, Lie-Quan Lee, and Andrew Lumsdaine 2000
|
||||
-->
|
||||
<param name="Iter" role="iterator-type"/>
|
||||
<param name="ValueType" role="value-type"/>
|
||||
|
||||
<use-header name="iterator"/>
|
||||
|
||||
<models-sentence>The iterator type <arg num="1"/> (with value type <arg num="2"/>) must be a model of <self/>.</models-sentence>
|
||||
|
||||
<description>
|
||||
<para>An output iterator is an iterator that can write a sequence of
|
||||
values. It is single-pass (old values of the iterator cannot be
|
||||
re-used), and write-only.</para>
|
||||
|
||||
<para>An output iterator represents a position in a (possibly infinite)
|
||||
sequence. Therefore, the iterator can point into the sequence (returning
|
||||
a value when dereferenced and being incrementable), or be off-the-end
|
||||
(and not dereferenceable or incrementable).</para>
|
||||
</description>
|
||||
|
||||
<models const="no" testable="yes" concept="Assignable">
|
||||
<type name="Iter"/>
|
||||
</models>
|
||||
|
||||
<models const="no" testable="yes" concept="Assignable">
|
||||
<type name="ValueType"/>
|
||||
</models>
|
||||
|
||||
<models const="no" testable="yes" concept="DefaultConstructible">
|
||||
<type name="Iter"/>
|
||||
</models>
|
||||
|
||||
<models const="no" testable="yes" concept="EqualityComparable">
|
||||
<type name="Iter"/>
|
||||
</models>
|
||||
|
||||
<associated-type name="value_type">
|
||||
<get-member-type name="value_type">
|
||||
<apply-template name="std::iterator_traits">
|
||||
<type name="Iter"/>
|
||||
</apply-template>
|
||||
</get-member-type>
|
||||
<description><simpara>The stated value type of the iterator (should be
|
||||
<code>void</code> for an output iterator that does not model some other
|
||||
iterator concept).</simpara></description>
|
||||
</associated-type>
|
||||
|
||||
<associated-type name="difference_type">
|
||||
<get-member-type name="difference_type">
|
||||
<apply-template name="std::iterator_traits">
|
||||
<type name="Iter"/>
|
||||
</apply-template>
|
||||
</get-member-type>
|
||||
<description><simpara>The difference type of the iterator</simpara></description>
|
||||
</associated-type>
|
||||
|
||||
<associated-type name="category">
|
||||
<get-member-type name="iterator_category">
|
||||
<apply-template name="std::iterator_traits">
|
||||
<type name="Iter"/>
|
||||
</apply-template>
|
||||
</get-member-type>
|
||||
<description><simpara>The category of the iterator</simpara></description>
|
||||
</associated-type>
|
||||
|
||||
<notation variables="i j">
|
||||
<sample-value>
|
||||
<type name="Iter"/>
|
||||
</sample-value>
|
||||
</notation>
|
||||
|
||||
<notation variables="x">
|
||||
<sample-value>
|
||||
<type name="ValueType"/>
|
||||
</sample-value>
|
||||
</notation>
|
||||
|
||||
<valid-type-expression name="Category tag">
|
||||
<description/>
|
||||
<type name="category"/>
|
||||
<return-type>
|
||||
<derived-from testable="yes">
|
||||
<type name="std::output_iterator_tag"/>
|
||||
</derived-from>
|
||||
<models-as-first-arg const="no" testable="yes" concept="DefaultConstructible"/>
|
||||
<models-as-first-arg const="no" testable="yes" concept="CopyConstructible"/>
|
||||
</return-type>
|
||||
</valid-type-expression>
|
||||
|
||||
<valid-type-expression name="Difference type properties">
|
||||
<description/>
|
||||
<type name="difference_type"/>
|
||||
<return-type>
|
||||
<models-as-first-arg const="no" testable="yes" concept="SignedInteger"/>
|
||||
</return-type>
|
||||
</valid-type-expression>
|
||||
|
||||
<valid-expression name="Dereference">
|
||||
<dereference>
|
||||
<sample-value><type name="Iter"/></sample-value>
|
||||
</dereference>
|
||||
<return-type/>
|
||||
<precondition><code>i</code> is incrementable (not
|
||||
off-the-end)</precondition>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Dereference and assign">
|
||||
<assign>
|
||||
<dereference>
|
||||
<sample-value><type name="Iter"/></sample-value>
|
||||
</dereference>
|
||||
<sample-value><const><reference-to><type name="ValueType"/></reference-to></const></sample-value>
|
||||
</assign>
|
||||
<return-type/>
|
||||
<precondition><code>i</code> is incrementable (not
|
||||
off-the-end)</precondition>
|
||||
<postcondition><code>*i</code> may not be written to again until it has
|
||||
been incremented.</postcondition>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Preincrement">
|
||||
<preincrement>
|
||||
<sample-value><reference-to><type name="Iter"/></reference-to></sample-value>
|
||||
</preincrement>
|
||||
<return-type>
|
||||
<require-same-type testable="yes">
|
||||
<reference-to><type name="Iter"/></reference-to>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
<precondition><code>i</code> is incrementable (not
|
||||
off-the-end)</precondition>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Postincrement">
|
||||
<postincrement>
|
||||
<sample-value><reference-to><type name="Iter"/></reference-to></sample-value>
|
||||
</postincrement>
|
||||
<return-type/>
|
||||
<precondition><code>i</code> is incrementable (not
|
||||
off-the-end)</precondition>
|
||||
<semantics>Equivalent to <code>(void)(++i)</code></semantics>
|
||||
<postcondition><code>i</code> is dereferenceable or
|
||||
off-the-end</postcondition>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Postincrement, dereference, and assign">
|
||||
<assign>
|
||||
<dereference>
|
||||
<postincrement>
|
||||
<sample-value><reference-to><type name="Iter"/></reference-to></sample-value>
|
||||
</postincrement>
|
||||
</dereference>
|
||||
<sample-value><const><reference-to><type name="ValueType"/></reference-to></const></sample-value>
|
||||
</assign>
|
||||
<return-type/>
|
||||
<precondition><code>i</code> is incrementable (not
|
||||
off-the-end)</precondition>
|
||||
<semantics>Equivalent to <code>{*i = t; ++i;}</code></semantics>
|
||||
<postcondition><code>i</code> is dereferenceable or
|
||||
off-the-end</postcondition>
|
||||
</valid-expression>
|
||||
|
||||
<complexity>
|
||||
All iterator operations must take amortized constant time.
|
||||
</complexity>
|
||||
|
||||
<example-model>
|
||||
<type name="std::ostream_iterator"/>
|
||||
<type name="..."/>
|
||||
</example-model>
|
||||
|
||||
<example-model>
|
||||
<type name="std::insert_iterator"/>
|
||||
<type name="..."/>
|
||||
</example-model>
|
||||
|
||||
<example-model>
|
||||
<type name="std::front_insert_iterator"/>
|
||||
<type name="..."/>
|
||||
</example-model>
|
||||
|
||||
<example-model>
|
||||
<type name="std::back_insert_iterator"/>
|
||||
<type name="..."/>
|
||||
</example-model>
|
||||
|
||||
<see-also concept="InputIterator"/>
|
||||
<see-also concept="ForwardIterator"/>
|
||||
|
||||
</concept>
|
313
doc/reference/RandomAccessIterator.xml
Normal file
313
doc/reference/RandomAccessIterator.xml
Normal file
@ -0,0 +1,313 @@
|
||||
<?xml version="1.0"?>
|
||||
<concept name="RandomAccessIterator" category="Iterator"><!--
|
||||
Based on concepts from the SGI Standard Template Library documentation:
|
||||
Copyright (c) 1996-1999
|
||||
Silicon Graphics Computer Systems, Inc.
|
||||
|
||||
Copyright (c) 1994
|
||||
Hewlett-Packard Company
|
||||
--><!--
|
||||
Copyright 2000-2001 University of Notre Dame du Lac.
|
||||
Copyright 2001-2002 Indiana University.
|
||||
Some concepts based on versions from the MTL draft manual and Boost Graph
|
||||
and Property Map documentation:
|
||||
Copyright (c) Jeremy Siek, Lie-Quan Lee, and Andrew Lumsdaine 2000
|
||||
-->
|
||||
<param name="Iter" role="iterator-type"/>
|
||||
|
||||
<use-header name="iterator"/>
|
||||
|
||||
<models-sentence>The iterator type <arg num="1"/> must be a model of <self/>.</models-sentence>
|
||||
|
||||
<description>
|
||||
<para>A random access iterator is an iterator that can read through
|
||||
a sequence of values. It can move in either direction through the
|
||||
sequence (by any amount in constant time), and can be either mutable
|
||||
(data pointed to by it can be changed) or not mutable.</para>
|
||||
|
||||
<para>An iterator represents a position in a sequence. Therefore,
|
||||
the iterator can point into the sequence (returning a value when
|
||||
dereferenced and being incrementable), or be off-the-end (and not
|
||||
dereferenceable or incrementable).</para>
|
||||
</description>
|
||||
|
||||
<associated-type name="value_type">
|
||||
<get-member-type name="value_type">
|
||||
<apply-template name="std::iterator_traits">
|
||||
<type name="Iter"/>
|
||||
</apply-template>
|
||||
</get-member-type>
|
||||
<description><simpara>The value type of the iterator</simpara></description>
|
||||
</associated-type>
|
||||
|
||||
<refines const="no" concept="BidirectionalIterator"/>
|
||||
<refines const="no" concept="LessThanComparable"/>
|
||||
|
||||
<notation variables="i j">
|
||||
<sample-value>
|
||||
<type name="Iter"/>
|
||||
</sample-value>
|
||||
</notation>
|
||||
|
||||
<associated-type name="category">
|
||||
<get-member-type name="iterator_category">
|
||||
<apply-template name="std::iterator_traits">
|
||||
<type name="Iter"/>
|
||||
</apply-template>
|
||||
</get-member-type>
|
||||
<description><simpara>The category of the iterator</simpara></description>
|
||||
</associated-type>
|
||||
|
||||
<associated-type name="difference_type">
|
||||
<get-member-type name="difference_type">
|
||||
<apply-template name="std::iterator_traits">
|
||||
<type name="Iter"/>
|
||||
</apply-template>
|
||||
</get-member-type>
|
||||
<description><simpara>The difference type of the iterator (measure of the number
|
||||
of steps between two iterators)</simpara></description>
|
||||
</associated-type>
|
||||
|
||||
<notation variables="x">
|
||||
<sample-value>
|
||||
<type name="value_type"/>
|
||||
</sample-value>
|
||||
</notation>
|
||||
|
||||
<notation variables="n">
|
||||
<sample-value>
|
||||
<type name="difference_type"/>
|
||||
</sample-value>
|
||||
</notation>
|
||||
|
||||
<notation variables="int_off">
|
||||
<sample-value>
|
||||
<type name="int"/>
|
||||
</sample-value>
|
||||
</notation>
|
||||
|
||||
<valid-type-expression name="Category tag">
|
||||
<description/>
|
||||
<type name="category"/>
|
||||
<return-type>
|
||||
<derived-from testable="yes">
|
||||
<type name="std::random_access_iterator_tag"/>
|
||||
</derived-from>
|
||||
</return-type>
|
||||
</valid-type-expression>
|
||||
|
||||
<valid-expression name="Motion">
|
||||
<add-assign>
|
||||
<sample-value><reference-to><type name="Iter"/></reference-to></sample-value>
|
||||
<sample-value><type name="difference_type"/></sample-value>
|
||||
</add-assign>
|
||||
<return-type>
|
||||
<require-same-type testable="yes">
|
||||
<reference-to><type name="Iter"/></reference-to>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
<semantics>Equivalent to applying <code>i++</code> <code>n</code> times
|
||||
if <code>n</code> is positive, applying <code>i--</code>
|
||||
<code>-n</code> times if <code>n</code> is negative, and to a null
|
||||
operation if <code>n</code> is zero.</semantics>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Motion (with integer offset)">
|
||||
<add-assign>
|
||||
<sample-value><reference-to><type name="Iter"/></reference-to></sample-value>
|
||||
<sample-value><type name="int"/></sample-value>
|
||||
</add-assign>
|
||||
<return-type>
|
||||
<require-same-type testable="yes">
|
||||
<reference-to><type name="Iter"/></reference-to>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
<semantics>Equivalent to applying <code>i++</code> <code>n</code> times
|
||||
if <code>n</code> is positive, applying <code>i--</code>
|
||||
<code>-n</code> times if <code>n</code> is negative, and to a null
|
||||
operation if <code>n</code> is zero.</semantics>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Subtractive motion">
|
||||
<subtract-assign>
|
||||
<sample-value><reference-to><type name="Iter"/></reference-to></sample-value>
|
||||
<sample-value><type name="difference_type"/></sample-value>
|
||||
</subtract-assign>
|
||||
<return-type>
|
||||
<require-same-type testable="yes">
|
||||
<reference-to><type name="Iter"/></reference-to>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
<semantics>Equivalent to <code>i+=(-n)</code></semantics>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Subtractive motion (with integer offset)">
|
||||
<subtract-assign>
|
||||
<sample-value><reference-to><type name="Iter"/></reference-to></sample-value>
|
||||
<sample-value><type name="int"/></sample-value>
|
||||
</subtract-assign>
|
||||
<return-type>
|
||||
<require-same-type testable="yes">
|
||||
<reference-to><type name="Iter"/></reference-to>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
<semantics>Equivalent to <code>i+=(-n)</code></semantics>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Addition">
|
||||
<add>
|
||||
<sample-value><type name="Iter"/></sample-value>
|
||||
<sample-value><type name="difference_type"/></sample-value>
|
||||
</add>
|
||||
<return-type>
|
||||
<require-same-type testable="yes"><type name="Iter"/></require-same-type>
|
||||
</return-type>
|
||||
<semantics>Equivalent to <code>{Iter j = i; j += n; return j;}</code></semantics>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Addition with integer">
|
||||
<add>
|
||||
<sample-value><type name="Iter"/></sample-value>
|
||||
<sample-value><type name="int"/></sample-value>
|
||||
</add>
|
||||
<return-type>
|
||||
<require-same-type testable="yes"><type name="Iter"/></require-same-type>
|
||||
</return-type>
|
||||
<semantics>Equivalent to <code>{Iter j = i; j += n; return j;}</code></semantics>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Addition (count first)">
|
||||
<add>
|
||||
<sample-value><type name="difference_type"/></sample-value>
|
||||
<sample-value><type name="Iter"/></sample-value>
|
||||
</add>
|
||||
<return-type>
|
||||
<require-same-type testable="yes"><type name="Iter"/></require-same-type>
|
||||
</return-type>
|
||||
<semantics>Equivalent to <code>i + n</code></semantics>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Addition with integer (count first)">
|
||||
<add>
|
||||
<sample-value><type name="int"/></sample-value>
|
||||
<sample-value><type name="Iter"/></sample-value>
|
||||
</add>
|
||||
<return-type>
|
||||
<require-same-type testable="yes"><type name="Iter"/></require-same-type>
|
||||
</return-type>
|
||||
<semantics>Equivalent to <code>i + n</code></semantics>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Subtraction">
|
||||
<subtract>
|
||||
<sample-value><type name="Iter"/></sample-value>
|
||||
<sample-value><type name="difference_type"/></sample-value>
|
||||
</subtract>
|
||||
<return-type>
|
||||
<require-same-type testable="yes"><type name="Iter"/></require-same-type>
|
||||
</return-type>
|
||||
<semantics>Equivalent to <code>i + (-n)</code></semantics>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Subtraction with integer">
|
||||
<subtract>
|
||||
<sample-value><type name="Iter"/></sample-value>
|
||||
<sample-value><type name="int"/></sample-value>
|
||||
</subtract>
|
||||
<return-type>
|
||||
<require-same-type testable="yes"><type name="Iter"/></require-same-type>
|
||||
</return-type>
|
||||
<semantics>Equivalent to <code>i + (-n)</code></semantics>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Distance">
|
||||
<subtract>
|
||||
<sample-value><type name="Iter"/></sample-value>
|
||||
<sample-value><type name="Iter"/></sample-value>
|
||||
</subtract>
|
||||
<return-type>
|
||||
<require-same-type testable="yes"><type name="difference_type"/></require-same-type>
|
||||
</return-type>
|
||||
<semantics>The number of times <code>i</code> must be incremented (or
|
||||
decremented if the result is negative) to reach <code>j</code>. Not
|
||||
defined if <code>j</code> is not reachable from
|
||||
<code>i</code>.</semantics>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Element access">
|
||||
<subscript>
|
||||
<sample-value><type name="Iter"/></sample-value>
|
||||
<sample-value><type name="difference_type"/></sample-value>
|
||||
</subscript>
|
||||
<return-type>
|
||||
<require-same-type testable="yes">
|
||||
<const-if-not-mutable>
|
||||
<reference-to>
|
||||
<type name="value_type"/>
|
||||
</reference-to>
|
||||
</const-if-not-mutable>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
<semantics>Equivalent to <code>*(i + n)</code></semantics>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Element access with integer index">
|
||||
<subscript>
|
||||
<sample-value><type name="Iter"/></sample-value>
|
||||
<sample-value><type name="int"/></sample-value>
|
||||
</subscript>
|
||||
<return-type>
|
||||
<require-same-type testable="yes">
|
||||
<const-if-not-mutable>
|
||||
<reference-to>
|
||||
<type name="value_type"/>
|
||||
</reference-to>
|
||||
</const-if-not-mutable>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
<semantics>Equivalent to <code>*(i + n)</code></semantics>
|
||||
</valid-expression>
|
||||
|
||||
<complexity>
|
||||
All iterator operations must take amortized constant time.
|
||||
</complexity>
|
||||
|
||||
<example-model>
|
||||
<pointer-to>
|
||||
<type name="T"/>
|
||||
</pointer-to>
|
||||
</example-model>
|
||||
|
||||
<example-model>
|
||||
<get-member-type name="iterator">
|
||||
<apply-template name="std::vector">
|
||||
<type name="T"/>
|
||||
</apply-template>
|
||||
</get-member-type>
|
||||
</example-model>
|
||||
|
||||
<example-model>
|
||||
<get-member-type name="const_iterator">
|
||||
<apply-template name="std::vector">
|
||||
<type name="T"/>
|
||||
</apply-template>
|
||||
</get-member-type>
|
||||
</example-model>
|
||||
|
||||
<example-model>
|
||||
<get-member-type name="iterator">
|
||||
<apply-template name="std::deque">
|
||||
<type name="T"/>
|
||||
</apply-template>
|
||||
</get-member-type>
|
||||
</example-model>
|
||||
|
||||
<example-model>
|
||||
<get-member-type name="const_iterator">
|
||||
<apply-template name="std::deque">
|
||||
<type name="T"/>
|
||||
</apply-template>
|
||||
</get-member-type>
|
||||
</example-model>
|
||||
|
||||
</concept>
|
549
doc/reference/SignedInteger.xml
Normal file
549
doc/reference/SignedInteger.xml
Normal file
@ -0,0 +1,549 @@
|
||||
<?xml version="1.0"?>
|
||||
<concept name="SignedInteger" category="Utility"><!--
|
||||
Based on concepts from the SGI Standard Template Library documentation:
|
||||
Copyright (c) 1996-1999
|
||||
Silicon Graphics Computer Systems, Inc.
|
||||
|
||||
Copyright (c) 1994
|
||||
Hewlett-Packard Company
|
||||
--><!--
|
||||
Copyright 2000-2001 University of Notre Dame du Lac.
|
||||
Copyright 2001-2002 Indiana University.
|
||||
Some concepts based on versions from the MTL draft manual and Boost Graph
|
||||
and Property Map documentation:
|
||||
Copyright (c) Jeremy Siek, Lie-Quan Lee, and Andrew Lumsdaine 2000
|
||||
-->
|
||||
<param name="T" role="integral-type"/>
|
||||
|
||||
<models-sentence>Integer type <arg num="1"/> must be a model of <self/>.</models-sentence>
|
||||
|
||||
<refines const="no" concept="CopyConstructible"/>
|
||||
<refines const="no" concept="Assignable"/>
|
||||
<refines const="no" concept="DefaultConstructible"/>
|
||||
<refines const="no" concept="EqualityComparable"/>
|
||||
<refines const="no" concept="LessThanComparable"/>
|
||||
|
||||
<notation variables="x y z">
|
||||
<sample-value><type name="T"/></sample-value>
|
||||
</notation>
|
||||
<notation variables="a b">
|
||||
<sample-value><type name="int"/></sample-value>
|
||||
</notation>
|
||||
|
||||
<!--
|
||||
<valid-type-expression name="int-ness">
|
||||
<documentation>Should this really be required?</documentation>
|
||||
<type name="T"/>
|
||||
<return-type>
|
||||
<require-same-type>
|
||||
<type name="int"/>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
</valid-type-expression>
|
||||
-->
|
||||
|
||||
<valid-expression name="Conversion from int">
|
||||
<construct template-parameters="">
|
||||
<type name="T"/>
|
||||
<sample-value><type name="int"/></sample-value>
|
||||
</construct>
|
||||
<return-type><require-same-type testable="yes">
|
||||
<type name="T"/>
|
||||
</require-same-type></return-type>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Preincrement">
|
||||
<preincrement>
|
||||
<sample-value>
|
||||
<reference-to><type name="T"/></reference-to>
|
||||
</sample-value>
|
||||
</preincrement>
|
||||
<return-type>
|
||||
<require-same-type testable="yes">
|
||||
<reference-to><type name="T"/></reference-to>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Predecrement">
|
||||
<predecrement>
|
||||
<sample-value>
|
||||
<reference-to><type name="T"/></reference-to>
|
||||
</sample-value>
|
||||
</predecrement>
|
||||
<return-type>
|
||||
<require-same-type testable="yes">
|
||||
<reference-to><type name="T"/></reference-to>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Postincrement">
|
||||
<postincrement>
|
||||
<sample-value>
|
||||
<reference-to><type name="T"/></reference-to>
|
||||
</sample-value>
|
||||
</postincrement>
|
||||
<return-type>
|
||||
<require-same-type testable="yes">
|
||||
<type name="T"/>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Postdecrement">
|
||||
<postdecrement>
|
||||
<sample-value>
|
||||
<reference-to><type name="T"/></reference-to>
|
||||
</sample-value>
|
||||
</postdecrement>
|
||||
<return-type>
|
||||
<require-same-type testable="yes">
|
||||
<type name="T"/>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Sum">
|
||||
<add>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
</add>
|
||||
<return-type>
|
||||
<require-same-type testable="yes">
|
||||
<type name="T"/>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Sum with int">
|
||||
<add>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
<sample-value>
|
||||
<type name="int"/>
|
||||
</sample-value>
|
||||
</add>
|
||||
<return-type>
|
||||
<require-same-type testable="yes">
|
||||
<type name="T"/>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Sum-assignment">
|
||||
<add-assign>
|
||||
<sample-value>
|
||||
<reference-to><type name="T"/></reference-to>
|
||||
</sample-value>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
</add-assign>
|
||||
<return-type>
|
||||
<require-same-type testable="yes">
|
||||
<reference-to><type name="T"/></reference-to>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Sum-assignment with int">
|
||||
<add-assign>
|
||||
<sample-value>
|
||||
<reference-to><type name="T"/></reference-to>
|
||||
</sample-value>
|
||||
<sample-value>
|
||||
<type name="int"/>
|
||||
</sample-value>
|
||||
</add-assign>
|
||||
<return-type>
|
||||
<require-same-type testable="yes">
|
||||
<reference-to><type name="T"/></reference-to>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Difference">
|
||||
<subtract>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
</subtract>
|
||||
<return-type>
|
||||
<require-same-type testable="yes">
|
||||
<type name="T"/>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Difference with int">
|
||||
<subtract>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
<sample-value>
|
||||
<type name="int"/>
|
||||
</sample-value>
|
||||
</subtract>
|
||||
<return-type>
|
||||
<require-same-type testable="yes">
|
||||
<type name="T"/>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Product">
|
||||
<multiply>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
</multiply>
|
||||
<return-type>
|
||||
<require-same-type testable="yes">
|
||||
<type name="T"/>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Product with int">
|
||||
<multiply>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
<sample-value>
|
||||
<type name="int"/>
|
||||
</sample-value>
|
||||
</multiply>
|
||||
<return-type>
|
||||
<require-same-type testable="yes">
|
||||
<type name="T"/>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Product-assignment with int">
|
||||
<multiply-assign>
|
||||
<sample-value>
|
||||
<reference-to><type name="T"/></reference-to>
|
||||
</sample-value>
|
||||
<sample-value>
|
||||
<type name="int"/>
|
||||
</sample-value>
|
||||
</multiply-assign>
|
||||
<return-type>
|
||||
<require-same-type testable="yes">
|
||||
<reference-to><type name="T"/></reference-to>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Product with int on left">
|
||||
<multiply>
|
||||
<sample-value>
|
||||
<type name="int"/>
|
||||
</sample-value>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
</multiply>
|
||||
<return-type>
|
||||
<require-same-type testable="yes">
|
||||
<type name="T"/>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Quotient">
|
||||
<divide>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
</divide>
|
||||
<return-type>
|
||||
<require-same-type testable="yes">
|
||||
<type name="T"/>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Quotient with int">
|
||||
<divide>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
<sample-value>
|
||||
<type name="int"/>
|
||||
</sample-value>
|
||||
</divide>
|
||||
<return-type>
|
||||
<require-same-type testable="yes">
|
||||
<type name="T"/>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Right-shift">
|
||||
<shift-right>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
</shift-right>
|
||||
<return-type>
|
||||
<require-same-type testable="yes">
|
||||
<type name="T"/>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Right-shift with int">
|
||||
<shift-right>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
<sample-value>
|
||||
<type name="int"/>
|
||||
</sample-value>
|
||||
</shift-right>
|
||||
<return-type>
|
||||
<require-same-type testable="yes">
|
||||
<type name="T"/>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Right-shift-assignment with int">
|
||||
<shift-right-assign>
|
||||
<sample-value>
|
||||
<reference-to><type name="T"/></reference-to>
|
||||
</sample-value>
|
||||
<sample-value>
|
||||
<type name="int"/>
|
||||
</sample-value>
|
||||
</shift-right-assign>
|
||||
<return-type>
|
||||
<require-same-type testable="yes">
|
||||
<reference-to><type name="T"/></reference-to>
|
||||
</require-same-type>
|
||||
</return-type>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Less-than comparison">
|
||||
<less-than>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
</less-than>
|
||||
<return-type>
|
||||
<convertible-to testable="yes">
|
||||
<type name="bool"/>
|
||||
</convertible-to>
|
||||
</return-type>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Less-than comparison with int">
|
||||
<less-than>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
<sample-value>
|
||||
<type name="int"/>
|
||||
</sample-value>
|
||||
</less-than>
|
||||
<return-type>
|
||||
<convertible-to testable="yes">
|
||||
<type name="bool"/>
|
||||
</convertible-to>
|
||||
</return-type>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Less-than comparison with size_t">
|
||||
<less-than>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
<sample-value>
|
||||
<type name="std::size_t"/>
|
||||
</sample-value>
|
||||
</less-than>
|
||||
<return-type>
|
||||
<convertible-to testable="yes">
|
||||
<type name="bool"/>
|
||||
</convertible-to>
|
||||
</return-type>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Greater-than comparison">
|
||||
<greater-than>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
</greater-than>
|
||||
<return-type>
|
||||
<convertible-to testable="yes">
|
||||
<type name="bool"/>
|
||||
</convertible-to>
|
||||
</return-type>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Greater-than comparison with int">
|
||||
<greater-than>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
<sample-value>
|
||||
<type name="int"/>
|
||||
</sample-value>
|
||||
</greater-than>
|
||||
<return-type>
|
||||
<convertible-to testable="yes">
|
||||
<type name="bool"/>
|
||||
</convertible-to>
|
||||
</return-type>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Less-than-or-equal comparison">
|
||||
<less-than-or-equal>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
</less-than-or-equal>
|
||||
<return-type>
|
||||
<convertible-to testable="yes">
|
||||
<type name="bool"/>
|
||||
</convertible-to>
|
||||
</return-type>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Less-than-or-equal comparison with int">
|
||||
<less-than-or-equal>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
<sample-value>
|
||||
<type name="int"/>
|
||||
</sample-value>
|
||||
</less-than-or-equal>
|
||||
<return-type>
|
||||
<convertible-to testable="yes">
|
||||
<type name="bool"/>
|
||||
</convertible-to>
|
||||
</return-type>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Greater-than-or-equal comparison">
|
||||
<greater-than-or-equal>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
</greater-than-or-equal>
|
||||
<return-type>
|
||||
<convertible-to testable="yes">
|
||||
<type name="bool"/>
|
||||
</convertible-to>
|
||||
</return-type>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Greater-than-or-equal comparison with int">
|
||||
<greater-than-or-equal>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
<sample-value>
|
||||
<type name="int"/>
|
||||
</sample-value>
|
||||
</greater-than-or-equal>
|
||||
<return-type>
|
||||
<convertible-to testable="yes">
|
||||
<type name="bool"/>
|
||||
</convertible-to>
|
||||
</return-type>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Greater-than-or-equal comparison with int on left">
|
||||
<greater-than-or-equal>
|
||||
<sample-value>
|
||||
<type name="int"/>
|
||||
</sample-value>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
</greater-than-or-equal>
|
||||
<return-type>
|
||||
<convertible-to testable="yes">
|
||||
<type name="bool"/>
|
||||
</convertible-to>
|
||||
</return-type>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Equality comparison">
|
||||
<equal-to>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
</equal-to>
|
||||
<return-type>
|
||||
<convertible-to testable="yes">
|
||||
<type name="bool"/>
|
||||
</convertible-to>
|
||||
</return-type>
|
||||
</valid-expression>
|
||||
|
||||
<valid-expression name="Equality comparison with int">
|
||||
<equal-to>
|
||||
<sample-value>
|
||||
<type name="T"/>
|
||||
</sample-value>
|
||||
<sample-value>
|
||||
<type name="int"/>
|
||||
</sample-value>
|
||||
</equal-to>
|
||||
<return-type>
|
||||
<convertible-to testable="yes">
|
||||
<type name="bool"/>
|
||||
</convertible-to>
|
||||
</return-type>
|
||||
</valid-expression>
|
||||
|
||||
<valid-type-expression name="Conversion to int">
|
||||
<documentation/>
|
||||
<type name="T"/>
|
||||
<return-type>
|
||||
<convertible-to testable="yes">
|
||||
<type name="int"/>
|
||||
</convertible-to>
|
||||
</return-type>
|
||||
</valid-type-expression>
|
||||
|
||||
</concept>
|
84
doc/reference/concepts.xml
Normal file
84
doc/reference/concepts.xml
Normal file
@ -0,0 +1,84 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE library-reference PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
||||
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
|
||||
<library-reference id="concepts.reference"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
last-revision="$Date$">
|
||||
<sectioninfo>
|
||||
<copyright>
|
||||
<year>2001</year>
|
||||
<year>2002</year>
|
||||
<holder>Indiana University</holder>
|
||||
</copyright>
|
||||
|
||||
<copyright>
|
||||
<year>2000</year>
|
||||
<year>2001</year>
|
||||
<holder>University of Notre Dame du Lac</holder>
|
||||
</copyright>
|
||||
|
||||
<copyright>
|
||||
<year>2000</year>
|
||||
<holder>Jeremy Siek</holder>
|
||||
<holder>Lie-Quan Lee</holder>
|
||||
<holder>Andrew Lumsdaine</holder>
|
||||
</copyright>
|
||||
|
||||
<copyright>
|
||||
<year>1996</year>
|
||||
<year>1997</year>
|
||||
<year>1998</year>
|
||||
<year>1999</year>
|
||||
<holder>Silicon Graphics Computer Systems, Inc.</holder>
|
||||
</copyright>
|
||||
|
||||
<copyright>
|
||||
<year>1994</year>
|
||||
<holder>Hewlett-Packard Company</holder>
|
||||
</copyright>
|
||||
|
||||
<legalnotice>
|
||||
<para>Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file <filename>LICENSE_1_0.txt</filename> or copy at
|
||||
<ulink
|
||||
url="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</ulink>)
|
||||
</para>
|
||||
|
||||
<para>This product includes software developed at the University
|
||||
of Notre Dame and the Pervasive Technology Labs at Indiana
|
||||
University. For technical information contact Andrew Lumsdaine
|
||||
at the Pervasive Technology Labs at Indiana University. For
|
||||
administrative and license questions contact the Advanced
|
||||
Research and Technology Institute at 351 West 10th Street.
|
||||
Indianapolis, Indiana 46202, phone 317-278-4100, fax
|
||||
317-274-5902.</para>
|
||||
|
||||
<para>Some concepts based on versions from the MTL draft manual
|
||||
and Boost Graph and Property Map documentation, the SGI Standard
|
||||
Template Library documentation and the Hewlett-Packard STL,
|
||||
under the following license:
|
||||
<blockquote><simpara>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.</simpara></blockquote></para>
|
||||
</legalnotice>
|
||||
</sectioninfo>
|
||||
<title>Concept reference</title>
|
||||
|
||||
<xi:include href="Assignable.xml"/>
|
||||
<xi:include href="InputIterator.xml"/>
|
||||
<xi:include href="OutputIterator.xml"/>
|
||||
<xi:include href="ForwardIterator.xml"/>
|
||||
<xi:include href="BidirectionalIterator.xml"/>
|
||||
<xi:include href="RandomAccessIterator.xml"/>
|
||||
<xi:include href="DefaultConstructible.xml"/>
|
||||
<xi:include href="CopyConstructible.xml"/>
|
||||
<xi:include href="EqualityComparable.xml"/>
|
||||
<xi:include href="LessThanComparable.xml"/>
|
||||
<xi:include href="SignedInteger.xml"/>
|
||||
</library-reference>
|
@ -1,50 +1,59 @@
|
||||
<HTML>
|
||||
<!--
|
||||
-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 2000
|
||||
--
|
||||
-- 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. We make no
|
||||
-- representations about the suitability of this software for any
|
||||
-- purpose. It is provided "as is" without express or implied warranty.
|
||||
-->
|
||||
<Head>
|
||||
<Title>Concept Checking Implementation</Title>
|
||||
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
|
||||
ALINK="#ff0000">
|
||||
<IMG SRC="../../c++boost.gif"
|
||||
ALT="C++ Boost" width="277" height="86">
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<BR Clear>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<!-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 2000, David Abrahams 2007 -->
|
||||
<!-- 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) -->
|
||||
|
||||
<head>
|
||||
<meta name="generator" content=
|
||||
"HTML Tidy for Linux/x86 (vers 1 September 2005), see www.w3.org" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<link rel="stylesheet" href="../../rst.css" type="text/css" />
|
||||
|
||||
<h2><a name="implementation">Implementation</a></h2>
|
||||
<title>Concept Checking Implementation</title>
|
||||
</head>
|
||||
|
||||
Ideally we would like to catch, and indicate, the concept violation at
|
||||
the point of instantiation. As mentioned in D&E[<a
|
||||
href="bibliography.htm#stroustrup94:_design_evolution">2</a>], the error
|
||||
can be caught by exercising all of the requirements needed by the
|
||||
function template. Exactly how the requirements (the valid
|
||||
expressions in particular) are exercised is a tricky issue, since we
|
||||
want the code to be compiled --- <i>but not executed</i>. Our
|
||||
approach is to exercise the requirements in a separate function that
|
||||
is assigned to a function pointer. In this case, the compiler will
|
||||
instantiate the function but will not actually invoke it. In
|
||||
addition, an optimizing compiler will remove the pointer assignment as
|
||||
``dead code'' (though the run-time overhead added by the assignment
|
||||
would be trivial in any case). It might be conceivable for a compiler
|
||||
to skip the semantic analysis and compilation of the constraints
|
||||
function in the first place, which would make our function pointer
|
||||
technique ineffective. However, this is unlikely because removal of
|
||||
unnecessary code and functions is typically done in later stages of a
|
||||
compiler. We have successfully used the function pointer technique
|
||||
with GNU C++, Microsoft Visual C++, and several EDG-based compilers
|
||||
(KAI C++, SGI MIPSpro). The following code shows how this technique
|
||||
can be applied to the <tt>std::stable_sort()</tt> function:
|
||||
<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" />
|
||||
|
||||
<pre>
|
||||
<h2><a name="warning" id="warning"><font color=
|
||||
"red">Warning</font></a></h2>
|
||||
|
||||
<p><font color="red">This documentation is out-of-date; similar but
|
||||
newer implementation techniques are now used. This documentation
|
||||
also refers to components and protocols in the library's old
|
||||
interface such as <code>BOOST_CLASS_REQUIRES</code>
|
||||
and <code>constraints()</code> functions, which are still supported
|
||||
but deprecated.</font></p>
|
||||
|
||||
<h2><a name="implementation" id="implementation">Implementation</a></h2>
|
||||
|
||||
<p>Ideally we would like to catch, and indicate, the concept violation at
|
||||
the point of instantiation. As mentioned in D&E[<a href=
|
||||
"bibliography.htm#stroustrup94:_design_evolution">2</a>], the error can be
|
||||
caught by exercising all of the requirements needed by the function
|
||||
template. Exactly how the requirements (the valid expressions in
|
||||
particular) are exercised is a tricky issue, since we want the code to be
|
||||
compiled—<i>but not executed</i>. Our approach is to exercise the
|
||||
requirements in a separate function that is assigned to a function pointer.
|
||||
In this case, the compiler will instantiate the function but will not
|
||||
actually invoke it. In addition, an optimizing compiler will remove the
|
||||
pointer assignment as ``dead code'' (though the run-time overhead added by
|
||||
the assignment would be trivial in any case). It might be conceivable for a
|
||||
compiler to skip the semantic analysis and compilation of the constraints
|
||||
function in the first place, which would make our function pointer
|
||||
technique ineffective. However, this is unlikely because removal of
|
||||
unnecessary code and functions is typically done in later stages of a
|
||||
compiler. We have successfully used the function pointer technique with GNU
|
||||
C++, Microsoft Visual C++, and several EDG-based compilers (KAI C++, SGI
|
||||
MIPSpro). The following code shows how this technique can be applied to the
|
||||
<tt>std::stable_sort()</tt> function:</p>
|
||||
<pre>
|
||||
template <class RandomAccessIterator>
|
||||
void stable_sort_constraints(RandomAccessIterator i)
|
||||
{
|
||||
@ -57,26 +66,25 @@ can be applied to the <tt>std::stable_sort()</tt> function:
|
||||
void stable_sort(RandomAccessIterator first, RandomAccessIterator last)
|
||||
{
|
||||
typedef void (*fptr_type)(RandomAccessIterator);
|
||||
fptr_type x = &stable_sort_constraints;
|
||||
fptr_type x = &stable_sort_constraints;
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
|
||||
There is often a large set of requirements that need to be checked,
|
||||
and it would be cumbersome for the library implementor to write
|
||||
constraint functions like <tt>stable_sort_constraints()</tt> for every
|
||||
public function. Instead, we group sets of valid expressions
|
||||
together, according to the definitions of the corresponding concepts.
|
||||
For each concept we define a concept checking class template where the
|
||||
template parameter is for the type to be checked. The class contains
|
||||
a <tt>contraints()</tt> member function which exercises all of the
|
||||
valid expressions of the concept. The objects used in the constraints
|
||||
function, such as <tt>n</tt> and <tt>i</tt>, are declared as data
|
||||
members of the concept checking class.
|
||||
|
||||
<pre>
|
||||
<p>There is often a large set of requirements that need to be checked, and
|
||||
it would be cumbersome for the library implementor to write constraint
|
||||
functions like <tt>stable_sort_constraints()</tt> for every public
|
||||
function. Instead, we group sets of valid expressions together, according
|
||||
to the definitions of the corresponding concepts. For each concept we
|
||||
define a concept checking class template where the template parameter is
|
||||
for the type to be checked. The class contains a <tt>constraints()</tt>
|
||||
member function which exercises all of the valid expressions of the
|
||||
concept. The objects used in the constraints function, such as <tt>n</tt>
|
||||
and <tt>i</tt>, are declared as data members of the concept checking
|
||||
class.</p>
|
||||
<pre>
|
||||
template <class Iter>
|
||||
struct RandomAccessIterator_concept
|
||||
struct RandomAccessIteratorConcept
|
||||
{
|
||||
void constraints()
|
||||
{
|
||||
@ -90,18 +98,14 @@ members of the concept checking class.
|
||||
};
|
||||
</pre>
|
||||
|
||||
We can still use the function pointer mechanism to cause instantiation
|
||||
of the constraints function, however now it will be a member function
|
||||
pointer. To make it easy for the library implementor to invoke the
|
||||
concept checks, we wrap the member function pointer mechanism in a
|
||||
function named <tt>function_requires()</tt>. The following code
|
||||
snippet shows how to use <tt>function_requires()</tt> to make sure
|
||||
that the iterator is a
|
||||
<a
|
||||
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">
|
||||
RandomAccessIterator</a>.
|
||||
|
||||
<pre>
|
||||
<p>We can still use the function pointer mechanism to cause instantiation
|
||||
of the constraints function, however now it will be a member function
|
||||
pointer. To make it easy for the library implementor to invoke the concept
|
||||
checks, we wrap the member function pointer mechanism in a function named
|
||||
<tt>function_requires()</tt>. The following code snippet shows how to use
|
||||
<tt>function_requires()</tt> to make sure that the iterator is a <a href=
|
||||
"http://www.boost.org/sgi/stl/RandomAccessIterator.html">RandomAccessIterator</a>.</p>
|
||||
<pre>
|
||||
template <class Iter>
|
||||
void stable_sort(Iter first, Iter last)
|
||||
{
|
||||
@ -110,16 +114,15 @@ RandomAccessIterator</a>.
|
||||
}
|
||||
</pre>
|
||||
|
||||
The definition of the <tt>function_requires()</tt> is as follows. The
|
||||
<tt>Concept</tt> is the concept checking class that has been
|
||||
instantiated with the modeling type. We assign the address of the
|
||||
constraints member function to the function pointer <tt>x</tt>, which
|
||||
causes the instantiation of the constraints function and checking of
|
||||
the concept's valid expressions. We then assign <tt>x</tt> to
|
||||
<tt>x</tt> to avoid unused variable compiler warnings, and wrap
|
||||
everything in a do-while loop to prevent name collisions.
|
||||
|
||||
<pre>
|
||||
<p>The definition of the <tt>function_requires()</tt> is as follows. The
|
||||
<tt>Concept</tt> is the concept checking class that has been instantiated
|
||||
with the modeling type. We assign the address of the constraints member
|
||||
function to the function pointer <tt>x</tt>, which causes the instantiation
|
||||
of the constraints function and checking of the concept's valid
|
||||
expressions. We then assign <tt>x</tt> to <tt>x</tt> to avoid unused
|
||||
variable compiler warnings, and wrap everything in a do-while loop to
|
||||
prevent name collisions.</p>
|
||||
<pre>
|
||||
template <class Concept>
|
||||
void function_requires()
|
||||
{
|
||||
@ -128,17 +131,16 @@ everything in a do-while loop to prevent name collisions.
|
||||
}
|
||||
</pre>
|
||||
|
||||
To check the type parameters of class templates, we provide the
|
||||
<tt>BOOST_CLASS_REQUIRE</tt> macro which can be used inside the body of a
|
||||
class definition (whereas <tt>function_requires()</tt> can only be used
|
||||
inside of a function body). This macro declares a nested class
|
||||
template, where the template parameter is a function pointer. We then
|
||||
use the nested class type in a typedef with the function pointer type
|
||||
of the constraint function as the template argument. We use the
|
||||
<tt>type_var</tt> and <tt>concept</tt> names in the nested class and
|
||||
typedef names to help prevent name collisions.
|
||||
|
||||
<pre>
|
||||
<p>To check the type parameters of class templates, we provide the
|
||||
<tt>BOOST_CLASS_REQUIRE</tt> macro which can be used inside the body of a
|
||||
class definition (whereas <tt>function_requires()</tt> can only be used
|
||||
inside of a function body). This macro declares a nested class template,
|
||||
where the template parameter is a function pointer. We then use the nested
|
||||
class type in a typedef with the function pointer type of the constraint
|
||||
function as the template argument. We use the <tt>type_var</tt> and
|
||||
<tt>concept</tt> names in the nested class and typedef names to help
|
||||
prevent name collisions.</p>
|
||||
<pre>
|
||||
#define BOOST_CLASS_REQUIRE(type_var, ns, concept) \
|
||||
typedef void (ns::concept <type_var>::* func##type_var##concept)(); \
|
||||
template <func##type_var##concept _Tp1> \
|
||||
@ -148,14 +150,12 @@ typedef names to help prevent name collisions.
|
||||
concept_checking_typedef_##type_var##concept
|
||||
</pre>
|
||||
|
||||
In addition, there are versions of <tt>BOOST_CLASS_REQUIRE</tt> that
|
||||
take more arguments, to handle concepts that include interactions
|
||||
between two or more types. <tt>BOOST_CLASS_REQUIRE</tt> was not used
|
||||
in the implementation of the BCCL concept checks because some
|
||||
compilers do not implement template parameters of function pointer
|
||||
type.
|
||||
|
||||
<!-- We decided not to go with this version since it is easier to misuse
|
||||
<p>In addition, there are versions of <tt>BOOST_CLASS_REQUIRE</tt> that
|
||||
take more arguments, to handle concepts that include interactions between
|
||||
two or more types. <tt>BOOST_CLASS_REQUIRE</tt> was not used in the
|
||||
implementation of the BCCL concept checks because some compilers do not
|
||||
implement template parameters of function pointer type.
|
||||
<!-- We decided not to go with this version since it is easier to misuse
|
||||
|
||||
To check the type parameters of class templates, we provide the
|
||||
<tt>class_requires</tt> class which can be used inside the body of a
|
||||
@ -184,21 +184,22 @@ Boost Concept Checking Library concept checks because several
|
||||
compilers do not implement template parameters of function pointer
|
||||
type.
|
||||
|
||||
-->
|
||||
--></p>
|
||||
|
||||
<p>
|
||||
<a href="./reference.htm">Next: Reference</a><br>
|
||||
<a href="prog_with_concepts.htm">Prev: Programming With Concepts</a>
|
||||
<p><a href="./reference.htm">Next: Reference</a><br />
|
||||
<a href="prog_with_concepts.htm">Prev: Programming With
|
||||
Concepts</a><br /></p>
|
||||
<hr />
|
||||
|
||||
<br>
|
||||
<HR>
|
||||
<TABLE>
|
||||
<TR valign=top>
|
||||
<TD nowrap>Copyright © 2000</TD><TD>
|
||||
<A HREF="../../people/jeremy_siek.htm">Jeremy Siek</A>(<A
|
||||
HREF="mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</A>)
|
||||
Andrew Lumsdaine</A>(<A HREF="mailto:lums@osl.iu.edu">lums@osl.iu.edu</A>)
|
||||
</TD></TR></TABLE>
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td nowrap="nowrap">Copyright © 2000</td>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
<td><a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</a>(<a href=
|
||||
"mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</a>) Andrew
|
||||
Lumsdaine(<a href="mailto:lums@osl.iu.edu">lums@osl.iu.edu</a>),
|
||||
2007 <a href="mailto:dave@boost-consulting.com">David Abrahams</a>.
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
|
45
include/boost/concept/assert.hpp
Normal file
45
include/boost/concept/assert.hpp
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright David Abrahams 2006. 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_CONCEPT_ASSERT_DWA2006430_HPP
|
||||
# define BOOST_CONCEPT_ASSERT_DWA2006430_HPP
|
||||
|
||||
# include <boost/config.hpp>
|
||||
# include <boost/config/workaround.hpp>
|
||||
|
||||
// The old protocol used a constraints() member function in concept
|
||||
// checking classes. If the compiler supports SFINAE, we can detect
|
||||
// that function and seamlessly support the old concept checking
|
||||
// classes. In this release, backward compatibility with the old
|
||||
// concept checking classes is enabled by default, where available.
|
||||
// The old protocol is deprecated, though, and backward compatibility
|
||||
// will no longer be the default in the next release.
|
||||
|
||||
# if !defined(BOOST_NO_OLD_CONCEPT_SUPPORT) \
|
||||
&& !defined(BOOST_NO_SFINAE) \
|
||||
\
|
||||
&& !(BOOST_WORKAROUND(__GNUC__, == 3) && BOOST_WORKAROUND(__GNUC_MINOR__, < 4))
|
||||
|
||||
// Note: gcc-2.96 through 3.3.x have some SFINAE, but no ability to
|
||||
// check for the presence of particularmember functions.
|
||||
|
||||
# define BOOST_OLD_CONCEPT_SUPPORT
|
||||
|
||||
# endif
|
||||
|
||||
# ifdef BOOST_MSVC
|
||||
# include <boost/concept/detail/msvc.hpp>
|
||||
# elif BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564))
|
||||
# include <boost/concept/detail/borland.hpp>
|
||||
# else
|
||||
# include <boost/concept/detail/general.hpp>
|
||||
# endif
|
||||
|
||||
// Usage, in class or function context:
|
||||
//
|
||||
// BOOST_CONCEPT_ASSERT((UnaryFunctionConcept<F,bool,int>));
|
||||
//
|
||||
# define BOOST_CONCEPT_ASSERT(ModelInParens) \
|
||||
BOOST_CONCEPT_ASSERT_FN(void(*)ModelInParens)
|
||||
|
||||
#endif // BOOST_CONCEPT_ASSERT_DWA2006430_HPP
|
16
include/boost/concept/detail/backward_compatibility.hpp
Normal file
16
include/boost/concept/detail/backward_compatibility.hpp
Normal file
@ -0,0 +1,16 @@
|
||||
// Copyright David Abrahams 2009. 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_CONCEPT_BACKWARD_COMPATIBILITY_DWA200968_HPP
|
||||
# define BOOST_CONCEPT_BACKWARD_COMPATIBILITY_DWA200968_HPP
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace concepts {}
|
||||
|
||||
# if defined(BOOST_HAS_CONCEPTS) && !defined(BOOST_CONCEPT_NO_BACKWARD_KEYWORD)
|
||||
namespace concept = concepts;
|
||||
# endif
|
||||
} // namespace boost::concept
|
||||
|
||||
#endif // BOOST_CONCEPT_BACKWARD_COMPATIBILITY_DWA200968_HPP
|
30
include/boost/concept/detail/borland.hpp
Normal file
30
include/boost/concept/detail/borland.hpp
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright David Abrahams 2006. 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_CONCEPT_DETAIL_BORLAND_DWA2006429_HPP
|
||||
# define BOOST_CONCEPT_DETAIL_BORLAND_DWA2006429_HPP
|
||||
|
||||
# include <boost/preprocessor/cat.hpp>
|
||||
# include <boost/concept/detail/backward_compatibility.hpp>
|
||||
|
||||
namespace boost { namespace concepts {
|
||||
|
||||
template <class ModelFnPtr>
|
||||
struct require;
|
||||
|
||||
template <class Model>
|
||||
struct require<void(*)(Model)>
|
||||
{
|
||||
enum { instantiate = sizeof((((Model*)0)->~Model()), 3) };
|
||||
};
|
||||
|
||||
# define BOOST_CONCEPT_ASSERT_FN( ModelFnPtr ) \
|
||||
enum \
|
||||
{ \
|
||||
BOOST_PP_CAT(boost_concept_check,__LINE__) = \
|
||||
boost::concepts::require<ModelFnPtr>::instantiate \
|
||||
}
|
||||
|
||||
}} // namespace boost::concept
|
||||
|
||||
#endif // BOOST_CONCEPT_DETAIL_BORLAND_DWA2006429_HPP
|
34
include/boost/concept/detail/concept_def.hpp
Normal file
34
include/boost/concept/detail/concept_def.hpp
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright David Abrahams 2006. 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_CONCEPT_DETAIL_CONCEPT_DEF_DWA200651_HPP
|
||||
# define BOOST_CONCEPT_DETAIL_CONCEPT_DEF_DWA200651_HPP
|
||||
# include <boost/preprocessor/seq/for_each_i.hpp>
|
||||
# include <boost/preprocessor/seq/enum.hpp>
|
||||
# include <boost/preprocessor/comma_if.hpp>
|
||||
# include <boost/preprocessor/cat.hpp>
|
||||
#endif // BOOST_CONCEPT_DETAIL_CONCEPT_DEF_DWA200651_HPP
|
||||
|
||||
// BOOST_concept(SomeName, (p1)(p2)...(pN))
|
||||
//
|
||||
// Expands to "template <class p1, class p2, ...class pN> struct SomeName"
|
||||
//
|
||||
// Also defines an equivalent SomeNameConcept for backward compatibility.
|
||||
// Maybe in the next release we can kill off the "Concept" suffix for good.
|
||||
# define BOOST_concept(name, params) \
|
||||
template < BOOST_PP_SEQ_FOR_EACH_I(BOOST_CONCEPT_typename,~,params) > \
|
||||
struct name; /* forward declaration */ \
|
||||
\
|
||||
template < BOOST_PP_SEQ_FOR_EACH_I(BOOST_CONCEPT_typename,~,params) > \
|
||||
struct BOOST_PP_CAT(name,Concept) \
|
||||
: name< BOOST_PP_SEQ_ENUM(params) > \
|
||||
{ \
|
||||
}; \
|
||||
\
|
||||
template < BOOST_PP_SEQ_FOR_EACH_I(BOOST_CONCEPT_typename,~,params) > \
|
||||
struct name
|
||||
|
||||
// Helper for BOOST_concept, above.
|
||||
# define BOOST_CONCEPT_typename(r, ignored, index, t) \
|
||||
BOOST_PP_COMMA_IF(index) typename t
|
||||
|
5
include/boost/concept/detail/concept_undef.hpp
Normal file
5
include/boost/concept/detail/concept_undef.hpp
Normal file
@ -0,0 +1,5 @@
|
||||
// Copyright David Abrahams 2006. 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)
|
||||
# undef BOOST_concept_typename
|
||||
# undef BOOST_concept
|
98
include/boost/concept/detail/general.hpp
Normal file
98
include/boost/concept/detail/general.hpp
Normal file
@ -0,0 +1,98 @@
|
||||
// Copyright David Abrahams 2006. 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_CONCEPT_DETAIL_GENERAL_DWA2006429_HPP
|
||||
# define BOOST_CONCEPT_DETAIL_GENERAL_DWA2006429_HPP
|
||||
|
||||
# include <boost/config.hpp>
|
||||
# include <boost/preprocessor/cat.hpp>
|
||||
# include <boost/concept/detail/backward_compatibility.hpp>
|
||||
|
||||
# ifdef BOOST_OLD_CONCEPT_SUPPORT
|
||||
# include <boost/concept/detail/has_constraints.hpp>
|
||||
# include <boost/type_traits/conditional.hpp>
|
||||
# endif
|
||||
|
||||
// This implementation works on Comeau and GCC, all the way back to
|
||||
// 2.95
|
||||
namespace boost { namespace concepts {
|
||||
|
||||
template <class ModelFn>
|
||||
struct requirement_;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <void(*)()> struct instantiate {};
|
||||
}
|
||||
|
||||
template <class Model>
|
||||
struct requirement
|
||||
{
|
||||
# if defined(BOOST_GCC) && (BOOST_GCC >= 110000)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wnonnull"
|
||||
# endif
|
||||
static void failed() { ((Model*)0)->~Model(); }
|
||||
# if defined(BOOST_GCC) && (BOOST_GCC >= 110000)
|
||||
# pragma GCC diagnostic pop
|
||||
# endif
|
||||
};
|
||||
|
||||
struct failed {};
|
||||
|
||||
template <class Model>
|
||||
struct requirement<failed ************ Model::************>
|
||||
{
|
||||
# if defined(BOOST_GCC) && (BOOST_GCC >= 110000)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wnonnull"
|
||||
# endif
|
||||
static void failed() { ((Model*)0)->~Model(); }
|
||||
# if defined(BOOST_GCC) && (BOOST_GCC >= 110000)
|
||||
# pragma GCC diagnostic pop
|
||||
# endif
|
||||
};
|
||||
|
||||
# ifdef BOOST_OLD_CONCEPT_SUPPORT
|
||||
|
||||
template <class Model>
|
||||
struct constraint
|
||||
{
|
||||
# if defined(BOOST_GCC) && (BOOST_GCC >= 110000)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wnonnull"
|
||||
# endif
|
||||
static void failed() { ((Model*)0)->constraints(); }
|
||||
# if defined(BOOST_GCC) && (BOOST_GCC >= 110000)
|
||||
# pragma GCC diagnostic pop
|
||||
# endif
|
||||
};
|
||||
|
||||
template <class Model>
|
||||
struct requirement_<void(*)(Model)>
|
||||
: boost::conditional<
|
||||
concepts::not_satisfied<Model>::value
|
||||
, constraint<Model>
|
||||
, requirement<failed ************ Model::************>
|
||||
>::type
|
||||
{};
|
||||
|
||||
# else
|
||||
|
||||
// For GCC-2.x, these can't have exactly the same name
|
||||
template <class Model>
|
||||
struct requirement_<void(*)(Model)>
|
||||
: requirement<failed ************ Model::************>
|
||||
{};
|
||||
|
||||
# endif
|
||||
|
||||
# define BOOST_CONCEPT_ASSERT_FN( ModelFnPtr ) \
|
||||
typedef ::boost::concepts::detail::instantiate< \
|
||||
&::boost::concepts::requirement_<ModelFnPtr>::failed> \
|
||||
BOOST_PP_CAT(boost_concept_check,__LINE__) \
|
||||
BOOST_ATTRIBUTE_UNUSED
|
||||
|
||||
}}
|
||||
|
||||
#endif // BOOST_CONCEPT_DETAIL_GENERAL_DWA2006429_HPP
|
50
include/boost/concept/detail/has_constraints.hpp
Normal file
50
include/boost/concept/detail/has_constraints.hpp
Normal file
@ -0,0 +1,50 @@
|
||||
// Copyright David Abrahams 2006. 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_CONCEPT_DETAIL_HAS_CONSTRAINTS_DWA2006429_HPP
|
||||
# define BOOST_CONCEPT_DETAIL_HAS_CONSTRAINTS_DWA2006429_HPP
|
||||
|
||||
# include <boost/type_traits/integral_constant.hpp>
|
||||
# include <boost/config/workaround.hpp>
|
||||
# include <boost/concept/detail/backward_compatibility.hpp>
|
||||
|
||||
namespace boost { namespace concepts {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// Here we implement the metafunction that detects whether a
|
||||
// constraints metafunction exists
|
||||
typedef char yes;
|
||||
typedef char (&no)[2];
|
||||
|
||||
template <class Model, void (Model::*)()>
|
||||
struct wrap_constraints {};
|
||||
|
||||
#if BOOST_WORKAROUND(__SUNPRO_CC, <= 0x580) || defined(__CUDACC__)
|
||||
// Work around the following bogus error in Sun Studio 11, by
|
||||
// turning off the has_constraints function entirely:
|
||||
// Error: complex expression not allowed in dependent template
|
||||
// argument expression
|
||||
inline no has_constraints_(...);
|
||||
#else
|
||||
template <class Model>
|
||||
inline yes has_constraints_(Model*, wrap_constraints<Model,&Model::constraints>* = 0);
|
||||
inline no has_constraints_(...);
|
||||
#endif
|
||||
}
|
||||
|
||||
// This would be called "detail::has_constraints," but it has a strong
|
||||
// tendency to show up in error messages.
|
||||
template <class Model>
|
||||
struct not_satisfied
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool
|
||||
, value = sizeof( detail::has_constraints_((Model*)0) ) == sizeof(detail::yes) );
|
||||
typedef boost::integral_constant<bool, value> type;
|
||||
};
|
||||
|
||||
}} // namespace boost::concepts::detail
|
||||
|
||||
#endif // BOOST_CONCEPT_DETAIL_HAS_CONSTRAINTS_DWA2006429_HPP
|
123
include/boost/concept/detail/msvc.hpp
Normal file
123
include/boost/concept/detail/msvc.hpp
Normal file
@ -0,0 +1,123 @@
|
||||
// Copyright David Abrahams 2006. 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_CONCEPT_CHECK_MSVC_DWA2006429_HPP
|
||||
# define BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP
|
||||
|
||||
# include <boost/preprocessor/cat.hpp>
|
||||
# include <boost/concept/detail/backward_compatibility.hpp>
|
||||
# include <boost/config.hpp>
|
||||
|
||||
# ifdef BOOST_OLD_CONCEPT_SUPPORT
|
||||
# include <boost/concept/detail/has_constraints.hpp>
|
||||
# include <boost/type_traits/conditional.hpp>
|
||||
# endif
|
||||
|
||||
# ifdef BOOST_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4100)
|
||||
# endif
|
||||
|
||||
namespace boost { namespace concepts {
|
||||
|
||||
|
||||
template <class Model>
|
||||
struct check
|
||||
{
|
||||
virtual void failed(Model* x)
|
||||
{
|
||||
x->~Model();
|
||||
}
|
||||
};
|
||||
|
||||
# ifndef BOOST_NO_PARTIAL_SPECIALIZATION
|
||||
struct failed {};
|
||||
template <class Model>
|
||||
struct check<failed ************ Model::************>
|
||||
{
|
||||
virtual void failed(Model* x)
|
||||
{
|
||||
x->~Model();
|
||||
}
|
||||
};
|
||||
# endif
|
||||
|
||||
# ifdef BOOST_OLD_CONCEPT_SUPPORT
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// No need for a virtual function here, since evaluating
|
||||
// not_satisfied below will have already instantiated the
|
||||
// constraints() member.
|
||||
struct constraint {};
|
||||
}
|
||||
|
||||
template <class Model>
|
||||
struct require
|
||||
: boost::conditional<
|
||||
not_satisfied<Model>::value
|
||||
, detail::constraint
|
||||
# ifndef BOOST_NO_PARTIAL_SPECIALIZATION
|
||||
, check<Model>
|
||||
# else
|
||||
, check<failed ************ Model::************>
|
||||
# endif
|
||||
>::type
|
||||
{};
|
||||
|
||||
# else
|
||||
|
||||
template <class Model>
|
||||
struct require
|
||||
# ifndef BOOST_NO_PARTIAL_SPECIALIZATION
|
||||
: check<Model>
|
||||
# else
|
||||
: check<failed ************ Model::************>
|
||||
# endif
|
||||
{};
|
||||
|
||||
# endif
|
||||
|
||||
# if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
|
||||
|
||||
//
|
||||
// The iterator library sees some really strange errors unless we
|
||||
// do things this way.
|
||||
//
|
||||
template <class Model>
|
||||
struct require<void(*)(Model)>
|
||||
{
|
||||
virtual void failed(Model*)
|
||||
{
|
||||
require<Model>();
|
||||
}
|
||||
};
|
||||
|
||||
# define BOOST_CONCEPT_ASSERT_FN( ModelFnPtr ) \
|
||||
enum \
|
||||
{ \
|
||||
BOOST_PP_CAT(boost_concept_check,__LINE__) = \
|
||||
sizeof(::boost::concepts::require<ModelFnPtr>) \
|
||||
}
|
||||
|
||||
# else // Not vc-7.1
|
||||
|
||||
template <class Model>
|
||||
require<Model>
|
||||
require_(void(*)(Model));
|
||||
|
||||
# define BOOST_CONCEPT_ASSERT_FN( ModelFnPtr ) \
|
||||
enum \
|
||||
{ \
|
||||
BOOST_PP_CAT(boost_concept_check,__LINE__) = \
|
||||
sizeof(::boost::concepts::require_((ModelFnPtr)0)) \
|
||||
}
|
||||
|
||||
# endif
|
||||
}}
|
||||
|
||||
# ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
# endif
|
||||
|
||||
#endif // BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP
|
93
include/boost/concept/requires.hpp
Normal file
93
include/boost/concept/requires.hpp
Normal file
@ -0,0 +1,93 @@
|
||||
// Copyright David Abrahams 2006. 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_CONCEPT_REQUIRES_DWA2006430_HPP
|
||||
# define BOOST_CONCEPT_REQUIRES_DWA2006430_HPP
|
||||
|
||||
# include <boost/config.hpp>
|
||||
# include <boost/concept/assert.hpp>
|
||||
# include <boost/preprocessor/seq/for_each.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
// unaryfunptr_arg_type from parameter/aux_/parenthesized_type.hpp
|
||||
|
||||
namespace ccheck_aux {
|
||||
|
||||
// A metafunction that transforms void(*)(T) -> T
|
||||
template <class UnaryFunctionPointer>
|
||||
struct unaryfunptr_arg_type;
|
||||
|
||||
template <class Arg>
|
||||
struct unaryfunptr_arg_type<void(*)(Arg)>
|
||||
{
|
||||
typedef Arg type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct unaryfunptr_arg_type<void(*)(void)>
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
} // namespace ccheck_aux
|
||||
|
||||
// Template for use in handwritten assertions
|
||||
template <class Model, class More>
|
||||
struct requires_ : More
|
||||
{
|
||||
BOOST_CONCEPT_ASSERT((Model));
|
||||
};
|
||||
|
||||
// Template for use by macros, where models must be wrapped in parens.
|
||||
// This isn't in namespace detail to keep extra cruft out of resulting
|
||||
// error messages.
|
||||
template <class ModelFn>
|
||||
struct _requires_
|
||||
{
|
||||
enum { value = 0 };
|
||||
BOOST_CONCEPT_ASSERT_FN(ModelFn);
|
||||
};
|
||||
|
||||
template <int check, class Result>
|
||||
struct Requires_ : ::boost::ccheck_aux::unaryfunptr_arg_type<Result>
|
||||
{
|
||||
};
|
||||
|
||||
# if BOOST_WORKAROUND(BOOST_INTEL_WIN, BOOST_TESTED_AT(1010))
|
||||
# define BOOST_CONCEPT_REQUIRES_(r,data,t) | (::boost::_requires_<void(*)t>::value)
|
||||
# else
|
||||
# define BOOST_CONCEPT_REQUIRES_(r,data,t) + (::boost::_requires_<void(*)t>::value)
|
||||
# endif
|
||||
|
||||
#if defined(NDEBUG)
|
||||
|
||||
# define BOOST_CONCEPT_REQUIRES(models, result) \
|
||||
typename ::boost::ccheck_aux::unaryfunptr_arg_type<void(*)result>::type
|
||||
|
||||
#elif BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564))
|
||||
|
||||
// Same thing as below without the initial typename
|
||||
# define BOOST_CONCEPT_REQUIRES(models, result) \
|
||||
::boost::Requires_< \
|
||||
(0 BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_REQUIRES_, ~, models)), \
|
||||
::boost::ccheck_aux::unaryfunptr_arg_type<void(*)result> \
|
||||
>::type
|
||||
|
||||
#else
|
||||
|
||||
// This just ICEs on MSVC6 :(
|
||||
# define BOOST_CONCEPT_REQUIRES(models, result) \
|
||||
typename ::boost::Requires_< \
|
||||
(0 BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_REQUIRES_, ~, models)), \
|
||||
void(*)result \
|
||||
>::type
|
||||
|
||||
#endif
|
||||
|
||||
// C++0x proposed syntax changed. This supports an older usage
|
||||
#define BOOST_CONCEPT_WHERE(models,result) BOOST_CONCEPT_REQUIRES(models,result)
|
||||
|
||||
} // namespace boost::concept_check
|
||||
|
||||
#endif // BOOST_CONCEPT_REQUIRES_DWA2006430_HPP
|
43
include/boost/concept/usage.hpp
Normal file
43
include/boost/concept/usage.hpp
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright David Abrahams 2006. 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_CONCEPT_USAGE_DWA2006919_HPP
|
||||
# define BOOST_CONCEPT_USAGE_DWA2006919_HPP
|
||||
|
||||
# include <boost/concept/assert.hpp>
|
||||
# include <boost/config/workaround.hpp>
|
||||
# include <boost/concept/detail/backward_compatibility.hpp>
|
||||
|
||||
namespace boost { namespace concepts {
|
||||
|
||||
template <class Model>
|
||||
struct usage_requirements
|
||||
{
|
||||
# if defined(BOOST_GCC) && (BOOST_GCC >= 110000)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wnonnull"
|
||||
# endif
|
||||
~usage_requirements() { ((Model*)0)->~Model(); }
|
||||
# if defined(BOOST_GCC) && (BOOST_GCC >= 110000)
|
||||
# pragma GCC diagnostic pop
|
||||
# endif
|
||||
};
|
||||
|
||||
# if BOOST_WORKAROUND(__GNUC__, <= 3)
|
||||
|
||||
# define BOOST_CONCEPT_USAGE(model) \
|
||||
model(); /* at least 2.96 and 3.4.3 both need this :( */ \
|
||||
BOOST_CONCEPT_ASSERT((boost::concepts::usage_requirements<model>)); \
|
||||
~model()
|
||||
|
||||
# else
|
||||
|
||||
# define BOOST_CONCEPT_USAGE(model) \
|
||||
BOOST_CONCEPT_ASSERT((boost::concepts::usage_requirements<model>)); \
|
||||
~model()
|
||||
|
||||
# endif
|
||||
|
||||
}} // namespace boost::concepts
|
||||
|
||||
#endif // BOOST_CONCEPT_USAGE_DWA2006919_HPP
|
@ -1,9 +1,8 @@
|
||||
//
|
||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
// (C) Copyright Jeremy Siek 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)
|
||||
//
|
||||
// Revision History:
|
||||
//
|
||||
@ -16,8 +15,10 @@
|
||||
#define BOOST_CONCEPT_ARCHETYPES_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/iterator.hpp>
|
||||
#include <boost/config/workaround.hpp>
|
||||
#include <functional>
|
||||
#include <iterator> // iterator tags
|
||||
#include <cstddef> // std::ptrdiff_t
|
||||
|
||||
namespace boost {
|
||||
|
||||
@ -51,12 +52,18 @@ namespace boost {
|
||||
// is really quite innocent. The name of this class needs to be
|
||||
// changed.
|
||||
template <class T>
|
||||
class static_object {
|
||||
class static_object
|
||||
{
|
||||
public:
|
||||
static T& get() {
|
||||
static char d[sizeof(T)];
|
||||
return *reinterpret_cast<T*>(d);
|
||||
}
|
||||
static T& get()
|
||||
{
|
||||
#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564))
|
||||
return *reinterpret_cast<T*>(0);
|
||||
#else
|
||||
static char d[sizeof(T)];
|
||||
return *reinterpret_cast<T*>(d);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
template <class Base = null_archetype<> >
|
||||
@ -258,25 +265,25 @@ namespace boost {
|
||||
struct optag2 { };
|
||||
struct optag3 { };
|
||||
|
||||
#define BOOST_DEFINE_BINARY_PREDICATE_ARCHETYPE(OP, NAME) \
|
||||
template <class Base = null_archetype<>, class Tag = optag1 > \
|
||||
class NAME##_first_archetype : public Base { \
|
||||
public: \
|
||||
NAME##_first_archetype(detail::dummy_constructor x) : Base(x) { } \
|
||||
}; \
|
||||
\
|
||||
template <class Base = null_archetype<>, class Tag = optag1 > \
|
||||
class NAME##_second_archetype : public Base { \
|
||||
public: \
|
||||
NAME##_second_archetype(detail::dummy_constructor x) : Base(x) { } \
|
||||
}; \
|
||||
\
|
||||
template <class BaseFirst, class BaseSecond, class Tag> \
|
||||
boolean_archetype \
|
||||
operator OP (const NAME##_first_archetype<BaseFirst, Tag>&, \
|
||||
const NAME##_second_archetype<BaseSecond, Tag>&) \
|
||||
{ \
|
||||
return boolean_archetype(static_object<detail::dummy_constructor>::get()); \
|
||||
#define BOOST_DEFINE_BINARY_PREDICATE_ARCHETYPE(OP, NAME) \
|
||||
template <class Base = null_archetype<>, class Tag = optag1 > \
|
||||
class NAME##_first_archetype : public Base { \
|
||||
public: \
|
||||
NAME##_first_archetype(detail::dummy_constructor x) : Base(x) { } \
|
||||
}; \
|
||||
\
|
||||
template <class Base = null_archetype<>, class Tag = optag1 > \
|
||||
class NAME##_second_archetype : public Base { \
|
||||
public: \
|
||||
NAME##_second_archetype(detail::dummy_constructor x) : Base(x) { } \
|
||||
}; \
|
||||
\
|
||||
template <class BaseFirst, class BaseSecond, class Tag> \
|
||||
boolean_archetype \
|
||||
operator OP (const NAME##_first_archetype<BaseFirst, Tag>&, \
|
||||
const NAME##_second_archetype<BaseSecond, Tag>&) \
|
||||
{ \
|
||||
return boolean_archetype(static_object<detail::dummy_constructor>::get()); \
|
||||
}
|
||||
|
||||
BOOST_DEFINE_BINARY_PREDICATE_ARCHETYPE(==, equal_op)
|
||||
@ -402,90 +409,38 @@ namespace boost {
|
||||
//===========================================================================
|
||||
// Iterator Archetype Classes
|
||||
|
||||
template <class T>
|
||||
struct input_proxy {
|
||||
operator const T&() { return static_object<T>::get(); }
|
||||
};
|
||||
template <class T>
|
||||
class trivial_iterator_archetype
|
||||
{
|
||||
typedef trivial_iterator_archetype self;
|
||||
public:
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
typedef T value_type;
|
||||
typedef void reference;
|
||||
typedef void pointer;
|
||||
typedef void difference_type;
|
||||
typedef void iterator_category;
|
||||
#endif
|
||||
trivial_iterator_archetype() { }
|
||||
self& operator=(const self&) { return *this; }
|
||||
bool operator==(const self&) const { return true; }
|
||||
bool operator!=(const self&) const { return true; }
|
||||
input_proxy<T> operator*() const { return input_proxy<T>(); }
|
||||
};
|
||||
} // namespace boost
|
||||
|
||||
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
|
||||
namespace std {
|
||||
template <class T>
|
||||
struct iterator_traits< boost::trivial_iterator_archetype<T> >
|
||||
{
|
||||
typedef T value_type;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
template <class T>
|
||||
struct input_output_proxy {
|
||||
input_output_proxy<T>& operator=(const T&) { return *this; }
|
||||
operator const T&() { return static_object<T>::get(); }
|
||||
};
|
||||
template <class T>
|
||||
class mutable_trivial_iterator_archetype
|
||||
{
|
||||
typedef mutable_trivial_iterator_archetype self;
|
||||
public:
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
typedef T value_type;
|
||||
typedef void reference;
|
||||
typedef void pointer;
|
||||
typedef void difference_type;
|
||||
typedef void iterator_category;
|
||||
#endif
|
||||
mutable_trivial_iterator_archetype() { }
|
||||
self& operator=(const self&) { return *this; }
|
||||
bool operator==(const self&) const { return true; }
|
||||
bool operator!=(const self&) const { return true; }
|
||||
input_output_proxy<T> operator*() const { return input_output_proxy<T>(); }
|
||||
};
|
||||
} // namespace boost
|
||||
|
||||
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
|
||||
namespace std {
|
||||
template <class T>
|
||||
struct iterator_traits< boost::mutable_trivial_iterator_archetype<T> >
|
||||
{
|
||||
typedef T value_type;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <class T>
|
||||
template <class T, int I = 0>
|
||||
class input_iterator_archetype
|
||||
{
|
||||
public:
|
||||
private:
|
||||
typedef input_iterator_archetype self;
|
||||
public:
|
||||
typedef std::input_iterator_tag iterator_category;
|
||||
typedef T value_type;
|
||||
struct reference {
|
||||
operator const value_type&() const { return static_object<T>::get(); }
|
||||
};
|
||||
typedef const T* pointer;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
self& operator=(const self&) { return *this; }
|
||||
bool operator==(const self&) const { return true; }
|
||||
bool operator!=(const self&) const { return true; }
|
||||
reference operator*() const { return reference(); }
|
||||
self& operator++() { return *this; }
|
||||
self operator++(int) { return *this; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class input_iterator_archetype_no_proxy
|
||||
{
|
||||
private:
|
||||
typedef input_iterator_archetype_no_proxy self;
|
||||
public:
|
||||
typedef std::input_iterator_tag iterator_category;
|
||||
typedef T value_type;
|
||||
typedef const T& reference;
|
||||
typedef const T* pointer;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
input_iterator_archetype() { }
|
||||
self& operator=(const self&) { return *this; }
|
||||
bool operator==(const self&) const { return true; }
|
||||
bool operator!=(const self&) const { return true; }
|
||||
@ -494,7 +449,7 @@ namespace boost {
|
||||
self operator++(int) { return *this; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
template <class T>
|
||||
struct output_proxy {
|
||||
output_proxy& operator=(const T&) { return *this; }
|
||||
};
|
||||
@ -522,6 +477,30 @@ namespace boost {
|
||||
output_iterator_archetype() { }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class input_output_iterator_archetype
|
||||
{
|
||||
private:
|
||||
typedef input_output_iterator_archetype self;
|
||||
struct in_out_tag : public std::input_iterator_tag, public std::output_iterator_tag { };
|
||||
public:
|
||||
typedef in_out_tag iterator_category;
|
||||
typedef T value_type;
|
||||
struct reference {
|
||||
reference& operator=(const T&) { return *this; }
|
||||
operator value_type() { return static_object<T>::get(); }
|
||||
};
|
||||
typedef const T* pointer;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
input_output_iterator_archetype() { }
|
||||
self& operator=(const self&) { return *this; }
|
||||
bool operator==(const self&) const { return true; }
|
||||
bool operator!=(const self&) const { return true; }
|
||||
reference operator*() const { return reference(); }
|
||||
self& operator++() { return *this; }
|
||||
self operator++(int) { return *this; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class forward_iterator_archetype
|
||||
{
|
||||
@ -531,7 +510,7 @@ namespace boost {
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef T value_type;
|
||||
typedef const T& reference;
|
||||
typedef T* pointer;
|
||||
typedef T const* pointer;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
forward_iterator_archetype() { }
|
||||
self& operator=(const self&) { return *this; }
|
||||
|
File diff suppressed because it is too large
Load Diff
25
include/boost/concept_check/borland.hpp
Normal file
25
include/boost/concept_check/borland.hpp
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright David Abrahams 2006. 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_CONCEPT_CHECK_BORLAND_DWA2006429_HPP
|
||||
# define BOOST_CONCEPT_CHECK_BORLAND_DWA2006429_HPP
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <class ModelFn>
|
||||
struct concept_check;
|
||||
|
||||
template <class Model>
|
||||
struct concept_check<void(*)(Model)>
|
||||
{
|
||||
enum { instantiate = sizeof((((Model*)0)->~Model()), 3) };
|
||||
};
|
||||
|
||||
# define BOOST_CONCEPT_ASSERT( ModelInParens ) \
|
||||
enum { BOOST_PP_CAT(boost_concept_check,__LINE__) = \
|
||||
boost::concept_check<void(*)ModelInParens>::instantiate \
|
||||
}
|
||||
|
||||
} // namespace boost::concept_checking
|
||||
|
||||
#endif // BOOST_CONCEPT_CHECK_BORLAND_DWA2006429_HPP
|
82
include/boost/concept_check/general.hpp
Normal file
82
include/boost/concept_check/general.hpp
Normal file
@ -0,0 +1,82 @@
|
||||
// Copyright David Abrahams 2006. 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_CONCEPT_CHECK_MSVC_DWA2006429_HPP
|
||||
# define BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP
|
||||
|
||||
# ifdef BOOST_OLD_CONCEPT_SUPPORT
|
||||
# include <boost/concept_check/has_constraints.hpp>
|
||||
# include <boost/type_traits/conditional.hpp>
|
||||
# endif
|
||||
|
||||
|
||||
// This implementation works on GCC and Comeau, but has actually been
|
||||
// fairly carefully tuned to work on GCC versions starting with
|
||||
// gcc-2.95.x. If you're trying to get an additional compiler to pass
|
||||
// the tests you might consider breaking out a separate gcc.hpp and
|
||||
// starting over on the general case.
|
||||
namespace boost
|
||||
{
|
||||
namespace concept_checking
|
||||
{
|
||||
template <void(*)()> struct instantiate {};
|
||||
}
|
||||
|
||||
template <class ModelFn> struct concept_check_;
|
||||
|
||||
template <class Model>
|
||||
void concept_check_failed()
|
||||
{
|
||||
((Model*)0)->~Model();
|
||||
}
|
||||
|
||||
template <class Model>
|
||||
struct concept_check
|
||||
{
|
||||
concept_checking::instantiate<concept_check_failed<Model> > x;
|
||||
enum { instantiate = 1 };
|
||||
};
|
||||
|
||||
# ifdef BOOST_OLD_CONCEPT_SUPPORT
|
||||
|
||||
template <class Model>
|
||||
void constraint_check_failed()
|
||||
{
|
||||
((Model*)0)->constraints();
|
||||
}
|
||||
|
||||
template <class Model>
|
||||
struct constraint_check
|
||||
{
|
||||
concept_checking::instantiate<constraint_check_failed<Model> > x;
|
||||
enum { instantiate = 1 };
|
||||
};
|
||||
|
||||
template <class Model>
|
||||
struct concept_check_<void(*)(Model)>
|
||||
: conditional<
|
||||
concept_checking::has_constraints<Model>::value
|
||||
, constraint_check<Model>
|
||||
, concept_check<Model>
|
||||
>::type
|
||||
{};
|
||||
|
||||
# else
|
||||
|
||||
template <class Model>
|
||||
struct concept_check_<void(*)(Model)>
|
||||
: concept_check<Model>
|
||||
{};
|
||||
|
||||
# endif
|
||||
|
||||
// Usage, in class or function context:
|
||||
//
|
||||
// BOOST_CONCEPT_ASSERT((UnaryFunctionConcept<F,bool,int>));
|
||||
# define BOOST_CONCEPT_ASSERT( ModelInParens ) \
|
||||
enum { BOOST_PP_CAT(boost_concept_check,__LINE__) = \
|
||||
::boost::concept_check_<void(*) ModelInParens>::instantiate \
|
||||
}
|
||||
}
|
||||
|
||||
#endif // BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP
|
31
include/boost/concept_check/has_constraints.hpp
Normal file
31
include/boost/concept_check/has_constraints.hpp
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright David Abrahams 2006. 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_CONCEPT_CHECK_HAS_CONSTRAINTS_DWA2006429_HPP
|
||||
# define BOOST_CONCEPT_CHECK_HAS_CONSTRAINTS_DWA2006429_HPP
|
||||
|
||||
namespace boost { namespace concept_checking {
|
||||
|
||||
// Here we implement the "metafunction" that detects whether a
|
||||
// constraints metafunction exists
|
||||
typedef char yes;
|
||||
typedef char (&no)[2];
|
||||
|
||||
template <class Model, void (Model::*)()>
|
||||
struct wrap_constraints {};
|
||||
|
||||
template <class Model>
|
||||
inline yes has_constraints_(Model*, wrap_constraints<Model,&Model::constraints>* = 0);
|
||||
inline no has_constraints_(...);
|
||||
|
||||
template <class Model>
|
||||
struct has_constraints
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool
|
||||
, value = sizeof( concept_checking::has_constraints_((Model*)0) ) == 1 );
|
||||
};
|
||||
|
||||
}} // namespace boost::concept_checking
|
||||
|
||||
#endif // BOOST_CONCEPT_CHECK_HAS_CONSTRAINTS_DWA2006429_HPP
|
90
include/boost/concept_check/msvc.hpp
Normal file
90
include/boost/concept_check/msvc.hpp
Normal file
@ -0,0 +1,90 @@
|
||||
// Copyright David Abrahams 2006. 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_CONCEPT_CHECK_MSVC_DWA2006429_HPP
|
||||
# define BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP
|
||||
|
||||
# ifdef BOOST_OLD_CONCEPT_SUPPORT
|
||||
# include <boost/concept_check/has_constraints.hpp>
|
||||
# include <boost/type_traits/conditional.hpp>
|
||||
# endif
|
||||
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace concept_checking
|
||||
{
|
||||
template <class Model>
|
||||
struct concept_check_
|
||||
{
|
||||
virtual void failed(Model* x)
|
||||
{
|
||||
x->~Model();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
# ifdef BOOST_OLD_CONCEPT_SUPPORT
|
||||
|
||||
namespace concept_checking
|
||||
{
|
||||
template <class Model>
|
||||
struct constraint_check
|
||||
{
|
||||
virtual void failed(Model* x)
|
||||
{
|
||||
x->constraints();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template <class Model>
|
||||
struct concept_check
|
||||
: conditional<
|
||||
concept_checking::has_constraints<Model>::value
|
||||
, concept_checking::constraint_check<Model>
|
||||
, concept_checking::concept_check_<Model>
|
||||
>::type
|
||||
{};
|
||||
|
||||
# else
|
||||
|
||||
template <class Model>
|
||||
struct concept_check
|
||||
: concept_checking::concept_check_<Model>
|
||||
{};
|
||||
|
||||
# endif
|
||||
|
||||
# if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
|
||||
|
||||
//
|
||||
// The iterator library sees some really strange errors unless we
|
||||
// use partial specialization to extract the model type with
|
||||
// msvc-7.1
|
||||
//
|
||||
template <class Model>
|
||||
struct concept_check<void(*)(Model)>
|
||||
: concept_check<Model>
|
||||
{ };
|
||||
|
||||
# define BOOST_CONCEPT_ASSERT( ModelInParens ) \
|
||||
enum { BOOST_PP_CAT(boost_concept_check,__LINE__) = \
|
||||
sizeof(::boost::concept_check<void(*) ModelInParens>) \
|
||||
}
|
||||
|
||||
# else
|
||||
|
||||
template <class Model>
|
||||
concept_check<Model>
|
||||
concept_check_(void(*)(Model));
|
||||
|
||||
# define BOOST_CONCEPT_ASSERT( ModelInParens ) \
|
||||
enum { BOOST_PP_CAT(boost_concept_check,__LINE__) = \
|
||||
sizeof(::boost::concept_check_((void(*) ModelInParens)0)) \
|
||||
}
|
||||
|
||||
# endif
|
||||
}
|
||||
|
||||
#endif // BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP
|
@ -4,6 +4,10 @@
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="concept_check.htm">concept_check.htm</a>.
|
||||
<a href="concept_check.htm">concept_check.htm</a>. <hr>
|
||||
<p><EFBFBD> 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>
|
||||
</body>
|
||||
</html>
|
30
meta/explicit-failures-markup.xml
Normal file
30
meta/explicit-failures-markup.xml
Normal file
@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<explicit-failures-markup>
|
||||
<!-- concept_check -->
|
||||
<library name="concept_check">
|
||||
<test name="class_concept_fail_expected">
|
||||
<mark-failure>
|
||||
<toolset name="cw-8.3*"/>
|
||||
<note author="B. Dawes" refid="3"/>
|
||||
</mark-failure>
|
||||
</test>
|
||||
<test name="class_concept_fail_expected">
|
||||
<mark-failure>
|
||||
<toolset name="borland-5*"/>
|
||||
<toolset name="msvc-6.5*"/>
|
||||
<toolset name="msvc-7.0"/>
|
||||
<note author="Jeremy Siek"/>
|
||||
</mark-failure>
|
||||
</test>
|
||||
<test name="stl_concept_check">
|
||||
<mark-failure>
|
||||
<toolset name="hp_cxx*"/>
|
||||
<note author="Markus Schoepflin" date="09 Dec 2007">
|
||||
This version of the Rogue Wave library fails to provide all
|
||||
needed addition operators for the iterator type and the
|
||||
difference type of std::deque.
|
||||
</note>
|
||||
</mark-failure>
|
||||
</test>
|
||||
</library>
|
||||
</explicit-failures-markup>
|
16
meta/libraries.json
Normal file
16
meta/libraries.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"key": "concept_check",
|
||||
"name": "Concept Check",
|
||||
"authors": [
|
||||
"Jeremy Siek"
|
||||
],
|
||||
"description": "Tools for generic programming.",
|
||||
"category": [
|
||||
"Correctness",
|
||||
"Generic"
|
||||
],
|
||||
"maintainers": [
|
||||
"Jeremy Siek <jeremy.siek -at- gmail.com>"
|
||||
],
|
||||
"cxxstd": "03"
|
||||
}
|
@ -1,57 +1,55 @@
|
||||
<HTML>
|
||||
<!--
|
||||
-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 2000
|
||||
--
|
||||
-- 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. We make no
|
||||
-- representations about the suitability of this software for any
|
||||
-- purpose. It is provided "as is" without express or implied warranty.
|
||||
-->
|
||||
<Head>
|
||||
<Title>Programming With Concepts</Title>
|
||||
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
|
||||
ALINK="#ff0000">
|
||||
<IMG SRC="../../c++boost.gif"
|
||||
ALT="C++ Boost" width="277" height="86">
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<BR Clear>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<!-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 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) -->
|
||||
|
||||
<h2><a name="programming-with-concepts">Programming with Concepts</a></h2>
|
||||
<head>
|
||||
<meta name="generator" content=
|
||||
"HTML Tidy for Linux/x86 (vers 1 September 2005), see www.w3.org" />
|
||||
|
||||
The process of deciding how to group requirements into concepts and
|
||||
deciding which concepts to use in each algorithm is perhaps the most
|
||||
difficult (yet most important) part of building a generic library.
|
||||
A guiding principle to use during this process is one we
|
||||
call the <i>requirement minimization principle</i>.
|
||||
<title>Programming With Concepts</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii" />
|
||||
<link rel="stylesheet" href="../../rst.css" type="text/css" />
|
||||
</head>
|
||||
|
||||
<p>
|
||||
<b>Requirement Minimization Principle:</b> Minimize the requirements
|
||||
on the input parameters of a component to increase its reusability.
|
||||
<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" />
|
||||
|
||||
<p>
|
||||
There is natural tension in this statement. By definition, the input
|
||||
parameters must be used by the component in order for the component to
|
||||
accomplish its task (by ``component'' we mean a function or class
|
||||
template). The challenge then is to implement the component in such a
|
||||
way that makes the fewest assumptions (the minimum requirements) about
|
||||
the inputs while still accomplishing the task.
|
||||
<h2><a name="programming-with-concepts" id=
|
||||
"programming-with-concepts">Programming with Concepts</a></h2>
|
||||
|
||||
<p>
|
||||
The traditional notions of <i>abstraction</i> tie in directly to the
|
||||
idea of minimal requirements. The more abstract the input, the fewer
|
||||
the requirements. Thus, concepts are simply the embodiment of generic
|
||||
abstract data types in C++ template programming.
|
||||
<p>The process of deciding how to group requirements into concepts and
|
||||
deciding which concepts to use in each algorithm is perhaps the most
|
||||
difficult (yet most important) part of building a generic library. A
|
||||
guiding principle to use during this process is one we call the
|
||||
<i>requirement minimization principle</i>.</p>
|
||||
|
||||
<p>
|
||||
When designing the concepts for some problem domain it is important to
|
||||
keep in mind their purpose, namely to express the requirements for the
|
||||
input to the components. With respect to the requirement minimization
|
||||
principle, this means we want to minimize concepts.
|
||||
<p><b>Requirement Minimization Principle:</b> Minimize the requirements on
|
||||
the input parameters of a component to increase its reusability.</p>
|
||||
|
||||
<!-- the following discussion does not match the Standard definition
|
||||
<p>There is natural tension in this statement. By definition, the input
|
||||
parameters must be used by the component in order for the component to
|
||||
accomplish its task (by ``component'' we mean a function or class
|
||||
template). The challenge then is to implement the component in such a way
|
||||
that makes the fewest assumptions (the minimum requirements) about the
|
||||
inputs while still accomplishing the task.</p>
|
||||
|
||||
<p>The traditional notions of <i>abstraction</i> tie in directly to the
|
||||
idea of minimal requirements. The more abstract the input, the fewer the
|
||||
requirements. Thus, concepts are simply the embodiment of generic abstract
|
||||
data types in C++ template programming.</p>
|
||||
|
||||
<p>When designing the concepts for some problem domain it is important to
|
||||
keep in mind their purpose, namely to express the requirements for the
|
||||
input to the components. With respect to the requirement minimization
|
||||
principle, this means we want to minimize concepts.
|
||||
<!-- the following discussion does not match the Standard definition
|
||||
of LessThanComparable and needs to be changed -Jeremy
|
||||
|
||||
<p>
|
||||
@ -62,7 +60,7 @@ in the concept.
|
||||
For example, the
|
||||
<tt>std::stable_sort()</tt> function requires that the value type of
|
||||
the iterator be <a
|
||||
href="http://www.sgi.com/tech/stl/LessThanComparable.html">
|
||||
href="http://www.boost.org/sgi/stl/LessThanComparable.html">
|
||||
LessThanComparable</a>, which not only
|
||||
includes <tt>operator<()</tt>, but also <tt>operator>()</tt>,
|
||||
<tt>operator<=()</tt>, and <tt>operator>=()</tt>.
|
||||
@ -70,25 +68,25 @@ It turns out that <tt>std::stable_sort()</tt> only uses
|
||||
<tt>operator<()</tt>. The question then arises: should
|
||||
<tt>std::stable_sort()</tt> be specified in terms of the concept
|
||||
<a
|
||||
href="http://www.sgi.com/tech/stl/LessThanComparable.html">
|
||||
href="http://www.boost.org/sgi/stl/LessThanComparable.html">
|
||||
LessThanComparable</a> or in terms of a concept that only
|
||||
requires <tt>operator<()</tt>?
|
||||
|
||||
<p>
|
||||
We remark first that the use of <a
|
||||
href="http://www.sgi.com/tech/stl/LessThanComparable.html">
|
||||
href="http://www.boost.org/sgi/stl/LessThanComparable.html">
|
||||
LessThanComparable</a> does not really violate the requirement
|
||||
minimization principle because all of the other operators can be
|
||||
trivially implemented in terms of <tt>operator<()</tt>. By
|
||||
``trivial'' we mean one line of code and a constant run-time cost.
|
||||
More fundamentally, however, the use of <a
|
||||
href="http://www.sgi.com/tech/stl/LessThanComparable.html">
|
||||
href="http://www.boost.org/sgi/stl/LessThanComparable.html">
|
||||
LessThanComparable</a> does not violate the requirement minimization
|
||||
principle because all of the comparison operators (<tt><</tt>,
|
||||
<tt>></tt>, <tt><=</tt>, <tt>>=</tt>) are conceptually equivalent (in
|
||||
a mathematical sense). Adding conceptually equivalent valid
|
||||
expressions is not a violation of the requirement minimization
|
||||
principle because no new semantics are being added --- only new
|
||||
principle because no new semantics are being added === only new
|
||||
syntax. The added syntax increases re-usability.
|
||||
|
||||
<p>
|
||||
@ -100,49 +98,47 @@ implementation in places to use <tt>operator>()</tt> instead of
|
||||
requirements are part of the public interface, such a change could
|
||||
potentially break client code. If instead
|
||||
<a
|
||||
href="http://www.sgi.com/tech/stl/LessThanComparable.html">
|
||||
href="http://www.boost.org/sgi/stl/LessThanComparable.html">
|
||||
LessThanComparable</a> is given as the requirement for
|
||||
<tt>std::stable_sort()</tt>, then the maintainer is given a reasonable
|
||||
amount of flexibility within which to work.
|
||||
|
||||
-->
|
||||
--></p>
|
||||
|
||||
<p>
|
||||
Minimality in concepts is a property associated with the underlying
|
||||
semantics of the problem domain being represented. In the problem
|
||||
domain of basic containers, requiring traversal in a single direction
|
||||
is a smaller requirement than requiring traversal in both directions
|
||||
(hence the distinction between <a
|
||||
href="http://www.sgi.com/tech/stl/ForwardIterator.html">
|
||||
ForwardIterator</a> and
|
||||
<a
|
||||
href="http://www.sgi.com/tech/stl/BidirectionalIterator.html">
|
||||
BidirectionalIterator</a>). The semantic difference can be easily seen
|
||||
in the difference between the set of concrete data structures that
|
||||
have forward iterators versus the set that has bidirectional
|
||||
iterators. For example, singly-linked lists would fall in the set of
|
||||
data structures having forward iterators, but not bidirectional
|
||||
iterators. In addition, the set of algorithms that one can implement
|
||||
using only forward iterators is quite different than the set that can
|
||||
be implemented with bidirectional iterators. Because of this, it is
|
||||
important to factor families of requirements into rather fine-grained
|
||||
concepts. For example, the requirements for iterators are factored
|
||||
into the six STL iterator concepts (trivial, output, input, forward,
|
||||
bidirectional, and random access).
|
||||
<p>Minimality in concepts is a property associated with the underlying
|
||||
semantics of the problem domain being represented. In the problem domain of
|
||||
basic containers, requiring traversal in a single direction is a smaller
|
||||
requirement than requiring traversal in both directions (hence the
|
||||
distinction between <a href=
|
||||
"http://www.boost.org/sgi/stl/ForwardIterator.html">ForwardIterator</a> and
|
||||
<a href=
|
||||
"http://www.boost.org/sgi/stl/BidirectionalIterator.html">BidirectionalIterator</a>).
|
||||
The semantic difference can be easily seen in the difference between the
|
||||
set of concrete data structures that have forward iterators versus the set
|
||||
that has bidirectional iterators. For example, singly-linked lists would
|
||||
fall in the set of data structures having forward iterators, but not
|
||||
bidirectional iterators. In addition, the set of algorithms that one can
|
||||
implement using only forward iterators is quite different than the set that
|
||||
can be implemented with bidirectional iterators. Because of this, it is
|
||||
important to factor families of requirements into rather fine-grained
|
||||
concepts. For example, the requirements for iterators are factored into the
|
||||
six STL iterator concepts (trivial, output, input, forward, bidirectional,
|
||||
and random access).</p>
|
||||
|
||||
<p>
|
||||
<a href="./implementation.htm">Next: Implementation</a><br>
|
||||
<a href="./concept_covering.htm">Prev: Concept Covering and Archetypes</a>
|
||||
<p><a href="./implementation.htm">Next: Implementation</a><br />
|
||||
<a href="./concept_covering.htm">Prev: Concept Covering and
|
||||
Archetypes</a><br /></p>
|
||||
<hr />
|
||||
|
||||
<br>
|
||||
<HR>
|
||||
<TABLE>
|
||||
<TR valign=top>
|
||||
<TD nowrap>Copyright © 2000</TD><TD>
|
||||
<A HREF="../../people/jeremy_siek.htm">Jeremy Siek</A>(<A
|
||||
HREF="mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</A>)
|
||||
Andrew Lumsdaine</A>(<A HREF="mailto:lums@osl.iu.edu">lums@osl.iu.edu</A>)
|
||||
</TD></TR></TABLE>
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td nowrap="nowrap">Copyright © 2000</td>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
<td><a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</a>(<a href=
|
||||
"mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</a>) Andrew
|
||||
Lumsdaine(<a href="mailto:lums@osl.iu.edu">lums@osl.iu.edu</a>),
|
||||
2007 <a href="mailto:dave@boost-consulting.com">David Abrahams</a>.
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
|
584
reference.htm
584
reference.htm
@ -1,314 +1,418 @@
|
||||
<HTML>
|
||||
<!--
|
||||
-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 2000
|
||||
--
|
||||
-- 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. We make no
|
||||
-- representations about the suitability of this software for any
|
||||
-- purpose. It is provided "as is" without express or implied warranty.
|
||||
-->
|
||||
<Head>
|
||||
<Title>Boost Concept Checking Reference</Title>
|
||||
</Head>
|
||||
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
|
||||
ALINK="#ff0000">
|
||||
<IMG SRC="../../c++boost.gif"
|
||||
ALT="C++ Boost" width="277" height="86">
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<BR Clear>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<!-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 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) -->
|
||||
|
||||
<h2><a name="reference">Reference</a></h2>
|
||||
<head>
|
||||
<meta name="generator" content=
|
||||
"HTML Tidy for Linux/x86 (vers 1 September 2005), see www.w3.org" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<link rel="stylesheet" href="../../rst.css" type="text/css" />
|
||||
|
||||
<OL>
|
||||
<LI><a href="#functions">Functions</a></LI>
|
||||
<LI><a href="#macros">Macros</a></LI>
|
||||
<LI><a href="#basic-concepts">Basic Concept Checking Classes</a></LI>
|
||||
<LI><a href="#iterator-concepts">Iterator Concept Checking Classes</a></LI>
|
||||
<LI><a href="#function-object-concepts">Function Object Concept Checking Classes</a></LI>
|
||||
<LI><a href="#container-concepts">Container Concept Checking Classes</a></LI>
|
||||
<LI><a href="#basic-archetype">Basic Archetype Classes</a></LI>
|
||||
<LI><a href="#iterator-archetype">Iterator Archetype Classes</a></LI>
|
||||
<LI><a href="#function-object-archetype">Function Object Archetype Classes</a></LI>
|
||||
<LI><a href="#container-archetype">Container Archetype Classes</a></LI>
|
||||
</OL>
|
||||
<title>Boost Concept Checking Reference</title>
|
||||
</head>
|
||||
|
||||
<h3><a name="functions">Functions</a></h3>
|
||||
<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" />
|
||||
|
||||
<pre>
|
||||
template <class Concept>
|
||||
void function_requires();
|
||||
<h2><a name="reference" id="reference">Reference</a></h2>
|
||||
|
||||
<ol>
|
||||
<li><a href="#macros">Macros</a></li>
|
||||
|
||||
<li><a href="#basic-concepts">Basic Concept Checking Classes</a></li>
|
||||
|
||||
<li><a href="#iterator-concepts">Iterator Concept Checking
|
||||
Classes</a></li>
|
||||
|
||||
<li><a href="#function-object-concepts">Function Object Concept Checking
|
||||
Classes</a></li>
|
||||
|
||||
<li><a href="#container-concepts">Container Concept Checking
|
||||
Classes</a></li>
|
||||
|
||||
<li><a href="#basic-archetype">Basic Archetype Classes</a></li>
|
||||
|
||||
<li><a href="#iterator-archetype">Iterator Archetype Classes</a></li>
|
||||
|
||||
<li><a href="#function-object-archetype">Function Object Archetype
|
||||
Classes</a></li>
|
||||
|
||||
<li><a href="#container-archetype">Container Archetype Classes</a></li>
|
||||
|
||||
<li><a href="#deprecated-functions">Deprecated Functions</a></li>
|
||||
|
||||
<li><a href="#deprecated-macros">Deprecated Macros</a></li>
|
||||
|
||||
<li><a href="#deprecated-concept-checking-classes">Deprecated Concept
|
||||
Checking Classes</a></li>
|
||||
</ol>
|
||||
|
||||
<h3><a name="macros" id="macros">Macros</a></h3>
|
||||
<pre>
|
||||
#include "boost/concept/assert.hpp"
|
||||
|
||||
BOOST_CONCEPT_ASSERT((<em>concept checking class template specialization</em>));
|
||||
</pre>
|
||||
|
||||
<h3><a name="macros">Macros</a></h3>
|
||||
<p><strong>Effects:</strong> causes a compilation failure if the concept is
|
||||
not satisfied.<br />
|
||||
<strong>Note:</strong> this macro can be used at global, class, or function
|
||||
scope.</p>
|
||||
|
||||
<pre>
|
||||
// Apply concept checks in class definitions.
|
||||
BOOST_CLASS_REQUIRE(<i>type</i>, <i>namespace-of-concept</i>, <i>concept</i>);
|
||||
BOOST_CLASS_REQUIRE2(<i>type1</i>, <i>type2</i>, <i>namespace-of-concept</i>, <i>concept</i>);
|
||||
BOOST_CLASS_REQUIRE3(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>namespace-of-concept</i>, <i>concept</i>);
|
||||
BOOST_CLASS_REQUIRE4(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>type4</i>, <i>namespace-of-concept</i>, <i>concept</i>);
|
||||
<pre>
|
||||
#include "boost/concept/requires.hpp"
|
||||
|
||||
<font color="gray">template <…<em>template parameters</em>…></font>
|
||||
BOOST_CONCEPT_REQUIRES(
|
||||
((<em>concept checking class template specialization<sub>1</sub></em>))
|
||||
((<em>concept checking class template specialization<sub>2</sub></em>))…
|
||||
((<em>concept checking class template specialization<sub>n</sub></em>))<strong>,</strong>
|
||||
(<em>function return type</em>)
|
||||
) <font color="gray"><em>function_template_name</em>(…<em>function parameters</em>…)</font>
|
||||
</pre>
|
||||
|
||||
Deprecated macros:
|
||||
<p><strong>Effects:</strong> causes a compilation failure if the
|
||||
given concepts are not satisfied.<br />
|
||||
<strong>Note:</strong> this macro is intended to be used in place of
|
||||
a function template's return type.</p>
|
||||
|
||||
<pre>
|
||||
// Apply concept checks in class definitions.
|
||||
BOOST_CLASS_REQUIRES(<i>type</i>, <i>concept</i>);
|
||||
BOOST_CLASS_REQUIRES2(<i>type1</i>, <i>type2</i>, <i>concept</i>);
|
||||
BOOST_CLASS_REQUIRES3(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>concept</i>);
|
||||
BOOST_CLASS_REQUIRES4(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>type4</i>, <i>concept</i>);
|
||||
<h3><a name="basic-concepts" id="basic-concepts">Basic Concept Checking
|
||||
Classes</a></h3>
|
||||
<pre>
|
||||
#include "boost/concept_check.hpp"
|
||||
|
||||
template <class T>
|
||||
struct Integer; // Is T a built-in integer type?
|
||||
|
||||
template <class T>
|
||||
struct SignedInteger; // Is T a built-in signed integer type?
|
||||
|
||||
template <class T>
|
||||
struct UnsignedInteger; // Is T a built-in unsigned integer type?
|
||||
|
||||
template <class X, class Y>
|
||||
struct Convertible; // Is X convertible to Y?
|
||||
|
||||
template <class T>
|
||||
struct <a href=
|
||||
"../utility/Assignable.html">Assignable</a>; // Standard ref 23.1
|
||||
|
||||
template <class T>
|
||||
struct SGI<a href=
|
||||
"http://www.boost.org/sgi/stl/Assignable.html">Assignable</a>;
|
||||
|
||||
template <class T>
|
||||
struct <a href=
|
||||
"http://www.boost.org/sgi/stl/DefaultConstructible.html">DefaultConstructible</a>;
|
||||
|
||||
template <class T>
|
||||
struct <a href=
|
||||
"../utility/CopyConstructible.html">CopyConstructible</a>; // Standard ref 20.1.3
|
||||
|
||||
template <class T>
|
||||
struct <a href=
|
||||
"http://www.boost.org/sgi/stl/EqualityComparable.html">EqualityComparable</a>; // Standard ref 20.1.1
|
||||
|
||||
template <class T>
|
||||
struct <a href=
|
||||
"../utility/LessThanComparable.html">LessThanComparable</a>; // Standard ref 20.1.2
|
||||
|
||||
template <class T>
|
||||
struct Comparable; // The SGI STL <a href=
|
||||
"http://www.boost.org/sgi/stl/LessThanComparable.html">LessThanComparable</a> concept
|
||||
</pre>
|
||||
|
||||
<h3><a name="basic-concepts">Basic Concept Checking Classes</a></h3>
|
||||
<h3><a name="iterator-concepts" id="iterator-concepts">Iterator Concept
|
||||
Checking Classes</a></h3>
|
||||
<pre>
|
||||
template <class Iter>
|
||||
struct <a href=
|
||||
"http://www.boost.org/sgi/stl/InputIterator.html">InputIterator</a>; // Standard ref 24.1.1 Table 72
|
||||
|
||||
<pre>
|
||||
template <class T>
|
||||
struct IntegerConcept; // Is T a built-in integer type?
|
||||
template <class Iter, class T>
|
||||
struct <a href=
|
||||
"http://www.boost.org/sgi/stl/OutputIterator.html">OutputIterator</a>; // Standard ref 24.1.2 Table 73
|
||||
|
||||
template <class T>
|
||||
struct SignedIntegerConcept; // Is T a built-in signed integer type?
|
||||
template <class Iter>
|
||||
struct <a href=
|
||||
"http://www.boost.org/sgi/stl/ForwardIterator.html">ForwardIterator</a>; // Standard ref 24.1.3 Table 74
|
||||
|
||||
template <class T>
|
||||
struct UnsignedIntegerConcept; // Is T a built-in unsigned integer type?
|
||||
template <class Iter>
|
||||
struct Mutable_ForwardIterator;
|
||||
|
||||
template <class X, class Y>
|
||||
struct ConvertibleConcept; // Is X convertible to Y?
|
||||
template <class Iter>
|
||||
struct <a href=
|
||||
"http://www.boost.org/sgi/stl/BidirectionalIterator.html">BidirectionalIterator</a>; // Standard ref 24.1.4 Table 75
|
||||
|
||||
template <class T>
|
||||
struct <a href="../utility/Assignable.html">Assignable</a>Concept; // Standard ref 23.1
|
||||
template <class Iter>
|
||||
struct Mutable_BidirectionalIterator;
|
||||
|
||||
template <class T>
|
||||
struct SGI<a href="http://www.sgi.com/tech/stl/Assignable.html">Assignable</a>Concept;
|
||||
template <class Iter>
|
||||
struct <a href=
|
||||
"http://www.boost.org/sgi/stl/RandomAccessIterator.html">RandomAccessIterator</a>; // Standard ref 24.1.5 Table 76
|
||||
|
||||
template <class T>
|
||||
struct <a
|
||||
href="http://www.sgi.com/tech/stl/DefaultConstructible.html">DefaultConstructible</a>Concept;
|
||||
|
||||
template <class T>
|
||||
struct <a href="../utility/CopyConstructible.html">CopyConstructible</a>Concept; // Standard ref 20.1.3
|
||||
|
||||
template <class T>
|
||||
struct <a href="http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</a>Concept; // Standard ref 20.1.1
|
||||
|
||||
template <class T>
|
||||
struct <a href="../utility/LessThanComparable.html">LessThanComparable</a>Concept; // Standard ref 20.1.2
|
||||
|
||||
template <class T>
|
||||
struct ComparableConcept; // The SGI STL <a href="http://www.sgi.com/tech/stl/LessThanComparable.html">LessThanComparable</a> concept
|
||||
template <class Iter>
|
||||
struct Mutable_RandomAccessIterator;
|
||||
</pre>
|
||||
|
||||
<h3><a name="iterator-concepts">Iterator Concept Checking Classes</a></h3>
|
||||
<h3><a name="function-object-concepts" id=
|
||||
"function-object-concepts">Function Object Concept Checking
|
||||
Classes</a></h3>
|
||||
<pre>
|
||||
#include "boost/concept_check.hpp"
|
||||
|
||||
<pre>
|
||||
template <class Iter>
|
||||
struct <a href="http://www.sgi.com/tech/stl/trivial.html">TrivialIterator</a>Concept;
|
||||
template <class Func, class Return>
|
||||
struct <a href="http://www.boost.org/sgi/stl/Generator.html">Generator</a>;
|
||||
|
||||
template <class Iter>
|
||||
struct Mutable_TrivialIteratorConcept;
|
||||
template <class Func, class Return, class Arg>
|
||||
struct <a href=
|
||||
"http://www.boost.org/sgi/stl/UnaryFunction.html">UnaryFunction</a>;
|
||||
|
||||
template <class Iter>
|
||||
struct <a href="http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>Concept; // Standard ref 24.1.1 Table 72
|
||||
template <class Func, class Return, class First, class Second>
|
||||
struct <a href=
|
||||
"http://www.boost.org/sgi/stl/BinaryFunction.html">BinaryFunction</a>;
|
||||
|
||||
template <class Iter, class T>
|
||||
struct <a href="http://www.sgi.com/tech/stl/OutputIterator.html">OutputIterator</a>Concept; // Standard ref 24.1.2 Table 73
|
||||
template <class Func, class Arg>
|
||||
struct Unary<a href=
|
||||
"http://www.boost.org/sgi/stl/Predicate.html">Predicate</a>;
|
||||
|
||||
template <class Iter>
|
||||
struct <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>Concept; // Standard ref 24.1.3 Table 74
|
||||
template <class Func, class First, class Second>
|
||||
struct <a href=
|
||||
"http://www.boost.org/sgi/stl/BinaryPredicate.html">BinaryPredicate</a>;
|
||||
|
||||
template <class Iter>
|
||||
struct Mutable_ForwardIteratorConcept;
|
||||
template <class Func, class First, class Second>
|
||||
struct Const_BinaryPredicate;
|
||||
|
||||
template <class Iter>
|
||||
struct <a href="http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterator</a>Concept; // Standard ref 24.1.4 Table 75
|
||||
template <class Func, class Return>
|
||||
struct <a href=
|
||||
"http://www.boost.org/sgi/stl/AdaptableGenerator.html">AdaptableGenerator</a>;
|
||||
|
||||
template <class Iter>
|
||||
struct Mutable_BidirectionalIteratorConcept;
|
||||
template <class Func, class Return, class Arg>
|
||||
struct <a href=
|
||||
"http://www.boost.org/sgi/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>;
|
||||
|
||||
template <class Iter>
|
||||
struct <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a>Concept; // Standard ref 24.1.5 Table 76
|
||||
template <class Func, class First, class Second>
|
||||
struct <a href=
|
||||
"http://www.boost.org/sgi/stl/AdaptableBinaryFunction.html">AdaptableBinaryFunction</a>;
|
||||
|
||||
template <class Iter>
|
||||
struct Mutable_RandomAccessIteratorConcept;
|
||||
template <class Func, class Arg>
|
||||
struct <a href=
|
||||
"http://www.boost.org/sgi/stl/AdaptablePredicate.html">AdaptablePredicate</a>;
|
||||
|
||||
template <class Func, class First, class Second>
|
||||
struct <a href=
|
||||
"http://www.boost.org/sgi/stl/AdaptableBinaryPredicate.html">AdaptableBinaryPredicate</a>;
|
||||
</pre>
|
||||
|
||||
<h3><a name="function-object-concepts">Function Object Concept Checking Classes</a></h3>
|
||||
<h3><a name="container-concepts" id="container-concepts">Container Concept
|
||||
Checking Classes</a></h3>
|
||||
<pre>
|
||||
#include "boost/concept_check.hpp"
|
||||
|
||||
<pre>
|
||||
template <class Func, class Return>
|
||||
struct <a href="http://www.sgi.com/tech/stl/Generator.html">Generator</a>Concept;
|
||||
template <class C>
|
||||
struct <a href=
|
||||
"http://www.boost.org/sgi/stl/Container.html">Container</a>; // Standard ref 23.1 Table 65
|
||||
|
||||
template <class Func, class Return, class Arg>
|
||||
struct <a href="http://www.sgi.com/tech/stl/UnaryFunction.html">UnaryFunction</a>Concept;
|
||||
template <class C>
|
||||
struct Mutable_Container;
|
||||
|
||||
template <class Func, class Return, class First, class Second>
|
||||
struct <a href="http://www.sgi.com/tech/stl/BinaryFunction.html">BinaryFunction</a>Concept;
|
||||
template <class C>
|
||||
struct <a href=
|
||||
"http://www.boost.org/sgi/stl/ForwardContainer.html">ForwardContainer</a>;
|
||||
|
||||
template <class Func, class Arg>
|
||||
struct Unary<a href="http://www.sgi.com/tech/stl/Predicate.html">Predicate</a>Concept;
|
||||
template <class C>
|
||||
struct Mutable_ForwardContainer;
|
||||
|
||||
template <class Func, class First, class Second>
|
||||
struct <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>Concept;
|
||||
template <class C>
|
||||
struct <a href=
|
||||
"http://www.boost.org/sgi/stl/ReversibleContainer.html">ReversibleContainer</a>; // Standard ref 23.1 Table 66
|
||||
|
||||
template <class Func, class First, class Second>
|
||||
struct Const_BinaryPredicateConcept;
|
||||
template <class C>
|
||||
struct Mutable_ReversibleContainer;
|
||||
|
||||
template <class Func, class Return>
|
||||
struct <a href="http://www.sgi.com/tech/stl/AdaptableGenerator.html">AdaptableGenerator</a>Concept;
|
||||
template <class C>
|
||||
struct <a href=
|
||||
"http://www.boost.org/sgi/stl/RandomAccessContainer.html">RandomAccessContainer</a>;
|
||||
|
||||
template <class Func, class Return, class Arg>
|
||||
struct <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>Concept;
|
||||
template <class C>
|
||||
struct Mutable_RandomAccessContainer;
|
||||
|
||||
template <class Func, class First, class Second>
|
||||
struct <a href="http://www.sgi.com/tech/stl/AdaptableBinaryFunction.html">AdaptableBinaryFunction</a>Concept;
|
||||
template <class C>
|
||||
struct <a href=
|
||||
"http://www.boost.org/sgi/stl/Sequence.html">Sequence</a>; // Standard ref 23.1.1
|
||||
|
||||
template <class Func, class Arg>
|
||||
struct <a href="http://www.sgi.com/tech/stl/AdaptablePredicate.html">AdaptablePredicate</a>Concept;
|
||||
template <class C>
|
||||
struct <a href=
|
||||
"http://www.boost.org/sgi/stl/FrontInsertionSequence.html">FrontInsertionSequence</a>;
|
||||
|
||||
template <class Func, class First, class Second>
|
||||
struct <a href="http://www.sgi.com/tech/stl/AdaptableBinaryPredicate.html">AdaptableBinaryPredicate</a>Concept;
|
||||
|
||||
template <class C>
|
||||
struct <a href=
|
||||
"http://www.boost.org/sgi/stl/BackInsertionSequence.html">BackInsertionSequence</a>;
|
||||
|
||||
template <class C>
|
||||
struct <a href=
|
||||
"http://www.boost.org/sgi/stl/AssociativeContainer.html">AssociativeContainer</a>; // Standard ref 23.1.2 Table 69
|
||||
|
||||
template <class C>
|
||||
struct <a href=
|
||||
"http://www.boost.org/sgi/stl/UniqueAssociativeContainer.html">UniqueAssociativeContainer</a>;
|
||||
|
||||
template <class C>
|
||||
struct <a href=
|
||||
"http://www.boost.org/sgi/stl/MultipleAssociativeContainer.html">MultipleAssociativeContainer</a>;
|
||||
|
||||
template <class C>
|
||||
struct <a href=
|
||||
"http://www.boost.org/sgi/stl/SimpleAssociativeContainer.html">SimpleAssociativeContainer</a>;
|
||||
|
||||
template <class C>
|
||||
struct <a href=
|
||||
"http://www.boost.org/sgi/stl/PairAssociativeContainer.html">PairAssociativeContainer</a>;
|
||||
|
||||
template <class C>
|
||||
struct <a href=
|
||||
"http://www.boost.org/sgi/stl/SortedAssociativeContainer.html">SortedAssociativeContainer</a>;
|
||||
|
||||
template <class C>
|
||||
struct <a href=
|
||||
"../utility/Collection.html">Collection</a>;
|
||||
</pre>
|
||||
|
||||
<h3><a name="container-concepts">Container Concept Checking Classes</a></h3>
|
||||
<h3><a name="basic-archetype" id="basic-archetype">Basic Archetype
|
||||
Classes</a></h3>
|
||||
<pre>
|
||||
#include "boost/concept_archetype.hpp"
|
||||
|
||||
<pre>
|
||||
template <class C>
|
||||
struct <a href="http://www.sgi.com/tech/stl/Container.html">Container</a>Concept; // Standard ref 23.1 Table 65
|
||||
template <class T = int>
|
||||
class null_archetype; // A type that models no concepts.
|
||||
|
||||
template <class C>
|
||||
struct Mutable_ContainerConcept;
|
||||
template <class Base = null_archetype>
|
||||
class default_constructible_archetype;
|
||||
|
||||
template <class C>
|
||||
struct <a href="http://www.sgi.com/tech/stl/ForwardContainer.html">ForwardContainer</a>Concept;
|
||||
template <class Base = null_archetype>
|
||||
class assignable_archetype;
|
||||
|
||||
template <class C>
|
||||
struct Mutable_ForwardContainerConcept;
|
||||
template <class Base = null_archetype>
|
||||
class copy_constructible_archetype;
|
||||
|
||||
template <class C>
|
||||
struct <a href="http://www.sgi.com/tech/stl/ReversibleContainer.html">ReversibleContainer</a>Concept; // Standard ref 23.1 Table 66
|
||||
template <class Base = null_archetype>
|
||||
class equality_comparable_archetype;
|
||||
|
||||
template <class C>
|
||||
struct Mutable_ReversibleContainerConcept;
|
||||
|
||||
template <class C>
|
||||
struct <a href="http://www.sgi.com/tech/stl/RandomAccessContainer.html">RandomAccessContainer</a>Concept;
|
||||
|
||||
template <class C>
|
||||
struct Mutable_RandomAccessContainerConcept;
|
||||
|
||||
template <class C>
|
||||
struct <a href="http://www.sgi.com/tech/stl/SequenceContainer.html">Sequence</a>Concept; // Standard ref 23.1.1
|
||||
|
||||
template <class C>
|
||||
struct <a href="http://www.sgi.com/tech/stl/FrontInsertionSequence.html">FrontInsertionSequence</a>Concept;
|
||||
|
||||
template <class C>
|
||||
struct <a href="http://www.sgi.com/tech/stl/BackInsertionSequence.html">BackInsertionSequence</a>Concept;
|
||||
|
||||
template <class C>
|
||||
struct <a href="http://www.sgi.com/tech/stl/Associative.html">AssociativeContainer</a>Concept; // Standard ref 23.1.2 Table 69
|
||||
|
||||
template <class C>
|
||||
struct <a href="http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html">UniqueAssociativeContainer</a>Concept;
|
||||
|
||||
template <class C>
|
||||
struct <a href="http://www.sgi.com/tech/stl/MultipleAssociativeContainer.html">MultipleAssociativeContainer</a>Concept;
|
||||
|
||||
template <class C>
|
||||
struct <a href="http://www.sgi.com/tech/stl/SimpleAssociativeContainer.html">SimpleAssociativeContainer</a>Concept;
|
||||
|
||||
template <class C>
|
||||
struct <a href="http://www.sgi.com/tech/stl/PairAssociativeContainer.html">PairAssociativeContainer</a>Concept;
|
||||
|
||||
template <class C>
|
||||
struct <a href="http://www.sgi.com/tech/stl/SortedAssociativeContainer.html">SortedAssociativeContainer</a>Concept;
|
||||
template <class T, class Base = null_archetype>
|
||||
class convertible_to_archetype;
|
||||
</pre>
|
||||
|
||||
<h3><a name="iterator-archetype" id="iterator-archetype">Iterator Archetype
|
||||
Classes</a></h3>
|
||||
<pre>
|
||||
#include "boost/concept_archetype.hpp"
|
||||
|
||||
<h3><a name="basic-archetype">Basic Archetype Classes</a></h3>
|
||||
template <class ValueType>
|
||||
class trivial_iterator_archetype;
|
||||
|
||||
<pre>
|
||||
template <class T = int>
|
||||
class null_archetype; // A type that models no concepts.
|
||||
template <class ValueType>
|
||||
class mutable_trivial_iterator_archetype;
|
||||
|
||||
template <class Base = null_archetype>
|
||||
class default_constructible_archetype;
|
||||
template <class ValueType>
|
||||
class input_iterator_archetype;
|
||||
|
||||
template <class Base = null_archetype>
|
||||
class assignable_archetype;
|
||||
template <class ValueType>
|
||||
class forward_iterator_archetype;
|
||||
|
||||
template <class Base = null_archetype>
|
||||
class copy_constructible_archetype;
|
||||
template <class ValueType>
|
||||
class bidirectional_iterator_archetype;
|
||||
|
||||
template <class Base = null_archetype>
|
||||
class equality_comparable_archetype;
|
||||
|
||||
template <class T, class Base = null_archetype>
|
||||
class convertible_to_archetype;
|
||||
template <class ValueType>
|
||||
class random_access_iterator_archetype;
|
||||
</pre>
|
||||
|
||||
<h3><a name="iterator-archetype">Iterator Archetype Classes</a></h3>
|
||||
<h3><a name="function-object-archetype" id=
|
||||
"function-object-archetype">Function Object Archetype Classes</a></h3>
|
||||
<pre>
|
||||
#include "boost/concept_archetype.hpp"
|
||||
|
||||
<pre>
|
||||
template <class ValueType>
|
||||
class trivial_iterator_archetype;
|
||||
template <class Arg, class Return>
|
||||
class unary_function_archetype;
|
||||
|
||||
template <class ValueType>
|
||||
class mutable_trivial_iterator_archetype;
|
||||
template <class Arg1, class Arg2, class Return>
|
||||
class binary_function_archetype;
|
||||
|
||||
template <class ValueType>
|
||||
class input_iterator_archetype;
|
||||
|
||||
template <class ValueType>
|
||||
class forward_iterator_archetype;
|
||||
|
||||
template <class ValueType>
|
||||
class bidirectional_iterator_archetype;
|
||||
|
||||
template <class ValueType>
|
||||
class random_access_iterator_archetype;
|
||||
template <class Arg>
|
||||
class predicate_archetype;
|
||||
|
||||
template <class Arg1, class Arg2>
|
||||
class binary_predicate_archetype;
|
||||
</pre>
|
||||
|
||||
<h3><a name="function-object-archetype">Function Object Archetype Classes</a></h3>
|
||||
|
||||
<pre>
|
||||
template <class Arg, class Return>
|
||||
class unary_function_archetype;
|
||||
|
||||
template <class Arg1, class Arg2, class Return>
|
||||
class binary_function_archetype;
|
||||
|
||||
template <class Arg>
|
||||
class predicate_archetype;
|
||||
|
||||
template <class Arg1, class Arg2>
|
||||
class binary_predicate_archetype;
|
||||
</pre>
|
||||
|
||||
<h3><a name="container-archetype">Container Archetype Classes</a></h3>
|
||||
|
||||
<pre>
|
||||
<h3><a name="container-archetype" id="container-archetype">Container
|
||||
Archetype Classes</a></h3>
|
||||
<pre>
|
||||
UNDER CONSTRUCTION
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
<a href="./concept_check.htm">Back to Introduction</a>
|
||||
<br>
|
||||
<a href="./implementation.htm">Prev: Implementation</a>
|
||||
<h3><a name="deprecated-functions" id="deprecated-functions">Deprecated
|
||||
Functions</a></h3>
|
||||
<pre>
|
||||
#include "boost/concept_check.hpp"
|
||||
|
||||
<br>
|
||||
<HR>
|
||||
<TABLE>
|
||||
<TR valign=top>
|
||||
<TD nowrap>Copyright © 2000</TD><TD>
|
||||
<A HREF="../../people/jeremy_siek.htm">Jeremy Siek</A>(<A
|
||||
HREF="mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</A>)
|
||||
Andrew Lumsdaine</A>(<A HREF="mailto:lums@osl.iu.edu">lums@osl.iu.edu</A>)
|
||||
</TD></TR></TABLE>
|
||||
template <class Concept>
|
||||
void function_requires();
|
||||
</pre>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
<p><code>function_requires()</code> has been deprecated in favor of <code>BOOST_CONCEPT_ASSERT</code>.
|
||||
This means that <del><code>function_requires< Concept<Type> >();</code></del>
|
||||
becomes <code>BOOST_CONCEPT_ASSERT((Concept<Type>));</code>
|
||||
(don't forget to <code>#include "boost/concept/assert.hpp"</code>).
|
||||
|
||||
|
||||
<h3><a name="deprecated-macros" id="deprecated-macros">Deprecated
|
||||
Macros</a></h3>
|
||||
<pre>
|
||||
#include "boost/concept_check.hpp"
|
||||
|
||||
// Apply concept checks in class definitions.
|
||||
BOOST_CLASS_REQUIRE(<i>type</i>, <i>namespace-of-concept</i>, <i>concept</i>);
|
||||
BOOST_CLASS_REQUIRE2(<i>type1</i>, <i>type2</i>, <i>namespace-of-concept</i>, <i>concept</i>);
|
||||
BOOST_CLASS_REQUIRE3(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>namespace-of-concept</i>, <i>concept</i>);
|
||||
BOOST_CLASS_REQUIRE4(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>type4</i>, <i>namespace-of-concept</i>, <i>concept</i>);
|
||||
|
||||
// Apply concept checks in class definitions.
|
||||
BOOST_CLASS_REQUIRES(<i>type</i>, <i>concept</i>);
|
||||
BOOST_CLASS_REQUIRES2(<i>type1</i>, <i>type2</i>, <i>concept</i>);
|
||||
BOOST_CLASS_REQUIRES3(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>concept</i>);
|
||||
BOOST_CLASS_REQUIRES4(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>type4</i>, <i>concept</i>);
|
||||
</pre>
|
||||
|
||||
<h3><a name="deprecated-concept-checking-classes" id=
|
||||
"deprecated-concept-checking-classes">Deprecated Concept Checking
|
||||
Classes</a></h3>
|
||||
|
||||
<p>For each of the concepts documented here, the library includes an
|
||||
identical concept checking class whose name ends in
|
||||
“<code>Concept</code>” For example, in
|
||||
addition to <code>RandomAccessIterator</code>, the library defines a
|
||||
<code>RandomAccessIteratorConcept</code> class template.</p>
|
||||
|
||||
<p><a href="./concept_check.htm">Back to Introduction</a><br />
|
||||
<a href="./implementation.htm">Prev: Implementation</a><br /></p>
|
||||
<hr />
|
||||
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td nowrap="nowrap">Copyright © 2000</td>
|
||||
|
||||
<td><a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</a>(<a href=
|
||||
"mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</a>) Andrew
|
||||
Lumsdaine(<a href="mailto:lums@osl.iu.edu">lums@osl.iu.edu</a>), 2007
|
||||
<a href="mailto:dave@boost-consulting.com">David Abrahams</a>.</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,93 +0,0 @@
|
||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
//
|
||||
// This file checks to see if various standard container
|
||||
// implementations live up to requirements specified in the C++
|
||||
// standard. As many implementations do not live to the requirements,
|
||||
// it is not uncommon for this file to fail to compile. The
|
||||
// BOOST_HIDE_EXPECTED_ERRORS macro is provided here if you want to
|
||||
// see as much of this file compile as possible.
|
||||
//
|
||||
|
||||
#include <boost/concept_check.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <deque>
|
||||
#ifndef BOOST_NO_SLIST
|
||||
#include <slist>
|
||||
#endif
|
||||
|
||||
// Define this macro if you want to hide the expected error, that is,
|
||||
// error in the various C++ standard library implementations.
|
||||
//
|
||||
//#define BOOST_HIDE_EXPECTED_ERRORS
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
using namespace boost;
|
||||
|
||||
#if defined(_ITERATOR_) && defined(BOOST_HIDE_EXPECTED_ERRORS)
|
||||
// VC++ STL implementation is not standard conformant and
|
||||
// fails to pass these concept checks
|
||||
#else
|
||||
typedef std::vector<int> Vector;
|
||||
typedef std::deque<int> Deque;
|
||||
typedef std::list<int> List;
|
||||
|
||||
// VC++ missing pointer and const_pointer typedefs
|
||||
function_requires< Mutable_RandomAccessContainerConcept<Vector> >();
|
||||
function_requires< BackInsertionSequenceConcept<Vector> >();
|
||||
|
||||
#if !(defined(__GNUC__) && defined(BOOST_HIDE_EXPECTED_ERRORS))
|
||||
#if !(defined(__sgi) && defined(BOOST_HIDE_EXPECTED_ERRORS))
|
||||
// old deque iterator missing n + iter operation
|
||||
function_requires< Mutable_RandomAccessContainerConcept<Deque> >();
|
||||
#endif
|
||||
// warnings about signed and unsigned in old deque version
|
||||
function_requires< FrontInsertionSequenceConcept<Deque> >();
|
||||
function_requires< BackInsertionSequenceConcept<Deque> >();
|
||||
#endif
|
||||
|
||||
// VC++ missing pointer and const_pointer typedefs
|
||||
function_requires< Mutable_ReversibleContainerConcept<List> >();
|
||||
function_requires< FrontInsertionSequenceConcept<List> >();
|
||||
function_requires< BackInsertionSequenceConcept<List> >();
|
||||
|
||||
#ifndef BOOST_NO_SLIST
|
||||
typedef BOOST_STD_EXTENSION_NAMESPACE::slist<int> SList;
|
||||
function_requires< FrontInsertionSequenceConcept<SList> >();
|
||||
#endif
|
||||
|
||||
typedef std::set<int> Set;
|
||||
typedef std::multiset<int> MultiSet;
|
||||
typedef std::map<int,int> Map;
|
||||
typedef std::multimap<int,int> MultiMap;
|
||||
|
||||
function_requires< SortedAssociativeContainerConcept<Set> >();
|
||||
function_requires< SimpleAssociativeContainerConcept<Set> >();
|
||||
function_requires< UniqueAssociativeContainerConcept<Set> >();
|
||||
|
||||
function_requires< SortedAssociativeContainerConcept<MultiSet> >();
|
||||
function_requires< SimpleAssociativeContainerConcept<MultiSet> >();
|
||||
function_requires< MultipleAssociativeContainerConcept<MultiSet> >();
|
||||
|
||||
function_requires< SortedAssociativeContainerConcept<Map> >();
|
||||
function_requires< UniqueAssociativeContainerConcept<Map> >();
|
||||
function_requires< PairAssociativeContainerConcept<Map> >();
|
||||
|
||||
function_requires< SortedAssociativeContainerConcept<MultiMap> >();
|
||||
function_requires< MultipleAssociativeContainerConcept<MultiMap> >();
|
||||
function_requires< PairAssociativeContainerConcept<MultiMap> >();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,90 +0,0 @@
|
||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
//
|
||||
// This file checks to see if various standard container
|
||||
// implementations live up to requirements specified in the C++
|
||||
// standard. As many implementations do not live to the requirements,
|
||||
// it is not uncommon for this file to fail to compile. The
|
||||
// BOOST_HIDE_EXPECTED_ERRORS macro is provided here if you want to
|
||||
// see as much of this file compile as possible.
|
||||
//
|
||||
|
||||
#include <boost/pending/concept_checks.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <deque>
|
||||
#ifndef BOOST_NO_SLIST
|
||||
#include <slist>
|
||||
#endif
|
||||
|
||||
//#define BOOST_HIDE_EXPECTED_ERRORS
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
using namespace boost;
|
||||
|
||||
#if defined(_ITERATOR_) && defined(BOOST_HIDE_EXPECTED_ERRORS)
|
||||
// VC++ STL implementation is not standard conformant and
|
||||
// fails to pass these concept checks
|
||||
#else
|
||||
typedef std::vector<int> Vector;
|
||||
typedef std::deque<int> Deque;
|
||||
typedef std::list<int> List;
|
||||
|
||||
// VC++ missing pointer and const_pointer typedefs
|
||||
function_requires< Mutable_RandomAccessContainerConcept<Vector> >();
|
||||
function_requires< BackInsertionSequenceConcept<Vector> >();
|
||||
|
||||
#if !(defined(__GNUC__) && defined(BOOST_HIDE_EXPECTED_ERRORS))
|
||||
#if !(defined(__sgi) && defined(BOOST_HIDE_EXPECTED_ERRORS))
|
||||
// old deque iterator missing n + iter operation
|
||||
function_requires< Mutable_RandomAccessContainerConcept<Deque> >();
|
||||
#endif
|
||||
// warnings about signed and unsigned in old deque version
|
||||
function_requires< FrontInsertionSequenceConcept<Deque> >();
|
||||
function_requires< BackInsertionSequenceConcept<Deque> >();
|
||||
#endif
|
||||
|
||||
// VC++ missing pointer and const_pointer typedefs
|
||||
function_requires< Mutable_ReversibleContainerConcept<List> >();
|
||||
function_requires< FrontInsertionSequenceConcept<List> >();
|
||||
function_requires< BackInsertionSequenceConcept<List> >();
|
||||
|
||||
#ifndef BOOST_NO_SLIST
|
||||
typedef std::slist<int> SList;
|
||||
function_requires< FrontInsertionSequenceConcept<SList> >();
|
||||
#endif
|
||||
|
||||
typedef std::set<int> Set;
|
||||
typedef std::multiset<int> MultiSet;
|
||||
typedef std::map<int,int> Map;
|
||||
typedef std::multimap<int,int> MultiMap;
|
||||
|
||||
function_requires< SortedAssociativeContainerConcept<Set> >();
|
||||
function_requires< SimpleAssociativeContainerConcept<Set> >();
|
||||
function_requires< UniqueAssociativeContainerConcept<Set> >();
|
||||
|
||||
function_requires< SortedAssociativeContainerConcept<MultiSet> >();
|
||||
function_requires< SimpleAssociativeContainerConcept<MultiSet> >();
|
||||
function_requires< MultipleAssociativeContainerConcept<MultiSet> >();
|
||||
|
||||
function_requires< SortedAssociativeContainerConcept<Map> >();
|
||||
function_requires< UniqueAssociativeContainerConcept<Map> >();
|
||||
function_requires< PairAssociativeContainerConcept<Map> >();
|
||||
|
||||
function_requires< SortedAssociativeContainerConcept<MultiMap> >();
|
||||
function_requires< MultipleAssociativeContainerConcept<MultiMap> >();
|
||||
function_requires< PairAssociativeContainerConcept<MultiMap> >();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
25
test/Jamfile.v2
Normal file
25
test/Jamfile.v2
Normal file
@ -0,0 +1,25 @@
|
||||
# Copyright David Abrahams, Jeremy Siek, Vladimir Prus
|
||||
# 2006. Distributed under the Boost Software License, Version
|
||||
# 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
import testing ;
|
||||
|
||||
test-suite concept_check
|
||||
: [ link stl_concept_covering.cpp ]
|
||||
[ run stl_concept_check.cpp ]
|
||||
[ run concept_check_test.cpp ]
|
||||
[ run class_concept_check_test.cpp ]
|
||||
[ compile-fail concept_check_fail_expected.cpp ]
|
||||
[ compile-fail class_concept_fail_expected.cpp ]
|
||||
|
||||
[ run where.cpp ]
|
||||
[ compile-fail where_fail.cpp ]
|
||||
[ compile-fail usage_fail.cpp ]
|
||||
|
||||
# Backward compatibility tests
|
||||
[ run old_concept_pass.cpp ]
|
||||
[ compile-fail function_requires_fail.cpp ]
|
||||
[ compile-fail old_concept_function_fail.cpp ]
|
||||
[ compile-fail old_concept_class_fail.cpp ]
|
||||
;
|
||||
|
34
test/class_concept_check_test.cpp
Normal file
34
test/class_concept_check_test.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
// (C) Copyright Jeremy Siek 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 <boost/concept_check.hpp>
|
||||
|
||||
/*
|
||||
|
||||
This file verifies that the BOOST_CLASS_REQUIRE macro of the Boost
|
||||
Concept Checking Library does not cause errors when it is not suppose
|
||||
to.
|
||||
|
||||
*/
|
||||
|
||||
struct foo { bool operator()(int) { return true; } };
|
||||
struct bar { bool operator()(int, char) { return true; } };
|
||||
|
||||
class class_requires_test
|
||||
{
|
||||
BOOST_CONCEPT_ASSERT((boost::EqualityComparable<int>));
|
||||
typedef int* int_ptr; typedef const int* const_int_ptr;
|
||||
BOOST_CONCEPT_ASSERT((boost::EqualOp<int_ptr,const_int_ptr>));
|
||||
BOOST_CONCEPT_ASSERT((boost::UnaryFunction<foo,bool,int>));
|
||||
BOOST_CONCEPT_ASSERT((boost::BinaryFunction<bar,bool,int,char>));
|
||||
};
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
class_requires_test x;
|
||||
boost::ignore_unused_variable_warning(x);
|
||||
return 0;
|
||||
}
|
32
test/class_concept_fail_expected.cpp
Normal file
32
test/class_concept_fail_expected.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
// (C) Copyright Jeremy Siek, David Abrahams 2000-2006.
|
||||
// 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)
|
||||
//
|
||||
// Change Log:
|
||||
// 20 Jan 2001 - Added warning suppression (David Abrahams)
|
||||
|
||||
#include <boost/concept_check.hpp>
|
||||
|
||||
/*
|
||||
|
||||
This file verifies that class_requires of the Boost Concept Checking
|
||||
Library catches errors when it is supposed to.
|
||||
|
||||
*/
|
||||
|
||||
struct foo { };
|
||||
|
||||
template <class T>
|
||||
class class_requires_test
|
||||
{
|
||||
BOOST_CONCEPT_ASSERT((boost::EqualityComparable<foo>));
|
||||
};
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
class_requires_test<int> x;
|
||||
(void)x; // suppress unused variable warning
|
||||
return 0;
|
||||
}
|
26
test/concept_check_fail_expected.cpp
Normal file
26
test/concept_check_fail_expected.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
// (C) Copyright Jeremy Siek, David Abrahams 2000-2006.
|
||||
// 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)
|
||||
|
||||
#ifdef NDEBUG
|
||||
# undef NDEBUG
|
||||
#endif
|
||||
|
||||
#include <boost/concept_check.hpp>
|
||||
|
||||
/*
|
||||
|
||||
This file verifies that BOOST_CONCEPT_ASSERT catches errors in
|
||||
function context.
|
||||
|
||||
*/
|
||||
|
||||
struct foo { };
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
BOOST_CONCEPT_ASSERT((boost::EqualityComparable<foo>));
|
||||
return 0;
|
||||
}
|
@ -1,8 +1,7 @@
|
||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
// (C) Copyright Jeremy Siek 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 <boost/concept_check.hpp>
|
||||
#include <boost/concept_archetype.hpp>
|
||||
@ -26,76 +25,76 @@ main()
|
||||
// Basic Concepts
|
||||
{
|
||||
typedef default_constructible_archetype<> foo;
|
||||
function_requires< DefaultConstructibleConcept<foo> >();
|
||||
function_requires< DefaultConstructible<foo> >();
|
||||
}
|
||||
{
|
||||
typedef assignable_archetype<> foo;
|
||||
function_requires< AssignableConcept<foo> >();
|
||||
function_requires< Assignable<foo> >();
|
||||
}
|
||||
{
|
||||
typedef copy_constructible_archetype<> foo;
|
||||
function_requires< CopyConstructibleConcept<foo> >();
|
||||
function_requires< CopyConstructible<foo> >();
|
||||
}
|
||||
{
|
||||
typedef sgi_assignable_archetype<> foo;
|
||||
function_requires< SGIAssignableConcept<foo> >();
|
||||
function_requires< SGIAssignable<foo> >();
|
||||
}
|
||||
{
|
||||
typedef copy_constructible_archetype<> foo;
|
||||
typedef convertible_to_archetype<foo> convertible_to_foo;
|
||||
function_requires< ConvertibleConcept<convertible_to_foo, foo> >();
|
||||
function_requires< Convertible<convertible_to_foo, foo> >();
|
||||
}
|
||||
{
|
||||
function_requires< ConvertibleConcept<boolean_archetype, bool> >();
|
||||
function_requires< Convertible<boolean_archetype, bool> >();
|
||||
}
|
||||
{
|
||||
typedef equality_comparable_archetype<> foo;
|
||||
function_requires< EqualityComparableConcept<foo> >();
|
||||
function_requires< EqualityComparable<foo> >();
|
||||
}
|
||||
{
|
||||
typedef less_than_comparable_archetype<> foo;
|
||||
function_requires< LessThanComparableConcept<foo> >();
|
||||
function_requires< LessThanComparable<foo> >();
|
||||
}
|
||||
{
|
||||
typedef comparable_archetype<> foo;
|
||||
function_requires< ComparableConcept<foo> >();
|
||||
function_requires< Comparable<foo> >();
|
||||
}
|
||||
{
|
||||
typedef equal_op_first_archetype<> First;
|
||||
typedef equal_op_second_archetype<> Second;
|
||||
function_requires< EqualOpConcept<First, Second> >();
|
||||
function_requires< EqualOp<First, Second> >();
|
||||
}
|
||||
{
|
||||
typedef not_equal_op_first_archetype<> First;
|
||||
typedef not_equal_op_second_archetype<> Second;
|
||||
function_requires< NotEqualOpConcept<First, Second> >();
|
||||
function_requires< NotEqualOp<First, Second> >();
|
||||
}
|
||||
{
|
||||
typedef less_than_op_first_archetype<> First;
|
||||
typedef less_than_op_second_archetype<> Second;
|
||||
function_requires< LessThanOpConcept<First, Second> >();
|
||||
function_requires< LessThanOp<First, Second> >();
|
||||
}
|
||||
{
|
||||
typedef less_equal_op_first_archetype<> First;
|
||||
typedef less_equal_op_second_archetype<> Second;
|
||||
function_requires< LessEqualOpConcept<First, Second> >();
|
||||
function_requires< LessEqualOp<First, Second> >();
|
||||
}
|
||||
{
|
||||
typedef greater_than_op_first_archetype<> First;
|
||||
typedef greater_than_op_second_archetype<> Second;
|
||||
function_requires< GreaterThanOpConcept<First, Second> >();
|
||||
function_requires< GreaterThanOp<First, Second> >();
|
||||
}
|
||||
{
|
||||
typedef greater_equal_op_first_archetype<> First;
|
||||
typedef greater_equal_op_second_archetype<> Second;
|
||||
function_requires< GreaterEqualOpConcept<First, Second> >();
|
||||
function_requires< GreaterEqualOp<First, Second> >();
|
||||
}
|
||||
|
||||
{
|
||||
typedef copy_constructible_archetype<> Return;
|
||||
typedef plus_op_first_archetype<Return> First;
|
||||
typedef plus_op_second_archetype<Return> Second;
|
||||
function_requires< PlusOpConcept<Return, First, Second> >();
|
||||
function_requires< PlusOp<Return, First, Second> >();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
@ -103,73 +102,70 @@ main()
|
||||
|
||||
{
|
||||
typedef generator_archetype<null_archetype<> > foo;
|
||||
function_requires< GeneratorConcept<foo, null_archetype<> > >();
|
||||
function_requires< Generator<foo, null_archetype<> > >();
|
||||
}
|
||||
#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
{
|
||||
function_requires< GeneratorConcept< void_generator_archetype, void > >();
|
||||
function_requires< Generator< void_generator_archetype, void > >();
|
||||
}
|
||||
#endif
|
||||
{
|
||||
typedef unary_function_archetype<int, int> F;
|
||||
function_requires< UnaryFunctionConcept<F, int, int> >();
|
||||
function_requires< UnaryFunction<F, int, int> >();
|
||||
}
|
||||
{
|
||||
typedef binary_function_archetype<int, int, int> F;
|
||||
function_requires< BinaryFunctionConcept<F, int, int, int> >();
|
||||
function_requires< BinaryFunction<F, int, int, int> >();
|
||||
}
|
||||
{
|
||||
typedef unary_predicate_archetype<int> F;
|
||||
function_requires< UnaryPredicateConcept<F, int> >();
|
||||
function_requires< UnaryPredicate<F, int> >();
|
||||
}
|
||||
{
|
||||
typedef binary_predicate_archetype<int, int> F;
|
||||
function_requires< BinaryPredicateConcept<F, int, int> >();
|
||||
function_requires< BinaryPredicate<F, int, int> >();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Iterator Concepts
|
||||
{
|
||||
typedef trivial_iterator_archetype<null_archetype<> > Iter;
|
||||
function_requires< TrivialIteratorConcept<Iter> >();
|
||||
}
|
||||
{
|
||||
typedef mutable_trivial_iterator_archetype<null_archetype<> > Iter;
|
||||
function_requires< Mutable_TrivialIteratorConcept<Iter> >();
|
||||
}
|
||||
{
|
||||
typedef input_iterator_archetype<null_archetype<> > Iter;
|
||||
function_requires< InputIteratorConcept<Iter> >();
|
||||
function_requires< InputIterator<Iter> >();
|
||||
}
|
||||
{
|
||||
typedef output_iterator_archetype<int> Iter;
|
||||
function_requires< OutputIteratorConcept<Iter, int> >();
|
||||
function_requires< OutputIterator<Iter, int> >();
|
||||
}
|
||||
{
|
||||
typedef input_output_iterator_archetype<int> Iter;
|
||||
function_requires< InputIterator<Iter> >();
|
||||
function_requires< OutputIterator<Iter, int> >();
|
||||
}
|
||||
{
|
||||
typedef forward_iterator_archetype<null_archetype<> > Iter;
|
||||
function_requires< ForwardIteratorConcept<Iter> >();
|
||||
function_requires< ForwardIterator<Iter> >();
|
||||
}
|
||||
{
|
||||
typedef mutable_forward_iterator_archetype<assignable_archetype<> > Iter;
|
||||
function_requires< Mutable_ForwardIteratorConcept<Iter> >();
|
||||
function_requires< Mutable_ForwardIterator<Iter> >();
|
||||
}
|
||||
{
|
||||
typedef bidirectional_iterator_archetype<null_archetype<> > Iter;
|
||||
function_requires< BidirectionalIteratorConcept<Iter> >();
|
||||
function_requires< BidirectionalIterator<Iter> >();
|
||||
}
|
||||
{
|
||||
typedef mutable_bidirectional_iterator_archetype<assignable_archetype<> >
|
||||
Iter;
|
||||
function_requires< Mutable_BidirectionalIteratorConcept<Iter> >();
|
||||
function_requires< Mutable_BidirectionalIterator<Iter> >();
|
||||
}
|
||||
{
|
||||
typedef random_access_iterator_archetype<null_archetype<> > Iter;
|
||||
function_requires< RandomAccessIteratorConcept<Iter> >();
|
||||
function_requires< RandomAccessIterator<Iter> >();
|
||||
}
|
||||
{
|
||||
typedef mutable_random_access_iterator_archetype<assignable_archetype<> >
|
||||
Iter;
|
||||
function_requires< Mutable_RandomAccessIteratorConcept<Iter> >();
|
||||
function_requires< Mutable_RandomAccessIterator<Iter> >();
|
||||
}
|
||||
|
||||
//===========================================================================
|
27
test/fake_sort.hpp
Normal file
27
test/fake_sort.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright David Abrahams 2006. 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_LIBS_CONCEPT_CHECK_FAKE_SORT_DWA2006430_HPP
|
||||
# define BOOST_LIBS_CONCEPT_CHECK_FAKE_SORT_DWA2006430_HPP
|
||||
|
||||
# include <iterator>
|
||||
# include <boost/concept/requires.hpp>
|
||||
# include <boost/concept_check.hpp>
|
||||
|
||||
namespace fake
|
||||
{
|
||||
using namespace boost;
|
||||
|
||||
template<typename RanIter>
|
||||
BOOST_CONCEPT_REQUIRES(
|
||||
((Mutable_RandomAccessIterator<RanIter>))
|
||||
((LessThanComparable<typename Mutable_RandomAccessIterator<RanIter>::value_type>))
|
||||
|
||||
, (void))
|
||||
sort(RanIter,RanIter)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // BOOST_LIBS_CONCEPT_CHECK_FAKE_SORT_DWA2006430_HPP
|
26
test/function_requires_fail.cpp
Normal file
26
test/function_requires_fail.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
// (C) Copyright Jeremy Siek 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)
|
||||
|
||||
#ifdef NDEBUG
|
||||
# undef NDEBUG
|
||||
#endif
|
||||
|
||||
#include <boost/concept_check.hpp>
|
||||
|
||||
/*
|
||||
|
||||
This file verifies that function_requires() of the Boost Concept
|
||||
Checking Library catches errors when it is suppose to.
|
||||
|
||||
*/
|
||||
|
||||
struct foo { };
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
boost::function_requires< boost::EqualityComparable<foo> >();
|
||||
return 0;
|
||||
}
|
28
test/old_concept_class_fail.cpp
Normal file
28
test/old_concept_class_fail.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
// (C) Copyright Jeremy Siek, David Abrahams 2000-2006.
|
||||
// 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)
|
||||
//
|
||||
// Change Log:
|
||||
// 20 Jan 2001 - Added warning suppression (David Abrahams)
|
||||
|
||||
#include "old_concepts.hpp"
|
||||
|
||||
// This file verifies that concepts written the old way still catch
|
||||
// errors in class context. This is not expected to work on compilers
|
||||
// without SFINAE support.
|
||||
|
||||
struct foo { };
|
||||
|
||||
class class_requires_test
|
||||
{
|
||||
BOOST_CLASS_REQUIRE(foo, old, EqualityComparableConcept);
|
||||
};
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
class_requires_test x;
|
||||
(void)x; // suppress unused variable warning
|
||||
return 0;
|
||||
}
|
23
test/old_concept_function_fail.cpp
Normal file
23
test/old_concept_function_fail.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
// (C) Copyright Jeremy Siek 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)
|
||||
|
||||
#ifdef NDEBUG
|
||||
# undef NDEBUG
|
||||
#endif
|
||||
|
||||
#include "old_concepts.hpp"
|
||||
|
||||
// This file verifies that concepts written the old way still catch
|
||||
// errors in function context. This is not expected to work on
|
||||
// compilers without SFINAE support.
|
||||
|
||||
struct foo { };
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
boost::function_requires< old::EqualityComparableConcept<foo> >();
|
||||
return 0;
|
||||
}
|
34
test/old_concept_pass.cpp
Normal file
34
test/old_concept_pass.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
// (C) Copyright Jeremy Siek, David Abrahams 2000-2006.
|
||||
// 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/concept_check.hpp>
|
||||
#include "old_concepts.hpp"
|
||||
|
||||
// This test verifies that use of the old-style concept checking
|
||||
// classes still compiles (but not that it detects constraint
|
||||
// violations). We check them with the old-style macros just for
|
||||
// completeness, since those macros stranslate into
|
||||
// BOOST_CONCEPT_ASSERTs.
|
||||
|
||||
struct foo { bool operator()(int) { return true; } };
|
||||
struct bar { bool operator()(int, char) { return true; } };
|
||||
|
||||
|
||||
class class_requires_test
|
||||
{
|
||||
BOOST_CLASS_REQUIRE(int, old, EqualityComparableConcept);
|
||||
typedef int* int_ptr; typedef const int* const_int_ptr;
|
||||
BOOST_CLASS_REQUIRE2(int_ptr, const_int_ptr, old, EqualOpConcept);
|
||||
BOOST_CLASS_REQUIRE3(foo, bool, int, old, UnaryFunctionConcept);
|
||||
BOOST_CLASS_REQUIRE4(bar, bool, int, char, old, BinaryFunctionConcept);
|
||||
};
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
class_requires_test x;
|
||||
boost::ignore_unused_variable_warning(x);
|
||||
return 0;
|
||||
}
|
67
test/old_concepts.hpp
Normal file
67
test/old_concepts.hpp
Normal file
@ -0,0 +1,67 @@
|
||||
// Copyright Jeremy Siek, David Abrahams 2000-2006. 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_LIBS_CONCEPT_CHECK_OLD_CONCEPTS_DWA2006428_HPP
|
||||
# define BOOST_LIBS_CONCEPT_CHECK_OLD_CONCEPTS_DWA2006428_HPP
|
||||
|
||||
#include <boost/concept_check.hpp>
|
||||
|
||||
namespace old
|
||||
{
|
||||
template <class TT>
|
||||
void require_boolean_expr(const TT& t) {
|
||||
bool x = t;
|
||||
boost::ignore_unused_variable_warning(x);
|
||||
}
|
||||
|
||||
template <class TT>
|
||||
struct EqualityComparableConcept
|
||||
{
|
||||
void constraints() {
|
||||
boost::require_boolean_expr(a == b);
|
||||
boost::require_boolean_expr(a != b);
|
||||
}
|
||||
TT a, b;
|
||||
};
|
||||
|
||||
template <class Func, class Return, class Arg>
|
||||
struct UnaryFunctionConcept
|
||||
{
|
||||
// required in case any of our template args are const-qualified:
|
||||
UnaryFunctionConcept();
|
||||
|
||||
void constraints() {
|
||||
r = f(arg); // require operator()
|
||||
}
|
||||
Func f;
|
||||
Arg arg;
|
||||
Return r;
|
||||
};
|
||||
|
||||
template <class Func, class Return, class First, class Second>
|
||||
struct BinaryFunctionConcept
|
||||
{
|
||||
void constraints() {
|
||||
r = f(first, second); // require operator()
|
||||
}
|
||||
Func f;
|
||||
First first;
|
||||
Second second;
|
||||
Return r;
|
||||
};
|
||||
|
||||
#define DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(OP,NAME) \
|
||||
template <class First, class Second> \
|
||||
struct NAME { \
|
||||
void constraints() { (void)constraints_(); } \
|
||||
bool constraints_() { \
|
||||
return a OP b; \
|
||||
} \
|
||||
First a; \
|
||||
Second b; \
|
||||
}
|
||||
|
||||
DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(==, EqualOpConcept);
|
||||
}
|
||||
|
||||
#endif // BOOST_LIBS_CONCEPT_CHECK_OLD_CONCEPTS_DWA2006428_HPP
|
93
test/stl_concept_check.cpp
Normal file
93
test/stl_concept_check.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
// (C) Copyright Jeremy Siek 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)
|
||||
|
||||
//
|
||||
// This file checks to see if various standard container
|
||||
// implementations live up to requirements specified in the C++
|
||||
// standard. As many implementations do not live to the requirements,
|
||||
// it is not uncommon for this file to fail to compile. The
|
||||
// BOOST_HIDE_EXPECTED_ERRORS macro is provided here if you want to
|
||||
// see as much of this file compile as possible.
|
||||
//
|
||||
|
||||
#include <boost/concept_check.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <deque>
|
||||
#if 0
|
||||
#include <slist>
|
||||
#endif
|
||||
|
||||
// Define this macro if you want to hide the expected error, that is,
|
||||
// error in the various C++ standard library implementations.
|
||||
//
|
||||
//#define BOOST_HIDE_EXPECTED_ERRORS
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
using namespace boost;
|
||||
|
||||
#if defined(_ITERATOR_) && defined(BOOST_HIDE_EXPECTED_ERRORS)
|
||||
// VC++ STL implementation is not standard conformant and
|
||||
// fails to pass these concept checks
|
||||
#else
|
||||
typedef std::vector<int> Vector;
|
||||
typedef std::deque<int> Deque;
|
||||
typedef std::list<int> List;
|
||||
|
||||
// VC++ missing pointer and const_pointer typedefs
|
||||
function_requires< Mutable_RandomAccessContainer<Vector> >();
|
||||
function_requires< BackInsertionSequence<Vector> >();
|
||||
|
||||
#if !(defined(__GNUC__) && defined(BOOST_HIDE_EXPECTED_ERRORS))
|
||||
#if !((defined(__sgi) || (defined(__DECCXX) && defined(_RWSTD_VER) && _RWSTD_VER <= 0x0203)) \
|
||||
&& defined(BOOST_HIDE_EXPECTED_ERRORS))
|
||||
// old deque iterator missing n + iter operation
|
||||
function_requires< Mutable_RandomAccessContainer<Deque> >();
|
||||
#endif
|
||||
// warnings about signed and unsigned in old deque version
|
||||
function_requires< FrontInsertionSequence<Deque> >();
|
||||
function_requires< BackInsertionSequence<Deque> >();
|
||||
#endif
|
||||
|
||||
// VC++ missing pointer and const_pointer typedefs
|
||||
function_requires< Mutable_ReversibleContainer<List> >();
|
||||
function_requires< FrontInsertionSequence<List> >();
|
||||
function_requires< BackInsertionSequence<List> >();
|
||||
|
||||
#if 0
|
||||
typedef BOOST_STD_EXTENSION_NAMESPACE::slist<int> SList;
|
||||
function_requires< FrontInsertionSequence<SList> >();
|
||||
#endif
|
||||
|
||||
typedef std::set<int> Set;
|
||||
typedef std::multiset<int> MultiSet;
|
||||
typedef std::map<int,int> Map;
|
||||
typedef std::multimap<int,int> MultiMap;
|
||||
|
||||
function_requires< SortedAssociativeContainer<Set> >();
|
||||
function_requires< SimpleAssociativeContainer<Set> >();
|
||||
function_requires< UniqueAssociativeContainer<Set> >();
|
||||
|
||||
function_requires< SortedAssociativeContainer<MultiSet> >();
|
||||
function_requires< SimpleAssociativeContainer<MultiSet> >();
|
||||
function_requires< MultipleAssociativeContainer<MultiSet> >();
|
||||
|
||||
function_requires< SortedAssociativeContainer<Map> >();
|
||||
function_requires< UniqueAssociativeContainer<Map> >();
|
||||
function_requires< PairAssociativeContainer<Map> >();
|
||||
|
||||
function_requires< SortedAssociativeContainer<MultiMap> >();
|
||||
function_requires< MultipleAssociativeContainer<MultiMap> >();
|
||||
function_requires< PairAssociativeContainer<MultiMap> >();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,13 +1,13 @@
|
||||
// (C) Copyright Jeremy Siek 2000-2002. Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
// (C) Copyright Jeremy Siek 2000-2002.
|
||||
// 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/concept_check.hpp>
|
||||
#include <boost/concept_archetype.hpp>
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/concept_check.hpp>
|
||||
#include <boost/concept_archetype.hpp>
|
||||
|
||||
/*
|
||||
|
||||
@ -25,6 +25,21 @@
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* Input iterator - explanation from Peter Dimov:
|
||||
*
|
||||
* Requirements say that *it is convertible to the value_type, and it is, in
|
||||
* our case. The problem however is that op== is a template and the first
|
||||
* argument fails deduction. std::find is specified in terms of the exact
|
||||
* expression `*it == value`, so if it doesn't compile (and it doesn't),
|
||||
* `find(it, it, value)` won't compile either.
|
||||
*
|
||||
* To address this, the no_proxy variant of the input iterator is used
|
||||
* instead.
|
||||
*/
|
||||
|
||||
#define BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE input_iterator_archetype_no_proxy
|
||||
|
||||
boost::detail::dummy_constructor dummy_cons;
|
||||
|
||||
// This is a special concept needed for std::swap_ranges.
|
||||
@ -63,6 +78,17 @@ namespace accum
|
||||
}
|
||||
}
|
||||
|
||||
// for std::shuffle
|
||||
namespace shuffle
|
||||
{
|
||||
struct URBG {
|
||||
typedef unsigned int result_type;
|
||||
result_type BOOST_CONSTEXPR static min() { return 0; }
|
||||
result_type BOOST_CONSTEXPR static max() { return 1; }
|
||||
result_type operator()() { return 1; }
|
||||
};
|
||||
}
|
||||
|
||||
// for std::inner_product
|
||||
namespace inner_prod
|
||||
{
|
||||
@ -93,22 +119,19 @@ namespace boost { // so Koenig lookup will find
|
||||
// for std::partial_sum and adj_diff
|
||||
namespace part_sum
|
||||
{
|
||||
typedef boost::null_archetype<> Tout;
|
||||
typedef boost::sgi_assignable_archetype<
|
||||
boost::convertible_to_archetype<Tout> > Ret;
|
||||
class Tin {
|
||||
class T {
|
||||
public:
|
||||
Tin(const Ret&) { }
|
||||
Tin(boost::detail::dummy_constructor x) { }
|
||||
operator const Tout&() const { return boost::static_object<Tout>::get(); }
|
||||
typedef boost::sgi_assignable_archetype<> Ret;
|
||||
T(const Ret&) { }
|
||||
T(boost::detail::dummy_constructor x) { }
|
||||
private:
|
||||
Tin() { }
|
||||
T() { }
|
||||
};
|
||||
Ret operator+(const Tin&, const Tin&) {
|
||||
return Ret(dummy_cons);
|
||||
T::Ret operator+(const T&, const T&) {
|
||||
return T::Ret(dummy_cons);
|
||||
}
|
||||
Ret operator-(const Tin&, const Tin&) {
|
||||
return Ret(dummy_cons);
|
||||
T::Ret operator-(const T&, const T&) {
|
||||
return T::Ret(dummy_cons);
|
||||
}
|
||||
}
|
||||
|
||||
@ -130,6 +153,7 @@ namespace power_stuff {
|
||||
struct tag1 { };
|
||||
struct tag2 { };
|
||||
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
@ -138,22 +162,22 @@ main()
|
||||
//===========================================================================
|
||||
// Non-mutating Algorithms
|
||||
{
|
||||
input_iterator_archetype<
|
||||
convertible_to_archetype< null_archetype<> > > in;
|
||||
input_iterator_archetype< null_archetype<> > in;
|
||||
unary_function_archetype< null_archetype<> , null_archetype<> >
|
||||
f(dummy_cons);
|
||||
std::for_each(in, in, f);
|
||||
}
|
||||
// gcc bug
|
||||
{
|
||||
typedef equality_comparable2_first_archetype<> Left;
|
||||
input_iterator_archetype< Left > in;
|
||||
BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE< Left > in;
|
||||
equality_comparable2_second_archetype<> value(dummy_cons);
|
||||
in = std::find(in, in, value);
|
||||
}
|
||||
{
|
||||
input_iterator_archetype<
|
||||
convertible_to_archetype< null_archetype<> > > in;
|
||||
unary_predicate_archetype< null_archetype<> > pred(dummy_cons);
|
||||
typedef null_archetype<> T;
|
||||
input_iterator_archetype<T> in;
|
||||
unary_predicate_archetype<T> pred(dummy_cons);
|
||||
in = std::find_if(in, in, pred);
|
||||
}
|
||||
{
|
||||
@ -167,61 +191,62 @@ main()
|
||||
pred(dummy_cons);
|
||||
fo = std::adjacent_find(fo, fo, pred);
|
||||
}
|
||||
// gcc bug
|
||||
{
|
||||
typedef equal_op_first_archetype<> Left;
|
||||
input_iterator_archetype<Left> in;
|
||||
BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Left> in;
|
||||
typedef equal_op_second_archetype<> Right;
|
||||
forward_iterator_archetype<Right> fo;
|
||||
in = std::find_first_of(in, in, fo, fo);
|
||||
}
|
||||
{
|
||||
typedef equal_op_first_archetype<> Left;
|
||||
typedef input_iterator_archetype<Left> InIter;
|
||||
typedef BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Left> InIter;
|
||||
InIter in;
|
||||
function_requires< InputIteratorConcept<InIter> >();
|
||||
function_requires< InputIterator<InIter> >();
|
||||
equal_op_second_archetype<> value(dummy_cons);
|
||||
std::iterator_traits<InIter>::difference_type
|
||||
n = std::count(in, in, value);
|
||||
ignore_unused_variable_warning(n);
|
||||
}
|
||||
{
|
||||
typedef input_iterator_archetype<
|
||||
convertible_to_archetype<null_archetype<> > > InIter;
|
||||
typedef input_iterator_archetype< null_archetype<> > InIter;
|
||||
InIter in;
|
||||
unary_predicate_archetype<null_archetype<> > pred(dummy_cons);
|
||||
std::iterator_traits<InIter>::difference_type
|
||||
n = std::count_if(in, in, pred);
|
||||
ignore_unused_variable_warning(n);
|
||||
}
|
||||
// gcc bug
|
||||
{
|
||||
typedef equal_op_first_archetype<> Left;
|
||||
typedef input_iterator_archetype<Left> InIter1;
|
||||
typedef BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Left> InIter1;
|
||||
InIter1 in1;
|
||||
typedef equal_op_second_archetype<> Right;
|
||||
typedef input_iterator_archetype<Right> InIter2;
|
||||
typedef BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Right> InIter2;
|
||||
InIter2 in2;
|
||||
std::pair<InIter1, InIter2> p = std::mismatch(in1, in1, in2);
|
||||
ignore_unused_variable_warning(p);
|
||||
}
|
||||
{
|
||||
typedef input_iterator_archetype<
|
||||
convertible_to_archetype<null_archetype<> > > InIter;
|
||||
typedef input_iterator_archetype<null_archetype<> > InIter;
|
||||
InIter in1, in2;
|
||||
binary_predicate_archetype<null_archetype<> , null_archetype<> >
|
||||
pred(dummy_cons);
|
||||
std::pair<InIter, InIter> p = std::mismatch(in1, in1, in2, pred);
|
||||
ignore_unused_variable_warning(p);
|
||||
}
|
||||
// gcc bug
|
||||
{
|
||||
typedef equality_comparable2_first_archetype<> Left;
|
||||
input_iterator_archetype<Left> in1;
|
||||
BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Left> in1;
|
||||
typedef equality_comparable2_second_archetype<> Right;
|
||||
input_iterator_archetype<Right> in2;
|
||||
BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Right> in2;
|
||||
bool b = std::equal(in1, in1, in2);
|
||||
ignore_unused_variable_warning(b);
|
||||
}
|
||||
{
|
||||
input_iterator_archetype< convertible_to_archetype<null_archetype<> > >
|
||||
input_iterator_archetype< null_archetype<> >
|
||||
in1, in2;
|
||||
binary_predicate_archetype<null_archetype<> , null_archetype<> >
|
||||
pred(dummy_cons);
|
||||
@ -286,10 +311,9 @@ main()
|
||||
// Mutating Algorithms
|
||||
|
||||
{
|
||||
typedef null_archetype<> OutT;
|
||||
typedef convertible_to_archetype<OutT> InT;
|
||||
input_iterator_archetype<InT> in;
|
||||
output_iterator_archetype<OutT> out(dummy_cons);
|
||||
typedef null_archetype<> T;
|
||||
input_iterator_archetype<T> in;
|
||||
output_iterator_archetype<T> out(dummy_cons);
|
||||
out = std::copy(in, in, out);
|
||||
}
|
||||
{
|
||||
@ -308,16 +332,19 @@ main()
|
||||
mutable_forward_iterator_archetype<T> a, b;
|
||||
std::iter_swap(a, b);
|
||||
}
|
||||
#if 0
|
||||
{
|
||||
// fails on gcc 7.3 and clang 6.0
|
||||
typedef mutually_convertible_archetype<int> Tin;
|
||||
typedef mutually_convertible_archetype<char> Tout;
|
||||
mutable_forward_iterator_archetype<Tin> fi1;
|
||||
mutable_forward_iterator_archetype<Tout> fi2;
|
||||
fi2 = std::swap_ranges(fi1, fi1, fi2);
|
||||
}
|
||||
#endif
|
||||
{
|
||||
typedef convertible_to_archetype<null_archetype<> > Tin;
|
||||
typedef null_archetype<> Tout;
|
||||
typedef null_archetype<int> Tin;
|
||||
typedef null_archetype<char> Tout;
|
||||
input_iterator_archetype<Tin> in;
|
||||
output_iterator_archetype<Tout> out(dummy_cons);
|
||||
unary_function_archetype<null_archetype<> ,
|
||||
@ -325,13 +352,13 @@ main()
|
||||
out = std::transform(in, in, out, op);
|
||||
}
|
||||
{
|
||||
typedef convertible_to_archetype<null_archetype<int> > Tin1;
|
||||
typedef convertible_to_archetype<null_archetype<char> > Tin2;
|
||||
typedef null_archetype<> Tout;
|
||||
typedef null_archetype<int> Tin1;
|
||||
typedef null_archetype<char> Tin2;
|
||||
typedef null_archetype<double> Tout;
|
||||
input_iterator_archetype<Tin1> in1;
|
||||
input_iterator_archetype<Tin2> in2;
|
||||
output_iterator_archetype<Tout> out(dummy_cons);
|
||||
binary_function_archetype<null_archetype<int>, null_archetype<char>,
|
||||
binary_function_archetype<Tin1, Tin2,
|
||||
convertible_to_archetype<Tout> > op(dummy_cons);
|
||||
out = std::transform(in1, in1, in2, out, op);
|
||||
}
|
||||
@ -352,45 +379,29 @@ main()
|
||||
convertible_to_archetype<FT> value(dummy_cons);
|
||||
std::replace_if(fi, fi, pred, value);
|
||||
}
|
||||
#if (!defined(BOOST_MSVC) || BOOST_WORKAROUND(BOOST_MSVC, > 1900)) && !defined(BOOST_EMBTC)
|
||||
// fails on MSVC 2015 and earlier
|
||||
{
|
||||
#if 0
|
||||
// Issue, the use of ?: inside replace_copy() complicates things
|
||||
typedef equal_op_first_archetype<> Tin;
|
||||
typedef null_archetype<> Tout;
|
||||
typedef equal_op_second_archetype< convertible_to_archetype<Tout> > T;
|
||||
input_iterator_archetype<Tin> in;
|
||||
BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Tin> in;
|
||||
output_iterator_archetype<Tout> out(dummy_cons);
|
||||
T value(dummy_cons);
|
||||
out = std::replace_copy(in, in, out, value, value);
|
||||
#else
|
||||
typedef null_archetype<> Tout;
|
||||
typedef equal_op_second_archetype< convertible_to_archetype<Tout> > T;
|
||||
// Adding convertible to T for Tin solves the problem, so would
|
||||
// making T convertible to Tin. Not sure what the right way to
|
||||
// express the requirement would be. Also, perhaps the
|
||||
// implementation's use of ?: is invalid.
|
||||
typedef equal_op_first_archetype< convertible_to_archetype<T> > Tin;
|
||||
input_iterator_archetype<Tin> in;
|
||||
output_iterator_archetype<Tout> out(dummy_cons);
|
||||
T value(dummy_cons);
|
||||
out = std::replace_copy(in, in, out, value, value);
|
||||
#endif
|
||||
}
|
||||
{
|
||||
// The issue of ?: also affects this function
|
||||
typedef null_archetype<int> PredArg;
|
||||
typedef null_archetype<char> Tout;
|
||||
typedef convertible_to_archetype<Tout,
|
||||
convertible_to_archetype<PredArg> > T;
|
||||
typedef convertible_to_archetype<PredArg,
|
||||
convertible_to_archetype<Tout,
|
||||
convertible_to_archetype<T> > > Tin;
|
||||
input_iterator_archetype<Tin> in;
|
||||
typedef null_archetype<> Tout;
|
||||
typedef assignable_archetype< convertible_to_archetype<Tout> > Tin;
|
||||
BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Tin> in;
|
||||
output_iterator_archetype<Tout> out(dummy_cons);
|
||||
unary_predicate_archetype<PredArg> pred(dummy_cons);
|
||||
T value(dummy_cons);
|
||||
unary_predicate_archetype<Tin> pred(dummy_cons);
|
||||
Tin value(dummy_cons);
|
||||
out = std::replace_copy_if(in, in, out, pred, value);
|
||||
}
|
||||
#endif
|
||||
{
|
||||
typedef assignable_archetype<> FT;
|
||||
mutable_forward_iterator_archetype<FT> fi;
|
||||
@ -398,6 +409,8 @@ main()
|
||||
T value(dummy_cons);
|
||||
std::fill(fi, fi, value);
|
||||
}
|
||||
#if !defined(BOOST_MSVC) || BOOST_WORKAROUND(BOOST_MSVC, >= 1700)
|
||||
// fails on MSVC 2010
|
||||
{
|
||||
typedef null_archetype<> Tout;
|
||||
typedef convertible_to_archetype<Tout> T;
|
||||
@ -406,6 +419,7 @@ main()
|
||||
int n = 1;
|
||||
out = std::fill_n(out, n, value);
|
||||
}
|
||||
#endif
|
||||
{
|
||||
typedef assignable_archetype<> FT;
|
||||
typedef convertible_to_archetype<FT> Ret;
|
||||
@ -435,24 +449,22 @@ main()
|
||||
unary_predicate_archetype<PredArg> pred(dummy_cons);
|
||||
fi = std::remove_if(fi, fi, pred);
|
||||
}
|
||||
// gcc bug
|
||||
{
|
||||
typedef null_archetype<> Tout;
|
||||
typedef equality_comparable2_first_archetype<
|
||||
convertible_to_archetype<Tout> > Tin;
|
||||
typedef equality_comparable2_second_archetype<> T;
|
||||
input_iterator_archetype<Tin> in;
|
||||
BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Tin> in;
|
||||
output_iterator_archetype<Tout> out(dummy_cons);
|
||||
T value(dummy_cons);
|
||||
out = std::remove_copy(in, in, out, value);
|
||||
}
|
||||
{
|
||||
typedef null_archetype<int> Tout;
|
||||
typedef null_archetype<char> PredArg;
|
||||
typedef convertible_to_archetype<PredArg,
|
||||
convertible_to_archetype<Tout> > Tin;
|
||||
input_iterator_archetype<Tin> in;
|
||||
output_iterator_archetype<Tout> out(dummy_cons);
|
||||
unary_predicate_archetype<PredArg> pred(dummy_cons);
|
||||
typedef null_archetype<> T;
|
||||
input_iterator_archetype<T> in;
|
||||
output_iterator_archetype<T> out(dummy_cons);
|
||||
unary_predicate_archetype<T> pred(dummy_cons);
|
||||
out = std::remove_copy_if(in, in, out, pred);
|
||||
}
|
||||
{
|
||||
@ -470,23 +482,18 @@ main()
|
||||
binary_predicate_archetype<Arg1, Arg2> pred(dummy_cons);
|
||||
fi = std::unique(fi, fi, pred);
|
||||
}
|
||||
// gcc bug
|
||||
{
|
||||
typedef equality_comparable_archetype< sgi_assignable_archetype<> > T;
|
||||
input_iterator_archetype<T> in;
|
||||
BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<T> in;
|
||||
output_iterator_archetype<T> out(dummy_cons);
|
||||
out = std::unique_copy(in, in, out);
|
||||
}
|
||||
{
|
||||
typedef null_archetype<int> Arg1;
|
||||
typedef null_archetype<char> Arg2;
|
||||
typedef null_archetype<short> Tout;
|
||||
typedef sgi_assignable_archetype<
|
||||
convertible_to_archetype<Tout,
|
||||
convertible_to_archetype<Arg1,
|
||||
convertible_to_archetype<Arg2> > > > Tin;
|
||||
input_iterator_archetype<Tin> in;
|
||||
output_iterator_archetype<Tout> out(dummy_cons);
|
||||
binary_predicate_archetype<Arg1, Arg2> pred(dummy_cons);
|
||||
typedef sgi_assignable_archetype<> T;
|
||||
input_iterator_archetype<T> in;
|
||||
output_iterator_archetype<T> out(dummy_cons);
|
||||
binary_predicate_archetype<T, T> pred(dummy_cons);
|
||||
out = std::unique_copy(in, in, out, pred);
|
||||
}
|
||||
{
|
||||
@ -514,6 +521,7 @@ main()
|
||||
output_iterator_archetype<Tout> out(dummy_cons);
|
||||
out = std::rotate_copy(fi, fi, fi, out);
|
||||
}
|
||||
#ifndef BOOST_NO_CXX98_RANDOM_SHUFFLE
|
||||
{
|
||||
typedef sgi_assignable_archetype<> T;
|
||||
mutable_random_access_iterator_archetype<T> ri;
|
||||
@ -525,6 +533,14 @@ main()
|
||||
unary_function_archetype<std::ptrdiff_t, std::ptrdiff_t> ran(dummy_cons);
|
||||
std::random_shuffle(ri, ri, ran);
|
||||
}
|
||||
#else
|
||||
{
|
||||
typedef sgi_assignable_archetype<> T;
|
||||
mutable_random_access_iterator_archetype<T> ri;
|
||||
shuffle::URBG urbg;
|
||||
std::shuffle(ri, ri, urbg);
|
||||
}
|
||||
#endif
|
||||
{
|
||||
typedef null_archetype<> PredArg;
|
||||
typedef sgi_assignable_archetype<convertible_to_archetype<PredArg> > FT;
|
||||
@ -532,14 +548,17 @@ main()
|
||||
unary_predicate_archetype<PredArg> pred(dummy_cons);
|
||||
bi = std::partition(bi, bi, pred);
|
||||
}
|
||||
#if !defined(BOOST_MSVC) && !defined(BOOST_EMBTC) && !defined(_MSC_VER)
|
||||
{
|
||||
// fails on MSVC and clang-win; stl headers come from Visual Studio and
|
||||
// they attempt to reverse the iterator
|
||||
typedef null_archetype<> PredArg;
|
||||
typedef sgi_assignable_archetype<convertible_to_archetype<PredArg> > FT;
|
||||
mutable_forward_iterator_archetype<FT> fi;
|
||||
unary_predicate_archetype<PredArg> pred(dummy_cons);
|
||||
fi = std::stable_partition(fi, fi, pred);
|
||||
}
|
||||
|
||||
#endif
|
||||
//===========================================================================
|
||||
// Sorting Algorithms
|
||||
{
|
||||
@ -585,22 +604,21 @@ main()
|
||||
binary_predicate_archetype<Arg, Arg> comp(dummy_cons);
|
||||
std::partial_sort(ri, ri, ri, comp);
|
||||
}
|
||||
// gcc bug
|
||||
{
|
||||
// This could be formulated so that the two iterators are not
|
||||
// required to have the same value type, but it is messy.
|
||||
typedef sgi_assignable_archetype<
|
||||
less_than_comparable_archetype<> > T;
|
||||
input_iterator_archetype<T> in;
|
||||
BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<T> in;
|
||||
mutable_random_access_iterator_archetype<T> ri_out;
|
||||
ri_out = std::partial_sort_copy(in, in , ri_out, ri_out);
|
||||
}
|
||||
{
|
||||
typedef null_archetype<> Arg;
|
||||
typedef sgi_assignable_archetype<
|
||||
convertible_to_archetype<Arg> > T;
|
||||
typedef sgi_assignable_archetype<> T;
|
||||
input_iterator_archetype<T> in;
|
||||
mutable_random_access_iterator_archetype<T> ri_out;
|
||||
binary_predicate_archetype<Arg, Arg> comp(dummy_cons);
|
||||
binary_predicate_archetype<T, T> comp(dummy_cons);
|
||||
ri_out = std::partial_sort_copy(in, in , ri_out, ri_out, comp);
|
||||
}
|
||||
{
|
||||
@ -619,14 +637,14 @@ main()
|
||||
std::nth_element(ri, ri, ri, comp);
|
||||
}
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
typedef less_than_op_first_archetype<> FT;
|
||||
typedef less_than_op_second_archetype<> T;
|
||||
#elif defined(__KCC)
|
||||
#if defined(__KCC)
|
||||
// The KAI version of this uses a one-argument less-than function
|
||||
// object.
|
||||
typedef less_than_comparable_archetype<> T;
|
||||
typedef convertible_to_archetype<T> FT;
|
||||
#else
|
||||
typedef less_than_op_first_archetype<> FT;
|
||||
typedef less_than_op_second_archetype<> T;
|
||||
#endif
|
||||
forward_iterator_archetype<FT> fi;
|
||||
T value(dummy_cons);
|
||||
@ -643,13 +661,13 @@ main()
|
||||
fi = std::lower_bound(fi, fi, value, comp);
|
||||
}
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
#if defined(__KCC)
|
||||
typedef less_than_comparable_archetype<> T;
|
||||
typedef convertible_to_archetype<T> FT;
|
||||
#else
|
||||
// Note, order of T,FT is flipped from lower_bound
|
||||
typedef less_than_op_second_archetype<> FT;
|
||||
typedef less_than_op_first_archetype<> T;
|
||||
#elif defined(__KCC)
|
||||
typedef less_than_comparable_archetype<> T;
|
||||
typedef convertible_to_archetype<T> FT;
|
||||
#endif
|
||||
forward_iterator_archetype<FT> fi;
|
||||
T value(dummy_cons);
|
||||
@ -666,15 +684,17 @@ main()
|
||||
binary_predicate_archetype<Arg1, Arg2> comp(dummy_cons);
|
||||
fi = std::upper_bound(fi, fi, value, comp);
|
||||
}
|
||||
#if !defined(BOOST_MSVC) || BOOST_WORKAROUND(BOOST_MSVC, >= 1900)
|
||||
// Fails on MSVC 2013 and earlier
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
#if defined(__KCC)
|
||||
typedef less_than_comparable_archetype<> T;
|
||||
typedef convertible_to_archetype<T> FT;
|
||||
#else
|
||||
typedef less_than_op_first_archetype<
|
||||
less_than_op_second_archetype< null_archetype<>, optag2>, optag1> FT;
|
||||
typedef less_than_op_second_archetype<
|
||||
less_than_op_first_archetype< null_archetype<>, optag2>, optag1> T;
|
||||
#elif defined(__KCC)
|
||||
typedef less_than_comparable_archetype<> T;
|
||||
typedef convertible_to_archetype<T> FT;
|
||||
#endif
|
||||
typedef forward_iterator_archetype<FT> FIter;
|
||||
FIter fi;
|
||||
@ -682,6 +702,7 @@ main()
|
||||
std::pair<FIter,FIter> p = std::equal_range(fi, fi, value);
|
||||
ignore_unused_variable_warning(p);
|
||||
}
|
||||
#endif
|
||||
{
|
||||
typedef null_archetype<int> Arg1;
|
||||
typedef null_archetype<char> Arg2;
|
||||
@ -697,14 +718,14 @@ main()
|
||||
ignore_unused_variable_warning(p);
|
||||
}
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
#if defined(__KCC)
|
||||
typedef less_than_op_first_archetype< less_than_comparable_archetype<> > T;
|
||||
typedef less_than_op_second_archetype< convertible_to_archetype<T> > FT;
|
||||
#else
|
||||
typedef less_than_op_first_archetype<
|
||||
less_than_op_second_archetype<null_archetype<>, optag2>, optag1> FT;
|
||||
typedef less_than_op_second_archetype<
|
||||
less_than_op_first_archetype<null_archetype<>, optag2>, optag1> T;
|
||||
#elif defined(__KCC)
|
||||
typedef less_than_op_first_archetype< less_than_comparable_archetype<> > T;
|
||||
typedef less_than_op_second_archetype< convertible_to_archetype<T> > FT;
|
||||
#endif
|
||||
forward_iterator_archetype<FT> fi;
|
||||
T value(dummy_cons);
|
||||
@ -714,12 +735,10 @@ main()
|
||||
{
|
||||
typedef null_archetype<int> Arg1;
|
||||
typedef null_archetype<char> Arg2;
|
||||
#if defined(__GNUC__) || defined(__KCC)
|
||||
typedef convertible_to_archetype<Arg1,
|
||||
convertible_to_archetype<Arg2> > FT;
|
||||
typedef convertible_to_archetype<Arg2,
|
||||
convertible_to_archetype<Arg1> > T;
|
||||
#endif
|
||||
typedef forward_iterator_archetype<FT> FIter;
|
||||
FIter fi;
|
||||
T value(dummy_cons);
|
||||
@ -729,16 +748,15 @@ main()
|
||||
}
|
||||
{
|
||||
typedef null_archetype<> Tout;
|
||||
#if defined(__GNUC__) || defined(__KCC)
|
||||
typedef less_than_op_first_archetype<
|
||||
less_than_op_second_archetype<
|
||||
convertible_to_archetype<Tout>, optag2>, optag1 > Tin1;
|
||||
typedef less_than_op_second_archetype<
|
||||
less_than_op_first_archetype<
|
||||
convertible_to_archetype<Tout>, optag2> ,optag1> Tin2;
|
||||
#endif
|
||||
input_iterator_archetype<Tin1> in1;
|
||||
input_iterator_archetype<Tin2> in2;
|
||||
// gcc bug
|
||||
BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Tin1> in1;
|
||||
BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Tin2> in2;
|
||||
output_iterator_archetype<Tout> out(dummy_cons);
|
||||
out = std::merge(in1, in1, in2, in2, out);
|
||||
out = std::set_union(in1, in1, in2, in2, out);
|
||||
@ -747,21 +765,11 @@ main()
|
||||
out = std::set_symmetric_difference(in1, in1, in2, in2, out);
|
||||
}
|
||||
{
|
||||
typedef null_archetype<int> Arg1;
|
||||
typedef null_archetype<char> Arg2;
|
||||
typedef null_archetype<short> Tout;
|
||||
#if defined(__GNUC__) || defined(__KCC)
|
||||
typedef convertible_to_archetype<Tout,
|
||||
convertible_to_archetype<Arg1,
|
||||
convertible_to_archetype<Arg2> > > Tin1;
|
||||
typedef convertible_to_archetype<Tout,
|
||||
convertible_to_archetype<Arg2,
|
||||
convertible_to_archetype<Arg1> > > Tin2;
|
||||
#endif
|
||||
input_iterator_archetype<Tin1> in1;
|
||||
input_iterator_archetype<Tin2> in2;
|
||||
output_iterator_archetype<Tout> out(dummy_cons);
|
||||
binary_predicate_archetype<Arg1, Arg2> comp(dummy_cons);
|
||||
typedef null_archetype<> T;
|
||||
input_iterator_archetype<T> in1;
|
||||
input_iterator_archetype<T,2> in2;
|
||||
output_iterator_archetype<T> out(dummy_cons);
|
||||
binary_predicate_archetype<T, T> comp(dummy_cons);
|
||||
out = std::merge(in1, in1, in2, in2, out, comp);
|
||||
out = std::set_union(in1, in1, in2, in2, out, comp);
|
||||
out = std::set_intersection(in1, in1, in2, in2, out, comp);
|
||||
@ -782,31 +790,23 @@ main()
|
||||
binary_predicate_archetype<Arg, Arg> comp(dummy_cons);
|
||||
std::inplace_merge(bi, bi, bi, comp);
|
||||
}
|
||||
// gcc bug
|
||||
{
|
||||
#if defined(__GNUC__) || defined(__KCC)
|
||||
typedef less_than_op_first_archetype<
|
||||
less_than_op_second_archetype<null_archetype<>, optag1>, optag2> Tin1;
|
||||
typedef less_than_op_second_archetype<
|
||||
less_than_op_first_archetype<null_archetype<>, optag1>, optag2> Tin2;
|
||||
#endif
|
||||
input_iterator_archetype<Tin1> in1;
|
||||
input_iterator_archetype<Tin2> in2;
|
||||
BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Tin1> in1;
|
||||
BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Tin2> in2;
|
||||
bool b = std::includes(in1, in1, in2, in2);
|
||||
b = std::lexicographical_compare(in1, in1, in2, in2);
|
||||
ignore_unused_variable_warning(b);
|
||||
}
|
||||
{
|
||||
typedef null_archetype<int> Arg1;
|
||||
typedef null_archetype<char> Arg2;
|
||||
#if defined(__GNUC__) || defined(__KCC)
|
||||
typedef convertible_to_archetype<Arg1,
|
||||
convertible_to_archetype<Arg2> > Tin1;
|
||||
typedef convertible_to_archetype<Arg2,
|
||||
convertible_to_archetype<Arg1> > Tin2;
|
||||
#endif
|
||||
input_iterator_archetype<Tin1> in1;
|
||||
input_iterator_archetype<Tin2> in2;
|
||||
binary_predicate_archetype<Arg1, Arg2> comp(dummy_cons);
|
||||
typedef null_archetype<int> Tin;
|
||||
input_iterator_archetype<Tin> in1;
|
||||
input_iterator_archetype<Tin,1> in2;
|
||||
binary_predicate_archetype<Tin, Tin> comp(dummy_cons);
|
||||
bool b = std::includes(in1, in1, in2, in2, comp);
|
||||
b = std::lexicographical_compare(in1, in1, in2, in2, comp);
|
||||
ignore_unused_variable_warning(b);
|
||||
@ -834,8 +834,10 @@ main()
|
||||
{
|
||||
typedef less_than_comparable_archetype<> T;
|
||||
T a(dummy_cons), b(dummy_cons);
|
||||
const T& c = std::min(a, b);
|
||||
const T& d = std::max(a, b);
|
||||
BOOST_USING_STD_MIN();
|
||||
BOOST_USING_STD_MAX();
|
||||
const T& c = min BOOST_PREVENT_MACRO_SUBSTITUTION(a, b);
|
||||
const T& d = max BOOST_PREVENT_MACRO_SUBSTITUTION(a, b);
|
||||
ignore_unused_variable_warning(c);
|
||||
ignore_unused_variable_warning(d);
|
||||
}
|
||||
@ -844,8 +846,10 @@ main()
|
||||
binary_predicate_archetype<Arg, Arg> comp(dummy_cons);
|
||||
typedef convertible_to_archetype<Arg> T;
|
||||
T a(dummy_cons), b(dummy_cons);
|
||||
const T& c = std::min(a, b, comp);
|
||||
const T& d = std::max(a, b, comp);
|
||||
BOOST_USING_STD_MIN();
|
||||
BOOST_USING_STD_MAX();
|
||||
const T& c = min BOOST_PREVENT_MACRO_SUBSTITUTION(a, b, comp);
|
||||
const T& d = max BOOST_PREVENT_MACRO_SUBSTITUTION(a, b, comp);
|
||||
ignore_unused_variable_warning(c);
|
||||
ignore_unused_variable_warning(d);
|
||||
}
|
||||
@ -897,8 +901,7 @@ main()
|
||||
typedef sgi_assignable_archetype<
|
||||
convertible_to_archetype<Arg1> > T;
|
||||
typedef convertible_to_archetype<T> Ret;
|
||||
typedef convertible_to_archetype<Arg2> Tin;
|
||||
input_iterator_archetype<Tin> in;
|
||||
input_iterator_archetype<Arg2> in;
|
||||
T init(dummy_cons);
|
||||
binary_function_archetype<Arg1, Arg2, Ret> op(dummy_cons);
|
||||
init = std::accumulate(in, in, init, op);
|
||||
@ -918,38 +921,30 @@ main()
|
||||
convertible_to_archetype<AddArg1> > T;
|
||||
typedef convertible_to_archetype<AddArg2> RetMult;
|
||||
typedef convertible_to_archetype<T> RetAdd;
|
||||
typedef convertible_to_archetype<MultArg1> Tin1;
|
||||
typedef convertible_to_archetype<MultArg2> Tin2;
|
||||
input_iterator_archetype<Tin1> in1;
|
||||
input_iterator_archetype<Tin2> in2;
|
||||
input_iterator_archetype<MultArg1> in1;
|
||||
input_iterator_archetype<MultArg2> in2;
|
||||
T init(dummy_cons);
|
||||
binary_function_archetype<MultArg1, MultArg2, RetMult> mult_op(dummy_cons);
|
||||
binary_function_archetype<AddArg1, AddArg2, RetAdd> add_op(dummy_cons);
|
||||
init = std::inner_product(in1, in1, in2, init, add_op, mult_op);
|
||||
}
|
||||
{
|
||||
input_iterator_archetype<part_sum::Tin> in;
|
||||
output_iterator_archetype<part_sum::Tout> out(dummy_cons);
|
||||
input_iterator_archetype<part_sum::T> in;
|
||||
output_iterator_archetype<part_sum::T> out(dummy_cons);
|
||||
out = std::partial_sum(in, in, out);
|
||||
}
|
||||
{
|
||||
typedef null_archetype<int> Arg;
|
||||
typedef null_archetype<char> Tout;
|
||||
typedef sgi_assignable_archetype<
|
||||
convertible_to_archetype<Arg,
|
||||
convertible_to_archetype<Tout> > > Tin;
|
||||
typedef convertible_to_archetype<Tout,
|
||||
convertible_to_archetype<Tin> > Ret;
|
||||
input_iterator_archetype<Tin> in;
|
||||
output_iterator_archetype<Tout> out(dummy_cons);
|
||||
binary_function_archetype<Arg, Arg, Ret> add_op(dummy_cons);
|
||||
typedef sgi_assignable_archetype<> T;
|
||||
input_iterator_archetype<T> in;
|
||||
output_iterator_archetype<T> out(dummy_cons);
|
||||
binary_function_archetype<T, T, T> add_op(dummy_cons);
|
||||
out = std::partial_sum(in, in, out, add_op);
|
||||
binary_function_archetype<Arg, Arg, Ret> subtract_op(dummy_cons);
|
||||
binary_function_archetype<T, T, T> subtract_op(dummy_cons);
|
||||
out = std::adjacent_difference(in, in, out, subtract_op);
|
||||
}
|
||||
{
|
||||
input_iterator_archetype<part_sum::Tin> in;
|
||||
output_iterator_archetype<part_sum::Tout> out(dummy_cons);
|
||||
input_iterator_archetype<part_sum::T> in;
|
||||
output_iterator_archetype<part_sum::T> out(dummy_cons);
|
||||
out = std::adjacent_difference(in, in, out);
|
||||
}
|
||||
return 0;
|
24
test/usage_fail.cpp
Normal file
24
test/usage_fail.cpp
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright David Abrahams 2006. 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/concept/usage.hpp>
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
|
||||
template <class T>
|
||||
struct StringInitializable
|
||||
{
|
||||
typedef int associated;
|
||||
BOOST_CONCEPT_USAGE(StringInitializable)
|
||||
{
|
||||
T x = "foo";
|
||||
boost::ignore_unused(x);
|
||||
}
|
||||
};
|
||||
|
||||
// Test that accessing an associated type will actually exercise usage
|
||||
// requirements
|
||||
typedef StringInitializable<int>::associated tee;
|
||||
|
||||
|
||||
|
13
test/where.cpp
Normal file
13
test/where.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright David Abrahams 2006. 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>
|
||||
#undef NDEBUG
|
||||
#include "fake_sort.hpp"
|
||||
|
||||
int main()
|
||||
{
|
||||
std::vector<int> v;
|
||||
fake::sort(v.begin(), v.end());
|
||||
return 0;
|
||||
}
|
13
test/where_fail.cpp
Normal file
13
test/where_fail.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright David Abrahams 2006. 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 <list>
|
||||
#undef NDEBUG
|
||||
#include "fake_sort.hpp"
|
||||
|
||||
int main()
|
||||
{
|
||||
std::list<int> v;
|
||||
fake::sort(v.begin(), v.end());
|
||||
return 0;
|
||||
}
|
@ -1,225 +1,186 @@
|
||||
<HTML>
|
||||
<!--
|
||||
-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 2000
|
||||
--
|
||||
-- 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. We make no
|
||||
-- representations about the suitability of this software for any
|
||||
-- purpose. It is provided "as is" without express or implied warranty.
|
||||
-->
|
||||
<Head>
|
||||
<Title>Using Concept Checks</Title>
|
||||
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
|
||||
ALINK="#ff0000">
|
||||
<IMG SRC="../../c++boost.gif"
|
||||
ALT="C++ Boost" width="277" height="86">
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<BR Clear>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<!-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 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) -->
|
||||
|
||||
<head>
|
||||
<meta name="generator" content=
|
||||
"HTML Tidy for Linux/x86 (vers 1 September 2005), see www.w3.org" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii" />
|
||||
|
||||
<h2><a name="using-concept-checks">Using Concept Checks</a></h2>
|
||||
<title>Using Concept Checks</title>
|
||||
<link rel="stylesheet" href="../../rst.css" type="text/css" />
|
||||
</head>
|
||||
|
||||
For each concept there is a concept checking class which can be used
|
||||
to make sure that a given type (or set of types) models the concept.
|
||||
The Boost Concept Checking Library (BCCL) includes concept checking classes
|
||||
for all of the concepts used in the C++ standard library and a few
|
||||
more. The <a href="./reference.htm">Reference</a> section lists these
|
||||
concept checking classes. In addition, other boost libraries come with
|
||||
concept checking classes for the concepts that are particular to those
|
||||
libraries. For example, there are <a
|
||||
href="../graph/doc/graph_concepts.html">graph concepts</a> and <a
|
||||
href="../property_map/property_map.html">property map concepts</a>.
|
||||
Also, whenever <b>anyone</b> writing a class of function template
|
||||
needs to express requirements that are not yet stated by an existing
|
||||
concept, a new concept checking class should be created. How
|
||||
to do this is explained in <a href="./creating_concepts.htm">Creating
|
||||
Concept Checking Classes</a>.
|
||||
<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" />
|
||||
|
||||
<p>
|
||||
An example of a concept checking class from the BCCL is the
|
||||
<tt>EqualityComparableConcept</tt> class. The class corresponds to the
|
||||
EqualityComparable requirements described in 20.1.1 of the C++
|
||||
Standard, and to the <a
|
||||
href="http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</a>
|
||||
concept documented in the SGI STL.
|
||||
<h2><a name="using-concept-checks" id="using-concept-checks">Using Concept
|
||||
Checks</a></h2>
|
||||
|
||||
<pre>
|
||||
template <class T>
|
||||
struct EqualityComparableConcept;
|
||||
<p>For each concept there is a concept checking class template that can be
|
||||
used to make sure that a given type (or set of types) models the concept.
|
||||
The Boost Concept Checking Library (BCCL) includes concept checking class
|
||||
templates for all of the concepts used in the C++ standard library and a
|
||||
few more. See the <a href="./reference.htm">Reference</a> section for a
|
||||
complete list. In addition, other boost libraries come with concept
|
||||
checking classes for the concepts that are particular to those libraries.
|
||||
For example, there are <a href="../graph/doc/graph_concepts.html">graph
|
||||
concepts</a> and <a href="../property_map/doc/property_map.html">property map
|
||||
concepts</a>. Also, whenever <b>anyone</b> writing function templates needs
|
||||
to express requirements that are not yet stated by an existing concept, a
|
||||
new concept checking class should be created. How to do this is explained
|
||||
in <a href="./creating_concepts.htm">Creating Concept Checking
|
||||
Classes</a>.</p>
|
||||
|
||||
<p>An example of a concept checking class from the BCCL is the
|
||||
<tt>EqualityComparableConcept</tt> class. The class corresponds to the
|
||||
EqualityComparable requirements described in 20.1.1 of the C++ Standard,
|
||||
and to the <a href=
|
||||
"http://www.boost.org/sgi/stl/EqualityComparable.html">EqualityComparable</a>
|
||||
concept documented in the SGI STL.</p>
|
||||
<pre>
|
||||
template <class T>
|
||||
struct EqualityComparable;
|
||||
</pre>
|
||||
|
||||
The template argument <tt>T</tt> will the type to be checked. That is,
|
||||
the purpose of <tt>EqualityComparableConcept</tt> is to make sure that
|
||||
the template argument given for <tt>T</tt> models the
|
||||
EqualityComparable concept.
|
||||
<p>The template argument is the type to be checked. That is, the purpose of
|
||||
<tt>EqualityComparable<<em>T</em>></tt> is to make sure that
|
||||
<tt><em>T</em></tt> models the EqualityComparable concept.</p>
|
||||
|
||||
<p>
|
||||
Each concept checking class has a member function named
|
||||
<tt>constraints()</tt> which contains the valid expressions for the
|
||||
concept. To check whether some type is EqualityComparable we need to
|
||||
instantiate the concept checking class with the type and then find a
|
||||
way to get the compiler to compile the <tt>constraints()</tt> function
|
||||
without actually executing the function. The Boost Concept Checking
|
||||
Library defines two utilities that make this easy:
|
||||
<tt>function_requires()</tt> and <tt>BOOST_CLASS_REQUIRE</tt>.
|
||||
<h4><tt>BOOST_CONCEPT_ASSERT()</tt></h4>
|
||||
|
||||
<h4><tt>function_requires()</tt></h4>
|
||||
<p>The most versatile way of checking concept requirements is to use the
|
||||
<code>BOOST_CONCEPT_ASSERT()</code> macro. You can use this macro at any
|
||||
scope, by passing a concept checking template specialization enclosed in
|
||||
parentheses. <strong>Note:</strong> that means invocations of
|
||||
<code>BOOST_CONCEPT_ASSERT</code> will appear to use <strong>double
|
||||
parentheses</strong>.</p>
|
||||
<pre>
|
||||
<font color="green">// In my library:</font>
|
||||
template <class T>
|
||||
void generic_library_function(T x)
|
||||
{
|
||||
BOOST_CONCEPT_ASSERT<strong>((</strong>EqualityComparable<T><strong>))</strong>;
|
||||
<font color="green">// ...</font>
|
||||
};
|
||||
|
||||
The <tt>function_requires()</tt> function can be used in function bodies
|
||||
and the <tt>BOOST_CLASS_REQUIRE</tt> macro can be used inside class
|
||||
bodies. The <tt>function_requires()</tt> function takes no arguments,
|
||||
but has a template parameter for the concept checking class. This
|
||||
means that the instantiated concept checking class must be given as an
|
||||
explicit template argument, as shown below.
|
||||
template <class It>
|
||||
class generic_library_class
|
||||
{
|
||||
BOOST_CONCEPT_ASSERT<strong>((</strong>RandomAccessIterator<It><strong>))</strong>;
|
||||
<font color="green">// ...</font>
|
||||
};
|
||||
|
||||
<pre>
|
||||
// In my library:
|
||||
template <class T>
|
||||
void generic_library_function(T x)
|
||||
{
|
||||
function_requires< EqualityComparableConcept<T> >();
|
||||
// ...
|
||||
};
|
||||
<font color="green">// In the user's code:</font>
|
||||
class foo {
|
||||
<font color="green">//... </font>
|
||||
};
|
||||
|
||||
// In the user's code:
|
||||
class foo {
|
||||
//...
|
||||
};
|
||||
|
||||
int main() {
|
||||
foo f;
|
||||
generic_library_function(f);
|
||||
return 0;
|
||||
}
|
||||
int main() {
|
||||
foo x;
|
||||
generic_library_function(x);
|
||||
generic_library_class<std::vector<char>::iterator> y;
|
||||
<font color="green">//...</font>
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h4><tt>BOOST_CONCEPT_REQUIRES</tt></h4>
|
||||
|
||||
<h4><tt>BOOST_CLASS_REQUIRE</tt></h4>
|
||||
<p>One of the nice things about the proposed C++0x <a href=
|
||||
"http://www.generic-programming.org/languages/conceptcpp/tutorial">syntax
|
||||
for declaring concept constrained function templates</a> is the way that
|
||||
constraints are part of the function <em>declaration</em>, so clients will
|
||||
see them. <code>BOOST_CONCEPT_ASSERT</code> can only express constraints
|
||||
within the function template definition, which hides the constraint in the
|
||||
function body. Aside from the loss of a self-documenting interface,
|
||||
asserting conformance only in the function body can undesirably delay
|
||||
checking if the function is explicitly instantiated in a different
|
||||
translation unit from the one in which it is called, or if the compiler
|
||||
does link-time instantiation.</p>
|
||||
|
||||
The <tt>BOOST_CLASS_REQUIRE</tt> macro can be used inside a class
|
||||
definition to check whether some type models a concept.
|
||||
|
||||
<pre>
|
||||
// In my library:
|
||||
template <class T>
|
||||
struct generic_library_class
|
||||
{
|
||||
BOOST_CLASS_REQUIRE(T, boost, EqualityComparableConcept);
|
||||
// ...
|
||||
};
|
||||
|
||||
// In the user's code:
|
||||
class foo {
|
||||
//...
|
||||
};
|
||||
|
||||
int main() {
|
||||
generic_library_class<foo> glc;
|
||||
// ...
|
||||
return 0;
|
||||
}
|
||||
<p>The <tt>BOOST_CONCEPT_REQUIRES</tt> macro can be used in a function
|
||||
template declaration to check whether some type models a concept. It
|
||||
accepts two arguments, a <strong>list of constraints</strong>, and the
|
||||
function template's return type. The list of constraints takes the form of
|
||||
a sequence of adjacent concept checking template specializations,
|
||||
<strong>in double parentheses</strong>, and the function's return type must
|
||||
also be parenthesized. For example, the standard <code>stable_sort</code>
|
||||
algorithm might be declared as follows: </p>
|
||||
<pre>
|
||||
template <class RanIter>
|
||||
BOOST_CONCEPT_REQUIRES(
|
||||
((Mutable_RandomAccessIterator<RanIter>))
|
||||
((LessThanComparable<typename Mutable_RandomAccessIterator<RanIter>::value_type>)),
|
||||
(void)) <font color="green">// return type</font>
|
||||
stable_sort(RanIter,RanIter);
|
||||
</pre>
|
||||
|
||||
<p>Note that the algorithm requires that the value type of the iterator be
|
||||
LessThanComparable, and it accesses that value type through the
|
||||
<code>Mutable_RandomAccessIterator</code> concept checking template. In
|
||||
general, the Boost concept checking classes expose associated types as
|
||||
nested member typedefs so that you can use this syntax, which mimics the
|
||||
approach used in the concept support proposed for the next version of
|
||||
C++.</p>
|
||||
|
||||
<h4>Example</h4>
|
||||
<h4>Multi-Type Concepts</h4>
|
||||
|
||||
<p>
|
||||
Getting back to the earlier <a
|
||||
href="./concept_check.htm#motivating-example">motivating example</a>,
|
||||
one good applicatino of concept checks would be to insert
|
||||
<tt>function_requires()</tt> at the top of <tt>std::stable_sort()</tt>
|
||||
to make sure the template parameter type models <a
|
||||
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">
|
||||
RandomAccessIterator</a>. In addition, <tt>std::stable_sort()</tt>
|
||||
requires that the <tt>value_type</tt> of the iterators be
|
||||
<a href="http://www.sgi.com/tech/stl/LessThanComparable.html">
|
||||
LessThanComparable</a>, so we also use <tt>function_requires()</tt> to
|
||||
check this.
|
||||
|
||||
<pre>
|
||||
template <class RandomAccessIter>
|
||||
void stable_sort(RandomAccessIter first, RandomAccessIter last)
|
||||
{
|
||||
function_requires< RandomAccessIteratorConcept<RandomAccessIter> >();
|
||||
typedef typename std::iterator_traits<RandomAccessIter>::value_type value_type;
|
||||
function_requires< LessThanComparableConcept<value_type> >();
|
||||
...
|
||||
}
|
||||
<p>Some concepts deal with more than one type. In this case the
|
||||
corresponding concept checking class will have multiple template
|
||||
parameters. The following example shows how <tt>BOOST_CONCEPT_REQUIRES</tt>
|
||||
is used with the <a href=
|
||||
"../property_map/doc/ReadWritePropertyMap.html">ReadWritePropertyMap</a>
|
||||
concept, which takes two type parameters: a property map and the key type
|
||||
for the map.</p>
|
||||
<pre>
|
||||
template <class G, class Buffer, class BFSVisitor,
|
||||
class ColorMap>
|
||||
BOOST_CONCEPT_REQUIRES(
|
||||
((ReadWritePropertyMap<ColorMap, typename IncidenceGraph<G>::vertex_descriptor>)),
|
||||
(void)) <font color="green">// return type</font>
|
||||
breadth_first_search(G& g,
|
||||
typename graph_traits<IncidenceGraph>::vertex_descriptor s,
|
||||
Buffer& Q, BFSVisitor vis, ColorMap color)
|
||||
{
|
||||
typedef typename IncidenceGraph<G>::vertex_descriptor Vertex;
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
|
||||
|
||||
|
||||
<!-- There are a few places where the SGI STL documentation differs
|
||||
from the corresponding requirements described in the C++ Standard. In
|
||||
these cases we use the definition from the C++ Standard. -->
|
||||
|
||||
<p>
|
||||
Some concepts deal with more than one type. In this case the
|
||||
corresponding concept checking class will have multiple template
|
||||
parameters. The following example shows how
|
||||
<tt>function_requires()</tt> is used with the <a
|
||||
href="../property_map/ReadWritePropertyMap.html">ReadWritePropertyMap</a>
|
||||
concept which takes two type parameters: a property map and the key
|
||||
type for the map.
|
||||
|
||||
<pre>
|
||||
template <class IncidenceGraph, class Buffer, class BFSVisitor,
|
||||
class ColorMap>
|
||||
void breadth_first_search(IncidenceGraph& g,
|
||||
typename graph_traits<IncidenceGraph>::vertex_descriptor s,
|
||||
Buffer& Q, BFSVisitor vis, ColorMap color)
|
||||
{
|
||||
typedef typename graph_traits<IncidenceGraph>::vertex_descriptor Vertex;
|
||||
function_requires< ReadWritePropertyMap<ColorMap, Vertex> >();
|
||||
...
|
||||
}
|
||||
<p>Although concept checks are designed for use by generic library
|
||||
implementors, they can also be useful to end users. Sometimes one may not
|
||||
be sure whether some type models a particular concept. The syntactic
|
||||
requirements, at least, can easily be checked by creating a small program
|
||||
and using <tt>BOOST_CONCEPT_ASSERT</tt> with the type and concept in
|
||||
question. For example:</p>
|
||||
<pre>
|
||||
<font color=
|
||||
"green">// Make sure list<int> has bidirectional iterators.</font>
|
||||
BOOST_CONCEPT_ASSERT((BidirectionalIterator<std::list<int>::iterator>));
|
||||
</pre>
|
||||
|
||||
<p><a href="./concept_check.htm">Prev: Concept Checking
|
||||
Introduction</a><br />
|
||||
<a href="./creating_concepts.htm">Next: Creating Concept Checking
|
||||
Classes</a><br /></p>
|
||||
<hr />
|
||||
|
||||
As an example of using <tt>BOOST_CLASS_REQUIRE</tt> we look at a concept
|
||||
check that could be added to <tt>std::vector</tt>. One requirement
|
||||
that is placed on the element type is that it must be <a
|
||||
href="http://www.sgi.com/tech/stl/Assignable.html">Assignable</a>.
|
||||
We can check this by inserting
|
||||
<tt>class_requires<AssignableConcept<T> ></tt> at the top
|
||||
of the definition for <tt>std::vector</tt>.
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td nowrap="nowrap">Copyright © 2000</td>
|
||||
|
||||
<pre>
|
||||
namespace std {
|
||||
template <class T>
|
||||
struct vector {
|
||||
BOOST_CLASS_REQUIRE(T, boost, AssignableConcept);
|
||||
...
|
||||
};
|
||||
}
|
||||
</pre>
|
||||
|
||||
|
||||
Although the concept checks are designed for use by generic library
|
||||
implementors, they can also be useful to end users. Sometimes one may
|
||||
not be sure whether some type models a particular concept. This can
|
||||
easily be checked by creating a small program and using
|
||||
<tt>function_requires()</tt> with the type and concept in question.
|
||||
The file <a
|
||||
href="./stl_concept_check.cpp"><tt>stl_concept_checks.cpp</tt></a>
|
||||
gives and example of applying the concept checks to STL containers.
|
||||
|
||||
<p>
|
||||
<a href="./concept_check.htm">Prev: Concept Checking Introduction</a> <br>
|
||||
<a href="./creating_concepts.htm">Next: Creating Concept Checking Classes</a>
|
||||
|
||||
<br>
|
||||
<HR>
|
||||
<TABLE>
|
||||
<TR valign=top>
|
||||
<TD nowrap>Copyright © 2000</TD><TD>
|
||||
<A HREF="../../people/jeremy_siek.htm">Jeremy Siek</A>(<A
|
||||
HREF="mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</A>)
|
||||
Andrew Lumsdaine</A>(<A HREF="mailto:lums@osl.iu.edu">lums@osl.iu.edu</A>)
|
||||
</TD></TR></TABLE>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
<td><a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</a>(<a href=
|
||||
"mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</a>) Andrew
|
||||
Lumsdaine(<a href="mailto:lums@osl.iu.edu">lums@osl.iu.edu</a>), 2007
|
||||
<a href="mailto:dave@boost-consulting.com">David Abrahams</a>.</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
|
Reference in New Issue
Block a user