diff --git a/.drone.jsonnet b/.drone.jsonnet new file mode 100644 index 00000000..c07dd21b --- /dev/null +++ b/.drone.jsonnet @@ -0,0 +1,441 @@ +# Copyright 2022 Peter Dimov +# Distributed under the Boost Software License, Version 1.0. +# https://www.boost.org/LICENSE_1_0.txt + +local library = "function"; + +local triggers = +{ + branch: [ "master", "develop", "feature/*" ] +}; + +local ubsan = { UBSAN: '1', UBSAN_OPTIONS: 'print_stacktrace=1' }; +local asan = { ASAN: '1' }; + +local linux_pipeline(name, image, environment, packages = "", sources = [], arch = "amd64") = +{ + name: name, + kind: "pipeline", + type: "docker", + trigger: triggers, + platform: + { + os: "linux", + arch: arch + }, + steps: + [ + { + name: "everything", + image: image, + environment: environment, + commands: + [ + 'set -e', + 'uname -a', + 'echo $DRONE_STAGE_MACHINE', + ] + + (if sources != [] then [ ('apt-add-repository "' + source + '"') for source in sources ] else []) + + (if packages != "" then [ 'apt-get update', 'apt-get -y install ' + packages ] else []) + + [ + 'export LIBRARY=' + library, + './.drone/drone.sh', + ] + } + ] +}; + +local macos_pipeline(name, environment, xcode_version = "12.2", osx_version = "catalina", arch = "amd64") = +{ + name: name, + kind: "pipeline", + type: "exec", + trigger: triggers, + platform: { + "os": "darwin", + "arch": arch + }, + node: { + "os": osx_version + }, + steps: [ + { + name: "everything", + environment: environment + { "DEVELOPER_DIR": "/Applications/Xcode-" + xcode_version + ".app/Contents/Developer" }, + commands: + [ + 'export LIBRARY=' + library, + './.drone/drone.sh', + ] + } + ] +}; + +local windows_pipeline(name, image, environment, arch = "amd64") = +{ + name: name, + kind: "pipeline", + type: "docker", + trigger: triggers, + platform: + { + os: "windows", + arch: arch + }, + "steps": + [ + { + name: "everything", + image: image, + environment: environment, + commands: + [ + 'cmd /C .drone\\\\drone.bat ' + library, + ] + } + ] +}; + +[ + linux_pipeline( + "Linux 16.04 GCC 4.7 32/64", + "cppalliance/droneubuntu1604:1", + { TOOLSET: 'gcc', COMPILER: 'g++-4.7', CXXSTD: '0x', ADDRMD: '32,64' }, + "g++-4.7-multilib", + ), + + linux_pipeline( + "Linux 16.04 GCC 4.8 32/64", + "cppalliance/droneubuntu1604:1", + { TOOLSET: 'gcc', COMPILER: 'g++-4.8', CXXSTD: '11', ADDRMD: '32,64' }, + "g++-4.8-multilib", + ), + + linux_pipeline( + "Linux 16.04 GCC 4.9 32/64", + "cppalliance/droneubuntu1604:1", + { TOOLSET: 'gcc', COMPILER: 'g++-4.9', CXXSTD: '11', ADDRMD: '32,64' }, + "g++-4.9-multilib", + ), + + linux_pipeline( + "Linux 16.04 GCC 5* 32/64", + "cppalliance/droneubuntu1604:1", + { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14', ADDRMD: '32,64' }, + ), + + linux_pipeline( + "Linux 18.04 GCC 6 32/64", + "cppalliance/droneubuntu1804:1", + { TOOLSET: 'gcc', COMPILER: 'g++-6', CXXSTD: '11,14', ADDRMD: '32,64' }, + "g++-6-multilib", + ), + + linux_pipeline( + "Linux 18.04 GCC 7* 32/64", + "cppalliance/droneubuntu1804:1", + { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14,17', ADDRMD: '32,64' }, + ), + + linux_pipeline( + "Linux 18.04 GCC 8 32/64", + "cppalliance/droneubuntu1804:1", + { TOOLSET: 'gcc', COMPILER: 'g++-8', CXXSTD: '11,14,17', ADDRMD: '32,64' }, + "g++-8-multilib", + ), + + linux_pipeline( + "Linux 20.04 GCC 9* 32/64", + "cppalliance/droneubuntu2004:1", + { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14,17,2a', ADDRMD: '32,64' }, + ), + + linux_pipeline( + "Linux 20.04 GCC 9* ARM64 UBSAN", + "cppalliance/droneubuntu2004:multiarch", + { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14,17,2a' } + ubsan, + arch="arm64", + ), + + linux_pipeline( + "Linux 20.04 GCC 9* ARM64 ASAN", + "cppalliance/droneubuntu2004:multiarch", + { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14,17,2a' } + asan, + arch="arm64", + ), + + linux_pipeline( + "Linux 20.04 GCC 9* S390x UBSAN", + "cppalliance/droneubuntu2004:multiarch", + { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14,17,2a' } + ubsan, + arch="s390x", + ), + + linux_pipeline( + "Linux 20.04 GCC 10 32/64", + "cppalliance/droneubuntu2004:1", + { TOOLSET: 'gcc', COMPILER: 'g++-10', CXXSTD: '11,14,17,20', ADDRMD: '32,64' }, + "g++-10-multilib", + ), + + linux_pipeline( + "Linux 22.04 GCC 11* 32/64", + "cppalliance/droneubuntu2204:1", + { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14,17,2a', ADDRMD: '32,64' }, + ), + + linux_pipeline( + "Linux 22.04 GCC 12 32/64", + "cppalliance/droneubuntu2204:1", + { TOOLSET: 'gcc', COMPILER: 'g++-12', CXXSTD: '11,14,17,20,2b', ADDRMD: '32,64' }, + "g++-12-multilib", + ), + + linux_pipeline( + "Linux 24.04 GCC 13 32/64", + "cppalliance/droneubuntu2404:1", + { TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '11,14,17,20,2b', ADDRMD: '32,64' }, + "g++-13-multilib", + ), + + linux_pipeline( + "Linux 24.04 GCC 14 32/64 UBSAN", + "cppalliance/droneubuntu2404:1", + { TOOLSET: 'gcc', COMPILER: 'g++-14', CXXSTD: '11,14,17,20,2b', ADDRMD: '32,64' } + ubsan, + "g++-14-multilib", + ), + + linux_pipeline( + "Linux 24.04 GCC 14 32/64 ASAN", + "cppalliance/droneubuntu2404:1", + { TOOLSET: 'gcc', COMPILER: 'g++-14', CXXSTD: '11,14,17,20,2b', ADDRMD: '32,64' } + asan, + "g++-14-multilib", + ), + + linux_pipeline( + "Linux 25.10 GCC 15 32/64", + "cppalliance/droneubuntu2510:1", + { TOOLSET: 'gcc', COMPILER: 'g++-15', CXXSTD: '11,14,17,20,23,2c', ADDRMD: '32,64' }, + "g++-15-multilib", + ), + + linux_pipeline( + "Linux 16.04 Clang 3.5", + "cppalliance/droneubuntu1604:1", + { TOOLSET: 'clang', COMPILER: 'clang++-3.5', CXXSTD: '11' }, + "clang-3.5", + ), + + linux_pipeline( + "Linux 16.04 Clang 3.6", + "cppalliance/droneubuntu1604:1", + { TOOLSET: 'clang', COMPILER: 'clang++-3.6', CXXSTD: '11,14' }, + "clang-3.6", + ), + + linux_pipeline( + "Linux 16.04 Clang 3.7", + "cppalliance/droneubuntu1604:1", + { TOOLSET: 'clang', COMPILER: 'clang++-3.7', CXXSTD: '11,14' }, + "clang-3.7", + ), + + linux_pipeline( + "Linux 16.04 Clang 3.8", + "cppalliance/droneubuntu1604:1", + { TOOLSET: 'clang', COMPILER: 'clang++-3.8', CXXSTD: '11,14' }, + "clang-3.8", + ), + + linux_pipeline( + "Linux 18.04 Clang 3.9", + "cppalliance/droneubuntu1804:1", + { TOOLSET: 'clang', COMPILER: 'clang++-3.9', CXXSTD: '11,14' }, + "clang-3.9", + ), + + linux_pipeline( + "Linux 18.04 Clang 4.0", + "cppalliance/droneubuntu1804:1", + { TOOLSET: 'clang', COMPILER: 'clang++-4.0', CXXSTD: '11,14' }, + "clang-4.0", + ), + + linux_pipeline( + "Linux 18.04 Clang 5.0", + "cppalliance/droneubuntu1804:1", + { TOOLSET: 'clang', COMPILER: 'clang++-5.0', CXXSTD: '11,14,1z' }, + "clang-5.0", + ), + + linux_pipeline( + "Linux 18.04 Clang 6.0", + "cppalliance/droneubuntu1804:1", + { TOOLSET: 'clang', COMPILER: 'clang++-6.0', CXXSTD: '11,14,17' }, + "clang-6.0", + ), + + linux_pipeline( + "Linux 20.04 Clang 7", + "cppalliance/droneubuntu2004:1", + { TOOLSET: 'clang', COMPILER: 'clang++-7', CXXSTD: '11,14,17' }, + "clang-7", + ), + + linux_pipeline( + "Linux 20.04 Clang 8", + "cppalliance/droneubuntu2004:1", + { TOOLSET: 'clang', COMPILER: 'clang++-8', CXXSTD: '11,14,17' }, + "clang-8", + ), + + linux_pipeline( + "Linux 20.04 Clang 9", + "cppalliance/droneubuntu2004:1", + { TOOLSET: 'clang', COMPILER: 'clang++-9', CXXSTD: '11,14,17,2a' }, + "clang-9", + ), + + linux_pipeline( + "Linux 20.04 Clang 10", + "cppalliance/droneubuntu2004:1", + { TOOLSET: 'clang', COMPILER: 'clang++-10', CXXSTD: '11,14,17,2a' }, + "clang-10", + ), + + linux_pipeline( + "Linux 20.04 Clang 11", + "cppalliance/droneubuntu2004:1", + { TOOLSET: 'clang', COMPILER: 'clang++-11', CXXSTD: '11,14,17,2a' }, + "clang-11", + ), + + linux_pipeline( + "Linux 20.04 Clang 12", + "cppalliance/droneubuntu2004:1", + { TOOLSET: 'clang', COMPILER: 'clang++-12', CXXSTD: '11,14,17,2a' }, + "clang-12", + ), + + linux_pipeline( + "Linux 22.04 Clang 13", + "cppalliance/droneubuntu2204:1", + { TOOLSET: 'clang', COMPILER: 'clang++-13', CXXSTD: '11,14,17,20' }, + "clang-13", + ), + + linux_pipeline( + "Linux 22.04 Clang 14", + "cppalliance/droneubuntu2204:1", + { TOOLSET: 'clang', COMPILER: 'clang++-14', CXXSTD: '11,14,17,20,2b' }, + "clang-14", + ), + + linux_pipeline( + "Linux 22.04 Clang 15", + "cppalliance/droneubuntu2204:1", + { TOOLSET: 'clang', COMPILER: 'clang++-15', CXXSTD: '11,14,17,20,2b' }, + "clang-15", + ), + + linux_pipeline( + "Linux 24.04 Clang 16", + "cppalliance/droneubuntu2404:1", + { TOOLSET: 'clang', COMPILER: 'clang++-16', CXXSTD: '11,14,17,20,2b' }, + "clang-16", + ), + + linux_pipeline( + "Linux 24.04 Clang 17", + "cppalliance/droneubuntu2404:1", + { TOOLSET: 'clang', COMPILER: 'clang++-17', CXXSTD: '11,14,17,20,2b' }, + "clang-17", + ), + + linux_pipeline( + "Linux 24.04 Clang 18", + "cppalliance/droneubuntu2404:1", + { TOOLSET: 'clang', COMPILER: 'clang++-18', CXXSTD: '11,14,17,20,2b' }, + "clang-18", + ), + + linux_pipeline( + "Linux 24.04 Clang 19", + "cppalliance/droneubuntu2404:1", + { TOOLSET: 'clang', COMPILER: 'clang++-18', CXXSTD: '11,14,17,20,2b' }, + "clang-18", + ), + + linux_pipeline( + "Linux 24.04 Clang 20 UBSAN", + "cppalliance/droneubuntu2404:1", + { TOOLSET: 'clang', COMPILER: 'clang++-20', CXXSTD: '11,14,17,20,2b' } + ubsan, + "clang-20", + ), + + linux_pipeline( + "Linux 24.04 Clang 20 ASAN", + "cppalliance/droneubuntu2404:1", + { TOOLSET: 'clang', COMPILER: 'clang++-20', CXXSTD: '11,14,17,20,2b' } + asan, + "clang-20", + ), + + linux_pipeline( + "Linux 25.10 Clang 21", + "cppalliance/droneubuntu2510:1", + { TOOLSET: 'clang', COMPILER: 'clang++-21', CXXSTD: '11,14,17,20,23,2c' }, + "clang-21", + ), + + macos_pipeline( + "MacOS 10.15 Xcode 12.2 UBSAN", + { TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '11,14,17,2a' } + ubsan, + ), + + macos_pipeline( + "MacOS 10.15 Xcode 12.2 ASAN", + { TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '11,14,17,2a' } + asan, + ), + + macos_pipeline( + "MacOS 12.4 Xcode 13.4.1 UBSAN", + { TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '11,14,17,20,2b' } + ubsan, + xcode_version = "13.4.1", osx_version = "monterey", arch = "arm64", + ), + + macos_pipeline( + "MacOS 12.4 Xcode 13.4.1 ASAN", + { TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '11,14,17,20,2b' } + asan, + xcode_version = "13.4.1", osx_version = "monterey", arch = "arm64", + ), + + windows_pipeline( + "Windows VS2015 msvc-14.0", + "cppalliance/dronevs2015", + { TOOLSET: 'msvc-14.0', CXXSTD: '14,latest', B2_DONT_EMBED_MANIFEST: '1' }, + ), + + windows_pipeline( + "Windows VS2017 msvc-14.1", + "cppalliance/dronevs2017", + { TOOLSET: 'msvc-14.1', CXXSTD: '14,17,latest' }, + ), + + windows_pipeline( + "Windows VS2019 msvc-14.2", + "cppalliance/dronevs2019", + { TOOLSET: 'msvc-14.2', CXXSTD: '14,17,20,latest' }, + ), + + windows_pipeline( + "Windows VS2022 msvc-14.3", + "cppalliance/dronevs2022:1", + { TOOLSET: 'msvc-14.3', CXXSTD: '14,17,20,latest' }, + ), + + windows_pipeline( + "Windows VS2026 msvc-14.5", + "cppalliance/dronevs2026:1", + { TOOLSET: 'msvc-14.5', CXXSTD: '14,17,20,latest' }, + ), +] diff --git a/.drone/drone.bat b/.drone/drone.bat new file mode 100644 index 00000000..c0e33656 --- /dev/null +++ b/.drone/drone.bat @@ -0,0 +1,23 @@ +@REM Copyright 2022 Peter Dimov +@REM Distributed under the Boost Software License, Version 1.0. +@REM https://www.boost.org/LICENSE_1_0.txt + +@ECHO ON + +set LIBRARY=%1 +set DRONE_BUILD_DIR=%CD% + +set BOOST_BRANCH=develop +if "%DRONE_BRANCH%" == "master" set BOOST_BRANCH=master +cd .. +git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root +cd boost-root +git submodule update --init tools/boostdep +xcopy /s /e /q %DRONE_BUILD_DIR% libs\%LIBRARY%\ +python tools/boostdep/depinst/depinst.py -I example %LIBRARY% +cmd /c bootstrap +b2 -d0 headers + +if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD% +if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD% +b2 -j3 libs/%LIBRARY%/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release embed-manifest-via=linker diff --git a/.drone/drone.sh b/.drone/drone.sh new file mode 100755 index 00000000..e3cda03d --- /dev/null +++ b/.drone/drone.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# Copyright 2022 Peter Dimov +# Distributed under the Boost Software License, Version 1.0. +# https://www.boost.org/LICENSE_1_0.txt + +set -ex +export PATH=~/.local/bin:/usr/local/bin:$PATH + +DRONE_BUILD_DIR=$(pwd) + +BOOST_BRANCH=develop +if [ "$DRONE_BRANCH" = "master" ]; then BOOST_BRANCH=master; fi + +cd .. +git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root +cd boost-root +git submodule update --init tools/boostdep +cp -r $DRONE_BUILD_DIR/* libs/$LIBRARY +python tools/boostdep/depinst/depinst.py -I example $LIBRARY +./bootstrap.sh +./b2 -d0 headers + +echo "using $TOOLSET : : $COMPILER ;" > ~/user-config.jam +./b2 -j3 libs/$LIBRARY/test toolset=$TOOLSET cxxstd=$CXXSTD variant=debug,release ${ADDRMD:+address-model=$ADDRMD} ${UBSAN:+undefined-sanitizer=norecover debug-symbols=on} ${ASAN:+address-sanitizer=norecover debug-symbols=on} ${LINKFLAGS:+linkflags=$LINKFLAGS} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..655c4b3e --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,672 @@ +name: CI + +on: + pull_request: + push: + branches: + - master + - develop + - feature/** + +env: + UBSAN_OPTIONS: print_stacktrace=1 + +jobs: + posix: + strategy: + fail-fast: false + matrix: + include: + - toolset: gcc-4.7 + cxxstd: "11" + container: ubuntu:16.04 + os: ubuntu-latest + install: g++-4.7-multilib + address-model: 32,64 + - toolset: gcc-4.8 + cxxstd: "11" + container: ubuntu:16.04 + os: ubuntu-latest + install: g++-4.8-multilib + address-model: 32,64 + - toolset: gcc-4.9 + cxxstd: "11" + container: ubuntu:16.04 + os: ubuntu-latest + install: g++-4.9-multilib + address-model: 32,64 + - toolset: gcc-5 + cxxstd: "11,14,1z" + container: ubuntu:18.04 + os: ubuntu-latest + install: g++-5-multilib + address-model: 32,64 + - toolset: gcc-6 + cxxstd: "11,14,1z" + container: ubuntu:18.04 + os: ubuntu-latest + install: g++-6-multilib + address-model: 32,64 + - toolset: gcc-7 + cxxstd: "11,14,17" + container: ubuntu:20.04 + os: ubuntu-latest + install: g++-7-multilib + address-model: 32,64 + - toolset: gcc-8 + cxxstd: "11,14,17,2a" + container: ubuntu:20.04 + os: ubuntu-latest + install: g++-8-multilib + address-model: 32,64 + - toolset: gcc-9 + cxxstd: "11,14,17,2a" + container: ubuntu:20.04 + os: ubuntu-latest + install: g++-9-multilib + address-model: 32,64 + - toolset: gcc-10 + cxxstd: "11,14,17,2a" + container: ubuntu:20.04 + os: ubuntu-latest + install: g++-10-multilib + address-model: 32,64 + - toolset: gcc-11 + cxxstd: "11,14,17,20,2b" + os: ubuntu-22.04 + install: g++-11-multilib + address-model: 32,64 + - toolset: gcc-12 + cxxstd: "11,14,17,20,2b" + os: ubuntu-22.04 + install: g++-12-multilib + address-model: 32,64 + - toolset: gcc-13 + cxxstd: "11,14,17,20,2b" + container: ubuntu:24.04 + os: ubuntu-latest + install: g++-13-multilib + address-model: 32,64 + - toolset: gcc-14 + cxxstd: "11,14,17,20,2b" + container: ubuntu:24.04 + os: ubuntu-latest + install: g++-14-multilib + address-model: 32,64 + - toolset: gcc-15 + cxxstd: "11,14,17,20,23,2c" + container: ubuntu:25.10 + os: ubuntu-latest + install: g++-15-multilib + address-model: 32,64 + - toolset: clang + compiler: clang++-3.9 + cxxstd: "11,14" + container: ubuntu:18.04 + os: ubuntu-latest + install: clang-3.9 + - toolset: clang + compiler: clang++-4.0 + cxxstd: "11,14" + container: ubuntu:18.04 + os: ubuntu-latest + install: clang-4.0 + - toolset: clang + compiler: clang++-5.0 + cxxstd: "11,14,1z" + container: ubuntu:18.04 + os: ubuntu-latest + install: clang-5.0 + - toolset: clang + compiler: clang++-6.0 + cxxstd: "11,14,17" + container: ubuntu:20.04 + os: ubuntu-latest + install: clang-6.0 + - toolset: clang + compiler: clang++-7 + cxxstd: "11,14,17" + container: ubuntu:20.04 + os: ubuntu-latest + install: clang-7 + - toolset: clang + compiler: clang++-8 + cxxstd: "11,14,17" + container: ubuntu:20.04 + os: ubuntu-latest + install: clang-8 + - toolset: clang + compiler: clang++-9 + cxxstd: "11,14,17" + container: ubuntu:20.04 + os: ubuntu-latest + install: clang-9 + - toolset: clang + compiler: clang++-10 + cxxstd: "11,14,17,2a" + container: ubuntu:20.04 + os: ubuntu-latest + install: clang-10 + - toolset: clang + compiler: clang++-11 + cxxstd: "11,14,17,2a" + container: ubuntu:20.04 + os: ubuntu-latest + install: clang-11 + - toolset: clang + compiler: clang++-12 + cxxstd: "11,14,17,20" + container: ubuntu:20.04 + os: ubuntu-latest + install: clang-12 + - toolset: clang + compiler: clang++-13 + cxxstd: "11,14,17,20" + container: ubuntu:22.04 + os: ubuntu-latest + install: clang-13 + - toolset: clang + compiler: clang++-14 + cxxstd: "11,14,17,20,2b" + container: ubuntu:22.04 + os: ubuntu-latest + install: clang-14 + - toolset: clang + compiler: clang++-15 + cxxstd: "11,14,17,20,2b" + container: ubuntu:22.04 + os: ubuntu-latest + install: clang-15 + - toolset: clang + compiler: clang++-16 + cxxstd: "11,14,17,20,2b" + container: ubuntu:24.04 + os: ubuntu-latest + install: clang-16 + - toolset: clang + compiler: clang++-17 + cxxstd: "11,14,17,20,2b" + container: ubuntu:24.04 + os: ubuntu-latest + install: clang-17 + - toolset: clang + compiler: clang++-18 + cxxstd: "11,14,17,20,2b" + container: ubuntu:24.04 + os: ubuntu-latest + install: clang-18 + - toolset: clang + compiler: clang++-19 + cxxstd: "11,14,17,20,2b" + container: ubuntu:24.04 + os: ubuntu-latest + install: clang-19 + - toolset: clang + compiler: clang++-20 + cxxstd: "11,14,17,20,23,2c" + container: ubuntu:24.04 + os: ubuntu-latest + install: clang-20 + - toolset: clang + compiler: clang++-21 + cxxstd: "11,14,17,20,23,2c" + container: ubuntu:25.10 + os: ubuntu-latest + install: clang-21 + - toolset: clang + cxxstd: "11,14,17,20,2b" + os: macos-14 + - toolset: clang + cxxstd: "11,14,17,20,2b" + os: macos-15 + - toolset: clang + cxxstd: "11,14,17,20,23,2c" + os: macos-26 + + runs-on: ${{matrix.os}} + + container: + image: ${{matrix.container}} + volumes: + - /node20217:/node20217:rw,rshared + - ${{ startsWith(matrix.container, 'ubuntu:1') && '/node20217:/__e/node20:ro,rshared' || ' ' }} + + defaults: + run: + shell: bash + + steps: + - name: Setup container environment + if: matrix.container + run: | + apt-get update + apt-get -y install sudo python3 git g++ curl xz-utils + + - name: Install nodejs20glibc2.17 + if: ${{ startsWith( matrix.container, 'ubuntu:1' ) }} + run: | + curl -LO https://archives.boost.io/misc/node/node-v20.9.0-linux-x64-glibc-217.tar.xz + tar -xf node-v20.9.0-linux-x64-glibc-217.tar.xz --strip-components 1 -C /node20217 + ldd /__e/node20/bin/node + + - uses: actions/checkout@v4 + + - name: Install packages + if: matrix.install + run: | + sudo apt-get update + sudo apt-get -y install ${{matrix.install}} + + - name: Setup Boost + run: | + echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY + LIBRARY=${GITHUB_REPOSITORY#*/} + echo LIBRARY: $LIBRARY + echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV + echo GITHUB_BASE_REF: $GITHUB_BASE_REF + echo GITHUB_REF: $GITHUB_REF + REF=${GITHUB_BASE_REF:-$GITHUB_REF} + REF=${REF#refs/heads/} + echo REF: $REF + BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true + echo BOOST_BRANCH: $BOOST_BRANCH + cd .. + git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY + git submodule update --init tools/boostdep + python3 tools/boostdep/depinst/depinst.py $LIBRARY + ./bootstrap.sh + ./b2 -d0 headers + + - name: Create user-config.jam + if: matrix.compiler + run: | + echo "using ${{matrix.toolset}} : : ${{matrix.compiler}} ;" > ~/user-config.jam + + - name: Run tests + run: | + cd ../boost-root + export ADDRMD=${{matrix.address-model}} + ./b2 -j3 libs/$LIBRARY/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} ${ADDRMD:+address-model=$ADDRMD} variant=debug,release + + windows: + strategy: + fail-fast: false + matrix: + include: + - toolset: msvc-14.3 + cxxstd: "14,17,20,latest" + addrmd: 32,64 + os: windows-2022 + - toolset: clang-win + cxxstd: "14,17,20,latest" + addrmd: 32,64 + os: windows-2025 + - toolset: gcc + cxxstd: "11,14,17,2a" + addrmd: 64 + os: windows-2022 + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v4 + + - name: Setup Boost + shell: cmd + run: | + echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY% + for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi + echo LIBRARY: %LIBRARY% + echo LIBRARY=%LIBRARY%>>%GITHUB_ENV% + echo GITHUB_BASE_REF: %GITHUB_BASE_REF% + echo GITHUB_REF: %GITHUB_REF% + if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF% + set BOOST_BRANCH=develop + for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master + echo BOOST_BRANCH: %BOOST_BRANCH% + cd .. + git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\ + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY% + cmd /c bootstrap + b2 -d0 headers + + - name: Run tests + shell: cmd + run: | + cd ../boost-root + b2 -j3 libs/%LIBRARY%/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release embed-manifest-via=linker + + posix-cmake-subdir: + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-latest + - os: macos-latest + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v4 + + - name: Install packages + if: matrix.install + run: sudo apt-get -y install ${{matrix.install}} + + - name: Setup Boost + run: | + echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY + LIBRARY=${GITHUB_REPOSITORY#*/} + echo LIBRARY: $LIBRARY + echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV + echo GITHUB_BASE_REF: $GITHUB_BASE_REF + echo GITHUB_REF: $GITHUB_REF + REF=${GITHUB_BASE_REF:-$GITHUB_REF} + REF=${REF#refs/heads/} + echo REF: $REF + BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true + echo BOOST_BRANCH: $BOOST_BRANCH + cd .. + git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY + + - name: Use library with add_subdirectory + run: | + cd ../boost-root/libs/$LIBRARY/test/cmake_subdir_test + mkdir __build__ && cd __build__ + cmake .. + cmake --build . + ctest --output-on-failure --no-tests=error + + posix-cmake-install: + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-latest + - os: macos-latest + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v4 + + - name: Install packages + if: matrix.install + run: sudo apt-get -y install ${{matrix.install}} + + - name: Setup Boost + run: | + echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY + LIBRARY=${GITHUB_REPOSITORY#*/} + echo LIBRARY: $LIBRARY + echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV + echo GITHUB_BASE_REF: $GITHUB_BASE_REF + echo GITHUB_REF: $GITHUB_REF + REF=${GITHUB_BASE_REF:-$GITHUB_REF} + REF=${REF#refs/heads/} + echo REF: $REF + BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true + echo BOOST_BRANCH: $BOOST_BRANCH + cd .. + git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY + + - name: Configure + run: | + cd ../boost-root + mkdir __build__ && cd __build__ + cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DCMAKE_INSTALL_PREFIX=~/.local .. + + - name: Install + run: | + cd ../boost-root/__build__ + cmake --build . --target install + + - name: Use the installed library + run: | + cd ../boost-root/libs/$LIBRARY/test/cmake_install_test && mkdir __build__ && cd __build__ + cmake -DCMAKE_INSTALL_PREFIX=~/.local .. + cmake --build . + ctest --output-on-failure --no-tests=error + + posix-cmake-test: + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-latest + - os: macos-latest + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v4 + + - name: Install packages + if: matrix.install + run: sudo apt-get -y install ${{matrix.install}} + + - name: Setup Boost + run: | + echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY + LIBRARY=${GITHUB_REPOSITORY#*/} + echo LIBRARY: $LIBRARY + echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV + echo GITHUB_BASE_REF: $GITHUB_BASE_REF + echo GITHUB_REF: $GITHUB_REF + REF=${GITHUB_BASE_REF:-$GITHUB_REF} + REF=${REF#refs/heads/} + echo REF: $REF + BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true + echo BOOST_BRANCH: $BOOST_BRANCH + cd .. + git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY + + - name: Configure + run: | + cd ../boost-root + mkdir __build__ && cd __build__ + cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DBUILD_TESTING=ON .. + + - name: Build tests + run: | + cd ../boost-root/__build__ + cmake --build . --target tests + + - name: Run tests + run: | + cd ../boost-root/__build__ + ctest --output-on-failure --no-tests=error + + windows-cmake-subdir: + strategy: + fail-fast: false + matrix: + include: + - os: windows-latest + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v4 + + - name: Setup Boost + shell: cmd + run: | + echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY% + for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi + echo LIBRARY: %LIBRARY% + echo LIBRARY=%LIBRARY%>>%GITHUB_ENV% + echo GITHUB_BASE_REF: %GITHUB_BASE_REF% + echo GITHUB_REF: %GITHUB_REF% + if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF% + set BOOST_BRANCH=develop + for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master + echo BOOST_BRANCH: %BOOST_BRANCH% + cd .. + git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\ + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY% + + - name: Use library with add_subdirectory (Debug) + shell: cmd + run: | + cd ../boost-root/libs/%LIBRARY%/test/cmake_subdir_test + mkdir __build__ && cd __build__ + cmake .. + cmake --build . --config Debug + ctest --output-on-failure --no-tests=error -C Debug + + - name: Use library with add_subdirectory (Release) + shell: cmd + run: | + cd ../boost-root/libs/%LIBRARY%/test/cmake_subdir_test/__build__ + cmake --build . --config Release + ctest --output-on-failure --no-tests=error -C Release + + windows-cmake-install: + strategy: + fail-fast: false + matrix: + include: + - os: windows-latest + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v4 + + - name: Setup Boost + shell: cmd + run: | + echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY% + for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi + echo LIBRARY: %LIBRARY% + echo LIBRARY=%LIBRARY%>>%GITHUB_ENV% + echo GITHUB_BASE_REF: %GITHUB_BASE_REF% + echo GITHUB_REF: %GITHUB_REF% + if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF% + set BOOST_BRANCH=develop + for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master + echo BOOST_BRANCH: %BOOST_BRANCH% + cd .. + git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\ + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY% + + - name: Configure + shell: cmd + run: | + cd ../boost-root + mkdir __build__ && cd __build__ + cmake -DBOOST_INCLUDE_LIBRARIES=%LIBRARY% -DCMAKE_INSTALL_PREFIX=C:/cmake-prefix .. + + - name: Install (Debug) + shell: cmd + run: | + cd ../boost-root/__build__ + cmake --build . --target install --config Debug + + - name: Install (Release) + shell: cmd + run: | + cd ../boost-root/__build__ + cmake --build . --target install --config Release + + - name: Use the installed library (Debug) + shell: cmd + run: | + cd ../boost-root/libs/%LIBRARY%/test/cmake_install_test && mkdir __build__ && cd __build__ + cmake -DCMAKE_INSTALL_PREFIX=C:/cmake-prefix .. + cmake --build . --config Debug + ctest --output-on-failure --no-tests=error -C Debug + + - name: Use the installed library (Release) + shell: cmd + run: | + cd ../boost-root/libs/%LIBRARY%/test/cmake_install_test/__build__ + cmake --build . --config Release + ctest --output-on-failure --no-tests=error -C Release + + windows-cmake-test: + strategy: + fail-fast: false + matrix: + include: + - os: windows-latest + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v4 + + - name: Setup Boost + shell: cmd + run: | + echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY% + for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi + echo LIBRARY: %LIBRARY% + echo LIBRARY=%LIBRARY%>>%GITHUB_ENV% + echo GITHUB_BASE_REF: %GITHUB_BASE_REF% + echo GITHUB_REF: %GITHUB_REF% + if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF% + set BOOST_BRANCH=develop + for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master + echo BOOST_BRANCH: %BOOST_BRANCH% + cd .. + git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\ + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY% + + - name: Configure + shell: cmd + run: | + cd ../boost-root + mkdir __build__ && cd __build__ + cmake -DBOOST_INCLUDE_LIBRARIES=%LIBRARY% -DBUILD_TESTING=ON .. + + - name: Build tests (Debug) + shell: cmd + run: | + cd ../boost-root/__build__ + cmake --build . --target tests --config Debug + + - name: Run tests (Debug) + shell: cmd + run: | + cd ../boost-root/__build__ + ctest --output-on-failure --no-tests=error -C Debug + + - name: Build tests (Release) + shell: cmd + run: | + cd ../boost-root/__build__ + cmake --build . --target tests --config Release + + - name: Run tests (Release) + shell: cmd + run: | + cd ../boost-root/__build__ + ctest --output-on-failure --no-tests=error -C Release diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..b5a07b26 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,362 @@ +# Copyright 2016-2019 Peter Dimov +# 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) + +language: cpp + +dist: xenial + +branches: + only: + - master + - develop + - /feature\/.*/ + +env: + matrix: + - BOGUS_JOB=true + +matrix: + + exclude: + - env: BOGUS_JOB=true + + include: + - os: linux + compiler: g++-4.4 + env: TOOLSET=gcc CXXSTD=98,0x + addons: + apt: + packages: + - g++-4.4 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: g++-4.6 + env: TOOLSET=gcc CXXSTD=03,0x + addons: + apt: + packages: + - g++-4.6 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: g++-4.7 + env: TOOLSET=gcc CXXSTD=03,11 + addons: + apt: + packages: + - g++-4.7 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: g++-4.8 + env: TOOLSET=gcc CXXSTD=03,11 + addons: + apt: + packages: + - g++-4.8 + sources: + - ubuntu-toolchain-r-test + - os: linux + compiler: g++-4.9 + env: TOOLSET=gcc CXXSTD=03,11 + addons: + apt: + packages: + - g++-4.9 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: g++-5 + env: TOOLSET=gcc CXXSTD=03,11,14,1z + addons: + apt: + packages: + - g++-5 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: g++-6 + env: TOOLSET=gcc CXXSTD=03,11,14,1z + addons: + apt: + packages: + - g++-6 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: g++-7 + env: TOOLSET=gcc CXXSTD=03,11,14,17 + addons: + apt: + packages: + - g++-7 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: g++-8 + env: TOOLSET=gcc CXXSTD=03,11,14,17,2a + addons: + apt: + packages: + - g++-8 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: g++-9 + env: TOOLSET=gcc CXXSTD=03,11,14,17,2a + addons: + apt: + packages: + - g++-9 + sources: + - ubuntu-toolchain-r-test + + - os: linux + dist: bionic + compiler: g++-10 + env: UBSAN=1 TOOLSET=gcc CXXSTD=03,11,14,17,2a UBSAN_OPTIONS=print_stacktrace=1 LINKFLAGS=-fuse-ld=gold + addons: + apt: + packages: + - g++-10 + sources: + - ubuntu-toolchain-r-test + + - os: linux + dist: trusty + compiler: /usr/bin/clang++ + env: TOOLSET=clang CXXSTD=03,11 + addons: + apt: + packages: + - clang-3.3 + + - os: linux + dist: trusty + compiler: /usr/bin/clang++ + env: TOOLSET=clang CXXSTD=03,11 + addons: + apt: + packages: + - clang-3.4 + + - os: linux + compiler: clang++-3.5 + env: TOOLSET=clang CXXSTD=03,11,14,1z + addons: + apt: + packages: + - clang-3.5 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: clang++-3.6 + env: TOOLSET=clang CXXSTD=03,11,14,1z + addons: + apt: + packages: + - clang-3.6 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: clang++-3.7 + env: TOOLSET=clang CXXSTD=03,11,14,1z + addons: + apt: + packages: + - clang-3.7 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: clang++-3.8 + env: TOOLSET=clang CXXSTD=03,11,14,1z + addons: + apt: + packages: + - clang-3.8 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: clang++-3.9 + env: TOOLSET=clang CXXSTD=03,11,14,1z + addons: + apt: + packages: + - clang-3.9 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: clang++-4.0 + env: TOOLSET=clang CXXSTD=03,11,14,1z + addons: + apt: + packages: + - clang-4.0 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: clang++-5.0 + env: TOOLSET=clang CXXSTD=03,11,14,1z + addons: + apt: + packages: + - clang-5.0 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: clang++-6.0 + env: TOOLSET=clang CXXSTD=03,11,14,17,2a + addons: + apt: + packages: + - clang-6.0 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: clang++-7 + env: TOOLSET=clang CXXSTD=03,11,14,17,2a + addons: + apt: + packages: + - clang-7 + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-7 + + - os: linux + compiler: clang++-8 + env: TOOLSET=clang CXXSTD=03,11,14,17,2a + addons: + apt: + packages: + - clang-8 + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 + + - os: linux + dist: bionic + compiler: clang++-9 + env: TOOLSET=clang CXXSTD=03,11,14,17,2a + addons: + apt: + packages: + - clang-9 + sources: + - ubuntu-toolchain-r-test + - sourceline: 'deb https://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main' + key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key' + + - os: linux + dist: bionic + compiler: clang++-10 + env: TOOLSET=clang CXXSTD=03,11,14,17,2a + addons: + apt: + packages: + - clang-10 + sources: + - ubuntu-toolchain-r-test + - sourceline: 'deb https://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main' + key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key' + + - os: linux + dist: bionic + compiler: clang++-11 + env: TOOLSET=clang CXXSTD=03,11,14,17,2a + addons: + apt: + packages: + - clang-11 + sources: + - ubuntu-toolchain-r-test + - sourceline: 'deb https://apt.llvm.org/bionic/ llvm-toolchain-bionic-11 main' + key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key' + + - os: linux + dist: bionic + compiler: clang++-12 + env: UBSAN=1 TOOLSET=clang CXXSTD=03,11,14,17,2a UBSAN_OPTIONS=print_stacktrace=1 + addons: + apt: + packages: + - clang-12 + sources: + - ubuntu-toolchain-r-test + - sourceline: 'deb https://apt.llvm.org/bionic/ llvm-toolchain-bionic-12 main' + key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key' + + - os: linux + dist: trusty + compiler: clang++-libc++ + env: UBSAN=1 TOOLSET=clang CXXSTD=03,11,14,1z UBSAN_OPTIONS=print_stacktrace=1 + addons: + apt: + packages: + - libc++-dev + + - os: linux + dist: bionic + compiler: clang++-libc++ + env: UBSAN=1 TOOLSET=clang CXXSTD=03,11,14,17,2a UBSAN_OPTIONS=print_stacktrace=1 + addons: + apt: + packages: + - libc++-dev + + - os: osx + compiler: clang++ + env: UBSAN=1 TOOLSET=clang CXXSTD=03,11,14,1z UBSAN_OPTIONS=print_stacktrace=1 + + - os: linux + env: CMAKE_TEST=1 + script: + - mkdir __build__ && cd __build__ + - cmake -DBOOST_ENABLE_CMAKE=1 -DBUILD_TESTING=ON -DBoost_VERBOSE=1 -DBOOST_INCLUDE_LIBRARIES=function .. + - ctest --output-on-failure -R boost_function + + - os: linux + env: CMAKE_SUBDIR_TEST=1 + script: + - cd libs/function/test/cmake_subdir_test && mkdir __build__ && cd __build__ + - cmake .. + - cmake --build . + - cmake --build . --target check + +install: + - BOOST_BRANCH=develop && [ "$TRAVIS_BRANCH" == "master" ] && BOOST_BRANCH=master || true + - cd .. + - git clone -b $BOOST_BRANCH https://github.com/boostorg/boost.git boost-root + - cd boost-root + - git submodule update --init tools/boostdep + - cp -r $TRAVIS_BUILD_DIR/* libs/function + - python tools/boostdep/depinst/depinst.py function + - ./bootstrap.sh + - ./b2 headers + +script: + - |- + echo "using $TOOLSET : : $TRAVIS_COMPILER ;" > ~/user-config.jam + - ./b2 -j3 libs/function/test toolset=$TOOLSET cxxstd=$CXXSTD variant=debug,release ${UBSAN:+cxxflags=-fsanitize=undefined cxxflags=-fno-sanitize-recover=undefined linkflags=-fsanitize=undefined debug-symbols=on} ${LINKFLAGS:+linkflags=$LINKFLAGS} + +notifications: + email: + on_success: always diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..56bc47be --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,30 @@ +# Generated by `boostdep --cmake function` +# Copyright 2020, 2021 Peter Dimov +# Distributed under the Boost Software License, Version 1.0. +# https://www.boost.org/LICENSE_1_0.txt + +cmake_minimum_required(VERSION 3.8...3.20) + +project(boost_function VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX) + +add_library(boost_function INTERFACE) +add_library(Boost::function ALIAS boost_function) + +target_include_directories(boost_function INTERFACE include) + +target_link_libraries(boost_function + INTERFACE + Boost::assert + Boost::bind + Boost::config + Boost::core + Boost::throw_exception +) + +target_compile_features(boost_function INTERFACE cxx_std_11) + +if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt") + + add_subdirectory(test) + +endif() diff --git a/README.md b/README.md new file mode 100644 index 00000000..8b3449cb --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +# Boost.Function, a polymorphic function wrapper + +[Boost.Function](http://boost.org/libs/function), part of the +[Boost C++ Libraries](http://boost.org), is the original implementation of the +polymorphic function wrapper `boost::function`, which was eventually accepted +into the C++11 standard as [`std::function`](https://en.cppreference.com/w/cpp/utility/functional/function). + +## Currently supported compilers + +* g++ 4.7 or later +* clang++ 3.9 or later +* Visual Studio 2013-2022 + +Tested on [Github Actions](https://github.com/boostorg/function/actions) and [Appveyor](https://ci.appveyor.com/project/pdimov/function/). + +## License + +Distributed under the [Boost Software License, Version 1.0](http://boost.org/LICENSE_1_0.txt). diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 00000000..55404a90 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,67 @@ +# Copyright 2016-2019 Peter Dimov +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) + +version: 1.0.{build}-{branch} + +shallow_clone: true + +branches: + only: + - master + - develop + - /feature\/.*/ + +environment: + matrix: + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + TOOLSET: msvc-12.0,msvc-14.0 + ADDRMD: 32,64 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + TOOLSET: msvc-14.1 + CXXSTD: 14,17 + ADDRMD: 32,64 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + TOOLSET: clang-win + CXXSTD: 14,17,latest + ADDRMD: 64 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + TOOLSET: clang-win + CXXSTD: 14,17,latest + ADDRMD: 64 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + ADDPATH: C:\cygwin\bin; + TOOLSET: gcc + CXXSTD: 11,14,1z + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + ADDPATH: C:\cygwin64\bin; + TOOLSET: gcc + CXXSTD: 11,14,1z + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + ADDPATH: C:\mingw\bin; + TOOLSET: gcc + CXXSTD: 11,14,1z + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + ADDPATH: C:\mingw-w64\x86_64-6.3.0-posix-seh-rt_v5-rev1\mingw64\bin; + TOOLSET: gcc + CXXSTD: 11,14,1z + +install: + - set BOOST_BRANCH=develop + - if "%APPVEYOR_REPO_BRANCH%" == "master" set BOOST_BRANCH=master + - cd .. + - git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root + - cd boost-root + - git submodule update --init tools/boostdep + - xcopy /s /e /q %APPVEYOR_BUILD_FOLDER% libs\function\ + - python tools/boostdep/depinst/depinst.py function + - cmd /c bootstrap + - b2 -d0 headers + +build: off + +test_script: + - PATH=%ADDPATH%%PATH% + - if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD% + - if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD% + - b2 -j3 libs/function/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release embed-manifest-via=linker diff --git a/build.jam b/build.jam new file mode 100644 index 00000000..fa276be4 --- /dev/null +++ b/build.jam @@ -0,0 +1,24 @@ +# Copyright 2023-2024 René Ferdinand Rivera Morell +# Copyright 2024 Peter Dimov +# Distributed under the Boost Software License, Version 1.0. +# https://www.boost.org/LICENSE_1_0.txt + +require-b2 5.2 ; + +constant boost_dependencies : + /boost/assert//boost_assert + /boost/bind//boost_bind + /boost/config//boost_config + /boost/core//boost_core + /boost/throw_exception//boost_throw_exception + ; + +project /boost/function ; + +explicit + [ alias boost_function : : : : include $(boost_dependencies) ] + [ alias all : boost_function example test ] + ; + +call-if : boost-library function + ; diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index a0f5e0de..f3b8d67d 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -14,3 +14,12 @@ boostbook function-doc pdf:boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html ; +############################################################################### +alias boostdoc + : function.xml + : + : + : ; +explicit boostdoc ; +alias boostrelease ; +explicit boostrelease ; diff --git a/doc/reference.xml b/doc/reference.xml index 843a25fa..64dc6635 100644 --- a/doc/reference.xml +++ b/doc/reference.xml @@ -128,7 +128,7 @@ const std::type_info& - typeid of the target function object, or typeid(void) if this->empty(). + typeid of the target function object, or typeid(void) if this->empty(). Works even with RTTI off. Will not throw. diff --git a/example/Jamfile b/example/Jamfile new file mode 100644 index 00000000..15d8f3c4 --- /dev/null +++ b/example/Jamfile @@ -0,0 +1,18 @@ +# Boost.Function Library example Jamfile +# +# Copyright (c) 2008 James E. King III +# +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt + +require-b2 5.0.1 ; +import-search /boost/config/checks ; +import config : requires ; +import testing ; + +project : requirements /boost/function//boost_function ; + +run bind1st.cpp : : : [ requires cxx98_binders ] ; +run int_div.cpp ; +run sum_avg.cpp ; diff --git a/include/boost/function.hpp b/include/boost/function.hpp index b72842bb..6fd7388b 100644 --- a/include/boost/function.hpp +++ b/include/boost/function.hpp @@ -1,3 +1,6 @@ +#ifndef BOOST_FUNCTION_HPP_INCLUDED +#define BOOST_FUNCTION_HPP_INCLUDED + // Boost.Function library // Copyright Douglas Gregor 2001-2003. Use, modification and @@ -10,57 +13,6 @@ // William Kempf, Jesse Jones and Karl Nelson were all very helpful in the // design of this library. -#include // unary_function, binary_function - -#include -#include - -#ifndef BOOST_FUNCTION_MAX_ARGS -# define BOOST_FUNCTION_MAX_ARGS 10 -#endif // BOOST_FUNCTION_MAX_ARGS - -// Include the prologue here so that the use of file-level iteration -// in anything that may be included by function_template.hpp doesn't break -#include +#include -// Older Visual Age C++ version do not handle the file iteration well -#if BOOST_WORKAROUND(__IBMCPP__, >= 500) && BOOST_WORKAROUND(__IBMCPP__, < 800) -# if BOOST_FUNCTION_MAX_ARGS >= 0 -# include -# endif -# if BOOST_FUNCTION_MAX_ARGS >= 1 -# include -# endif -# if BOOST_FUNCTION_MAX_ARGS >= 2 -# include -# endif -# if BOOST_FUNCTION_MAX_ARGS >= 3 -# include -# endif -# if BOOST_FUNCTION_MAX_ARGS >= 4 -# include -# endif -# if BOOST_FUNCTION_MAX_ARGS >= 5 -# include -# endif -# if BOOST_FUNCTION_MAX_ARGS >= 6 -# include -# endif -# if BOOST_FUNCTION_MAX_ARGS >= 7 -# include -# endif -# if BOOST_FUNCTION_MAX_ARGS >= 8 -# include -# endif -# if BOOST_FUNCTION_MAX_ARGS >= 9 -# include -# endif -# if BOOST_FUNCTION_MAX_ARGS >= 10 -# include -# endif -#else -// What is the '3' for? -# define BOOST_PP_ITERATION_PARAMS_1 (3,(0,BOOST_FUNCTION_MAX_ARGS,)) -# include BOOST_PP_ITERATE() -# undef BOOST_PP_ITERATION_PARAMS_1 -#endif +#endif // #ifndef BOOST_FUNCTION_HPP_INCLUDED diff --git a/include/boost/function/detail/function_iterate.hpp b/include/boost/function/detail/function_iterate.hpp deleted file mode 100644 index 5370b36a..00000000 --- a/include/boost/function/detail/function_iterate.hpp +++ /dev/null @@ -1,16 +0,0 @@ -// Boost.Function library - -// Copyright Douglas Gregor 2003. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// For more information, see http://www.boost.org -#if !defined(BOOST_PP_IS_ITERATING) -# error Boost.Function - do not include this file! -#endif - -#define BOOST_FUNCTION_NUM_ARGS BOOST_PP_ITERATION() -#include -#undef BOOST_FUNCTION_NUM_ARGS - diff --git a/include/boost/function/detail/gen_maybe_include.pl b/include/boost/function/detail/gen_maybe_include.pl deleted file mode 100644 index d0629205..00000000 --- a/include/boost/function/detail/gen_maybe_include.pl +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/perl -w -# -# Boost.Function library -# -# Copyright (C) 2001-2003 Douglas Gregor (gregod@cs.rpi.edu) -# -# Permission to copy, use, sell and distribute this software is granted -# provided this copyright notice appears in all copies. -# Permission to modify the code and to distribute modified code is granted -# provided this copyright notice appears in all copies, and a notice -# that the code was modified is included with the copyright notice. -# -# This software is provided "as is" without express or implied warranty, -# and with no claim as to its suitability for any purpose. -# -# For more information, see http://www.boost.org -use English; - -$max_args = $ARGV[0]; - -open (OUT, ">maybe_include.hpp") or die("Cannot write to maybe_include.hpp"); -for($on_arg = 0; $on_arg <= $max_args; ++$on_arg) { - if ($on_arg == 0) { - print OUT "#if"; - } - else { - print OUT "#elif"; - } - print OUT " BOOST_FUNCTION_NUM_ARGS == $on_arg\n"; - print OUT "# ifndef BOOST_FUNCTION_$on_arg\n"; - print OUT "# define BOOST_FUNCTION_$on_arg\n"; - print OUT "# include \n"; - print OUT "# endif\n"; -} -print OUT "#else\n"; -print OUT "# error Cannot handle Boost.Function objects that accept more than $max_args arguments!\n"; -print OUT "#endif\n"; diff --git a/include/boost/function/detail/maybe_include.hpp b/include/boost/function/detail/maybe_include.hpp deleted file mode 100644 index 92f71bb2..00000000 --- a/include/boost/function/detail/maybe_include.hpp +++ /dev/null @@ -1,267 +0,0 @@ -// Boost.Function library - -// Copyright Douglas Gregor 2003. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// For more information, see http://www.boost.org - -#if BOOST_FUNCTION_NUM_ARGS == 0 -# ifndef BOOST_FUNCTION_0 -# define BOOST_FUNCTION_0 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 1 -# ifndef BOOST_FUNCTION_1 -# define BOOST_FUNCTION_1 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 2 -# ifndef BOOST_FUNCTION_2 -# define BOOST_FUNCTION_2 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 3 -# ifndef BOOST_FUNCTION_3 -# define BOOST_FUNCTION_3 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 4 -# ifndef BOOST_FUNCTION_4 -# define BOOST_FUNCTION_4 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 5 -# ifndef BOOST_FUNCTION_5 -# define BOOST_FUNCTION_5 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 6 -# ifndef BOOST_FUNCTION_6 -# define BOOST_FUNCTION_6 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 7 -# ifndef BOOST_FUNCTION_7 -# define BOOST_FUNCTION_7 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 8 -# ifndef BOOST_FUNCTION_8 -# define BOOST_FUNCTION_8 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 9 -# ifndef BOOST_FUNCTION_9 -# define BOOST_FUNCTION_9 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 10 -# ifndef BOOST_FUNCTION_10 -# define BOOST_FUNCTION_10 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 11 -# ifndef BOOST_FUNCTION_11 -# define BOOST_FUNCTION_11 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 12 -# ifndef BOOST_FUNCTION_12 -# define BOOST_FUNCTION_12 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 13 -# ifndef BOOST_FUNCTION_13 -# define BOOST_FUNCTION_13 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 14 -# ifndef BOOST_FUNCTION_14 -# define BOOST_FUNCTION_14 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 15 -# ifndef BOOST_FUNCTION_15 -# define BOOST_FUNCTION_15 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 16 -# ifndef BOOST_FUNCTION_16 -# define BOOST_FUNCTION_16 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 17 -# ifndef BOOST_FUNCTION_17 -# define BOOST_FUNCTION_17 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 18 -# ifndef BOOST_FUNCTION_18 -# define BOOST_FUNCTION_18 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 19 -# ifndef BOOST_FUNCTION_19 -# define BOOST_FUNCTION_19 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 20 -# ifndef BOOST_FUNCTION_20 -# define BOOST_FUNCTION_20 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 21 -# ifndef BOOST_FUNCTION_21 -# define BOOST_FUNCTION_21 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 22 -# ifndef BOOST_FUNCTION_22 -# define BOOST_FUNCTION_22 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 23 -# ifndef BOOST_FUNCTION_23 -# define BOOST_FUNCTION_23 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 24 -# ifndef BOOST_FUNCTION_24 -# define BOOST_FUNCTION_24 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 25 -# ifndef BOOST_FUNCTION_25 -# define BOOST_FUNCTION_25 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 26 -# ifndef BOOST_FUNCTION_26 -# define BOOST_FUNCTION_26 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 27 -# ifndef BOOST_FUNCTION_27 -# define BOOST_FUNCTION_27 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 28 -# ifndef BOOST_FUNCTION_28 -# define BOOST_FUNCTION_28 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 29 -# ifndef BOOST_FUNCTION_29 -# define BOOST_FUNCTION_29 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 30 -# ifndef BOOST_FUNCTION_30 -# define BOOST_FUNCTION_30 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 31 -# ifndef BOOST_FUNCTION_31 -# define BOOST_FUNCTION_31 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 32 -# ifndef BOOST_FUNCTION_32 -# define BOOST_FUNCTION_32 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 33 -# ifndef BOOST_FUNCTION_33 -# define BOOST_FUNCTION_33 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 34 -# ifndef BOOST_FUNCTION_34 -# define BOOST_FUNCTION_34 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 35 -# ifndef BOOST_FUNCTION_35 -# define BOOST_FUNCTION_35 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 36 -# ifndef BOOST_FUNCTION_36 -# define BOOST_FUNCTION_36 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 37 -# ifndef BOOST_FUNCTION_37 -# define BOOST_FUNCTION_37 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 38 -# ifndef BOOST_FUNCTION_38 -# define BOOST_FUNCTION_38 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 39 -# ifndef BOOST_FUNCTION_39 -# define BOOST_FUNCTION_39 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 40 -# ifndef BOOST_FUNCTION_40 -# define BOOST_FUNCTION_40 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 41 -# ifndef BOOST_FUNCTION_41 -# define BOOST_FUNCTION_41 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 42 -# ifndef BOOST_FUNCTION_42 -# define BOOST_FUNCTION_42 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 43 -# ifndef BOOST_FUNCTION_43 -# define BOOST_FUNCTION_43 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 44 -# ifndef BOOST_FUNCTION_44 -# define BOOST_FUNCTION_44 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 45 -# ifndef BOOST_FUNCTION_45 -# define BOOST_FUNCTION_45 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 46 -# ifndef BOOST_FUNCTION_46 -# define BOOST_FUNCTION_46 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 47 -# ifndef BOOST_FUNCTION_47 -# define BOOST_FUNCTION_47 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 48 -# ifndef BOOST_FUNCTION_48 -# define BOOST_FUNCTION_48 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 49 -# ifndef BOOST_FUNCTION_49 -# define BOOST_FUNCTION_49 -# include -# endif -#elif BOOST_FUNCTION_NUM_ARGS == 50 -# ifndef BOOST_FUNCTION_50 -# define BOOST_FUNCTION_50 -# include -# endif -#else -# error Cannot handle Boost.Function objects that accept more than 50 arguments! -#endif diff --git a/include/boost/function/detail/prologue.hpp b/include/boost/function/detail/prologue.hpp deleted file mode 100644 index 53d0f05c..00000000 --- a/include/boost/function/detail/prologue.hpp +++ /dev/null @@ -1,26 +0,0 @@ -// Boost.Function library - -// Copyright Douglas Gregor 2002-2003. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// For more information, see http://www.boost.org - -#ifndef BOOST_FUNCTION_PROLOGUE_HPP -#define BOOST_FUNCTION_PROLOGUE_HPP -# include -# include -# include // unary_function, binary_function -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -#endif // BOOST_FUNCTION_PROLOGUE_HPP diff --git a/include/boost/function/function0.hpp b/include/boost/function/function0.hpp index 65a02e5f..b0275b26 100644 --- a/include/boost/function/function0.hpp +++ b/include/boost/function/function0.hpp @@ -7,6 +7,4 @@ // For more information, see http://www.boost.org -#define BOOST_FUNCTION_NUM_ARGS 0 -#include -#undef BOOST_FUNCTION_NUM_ARGS +#include diff --git a/include/boost/function/function1.hpp b/include/boost/function/function1.hpp index 90897151..b0275b26 100644 --- a/include/boost/function/function1.hpp +++ b/include/boost/function/function1.hpp @@ -7,6 +7,4 @@ // For more information, see http://www.boost.org -#define BOOST_FUNCTION_NUM_ARGS 1 -#include -#undef BOOST_FUNCTION_NUM_ARGS +#include diff --git a/include/boost/function/function10.hpp b/include/boost/function/function10.hpp index 65627248..b0275b26 100644 --- a/include/boost/function/function10.hpp +++ b/include/boost/function/function10.hpp @@ -7,6 +7,4 @@ // For more information, see http://www.boost.org -#define BOOST_FUNCTION_NUM_ARGS 10 -#include -#undef BOOST_FUNCTION_NUM_ARGS +#include diff --git a/include/boost/function/function2.hpp b/include/boost/function/function2.hpp index dc8bf975..b0275b26 100644 --- a/include/boost/function/function2.hpp +++ b/include/boost/function/function2.hpp @@ -7,6 +7,4 @@ // For more information, see http://www.boost.org -#define BOOST_FUNCTION_NUM_ARGS 2 -#include -#undef BOOST_FUNCTION_NUM_ARGS +#include diff --git a/include/boost/function/function3.hpp b/include/boost/function/function3.hpp index 19d1a49d..b0275b26 100644 --- a/include/boost/function/function3.hpp +++ b/include/boost/function/function3.hpp @@ -7,6 +7,4 @@ // For more information, see http://www.boost.org -#define BOOST_FUNCTION_NUM_ARGS 3 -#include -#undef BOOST_FUNCTION_NUM_ARGS +#include diff --git a/include/boost/function/function4.hpp b/include/boost/function/function4.hpp index f3349e2d..b0275b26 100644 --- a/include/boost/function/function4.hpp +++ b/include/boost/function/function4.hpp @@ -7,6 +7,4 @@ // For more information, see http://www.boost.org -#define BOOST_FUNCTION_NUM_ARGS 4 -#include -#undef BOOST_FUNCTION_NUM_ARGS +#include diff --git a/include/boost/function/function5.hpp b/include/boost/function/function5.hpp index a1305eb5..b0275b26 100644 --- a/include/boost/function/function5.hpp +++ b/include/boost/function/function5.hpp @@ -7,6 +7,4 @@ // For more information, see http://www.boost.org -#define BOOST_FUNCTION_NUM_ARGS 5 -#include -#undef BOOST_FUNCTION_NUM_ARGS +#include diff --git a/include/boost/function/function6.hpp b/include/boost/function/function6.hpp index 1f609149..b0275b26 100644 --- a/include/boost/function/function6.hpp +++ b/include/boost/function/function6.hpp @@ -7,6 +7,4 @@ // For more information, see http://www.boost.org -#define BOOST_FUNCTION_NUM_ARGS 6 -#include -#undef BOOST_FUNCTION_NUM_ARGS +#include diff --git a/include/boost/function/function7.hpp b/include/boost/function/function7.hpp index 68542ed4..b0275b26 100644 --- a/include/boost/function/function7.hpp +++ b/include/boost/function/function7.hpp @@ -7,6 +7,4 @@ // For more information, see http://www.boost.org -#define BOOST_FUNCTION_NUM_ARGS 7 -#include -#undef BOOST_FUNCTION_NUM_ARGS +#include diff --git a/include/boost/function/function8.hpp b/include/boost/function/function8.hpp index cf2c3766..b0275b26 100644 --- a/include/boost/function/function8.hpp +++ b/include/boost/function/function8.hpp @@ -7,6 +7,4 @@ // For more information, see http://www.boost.org -#define BOOST_FUNCTION_NUM_ARGS 8 -#include -#undef BOOST_FUNCTION_NUM_ARGS +#include diff --git a/include/boost/function/function9.hpp b/include/boost/function/function9.hpp index 590e0883..b0275b26 100644 --- a/include/boost/function/function9.hpp +++ b/include/boost/function/function9.hpp @@ -7,6 +7,4 @@ // For more information, see http://www.boost.org -#define BOOST_FUNCTION_NUM_ARGS 9 -#include -#undef BOOST_FUNCTION_NUM_ARGS +#include diff --git a/include/boost/function/function_base.hpp b/include/boost/function/function_base.hpp index 9e01ef94..ca15b7b7 100644 --- a/include/boost/function/function_base.hpp +++ b/include/boost/function/function_base.hpp @@ -11,80 +11,30 @@ #ifndef BOOST_FUNCTION_BASE_HEADER #define BOOST_FUNCTION_BASE_HEADER +#include +#include +#include +#include +#include +#include +#include #include #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef BOOST_NO_SFINAE -# include "boost/utility/enable_if.hpp" -#else -# include "boost/mpl/bool.hpp" -#endif -#include -#include +#include #if defined(BOOST_MSVC) # pragma warning( push ) # pragma warning( disable : 4793 ) // complaint about native code generation # pragma warning( disable : 4127 ) // "conditional expression is constant" -#endif - -// Define BOOST_FUNCTION_STD_NS to the namespace that contains type_info. -#ifdef BOOST_NO_STD_TYPEINFO -// Embedded VC++ does not have type_info in namespace std -# define BOOST_FUNCTION_STD_NS -#else -# define BOOST_FUNCTION_STD_NS std #endif -// Borrowed from Boost.Python library: determines the cases where we -// need to use std::type_info::name to compare instead of operator==. -#if defined( BOOST_NO_TYPEID ) -# define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) ((X)==(Y)) -#elif defined(__GNUC__) \ - || defined(_AIX) \ - || ( defined(__sgi) && defined(__host_mips)) -# include -# define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) \ - (std::strcmp((X).name(),(Y).name()) == 0) -# else -# define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) ((X)==(Y)) -#endif +// retained because used in a test +#define BOOST_FUNCTION_TARGET_FIX(x) -#if defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 && !defined(BOOST_STRICT_CONFIG) -# define BOOST_FUNCTION_TARGET_FIX(x) x -#else -# define BOOST_FUNCTION_TARGET_FIX(x) -#endif // __ICL etc - -#if !BOOST_WORKAROUND(__BORLANDC__, < 0x5A0) -# define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \ - typename ::boost::enable_if_c<(::boost::type_traits::ice_not< \ - (::boost::is_integral::value)>::value), \ - Type>::type -#else -// BCC doesn't recognize this depends on a template argument and complains -// about the use of 'typename' -# define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \ - ::boost::enable_if_c<(::boost::type_traits::ice_not< \ - (::boost::is_integral::value)>::value), \ - Type>::type -#endif +#define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \ + typename std::enable_if< !std::is_integral::value, Type>::type namespace boost { namespace detail { @@ -97,15 +47,16 @@ namespace boost { * object pointers, and a structure that resembles a bound * member function pointer. */ - union function_buffer + union function_buffer_members { // For pointers to function objects - mutable void* obj_ptr; + typedef void* obj_ptr_t; + mutable obj_ptr_t obj_ptr; // For pointers to std::type_info objects struct type_t { // (get_functor_type_tag, check_functor_type_tag). - const detail::sp_typeinfo* type; + const boost::core::typeinfo* type; // Whether the type is const-qualified. bool const_qualified; @@ -114,7 +65,13 @@ namespace boost { } type; // For function pointers of all kinds - mutable void (*func_ptr)(); + typedef void (*func_ptr_t)(); + mutable func_ptr_t func_ptr; + +#if defined(BOOST_MSVC) && BOOST_MSVC >= 1929 +# pragma warning(push) +# pragma warning(disable: 5243) +#endif // For bound member pointers struct bound_memfunc_ptr_t { @@ -122,6 +79,10 @@ namespace boost { void* obj_ptr; } bound_memfunc_ptr; +#if defined(BOOST_MSVC) && BOOST_MSVC >= 1929 +# pragma warning(pop) +#endif + // For references to function objects. We explicitly keep // track of the cv-qualifiers on the object referenced. struct obj_ref_t { @@ -129,33 +90,15 @@ namespace boost { bool is_const_qualified; bool is_volatile_qualified; } obj_ref; - - // To relax aliasing constraints - mutable char data; }; - /** - * The unusable class is a placeholder for unused function arguments - * It is also completely unusable except that it constructable from - * anything. This helps compilers without partial specialization to - * handle Boost.Function objects returning void. - */ - struct unusable + union BOOST_SYMBOL_VISIBLE function_buffer { - unusable() {} - template unusable(const T&) {} - }; - - /* Determine the return type. This supports compilers that do not support - * void returns or partial specialization by silently changing the return - * type to "unusable". - */ - template struct function_return_type { typedef T type; }; + // Type-specific union members + mutable function_buffer_members members; - template<> - struct function_return_type - { - typedef unusable type; + // To relax aliasing constraints + mutable char data[sizeof(function_buffer_members)]; }; // The operation type to perform on the given functor/function pointer @@ -176,15 +119,15 @@ namespace boost { template class get_function_tag { - typedef typename mpl::if_c<(is_pointer::value), + typedef typename std::conditional::value, function_ptr_tag, function_obj_tag>::type ptr_or_obj_tag; - typedef typename mpl::if_c<(is_member_pointer::value), + typedef typename std::conditional::value, member_ptr_tag, ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag; - typedef typename mpl::if_c<(is_reference_wrapper::value), + typedef typename std::conditional::value, function_obj_ref_tag, ptr_or_obj_or_mem_tag>::type or_ref_tag; @@ -198,45 +141,42 @@ namespace boost { struct reference_manager { static inline void - manage(const function_buffer& in_buffer, function_buffer& out_buffer, + manage(const function_buffer& in_buffer, function_buffer& out_buffer, functor_manager_operation_type op) { switch (op) { - case clone_functor_tag: - out_buffer.obj_ref = in_buffer.obj_ref; + case clone_functor_tag: + out_buffer.members.obj_ref = in_buffer.members.obj_ref; return; case move_functor_tag: - out_buffer.obj_ref = in_buffer.obj_ref; - in_buffer.obj_ref.obj_ptr = 0; + out_buffer.members.obj_ref = in_buffer.members.obj_ref; + in_buffer.members.obj_ref.obj_ptr = 0; return; case destroy_functor_tag: - out_buffer.obj_ref.obj_ptr = 0; + out_buffer.members.obj_ref.obj_ptr = 0; return; case check_functor_type_tag: { - const detail::sp_typeinfo& check_type - = *out_buffer.type.type; - // Check whether we have the same type. We can add // cv-qualifiers, but we can't take them away. - if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(F)) - && (!in_buffer.obj_ref.is_const_qualified - || out_buffer.type.const_qualified) - && (!in_buffer.obj_ref.is_volatile_qualified - || out_buffer.type.volatile_qualified)) - out_buffer.obj_ptr = in_buffer.obj_ref.obj_ptr; + if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(F) + && (!in_buffer.members.obj_ref.is_const_qualified + || out_buffer.members.type.const_qualified) + && (!in_buffer.members.obj_ref.is_volatile_qualified + || out_buffer.members.type.volatile_qualified)) + out_buffer.members.obj_ptr = in_buffer.members.obj_ref.obj_ptr; else - out_buffer.obj_ptr = 0; + out_buffer.members.obj_ptr = 0; } return; case get_functor_type_tag: - out_buffer.type.type = &BOOST_SP_TYPEID(F); - out_buffer.type.const_qualified = in_buffer.obj_ref.is_const_qualified; - out_buffer.type.volatile_qualified = in_buffer.obj_ref.is_volatile_qualified; + out_buffer.members.type.type = &BOOST_CORE_TYPEID(F); + out_buffer.members.type.const_qualified = in_buffer.members.obj_ref.is_const_qualified; + out_buffer.members.type.volatile_qualified = in_buffer.members.obj_ref.is_volatile_qualified; return; } } @@ -250,10 +190,10 @@ namespace boost { struct function_allows_small_object_optimization { BOOST_STATIC_CONSTANT - (bool, + (bool, value = ((sizeof(F) <= sizeof(function_buffer) && - (alignment_of::value - % alignment_of::value == 0)))); + (std::alignment_of::value + % std::alignment_of::value == 0)))); }; template @@ -264,7 +204,7 @@ namespace boost { A(a) { } - + functor_wrapper(const functor_wrapper& f) : F(static_cast(f)), A(static_cast(f)) @@ -283,61 +223,56 @@ namespace boost { // Function pointers static inline void - manage_ptr(const function_buffer& in_buffer, function_buffer& out_buffer, + manage_ptr(const function_buffer& in_buffer, function_buffer& out_buffer, functor_manager_operation_type op) { if (op == clone_functor_tag) - out_buffer.func_ptr = in_buffer.func_ptr; + out_buffer.members.func_ptr = in_buffer.members.func_ptr; else if (op == move_functor_tag) { - out_buffer.func_ptr = in_buffer.func_ptr; - in_buffer.func_ptr = 0; + out_buffer.members.func_ptr = in_buffer.members.func_ptr; + in_buffer.members.func_ptr = 0; } else if (op == destroy_functor_tag) - out_buffer.func_ptr = 0; + out_buffer.members.func_ptr = 0; else if (op == check_functor_type_tag) { - const boost::detail::sp_typeinfo& check_type - = *out_buffer.type.type; - if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(Functor))) - out_buffer.obj_ptr = &in_buffer.func_ptr; + if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(Functor)) + out_buffer.members.obj_ptr = &in_buffer.members.func_ptr; else - out_buffer.obj_ptr = 0; + out_buffer.members.obj_ptr = 0; } else /* op == get_functor_type_tag */ { - out_buffer.type.type = &BOOST_SP_TYPEID(Functor); - out_buffer.type.const_qualified = false; - out_buffer.type.volatile_qualified = false; + out_buffer.members.type.type = &BOOST_CORE_TYPEID(Functor); + out_buffer.members.type.const_qualified = false; + out_buffer.members.type.volatile_qualified = false; } } // Function objects that fit in the small-object buffer. static inline void - manage_small(const function_buffer& in_buffer, function_buffer& out_buffer, + manage_small(const function_buffer& in_buffer, function_buffer& out_buffer, functor_manager_operation_type op) { - if (op == clone_functor_tag || op == move_functor_tag) { - const functor_type* in_functor = - reinterpret_cast(&in_buffer.data); - new (reinterpret_cast(&out_buffer.data)) functor_type(*in_functor); - - if (op == move_functor_tag) { - functor_type* f = reinterpret_cast(&in_buffer.data); - (void)f; // suppress warning about the value of f not being used (MSVC) + if (op == clone_functor_tag) { + const functor_type* in_functor = + reinterpret_cast(in_buffer.data); + new (reinterpret_cast(out_buffer.data)) functor_type(*in_functor); + + } else if (op == move_functor_tag) { + functor_type* f = reinterpret_cast(in_buffer.data); + new (reinterpret_cast(out_buffer.data)) functor_type(std::move(*f)); f->~Functor(); - } } else if (op == destroy_functor_tag) { // Some compilers (Borland, vc6, ...) are unhappy with ~functor_type. - functor_type* f = reinterpret_cast(&out_buffer.data); + functor_type* f = reinterpret_cast(out_buffer.data); (void)f; // suppress warning about the value of f not being used (MSVC) f->~Functor(); } else if (op == check_functor_type_tag) { - const detail::sp_typeinfo& check_type - = *out_buffer.type.type; - if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(Functor))) - out_buffer.obj_ptr = &in_buffer.data; + if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(Functor)) + out_buffer.members.obj_ptr = in_buffer.data; else - out_buffer.obj_ptr = 0; + out_buffer.members.obj_ptr = 0; } else /* op == get_functor_type_tag */ { - out_buffer.type.type = &BOOST_SP_TYPEID(Functor); - out_buffer.type.const_qualified = false; - out_buffer.type.volatile_qualified = false; + out_buffer.members.type.type = &BOOST_CORE_TYPEID(Functor); + out_buffer.members.type.const_qualified = false; + out_buffer.members.type.volatile_qualified = false; } } }; @@ -350,7 +285,7 @@ namespace boost { // Function pointers static inline void - manager(const function_buffer& in_buffer, function_buffer& out_buffer, + manager(const function_buffer& in_buffer, function_buffer& out_buffer, functor_manager_operation_type op, function_ptr_tag) { functor_manager_common::manage_ptr(in_buffer,out_buffer,op); @@ -358,16 +293,16 @@ namespace boost { // Function objects that fit in the small-object buffer. static inline void - manager(const function_buffer& in_buffer, function_buffer& out_buffer, - functor_manager_operation_type op, mpl::true_) + manager(const function_buffer& in_buffer, function_buffer& out_buffer, + functor_manager_operation_type op, std::true_type) { functor_manager_common::manage_small(in_buffer,out_buffer,op); } - + // Function objects that require heap allocation static inline void - manager(const function_buffer& in_buffer, function_buffer& out_buffer, - functor_manager_operation_type op, mpl::false_) + manager(const function_buffer& in_buffer, function_buffer& out_buffer, + functor_manager_operation_type op, std::false_type) { if (op == clone_functor_tag) { // Clone the functor @@ -376,29 +311,27 @@ namespace boost { // jewillco: Changing this to static_cast because GCC 2.95.3 is // obsolete. const functor_type* f = - static_cast(in_buffer.obj_ptr); + static_cast(in_buffer.members.obj_ptr); functor_type* new_f = new functor_type(*f); - out_buffer.obj_ptr = new_f; + out_buffer.members.obj_ptr = new_f; } else if (op == move_functor_tag) { - out_buffer.obj_ptr = in_buffer.obj_ptr; - in_buffer.obj_ptr = 0; + out_buffer.members.obj_ptr = in_buffer.members.obj_ptr; + in_buffer.members.obj_ptr = 0; } else if (op == destroy_functor_tag) { /* Cast from the void pointer to the functor pointer type */ functor_type* f = - static_cast(out_buffer.obj_ptr); + static_cast(out_buffer.members.obj_ptr); delete f; - out_buffer.obj_ptr = 0; + out_buffer.members.obj_ptr = 0; } else if (op == check_functor_type_tag) { - const detail::sp_typeinfo& check_type - = *out_buffer.type.type; - if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(Functor))) - out_buffer.obj_ptr = in_buffer.obj_ptr; + if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(Functor)) + out_buffer.members.obj_ptr = in_buffer.members.obj_ptr; else - out_buffer.obj_ptr = 0; + out_buffer.members.obj_ptr = 0; } else /* op == get_functor_type_tag */ { - out_buffer.type.type = &BOOST_SP_TYPEID(Functor); - out_buffer.type.const_qualified = false; - out_buffer.type.volatile_qualified = false; + out_buffer.members.type.type = &BOOST_CORE_TYPEID(Functor); + out_buffer.members.type.const_qualified = false; + out_buffer.members.type.volatile_qualified = false; } } @@ -406,39 +339,35 @@ namespace boost { // object can use the small-object optimization buffer or // whether we need to allocate it on the heap. static inline void - manager(const function_buffer& in_buffer, function_buffer& out_buffer, + manager(const function_buffer& in_buffer, function_buffer& out_buffer, functor_manager_operation_type op, function_obj_tag) { manager(in_buffer, out_buffer, op, - mpl::bool_<(function_allows_small_object_optimization::value)>()); + std::integral_constant::value)>()); } // For member pointers, we use the small-object optimization buffer. static inline void - manager(const function_buffer& in_buffer, function_buffer& out_buffer, + manager(const function_buffer& in_buffer, function_buffer& out_buffer, functor_manager_operation_type op, member_ptr_tag) { - manager(in_buffer, out_buffer, op, mpl::true_()); + manager(in_buffer, out_buffer, op, std::true_type()); } public: /* Dispatch to an appropriate manager based on whether we have a function pointer or a function object pointer. */ static inline void - manage(const function_buffer& in_buffer, function_buffer& out_buffer, + manage(const function_buffer& in_buffer, function_buffer& out_buffer, functor_manager_operation_type op) { typedef typename get_function_tag::type tag_type; - switch (op) { - case get_functor_type_tag: - out_buffer.type.type = &BOOST_SP_TYPEID(functor_type); - out_buffer.type.const_qualified = false; - out_buffer.type.volatile_qualified = false; - return; - - default: + if (op == get_functor_type_tag) { + out_buffer.members.type.type = &BOOST_CORE_TYPEID(functor_type); + out_buffer.members.type.const_qualified = false; + out_buffer.members.type.volatile_qualified = false; + } else { manager(in_buffer, out_buffer, op, tag_type()); - return; } } }; @@ -451,7 +380,7 @@ namespace boost { // Function pointers static inline void - manager(const function_buffer& in_buffer, function_buffer& out_buffer, + manager(const function_buffer& in_buffer, function_buffer& out_buffer, functor_manager_operation_type op, function_ptr_tag) { functor_manager_common::manage_ptr(in_buffer,out_buffer,op); @@ -459,57 +388,55 @@ namespace boost { // Function objects that fit in the small-object buffer. static inline void - manager(const function_buffer& in_buffer, function_buffer& out_buffer, - functor_manager_operation_type op, mpl::true_) + manager(const function_buffer& in_buffer, function_buffer& out_buffer, + functor_manager_operation_type op, std::true_type) { functor_manager_common::manage_small(in_buffer,out_buffer,op); } - + // Function objects that require heap allocation static inline void - manager(const function_buffer& in_buffer, function_buffer& out_buffer, - functor_manager_operation_type op, mpl::false_) + manager(const function_buffer& in_buffer, function_buffer& out_buffer, + functor_manager_operation_type op, std::false_type) { typedef functor_wrapper functor_wrapper_type; - typedef typename Allocator::template rebind::other - wrapper_allocator_type; - typedef typename wrapper_allocator_type::pointer wrapper_allocator_pointer_type; + + using wrapper_allocator_type = typename std::allocator_traits::template rebind_alloc; + using wrapper_allocator_pointer_type = typename std::allocator_traits::pointer; if (op == clone_functor_tag) { // Clone the functor // GCC 2.95.3 gets the CV qualifiers wrong here, so we // can't do the static_cast that we should do. const functor_wrapper_type* f = - static_cast(in_buffer.obj_ptr); + static_cast(in_buffer.members.obj_ptr); wrapper_allocator_type wrapper_allocator(static_cast(*f)); wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1); - wrapper_allocator.construct(copy, *f); + std::allocator_traits::construct(wrapper_allocator, copy, *f); // Get back to the original pointer type functor_wrapper_type* new_f = static_cast(copy); - out_buffer.obj_ptr = new_f; + out_buffer.members.obj_ptr = new_f; } else if (op == move_functor_tag) { - out_buffer.obj_ptr = in_buffer.obj_ptr; - in_buffer.obj_ptr = 0; + out_buffer.members.obj_ptr = in_buffer.members.obj_ptr; + in_buffer.members.obj_ptr = 0; } else if (op == destroy_functor_tag) { /* Cast from the void pointer to the functor_wrapper_type */ functor_wrapper_type* victim = - static_cast(in_buffer.obj_ptr); + static_cast(in_buffer.members.obj_ptr); wrapper_allocator_type wrapper_allocator(static_cast(*victim)); - wrapper_allocator.destroy(victim); + std::allocator_traits::destroy(wrapper_allocator, victim); wrapper_allocator.deallocate(victim,1); - out_buffer.obj_ptr = 0; + out_buffer.members.obj_ptr = 0; } else if (op == check_functor_type_tag) { - const detail::sp_typeinfo& check_type - = *out_buffer.type.type; - if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(Functor))) - out_buffer.obj_ptr = in_buffer.obj_ptr; + if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(Functor)) + out_buffer.members.obj_ptr = in_buffer.members.obj_ptr; else - out_buffer.obj_ptr = 0; + out_buffer.members.obj_ptr = 0; } else /* op == get_functor_type_tag */ { - out_buffer.type.type = &BOOST_SP_TYPEID(Functor); - out_buffer.type.const_qualified = false; - out_buffer.type.volatile_qualified = false; + out_buffer.members.type.type = &BOOST_CORE_TYPEID(Functor); + out_buffer.members.type.const_qualified = false; + out_buffer.members.type.volatile_qualified = false; } } @@ -517,31 +444,27 @@ namespace boost { // object can use the small-object optimization buffer or // whether we need to allocate it on the heap. static inline void - manager(const function_buffer& in_buffer, function_buffer& out_buffer, + manager(const function_buffer& in_buffer, function_buffer& out_buffer, functor_manager_operation_type op, function_obj_tag) { manager(in_buffer, out_buffer, op, - mpl::bool_<(function_allows_small_object_optimization::value)>()); + std::integral_constant::value)>()); } public: /* Dispatch to an appropriate manager based on whether we have a function pointer or a function object pointer. */ static inline void - manage(const function_buffer& in_buffer, function_buffer& out_buffer, + manage(const function_buffer& in_buffer, function_buffer& out_buffer, functor_manager_operation_type op) { typedef typename get_function_tag::type tag_type; - switch (op) { - case get_functor_type_tag: - out_buffer.type.type = &BOOST_SP_TYPEID(functor_type); - out_buffer.type.const_qualified = false; - out_buffer.type.volatile_qualified = false; - return; - - default: + if (op == get_functor_type_tag) { + out_buffer.members.type.type = &BOOST_CORE_TYPEID(functor_type); + out_buffer.members.type.const_qualified = false; + out_buffer.members.type.volatile_qualified = false; + } else { manager(in_buffer, out_buffer, op, tag_type()); - return; } } }; @@ -549,73 +472,14 @@ namespace boost { // A type that is only used for comparisons against zero struct useless_clear_type {}; -#ifdef BOOST_NO_SFINAE - // These routines perform comparisons between a Boost.Function - // object and an arbitrary function object (when the last - // parameter is mpl::bool_) or against zero (when the - // last parameter is mpl::bool_). They are only necessary - // for compilers that don't support SFINAE. - template - bool - compare_equal(const Function& f, const Functor&, int, mpl::bool_) - { return f.empty(); } - - template - bool - compare_not_equal(const Function& f, const Functor&, int, - mpl::bool_) - { return !f.empty(); } - - template - bool - compare_equal(const Function& f, const Functor& g, long, - mpl::bool_) - { - if (const Functor* fp = f.template target()) - return function_equal(*fp, g); - else return false; - } - - template - bool - compare_equal(const Function& f, const reference_wrapper& g, - int, mpl::bool_) - { - if (const Functor* fp = f.template target()) - return fp == g.get_pointer(); - else return false; - } - - template - bool - compare_not_equal(const Function& f, const Functor& g, long, - mpl::bool_) - { - if (const Functor* fp = f.template target()) - return !function_equal(*fp, g); - else return true; - } - - template - bool - compare_not_equal(const Function& f, - const reference_wrapper& g, int, - mpl::bool_) - { - if (const Functor* fp = f.template target()) - return fp != g.get_pointer(); - else return true; - } -#endif // BOOST_NO_SFINAE - /** * Stores the "manager" portion of the vtable for a * boost::function object. */ struct vtable_base { - void (*manager)(const function_buffer& in_buffer, - function_buffer& out_buffer, + void (*manager)(const function_buffer& in_buffer, + function_buffer& out_buffer, functor_manager_operation_type op); }; } // end namespace function @@ -635,15 +499,15 @@ class function_base /** Determine if the function is empty (i.e., has no target). */ bool empty() const { return !vtable; } - /** Retrieve the type of the stored function object, or BOOST_SP_TYPEID(void) + /** Retrieve the type of the stored function object, or type_id() if this is empty. */ - const detail::sp_typeinfo& target_type() const + const boost::core::typeinfo& target_type() const { - if (!vtable) return BOOST_SP_TYPEID(void); + if (!vtable) return BOOST_CORE_TYPEID(void); detail::function::function_buffer type; get_vtable()->manager(functor, type, detail::function::get_functor_type_tag); - return *type.type.type; + return *type.members.type.type; } template @@ -652,12 +516,12 @@ class function_base if (!vtable) return 0; detail::function::function_buffer type_result; - type_result.type.type = &BOOST_SP_TYPEID(Functor); - type_result.type.const_qualified = is_const::value; - type_result.type.volatile_qualified = is_volatile::value; - get_vtable()->manager(functor, type_result, + type_result.members.type.type = &BOOST_CORE_TYPEID(Functor); + type_result.members.type.const_qualified = std::is_const::value; + type_result.members.type.volatile_qualified = std::is_volatile::value; + get_vtable()->manager(functor, type_result, detail::function::check_functor_type_tag); - return static_cast(type_result.obj_ptr); + return static_cast(type_result.members.obj_ptr); } template @@ -666,18 +530,19 @@ class function_base if (!vtable) return 0; detail::function::function_buffer type_result; - type_result.type.type = &BOOST_SP_TYPEID(Functor); - type_result.type.const_qualified = true; - type_result.type.volatile_qualified = is_volatile::value; - get_vtable()->manager(functor, type_result, + type_result.members.type.type = &BOOST_CORE_TYPEID(Functor); + type_result.members.type.const_qualified = true; + type_result.members.type.volatile_qualified = std::is_volatile::value; + get_vtable()->manager(functor, type_result, detail::function::check_functor_type_tag); // GCC 2.95.3 gets the CV qualifiers wrong here, so we // can't do the static_cast that we should do. - return static_cast(type_result.obj_ptr); + return static_cast(type_result.members.obj_ptr); } template - bool contains(const F& f) const + typename std::enable_if< !std::is_function::value, bool >::type + contains(const F& f) const { if (const F* fp = this->template target()) { @@ -687,28 +552,18 @@ class function_base } } -#if defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3 - // GCC 3.3 and newer cannot copy with the global operator==, due to - // problems with instantiation of function return types before it - // has been verified that the argument types match up. - template - BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool) - operator==(Functor g) const - { - if (const Functor* fp = target()) - return function_equal(*fp, g); - else return false; - } - - template - BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool) - operator!=(Functor g) const + template + typename std::enable_if< std::is_function::value, bool >::type + contains(Fn& f) const { - if (const Functor* fp = target()) - return !function_equal(*fp, g); - else return true; + typedef Fn* F; + if (const F* fp = this->template target()) + { + return function_equal(*fp, &f); + } else { + return false; + } } -#endif public: // should be protected, but GCC 2.95.3 will fail to allow access detail::function::vtable_base* get_vtable() const { @@ -724,17 +579,23 @@ class function_base mutable detail::function::function_buffer functor; }; +#if defined(BOOST_CLANG) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wweak-vtables" +#endif /** * The bad_function_call exception class is thrown when a boost::function * object is invoked */ -class bad_function_call : public std::runtime_error +class BOOST_SYMBOL_VISIBLE bad_function_call : public std::runtime_error { public: bad_function_call() : std::runtime_error("call to empty boost::function") {} }; +#if defined(BOOST_CLANG) +# pragma clang diagnostic pop +#endif -#ifndef BOOST_NO_SFINAE inline bool operator==(const function_base& f, detail::function::useless_clear_type*) { @@ -758,43 +619,10 @@ inline bool operator!=(detail::function::useless_clear_type*, { return !f.empty(); } -#endif - -#ifdef BOOST_NO_SFINAE -// Comparisons between boost::function objects and arbitrary function objects -template - inline bool operator==(const function_base& f, Functor g) - { - typedef mpl::bool_<(is_integral::value)> integral; - return detail::function::compare_equal(f, g, 0, integral()); - } - -template - inline bool operator==(Functor g, const function_base& f) - { - typedef mpl::bool_<(is_integral::value)> integral; - return detail::function::compare_equal(f, g, 0, integral()); - } -template - inline bool operator!=(const function_base& f, Functor g) - { - typedef mpl::bool_<(is_integral::value)> integral; - return detail::function::compare_not_equal(f, g, 0, integral()); - } - -template - inline bool operator!=(Functor g, const function_base& f) - { - typedef mpl::bool_<(is_integral::value)> integral; - return detail::function::compare_not_equal(f, g, 0, integral()); - } -#else - -# if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3) // Comparisons between boost::function objects and arbitrary function -// objects. GCC 3.3 and before has an obnoxious bug that prevents this -// from working. +// objects. + template BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool) operator==(const function_base& f, Functor g) @@ -830,7 +658,6 @@ template return !function_equal(g, *fp); else return true; } -# endif template BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool) @@ -868,8 +695,6 @@ template else return true; } -#endif // Compiler supporting SFINAE - namespace detail { namespace function { inline bool has_empty_target(const function_base* f) @@ -893,10 +718,9 @@ namespace detail { } // end namespace boost #undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL -#undef BOOST_FUNCTION_COMPARE_TYPE_ID #if defined(BOOST_MSVC) # pragma warning( pop ) -#endif +#endif #endif // BOOST_FUNCTION_BASE_HEADER diff --git a/include/boost/function/function_fwd.hpp b/include/boost/function/function_fwd.hpp index e79b5048..fccfecc2 100644 --- a/include/boost/function/function_fwd.hpp +++ b/include/boost/function/function_fwd.hpp @@ -10,24 +10,9 @@ #define BOOST_FUNCTION_FWD_HPP #include -#if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG) -// Work around a compiler bug. -// boost::python::objects::function has to be seen by the compiler before the -// boost::function class template. -namespace boost { namespace python { namespace objects { - class function; -}}} -#endif - -#if defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG) \ - || !(defined(BOOST_STRICT_CONFIG) || !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540) -# define BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX -#endif - namespace boost { class bad_function_call; -#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX) // Preferred syntax template class function; @@ -36,34 +21,44 @@ namespace boost { { f1.swap(f2); } -#endif // have partial specialization // Portable syntax - template class function0; - template class function1; - template class function2; - template class function3; - template - class function4; - template - class function5; - template - class function6; - template - class function7; - template - class function8; - template - class function9; - template - class function10; + template class function_n; + + template using function0 = function_n; + template using function1 = function_n; + template using function2 = function_n; + template using function3 = function_n; + template using function4 = function_n; + template using function5 = function_n; + template using function6 = function_n; + template using function7 = function_n; + template using function8 = function_n; + template using function9 = function_n; + + template using function10 = function_n; + template using function11 = function_n; + template using function12 = function_n; + template using function13 = function_n; + template using function14 = function_n; + template using function15 = function_n; + template using function16 = function_n; + template using function17 = function_n; + template using function18 = function_n; + template using function19 = function_n; + + template using function20 = function_n; + template using function21 = function_n; + template using function22 = function_n; + template using function23 = function_n; + template using function24 = function_n; + template using function25 = function_n; + template using function26 = function_n; + template using function27 = function_n; + template using function28 = function_n; + template using function29 = function_n; + + template using function30 = function_n; } #endif diff --git a/include/boost/function/function_template.hpp b/include/boost/function/function_template.hpp index ab7abc51..ac4a5b24 100644 --- a/include/boost/function/function_template.hpp +++ b/include/boost/function/function_template.hpp @@ -1,3 +1,6 @@ +#ifndef BOOST_FUNCTION_FUNCTION_TEMPLATE_HPP_INCLUDED +#define BOOST_FUNCTION_FUNCTION_TEMPLATE_HPP_INCLUDED + // Boost.Function library // Copyright Douglas Gregor 2001-2006 @@ -8,80 +11,18 @@ // For more information, see http://www.boost.org -// Note: this header is a header template and must NOT have multiple-inclusion -// protection. -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include #if defined(BOOST_MSVC) # pragma warning( push ) # pragma warning( disable : 4127 ) // "conditional expression is constant" -#endif - -#define BOOST_FUNCTION_TEMPLATE_PARMS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, typename T) - -#define BOOST_FUNCTION_TEMPLATE_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, T) - -#define BOOST_FUNCTION_PARM(J,I,D) BOOST_PP_CAT(T,I) BOOST_PP_CAT(a,I) - -#define BOOST_FUNCTION_PARMS BOOST_PP_ENUM(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_PARM,BOOST_PP_EMPTY) - -#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES -# define BOOST_FUNCTION_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, a) -#else -# include -# define BOOST_FUNCTION_ARG(J,I,D) ::boost::forward< BOOST_PP_CAT(T,I) >(BOOST_PP_CAT(a,I)) -# define BOOST_FUNCTION_ARGS BOOST_PP_ENUM(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_ARG,BOOST_PP_EMPTY) -#endif - -#define BOOST_FUNCTION_ARG_TYPE(J,I,D) \ - typedef BOOST_PP_CAT(T,I) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(I)),_type); - -#define BOOST_FUNCTION_ARG_TYPES BOOST_PP_REPEAT(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_ARG_TYPE,BOOST_PP_EMPTY) - -// Comma if nonzero number of arguments -#if BOOST_FUNCTION_NUM_ARGS == 0 -# define BOOST_FUNCTION_COMMA -#else -# define BOOST_FUNCTION_COMMA , -#endif // BOOST_FUNCTION_NUM_ARGS > 0 - -// Class names used in this version of the code -#define BOOST_FUNCTION_FUNCTION BOOST_JOIN(function,BOOST_FUNCTION_NUM_ARGS) -#define BOOST_FUNCTION_FUNCTION_INVOKER \ - BOOST_JOIN(function_invoker,BOOST_FUNCTION_NUM_ARGS) -#define BOOST_FUNCTION_VOID_FUNCTION_INVOKER \ - BOOST_JOIN(void_function_invoker,BOOST_FUNCTION_NUM_ARGS) -#define BOOST_FUNCTION_FUNCTION_OBJ_INVOKER \ - BOOST_JOIN(function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) -#define BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER \ - BOOST_JOIN(void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) -#define BOOST_FUNCTION_FUNCTION_REF_INVOKER \ - BOOST_JOIN(function_ref_invoker,BOOST_FUNCTION_NUM_ARGS) -#define BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER \ - BOOST_JOIN(void_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS) -#define BOOST_FUNCTION_MEMBER_INVOKER \ - BOOST_JOIN(function_mem_invoker,BOOST_FUNCTION_NUM_ARGS) -#define BOOST_FUNCTION_VOID_MEMBER_INVOKER \ - BOOST_JOIN(function_void_mem_invoker,BOOST_FUNCTION_NUM_ARGS) -#define BOOST_FUNCTION_GET_FUNCTION_INVOKER \ - BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS) -#define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \ - BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) -#define BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER \ - BOOST_JOIN(get_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS) -#define BOOST_FUNCTION_GET_MEMBER_INVOKER \ - BOOST_JOIN(get_member_invoker,BOOST_FUNCTION_NUM_ARGS) -#define BOOST_FUNCTION_GET_INVOKER \ - BOOST_JOIN(get_invoker,BOOST_FUNCTION_NUM_ARGS) -#define BOOST_FUNCTION_VTABLE BOOST_JOIN(basic_vtable,BOOST_FUNCTION_NUM_ARGS) - -#ifndef BOOST_NO_VOID_RETURNS -# define BOOST_FUNCTION_VOID_RETURN_TYPE void -# define BOOST_FUNCTION_RETURN(X) X -#else -# define BOOST_FUNCTION_VOID_RETURN_TYPE boost::detail::function::unusable -# define BOOST_FUNCTION_RETURN(X) X; return BOOST_FUNCTION_VOID_RETURN_TYPE () #endif namespace boost { @@ -89,276 +30,271 @@ namespace boost { namespace function { template< typename FunctionPtr, - typename R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_PARMS + typename R, + typename... T > - struct BOOST_FUNCTION_FUNCTION_INVOKER + struct function_invoker { - static R invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA - BOOST_FUNCTION_PARMS) + static R invoke(function_buffer& function_ptr, + T... a) { - FunctionPtr f = reinterpret_cast(function_ptr.func_ptr); - return f(BOOST_FUNCTION_ARGS); + FunctionPtr f = reinterpret_cast(function_ptr.members.func_ptr); + return f(static_cast(a)...); } }; template< typename FunctionPtr, - typename R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_PARMS + typename R, + typename... T > - struct BOOST_FUNCTION_VOID_FUNCTION_INVOKER + struct void_function_invoker { - static BOOST_FUNCTION_VOID_RETURN_TYPE - invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA - BOOST_FUNCTION_PARMS) + static void + invoke(function_buffer& function_ptr, + T... a) { - FunctionPtr f = reinterpret_cast(function_ptr.func_ptr); - BOOST_FUNCTION_RETURN(f(BOOST_FUNCTION_ARGS)); + FunctionPtr f = reinterpret_cast(function_ptr.members.func_ptr); + f(static_cast(a)...); } }; template< typename FunctionObj, - typename R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_PARMS + typename R, + typename... T > - struct BOOST_FUNCTION_FUNCTION_OBJ_INVOKER + struct function_obj_invoker { - static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA - BOOST_FUNCTION_PARMS) + static R invoke(function_buffer& function_obj_ptr, + T... a) { FunctionObj* f; if (function_allows_small_object_optimization::value) - f = reinterpret_cast(&function_obj_ptr.data); + f = reinterpret_cast(function_obj_ptr.data); else - f = reinterpret_cast(function_obj_ptr.obj_ptr); - return (*f)(BOOST_FUNCTION_ARGS); + f = reinterpret_cast(function_obj_ptr.members.obj_ptr); + return (*f)(static_cast(a)...); } }; template< typename FunctionObj, - typename R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_PARMS + typename R, + typename... T > - struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER + struct void_function_obj_invoker { - static BOOST_FUNCTION_VOID_RETURN_TYPE - invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA - BOOST_FUNCTION_PARMS) + static void + invoke(function_buffer& function_obj_ptr, + T... a) { FunctionObj* f; if (function_allows_small_object_optimization::value) - f = reinterpret_cast(&function_obj_ptr.data); + f = reinterpret_cast(function_obj_ptr.data); else - f = reinterpret_cast(function_obj_ptr.obj_ptr); - BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS)); + f = reinterpret_cast(function_obj_ptr.members.obj_ptr); + (*f)(static_cast(a)...); } }; template< typename FunctionObj, - typename R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_PARMS + typename R, + typename... T > - struct BOOST_FUNCTION_FUNCTION_REF_INVOKER + struct function_ref_invoker { - static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA - BOOST_FUNCTION_PARMS) + static R invoke(function_buffer& function_obj_ptr, + T... a) { - FunctionObj* f = - reinterpret_cast(function_obj_ptr.obj_ptr); - return (*f)(BOOST_FUNCTION_ARGS); + FunctionObj* f = + reinterpret_cast(function_obj_ptr.members.obj_ptr); + return (*f)(static_cast(a)...); } }; template< typename FunctionObj, - typename R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_PARMS + typename R, + typename... T > - struct BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER + struct void_function_ref_invoker { - static BOOST_FUNCTION_VOID_RETURN_TYPE - invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA - BOOST_FUNCTION_PARMS) + static void + invoke(function_buffer& function_obj_ptr, + T... a) { - FunctionObj* f = - reinterpret_cast(function_obj_ptr.obj_ptr); - BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS)); + FunctionObj* f = + reinterpret_cast(function_obj_ptr.members.obj_ptr); + (*f)(static_cast(a)...); } }; -#if BOOST_FUNCTION_NUM_ARGS > 0 /* Handle invocation of member pointers. */ template< typename MemberPtr, - typename R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_PARMS + typename R, + typename... T > - struct BOOST_FUNCTION_MEMBER_INVOKER + struct member_invoker { - static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA - BOOST_FUNCTION_PARMS) + static R invoke(function_buffer& function_obj_ptr, + T... a) { - MemberPtr* f = - reinterpret_cast(&function_obj_ptr.data); - return boost::mem_fn(*f)(BOOST_FUNCTION_ARGS); + MemberPtr* f = + reinterpret_cast(function_obj_ptr.data); + return boost::mem_fn(*f)(static_cast(a)...); } }; template< typename MemberPtr, - typename R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_PARMS + typename R, + typename... T > - struct BOOST_FUNCTION_VOID_MEMBER_INVOKER + struct void_member_invoker { - static BOOST_FUNCTION_VOID_RETURN_TYPE - invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA - BOOST_FUNCTION_PARMS) + static void + invoke(function_buffer& function_obj_ptr, + T... a) { - MemberPtr* f = - reinterpret_cast(&function_obj_ptr.data); - BOOST_FUNCTION_RETURN(boost::mem_fn(*f)(BOOST_FUNCTION_ARGS)); + MemberPtr* f = + reinterpret_cast(function_obj_ptr.data); + boost::mem_fn(*f)(static_cast(a)...); } }; -#endif template< typename FunctionPtr, - typename R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_PARMS + typename R, + typename... T > - struct BOOST_FUNCTION_GET_FUNCTION_INVOKER + struct get_function_invoker { - typedef typename mpl::if_c<(is_void::value), - BOOST_FUNCTION_VOID_FUNCTION_INVOKER< + typedef typename std::conditional::value, + void_function_invoker< FunctionPtr, - R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS + R, + T... >, - BOOST_FUNCTION_FUNCTION_INVOKER< + function_invoker< FunctionPtr, - R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS + R, + T... > >::type type; }; template< typename FunctionObj, - typename R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_PARMS + typename R, + typename... T > - struct BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER + struct get_function_obj_invoker { - typedef typename mpl::if_c<(is_void::value), - BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER< + typedef typename std::conditional::value, + void_function_obj_invoker< FunctionObj, - R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS + R, + T... >, - BOOST_FUNCTION_FUNCTION_OBJ_INVOKER< + function_obj_invoker< FunctionObj, - R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS + R, + T... > >::type type; }; template< typename FunctionObj, - typename R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_PARMS + typename R, + typename... T > - struct BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER + struct get_function_ref_invoker { - typedef typename mpl::if_c<(is_void::value), - BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER< + typedef typename std::conditional::value, + void_function_ref_invoker< FunctionObj, - R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS + R, + T... >, - BOOST_FUNCTION_FUNCTION_REF_INVOKER< + function_ref_invoker< FunctionObj, - R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS + R, + T... > >::type type; }; -#if BOOST_FUNCTION_NUM_ARGS > 0 /* Retrieve the appropriate invoker for a member pointer. */ template< typename MemberPtr, - typename R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_PARMS + typename R, + typename... T > - struct BOOST_FUNCTION_GET_MEMBER_INVOKER + struct get_member_invoker { - typedef typename mpl::if_c<(is_void::value), - BOOST_FUNCTION_VOID_MEMBER_INVOKER< + typedef typename std::conditional::value, + void_member_invoker< MemberPtr, - R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS + R, + T... >, - BOOST_FUNCTION_MEMBER_INVOKER< + member_invoker< MemberPtr, - R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS + R, + T... > >::type type; }; -#endif /* Given the tag returned by get_function_tag, retrieve the actual invoker that will be used for the given function - object. + object. - Each specialization contains an "apply" nested class template + Each specialization contains an "apply_" nested class template that accepts the function object, return type, function - argument types, and allocator. The resulting "apply" class + argument types, and allocator. The resulting "apply_" class contains two typedefs, "invoker_type" and "manager_type", which correspond to the invoker and manager types. */ template - struct BOOST_FUNCTION_GET_INVOKER { }; + struct get_invoker { }; /* Retrieve the invoker for a function pointer. */ template<> - struct BOOST_FUNCTION_GET_INVOKER + struct get_invoker { template - struct apply + typename R, typename... T> + struct apply_ { - typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER< + typedef typename get_function_invoker< FunctionPtr, - R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS + R, + T... >::type invoker_type; typedef functor_manager manager_type; }; - template + template struct apply_a { - typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER< + typedef typename get_function_invoker< FunctionPtr, - R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS + R, + T... >::type invoker_type; @@ -366,69 +302,65 @@ namespace boost { }; }; -#if BOOST_FUNCTION_NUM_ARGS > 0 /* Retrieve the invoker for a member pointer. */ template<> - struct BOOST_FUNCTION_GET_INVOKER + struct get_invoker { template - struct apply + typename R, typename... T> + struct apply_ { - typedef typename BOOST_FUNCTION_GET_MEMBER_INVOKER< + typedef typename get_member_invoker< MemberPtr, - R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS + R, + T... >::type invoker_type; typedef functor_manager manager_type; }; - template + template struct apply_a { - typedef typename BOOST_FUNCTION_GET_MEMBER_INVOKER< + typedef typename get_member_invoker< MemberPtr, - R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS + R, + T... >::type invoker_type; typedef functor_manager manager_type; }; }; -#endif /* Retrieve the invoker for a function object. */ template<> - struct BOOST_FUNCTION_GET_INVOKER + struct get_invoker { template - struct apply + typename R, typename... T> + struct apply_ { - typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER< + typedef typename get_function_obj_invoker< FunctionObj, - R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS + R, + T... >::type invoker_type; typedef functor_manager manager_type; }; - template + template struct apply_a { - typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER< + typedef typename get_function_obj_invoker< FunctionObj, - R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS + R, + T... >::type invoker_type; @@ -438,31 +370,30 @@ namespace boost { /* Retrieve the invoker for a reference to a function object. */ template<> - struct BOOST_FUNCTION_GET_INVOKER + struct get_invoker { template - struct apply + typename R, typename... T> + struct apply_ { - typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER< + typedef typename get_function_ref_invoker< typename RefWrapper::type, - R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS + R, + T... >::type invoker_type; typedef reference_manager manager_type; }; - template + template struct apply_a { - typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER< + typedef typename get_function_ref_invoker< typename RefWrapper::type, - R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS + R, + T... >::type invoker_type; @@ -478,63 +409,64 @@ namespace boost { * members. It therefore cannot have any constructors, * destructors, base classes, etc. */ - template - struct BOOST_FUNCTION_VTABLE + template + struct basic_vtable { -#ifndef BOOST_NO_VOID_RETURNS typedef R result_type; -#else - typedef typename function_return_type::type result_type; -#endif // BOOST_NO_VOID_RETURNS typedef result_type (*invoker_type)(function_buffer& - BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS); + , + T...); template bool assign_to(F f, function_buffer& functor) const { typedef typename get_function_tag::type tag; - return assign_to(f, functor, tag()); + return assign_to(std::move(f), functor, tag()); } template bool assign_to_a(F f, function_buffer& functor, Allocator a) const { typedef typename get_function_tag::type tag; - return assign_to_a(f, functor, a, tag()); + return assign_to_a(std::move(f), functor, a, tag()); } void clear(function_buffer& functor) const { +#if defined(BOOST_GCC) && (__GNUC__ >= 11) +# pragma GCC diagnostic push +// False positive in GCC 11/12 for empty function objects +# pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif if (base.manager) base.manager(functor, functor, destroy_functor_tag); +#if defined(BOOST_GCC) && (__GNUC__ >= 11) +# pragma GCC diagnostic pop +#endif } private: // Function pointers template - bool + bool assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag) const { this->clear(functor); if (f) { - // should be a reinterpret cast, but some compilers insist - // on giving cv-qualifiers to free functions - functor.func_ptr = reinterpret_cast(f); + functor.members.func_ptr = reinterpret_cast(f); return true; } else { return false; } } template - bool + bool assign_to_a(FunctionPtr f, function_buffer& functor, Allocator, function_ptr_tag) const { - return assign_to(f,functor,function_ptr_tag()); + return assign_to(std::move(f),functor,function_ptr_tag()); } // Member pointers -#if BOOST_FUNCTION_NUM_ARGS > 0 template bool assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag) const { @@ -561,64 +493,65 @@ namespace boost { return false; } } -#endif // BOOST_FUNCTION_NUM_ARGS > 0 // Function objects // Assign to a function object using the small object optimization template - void - assign_functor(FunctionObj f, function_buffer& functor, mpl::true_) const + void + assign_functor(FunctionObj f, function_buffer& functor, std::true_type) const { - new (reinterpret_cast(&functor.data)) FunctionObj(f); + new (reinterpret_cast(functor.data)) FunctionObj(std::move(f)); } template - void - assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, mpl::true_) const + void + assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, std::true_type) const { - assign_functor(f,functor,mpl::true_()); + assign_functor(std::move(f),functor,std::true_type()); } // Assign to a function object allocated on the heap. template - void - assign_functor(FunctionObj f, function_buffer& functor, mpl::false_) const + void + assign_functor(FunctionObj f, function_buffer& functor, std::false_type) const { - functor.obj_ptr = new FunctionObj(f); + functor.members.obj_ptr = new FunctionObj(std::move(f)); } template - void - assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, mpl::false_) const + void + assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, std::false_type) const { typedef functor_wrapper functor_wrapper_type; - typedef typename Allocator::template rebind::other - wrapper_allocator_type; - typedef typename wrapper_allocator_type::pointer wrapper_allocator_pointer_type; + + using wrapper_allocator_type = typename std::allocator_traits::template rebind_alloc; + using wrapper_allocator_pointer_type = typename std::allocator_traits::pointer; + wrapper_allocator_type wrapper_allocator(a); wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1); - wrapper_allocator.construct(copy, functor_wrapper_type(f,a)); + std::allocator_traits::construct(wrapper_allocator, copy, functor_wrapper_type(f,a)); + functor_wrapper_type* new_f = static_cast(copy); - functor.obj_ptr = new_f; + functor.members.obj_ptr = new_f; } template - bool + bool assign_to(FunctionObj f, function_buffer& functor, function_obj_tag) const { if (!boost::detail::function::has_empty_target(boost::addressof(f))) { - assign_functor(f, functor, - mpl::bool_<(function_allows_small_object_optimization::value)>()); + assign_functor(std::move(f), functor, + std::integral_constant::value)>()); return true; } else { return false; } } template - bool + bool assign_to_a(FunctionObj f, function_buffer& functor, Allocator a, function_obj_tag) const { if (!boost::detail::function::has_empty_target(boost::addressof(f))) { - assign_functor_a(f, functor, a, - mpl::bool_<(function_allows_small_object_optimization::value)>()); + assign_functor_a(std::move(f), functor, a, + std::integral_constant::value)>()); return true; } else { return false; @@ -627,18 +560,18 @@ namespace boost { // Reference to a function object template - bool - assign_to(const reference_wrapper& f, + bool + assign_to(const reference_wrapper& f, function_buffer& functor, function_obj_ref_tag) const { - functor.obj_ref.obj_ptr = (void *)(f.get_pointer()); - functor.obj_ref.is_const_qualified = is_const::value; - functor.obj_ref.is_volatile_qualified = is_volatile::value; + functor.members.obj_ref.obj_ptr = (void *)(f.get_pointer()); + functor.members.obj_ref.is_const_qualified = std::is_const::value; + functor.members.obj_ref.is_volatile_qualified = std::is_volatile::value; return true; } template - bool - assign_to_a(const reference_wrapper& f, + bool + assign_to_a(const reference_wrapper& f, function_buffer& functor, Allocator, function_obj_ref_tag) const { return assign_to(f,functor,function_obj_ref_tag()); @@ -648,37 +581,146 @@ namespace boost { vtable_base base; invoker_type invoker; }; - } // end namespace function - } // end namespace detail - template< - typename R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_PARMS - > - class BOOST_FUNCTION_FUNCTION : public function_base + template + struct variadic_function_base + {}; + + template + struct variadic_function_base + { + typedef T1 argument_type; + typedef T1 arg1_type; + }; -#if BOOST_FUNCTION_NUM_ARGS == 1 + template + struct variadic_function_base + { + typedef T1 first_argument_type; + typedef T2 second_argument_type; + typedef T1 arg1_type; + typedef T2 arg2_type; + }; - , public std::unary_function + template + struct variadic_function_base + { + typedef T1 arg1_type; + typedef T2 arg2_type; + typedef T3 arg3_type; + }; -#elif BOOST_FUNCTION_NUM_ARGS == 2 + template + struct variadic_function_base + { + typedef T1 arg1_type; + typedef T2 arg2_type; + typedef T3 arg3_type; + typedef T4 arg4_type; + }; + + template + struct variadic_function_base + { + typedef T1 arg1_type; + typedef T2 arg2_type; + typedef T3 arg3_type; + typedef T4 arg4_type; + typedef T5 arg5_type; + }; - , public std::binary_function + template + struct variadic_function_base + { + typedef T1 arg1_type; + typedef T2 arg2_type; + typedef T3 arg3_type; + typedef T4 arg4_type; + typedef T5 arg5_type; + typedef T6 arg6_type; + }; + + template + struct variadic_function_base + { + typedef T1 arg1_type; + typedef T2 arg2_type; + typedef T3 arg3_type; + typedef T4 arg4_type; + typedef T5 arg5_type; + typedef T6 arg6_type; + typedef T7 arg7_type; + }; + + template + struct variadic_function_base + { + typedef T1 arg1_type; + typedef T2 arg2_type; + typedef T3 arg3_type; + typedef T4 arg4_type; + typedef T5 arg5_type; + typedef T6 arg6_type; + typedef T7 arg7_type; + typedef T8 arg8_type; + }; + + template + struct variadic_function_base + { + typedef T1 arg1_type; + typedef T2 arg2_type; + typedef T3 arg3_type; + typedef T4 arg4_type; + typedef T5 arg5_type; + typedef T6 arg6_type; + typedef T7 arg7_type; + typedef T8 arg8_type; + typedef T9 arg9_type; + }; + + template + struct variadic_function_base + { + typedef T1 arg1_type; + typedef T2 arg2_type; + typedef T3 arg3_type; + typedef T4 arg4_type; + typedef T5 arg5_type; + typedef T6 arg6_type; + typedef T7 arg7_type; + typedef T8 arg8_type; + typedef T9 arg9_type; + typedef T10 arg10_type; + }; + +#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 + + template struct is_trivially_copyable: std::integral_constant {}; + +#else + + using std::is_trivially_copyable; #endif + } // end namespace function + } // end namespace detail + + template< + typename R, + typename... T + > + class function_n : public function_base + , public detail::function::variadic_function_base { public: -#ifndef BOOST_NO_VOID_RETURNS typedef R result_type; -#else - typedef typename boost::detail::function::function_return_type::type - result_type; -#endif // BOOST_NO_VOID_RETURNS private: - typedef boost::detail::function::BOOST_FUNCTION_VTABLE< - R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> + typedef boost::detail::function::basic_vtable< + R, T...> vtable_type; vtable_type* get_vtable() const { @@ -689,8 +731,6 @@ namespace boost { struct clear_type {}; public: - BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS); - // add signature for boost::lambda template struct sig @@ -698,96 +738,68 @@ namespace boost { typedef result_type type; }; -#if BOOST_FUNCTION_NUM_ARGS == 1 - typedef T0 argument_type; -#elif BOOST_FUNCTION_NUM_ARGS == 2 - typedef T0 first_argument_type; - typedef T1 second_argument_type; -#endif + BOOST_STATIC_CONSTANT(int, arity = sizeof...(T)); - BOOST_STATIC_CONSTANT(int, arity = BOOST_FUNCTION_NUM_ARGS); - BOOST_FUNCTION_ARG_TYPES + typedef function_n self_type; - typedef BOOST_FUNCTION_FUNCTION self_type; - - BOOST_FUNCTION_FUNCTION() : function_base() { } + BOOST_DEFAULTED_FUNCTION(function_n(), : function_base() {}) // MSVC chokes if the following two constructors are collapsed into // one with a default parameter. template - BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f -#ifndef BOOST_NO_SFINAE - ,typename enable_if_c< - (boost::type_traits::ice_not< - (is_integral::value)>::value), + function_n(Functor f + ,typename std::enable_if< + !std::is_integral::value, int>::type = 0 -#endif // BOOST_NO_SFINAE ) : function_base() { - this->assign_to(f); + this->assign_to(std::move(f)); } template - BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a -#ifndef BOOST_NO_SFINAE - ,typename enable_if_c< - (boost::type_traits::ice_not< - (is_integral::value)>::value), + function_n(Functor f, Allocator a + ,typename std::enable_if< + !std::is_integral::value, int>::type = 0 -#endif // BOOST_NO_SFINAE ) : function_base() { - this->assign_to_a(f,a); + this->assign_to_a(std::move(f),a); } -#ifndef BOOST_NO_SFINAE - BOOST_FUNCTION_FUNCTION(clear_type*) : function_base() { } -#else - BOOST_FUNCTION_FUNCTION(int zero) : function_base() - { - BOOST_ASSERT(zero == 0); - } -#endif + function_n(clear_type*) : function_base() { } - BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) : function_base() + function_n(const function_n& f) : function_base() { this->assign_to_own(f); } - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - BOOST_FUNCTION_FUNCTION(BOOST_FUNCTION_FUNCTION&& f) : function_base() + + function_n(function_n&& f) : function_base() { this->move_assign(f); } -#endif - - ~BOOST_FUNCTION_FUNCTION() { clear(); } - result_type operator()(BOOST_FUNCTION_PARMS) const + ~function_n() { clear(); } + + result_type operator()(T... a) const { if (this->empty()) boost::throw_exception(bad_function_call()); return get_vtable()->invoker - (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS); + (this->functor, static_cast(a)...); } - // The distinction between when to use BOOST_FUNCTION_FUNCTION and + // The distinction between when to use function_n and // when to use self_type is obnoxious. MSVC cannot handle self_type as // the return type of these assignment operators, but Borland C++ cannot - // handle BOOST_FUNCTION_FUNCTION as the type of the temporary to + // handle function_n as the type of the temporary to // construct. template -#ifndef BOOST_NO_SFINAE - typename enable_if_c< - (boost::type_traits::ice_not< - (is_integral::value)>::value), - BOOST_FUNCTION_FUNCTION&>::type -#else - BOOST_FUNCTION_FUNCTION& -#endif - operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f) + typename std::enable_if< + !std::is_integral::value, + function_n&>::type + operator=(Functor f) { this->clear(); BOOST_TRY { @@ -800,7 +812,7 @@ namespace boost { return *this; } template - void assign(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a) + void assign(Functor f, Allocator a) { this->clear(); BOOST_TRY{ @@ -812,23 +824,14 @@ namespace boost { BOOST_CATCH_END } -#ifndef BOOST_NO_SFINAE - BOOST_FUNCTION_FUNCTION& operator=(clear_type*) + function_n& operator=(clear_type*) { this->clear(); return *this; } -#else - BOOST_FUNCTION_FUNCTION& operator=(int zero) - { - BOOST_ASSERT(zero == 0); - this->clear(); - return *this; - } -#endif - // Assignment from another BOOST_FUNCTION_FUNCTION - BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f) + // Assignment from another function_n + function_n& operator=(const function_n& f) { if (&f == this) return *this; @@ -843,12 +846,10 @@ namespace boost { BOOST_CATCH_END return *this; } - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - // Move assignment from another BOOST_FUNCTION_FUNCTION - BOOST_FUNCTION_FUNCTION& operator=(BOOST_FUNCTION_FUNCTION&& f) + + // Move assignment from another function_n + function_n& operator=(function_n&& f) { - if (&f == this) return *this; @@ -862,14 +863,13 @@ namespace boost { BOOST_CATCH_END return *this; } -#endif - void swap(BOOST_FUNCTION_FUNCTION& other) + void swap(function_n& other) { if (&other == this) return; - BOOST_FUNCTION_FUNCTION tmp; + function_n tmp; tmp.move_assign(*this); this->move_assign(other); other.move_assign(tmp); @@ -885,33 +885,31 @@ namespace boost { } } -#if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG) - // Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it - operator bool () const { return !this->empty(); } -#else - private: - struct dummy { - void nonnull() {} - }; - - typedef void (dummy::*safe_bool)(); - - public: - operator safe_bool () const - { return (this->empty())? 0 : &dummy::nonnull; } - - bool operator!() const - { return this->empty(); } -#endif + explicit operator bool () const { return !this->empty(); } private: - void assign_to_own(const BOOST_FUNCTION_FUNCTION& f) + void assign_to_own(const function_n& f) { if (!f.empty()) { this->vtable = f.vtable; - if (this->has_trivial_copy_and_destroy()) - this->functor = f.functor; - else + if (this->has_trivial_copy_and_destroy()) { + // Don't operate on storage directly since union type doesn't relax + // strict aliasing rules, despite of having member char type. +# if defined(BOOST_GCC) && (BOOST_GCC >= 40700) +# pragma GCC diagnostic push + // This warning is technically correct, but we don't want to pay the price for initializing + // just to silence a warning: https://github.com/boostorg/function/issues/27 +# pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +# if (BOOST_GCC >= 110000) + // GCC 11.3, 12 emit a different warning: https://github.com/boostorg/function/issues/42 +# pragma GCC diagnostic ignored "-Wuninitialized" +# endif +# endif + std::memcpy(this->functor.data, f.functor.data, sizeof(boost::detail::function::function_buffer)); +# if defined(BOOST_GCC) && (BOOST_GCC >= 40700) +# pragma GCC diagnostic pop +# endif + } else get_vtable()->base.manager(f.functor, this->functor, boost::detail::function::clone_functor_tag); } @@ -923,12 +921,12 @@ namespace boost { using boost::detail::function::vtable_base; typedef typename boost::detail::function::get_function_tag::type tag; - typedef boost::detail::function::BOOST_FUNCTION_GET_INVOKER get_invoker; + typedef boost::detail::function::get_invoker get_invoker; typedef typename get_invoker:: - template apply + template apply_ handler_type; - + typedef typename handler_type::invoker_type invoker_type; typedef typename handler_type::manager_type manager_type; @@ -936,18 +934,17 @@ namespace boost { // static initialization. Otherwise, we will have a race // condition here in multi-threaded code. See // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/. - static const vtable_type stored_vtable = + static const vtable_type stored_vtable = { { &manager_type::manage }, &invoker_type::invoke }; - if (stored_vtable.assign_to(f, functor)) { + if (stored_vtable.assign_to(std::move(f), functor)) { std::size_t value = reinterpret_cast(&stored_vtable.base); // coverity[pointless_expression]: suppress coverity warnings on apparant if(const). - if (boost::has_trivial_copy_constructor::value && - boost::has_trivial_destructor::value && + if (boost::detail::function::is_trivially_copyable::value && boost::detail::function::function_allows_small_object_optimization::value) value |= static_cast(0x01); vtable = reinterpret_cast(value); - } else + } else vtable = 0; } @@ -957,13 +954,12 @@ namespace boost { using boost::detail::function::vtable_base; typedef typename boost::detail::function::get_function_tag::type tag; - typedef boost::detail::function::BOOST_FUNCTION_GET_INVOKER get_invoker; + typedef boost::detail::function::get_invoker get_invoker; typedef typename get_invoker:: - template apply_a + template apply_a handler_type; - + typedef typename handler_type::invoker_type invoker_type; typedef typename handler_type::manager_type manager_type; @@ -974,34 +970,56 @@ namespace boost { static const vtable_type stored_vtable = { { &manager_type::manage }, &invoker_type::invoke }; - if (stored_vtable.assign_to_a(f, functor, a)) { + if (stored_vtable.assign_to_a(std::move(f), functor, a)) { std::size_t value = reinterpret_cast(&stored_vtable.base); // coverity[pointless_expression]: suppress coverity warnings on apparant if(const). - if (boost::has_trivial_copy_constructor::value && - boost::has_trivial_destructor::value && + if (boost::detail::function::is_trivially_copyable::value && boost::detail::function::function_allows_small_object_optimization::value) value |= static_cast(0x01); vtable = reinterpret_cast(value); - } else + } else vtable = 0; } - // Moves the value from the specified argument to *this. If the argument - // has its function object allocated on the heap, move_assign will pass - // its buffer to *this, and set the argument's buffer pointer to NULL. - void move_assign(BOOST_FUNCTION_FUNCTION& f) - { + // Moves the value from the specified argument to *this. If the argument + // has its function object allocated on the heap, move_assign will pass + // its buffer to *this, and set the argument's buffer pointer to NULL. + void move_assign(function_n& f) + { if (&f == this) return; BOOST_TRY { if (!f.empty()) { this->vtable = f.vtable; - if (this->has_trivial_copy_and_destroy()) - this->functor = f.functor; - else + if (this->has_trivial_copy_and_destroy()) { + // Don't operate on storage directly since union type doesn't relax + // strict aliasing rules, despite of having member char type. +# if defined(BOOST_GCC) && (BOOST_GCC >= 40700) +# pragma GCC diagnostic push + // This warning is technically correct, but we don't want to pay the price for initializing + // just to silence a warning: https://github.com/boostorg/function/issues/27 +# pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +# if (BOOST_GCC >= 120000) + // GCC 12 emits a different warning: https://github.com/boostorg/function/issues/42 +# pragma GCC diagnostic ignored "-Wuninitialized" +# endif +# endif + std::memcpy(this->functor.data, f.functor.data, sizeof(this->functor.data)); +# if defined(BOOST_GCC) && (BOOST_GCC >= 40700) +# pragma GCC diagnostic pop +# endif + } else +#if defined(BOOST_GCC) && (__GNUC__ >= 11) +# pragma GCC diagnostic push +// False positive in GCC 11/12 for empty function objects (function_n_test.cpp:673) +# pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif get_vtable()->base.manager(f.functor, this->functor, boost::detail::function::move_functor_tag); +#if defined(BOOST_GCC) && (__GNUC__ >= 11) +# pragma GCC diagnostic pop +#endif f.vtable = 0; } else { clear(); @@ -1014,183 +1032,148 @@ namespace boost { } }; - template - inline void swap(BOOST_FUNCTION_FUNCTION< - R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS + template + inline void swap(function_n< + R, + T... >& f1, - BOOST_FUNCTION_FUNCTION< - R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS + function_n< + R, + T... >& f2) { f1.swap(f2); } // Poison comparisons between boost::function objects of the same type. -template - void operator==(const BOOST_FUNCTION_FUNCTION< - R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS>&, - const BOOST_FUNCTION_FUNCTION< - R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS>&); -template - void operator!=(const BOOST_FUNCTION_FUNCTION< - R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS>&, - const BOOST_FUNCTION_FUNCTION< - R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS>& ); - -#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX) - -#if BOOST_FUNCTION_NUM_ARGS == 0 -#define BOOST_FUNCTION_PARTIAL_SPEC R (void) -#else -#define BOOST_FUNCTION_PARTIAL_SPEC R (BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,T)) -#endif - -template -class function - : public BOOST_FUNCTION_FUNCTION +template + void operator==(const function_n< + R, + T...>&, + const function_n< + R, + T...>&); +template + void operator!=(const function_n< + R, + T...>&, + const function_n< + R, + T...>& ); + +template +class function + : public function_n { - typedef BOOST_FUNCTION_FUNCTION base_type; + typedef function_n base_type; typedef function self_type; struct clear_type {}; public: - function() : base_type() {} + BOOST_DEFAULTED_FUNCTION(function(), : base_type() {}) template function(Functor f -#ifndef BOOST_NO_SFINAE - ,typename enable_if_c< - (boost::type_traits::ice_not< - (is_integral::value)>::value), + ,typename std::enable_if< + !std::is_integral::value, int>::type = 0 -#endif ) : - base_type(f) + base_type(std::move(f)) { } template function(Functor f, Allocator a -#ifndef BOOST_NO_SFINAE - ,typename enable_if_c< - (boost::type_traits::ice_not< - (is_integral::value)>::value), + ,typename std::enable_if< + !std::is_integral::value, int>::type = 0 -#endif ) : - base_type(f,a) + base_type(std::move(f),a) { } -#ifndef BOOST_NO_SFINAE function(clear_type*) : base_type() {} -#endif function(const self_type& f) : base_type(static_cast(f)){} function(const base_type& f) : base_type(static_cast(f)){} -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES // Move constructors function(self_type&& f): base_type(static_cast(f)){} function(base_type&& f): base_type(static_cast(f)){} -#endif - + self_type& operator=(const self_type& f) { self_type(f).swap(*this); return *this; } -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES self_type& operator=(self_type&& f) { self_type(static_cast(f)).swap(*this); return *this; } -#endif template -#ifndef BOOST_NO_SFINAE - typename enable_if_c< - (boost::type_traits::ice_not< - (is_integral::value)>::value), + typename std::enable_if< + !std::is_integral::value, self_type&>::type -#else - self_type& -#endif operator=(Functor f) { self_type(f).swap(*this); return *this; } -#ifndef BOOST_NO_SFINAE self_type& operator=(clear_type*) { this->clear(); return *this; } -#endif self_type& operator=(const base_type& f) { self_type(f).swap(*this); return *this; } - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + self_type& operator=(base_type&& f) { self_type(static_cast(f)).swap(*this); return *this; } -#endif }; -#undef BOOST_FUNCTION_PARTIAL_SPEC -#endif // have partial specialization - } // end namespace boost -// Cleanup after ourselves... -#undef BOOST_FUNCTION_VTABLE -#undef BOOST_FUNCTION_COMMA -#undef BOOST_FUNCTION_FUNCTION -#undef BOOST_FUNCTION_FUNCTION_INVOKER -#undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER -#undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER -#undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER -#undef BOOST_FUNCTION_FUNCTION_REF_INVOKER -#undef BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER -#undef BOOST_FUNCTION_MEMBER_INVOKER -#undef BOOST_FUNCTION_VOID_MEMBER_INVOKER -#undef BOOST_FUNCTION_GET_FUNCTION_INVOKER -#undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER -#undef BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER -#undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER -#undef BOOST_FUNCTION_GET_INVOKER -#undef BOOST_FUNCTION_TEMPLATE_PARMS -#undef BOOST_FUNCTION_TEMPLATE_ARGS -#undef BOOST_FUNCTION_PARMS -#undef BOOST_FUNCTION_PARM -#ifdef BOOST_FUNCTION_ARG -# undef BOOST_FUNCTION_ARG -#endif -#undef BOOST_FUNCTION_ARGS -#undef BOOST_FUNCTION_ARG_TYPE -#undef BOOST_FUNCTION_ARG_TYPES -#undef BOOST_FUNCTION_VOID_RETURN_TYPE -#undef BOOST_FUNCTION_RETURN - #if defined(BOOST_MSVC) # pragma warning( pop ) -#endif +#endif + +// Resolve C++20 issue with fn == bind(...) +// https://github.com/boostorg/function/issues/45 + +namespace boost +{ + +namespace _bi +{ + +template class bind_t; + +} // namespace _bi + +template bool operator==( function const& f, _bi::bind_t const& b ) +{ + return f.contains( b ); +} + +template bool operator!=( function const& f, _bi::bind_t const& b ) +{ + return !f.contains( b ); +} + +} // namespace boost + +#endif // #ifndef BOOST_FUNCTION_FUNCTION_TEMPLATE_HPP_INCLUDED diff --git a/include/boost/function/function_typeof.hpp b/include/boost/function/function_typeof.hpp index 246dc15d..3bef2704 100644 --- a/include/boost/function/function_typeof.hpp +++ b/include/boost/function/function_typeof.hpp @@ -9,37 +9,7 @@ #ifndef BOOST_FUNCTION_TYPEOF_HPP #define BOOST_FUNCTION_TYPEOF_HPP #include -#include -#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() +// This header is no longer necessary and is only retained for compatibility -BOOST_TYPEOF_REGISTER_TYPE(boost::bad_function_call) - -#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX) -BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function, (typename)) -#endif - -BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function0, (typename)) -BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function1, (typename)(typename)) -BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function2, (typename)(typename)(typename)) -BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function3, - (typename)(typename)(typename)(typename)) -BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function4, - (typename)(typename)(typename)(typename)(typename)) -BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function5, - (typename)(typename)(typename)(typename)(typename)(typename)) -BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function6, - (typename)(typename)(typename)(typename)(typename)(typename)(typename)) -BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function7, - (typename)(typename)(typename)(typename)(typename)(typename)(typename) - (typename)) -BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function8, - (typename)(typename)(typename)(typename)(typename)(typename)(typename) - (typename)(typename)) -BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function9, - (typename)(typename)(typename)(typename)(typename)(typename)(typename) - (typename)(typename)(typename)) -BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function10, - (typename)(typename)(typename)(typename)(typename)(typename)(typename) - (typename)(typename)(typename)(typename)) #endif diff --git a/include/boost/function/gen_function_N.pl b/include/boost/function/gen_function_N.pl deleted file mode 100644 index d8f1249b..00000000 --- a/include/boost/function/gen_function_N.pl +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/perl -w -# -# Boost.Function library -# -# Copyright Douglas Gregor 2001-2003. Use, modification and -# distribution is subject to the Boost Software License, Version -# 1.0. (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) -# -# For more information, see http://www.boost.org -use English; - -if ($#ARGV < 0) { - print "Usage: perl gen_function_N \n"; - exit; -} - - -$totalNumArgs = $ARGV[0]; -for ($numArgs = 0; $numArgs <= $totalNumArgs; ++$numArgs) { - open OUT, ">function$numArgs.hpp"; - print OUT "#define BOOST_FUNCTION_NUM_ARGS $numArgs\n"; - print OUT "#include \n"; - print OUT "#undef BOOST_FUNCTION_NUM_ARGS\n"; - close OUT; -} diff --git a/meta/libraries.json b/meta/libraries.json index 92523197..4581166b 100644 --- a/meta/libraries.json +++ b/meta/libraries.json @@ -13,6 +13,7 @@ "Programming" ], "maintainers": [ - "Douglas Gregor " - ] + "Peter Dimov " + ], + "cxxstd": "11" } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 00000000..329e1ac9 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,11 @@ +# Copyright 2018, 2019 Peter Dimov +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt + +include(BoostTestJamfile OPTIONAL RESULT_VARIABLE HAVE_BOOST_TEST) + +if(HAVE_BOOST_TEST) + +boost_test_jamfile(FILE Jamfile.v2 LINK_LIBRARIES Boost::function Boost::core Boost::lambda Boost::move) + +endif() diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 5a2dbad3..22c3ebfe 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -7,63 +7,91 @@ # For more information, see http://www.boost.org/ -project - : requirements msvc:on - : source-location $(BOOST_ROOT) - ; - -# bring in rules for testing import testing ; -{ - - test-suite function - : - [ run libs/function/test/function_test.cpp : : : : lib_function_test ] - - [ run libs/function/test/function_n_test.cpp : : : : ] - - [ run libs/function/test/allocator_test.cpp ../../../libs/test/build//boost_test_exec_monitor : : : : ] - - [ run libs/function/test/stateless_test.cpp ../../../libs/test/build//boost_test_exec_monitor : : : : ] - - [ run libs/function/test/lambda_test.cpp ../../../libs/test/build//boost_test_exec_monitor : : : : ] - - [ compile-fail libs/function/test/function_test_fail1.cpp : : : : ] - - [ compile-fail libs/function/test/function_test_fail2.cpp : : : : ] - - [ compile libs/function/test/function_30.cpp : : : : ] - - [ run libs/function/test/function_arith_cxx98.cpp : : : : ] - - [ run libs/function/test/function_arith_portable.cpp : : : : ] - - [ run libs/function/test/sum_avg_cxx98.cpp : : : : ] - - [ run libs/function/test/sum_avg_portable.cpp : : : : ] - - [ run libs/function/test/mem_fun_cxx98.cpp : : : : ] - - [ run libs/function/test/mem_fun_portable.cpp : : : : ] - - [ run libs/function/test/std_bind_cxx98.cpp : : : : ] - - [ run libs/function/test/std_bind_portable.cpp : : : : ] - - [ run libs/function/test/function_ref_cxx98.cpp : : : : ] - - [ run libs/function/test/function_ref_portable.cpp : : : : ] - - [ run libs/function/test/contains_test.cpp : : : : ] - - [ run libs/function/test/contains2_test.cpp : : : : ] - - [ run libs/function/test/nothrow_swap.cpp : : : : ] - - [ run libs/function/test/rvalues_test.cpp : : : : ] - - [ compile libs/function/test/function_typeof_test.cpp ] - ; -} - +project + : default-build + extra + : requirements + msvc:on + gcc:on + clang:on + /boost/function//boost_function + /boost/typeof//boost_typeof + ; + +run function_test.cpp ; +# /usr/include/c++/4.4/bits/shared_ptr.h:146: error: cannot use typeid with -fno-rtti +run function_test.cpp : : : off gcc-4.4,0x:no : function_test_no_rtti ; +run function_n_test.cpp ; +run allocator_test.cpp ; +run stateless_test.cpp ; +run lambda_test.cpp + : : : /boost/lambda//boost_lambda ; +compile-fail function_test_fail1.cpp ; +compile-fail function_test_fail2.cpp ; +compile function_30.cpp ; +compile function_30_repeat.cpp ; +run function_arith_cxx98.cpp ; +run function_arith_portable.cpp ; +run sum_avg_cxx98.cpp ; +run sum_avg_portable.cpp ; +run mem_fun_cxx98.cpp ; +run mem_fun_portable.cpp ; +run std_bind_cxx98.cpp ; +run std_bind_portable.cpp ; +run function_ref_cxx98.cpp ; +run function_ref_portable.cpp ; +run contains_test.cpp ; +run contains2_test.cpp ; +run nothrow_swap.cpp ; +run rvalues_test.cpp + : : : /boost/move//boost_move ; +compile function_typeof_test.cpp + : 03:no 98:no 0x:no ; +run result_arg_types_test.cpp ; +run result_arg_n_types_test.cpp ; + +lib throw_bad_function_call : throw_bad_function_call.cpp : shared:THROW_BAD_FUNCTION_CALL_DYN_LINK=1 ; + +run test_bad_function_call.cpp throw_bad_function_call : : : shared : test_bad_function_call_shared ; +run test_bad_function_call.cpp throw_bad_function_call : : : static : test_bad_function_call_static ; + +lib mixed_cxxstd : mixed_cxxstd.cpp : shared:MIXED_CXXSTD_DYN_LINK=1 ; + +run test_mixed_cxxstd.cpp mixed_cxxstd : : : shared : mixed_cxxstd_shared ; +run test_mixed_cxxstd.cpp mixed_cxxstd : : : static : mixed_cxxstd_static ; + +run test_mixed_cxxstd.cpp mixed_cxxstd/0x : : : shared : mixed_cxxstd_shared_0x ; +run test_mixed_cxxstd.cpp mixed_cxxstd/0x : : : static : mixed_cxxstd_static_0x ; + +local check14 = [ check-target-builds mixed_cxxstd/14 : : no ] ; + +run test_mixed_cxxstd.cpp mixed_cxxstd/14 : : : shared $(check14) : mixed_cxxstd_shared_14 ; +run test_mixed_cxxstd.cpp mixed_cxxstd/14 : : : static $(check14) : mixed_cxxstd_static_14 ; + +lib return_function : return_function.cpp : shared:RETURN_FUNCTION_DYN_LINK=1 ; + +run test_return_function.cpp return_function : : : shared : return_function_shared ; +run test_return_function.cpp return_function : : : static : return_function_static ; + +run test_return_function.cpp return_function/0x : : : shared : return_function_shared_0x ; +run test_return_function.cpp return_function/0x : : : static : return_function_static_0x ; + +run test_return_function.cpp return_function/14 : : : shared $(check14) : return_function_shared_14 ; +run test_return_function.cpp return_function/14 : : : static $(check14) : return_function_static_14 ; + +run quick.cpp ; + +compile issue_42.cpp ; + +run fn_eq_bind_test.cpp ; + +# /usr/include/c++/4.4/bits/shared_ptr.h:146: error: cannot use typeid with -fno-rtti +run contains_test.cpp : : : off gcc-4.4,0x:no : contains_test_no_rtti ; +run contains2_test.cpp : : : off gcc-4.4,0x:no : contains2_test_no_rtti ; + +run contains3_test.cpp ; +run contains3_test.cpp : : : off gcc-4.4,0x:no : contains3_test_no_rtti ; + +compile issue_53.cpp ; diff --git a/test/allocator_test.cpp b/test/allocator_test.cpp index 3643b2b8..a09f067c 100644 --- a/test/allocator_test.cpp +++ b/test/allocator_test.cpp @@ -7,10 +7,10 @@ // For more information, see http://www.boost.org -#include +#include +#include #include #include -#include using namespace std; using namespace boost; @@ -74,20 +74,19 @@ struct DoNothing: base static void do_nothing() {} -int -test_main(int, char*[]) +int main() { function2 f; f.assign( plus_int(), counting_allocator() ); f.clear(); - BOOST_CHECK(alloc_count == 1); - BOOST_CHECK(dealloc_count == 1); + BOOST_TEST_EQ( alloc_count, 1 ); + BOOST_TEST_EQ( dealloc_count, 1 ); alloc_count = 0; dealloc_count = 0; f.assign( plus_int(), counting_allocator() ); f.clear(); - BOOST_CHECK(alloc_count == 0); - BOOST_CHECK(dealloc_count == 0); + BOOST_TEST_EQ( alloc_count, 0 ); + BOOST_TEST_EQ( dealloc_count, 0 ); f.assign( plus_int(), std::allocator() ); f.clear(); f.assign( plus_int(), std::allocator() ); @@ -97,8 +96,8 @@ test_main(int, char*[]) dealloc_count = 0; f.assign( &do_minus, counting_allocator() ); f.clear(); - BOOST_CHECK(alloc_count == 0); - BOOST_CHECK(dealloc_count == 0); + BOOST_TEST_EQ( alloc_count, 0 ); + BOOST_TEST_EQ( dealloc_count, 0 ); f.assign( &do_minus, std::allocator() ); f.clear(); @@ -107,14 +106,14 @@ test_main(int, char*[]) dealloc_count = 0; fv.assign( DoNothing(), counting_allocator() ); fv.clear(); - BOOST_CHECK(alloc_count == 1); - BOOST_CHECK(dealloc_count == 1); + BOOST_TEST_EQ( alloc_count, 1 ); + BOOST_TEST_EQ( dealloc_count, 1 ); alloc_count = 0; dealloc_count = 0; fv.assign( DoNothing(), counting_allocator() ); fv.clear(); - BOOST_CHECK(alloc_count == 0); - BOOST_CHECK(dealloc_count == 0); + BOOST_TEST_EQ( alloc_count, 0 ); + BOOST_TEST_EQ( dealloc_count, 0 ); fv.assign( DoNothing(), std::allocator() ); fv.clear(); fv.assign( DoNothing(), std::allocator() ); @@ -124,8 +123,8 @@ test_main(int, char*[]) dealloc_count = 0; fv.assign( &do_nothing, counting_allocator() ); fv.clear(); - BOOST_CHECK(alloc_count == 0); - BOOST_CHECK(dealloc_count == 0); + BOOST_TEST_EQ( alloc_count, 0 ); + BOOST_TEST_EQ( dealloc_count, 0 ); fv.assign( &do_nothing, std::allocator() ); fv.clear(); @@ -133,5 +132,5 @@ test_main(int, char*[]) fv.assign(&do_nothing, std::allocator() ); fv2.assign(fv, std::allocator() ); - return 0; + return boost::report_errors(); } diff --git a/test/cmake_install_test/CMakeLists.txt b/test/cmake_install_test/CMakeLists.txt new file mode 100644 index 00000000..c8ebe9c5 --- /dev/null +++ b/test/cmake_install_test/CMakeLists.txt @@ -0,0 +1,17 @@ +# Copyright 2018, 2019 Peter Dimov +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt + +cmake_minimum_required(VERSION 3.5...3.16) + +project(cmake_install_test LANGUAGES CXX) + +find_package(boost_function REQUIRED) + +add_executable(main main.cpp) +target_link_libraries(main Boost::function) + +enable_testing() +add_test(main main) + +add_custom_target(check VERBATIM COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C $) diff --git a/test/cmake_install_test/main.cpp b/test/cmake_install_test/main.cpp new file mode 100644 index 00000000..3435a946 --- /dev/null +++ b/test/cmake_install_test/main.cpp @@ -0,0 +1,22 @@ +// Copyright 2017, 2021 Peter Dimov. +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// See library home page at http://www.boost.org/libs/function + +#include +#include + +#define BOOST_TEST(expr) assert(expr) +#define BOOST_TEST_EQ(x1, x2) assert((x1)==(x2)) + +int add( int x, int y ) +{ + return x + y; +} + +int main() +{ + boost::function fn( &add ); + BOOST_TEST_EQ( fn( 1, 2 ), 3 ); +} diff --git a/test/cmake_subdir_test/CMakeLists.txt b/test/cmake_subdir_test/CMakeLists.txt new file mode 100644 index 00000000..dd92879b --- /dev/null +++ b/test/cmake_subdir_test/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright 2018, 2019 Peter Dimov +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt + +cmake_minimum_required(VERSION 3.5...3.20) + +project(cmake_subdir_test LANGUAGES CXX) + +add_subdirectory(../.. boostorg/function) + +set(deps + +# Primary dependencies + +assert +bind +config +core +throw_exception + +# Secondary dependencies + +) + +foreach(dep IN LISTS deps) + + add_subdirectory(../../../${dep} boostorg/${dep}) + +endforeach() + +# --target check + +add_executable(quick ../quick.cpp) +target_link_libraries(quick Boost::function Boost::core) + +enable_testing() +add_test(quick quick) + +add_custom_target(check VERBATIM COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C $) diff --git a/test/contains2_test.cpp b/test/contains2_test.cpp index cf6d4798..9cfa5c34 100644 --- a/test/contains2_test.cpp +++ b/test/contains2_test.cpp @@ -9,7 +9,7 @@ // http://www.boost.org/LICENSE_1_0.txt) #include -#include +#include static int forty_two() { diff --git a/test/contains3_test.cpp b/test/contains3_test.cpp new file mode 100644 index 00000000..e6130bbe --- /dev/null +++ b/test/contains3_test.cpp @@ -0,0 +1,33 @@ +// Copyright 2023 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include + +static int f() +{ + return 1; +} + +static int g() +{ + return 2; +} + +int main() +{ + { + boost::function fn; + BOOST_TEST( !fn.contains( f ) ); + BOOST_TEST( !fn.contains( g ) ); + } + + { + boost::function fn( f ); + BOOST_TEST( fn.contains( f ) ); + BOOST_TEST( !fn.contains( g ) ); + } + + return boost::report_errors(); +} diff --git a/test/contains_test.cpp b/test/contains_test.cpp index fa115599..64418711 100644 --- a/test/contains_test.cpp +++ b/test/contains_test.cpp @@ -5,10 +5,12 @@ // 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include #include +#include #include +#define BOOST_CHECK BOOST_TEST + static int forty_two() { return 42; } struct Seventeen @@ -31,7 +33,7 @@ bool operator==(const ReturnInt& x, const ReturnInt& y) bool operator!=(const ReturnInt& x, const ReturnInt& y) { return x.value != y.value; } -namespace contain_test { +namespace contains_test { struct ReturnIntFE { @@ -42,34 +44,10 @@ struct ReturnIntFE int value; }; -} - -#ifndef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP - -namespace contain_test { -# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING bool function_equal(const ReturnIntFE& x, const ReturnIntFE& y) { return x.value == y.value; } -# else -bool function_equal_impl(const ReturnIntFE& x, const ReturnIntFE& y, int) -{ return x.value == y.value; } -# endif // #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING -} -#else // BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP -namespace boost { -# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING -bool -function_equal(const contain_test::ReturnIntFE& x, - const contain_test::ReturnIntFE& y) -{ return x.value == y.value; } -# else -bool -function_equal_impl(const contain_test::ReturnIntFE& x, - const contain_test::ReturnIntFE& y, int) -{ return x.value == y.value; } -# endif -} -#endif + +} // namespace contains_test static void target_test() { @@ -106,10 +84,8 @@ static void equal_test() f = &forty_two; BOOST_CHECK(f == &forty_two); BOOST_CHECK(f != ReturnInt(17)); -#if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3) BOOST_CHECK(&forty_two == f); BOOST_CHECK(ReturnInt(17) != f); -#endif BOOST_CHECK(f.contains(&forty_two)); @@ -117,47 +93,37 @@ static void equal_test() BOOST_CHECK(f != &forty_two); BOOST_CHECK(f == ReturnInt(17)); BOOST_CHECK(f != ReturnInt(16)); -#if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3) BOOST_CHECK(&forty_two != f); BOOST_CHECK(ReturnInt(17) == f); BOOST_CHECK(ReturnInt(16) != f); -#endif BOOST_CHECK(f.contains(ReturnInt(17))); - f = contain_test::ReturnIntFE(17); + f = contains_test::ReturnIntFE(17); BOOST_CHECK(f != &forty_two); - BOOST_CHECK(f == contain_test::ReturnIntFE(17)); - BOOST_CHECK(f != contain_test::ReturnIntFE(16)); -#if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3) + BOOST_CHECK(f == contains_test::ReturnIntFE(17)); + BOOST_CHECK(f != contains_test::ReturnIntFE(16)); BOOST_CHECK(&forty_two != f); - BOOST_CHECK(contain_test::ReturnIntFE(17) == f); - BOOST_CHECK(contain_test::ReturnIntFE(16) != f); -#endif + BOOST_CHECK(contains_test::ReturnIntFE(17) == f); + BOOST_CHECK(contains_test::ReturnIntFE(16) != f); - BOOST_CHECK(f.contains(contain_test::ReturnIntFE(17))); + BOOST_CHECK(f.contains(contains_test::ReturnIntFE(17))); -#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX) boost::function g; g = &forty_two; BOOST_CHECK(g == &forty_two); BOOST_CHECK(g != ReturnInt(17)); -# if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3) BOOST_CHECK(&forty_two == g); BOOST_CHECK(ReturnInt(17) != g); -# endif g = ReturnInt(17); BOOST_CHECK(g != &forty_two); BOOST_CHECK(g == ReturnInt(17)); BOOST_CHECK(g != ReturnInt(16)); -# if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3) BOOST_CHECK(&forty_two != g); BOOST_CHECK(ReturnInt(17) == g); BOOST_CHECK(ReturnInt(16) != g); -# endif -#endif } static void ref_equal_test() @@ -173,10 +139,8 @@ static void ref_equal_test() BOOST_CHECK(!(f != boost::ref(ri))); BOOST_CHECK(!(f != ri)); BOOST_CHECK(!(boost::ref(ri) != f)); -#if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3) BOOST_CHECK(ri == f); BOOST_CHECK(!(ri != f)); -#endif // Values equal, references inequal ReturnInt ri2(17); @@ -186,13 +150,10 @@ static void ref_equal_test() BOOST_CHECK(!(f != ri2)); BOOST_CHECK(!(f == boost::ref(ri2))); BOOST_CHECK(!(boost::ref(ri2) == f)); -#if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3) BOOST_CHECK(ri2 == f); BOOST_CHECK(!(ri2 != f)); -#endif } -#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX) { ReturnInt ri(17); boost::function f = boost::ref(ri); @@ -204,10 +165,8 @@ static void ref_equal_test() BOOST_CHECK(!(f != boost::ref(ri))); BOOST_CHECK(!(f != ri)); BOOST_CHECK(!(boost::ref(ri) != f)); -# if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3) BOOST_CHECK(ri == f); BOOST_CHECK(!(ri != f)); -# endif // Values equal, references inequal ReturnInt ri2(17); @@ -217,19 +176,16 @@ static void ref_equal_test() BOOST_CHECK(!(f != ri2)); BOOST_CHECK(!(f == boost::ref(ri2))); BOOST_CHECK(!(boost::ref(ri2) == f)); -# if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3) BOOST_CHECK(ri2 == f); BOOST_CHECK(!(ri2 != f)); -# endif } -#endif } -int test_main(int, char*[]) +int main() { target_test(); equal_test(); ref_equal_test(); - return 0; + return boost::report_errors(); } diff --git a/test/fn_eq_bind_test.cpp b/test/fn_eq_bind_test.cpp new file mode 100644 index 00000000..b6ad599f --- /dev/null +++ b/test/fn_eq_bind_test.cpp @@ -0,0 +1,87 @@ +// Copyright 2023 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include + +using namespace boost::placeholders; + +int f1() { return 1; } +int f2() { return 2; } + +int main() +{ + { + boost::function fn( boost::bind( f1 ) ); + + BOOST_TEST( fn == boost::bind( f1 ) ); + BOOST_TEST( fn != boost::bind( f2 ) ); + } + + { + boost::function fn( boost::bind( f1 ) ); + + BOOST_TEST( fn == boost::bind( f1 ) ); + BOOST_TEST( fn != boost::bind( f2 ) ); + } + + { + boost::function fn( boost::bind( f1 ) ); + + BOOST_TEST( fn == boost::bind( f1 ) ); + BOOST_TEST( fn != boost::bind( f2 ) ); + } + + { + boost::function fn( boost::bind( f1 ) ); + + BOOST_TEST( fn == boost::bind( f1 ) ); + BOOST_TEST( fn != boost::bind( f2 ) ); + } + + { + boost::function fn( boost::bind( f1 ) ); + + BOOST_TEST( fn == boost::bind( f1 ) ); + BOOST_TEST( fn != boost::bind( f2 ) ); + } + + { + boost::function fn( boost::bind( f1 ) ); + + BOOST_TEST( fn == boost::bind( f1 ) ); + BOOST_TEST( fn != boost::bind( f2 ) ); + } + + { + boost::function fn( boost::bind( f1 ) ); + + BOOST_TEST( fn == boost::bind( f1 ) ); + BOOST_TEST( fn != boost::bind( f2 ) ); + } + + { + boost::function fn( boost::bind( f1 ) ); + + BOOST_TEST( fn == boost::bind( f1 ) ); + BOOST_TEST( fn != boost::bind( f2 ) ); + } + + { + boost::function fn( boost::bind( f1 ) ); + + BOOST_TEST( fn == boost::bind( f1 ) ); + BOOST_TEST( fn != boost::bind( f2 ) ); + } + + { + boost::function fn( boost::bind( f1 ) ); + + BOOST_TEST( fn == boost::bind( f1 ) ); + BOOST_TEST( fn != boost::bind( f2 ) ); + } + + return boost::report_errors(); +} diff --git a/test/function_30_repeat.cpp b/test/function_30_repeat.cpp new file mode 100644 index 00000000..b8107063 --- /dev/null +++ b/test/function_30_repeat.cpp @@ -0,0 +1,35 @@ +// Boost.Function library + +// Copyright Douglas Gregor 2002-2003. Use, modification and +// distribution is subject to the Boost Software License, Version +// 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// For more information, see http://www.boost.org + +// Make sure we don't try to redefine function2 +#include + +// Define all Boost.Function class templates up to 30 arguments +#define BOOST_FUNCTION_MAX_ARGS 20 +#include +#undef BOOST_FUNCTION_MAX_ARGS +#define BOOST_FUNCTION_MAX_ARGS 40 +#include +#undef BOOST_FUNCTION_MAX_ARGS +#define BOOST_FUNCTION_MAX_ARGS 25 +#include +#undef BOOST_FUNCTION_MAX_ARGS +#define BOOST_FUNCTION_MAX_ARGS 30 +#include +#include + +int main() +{ + boost::function0 f0; + + boost::function30 f30; + return 0; +} diff --git a/test/function_n_test.cpp b/test/function_n_test.cpp index cdd71459..7fcf3f2e 100644 --- a/test/function_n_test.cpp +++ b/test/function_n_test.cpp @@ -7,12 +7,20 @@ // For more information, see http://www.boost.org -#include +#if defined(__clang__) && defined(__has_warning) +# if __has_warning( "-Wself-assign-overloaded" ) +# pragma clang diagnostic ignored "-Wself-assign-overloaded" +# endif +#endif + #include +#include #include #include #include +#define BOOST_CHECK BOOST_TEST + using namespace boost; using std::string; using std::negate; @@ -631,7 +639,7 @@ test_ref() boost::function2 f(ref(atc)); BOOST_CHECK(f(1, 3) == 4); } - catch(std::runtime_error e) { + catch(std::runtime_error const&) { BOOST_ERROR("Nonthrowing constructor threw an exception"); } } @@ -684,7 +692,7 @@ void test_construct_destroy_count() BOOST_CHECK(construction_count == destruction_count); } -int test_main(int, char* []) +int main() { test_zero_args(); test_one_arg(); @@ -693,5 +701,5 @@ int test_main(int, char* []) test_member_functions(); test_ref(); test_construct_destroy_count(); - return 0; + return boost::report_errors(); } diff --git a/test/function_test.cpp b/test/function_test.cpp index 02a60cef..03d6fe0f 100644 --- a/test/function_test.cpp +++ b/test/function_test.cpp @@ -7,12 +7,20 @@ // For more information, see http://www.boost.org -#include +#if defined(__clang__) && defined(__has_warning) +# if __has_warning( "-Wself-assign-overloaded" ) +# pragma clang diagnostic ignored "-Wself-assign-overloaded" +# endif +#endif + #include +#include #include #include #include +#define BOOST_CHECK BOOST_TEST + using boost::function; using std::string; @@ -624,11 +632,22 @@ test_ref() boost::function f(boost::ref(atc)); BOOST_CHECK(f(1, 3) == 4); } - catch(std::runtime_error e) { + catch(std::runtime_error const&) { BOOST_ERROR("Nonthrowing constructor threw an exception"); } } +#if BOOST_WORKAROUND(BOOST_GCC, >= 70000 && BOOST_GCC < 80000) && __cplusplus >= 201700 + +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81311 +#pragma message("Skipping test_empty_ref on g++ 7 -std=c++17") + +static void test_empty_ref() +{ +} + +#else + static void dummy() {} static void test_empty_ref() @@ -640,18 +659,20 @@ static void test_empty_ref() f2(); BOOST_ERROR("Exception didn't throw for reference to empty function."); } - catch(std::runtime_error e) {} + catch(std::runtime_error const&) {} f1 = dummy; try { f2(); } - catch(std::runtime_error e) { + catch(std::runtime_error const&) { BOOST_ERROR("Error calling referenced function."); } } +#endif + static void test_exception() { @@ -660,7 +681,7 @@ static void test_exception() f(5, 4); BOOST_CHECK(false); } - catch(boost::bad_function_call) { + catch(boost::bad_function_call const&) { // okay } } @@ -733,7 +754,6 @@ static void test_move_semantics() BOOST_CHECK(!f1.empty()); BOOST_CHECK(global_int == 1); -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES // Testing rvalue constructors f1_type f2(static_cast(f1)); BOOST_CHECK(f1.empty()); @@ -775,11 +795,9 @@ static void test_move_semantics() BOOST_CHECK(global_int == 5); f4 = static_cast(f5); BOOST_CHECK(global_int == 4); - -#endif } -int test_main(int, char* []) +int main() { test_zero_args(); test_one_arg(); @@ -794,5 +812,5 @@ int test_main(int, char* []) test_move_semantics >(); test_move_semantics >(); - return 0; + return boost::report_errors(); } diff --git a/test/function_test_fail1.cpp b/test/function_test_fail1.cpp index 99c599ca..0b84cc7d 100644 --- a/test/function_test_fail1.cpp +++ b/test/function_test_fail1.cpp @@ -7,22 +7,12 @@ // For more information, see http://www.boost.org -#include #include -using namespace std; -using namespace boost; - -int -test_main(int, char*[]) +void test() { - function0 f1; - function0 f2; - - if (f1 == f2) { - } - - BOOST_ERROR("This should not have compiled."); + boost::function0 f1; + boost::function0 f2; - return 0; + if( f1 == f2 ) {} } diff --git a/test/function_test_fail2.cpp b/test/function_test_fail2.cpp index 57f2d22e..d113e457 100644 --- a/test/function_test_fail2.cpp +++ b/test/function_test_fail2.cpp @@ -7,21 +7,12 @@ // For more information, see http://www.boost.org -#include #include -using namespace std; -using namespace boost; - static int bad_fn(float f) { return static_cast(f); } -int -test_main(int, char*[]) +void test() { - function0 f1; - f1 = bad_fn; - - BOOST_ERROR("This should not have compiled."); - - return 0; + boost::function0 f1; + f1 = bad_fn; } diff --git a/test/issue_42.cpp b/test/issue_42.cpp new file mode 100644 index 00000000..a6985717 --- /dev/null +++ b/test/issue_42.cpp @@ -0,0 +1,21 @@ +// Copyright 2022 Peter Dimov. +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt +// +// https://github.com/boostorg/function/issues/42 + +#include + +struct F +{ + int operator()( int x ) const { return -x; } +}; + +struct X +{ + boost::function f_; + explicit X( boost::function f ): f_( f ) {} +}; + +F f2; +X x( f2 ); // -Wuninitialized under GCC 12 diff --git a/test/issue_53.cpp b/test/issue_53.cpp new file mode 100644 index 00000000..45e00d9a --- /dev/null +++ b/test/issue_53.cpp @@ -0,0 +1,20 @@ +// Copyright 2024 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt +// +// https://github.com/boostorg/function/issues/53 + +#include +#include +#include + +int TestArg( int, double ) +{ + return 0; +} + + +void f() +{ + boost::function fn = boost::bind( &TestArg, boost::placeholders::_1, 1.0 ); +} diff --git a/test/lambda_test.cpp b/test/lambda_test.cpp index 2abca54f..738e876a 100644 --- a/test/lambda_test.cpp +++ b/test/lambda_test.cpp @@ -7,13 +7,13 @@ // For more information, see http://www.boost.org +#include +#include +#include +#include #include #include -#include -#include -#include -#include static unsigned func_impl(int arg1, bool arg2, double arg3) @@ -22,17 +22,19 @@ func_impl(int arg1, bool arg2, double arg3) return abs (static_cast((arg2 ? arg1 : 2 * arg1) * arg3)); } -int test_main(int, char*[]) +int main() { using boost::function; using namespace boost::lambda; function f1 = bind(func_impl, 15, _1, _2); + BOOST_TEST_EQ( f1(true, 2.0), 30u ); + function f2 = boost::lambda::bind(f1, false, _1); - function f3 = boost::lambda::bind(f2, 4.0); + BOOST_TEST_EQ( f2(2.0), 60u ); - f3(); + function f3 = boost::lambda::bind(f2, 4.0); + BOOST_TEST_EQ( f3(), 120u ); - return 0; + return boost::report_errors(); } - diff --git a/test/mem_fun_cxx98.cpp b/test/mem_fun_cxx98.cpp index c2897912..b42cc001 100644 --- a/test/mem_fun_cxx98.cpp +++ b/test/mem_fun_cxx98.cpp @@ -10,13 +10,13 @@ #include -#include +#include #include #include struct Y { Y(int y = 0) : y_(y) {} - bool operator==(const Y& rhs) { return y_ == rhs.y_; } + bool operator==(const Y& rhs) const { return y_ == rhs.y_; } private: int y_; }; diff --git a/test/mem_fun_portable.cpp b/test/mem_fun_portable.cpp index 02513393..0cf1ed4b 100644 --- a/test/mem_fun_portable.cpp +++ b/test/mem_fun_portable.cpp @@ -10,13 +10,13 @@ #include -#include +#include #include #include struct Y { Y(int y = 0) : y_(y) {} - bool operator==(const Y& rhs) { return y_ == rhs.y_; } + bool operator==(const Y& rhs) const { return y_ == rhs.y_; } private: int y_; }; diff --git a/test/mixed_cxxstd.cpp b/test/mixed_cxxstd.cpp new file mode 100644 index 00000000..417037aa --- /dev/null +++ b/test/mixed_cxxstd.cpp @@ -0,0 +1,42 @@ + +// Copyright 2018 Peter Dimov. +// Distributed under the Boost Software License, Version 1.0. + +#include +#include + +#if defined(MIXED_CXXSTD_DYN_LINK) +# define EXPORT BOOST_SYMBOL_EXPORT +#else +# define EXPORT +#endif + +EXPORT void call_fn_1( boost::function const & fn ) +{ + fn(); +} + +EXPORT void call_fn_2( boost::function const & fn ) +{ + fn( 1 ); +} + +EXPORT void call_fn_3( boost::function const & fn ) +{ + fn( 1, 2 ); +} + +EXPORT void call_fn_4( boost::function0 const & fn ) +{ + fn(); +} + +EXPORT void call_fn_5( boost::function1 const & fn ) +{ + fn( 1 ); +} + +EXPORT void call_fn_6( boost::function2 const & fn ) +{ + fn( 1, 2 ); +} diff --git a/test/nothrow_swap.cpp b/test/nothrow_swap.cpp index 0a5b740c..8b1b6dc8 100644 --- a/test/nothrow_swap.cpp +++ b/test/nothrow_swap.cpp @@ -7,8 +7,10 @@ // For more information, see http://www.boost.org -#include #include +#include + +#define BOOST_CHECK BOOST_TEST struct tried_to_copy { }; @@ -40,7 +42,7 @@ struct MaybeThrowOnCopy { bool MaybeThrowOnCopy::throwOnCopy = false; -int test_main(int, char* []) +int main() { boost::function0 f; boost::function0 g; @@ -56,5 +58,5 @@ int test_main(int, char* []) BOOST_CHECK(f() == 2); BOOST_CHECK(g() == 1); - return 0; + return boost::report_errors(); } diff --git a/test/quick.cpp b/test/quick.cpp new file mode 100644 index 00000000..d2d37d06 --- /dev/null +++ b/test/quick.cpp @@ -0,0 +1,21 @@ +// Copyright 2019 Peter Dimov + +// Use, modification and distribution is subject to the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt + +#include +#include + +static int f( int x ) +{ + return x + 1; +} + +int main() +{ + boost::function fn( f ); + + BOOST_TEST_EQ( fn( 5 ), 6 ); + + return boost::report_errors(); +} diff --git a/test/result_arg_n_types_test.cpp b/test/result_arg_n_types_test.cpp new file mode 100644 index 00000000..c7e5780f --- /dev/null +++ b/test/result_arg_n_types_test.cpp @@ -0,0 +1,146 @@ +// Copyright 2024 Peter Dimov +// Use, modification and distribution is subject to +// the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include + +struct R {}; + +struct A1 {}; +struct A2 {}; +struct A3 {}; +struct A4 {}; +struct A5 {}; +struct A6 {}; +struct A7 {}; +struct A8 {}; +struct A9 {}; +struct A10 {}; + +int main() +{ + { + typedef boost::function F; + + BOOST_TEST_TRAIT_SAME(F::result_type, R); + } + + { + typedef boost::function F; + + BOOST_TEST_TRAIT_SAME(F::result_type, R); + BOOST_TEST_TRAIT_SAME(F::arg1_type, A1); + } + + { + typedef boost::function F; + + BOOST_TEST_TRAIT_SAME(F::result_type, R); + BOOST_TEST_TRAIT_SAME(F::arg1_type, A1); + BOOST_TEST_TRAIT_SAME(F::arg2_type, A2); + } + + { + typedef boost::function F; + + BOOST_TEST_TRAIT_SAME(F::result_type, R); + BOOST_TEST_TRAIT_SAME(F::arg1_type, A1); + BOOST_TEST_TRAIT_SAME(F::arg2_type, A2); + BOOST_TEST_TRAIT_SAME(F::arg3_type, A3); + } + + { + typedef boost::function F; + + BOOST_TEST_TRAIT_SAME(F::result_type, R); + BOOST_TEST_TRAIT_SAME(F::arg1_type, A1); + BOOST_TEST_TRAIT_SAME(F::arg2_type, A2); + BOOST_TEST_TRAIT_SAME(F::arg3_type, A3); + BOOST_TEST_TRAIT_SAME(F::arg4_type, A4); + } + + { + typedef boost::function F; + + BOOST_TEST_TRAIT_SAME(F::result_type, R); + BOOST_TEST_TRAIT_SAME(F::arg1_type, A1); + BOOST_TEST_TRAIT_SAME(F::arg2_type, A2); + BOOST_TEST_TRAIT_SAME(F::arg3_type, A3); + BOOST_TEST_TRAIT_SAME(F::arg4_type, A4); + BOOST_TEST_TRAIT_SAME(F::arg5_type, A5); + } + + { + typedef boost::function F; + + BOOST_TEST_TRAIT_SAME(F::result_type, R); + BOOST_TEST_TRAIT_SAME(F::arg1_type, A1); + BOOST_TEST_TRAIT_SAME(F::arg2_type, A2); + BOOST_TEST_TRAIT_SAME(F::arg3_type, A3); + BOOST_TEST_TRAIT_SAME(F::arg4_type, A4); + BOOST_TEST_TRAIT_SAME(F::arg5_type, A5); + BOOST_TEST_TRAIT_SAME(F::arg6_type, A6); + } + + { + typedef boost::function F; + + BOOST_TEST_TRAIT_SAME(F::result_type, R); + BOOST_TEST_TRAIT_SAME(F::arg1_type, A1); + BOOST_TEST_TRAIT_SAME(F::arg2_type, A2); + BOOST_TEST_TRAIT_SAME(F::arg3_type, A3); + BOOST_TEST_TRAIT_SAME(F::arg4_type, A4); + BOOST_TEST_TRAIT_SAME(F::arg5_type, A5); + BOOST_TEST_TRAIT_SAME(F::arg6_type, A6); + BOOST_TEST_TRAIT_SAME(F::arg7_type, A7); + } + + { + typedef boost::function F; + + BOOST_TEST_TRAIT_SAME(F::result_type, R); + BOOST_TEST_TRAIT_SAME(F::arg1_type, A1); + BOOST_TEST_TRAIT_SAME(F::arg2_type, A2); + BOOST_TEST_TRAIT_SAME(F::arg3_type, A3); + BOOST_TEST_TRAIT_SAME(F::arg4_type, A4); + BOOST_TEST_TRAIT_SAME(F::arg5_type, A5); + BOOST_TEST_TRAIT_SAME(F::arg6_type, A6); + BOOST_TEST_TRAIT_SAME(F::arg7_type, A7); + BOOST_TEST_TRAIT_SAME(F::arg8_type, A8); + } + + { + typedef boost::function F; + + BOOST_TEST_TRAIT_SAME(F::result_type, R); + BOOST_TEST_TRAIT_SAME(F::arg1_type, A1); + BOOST_TEST_TRAIT_SAME(F::arg2_type, A2); + BOOST_TEST_TRAIT_SAME(F::arg3_type, A3); + BOOST_TEST_TRAIT_SAME(F::arg4_type, A4); + BOOST_TEST_TRAIT_SAME(F::arg5_type, A5); + BOOST_TEST_TRAIT_SAME(F::arg6_type, A6); + BOOST_TEST_TRAIT_SAME(F::arg7_type, A7); + BOOST_TEST_TRAIT_SAME(F::arg8_type, A8); + BOOST_TEST_TRAIT_SAME(F::arg9_type, A9); + } + + { + typedef boost::function F; + + BOOST_TEST_TRAIT_SAME(F::result_type, R); + BOOST_TEST_TRAIT_SAME(F::arg1_type, A1); + BOOST_TEST_TRAIT_SAME(F::arg2_type, A2); + BOOST_TEST_TRAIT_SAME(F::arg3_type, A3); + BOOST_TEST_TRAIT_SAME(F::arg4_type, A4); + BOOST_TEST_TRAIT_SAME(F::arg5_type, A5); + BOOST_TEST_TRAIT_SAME(F::arg6_type, A6); + BOOST_TEST_TRAIT_SAME(F::arg7_type, A7); + BOOST_TEST_TRAIT_SAME(F::arg8_type, A8); + BOOST_TEST_TRAIT_SAME(F::arg9_type, A9); + BOOST_TEST_TRAIT_SAME(F::arg10_type, A10); + } + + return boost::report_errors(); +} diff --git a/test/result_arg_types_test.cpp b/test/result_arg_types_test.cpp new file mode 100644 index 00000000..9d5aa2c7 --- /dev/null +++ b/test/result_arg_types_test.cpp @@ -0,0 +1,39 @@ +// Boost.Function library + +// Copyright 2016 Peter Dimov + +// Use, modification and distribution is subject to +// the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +struct X +{ +}; + +struct Y +{ +}; + +struct Z +{ +}; + +int main() +{ + typedef boost::function F1; + + BOOST_TEST_TRAIT_SAME(F1::result_type, X); + BOOST_TEST_TRAIT_SAME(F1::argument_type, Y); + + typedef boost::function F2; + + BOOST_TEST_TRAIT_SAME(F2::result_type, X); + BOOST_TEST_TRAIT_SAME(F2::first_argument_type, Y); + BOOST_TEST_TRAIT_SAME(F2::second_argument_type, Z); + + return boost::report_errors(); +} diff --git a/test/return_function.cpp b/test/return_function.cpp new file mode 100644 index 00000000..3fca7bbd --- /dev/null +++ b/test/return_function.cpp @@ -0,0 +1,27 @@ + +// Copyright 2018 Peter Dimov. +// Distributed under the Boost Software License, Version 1.0. + +#include +#include + +#if defined(RETURN_FUNCTION_DYN_LINK) +# define EXPORT BOOST_SYMBOL_EXPORT +#else +# define EXPORT +#endif + +int f( int x, int y ) +{ + return x + y; +} + +EXPORT boost::function get_fn_1() +{ + return f; +} + +EXPORT boost::function2 get_fn_2() +{ + return f; +} diff --git a/test/rvalues_test.cpp b/test/rvalues_test.cpp index 977f4ba7..0d21ec4e 100644 --- a/test/rvalues_test.cpp +++ b/test/rvalues_test.cpp @@ -6,12 +6,13 @@ // For more information, see http://www.boost.org +#include +#include +#include #include #include -#include -#include -#include +#define BOOST_CHECK BOOST_TEST class only_movable { private: @@ -58,12 +59,10 @@ struct sum_struct { } }; -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES int three(std::string&&) { return 1; } std::string&& four(std::string&& s) { return boost::move(s); } -#endif -int test_main(int, char*[]) +int main() { using boost::function; @@ -94,13 +93,11 @@ int test_main(int, char*[]) BOOST_CHECK(om2_sum_2.get_value() == 3); } -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES function f3 = three; function f4 = four; f3(std::string("Hello")); BOOST_CHECK(f4(std::string("world")) == "world"); -#endif - return 0; + return boost::report_errors(); } diff --git a/test/stateless_test.cpp b/test/stateless_test.cpp index 3bc9e457..5ec1b84c 100644 --- a/test/stateless_test.cpp +++ b/test/stateless_test.cpp @@ -7,16 +7,18 @@ // For more information, see http://www.boost.org -#include #include +#include #include +#include struct stateless_integer_add { int operator()(int x, int y) const { return x+y; } - void* operator new(std::size_t) + void* operator new(std::size_t n) { - throw std::runtime_error("Cannot allocate a stateless_integer_add"); + BOOST_ERROR( "stateless_integer_add incorrectly allocated" ); + return ::operator new( n ); } void* operator new(std::size_t, void* p) @@ -24,15 +26,17 @@ struct stateless_integer_add { return p; } - void operator delete(void*) throw() + void operator delete(void* p) throw() { + BOOST_ERROR( "stateless_integer_add incorrectly deallocated" ); + return ::operator delete( p ); } }; -int test_main(int, char*[]) +int main() { boost::function2 f; f = stateless_integer_add(); - return 0; + return boost::report_errors(); } diff --git a/test/std_bind_cxx98.cpp b/test/std_bind_cxx98.cpp index 2d69eb99..ffdf772a 100644 --- a/test/std_bind_cxx98.cpp +++ b/test/std_bind_cxx98.cpp @@ -8,7 +8,16 @@ // For more information, see http://www.boost.org/ - +#if defined(__clang__) && defined(__has_warning) +# if __has_warning( "-Wdeprecated-declarations" ) +# pragma clang diagnostic ignored "-Wdeprecated-declarations" +# endif +#endif + +#if defined(__GNUC__) && __GNUC__ >= 12 +# pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + #include #include #include @@ -20,11 +29,12 @@ int X::foo(int x) { return -x; } int main() { +#ifndef BOOST_NO_CXX98_BINDERS boost::function f; X x; f = std::bind1st( std::mem_fun(&X::foo), &x); f(5); // Call x.foo(5) - +#endif return 0; } diff --git a/test/std_bind_portable.cpp b/test/std_bind_portable.cpp index 339ffa8d..782ae8ad 100644 --- a/test/std_bind_portable.cpp +++ b/test/std_bind_portable.cpp @@ -8,7 +8,16 @@ // For more information, see http://www.boost.org/ - +#if defined(__clang__) && defined(__has_warning) +# if __has_warning( "-Wdeprecated-declarations" ) +# pragma clang diagnostic ignored "-Wdeprecated-declarations" +# endif +#endif + +#if defined(__GNUC__) && __GNUC__ >= 12 +# pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + #include #include #include @@ -20,11 +29,12 @@ int X::foo(int x) { return -x; } int main() { +#ifndef BOOST_NO_CXX98_BINDERS boost::function1 f; X x; f = std::bind1st( std::mem_fun(&X::foo), &x); f(5); // Call x.foo(5) - +#endif return 0; } diff --git a/test/test_bad_function_call.cpp b/test/test_bad_function_call.cpp new file mode 100644 index 00000000..3c88dd39 --- /dev/null +++ b/test/test_bad_function_call.cpp @@ -0,0 +1,14 @@ + +// Copyright 2018 Peter Dimov. +// Distributed under the Boost Software License, Version 1.0. + +#include +#include + +void throw_bad_function_call(); + +int main() +{ + BOOST_TEST_THROWS( throw_bad_function_call(), boost::bad_function_call ); + return boost::report_errors(); +} diff --git a/test/test_mixed_cxxstd.cpp b/test/test_mixed_cxxstd.cpp new file mode 100644 index 00000000..6622ab37 --- /dev/null +++ b/test/test_mixed_cxxstd.cpp @@ -0,0 +1,48 @@ + +// Copyright 2018 Peter Dimov. +// Distributed under the Boost Software License, Version 1.0. + +#include +#include + +// + +void call_fn_1( boost::function const & fn ); +void call_fn_2( boost::function const & fn ); +void call_fn_3( boost::function const & fn ); + +void call_fn_4( boost::function0 const & fn ); +void call_fn_5( boost::function1 const & fn ); +void call_fn_6( boost::function2 const & fn ); + +// + +static int v; + +void f0() +{ + v = -1; +} + +void f1( int x ) +{ + v = x; +} + +void f2( int x, int y ) +{ + v = x + y; +} + +int main() +{ + v = 0; call_fn_1( f0 ); BOOST_TEST_EQ( v, -1 ); + v = 0; call_fn_2( f1 ); BOOST_TEST_EQ( v, 1 ); + v = 0; call_fn_3( f2 ); BOOST_TEST_EQ( v, 3 ); + + v = 0; call_fn_4( f0 ); BOOST_TEST_EQ( v, -1 ); + v = 0; call_fn_5( f1 ); BOOST_TEST_EQ( v, 1 ); + v = 0; call_fn_6( f2 ); BOOST_TEST_EQ( v, 3 ); + + return boost::report_errors(); +} diff --git a/test/test_return_function.cpp b/test/test_return_function.cpp new file mode 100644 index 00000000..05712ed2 --- /dev/null +++ b/test/test_return_function.cpp @@ -0,0 +1,21 @@ + +// Copyright 2018 Peter Dimov. +// Distributed under the Boost Software License, Version 1.0. + +#include +#include + +// + +boost::function get_fn_1(); +boost::function2 get_fn_2(); + +// + +int main() +{ + BOOST_TEST_EQ( get_fn_1()( 1, 2 ), 3 ); + BOOST_TEST_EQ( get_fn_2()( 1, 2 ), 3 ); + + return boost::report_errors(); +} diff --git a/test/throw_bad_function_call.cpp b/test/throw_bad_function_call.cpp new file mode 100644 index 00000000..d6037592 --- /dev/null +++ b/test/throw_bad_function_call.cpp @@ -0,0 +1,17 @@ + +// Copyright 2018 Peter Dimov. +// Distributed under the Boost Software License, Version 1.0. + +#include +#include + +#if defined(THROW_BAD_FUNCTION_CALL_DYN_LINK) +# define EXPORT BOOST_SYMBOL_EXPORT +#else +# define EXPORT +#endif + +EXPORT void throw_bad_function_call() +{ + throw boost::bad_function_call(); +}