2
0
mirror of https://github.com/boostorg/lambda.git synced 2026-01-21 17:02:36 +00:00

Compare commits

..

91 Commits

Author SHA1 Message Date
Jaakko Järvi
aa52de0931 replaced by algorithm.hpp
[SVN r12939]
2002-02-25 22:06:38 +00:00
Jaakko Järvi
b335b7cf30 f
[SVN r12906]
2002-02-22 21:13:29 +00:00
Jaakko Järvi
f54bbdc1a7 added test coverage
[SVN r12904]
2002-02-22 19:43:42 +00:00
Jaakko Järvi
f404313f16 fix
[SVN r12900]
2002-02-22 15:25:15 +00:00
Jaakko Järvi
d86ebf9f1a spacing
[SVN r12899]
2002-02-22 15:24:53 +00:00
Jaakko Järvi
1a698677ad added workarounds for gcc2.96
[SVN r12898]
2002-02-22 15:21:17 +00:00
Jaakko Järvi
b57fe61901 fixed a comment
[SVN r12885]
2002-02-21 22:29:52 +00:00
Jaakko Järvi
1d33face98 removed some extra consts
[SVN r12884]
2002-02-21 22:29:29 +00:00
Jaakko Järvi
e36b3e7c7a removed ;
[SVN r12883]
2002-02-21 22:28:54 +00:00
Jaakko Järvi
ce9d859823 docs in smaller chunks
[SVN r12882]
2002-02-21 22:27:28 +00:00
Jaakko Järvi
9eaab4dbc6 added definitions for logical_action<or/and_action> as KCC needs them
[SVN r12881]
2002-02-21 21:01:28 +00:00
Jaakko Järvi
8e2c7efc1e added test file bll_and_function.cpp
[SVN r12880]
2002-02-21 21:00:31 +00:00
Jaakko Järvi
65fe870596 test file for using boost::function and BLL together
[SVN r12877]
2002-02-21 16:03:12 +00:00
Jaakko Järvi
027c6bf563 changed placheolder typedef names
[SVN r12812]
2002-02-14 20:11:19 +00:00
Jaakko Järvi
02cd3b5453 changed placeholder typedef names
[SVN r12811]
2002-02-14 20:10:52 +00:00
Jaakko Järvi
be8e0e3cd3 progress
[SVN r12809]
2002-02-14 20:09:30 +00:00
Jaakko Järvi
5933a21c2d contains only a small subset of STL algs at this point
[SVN r12789]
2002-02-12 21:54:59 +00:00
Jaakko Järvi
098bdd80c9 still a draft but should now include all sections
[SVN r12788]
2002-02-12 21:53:36 +00:00
Jaakko Järvi
b330716694 nested stl algorithms, for_each and transform for just now
[SVN r12784]
2002-02-11 21:53:26 +00:00
Jaakko Järvi
96bccbf4b7 added #include <iterators>
[SVN r12759]
2002-02-08 15:27:17 +00:00
Jaakko Järvi
11c0b6a2f0 added text for constructors and destructors, fixed a few typos,
added comment about function objects with side-effects in non-modifyin
sequence algorithms like for_each


[SVN r12750]
2002-02-07 22:39:18 +00:00
Jaakko Järvi
af371a4ae0 control construct docs added
[SVN r12734]
2002-02-05 22:26:30 +00:00
Jaakko Järvi
4c1ba44195 bugfix
[SVN r12716]
2002-02-04 23:20:33 +00:00
Jaakko Järvi
93a8e679a7 a draft documentation, still incomplete
[SVN r12714]
2002-02-04 22:32:43 +00:00
Jaakko Järvi
5cd4705a3a reordering
[SVN r12713]
2002-02-04 22:30:58 +00:00
Jaakko Järvi
5659b120aa compile with gcc3.x.x, KCC with edg 2.43.
some files do not compile with gcc2.9x


[SVN r12711]
2002-02-04 21:52:54 +00:00
Jaakko Järvi
e11111073a gcc 2.9{5,6} fail to compile bind calls with function references,
hence created a separate test for that.
bind_test_simple.cpp now does all calls as function pointers


[SVN r12704]
2002-02-04 20:14:32 +00:00
Jaakko Järvi
beadc914b1 changes to make return type deduction extensions easier, fixed --strict
compilation warnings and errors


[SVN r12536]
2002-01-28 16:15:09 +00:00
Jaakko Järvi
276a81f517 Compile and run with gcc3.0.2. and KCC (edg.2.43.1)
[SVN r12535]
2002-01-28 16:13:33 +00:00
Jaakko Järvi
3aeaf08362 comment change
[SVN r12349]
2002-01-18 19:28:10 +00:00
Jaakko Järvi
64b7d3f97a bugfix
[SVN r12321]
2002-01-14 22:44:35 +00:00
Jaakko Järvi
640ab42a5e going forward
[SVN r12320]
2002-01-14 22:44:06 +00:00
Jaakko Järvi
98ca7523d3 added const_parameters
[SVN r12312]
2002-01-14 16:22:35 +00:00
Jaakko Järvi
6a0ab1ad04 added tests for break_const and const_parameters
[SVN r12311]
2002-01-14 16:21:38 +00:00
Jaakko Järvi
1ce4f8fb57 added test for break_const
[SVN r12278]
2002-01-10 22:05:59 +00:00
Jaakko Järvi
fd0c89cdc5 bug fixes to const_incorrect_lambda_functor
[SVN r12277]
2002-01-10 22:05:13 +00:00
Jaakko Järvi
7236002954 removed constify_rvalues as not used anymore
[SVN r12276]
2002-01-10 21:08:37 +00:00
Jaakko Järvi
31390192ee is_instance_of templates moved from detail to lambda.
Added a test to make sure that is_instance_of<...>::value is a compile
time constant


[SVN r12275]
2002-01-10 20:57:26 +00:00
Jaakko Järvi
b13e8f403d some tidying up and more tests
[SVN r12274]
2002-01-10 20:55:12 +00:00
Jaakko Järvi
afaacdc785 a lot of changes:
support for FC++ style sig templates for return type deduction
support for currying lambda functors
proper protect support
if lambda functors are bound, return type deduction works


[SVN r12273]
2002-01-10 20:54:11 +00:00
Jaakko Järvi
682939bf35 tests for currying, protect, unlambda, ...
[SVN r12269]
2002-01-10 18:58:03 +00:00
Jaakko Järvi
be14866425 is_instance_of was moved from detail namespace to boost::lambda
[SVN r12220]
2002-01-04 21:33:48 +00:00
Jaakko Järvi
5789f3d98a moved comma from operator_actions.hpp to actions.hpp
added leftshift_action_no_stream and rightshift_action_no_stream


[SVN r12219]
2002-01-04 21:32:57 +00:00
Jaakko Järvi
286dc4bdd3 all types sent down to return_type_N templates are now references.
This makes it easier to provide user defined specializations.
Added a specialization for comma operator for return_type<> level, as
it is an exception to the above rule.


[SVN r12218]
2002-01-04 21:31:30 +00:00
Jaakko Järvi
2eb62a137d added specializations for subscripting standard containers,
support for << >> with templated streams, plus other small fixes


[SVN r12217]
2002-01-04 21:29:06 +00:00
Jaakko Järvi
006d968e5a implementation now uses is_convertible to deal with bugs in different
compilers


[SVN r12216]
2002-01-04 21:00:10 +00:00
Jaakko Järvi
cd6db4a38c removed lambda_functor_sub as obsolete
[SVN r12182]
2001-12-31 18:31:15 +00:00
Jaakko Järvi
dd50c9ad38 added the ability to copy compatible lambda functors (same aritycode,
same action and compatible argument tuples). Removed lambda_functor_sub,
as it became obsolete


[SVN r12181]
2001-12-31 18:29:40 +00:00
Jaakko Järvi
c2f3f1cf5d changed to use the new boost preprocessor library
[SVN r12180]
2001-12-31 18:26:12 +00:00
Jaakko Järvi
8421704962 some comment changed
[SVN r12179]
2001-12-31 18:23:41 +00:00
Jaakko Järvi
40a8126a62 removed the local copy of preprocessor, as it is now part of boost
[SVN r12176]
2001-12-31 16:30:45 +00:00
Jaakko Järvi
2762e6c8cd minor changes
[SVN r12154]
2001-12-27 15:07:03 +00:00
Jaakko Järvi
4e607bc493 still very much a draft
[SVN r12152]
2001-12-26 21:59:18 +00:00
Jaakko Järvi
3dff7d970d removed some old commented code
[SVN r12151]
2001-12-26 15:42:13 +00:00
Jaakko Järvi
cb2c689df7 added support for protect, unlambda, currying and break_const
[SVN r12139]
2001-12-21 19:28:31 +00:00
Jaakko Järvi
2c8b1949ec added support for protect and currying (lambda functor return types)
[SVN r12138]
2001-12-21 19:27:26 +00:00
Jaakko Järvi
2ef4480a3f added a really old draft of a user's guide. Not ready and not even
correct in many places, don't read yet.


[SVN r12137]
2001-12-21 19:26:25 +00:00
Jaakko Järvi
99260b26b6 added an accompanying example file for users guide
[SVN r12136]
2001-12-21 19:25:13 +00:00
Jaakko Järvi
d52a33ac2a support for currying
[SVN r12135]
2001-12-21 19:22:59 +00:00
Jaakko Järvi
aa715e88d4 return type deduction should not fail now
[SVN r12111]
2001-12-18 16:23:53 +00:00
Jaakko Järvi
1f583d7b3a a test file for member pointer operators
[SVN r12110]
2001-12-18 16:22:54 +00:00
Jaakko Järvi
aef38586e2 adding bind<ret>(...) syntax
[SVN r12095]
2001-12-17 22:44:14 +00:00
Jaakko Järvi
08bdbd1b69 making return type deduction system not to fail at compile time
[SVN r12094]
2001-12-17 22:43:43 +00:00
Jaakko Järvi
d364221497 removed an unneeded definition
[SVN r12093]
2001-12-17 22:41:53 +00:00
Jaakko Järvi
9c7429a513 added bind<ret>(... syntax, trying to make the return type deduction
never to fail at compile time (still not quite there)


[SVN r12092]
2001-12-17 22:40:45 +00:00
Jaakko Järvi
60fc136bfa complete rewrite of member pointer operator
[SVN r12017]
2001-12-11 22:06:07 +00:00
Jaakko Järvi
38e589d0db stylistic changes
[SVN r12016]
2001-12-11 22:04:07 +00:00
Jaakko Järvi
9a8290de00 pointer to member stuff moved into a separate header
[SVN r12015]
2001-12-11 22:03:42 +00:00
Jaakko Järvi
072cd1d47c helper templates for bind lambda functors
[SVN r12014]
2001-12-11 22:02:29 +00:00
Jaakko Järvi
183b3a6445 changed a conflicting macro name
[SVN r11941]
2001-12-05 22:06:10 +00:00
Jaakko Järvi
37833a292d moved member_ptr return type deductions to member_ptr.hpp
[SVN r11939]
2001-12-05 21:50:46 +00:00
Jaakko Järvi
cc91943c2e moved member pointer action class to member_ptr.hpp
[SVN r11938]
2001-12-05 21:48:33 +00:00
Jaakko Järvi
d36cab6276 moved member_ptr_action to another file
[SVN r11936]
2001-12-05 21:44:00 +00:00
Jaakko Järvi
5018d11428 removed unnecessary using declaration
[SVN r11881]
2001-12-03 21:13:34 +00:00
Jaakko Järvi
0b81a44df5 added some helper traits to make lambda functor types shorter
[SVN r11765]
2001-11-21 22:04:37 +00:00
Jaakko Järvi
41d84d6c08 changed the include order
[SVN r11764]
2001-11-21 22:03:17 +00:00
Jaakko Järvi
621887af2b one test function wasn't called at all
[SVN r11763]
2001-11-21 22:00:36 +00:00
Jaakko Järvi
87b9c4f66d added ll_sizeof tests
[SVN r11750]
2001-11-20 22:03:25 +00:00
Jaakko Järvi
347cfc8436 added ll_sizeof to casts.hpp
[SVN r11749]
2001-11-20 22:02:04 +00:00
Jaakko Järvi
b456eaf07c all the stuff moved to other files
[SVN r11745]
2001-11-20 17:04:06 +00:00
Jaakko Järvi
242c5c8127 typo in comments, added copyright
[SVN r11744]
2001-11-20 16:17:34 +00:00
Jaakko Järvi
cb21ef5863 removed a testing function
[SVN r11742]
2001-11-19 22:30:04 +00:00
Jaakko Järvi
7dd0e88f2b RET static -> static RET
[SVN r11735]
2001-11-19 22:11:10 +00:00
Jaakko Järvi
273f83d01d added missing typenames to avoid errors in strict mode
[SVN r11734]
2001-11-19 22:09:44 +00:00
Jaakko Järvi
4d49196c48 removed weird linebreaks
[SVN r11733]
2001-11-19 22:09:01 +00:00
Jaakko Järvi
bcc486c8e6 lambda_development branch activites
[SVN r11714]
2001-11-15 21:20:43 +00:00
Jaakko Järvi
d6af6a54fd creating the lambda_development branch
[SVN r11713]
2001-11-15 21:18:10 +00:00
Jaakko Järvi
5d37469865 removed a dummy file
[SVN r11712]
2001-11-15 21:04:44 +00:00
Jaakko Järvi
b376ba2fcf lambda_development branch creation
[SVN r11711]
2001-11-15 20:47:16 +00:00
nobody
e6525e8694 This commit was manufactured by cvs2svn to create branch
'lambda_development'.

[SVN r11710]
2001-11-15 20:42:38 +00:00
Jaakko Järvi
44ae5a9a80 lambda_development branch creation
[SVN r11708]
2001-11-15 20:38:57 +00:00
88 changed files with 9414 additions and 16572 deletions

View File

@@ -1,635 +0,0 @@
name: CI
on:
pull_request:
push:
branches:
- master
- develop
- feature/**
env:
UBSAN_OPTIONS: print_stacktrace=1
jobs:
posix:
strategy:
fail-fast: false
matrix:
include:
- toolset: gcc-4.8
cxxstd: "11"
os: ubuntu-latest
container: ubuntu:18.04
install: g++-4.8
- toolset: gcc-5
cxxstd: "11,14,1z"
os: ubuntu-latest
container: ubuntu:18.04
install: g++-5
- toolset: gcc-6
cxxstd: "11,14,1z"
os: ubuntu-latest
container: ubuntu:18.04
install: g++-6
- toolset: gcc-7
cxxstd: "11,14,17"
os: ubuntu-20.04
install: g++-7
- toolset: gcc-8
cxxstd: "11,14,17,2a"
os: ubuntu-20.04
install: g++-8
- toolset: gcc-9
cxxstd: "11,14,17,2a"
os: ubuntu-20.04
- toolset: gcc-10
cxxstd: "11,14,17,2a"
os: ubuntu-20.04
install: g++-10
- toolset: gcc-11
cxxstd: "11,14,17,2a"
os: ubuntu-22.04
- toolset: gcc-12
cxxstd: "11,14,17,20,2b"
os: ubuntu-22.04
install: g++-12
- toolset: gcc-13
cxxstd: "11,14,17,20,2b"
container: ubuntu:24.04
os: ubuntu-latest
install: g++-13
- toolset: gcc-14
cxxstd: "11,14,17,20,2b"
container: ubuntu:24.04
os: ubuntu-latest
install: g++-14
- toolset: clang
compiler: clang++-3.9
cxxstd: "11,14"
os: ubuntu-latest
container: ubuntu:18.04
install: clang-3.9
- toolset: clang
compiler: clang++-4.0
cxxstd: "11,14"
os: ubuntu-latest
container: ubuntu:18.04
install: clang-4.0
- toolset: clang
compiler: clang++-5.0
cxxstd: "11,14,1z"
os: ubuntu-latest
container: ubuntu:18.04
install: clang-5.0
- toolset: clang
compiler: clang++-6.0
cxxstd: "11,14,17"
os: ubuntu-20.04
install: clang-6.0
- toolset: clang
compiler: clang++-7
cxxstd: "11,14,17"
os: ubuntu-20.04
install: clang-7
- toolset: clang
compiler: clang++-8
cxxstd: "11,14,17"
os: ubuntu-20.04
install: clang-8
- toolset: clang
compiler: clang++-9
cxxstd: "11,14,17,2a"
os: ubuntu-20.04
install: clang-9
- toolset: clang
compiler: clang++-10
cxxstd: "11,14,17,2a"
os: ubuntu-20.04
install: clang-10
- toolset: clang
compiler: clang++-11
cxxstd: "11,14,17,2a"
os: ubuntu-20.04
install: clang-11
- toolset: clang
compiler: clang++-12
cxxstd: "11,14,17,2a"
os: ubuntu-20.04
install: clang-12
- toolset: clang
compiler: clang++-13
cxxstd: "11,14,17,20,2b"
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
cxxstd: "11,14,17,20,2b"
os: macos-13
- toolset: clang
cxxstd: "11,14,17,20,2b"
os: macos-14
- toolset: clang
cxxstd: "11,14,17,20,2b"
os: macos-15
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 --git_args "--jobs 3" $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
STDLIB=${{matrix.stdlib}}
./b2 -j3 libs/$LIBRARY/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} variant=debug,release ${STDLIB:+stdlib=$STDLIB}
windows:
strategy:
fail-fast: false
matrix:
include:
- toolset: msvc-14.0
cxxstd: "14,latest"
addrmd: 32,64
os: windows-2019
- toolset: msvc-14.2
cxxstd: "14,17,20,latest"
addrmd: 32,64
os: windows-2019
- toolset: msvc-14.3
cxxstd: "14,17,20,latest"
addrmd: 32,64
os: windows-2022
- toolset: clang-win
cxxstd: "14,17,latest"
addrmd: 32,64
os: windows-2022
- toolset: gcc
cxxstd: "11,14,17,2a"
addrmd: 64
os: windows-2019
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
posix-cmake-subdir:
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-20.04
- os: ubuntu-22.04
- os: ubuntu-24.04
- os: macos-13
- os: macos-14
- os: macos-15
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v4
- name: Install packages
if: matrix.install
run: sudo apt install ${{matrix.install}}
- name: Setup Boost
run: |
echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY
LIBRARY=${GITHUB_REPOSITORY#*/}
echo LIBRARY: $LIBRARY
echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV
echo GITHUB_BASE_REF: $GITHUB_BASE_REF
echo GITHUB_REF: $GITHUB_REF
REF=${GITHUB_BASE_REF:-$GITHUB_REF}
REF=${REF#refs/heads/}
echo REF: $REF
BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true
echo BOOST_BRANCH: $BOOST_BRANCH
cd ..
git clone -b $BOOST_BRANCH --depth 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-20.04
- os: ubuntu-22.04
- os: ubuntu-24.04
- os: macos-13
- os: macos-14
- os: macos-15
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v4
- name: Install packages
if: matrix.install
run: sudo apt install ${{matrix.install}}
- name: Setup Boost
run: |
echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY
LIBRARY=${GITHUB_REPOSITORY#*/}
echo LIBRARY: $LIBRARY
echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV
echo GITHUB_BASE_REF: $GITHUB_BASE_REF
echo GITHUB_REF: $GITHUB_REF
REF=${GITHUB_BASE_REF:-$GITHUB_REF}
REF=${REF#refs/heads/}
echo REF: $REF
BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true
echo BOOST_BRANCH: $BOOST_BRANCH
cd ..
git clone -b $BOOST_BRANCH --depth 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-20.04
- os: ubuntu-22.04
- os: ubuntu-24.04
- os: macos-13
- os: macos-14
- os: macos-15
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v4
- name: Install packages
if: matrix.install
run: sudo apt install ${{matrix.install}}
- name: Setup Boost
run: |
echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY
LIBRARY=${GITHUB_REPOSITORY#*/}
echo LIBRARY: $LIBRARY
echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV
echo GITHUB_BASE_REF: $GITHUB_BASE_REF
echo GITHUB_REF: $GITHUB_REF
REF=${GITHUB_BASE_REF:-$GITHUB_REF}
REF=${REF#refs/heads/}
echo REF: $REF
BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true
echo BOOST_BRANCH: $BOOST_BRANCH
cd ..
git clone -b $BOOST_BRANCH --depth 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-2019
- 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%
- 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-2019
- 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%
- 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-2019
- 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%
- 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

View File

@@ -1,163 +0,0 @@
# Copyright 2016 Edward Diener
# Copyright 2016, 2017, 2021 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
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.8
env: TOOLSET=gcc CXXSTD=03,11
addons:
apt:
packages:
- g++-4.8
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-5
env: TOOLSET=gcc CXXSTD=03,11,14
addons:
apt:
packages:
- g++-5
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++-9
env: TOOLSET=gcc CXXSTD=03,11,14,17
addons:
apt:
packages:
- g++-9
sources:
- ubuntu-toolchain-r-test
- os: linux
dist: bionic
compiler: g++-10
env: TOOLSET=gcc CXXSTD=03,11,14,17,2a
addons:
apt:
packages:
- g++-10
sources:
- sourceline: "ppa:ubuntu-toolchain-r/test"
- os: linux
dist: bionic
compiler: g++-11
env: UBSAN=1 TOOLSET=gcc CXXSTD=03,11,14,17,20 UBSAN_OPTIONS=print_stacktrace=1 LINKFLAGS=-fuse-ld=gold
addons:
apt:
packages:
- g++-11
sources:
- sourceline: "ppa:ubuntu-toolchain-r/test"
- os: linux
compiler: clang++-11
env: TOOLSET=clang CXXSTD=03,11,14,17,20
addons:
apt:
packages:
- clang-11
sources:
- ubuntu-toolchain-r-test
- sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-11 main'
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
- os: linux
compiler: clang++-12
env: UBSAN=1 TOOLSET=clang CXXSTD=03,11,14,17,20 UBSAN_OPTIONS=print_stacktrace=1
addons:
apt:
packages:
- clang-12
sources:
- ubuntu-toolchain-r-test
- sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-12 main'
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
- os: linux
dist: bionic
compiler: clang++-libc++
env: TOOLSET=clang CXXSTD=03,11,14,17,2a
addons:
apt:
packages:
- libc++-dev
- os: osx
compiler: clang++
env: UBSAN=1 TOOLSET=clang CXXSTD=03,11,14,1z UBSAN_OPTIONS=print_stacktrace=1
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/lambda
- python tools/boostdep/depinst/depinst.py lambda
- ./bootstrap.sh
- ./b2 headers
script:
- |-
echo "using $TOOLSET : : $TRAVIS_COMPILER ;" > ~/user-config.jam
- ./b2 -j3 libs/lambda/test toolset=$TOOLSET cxxstd=$CXXSTD variant=debug,release ${UBSAN:+cxxflags=-fsanitize=undefined cxxflags=-fno-sanitize-recover=undefined linkflags=-fsanitize=undefined define=UBSAN=1 debug-symbols=on} ${LINKFLAGS:+linkflags=$LINKFLAGS}
notifications:
email:
on_success: always

View File

@@ -1,34 +0,0 @@
# Generated by `boostdep --cmake lambda`
# Copyright 2020 Peter Dimov
# Distributed under the Boost Software License, Version 1.0.
# https://www.boost.org/LICENSE_1_0.txt
cmake_minimum_required(VERSION 3.5...3.16)
project(boost_lambda VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX)
add_library(boost_lambda INTERFACE)
add_library(Boost::lambda ALIAS boost_lambda)
target_include_directories(boost_lambda INTERFACE include)
target_link_libraries(boost_lambda
INTERFACE
Boost::bind
Boost::config
Boost::core
Boost::detail
Boost::iterator
Boost::mpl
Boost::preprocessor
Boost::tuple
Boost::type_traits
Boost::utility
)
if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt")
add_subdirectory(test)
endif()

View File

@@ -1,46 +0,0 @@
# Copyright 2016-2021 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-14.0
ADDRMD: 32,64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
TOOLSET: msvc-14.1
CXXSTD: 14,17,latest
ADDRMD: 32,64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
TOOLSET: clang-win
CXXSTD: 14,17,latest
ADDRMD: 32,64
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\lambda\
- python tools/boostdep/depinst/depinst.py lambda
- cmd /c bootstrap
- b2 -d0 headers
build: off
test_script:
- if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD%
- if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD%
- b2 -j3 libs/lambda/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release embed-manifest-via=linker

View File

@@ -1,21 +0,0 @@
project lambda/doc ;
import boostbook : boostbook ;
# Are these really the correct images??
path-constant images : ../../spirit/phoenix/doc/html ;
boostbook lambda-doc : lambda.xml
:
<xsl:param>boost.root=../../../..
<format>pdf:<xsl:param>img.src.path=$(images)/
;
###############################################################################
alias boostdoc
: lambda.xml
:
:
: ;
explicit boostdoc ;
alias boostrelease ;
explicit boostrelease ;

53
doc/ar01s02.html Normal file
View File

@@ -0,0 +1,53 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head><meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type"><title>2. Getting Started</title><meta name="generator" content="DocBook XSL Stylesheets V1.48"><link rel="home" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="up" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="previous" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="next" href="ar01s03.html" title="3. Introduction"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">2. Getting Started</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="index.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="ar01s03.html">Next</a></td></tr></table><hr></div><div class="section"><div class="titlepage"><div><h2 class="title" style="clear: both"><a name="sect:getting_started"></a>2. Getting Started</h2></div></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="id2790112"></a>2.1. Installing the library</h3></div></div><p>
The library consists of include files only, hence there is no
installation procedure. The <tt>boost</tt> include directory
must be on the include path.
There are a number of include files that give different functionality:
<div class="itemizedlist"><ul type="disc"><li><p>
<tt>lambda/lambda.hpp</tt> defines lambda expressions for different C++
operators, see <a href="ar01s05.html#sect:operator_expressions" title="5.2. Operator expressions">Section 5.2</a>.
</p></li><li><p>
<tt>lambda/bind.hpp</tt> defines <tt>bind</tt> functions for up to 9 arguments, see <a href="ar01s05.html#sect:bind_expressions" title="5.3. Bind expressions">Section 5.3</a>.</p></li><li><p>
<tt>lambda/control_constructs.hpp</tt> defines lambda function equivalents for the control constructs in C++, see <a href="ar01s05.html#sect:lambda_expressions_for_control_structures" title="5.6. Lambda expressions for control structures">Section 5.6</a> (includes <tt>lambda.hpp</tt>).
</p></li><li><p>
<tt>lambda/construct.hpp</tt> provides tools for writing lambda expressions with constructor, destructor, new and delete invocations, see <a href="ar01s05.html#sect:construction_and_destruction" title="5.8. Construction and destruction">Section 5.8</a> (includes <tt>lambda.hpp</tt>).
</p></li><li><p>
<tt>lambda/casts.hpp</tt> provides lambda versions of different casts, as well as <tt>sizeof</tt> and <tt>typeid</tt>, see <a href="ar01s05.html#sect:cast_expressions" title="5.10.1.
Cast expressions
">Section 5.10.1</a>.
</p></li><li><p>
<tt>lambda/exceptions.hpp</tt> gives tools for throwing and catching
exceptions within lambda functions, <a href="ar01s05.html#sect:exceptions" title="5.7. Exceptions">Section 5.7</a> (includes
<tt>lambda.hpp</tt>).
</p></li><li><p>
<tt>lambda/algorithm.hpp</tt> allows nested STL algorithm invocations, see <a href="ar01s05.html#sect:nested_stl_algorithms" title="5.11. Nesting STL algorithm invocations">Section 5.11</a>.
</p></li></ul></div>
Any other header files in the package are for internal use.
Additionally, the library depends on two other Boost Libraries, the
<span class="emphasis"><i>Tuple</i></span> [<a href="bi01.html#cit:boost::tuple" title="[tuple]">tuple</a>] and the <span class="emphasis"><i>type_traits</i></span> [<a href="bi01.html#cit:boost::type_traits" title="[type_traits]">type_traits</a>] libraries, and on the <tt>boost/ref.hpp</tt> header.
</p><p>
All definitions are placed in the namespace <tt>boost::lambda</tt> and its subnamespaces.
</p></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="id2742926"></a>2.2. Conventions used in this document</h3></div></div><p>In most code examples, we omit the namespace prefixes for names in the <tt>std</tt> and <tt>boost::lambda</tt> namespaces.
Implicit using declarations
<pre class="programlisting">
using namespace std;
using namespace boost::lambda;
</pre>
are assumed to be in effect.
</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="index.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="index.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="ar01s03.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">
C++ BOOST
The Boost Lambda Library </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> 3. Introduction</td></tr></table></div></body></html>

180
doc/ar01s03.html Normal file
View File

@@ -0,0 +1,180 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head><meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type"><title>3. Introduction</title><meta name="generator" content="DocBook XSL Stylesheets V1.48"><link rel="home" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="up" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="previous" href="ar01s02.html" title="2. Getting Started"><link rel="next" href="ar01s04.html" title="4. Using the library"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">3. Introduction</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ar01s02.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="ar01s04.html">Next</a></td></tr></table><hr></div><div class="section"><div class="titlepage"><div><h2 class="title" style="clear: both"><a name="id2742973"></a>3. Introduction</h2></div></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="id2742980"></a>3.1. Motivation</h3></div></div><p>The Standard Template Library (STL)
[<a href="bi01.html#cit:stepanov:94" title="[STL94]">STL94</a>], now part of the C++ Standard Library [<a href="bi01.html#cit:c++:98" title="[C++98]">C++98</a>], is a generic container and algorithm library.
Typically STL algorithms operate on container elements via <span class="emphasis"><i>function objects</i></span>. These function objects are passed as arguments to the algorithms.
</p><p>
Any C++ construct that can be called with the function call syntax
is a function object.
The STL contains predefined function objects for some common cases (such as <tt>plus</tt>, <tt>less</tt> and <tt>not1</tt>).
As an example, one possible implementation for the standard <tt>plus</tt> template is:
<pre class="programlisting">
template &lt;class T&gt; : public binary_function&lt;T, T, T&gt;
struct plus {
T operator()(const T&amp; i, const T&amp; j) const {
return i + j;
}
};
</pre>
The base class <tt>binary_function&lt;T, T, T&gt;</tt> contains typedefs for the argument and return types of the function object, which are needed to make the function object <span class="emphasis"><i>adaptable</i></span>.
</p><p>
In addition to the basic function object classes, such as the one above,
the STL contains <span class="emphasis"><i>binder</i></span> templates for creating a unary function object from an adaptable binary function object by fixing one of the arguments to a constant value.
For example, instead of having to explicitly write a function object class like:
<pre class="programlisting">
class plus_1 {
int _i;
public:
plus_1(const int&amp; i) : _i(i) {}
int operator(const int&amp; j) { return i + j; }
};
</pre>
the equivalent functionality can be achieved with the <tt>plus</tt> template and one of the binder templates (<tt>bind1st</tt>).
E.g., the following two expressions create function objects with identical functionalities;
when invoked, both return the result of adding <tt>1</tt> to the argument of the function object:
<pre class="programlisting">
plus_1(1)
bind1st(plus&lt;int&gt;(), 1)
</pre>
The subexpression <tt>plus&lt;int&gt;()</tt> in the latter line is a binary function object which computes the sum of two integers, and <tt>bind1st</tt> invokes this function object partially binding the first argument to <tt>1</tt>.
As an example of using the above function object, the following code adds <tt>1</tt> to each element of some container <tt>a</tt> and outputs the results into the standard output stream <tt>cout</tt>.
<pre class="programlisting">
transform(a.begin(), a.end(), ostream_iterator&lt;int&gt;(cout),
bind1st(plus&lt;int&gt;(), 1));
</pre>
</p><p>
To make the binder templates more generally applicable, the STL contains <span class="emphasis"><i>adaptors</i></span> for making
pointers or references to functions, and pointers to member functions,
adaptable.
Finally, some STL implementations contain function composition operations as
extensions to the standard [<a href="bi01.html#cit:sgi:02" title="[SGI02]">SGI02</a>].
</p><p>
All these tools aim at one goal: to make it possible to specify
<span class="emphasis"><i>unnamed functions</i></span> in a call of an STL algorithm,
in other words, to pass code fragments as an argument to a function.
However, this goal is attained only partially.
The simple example above shows that the definition of unnamed functions
with the standard tools is cumbersome.
Complex expressions involving functors, adaptors, binders and
function composition operations tend to be difficult to comprehend.
In addition to this, there are significant restrictions in applying
the standard tools. E.g. the standard binders allow only one argument
of a binary function to be bound; there are no binders for
3-ary, 4-ary etc. functions.
</p><p>
The Boost Lambda Library provides solutions for the problems described above:
<div class="itemizedlist"><ul type="disc"><li><p>
Unnamed functions can be created easily with an intuitive syntax.
The above example can be written as:
<pre class="programlisting">
transform(a.begin(), a.end(), ostream_iterator&lt;int&gt;(cout),
1 + _1);
</pre>
or even more intuitively:
<pre class="programlisting">
for_each(a.begin(), a.end(), cout &lt;&lt; (1 + _1));
</pre>
</p></li><li><p>
Most of the restrictions in argument binding are removed,
arbitrary arguments of practically any C++ function can be bound.
</p></li><li><p>
Separate function composition operations are not needed,
as function composition is supported implicitly.
</p></li></ul></div>
</p></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="id2741408"></a>3.2. Introduction to lambda expressions</h3></div></div><p>
Lambda expression are common in functional programming languages.
Their syntax varies between languages (and between different forms of lambda calculus), but the basic form of a lambda expressions is:
<pre class="programlisting">
lambda x<sub>1</sub> ... x<sub>n</sub>.e
</pre>
A lambda expression defines an unnamed function and consists of:
<div class="itemizedlist"><ul type="disc"><li><p>
the parameters of this function: <tt>x<sub>1</sub> ... x<sub>n</sub></tt>.
</p></li><li><p>the expression e which computes the value of the function in terms of the parameters <tt>x<sub>1</sub> ... x<sub>n</sub></tt>.
</p></li></ul></div>
A simple example of a lambda expression is
<pre class="programlisting">
lambda x y.x+y
</pre>
Applying the lambda function means substituting the formal parameters with the actual arguments:
<pre class="programlisting">
(lambda x y.x+y) 2 3 = 2 + 3 = 5
</pre>
</p><p>
In the C++ version of lambda expressions the <tt>lambda x<sub>1</sub> ... x<sub>n</sub></tt> part is missing and the formal parameters have predefined names.
There are three such predefined formal parameters, called <span class="emphasis"><i>placeholders</i></span>: <tt>_1</tt>, <tt>_2</tt> and <tt>_3</tt>.
They refer to the first, second and third argument of the function defined by the lambda expression.
For example, the C++ version of the definition
<pre class="programlisting">lambda x y.x+y</pre>
is
<pre class="programlisting">_1 + _2</pre>
</p><p>
Hence, there is no syntactic keyword for C++ lambda expressions.
The use of a placeholder as an operand implies that the operator invocation is a lambda expression.
However, this is true only for operator invocations.
Lambda expressions containing function calls, control structures, casts etc. require special syntactic constructs.
Most importantly, function calls need to be wrapped inside a <tt>bind</tt> function.
As an example, consider the lambda expression:
<pre class="programlisting">lambda x y.foo(x,y)</pre>
Rather than <tt>foo(_1, _2)</tt>, the C++ counterpart for this expression is:
<pre class="programlisting">bind(foo, _1, _2)</pre>
We refer to this type of C++ lambda expressions as <span class="emphasis"><i>bind expressions</i></span>.
</p><p>A lambda expression defines a C++ function object, hence function application syntax is like calling any other function object, for instance: <tt>(_1 + _2)(i, j)</tt>.
</p><div class="section"><div class="titlepage"><div><h4 class="title"><a name="sect:partial_function_application"></a>3.2.1. Partial function application</h4></div></div><p>
A bind expression is in effect a <span class="emphasis"><i>partial function application</i></span>.
In partial function application, some of the arguments of a function are bound to fixed values.
The result is another function, with possibly fewer arguments.
When called with the unbound arguments, this new function invokes the original function with the merged argument list of bound and unbound arguments.
</p></div><div class="section"><div class="titlepage"><div><h4 class="title"><a name="sect:currying_intro"></a>3.2.2. Currying</h4></div></div><p>
A related concept to partial function application is <span class="emphasis"><i>currying</i></span>.
Any function of n arguments can be considered
as a function of one argument which returns another function of n-1 arguments.
Taking the above function application example, and considering the lambda expression as a curried function, the application sequence becomes:
<pre class="programlisting">
(lambda x y.x+y) 2 3 = (lambda y.2+y) 3 = 2 + 3 = 5
</pre>
The <a href="ar01s05.html#sect:currying" title="5.1.1. Currying">Section 5.1.1</a> describes how currying is supported in BLL.
</p></div><div class="section"><div class="titlepage"><div><h4 class="title"><a name="sect:terminology"></a>3.2.3. Terminology</h4></div></div><p>
A lambda expression defines a function. A C++ lambda expression concretely constructs a function object, <span class="emphasis"><i>a functor</i></span>, when evaluated. We use the name <span class="emphasis"><i>lambda functor</i></span> to refer to such a function object.
Hence, in the terminology adopted here, the result of evaluating a lambda expression is a lambda functor.
</p></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ar01s02.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="index.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="ar01s04.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">2. Getting Started </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> 4. Using the library</td></tr></table></div></body></html>

164
doc/ar01s04.html Normal file
View File

@@ -0,0 +1,164 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head><meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type"><title>4. Using the library</title><meta name="generator" content="DocBook XSL Stylesheets V1.48"><link rel="home" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="up" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="previous" href="ar01s03.html" title="3. Introduction"><link rel="next" href="ar01s05.html" title="5. Lambda expressions in details"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">4. Using the library</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ar01s03.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="ar01s05.html">Next</a></td></tr></table><hr></div><div class="section"><div class="titlepage"><div><h2 class="title" style="clear: both"><a name="sect:using_library"></a>4. Using the library</h2></div></div><p>
The purpose of this section is to introduce the basic functionality of the library.
There are quite a lot of exceptions and special cases, but discussion of them is postponed until later sections.
</p><div class="section"><div class="titlepage"><div><h3 class="title"><a name="sect:introductory_examples"></a>4.1. Introductory Examples</h3></div></div><p>
In this section we give basic examples of using BLL lambda expressions in STL algorithm invocations.
We start with some simple expressions and work up.
First, we initialize the elements of a container, say, a <tt>list</tt>, to the value <tt>1</tt>:
<pre class="programlisting">
list&lt;int&gt; v(10);
for_each(v.begin(), v.end(), _1 = 1);</pre>
The expression <tt>_1 = 1</tt> creates a lambda functor which assigns the value <tt>1</tt> to every element in <tt>v</tt>.<sup>[<a name="id2739690" href="#ftn.id2739690">1</a>]</sup>
</p><p>
Next, we create a container of pointers and make them point to the elements in the first container <tt>v</tt>:
<pre class="programlisting">
list&lt;int*&gt; vp(10);
transform(v.begin(), v.end(), vp.begin(), &amp;_1);</pre>
The expression <tt>&amp;_1</tt> creates a function object for getting the address of each element in <tt>v</tt>.
The addresses get assigned to the corresponding elements in <tt>vp</tt>.
</p><p>
The next code fragment changes the values in <tt>v</tt>.
For each element, the function <tt>foo</tt> is called.
The original value of the element is passed as an argument to <tt>foo</tt>.
The result of <tt>foo</tt> is assigned back to the element:
<pre class="programlisting">
int foo(int);
for_each(v.begin(), v.end(), _1 = bind(foo, _1));</pre>
</p><p>
The next step is to sort the elements of <tt>vp</tt>:
<pre class="programlisting">sort(vp.begin(), vp.end(), *_1 &gt; *_2);</pre>
In this call to <tt>sort</tt>, we are sorting the elements by their contents in descending order.
</p><p>
Finally, the following <tt>for_each</tt> call outputs the sorted content of <tt>vp</tt> separated by line breaks:
<pre class="programlisting">
for_each(vp.begin(), vp.end(), cout &lt;&lt; *_1 &lt;&lt; '\n');
</pre>
Note that a normal (non-lambda) expression as subexpression of a lambda expression is evaluated immediately.
This may cause surprises.
For instance, if the previous example is rewritten as
<pre class="programlisting">
for_each(vp.begin(), vp.end(), cout &lt;&lt; '\n' &lt;&lt; *_1);
</pre>
the subexpression <tt>cout &lt;&lt; '\n'</tt> is evaluated immediately and the effect is to output a single line break, followed by the elements of <tt>vp</tt>.
The BLL provides functions <tt>constant</tt> and <tt>var</tt> to turn constants and, resepectively, variables into lambda expressions, and can be used to prevent the immediate evaluation of subexpressions:
<pre class="programlisting">
for_each(vp.begin(), vp.end(), cout &lt;&lt; constant('\n') &lt;&lt; *_1);
</pre>
These functions are described more thoroughly in <a href="ar01s05.html#sect:delaying_constants_and_variables" title="5.5. Delaying constants and variables">Section 5.5</a>
</p></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="sect:parameter_and_return_types"></a>4.2. Parameter and return types of lambda functors</h3></div></div><p>
During the invocation of a lambda functor, the actual arguments are substituted for the placeholders.
The placeholders do not dictate the type of these actual arguments.
The basic rule is that a lambda function can be called with arguments of any types, as long as the lambda expression with substitutions performed is a valid C++ expression.
As an example, the expression
<tt>_1 + _2</tt> creates a binary lambda functor.
It can be called with two objects of any types <tt>A</tt> and <tt>B</tt> for which <tt>operator+(A,B)</tt> is defined (and for which BLL knows the return type of the operator, see below).
</p><p>
C++ lacks a mechanism to query a type of an expression.
However, this precise mechanism is crucial for the implementation of C++ lambda expressions.
Consequently, BLL includes a somewhat complex type deduction system which uses a set of traits classes for deducing the resulting type of lambda functions.
It handles expressions where the operands are of built-in types and many of the expressions with operands of standard library types.
Many of the user defined types are covered as well, particularly if the user defined operators obey normal conventions in defining the return types.
</p><p>
There are, however, cases when the return type cannot be deduced. For example, suppose you have defined:
<pre class="programlisting">C operator+(A, B);</pre>
The following lambda function invocation fails, since the return type cannot be deduced:
<pre class="programlisting">A a; B b; (_1 + _2)(a, b);</pre>
</p><p>
There are two alternative solutions to this.
The first is to extend the BLL type deduction system to cover your own types (see <a href="ar01s06.html#sect:extending_return_type_system" title="6. Extending return type deduction system">Section 6</a>).
The second is to use a special lambda expression (<tt>ret</tt>) which defines the return type in place (see <a href="ar01s05.html#sect:overriding_deduced_return_type" title="5.4. Overriding the deduced return type">Section 5.4</a>):
<pre class="programlisting">A a; B b; ret&lt;C&gt;(_1 + _2)(a, b);</pre>
</p><p>
For bind expressions, the return type can be defined as a template argument of the bind function as well:
<pre class="programlisting">bind&lt;int&gt;(foo, _1, _2);</pre>
</p></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="sect:actual_arguments_to_lambda_functors"></a>4.3. About actual arguments to lambda functors</h3></div></div><p>A general restriction for the actual arguments is that they cannot be non-const rvalues.
For example:
<pre class="programlisting">
int i = 1; int j = 2;
(_1 + _2)(i, j); // ok
(_1 + _2)(1, 2); // error (!)
</pre>
This restriction is not as bad as it may look.
Since the lambda functors are most often called inside STL-algorithms,
the arguments originate from dereferencing iterators and the dereferencing operators seldom return rvalues.
And for the cases where they do, there are workarounds discussed in
<a href="ar01s05.html#sect:rvalues_as_actual_arguments" title="5.9.2. Rvalues as actual arguments to lambda functors">Section 5.9.2</a>.
</p></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="sect:storing_bound_arguments"></a>4.4. Storing bound arguments in lambda functions</h3></div></div><p>
The lambda function stores the bound arguments in a tuple object [<a href="bi01.html#cit:boost::tuple" title="[tuple]">tuple</a>].
By default, temporary const copies of the arguments are stored.
This means that the value of a bound argument is fixed at the time of the creation of the lambda function and remains constant during the lifetime of the lambda function object.
For example:
<pre class="programlisting">
int i = 1;
(_1 + i)(i = 2);
</pre>
The value of the expression in the last line is 3, not 4.
In other words, the lambda expression <tt>_1 + i</tt> creates a lambda function <tt>lambda x.x+1</tt> rather than <tt>lambda x.x+i</tt>.
</p><p>As said, this is the default behavior for which there are exceptions.
The exact rules are as follows:
<div class="itemizedlist"><ul type="disc"><li><p>
The programmer can control the storing mechanism with <tt>ref</tt> and <tt>cref</tt> wrappers [<a href="bi01.html#cit:boost::ref" title="[ref]">ref</a>].
Wrapping an argument with <tt>ref</tt>, or <tt>cref</tt>, instructs the library to store the argument as a reference, or as a reference to const respectively.
For example, if we rewrite the previous example and wrap the variable <tt>i</tt> with <tt>ref</tt>, we are creating the lambda expression <tt>lambda x.x+i</tt> and the value of the expression in the last line will be 4:
<pre class="programlisting">
i = 1;
(_1 + ref(i))(i = 2);
</pre>
</p></li><li><p>
Array types cannot be copied, they are thus stored as const reference by default.
</p></li><li><p>
For some expressions, it makes more sense to store the arguments as references.
For example, the obvious intention of the lambda expression <tt>i += _1</tt> is that calls to the lambda functor affect the value of the variable <tt>i</tt>, rather than some temporary copy of it.
As another example, the streaming operators take their leftmost argument as non-const references.
The exact rules are:
<div class="itemizedlist"><ul type="round"><li><p>The left argument of compound assignment operators (<tt>+=</tt>, <tt>*=</tt>, etc.) are stored as references to non-const.</p></li><li><p>If the left argument of <tt>&lt;&lt;</tt> or <tt>&gt;&gt;</tt> operator is derived from an instantiation of <tt>basic_ostream</tt> or respectively from <tt>basic_istream</tt>, the argument is stored as a reference to non-const.
For all other types, the argument is stored as a copy.
</p></li><li><p>
In pointer arithmetic expressions, non-const array types are stored as non-const references.
This is to prevent pointer arithmetic making non-const arrays const.
</p></li></ul></div>
</p></li></ul></div>
</p></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.id2739690" href="#id2739690">1</a>] </sup>
Strictly taken, the C++ standard defines <tt>for_each</tt> as a <span class="emphasis"><i>non-modifying sequence operation</i></span>, and the function object passed to <tt>for_each</tt> should not modify its argument.
The requirements for the arguments of <tt>for_each</tt> are unnecessary strict, since as long as the iterators are <span class="emphasis"><i>mutable</i></span>, <tt>for_each</tt> accepts a function object that can have side-effects on their argument.
Nevertheless, it is straightforward to provide another function template with the functionality of<tt>std::for_each</tt> but more fine-grained requirements for its arguments.
</p></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ar01s03.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="index.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="ar01s05.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">3. Introduction </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> 5. Lambda expressions in details</td></tr></table></div></body></html>

914
doc/ar01s05.html Normal file
View File

@@ -0,0 +1,914 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head><meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type"><title>5. Lambda expressions in details</title><meta name="generator" content="DocBook XSL Stylesheets V1.48"><link rel="home" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="up" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="previous" href="ar01s04.html" title="4. Using the library"><link rel="next" href="ar01s06.html" title="6. Extending return type deduction system"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">5. Lambda expressions in details</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ar01s04.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="ar01s06.html">Next</a></td></tr></table><hr></div><div class="section"><div class="titlepage"><div><h2 class="title" style="clear: both"><a name="sect:lambda_expressions_in_details"></a>5. Lambda expressions in details</h2></div></div><p>
This section describes different categories of lambda expressions in details.
We devote a separate section for each of the possible forms of a lambda expression.
</p><div class="section"><div class="titlepage"><div><h3 class="title"><a name="sect:placeholders"></a>5.1. Placeholders</h3></div></div><p>
The BLL defines three placeholder types: <tt>placeholder1_type</tt>, <tt>placeholder2_type</tt> and <tt>placeholder3_type</tt>.
BLL has a predefined placeholder variable for each placeholder type: <tt>_1</tt>, <tt>_2</tt> and <tt>_3</tt>.
However, the user is not forced to use these placeholders.
It is easy to define placeholders with alternative names.
This is done by defining new variables of placeholder types.
For example:
<pre class="programlisting">boost::lambda::placeholder1_type X;
boost::lambda::placeholder2_type Y;
boost::lambda::placeholder3_type Z;
</pre>
With these variables defined, <tt>X += Y * Z</tt> is equivalent to <tt>_1 += _2 * _3</tt>.
</p><p>
The use of placeholders in the lambda expression determines whether the resulting function is nullary, unary, binary or 3-ary.
The highest placeholder index is decisive. For example:
<pre class="programlisting">
_1 + 5 // unary
_1 * _1 + _1 // unary
_1 + _2 // binary
bind(f, _1, _2, _3) // 3-ary
_3 + 10 // 3-ary
</pre>
Note that the last line creates a 3-ary function, which adds <tt>10</tt> to its <span class="emphasis"><i>third</i></span> argument.
The first two arguments are discarded.
</p><p>
In addition to these three placeholder types, there is also a fourth placeholder type <tt>placeholderE_type</tt>.
The use of this placeholder is defined in <a href="ar01s05.html#sect:exceptions" title="5.7. Exceptions">Section 5.7</a> describing exception handling in lambda expressions.
</p><p>When an actual argument is supplied for a placeholder, the parameter passing mode is always by reference.
This means that any side-effects to the placeholder are reflected to the actual argument.
For example:
<pre class="programlisting">
int i = 1;
(_1 += 2)(i); // i is now 3
(++_1, cout &lt;&lt; _1)(i) // i is now 4, outputs 4
</pre>
</p><p>
Note that placeholder objects do not define the function call operator.
So strictly speaking, they are not lambda expressions, as evaluating a placeholder does not create a callable lambda functor.
Creating an identity functor is however straightforward, for example: <tt>0, _1</tt> serves for this purpose.
</p><div class="section"><div class="titlepage"><div><h4 class="title"><a name="sect:currying"></a>5.1.1. Currying</h4></div></div><p>Lambda functors support currying, that is, calling functions with one argument at a time.
If too few arguments are provided for a lambda functor, another lambda functor with a lower arity results.
When all arguments are provided, the original lambda functor is called.
For example, the last four lines below all have the same functionality; each of them ends up calling <tt>i + j + k</tt>:
<pre class="programlisting">
int i, j, k;
(_1 + _2 + _3)(i, j, k);
(_1 + _2 + _3)(i)(j)(k);
(_1 + _2 + _3)(i, j)(k);
(_1 + _2 + _3)(i)(j, k);
</pre>
</p><p>
A curried lambda functor just stores the arguments that are provided.
No subexpressions of the original lambda expression are evaluated, even though this might seem possible.
E.g., in the expression <tt>(_1 * _1 + _2)(i)</tt>, the subexpression <tt>i * i</tt> is not evaluated, rather its evaluation is postponed until the actual argument for <tt>_2</tt> is available too.
</p></div></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="sect:operator_expressions"></a>5.2. Operator expressions</h3></div></div><p>
The basic rule is that any C++ operator invocation with at least one argument being a lambda expression is itself a lambda expression.
Almost all overloadable operators are supported.
For example, the following is a valid lambda expression:
<pre class="programlisting">cout &lt;&lt; _1, _2[_3] = _1 &amp;&amp; false</pre>
</p><p>
However, there are some restrictions that originate from the C++ operator overloading rules, and some special cases.
</p><div class="section"><div class="titlepage"><div><h4 class="title"><a name="id2740698"></a>5.2.1. Operators that cannot be overloaded</h4></div></div><p>
Some operators cannot be overloaded at all, or their overloading rules prevent them to be overloaded to create lambda functors.
These operators are <tt>-&gt;.</tt>, <tt>-&gt;</tt>, <tt>new</tt>, <tt>new[]</tt>, <tt>delete</tt>, <tt>delete[]</tt> and <tt>?:</tt> (the conditional operator).
</p></div><div class="section"><div class="titlepage"><div><h4 class="title"><a name="sect:assignment_and_subscript"></a>5.2.2. Assignment and subscript operators</h4></div></div><p>
These operators must be implemented as class members.
Consequently, the left operand must be a lambda expression. For example:
<pre class="programlisting">
int i;
_1 = i; // ok
i = _1; // not ok. i is not a lambda expression
</pre>
There is a simple solution around this limitation, described in <a href="ar01s05.html#sect:delaying_constants_and_variables" title="5.5. Delaying constants and variables">Section 5.5</a>.
In short,
the left hand argument can be explicitly turned into a lambda functor by wrapping it with a special <tt>var</tt> function:
<pre class="programlisting">
var(i) = _1; // ok
</pre>
</p></div><div class="section"><div class="titlepage"><div><h4 class="title"><a name="sect:logical_operators"></a>5.2.3. Logical operators</h4></div></div><p>
Logical operators obey the short-circuiting evaluation rules. For example, in the following code, <tt>i</tt> is never incremented:
<pre class="programlisting">
bool flag = true; int i = 0;
(_1 || ++_2)(flag, i);
</pre>
</p></div><div class="section"><div class="titlepage"><div><h4 class="title"><a name="sect:comma_operator"></a>5.2.4. Comma operator</h4></div></div><p>
Comma operator is the &#8216;statement separator&#8217; in lambda expressions.
Since comma is also the separator between arguments in a function call, extra parenthesis are sometimes needed:
<pre class="programlisting">
for_each(a.begin(), a.end(), (++_1, cout &lt;&lt; _1));
</pre>
Without the extra parenthesis around <tt>++_1, cout &lt;&lt; _1</tt>, the code would be interpreted as an attempt to call <tt>for_each</tt> with four arguments.
</p><p>
The lambda functor created by the comma operator adheres to the C++ rule of always evaluating the left operand before the right one.
In the above example, each element of <tt>a</tt> is first incremented, then written to the stream.
</p></div><div class="section"><div class="titlepage"><div><h4 class="title"><a name="sect:function_call_operator"></a>5.2.5. Function call operator</h4></div></div><p>
A lambda functor of arity n defines the n-ary function call operator, which evaluates the functor.
Function call operators of arities between 1 and n-1 are defined to support curried calls (see currying, <a href="ar01s05.html#sect:currying" title="5.1.1. Currying">Section 5.1.1</a>).
Note that placeholders do not define the function call operator.
</p></div><div class="section"><div class="titlepage"><div><h4 class="title"><a name="sect:member_pointer_operator"></a>5.2.6. Member pointer operator</h4></div></div><p>
The member pointer operator <tt>operator-&gt;*</tt> can be overloaded freely.
Hence, for user defined types, member pointer operator is no special case.
The built-in meaning, however, is a somewhat more complicated case.
The built-in member pointer operator is applied, if the left argument is a pointer to an object of some class <tt>A</tt>, and the right hand argument is a pointer to a member of <tt>A</tt>, or a pointer to a member of a class from which <tt>A</tt> derives.
We must separate two cases:
<div class="itemizedlist"><ul type="disc"><li><p>The right hand argument is a pointer to a data member.
In this case the lambda functor simply performs the argument substitution and calls the built-in member pointer operator, which returns a reference to the member pointed to.
For example:
<pre class="programlisting">
struct A { int d; };
A* a = new A();
...
(a -&gt;* &amp;A::d); // returns a reference to a-&gt;d
(_1 -&gt;* &amp;A::d)(a); // likewise
</pre>
</p></li><li><p>
The right hand argument is a pointer to a member function.
For a built-in call like this, the result is kind of a delayed member function call.
Such an expression must be followed by a function argument list, with which the delayed member function call is performed.
For example:
<pre class="programlisting">
struct B { int foo(int); };
B* b = new B();
...
(b -&gt;* &amp;B::foo) // returns a delayed call to b-&gt;foo
// a function argument list must follow
(b -&gt;* &amp;B::foo)(1) // ok, calls b-&gt;foo(1)
(_1 -&gt;* &amp;B::foo)(b); // returns a delayed call to b-&gt;foo,
// no effect as such
(_1 -&gt;* &amp;B::foo)(b)(1); // calls b-&gt;foo(1)
</pre>
</p></li></ul></div>
</p></div></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="sect:bind_expressions"></a>5.3. Bind expressions</h3></div></div><p>
Bind expressions can have two forms:
<pre class="programlisting">
bind(<i><tt>target-function</tt></i>, <i><tt>bind-argument-list</tt></i>)
bind(<i><tt>target-member-function</tt></i>, <i><tt>object-argument</tt></i>, <i><tt>bind-argument-list</tt></i>)
</pre>
A bind expression delays the call of a function.
If this <span class="emphasis"><i>target function</i></span> is <span class="emphasis"><i>n</i></span>-ary, then the <tt><span class="emphasis"><i>bind-argument-list</i></span></tt> must contain <span class="emphasis"><i>n</i></span> arguments as well.
In the current version of the BLL, 0 &lt;= n &lt;= 9 must hold.
For member functions, the number of arguments must be at most 8, as the object argument takes one argument position.
Basically, the
<span class="emphasis"><i><tt>bind-argument-list</tt></i></span> must be a valid argument list for the target function, except that any argument can be replaced with a placeholder, or more generally, with a lambda expression.
Note that also the target function can be a lambda expression.
The result of a bind expression is either a nullary, unary, binary or 3-ary function object depending on the use of placeholders in the <span class="emphasis"><i><tt>bind-argument-list</tt></i></span> (see <a href="ar01s05.html#sect:placeholders" title="5.1. Placeholders">Section 5.1</a>).
</p><p>
The return type of the lambda functor created by the bind expression can be given as an explicitly specified template parameter, as in the following example:
<pre class="programlisting">
bind&lt;<span class="emphasis"><i>RET</i></span>&gt;(<span class="emphasis"><i>target-function</i></span>, <span class="emphasis"><i>bind-argument-list</i></span>)
</pre>
This is only necessary, if the return type of the target function cannot be deduced.
</p><p>
The following sections describe the different types of bind expressions.
</p><div class="section"><div class="titlepage"><div><h4 class="title"><a name="sect:function_pointers_as_targets"></a>5.3.1. Function pointers or references as targets</h4></div></div><p>The target function can be a pointer or a reference to a function and it can be either bound or unbound. For example:
<pre class="programlisting">
X foo(A, B, C); A a; B b; C c;
bind(foo, _1, _2, c)(a, b);
bind(&amp;foo, _1, _2, c)(a, b);
bind(_1, a, b, c)(foo);
</pre>
The return type deduction always succeeds with this type of bind expressions.
</p><p>
Note, that in C++ it is possible to take the address of an overloaded function only if the address is assigned to, or used as an initializer of, a variable, the type of which solves the amibiguity, or if an explicit cast expression is used.
This means, that overloaded functions cannot be used in bind expressions directly, e.g.:
<pre class="programlisting">
void foo(int);
void foo(float);
int i;
...
bind(&amp;foo, _1)(i); // error
...
void (*pf1)(int) = &amp;foo;
bind(pf1, _1)(i); // ok
bind(static_cast&lt;void(*)(int)&gt;(&amp;foo), _1)(i); // ok
</pre>
</p></div><div class="section"><div class="titlepage"><div><h4 class="title"><a name="member_functions_as_targets"></a>5.3.2. Member functions as targets</h4></div></div><p>
The syntax for using pointers to member function in bind expression is:
<pre class="programlisting">
bind(<i><tt>target-member-function</tt></i>, <i><tt>object-argument</tt></i>, <i><tt>bind-argument-list</tt></i>)
</pre>
The object argument can be a reference or pointer to the object, the BLL supports both cases with a uniform interface:
<pre class="programlisting">
bool A::foo(int) const;
A a;
vector&lt;int&gt; ints;
...
find_if(ints.begin(), ints.end(), bind(&amp;A::foo, a, _1));
find_if(ints.begin(), ints.end(), bind(&amp;A::foo, &amp;a, _1));
</pre>
Similarly, if the object argument is unbound, the resulting binder object can be called both via a pointer or a reference:
<pre class="programlisting">
bool A::foo(int);
list&lt;A&gt; refs;
list&lt;A*&gt; pointers;
...
find_if(refs.begin(), refs.end(), bind(&amp;A::foo, _1, 1));
find_if(pointers.begin(), pointers.end(), bind(&amp;A::foo, _1, 1));
</pre>
</p><p>
Even though the interfaces are the same, there are important semantic differences between using a pointer or a reference as the object argument.
The differences stem from the way <tt>bind</tt>-functions take their parameters, and how the bound parameters are stored within the lambda functor.
The object argument has the same parameter passing and storing mechanism than any other bind argument slot (see <a href="ar01s04.html#sect:storing_bound_arguments" title="4.4. Storing bound arguments in lambda functions">Section 4.4</a>); it is passed as a const reference and stored as a const copy in the lambda functor.
This creates some asymmetry between the lambda functor and the original member function, and between seemingly similar lambda functors. For example:
<pre class="programlisting">
class A {
int i; mutable int j;
public:
A(int ii, int jj) : i(ii), j(jj) {};
void set_i(int x) { i = x; };
void set_j(int x) { j = x; };
};
</pre>
When a pointer is used, the behavior is what the programmer might expect:
<pre class="programlisting">
A a(0,0); int k = 1;
bind(&amp;A::set_i, &amp;a, _1)(k); // a.i == 1
bind(&amp;A::set_j, &amp;a, _1)(k); // a.j == 1
</pre>
Even though a const copy of the object argument is stored, the original object <tt>a</tt> is still modified.
This is since the object argument is a pointer, and the pointer is copied, not the object it points to.
When we use a reference, the behaviour is different:
<pre class="programlisting">
A a(0,0); int k = 1;
bind(&amp;A::set_i, a, _1)(k); // error; a const copy of a is stored.
// Cannot call a non-const function set_i
bind(&amp;A::set_j, a, _1)(k); // a.j == 0, as a copy of a is modified
</pre>
</p><p>
To prevent the copying from taking place, one can use the <tt>ref</tt> or <tt>cref</tt> wrappers:
<pre class="programlisting">
bind(&amp;A::set_i, ref(a), _1)(k); // a.j == 1
bind(&amp;A::set_j, cref(a), _1)(k); // a.j == 1
</pre>
</p><p>Note that the preceding discussion is relevant only for bound arguments.
If the object argument is unbound, the parameter passing mode is always by reference.
Hence, no copying occurs for the actual arguments of the lambda functor:
<pre class="programlisting">
A a(0,0);
bind(&amp;A::set_i, _1, 1)(a); // a.i == 1
bind(&amp;A::set_j, _1, 1)(a); // a.j == 1
</pre>
</p></div><div class="section"><div class="titlepage"><div><h4 class="title"><a name="sect:function_objects_as_targets"></a>5.3.3. Function objects as targets</h4></div></div><p>Function objects, that is, class objects which have the function call operator defined, can be used as target functions.
In general, BLL cannot deduce the return type of an arbitrary function object.
However, there are two ways to give BLL this capability for a certain function object class.
</p><div class="simplesect"><div class="titlepage"><div><h5 class="title"><a name="id2803148"></a>The result_type typedef</h5></div></div><p>
The BLL recognizes the typedef <tt>result_type</tt> in the function object, and uses that as the return type of the function call operator.
For example:
<pre class="programlisting">
struct A {
typedef B result_type;
B operator()(X, Y, Z);
};
</pre>
Function objects in the standard library adhere to this convention.
</p><p>
There are two significant restrictions with this scheme:
<div class="orderedlist"><ol type="1"><li><p>
If the function object defines several function call operators, there is no way to specify different result types for them.
</p></li><li><p>
If the function call operator is a template, the result type may depend on the template parameters.
Hence, the typedef ought to be a template too, which the C++ language does not support.
</p></li></ol></div>
</p></div><div class="simplesect"><div class="titlepage"><div><h5 class="title"><a name="id2803217"></a>The sig template</h5></div></div><p>
The second method is slightly more complex, but also more flexible.
The steps that need to be taken to make BLL aware of the return type(s) of a function object are:
<div class="orderedlist"><ol type="1"><li><p>
Make the function object class derive from <tt>has_sig</tt> class.
(This is a technical requirement that is needed to let the two mechanisms for specifying the return type coexist.)
</p></li><li><p>Provide a member template struct <tt>sig&lt;Args&gt;</tt> with a typedef <tt>type</tt> that specifies the result type of the function call operator of the function object class.
The template argument <tt>Args</tt> is a <tt>tuple</tt> (or more precisely a <tt>cons</tt> list) type, where the first element is the function object type itself, and the remaining elements are the types of the arguments, with which the function object is being called.
Note that the elements of the <tt>Args</tt> tuple are always reference types.
Moreover, the types referenced can have a const or volatile qualifier, or both.
Also, there is no distinction between rvalues and const lvalues, that is, if the actual argument to the function call operator is an rvalue of type <tt>T</tt>, the corresponding argument in the <tt>Args</tt> tuple is <tt>const T&amp;</tt>.
</p></li></ol></div>
This convention does not suffer from the same restrictions than using a plain typedef:
return types for templated and/or overloaded function call operators can be specified.
For example:
<pre class="programlisting">
struct A : public has_sig {
// the return type equals the third argument type:
template&lt;class T1, T2, T3&gt;
T3 operator()(const T1&amp; t1, const T2&amp; t2, const T3&amp; t3);
template &lt;class Args&gt;
class sig {
// get the third argument type (4th element)
typedef typename
boost::tuples::get&lt;3, Args&gt;::type T3;
typedef typename
boost::remove_reference&lt;T3&gt;::type T3_non_ref;
public:
typedef typename
boost::remove_const&lt;T3_non_ref&gt;::type type;
}
};
</pre>
The <tt>sig</tt> template is a <span class="emphasis"><i>meta-function</i></span> that maps the argument type tuple to the result type.
As the example above demonstrates, the template can end up being somewhat complex.
Typical tasks to be performed are the extraction of the relevant types from the tuple, removing cv-qualifiers, removing references etc.
See the Boost type_traits Library for tools that can aid in these tasks.
</p></div></div></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="sect:overriding_deduced_return_type"></a>5.4. Overriding the deduced return type</h3></div></div><p>
The return type deduction system may not be able to deduce the return types of some user defined operators or bind expressions with class objects.
A special lambda expression type is provided for stating the return type explicitly and overriding the deduction system.
To state that the return type of the lambda functor defined by the lambda expression <tt>e</tt> is <tt>T</tt>, you can write:
<pre class="programlisting">ret&lt;T&gt;(e);</pre>
The effect is that the return type deduction is not performed for the lambda expression <tt>e</tt> at all, but instead, <tt>T</tt> is used as the return type.
Obviously <tt>T</tt> cannot be an arbitrary type, the true result of the lambda functor must be implicitly convertible to <tt>T</tt>.
For example:
<pre class="programlisting">
A a; B b;
C operator+(A, B);
int operator*(A, B);
...
ret&lt;D&gt;(_1 + _2)(a, b); // error (C cannot be converted to D)
ret&lt;C&gt;(_1 + _2)(a, b); // ok
ret&lt;float&gt;(_1 * _2)(a, b); // ok (int can be converted to float)
...
struct X {
typedef Y result_type;
Y operator()(); // #1
Z operator(int)(); // #2
};
...
X x; int i;
bind(x)(); // ok, call #1
bind(x, _1)(i); // try to call #2: error, deduction gives Y
ret&lt;Z&gt;(bind(x, _1))(i); // ok, call #2
</pre>
For bind expressions, there is a short-hand notation that can be used instead of <tt>ret</tt>.
The last line could alternatively be written as:
<pre class="programlisting">bind&lt;Z&gt;(x, _1)(i);</pre>
</p><p>Note that within nested lambda expressions, the <tt>ret</tt> must be used at each invocation where the deduction would otherwise fail.
For example:
<pre class="programlisting">
A a; B b;
C operator+(A, B); D operator-(C);
...
ret&lt;D&gt;( - (_1 + _2))(a, b); // error
ret&lt;D&gt;( - ret&lt;C&gt;(_1 + _2))(a, b); // ok
</pre>
</p><p>If you find yourself using <tt>ret</tt> repeatedly with the same types, it is worth while extending the return type deduction (see <a href="ar01s06.html#sect:extending_return_type_system" title="6. Extending return type deduction system">Section 6</a>).
</p><div class="section"><div class="titlepage"><div><h4 class="title"><a name="sect:nullary_functors_and_ret"></a>5.4.1. Nullary lambda functors and ret</h4></div></div><p>
As stated above, the effect of <tt>ret</tt> is to prevent the return type deduction to be performed.
However, there is an exception.
Due to the way the C++ template instantiation works, the compiler is always forced to instantiate the return type deduction templates for zero-argument lambda functors.
This introduces a slight problem with <tt>ret</tt>, best described with an example:
<pre class="programlisting">
struct F { int operator()(int i) const; };
F f;
...
bind(f, _1); // fails, cannot deduce the return type
ret&lt;int&gt;(bind(f, _1)); // ok
...
bind(f, 1); // fails, cannot deduce the return type
ret&lt;int&gt;(bind(f, 1)); // fails as well!
</pre>
The BLL cannot deduce the return types of the above bind calls, as <tt>F</tt> does not define the typedef <tt>result_type</tt>.
One would expect <tt>ret</tt> to fix this, but for the nullary lambda functor that results from a bind expression (last line above) this does not work.
The return type deduction templates are instantiated, even though it would not be necessary and the result is a compilation error.
</p><p>The solution to this is not to use the <tt>ret</tt> function, but rather define the return type as an explicitly specified template parameter in the <tt>bind</tt> call:
<pre class="programlisting">
bind&lt;int&gt;(f, 1); // ok
</pre>
The lambda functors created with
<tt>ret&lt;<i><tt>T</tt></i>&gt;(bind(<i><tt>arg-list</tt></i>))</tt> and
<tt>bind&lt;<i><tt>T</tt></i>&gt;(<i><tt>arg-list</tt></i>)</tt> have the exact same functionality &#8212;
apart from the fact that for some nullary lambda functors the former does not work while the latter does.
</p></div></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="sect:delaying_constants_and_variables"></a>5.5. Delaying constants and variables</h3></div></div><p>
The unary functions <tt>constant</tt> and <tt>var</tt> turn their argument into a lambda functor, that implements an identity mapping.
The former is for constants, the latter for variables.
The use of these <span class="emphasis"><i>delayed</i></span> constants and variables is sometimes necessary due to the lack of explicit syntax for lambda expressions.
For example:
<pre class="programlisting">
for_each(a.begin(), a.end(), cout &lt;&lt; _1 &lt;&lt; ' ');
for_each(a.begin(), a.end(), cout &lt;&lt; ' ' &lt;&lt; _1);
</pre>
The first line outputs the elements of <tt>a</tt> separated by spaces, while the second line outputs a space followed by the elements of <tt>a</tt> without any separators.
The reason for this is that neither of the operands of
<tt>cout &lt;&lt; ' '</tt> is a lambda expression, hence <tt>cout &lt;&lt; ' '</tt> is evaluated immediately.
To delay the evaluation of <tt>cout &lt;&lt; ' '</tt>, one of the operands must be explicitly marked as a lambda expression.
This is accomplished with the <tt>constant</tt> function:
<pre class="programlisting">
for_each(a.begin(), a.end(), cout &lt;&lt; constant(' ') &lt;&lt; _1);
</pre>
The call <tt>constant(' ')</tt> creates a nullary lambda functor which stores the character constant <tt>' '</tt> and returns a reference to it when invoked.
The <tt>constant</tt> is only needed when the operator call has side effects, like in the above example.
</p><p>
Sometimes we need to delay the evaluation of a variable.
Suppose we wanted to output the elements of a container in a numbered list:
<pre class="programlisting">
int index = 0;
for_each(a.begin(), a.end(), cout &lt;&lt; ++index &lt;&lt; ':' &lt;&lt; _1 &lt;&lt; '\n');
for_each(a.begin(), a.end(), cout &lt;&lt; ++var(index) &lt;&lt; ':' &lt;&lt; _1 &lt;&lt; '\n');
</pre>
The first <tt>for_each</tt> invocation does not do what we want; <tt>index</tt> is incremented only once, and its value is written into the output stream only once.
By using <tt>var</tt> to make <tt>index</tt> a lambda expression, we get the desired effect.
</p><p>
In sum, <tt>var(x)</tt> creates a nullary lambda functor,
which stores a reference to the variable <tt>x</tt>.
When the lambda functor is invoked, a reference to <tt>x</tt> is returned.
</p><div class="simplesect"><div class="titlepage"><div><h4 class="title"><a name="id2803927"></a>Naming delayed constants and variables</h4></div></div><p>
It is possible to predefine and name a delayed variable or constant outside a lambda expression.
The templates <tt>var_type</tt> and <tt>constant_type</tt> serve for this purpose.
They are used as:
<pre class="programlisting">
var_type&lt;T&gt;::type delayed_i(var(i));
constant_type&lt;T&gt;::type delayed_c(constant(c));
</pre>
The first line defines the variable <tt>delayed_i</tt> which is a delayed version of the variable <tt>i</tt> of type <tt>T</tt>.
Analogously, the second line defines the constant <tt>delayed_c</tt> as a delayed version of the constant <tt>c</tt>.
For example:
<pre class="programlisting">
int i = 0; int j;
for_each(a.begin(), a.end(), (var(j) = _1, _1 = var(i), var(i) = var(j)));
</pre>
is equivalent to:
<pre class="programlisting">
int i = 0; int j;
var_type&lt;int&gt;::type vi(var(i)), vj(var(j));
for_each(a.begin(), a.end(), (vj = _1, _1 = vi, vi = vj));
</pre>
</p><p>
Here is an example of naming a delayed constant:
<pre class="programlisting">
constant_type&lt;char&gt;::type space(constant(' '));
for_each(a.begin(),a.end(), cout &lt;&lt; space &lt;&lt; _1);
</pre>
</p></div><div class="simplesect"><div class="titlepage"><div><h4 class="title"><a name="id2804044"></a>About assignment and subscript operators</h4></div></div><p>
As described in <a href="ar01s05.html#sect:assignment_and_subscript" title="5.2.2. Assignment and subscript operators">Section 5.2.2</a>, assignment and subscripting operators are always defined as member functions.
This means, that for expressions of the form
<tt>x = y</tt> or <tt>x[y]</tt> to be interpreted as lambda expressions, the left-hand operand <tt>x</tt> must be a lambda expression.
Consequently, it is sometimes necessary to use <tt>var</tt> for this purpose.
We repeat the example from <a href="ar01s05.html#sect:assignment_and_subscript" title="5.2.2. Assignment and subscript operators">Section 5.2.2</a>:
<pre class="programlisting">
int i;
i = _1; // error
var(i) = _1; // ok
</pre>
</p><p>
Note that the compound assignment operators <tt>+=</tt>, <tt>-=</tt> etc. can be defined as non-member functions, and thus they are interpreted as lambda expressions even if only the right-hand operand is a lambda expression.
Nevertheless, it is perfectly ok to delay the left operand explicitly.
For example, <tt>i += _1</tt> is equivalent to <tt>var(i) += _1</tt>.
</p></div></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="sect:lambda_expressions_for_control_structures"></a>5.6. Lambda expressions for control structures</h3></div></div><p>
BLL defines several functions to create lambda functors that represent control structures.
They all take lambda functors as parameters and return <tt>void</tt>.
To start with an example, the following code outputs all even elements of some container <tt>a</tt>:
<pre class="programlisting">
for_each(a.begin(), a.end(),
if_then(_1 % 2 == 0, cout &lt;&lt; _1));
</pre>
</p><p>
The BLL supports the following function templates for control structures:
<pre class="programlisting">
if_then(condition, then_part)
if_then_else(condition, then_part, else_part)
while_loop(condition, body)
while_loop(condition) // no body case
do_while_loop(condition, body)
do_while_loop(condition) // no body case
for_loop(init, condition, increment, body)
for_loop(init, condition, increment) // no body case
switch_statement(...)
</pre>
</p><p>
Delayed variables tend to be commonplace in control structure lambda expressions.
For instance, here we use the <tt>var</tt> function to turn the arguments of <tt>for_loop</tt> into lambda expressions.
The effect of the code is to add 1 to each element of a two-dimensional array:
<pre class="programlisting">
int a[5][10]; int i;
for_each(a, a+5,
for_loop(var(i)=0, var(i)&lt;10, ++var(i),
_1[var(i)] += 1));
</pre>
</p><div class="section"><div class="titlepage"><div><h4 class="title"><a name="sect:switch_statement"></a>5.6.1. Switch statement</h4></div></div></div><p>
The lambda expressions for <tt>switch</tt> control structures are more complex since the number of cases may vary.
The general form of a switch lambda expression is:
<pre class="programlisting">
switch_statement(<i><tt>condition</tt></i>,
case_statement&lt;<i><tt>label</tt></i>&gt;(<i><tt>lambda expression</tt></i>),
case_statement&lt;<i><tt>label</tt></i>&gt;(<i><tt>lambda expression</tt></i>),
...
default_statement(<i><tt>lambda expression</tt></i>)
)
</pre>
The <tt><i><tt>condition</tt></i></tt> argument must be a lambda expression that creates a lambda functor with an integral return type.
The different cases are created with the <tt>case_statement</tt> functions, and the optional default case with the <tt>default_statement</tt> function.
The case labels are given as explicitly specified template arguments to <tt>case_statement</tt> functions and
<tt>break</tt> statements are implicitly part of each case.
For example, <tt>case_statement&lt;1&gt;(a)</tt>, where <tt>a</tt> is some lambda functor, generates the code:
<pre class="programlisting">
case 1:
<i><tt>evaluate lambda functor</tt></i> a;
break;
</pre>
The <tt>switch_statement</tt> function is specialized for up to 9 case statements.
</p><p>
As a concrete example, the following code iterates over some container <tt>v</tt> and ouptuts &#8220;zero&#8221; for each <tt>0</tt>, &#8220;one&#8221; for each <tt>1</tt>, and &#8220;other: <i><tt>n</tt></i>&#8221; for any other value <i><tt>n</tt></i>.
Note that another lambda expression is sequenced after the <tt>switch_statement</tt> to output a line break after each element:
<pre class="programlisting">
std::for_each(v.begin(), v.end(),
(
switch_statement(
_1,
case_statement&lt;0&gt;(std::cout &lt;&lt; constant(&quot;zero&quot;)),
case_statement&lt;1&gt;(std::cout &lt;&lt; constant(&quot;one&quot;)),
default_statement(cout &lt;&lt; constant(&quot;other: &quot;) &lt;&lt; _1)
),
cout &lt;&lt; constant(&quot;\n&quot;)
)
);
</pre>
</p></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="sect:exceptions"></a>5.7. Exceptions</h3></div></div><p>
The BLL provides lambda functors that throw and catch exceptions.
Lambda functors for throwing exceptions are created with the unary function <tt>throw_exception</tt>.
The argument to this function is the exception to be thrown, or a lambda functor which creates the exception to be thrown.
A lambda functor for rethrowing exceptions is created with the nullary <tt>rethrow</tt> function.
</p><p>
Lambda expressions for handling exceptions are somewhat more complex.
The general form of a lambda expression for try catch blocks is as follows:
<pre class="programlisting">
try_catch(
<i><tt>lambda expression</tt></i>,
catch_exception&lt;<i><tt>type</tt></i>&gt;(<i><tt>lambda expression</tt></i>),
catch_exception&lt;<i><tt>type</tt></i>&gt;(<i><tt>lambda expression</tt></i>),
...
catch_all(<i><tt>lambda expression</tt></i>)
)
</pre>
The first lambda expression is the try block.
Each <tt>catch_exception</tt> defines a catch block where the explicitly specified template argument defines the type of the exception to catch.
The lambda expression within the <tt>catch_exception</tt> defines the actions to take if the exception is caught.
Note that the resulting exception handlers catch the exceptions as references, i.e.,
<tt>catch_exception&lt;T&gt;(...)</tt> results in the catch block:
<pre class="programlisting">
catch(T&amp; e) { ... }
</pre>
The last catch block can alternatively be a call to
<tt>catch_exception&lt;<i><tt>type</tt></i>&gt;</tt>
or to
<tt>catch_all</tt>, which is the lambda expression equivalent to
<tt>catch(...)</tt>.
</p><p>
The <a href="ar01s05.html#ex:exceptions" title="Example 1. Throwing and handling exceptions in lambda expressions.">Example 1</a>. demonstrates the use of the BLL exception handling tools.
The first handler catches exceptions of type <tt>foo_exception</tt>.
Note the use of <tt>_1</tt> placeholder in the body of the handler.
</p><p>
The second handler shows how to throw exceptions, and demonstrates the use of the <span class="emphasis"><i>exception placeholder</i></span> <tt>_E</tt>.
It is a special placeholder, which refers to the caught exception object within the handler body.
Here we are handling an exception of type <tt>std::exception</tt>, which carries a string explaining the cause of the exception.
This explanation can be queried with the zero-argument member function <tt>what</tt>.
The expression
<tt>bind(&amp;std::exception::what, _E)</tt> creates the lambda function for making that call.
Note that <tt>_E</tt> is not a full-fledged placeholder, but rather a special case of <tt>_3</tt>.
As a consequence, <tt>_E</tt> cannot be used outside of an exception handler lambda expression, and <tt>_3</tt> cannot be used inside of an exception handler lambda expression.
Violating this rule is caught by the compiler.
The last line of the second handler constructs a new exception object and throws that with <tt>throw exception</tt>. Constructing and destructing objects within lambda expressions is explained in <a href="ar01s05.html#sect:construction_and_destruction" title="5.8. Construction and destruction">Section 5.8</a>
</p><p>
Finally, the third handler (<tt>catch_all</tt>) demonstrates rethrowing exceptions.
</p><div class="example"><p><a name="ex:exceptions"></a><b>Example 1. Throwing and handling exceptions in lambda expressions.</b></p><pre class="programlisting">
for_each(
a.begin(), a.end(),
try_catch(
bind(foo, _1), // foo may throw
catch_exception&lt;foo_exception&gt;(
cout &lt;&lt; constant(&quot;Caught foo_exception: &quot;)
&lt;&lt; &quot;foo was called with argument = &quot; &lt;&lt; _1
),
catch_exception&lt;std::exception&gt;(
cout &lt;&lt; constant(&quot;Caught std::exception: &quot;)
&lt;&lt; bind(&amp;std::exception::what, _E),
throw_exception(bind(constructor&lt;bar_exception&gt;(), _1)))
),
catch_all(
(cout &lt;&lt; constant(&quot;Unknown&quot;), rethrow())
)
)
);
</pre></div></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="sect:construction_and_destruction"></a>5.8. Construction and destruction</h3></div></div></div><p>
Operators <tt>new</tt> and <tt>delete</tt> can be overloaded, but their return types are fixed.
Particularly, the return types cannot be lambda functors, which prevents them to be overloaded for lambda expressions.
It is not possible to take the address of a constructor, hence constructors cannot be used as target functions in bind expressions.
The same is true for destructors.
As a way around these constraints, BLL defines wrapper classes for <tt>new</tt> and <tt>delete</tt> calls, as well as for constructors and destructors.
Instances of these classes are function objects, that can be used as target functions of bind expressions.
For example:
<pre class="programlisting">
int* a[10];
for_each(a, a+10, _1 = bind(new_ptr&lt;int&gt;()));
for_each(a, a+10, bind(delete_ptr(), _1));
</pre>
The <tt>new_ptr&lt;int&gt;()</tt> expression creates a function object that calls <tt>new int()</tt> when invoked, and wrapping that inside <tt>bind</tt> makes it a lambda functor.
In the same way, the expression <tt>delete_ptr()</tt> creates a function object that invokes <tt>delete</tt> on its argument.
Note that <tt>new_ptr&lt;<i><tt>T</tt></i>&gt;()</tt> can take arguments as well.
They are passed directly to the constructor invocation and thus allow calls to constructors which take arguments.
</p><p>
As an example of constructor calls in lambda expressions, the following code reads integers from two containers <tt>x</tt> and <tt>y</tt>, constructs pairs out of them and inserts them into a third container:
<pre class="programlisting">
vector&lt;pair&lt;int, int&gt; &gt; v;
transform(x.begin(), x.end(), y.begin(), back_inserter(v),
bind(constructor&lt;pair&lt;int, int&gt; &gt;(), _1, _2));
</pre>
<a href="ar01s05.html#table:constructor_destructor_fos" title="Table 1. Construction and destruction related function objects.">Table 1</a>. lists all the function objects related to creating and destroying objects, showing the expression to create and call the function object, and the effect of evaluating that expression.
</p><div class="table"><p><a name="table:constructor_destructor_fos"></a><b>Table 1. Construction and destruction related function objects.</b></p><table summary="Construction and destruction related function objects." border="1"><colgroup><col><col></colgroup><thead><tr><th>Function object call</th><th>Wrapped expression</th></tr></thead><tbody><tr><td><tt>constructor&lt;T&gt;()(<i><tt>arg_list</tt></i>)</tt></td><td>T(<i><tt>arg_list</tt></i>)</td></tr><tr><td><tt>destructor()(a)</tt></td><td><tt>a.~A()</tt>, where <tt>a</tt> is of type <tt>A</tt></td></tr><tr><td><tt>destructor()(pa)</tt></td><td><tt>pa.-&gt;A()</tt>, where <tt>pa</tt> is of type <tt>A*</tt></td></tr><tr><td><tt>new_ptr&lt;T&gt;()(<i><tt>arg_list</tt></i>)</tt></td><td><tt>new T(<i><tt>arg_list</tt></i>)</tt></td></tr><tr><td><tt>new_array&lt;T&gt;()(sz)</tt></td><td><tt>new T[sz]</tt></td></tr><tr><td><tt>delete_ptr()(p)</tt></td><td><tt>delete p</tt></td></tr><tr><td><tt>delete_array()(p)</tt></td><td><tt>delete p[]</tt></td></tr></tbody></table></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="id2805233"></a>5.9. Special lambda expressions</h3></div></div><div class="section"><div class="titlepage"><div><h4 class="title"><a name="id2805240"></a>5.9.1. Preventing argument substitution</h4></div></div><p>
When a lambda functor is called, the default behavior is to substitute the actual arguments for the placeholders within all subexpressions.
This section describes the tools to prevent the substitution and evaluation of a subexpression, and explains when these tools should be used.
</p><p>
The arguments to a bind expression can be arbitrary lambda expressions, e.g., other bind expressions.
For example:
<pre class="programlisting">
int foo(int); int bar(int);
...
int i;
bind(foo, bind(bar, _1)(i);
</pre>
The last line makes the call <tt>foo(bar(i));</tt>
Note that the first argument in a bind expression, the target function, is no exception, and can thus be a bind expression too.
The innermost lambda functor just has to return something that can be used as a target function: another lambda functor, function pointer, pointer to member function etc.
For example, in the following code the innermost lambda functor makes a selection between two functions, and returns a pointer to one of them:
<pre class="programlisting">
int add(int a, int b) { return a+b; }
int mul(int a, int b) { return a*b; }
int(*)(int, int) add_or_mul(bool x) {
return x ? add : mul;
}
bool condition; int i; int j;
...
bind(bind(&amp;add_or_mul, _1), _2, _3)(condition, i, j);
</pre>
</p><div class="section"><div class="titlepage"><div><h5 class="title"><a name="sect:unlambda"></a>5.9.1.1. Unlambda</h5></div></div><p>A nested bind expression may occur inadvertently, if the target function is a variable with a type that depends on a template parameter.
Typically the target function could be a formal parameter of a function template.
In such a case, the programmer may not know whether the target function is a lambda functor or not.
</p><p>Consider the following function template:
<pre class="programlisting">
template&lt;class F&gt;
int nested(const F&amp; f) {
int x;
...
bind(f, _1)(x);
...
}
</pre>
Somewhere inside the function the formal parameter
<tt>f</tt> is used as a target function in a bind expression.
In order for this <tt>bind</tt> call to be valid, <tt>f</tt> must be a unary function.
Suppose the following two calls to <tt>nested</tt> are made:
<pre class="programlisting">
int foo(int);
int bar(int, int);
nested(&amp;foo);
nested(bind(bar, 1, _1));
</pre>
Both are unary functions, or function objects, with appropriate argument and return types, but the latter will not compile.
In the latter call, the bind expression inside <tt>nested</tt> will become:
<pre class="programlisting">
bind(bind(bar, 1, _1), _1)
</pre>
When this is invoked with <tt>x</tt>, after substituitions we end up trying to call
<pre class="programlisting">
bar(1, x)(x)
</pre>
which is an error.
The call to <tt>bar</tt> returns int, not a unary function or function object.
</p><p>
In the example above, the intent of the bind expression in the <tt>nested</tt> function is to treat <tt>f</tt> as an ordinary function object, instead of a lambda functor.
The BLL provides the function template <tt>unlambda</tt> to express this: a lambda functor wrapped inside <tt>unlambda</tt> is not a lambda functor anymore, and does not take part into the argument substitution process.
Note that for all other argument types <tt>unlambda</tt> is an identity operation, except for making non-const objects const.
</p><p>
Using <tt>unlambda</tt>, the <tt>nested</tt> function is written as:
<pre class="programlisting">
template&lt;class F&gt;
int nested(const F&amp; f) {
int x;
...
bind(unlambda(f), _1)(x);
...
}
</pre>
</p></div><div class="section"><div class="titlepage"><div><h5 class="title"><a name="id2805499"></a>5.9.1.2. Protect</h5></div></div><p>
The <tt>protect</tt> function is related to unlambda.
It is also used to prevent the argument substitution taking place, but whereas <tt>unlambda</tt> turns a lambda functor into an ordinary function object for good, <tt>protect</tt> does this temporarily, for just one evaluation round.
For example:
<pre class="programlisting">
int x = 1, y = 10;
(_1 + protect(_1 + 2))(x)(y);
</pre>
The first call substitutes <tt>x</tt> for the leftmost <tt>_1</tt>, and results in another lambda functor <tt>x + (_1 + 2)</tt>, which after the call with <tt>y</tt> becomes <tt>x + (y + 2)</tt>, and thus finally 13.
</p><p>
Primary motivation for including <tt>protect</tt> into the library, was to allow nested STL algorithm invocations (<a href="ar01s05.html#sect:nested_stl_algorithms" title="5.11. Nesting STL algorithm invocations">Section 5.11</a>).
</p></div></div><div class="section"><div class="titlepage"><div><h4 class="title"><a name="sect:rvalues_as_actual_arguments"></a>5.9.2. Rvalues as actual arguments to lambda functors</h4></div></div><p>
Actual arguments to the lambda functors cannot be non-const rvalues.
This is due to a deliberate design decision: either we have this restriction, or there can be no side-effects to the actual arguments.
There are ways around this limitation.
We repeat the example from section <a href="ar01s04.html#sect:actual_arguments_to_lambda_functors" title="4.3. About actual arguments to lambda functors">Section 4.3</a> and list the different solutions:
<pre class="programlisting">
int i = 1; int j = 2;
(_1 + _2)(i, j); // ok
(_1 + _2)(1, 2); // error (!)
</pre>
<div class="orderedlist"><ol type="1"><li><p>
If the rvalue is of a class type, the return type of the function that creates the rvalue should be defined as const. Due to an unfortunate language restriction this does not work for built-in types, as built-in rvalues cannot be const qualified. </p></li><li><p>
If the lambda function call is accessible, the <tt>make_const</tt> function can be used to <span class="emphasis"><i>constify</i></span> the rvalue. E.g.:
<pre class="programlisting">
(_1 + _2)(make_const(1), make_const(2)); // ok</pre>
Commonly the lambda function call site is inside a standard algorithm function template, preventing this solution to be used.
</p></li><li><p>
If neither of the above is possible, the lambda expression can be wrapped in a <tt>const_parameters</tt> function.
It creates another type of lambda functor, which takes its arguments as const references. For example:
<pre class="programlisting">
const_parameters(_1 + _2)(1, 2); // ok
</pre>
Note that <tt>const_parameters</tt> makes all arguments const.
Hence, in the case were one of the arguments is a non-const rvalue, and another argument needs to be passed as a non-const reference, this approach cannot be used.
</p></li><li><p>If none of the above is possible, there is still one solution, which unfortunately can break const correctness.
The solution is yet another lambda functor wrapper, which we have named <tt>break_const</tt> to alert the user of the potential dangers of this function.
The <tt>break_const</tt> function creates a lambda functor that takes its arguments as const, and casts away constness prior to the call to the original wrapped lambda functor.
For example:
<pre class="programlisting">
int i;
...
(_1 += _2)(i, 2); // error, 2 is a non-const rvalue
const_parameters(_1 += _2)(i, 2); // error, i becomes const
break_const(_1 += _2)(i, 2); // ok, but dangerous
</pre>
Note, that the results of
<tt> break_const</tt> or <tt>const_parameters</tt> are not lambda functors, so they cannot be used as subexpressions of lambda expressions. For instance:
<pre class="programlisting">
break_const(_1 + _2) + _3; // fails.
const_parameters(_1 + _2) + _3; // fails.
</pre>
However, this kind of code should never be necessary, since calls to sub lambda functors are made inside the BLL, and are not affected by the non-const rvalue problem.
</p></li></ol></div>
</p></div></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="id2805803"></a>5.10. Casts, sizeof and typeid</h3></div></div><div class="section"><div class="titlepage"><div><h4 class="title"><a name="sect:cast_expressions"></a>5.10.1.
Cast expressions
</h4></div></div><p>
The BLL defines its counterparts for the four cast expressions <tt>static_cast</tt>, <tt>dynamic_cast</tt>, <tt>const_cast</tt> and <tt>reinterpret_cast</tt>.
The BLL versions of the cast expressions have the prefix <tt>ll_</tt>.
The type to cast to is given as an explicitly specified template argument, and the sole argument is the expression from which to perform the cast.
If the argument is a lambda functor, the lambda functor is evaluated first.
For example, the following code uses <tt>ll_dynamic_cast</tt> to count the number of <tt>derived</tt> instances in the container <tt>a</tt>:
<pre class="programlisting">
class base {};
class derived : public base {};
vector&lt;base*&gt; a;
...
int count = 0;
for_each(a.begin(), a.end(),
if_then(ll_dynamic_cast&lt;derived*&gt;(_1), ++var(count)));
</pre>
</p></div><div class="section"><div class="titlepage"><div><h4 class="title"><a name="id2805904"></a>5.10.2. Sizeof and typeid</h4></div></div><p>
The BLL counterparts for these expressions are named <tt>ll_sizeof</tt> and <tt>ll_typeid</tt>.
Both take one argument, which can be a lambda expression.
The lambda functor created wraps the <tt>sizeof</tt> or <tt>typeid</tt> call, and when the lambda functor is called the wrapped operation is performed.
For example:
<pre class="programlisting">
vector&lt;base*&gt; a;
...
for_each(a.begin(), a.end(),
cout &lt;&lt; bind(&amp;type_info::name, ll_typeid(*_1)));
</pre>
Here <tt>ll_typeid</tt> creates a lambda functor for calling <tt>typeid</tt> for each element.
The result of a <tt>typeid</tt> call is an instance of the <tt>type_info</tt> class, and the bind expression creates a lambda functor for calling the <tt>name</tt> member function of that class.
</p></div></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="sect:nested_stl_algorithms"></a>5.11. Nesting STL algorithm invocations</h3></div></div><p>
The BLL defines common STL algorithms as function object classes, instances of which can be used as target functions in bind expressions.
For example, the following code iterates over the elements of a two-dimensional array, and computes their sum.
<pre class="programlisting">
int a[100][200];
int sum = 0;
std::for_each(a, a + 100,
bind(ll::for_each(), _1, _1 + 200, protect(sum += _1)));
</pre>
The BLL versions of the STL algorithms are classes, which define the function call operator (or several overloaded ones) to call the corresponding function templates in the <tt>std</tt> namespace.
All these structs are placed in the subnamespace <tt>boost::lambda:ll</tt>.
The supported algorithms are listed in <a href="ar01s05.html#table:nested_algorithms" title="Table 2. The nested STL algorithms.">Table 2</a>.
</p><p>
Note that there is no easy way to express an overloaded member function call in a lambda expression.
This limits the usefulness of nested STL algorithms, as for instance the <tt>begin</tt> function has more than one overloaded definitions in container templates.
In general, something analogous to the pseudo-code below cannot be written:
<pre class="programlisting">
std::for_each(a.begin(), a.end(),
bind(ll::for_each(), _1.begin(), _1.end(), protect(sum += _1)));
</pre>
Some aid for common special cases can be provided though.
The BLL defines two helper function object classes, <tt>call_begin</tt> and <tt>call_end</tt>, which wrap a call to the <tt>begin</tt> and, respectively, <tt>end</tt> functions of a container, and return the <tt>const_iterator</tt> type of the container.
With these helper templates, the above code becomes:
<pre class="programlisting">
std::for_each(a.begin(), a.end(),
bind(ll::for_each(),
bind(call_begin(), _1), bind(call_end(), _1),
protect(sum += _1)));
</pre>
</p><div class="table"><p><a name="table:nested_algorithms"></a><b>Table 2. The nested STL algorithms.</b></p><table summary="The nested STL algorithms." border="1"><colgroup><col></colgroup><thead></thead><tbody><tr><td><tt>for_each</tt></td></tr><tr><td><tt>find</tt></td></tr><tr><td><tt>find_if</tt></td></tr><tr><td><tt>find_end</tt></td></tr><tr><td><tt>find_first_of</tt></td></tr><tr><td><tt>transform</tt></td></tr></tbody></table></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ar01s04.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="index.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="ar01s06.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">4. Using the library </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> 6. Extending return type deduction system</td></tr></table></div></body></html>

124
doc/ar01s06.html Normal file
View File

@@ -0,0 +1,124 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head><meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type"><title>6. Extending return type deduction system</title><meta name="generator" content="DocBook XSL Stylesheets V1.48"><link rel="home" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="up" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="previous" href="ar01s05.html" title="5. Lambda expressions in details"><link rel="next" href="ar01s07.html" title="7. Practical considerations"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">6. Extending return type deduction system</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ar01s05.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="ar01s07.html">Next</a></td></tr></table><hr></div><div class="section"><div class="titlepage"><div><h2 class="title" style="clear: both"><a name="sect:extending_return_type_system"></a>6. Extending return type deduction system</h2></div></div><p>
In this section, we explain how to extend the return type deduction system to cover user defined operators.
In many cases this is not necessary, as the BLL defines default return types for operators.
For example, the default return type for all comparison operators is <tt>bool</tt>, and as long as the user defined comparison operators have a bool return type, there is no need to write new specializations for the return type deduction classes.
Sometimes this cannot be avoided, though.
</p><p>
The overloadable user defined operators are either unary or binary.
For each arity, there are two traits templates that define the return types of the different operators.
Hence, the return type system can be extended by providing more specializations for these templates.
The templates for unary functors are
<tt>
plain_return_type_1&lt;Action, A&gt;
</tt>
and
<tt>
return_type_1&lt;Action, A&gt;
</tt>, and
<tt>
plain_return_type_2&lt;Action, A, B&gt;
</tt>
and
<tt>
return_type_2&lt;Action, A, B&gt;
</tt>
respectively for binary functors.
</p><p>The first parameter (<tt>Action</tt>) to all these templates is the <span class="emphasis"><i>action</i></span> class, which specifies the operator.
Operators with similar return type rules are grouped together into <span class="emphasis"><i>action groups</i></span>, and only the action class and action group together define the operator unambiguously.
As an example, the action type <tt>arithmetic_action&lt;plus_action&gt;</tt> stands for <tt>operator+</tt>.
The complete listing of different action types is shown in <a href="ar01s06.html#table:actions" title="Table 3. Action types">Table 3</a>.
</p><p>
The latter parameters,
<tt>A</tt> in the unary case, or A and B in the binary case, stand for the argument types of the operator call.
The two sets of templates, <tt>plain_return_type_<i><tt>n</tt></i></tt> and <tt>return_type_<i><tt>n</tt></i></tt> (<i><tt>n</tt></i> is 1 or 2) differ in the way how parameter types are presented to them.
For the former templates, the parameter types are always provided as non-reference types, and do not have const or volatile qualifiers.
This makes specializing easy, as commonly one specialization for each user defined operator, or operator group, is enough.
On the other hand, if a particular operator is overloaded for different cv-qualifications of the same argument types, and the return types of these overloaded versions differ, a more fine-grained control is needed.
Hence, for the latter templates, the parameter types are always reference types, and const and volatile qualifiers are preserved.
The downside is, that for an overloaded set of operators of the kind described above, one may end up needing up to 16 <tt>return_type_2</tt> specializations.
</p><p>
Suppose the user has overloaded the following operators for some user defined types <tt>X</tt>, <tt>Y</tt> and <tt>Z</tt>:
<pre class="programlisting">
Z operator+(const X&amp;, const Y&amp;);
Z operator-(const X&amp;, const Y&amp;);
</pre>
Now, one can add a specialization stating, that if the left hand argument is of type <tt>X</tt>, and the right hand one of type <tt>Y</tt>, the return type of all such binary arithmetic operators is <tt>Z</tt>:
<pre class="programlisting">
namespace boost {
namespace lambda {
template&lt;class Act&gt;
struct plain_return_type_2&lt;arithmetic_action&lt;Act&gt;, X, Y&gt; {
typedef Z type;
};
}
}
</pre>
Having this specialization defined, BLL is capable of correctly deducing the return type of the above two operators.
Note, that the specializations must be in the same namespace, <tt>::boost::lambda</tt>, with the primary template.
For brevity, we do not show the namespace definitions in the examples below.
</p><p>
It is possible to specialize on the level of an individual operator as well, in addition to providing a specialization for a group of operators. Say, we add a new arithmetic operator for argument types <tt>X</tt> and <tt>Y</tt>:
<pre class="programlisting">
X operator*(const X&amp;, const Y&amp;);
</pre>
Our first rule for all arithmetic operators specifies that the return type of this operator is <tt>Z</tt>, which obviously is not the case.
Hence, we provide a new rule for the multiplication operator:
<pre class="programlisting">
template&lt;&gt;
struct plain_return_type_2&lt;arithmetic_action&lt;multiply_action&gt;, X, Y&gt; {
typedef X type;
};
</pre>
</p><p>
The specializations can define arbitrary mappings from the argument types to the return type.
Suppose we have some mathematical vector type, templated on the element type:
<pre class="programlisting">template &lt;class T&gt; class my_vector;</pre>
Suppose the addition operator is defined between any two <tt>my_vector</tt> instantiations, as long as the addition operator is defined between their element types.
Furthermore, the element type of the resulting <tt>my_vector</tt> is the same as the result type of the addition between the element types.
E.g., adding <tt>my_vector&lt;int&gt;</tt> and <tt>my_vector&lt;double&gt;</tt> results in <tt>my_vector&lt;double&gt;</tt>.
The BLL has traits classes to perform the implicit built-in and standard type conversions between integral, floating point, and complex classes.
Using BLL tools, the addition operator described above can be defined as:
<pre class="programlisting">
template&lt;class A, class B&gt;
my_vector&lt;typename return_type_2&lt;arithmetic_action&lt;plus_action&gt;, A&amp;, B&amp;&gt;::type&gt;
operator+(const my_vector&lt;A&gt;&amp; a, const my_vector&lt;B&gt;&amp; b)
{
typedef typename
return_type_2&lt;arithmetic_action&lt;plus_action&gt;, A&amp;, B&amp;&gt;::type res_type;
return my_vector&lt;res_type&gt;();
}
</pre>
</p><p>
To allow BLL to deduce the type of <tt>my_vector</tt> additions correctly, we can define:
<pre class="programlisting">
template&lt;class A, class B&gt;
class plain_return_type_2&lt;arithmetic_action&lt;plus_action&gt;,
my_vector&lt;A&gt;, my_vector&lt;B&gt; &gt; {
typedef typename
return_type_2&lt;arithmetic_action&lt;plus_action&gt;, A&amp;, B&amp;&gt;::type res_type;
public:
typedef my_vector&lt;res_type&gt; type;
};
</pre>
Note, that we are reusing the existing specializations for the BLL <tt>return_type_2</tt> template, which require that the argument types are references.
</p><div class="table"><p><a name="table:actions"></a><b>Table 3. Action types</b></p><table summary="Action types" border="1"><colgroup><col><col></colgroup><tbody><tr><td><tt>+</tt></td><td><tt>arithmetic_action&lt;plus_action&gt;</tt></td></tr><tr><td><tt>-</tt></td><td><tt>arithmetic_action&lt;minus_action&gt;</tt></td></tr><tr><td><tt>*</tt></td><td><tt>arithmetic_action&lt;multiply_action&gt;</tt></td></tr><tr><td><tt>/</tt></td><td><tt>arithmetic_action&lt;divide_action&gt;</tt></td></tr><tr><td><tt>%</tt></td><td><tt>arithmetic_action&lt;remainder_action&gt;</tt></td></tr><tr><td><tt>+</tt></td><td><tt>unary_arithmetic_action&lt;plus_action&gt;</tt></td></tr><tr><td><tt>-</tt></td><td><tt>unary_arithmetic_action&lt;minus_action&gt;</tt></td></tr><tr><td><tt>&amp;</tt></td><td><tt>bitwise_action&lt;and_action&gt;</tt></td></tr><tr><td><tt>|</tt></td><td><tt>bitwise_action&lt;or_action&gt;</tt></td></tr><tr><td><tt>~</tt></td><td><tt>bitwise_action&lt;not_action&gt;</tt></td></tr><tr><td><tt>^</tt></td><td><tt>bitwise_action&lt;xor_action&gt;</tt></td></tr><tr><td><tt>&lt;&lt;</tt></td><td><tt>bitwise_action&lt;leftshift_action_no_stream&gt;</tt></td></tr><tr><td><tt>&gt;&gt;</tt></td><td><tt>bitwise_action&lt;rightshift_action_no_stream&gt;</tt></td></tr><tr><td><tt>&amp;&amp;</tt></td><td><tt>logical_action&lt;and_action&gt;</tt></td></tr><tr><td><tt>||</tt></td><td><tt>logical_action&lt;or_action&gt;</tt></td></tr><tr><td><tt>!</tt></td><td><tt>logical_action&lt;not_action&gt;</tt></td></tr><tr><td><tt>&lt;</tt></td><td><tt>relational_action&lt;less_action&gt;</tt></td></tr><tr><td><tt>&gt;</tt></td><td><tt>relational_action&lt;greater_action&gt;</tt></td></tr><tr><td><tt>&lt;=</tt></td><td><tt>relational_action&lt;lessorequal_action&gt;</tt></td></tr><tr><td><tt>&gt;=</tt></td><td><tt>relational_action&lt;greaterorequal_action&gt;</tt></td></tr><tr><td><tt>==</tt></td><td><tt>relational_action&lt;equal_action&gt;</tt></td></tr><tr><td><tt>!=</tt></td><td><tt>relational_action&lt;notequal_action&gt;</tt></td></tr><tr><td><tt>+=</tt></td><td><tt>arithmetic_assignment_action&lt;plus_action&gt;</tt></td></tr><tr><td><tt>-=</tt></td><td><tt>arithmetic_assignment_action&lt;minus_action&gt;</tt></td></tr><tr><td><tt>*=</tt></td><td><tt>arithmetic_assignment_action&lt;multiply_action&gt;</tt></td></tr><tr><td><tt>/=</tt></td><td><tt>arithmetic_assignment_action&lt;divide_action&gt;</tt></td></tr><tr><td><tt>%=</tt></td><td><tt>arithmetic_assignment_action&lt;remainder_action&gt;</tt></td></tr><tr><td><tt>&amp;=</tt></td><td><tt>bitwise_assignment_action&lt;and_action&gt;</tt></td></tr><tr><td><tt>=|</tt></td><td><tt>bitwise_assignment_action&lt;or_action&gt;</tt></td></tr><tr><td><tt>^=</tt></td><td><tt>bitwise_assignment_action&lt;xor_action&gt;</tt></td></tr><tr><td><tt>&lt;&lt;=</tt></td><td><tt>bitwise_assignment_action&lt;leftshift_action&gt;</tt></td></tr><tr><td><tt>&gt;&gt;=</tt></td><td><tt>bitwise_assignment_action&lt;rightshift_action&gt;</tt></td></tr><tr><td><tt>++</tt></td><td><tt>pre_increment_decrement_action&lt;increment_action&gt;</tt></td></tr><tr><td><tt>--</tt></td><td><tt>pre_increment_decrement_action&lt;decrement_action&gt;</tt></td></tr><tr><td><tt>++</tt></td><td><tt>post_increment_decrement_action&lt;increment_action&gt;</tt></td></tr><tr><td><tt>--</tt></td><td><tt>post_increment_decrement_action&lt;decrement_action&gt;</tt></td></tr><tr><td><tt>&amp;</tt></td><td><tt>other_action&lt;address_of_action&gt;</tt></td></tr><tr><td><tt>*</tt></td><td><tt>other_action&lt;contents_of_action&gt;</tt></td></tr><tr><td><tt>,</tt></td><td><tt>other_action&lt;comma_action&gt;</tt></td></tr></tbody></table></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ar01s05.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="index.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="ar01s07.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">5. Lambda expressions in details </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> 7. Practical considerations</td></tr></table></div></body></html>

85
doc/ar01s07.html Normal file
View File

@@ -0,0 +1,85 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head><meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type"><title>7. Practical considerations</title><meta name="generator" content="DocBook XSL Stylesheets V1.48"><link rel="home" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="up" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="previous" href="ar01s06.html" title="6. Extending return type deduction system"><link rel="next" href="ar01s08.html" title="8. Relation to other Boost libraries"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">7. Practical considerations</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ar01s06.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="ar01s08.html">Next</a></td></tr></table><hr></div><div class="section"><div class="titlepage"><div><h2 class="title" style="clear: both"><a name="id2807377"></a>7. Practical considerations</h2></div></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="id2807383"></a>7.1. Performance</h3></div></div><p>In theory, all overhead of using STL algorithms and lambda functors compared to hand written loops can be optimized away, just as the overhead from standard STL function objects and binders can.
Depending on the compiler, this can also be true in practice.
</p><p>We have only performed limited performance testing described in [<a href="bi01.html#cit:jarvi:00" title="[Jär00]">Jär00</a>], and
our tests suggest that the BLL does not introduce a loss of performance compared to STL function objects.
Hence, with a reasonable optimizing compiler, one should expect the performance characteristics be comparable to using classic STL.
Moreover, with a great optimizing compiler there may be no performance penalty at all.
Note however, that evaluating a lambda functor consist of a sequence of calls to small functions that are declared inline.
If the compiler fails to actually expand these functions inline, the performance, compared to hand written loops, can suffer.
</p></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="id2807426"></a>7.2. About compiling</h3></div></div><p>The BLL uses templates rather heavily, performing numerous recursive instantiations of the same templates.
This has (at least) three implications:
<div class="itemizedlist"><ul type="disc"><li><p>
While it is possible to write incredibly complex lambda expressions, it probably isn't a good idea.
Compiling such expressions may end up requiring a lot of memory
at compile time, and being slow to compile.
</p></li><li><p>
The types of lambda functors that result from even the simplest lambda expressions are cryptic.
Usually the programmer doesn't need to deal with the lambda functor the types at all, but in the case of an error in a lambda expression, the compiler usually outputs the types of the lambda functors involved.
This can make the error messages very long and difficult to interpret, particularly if the compiler outputs the whole chain of template instantiations.
</p></li><li><p>
The C++ Standard suggests a template nesting level of 17 to help detect infinite recursion.
Complex lambda templates can easily exceed this limit.
Most compilers allow a greater number of nested templates, but commonly require the limit explicitly increased with a command line argument.
</p></li></ul></div></p></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="id2807495"></a>7.3. Portability</h3></div></div><p>
The BLL works with the following compilers, that is, the compilers are capable of compiling the test cases that are included with the BLL:
<div class="itemizedlist"><ul type="disc"><li>GCC 3.0.2
</li><li>KCC 4.0f with EDG 2.43.1
</li><li>GCC 2.96 (fails with one test case, the <tt>exception_test.cpp</tt> results in an internal compiler error.
)
</li></ul></div>
</p><div class="section"><div class="titlepage"><div><h4 class="title"><a name="id2807535"></a>7.3.1. Test coverage</h4></div></div><p>The following list describes the test files included and the features that each file covers:
<div class="itemizedlist"><ul type="disc"><li><p>
<tt>bind_tests_simple.cpp</tt> : Bind expressions of different arities and types of target functions: function pointers, function objects and member functions.
Function composition with bind expressions.</p></li><li><p><tt>bind_tests_simple_function_references.cpp</tt> :
Repeats all tests from <tt>bind_tests_simple.cpp</tt> where the target function is a function pointer, but uses function references instead.
</p></li><li><p><tt>bind_tests_advanced.cpp</tt> : Contains tests for nested bind expressions, <tt>unlambda</tt>, <tt>protect</tt>, <tt>const_parameters</tt> and <tt>break_const</tt>.
Tests passing lambda functors as actual arguments to other lambda functors, currying, and using the <tt>sig</tt> template to specify the return type of a function object.
</p></li><li><p>
<tt>operator_tests_simple.cpp</tt> :
Tests using all operators that are overloaded for lambda expressions, that is, unary and binary arithmetic,
bitwise,
comparison,
logical,
increment and decrement,
compound,
assignment,
subscrict,
address of,
dereference, and comma operators.
The streaming nature of shift operators is tested, as well as pointer arithmetic with plus and minus operators.
</p></li><li><p><tt>member_pointer_test.cpp</tt> : The pointer to member operator is complex enough to warrant a separate test file.
</p></li><li><p>
<tt>control_structures.cpp</tt> :
Tests for the looping and if constructs.
</p></li><li><p>
<tt>switch_construct.cpp</tt> :
Includes tests for all supported arities of the switch statement, both with and without the default case.
</p></li><li><p>
<tt>exception_test.cpp</tt> :
Includes tests for throwing exceptions and for try/catch constructs with varying number of catch blocks.
</p></li><li><p>
<tt>constructor_tests.cpp</tt> :
Contains tests for <tt>constructor</tt>, <tt>destructor</tt>, <tt>new_ptr</tt>, <tt>delete_ptr</tt>, <tt>new_array</tt> and <tt>delete_array</tt>.
</p></li><li><p>
<tt>cast_test.cpp</tt> : Tests for the four cast expressions, as well as <tt>typeid</tt> and <tt>sizeof</tt>.
</p></li><li><p>
<tt>extending_return_type_traits.cpp</tt> : Tests extending the return type deduction system for user defined types.
Contains several user defined operators and the corresponding specializations for the return type deduction templates.
</p></li><li><p>
<tt>is_instance_of_test.cpp</tt> : Includes tests for an internally used traits template, which can detect whether a given type is an instance of a certain template or not.
</p></li><li><p>
<tt>bll_and_function.cpp</tt> :
Contains tests for using <tt>boost::function</tt> together with lambda functors.
</p></li></ul></div>
</p></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ar01s06.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="index.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="ar01s08.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">6. Extending return type deduction system </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> 8. Relation to other Boost libraries</td></tr></table></div></body></html>

143
doc/ar01s08.html Normal file
View File

@@ -0,0 +1,143 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head><meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type"><title>8. Relation to other Boost libraries</title><meta name="generator" content="DocBook XSL Stylesheets V1.48"><link rel="home" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="up" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="previous" href="ar01s07.html" title="7. Practical considerations"><link rel="next" href="ar01s09.html" title="9. Contributors"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">8. Relation to other Boost libraries</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ar01s07.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="ar01s09.html">Next</a></td></tr></table><hr></div><div class="section"><div class="titlepage"><div><h2 class="title" style="clear: both"><a name="id2807880"></a>8. Relation to other Boost libraries</h2></div></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="id2807887"></a>8.1. Boost Function</h3></div></div><p>Sometimes it is convenient to store lambda functors in variables.
However, the types of even the simplest lambda functors are long and unwieldy, and it is in general unfeasible to declare variables with lambda functor types.
<span class="emphasis"><i>The Boost Function library</i></span> [<a href="bi01.html#cit:boost::function" title="[function]">function</a>] defines wrappers for (almost) arbitrary function objects; and these wrappers have types that are easy to type out.
For example:
<pre class="programlisting">
int foo(float, char);
boost::function&lt;int, float, char&gt; f = foo;
boost::function&lt;int, int, int&gt; g = std::plus&lt;int&gt;();
</pre>
The return and parameter types of the wrapped function object must be written explicilty as template arguments to the wrapper template <tt>boost::function</tt>; even when lambda functors, which otherwise have generic parameters, are wrapped.
Wrapping a function object with <tt>boost::function</tt> introduces a performance cost comparable to virtual function dispatch, though virtual functions are not actually used.
</p><p>
Due to a technical conflict between the two libraries, lambda functors cannot be directly wrapped with <tt>boost::function</tt> (this may be resolved in the future).
However, applying the <tt>unlambda</tt> (see <a href="ar01s05.html#sect:unlambda" title="5.9.1.1. Unlambda">Section 5.9.1.1</a>) function to a lambda functor gives a function object that is compatible with <tt>boost::function</tt>.
For example:
<pre class="programlisting">
boost::function&lt;int, int, int&gt; f = unlambda(_1 + _2);
f(1, 2); // returns 3
</pre>
<pre class="programlisting">
int i = 1;
boost::function&lt;int&amp;, int&amp;&gt; g = unlambda(_1 += 10);
g(i); // i == 11;
</pre>
Note that storing lambda functors inside <tt>boost::function</tt> introduces a danger.
Certain types of lambda functors may store references to the bound arguments, instead as taking copies of the arguments of the lambda expression.
When temporary lambda functor objects are used
in STL algorithm invocations this is always safe, as the lambda functor gets destructed immediately after the STL algortihm invocation is completed.
However, a lambda functor wrapped inside <tt>boost::function</tt> may continue to exist longer, creating the possibility of dangling references.
For example:
<pre class="programlisting">
int* sum = new int();
*sum = 0;
boost::function&lt;int&amp;, int&gt; counter = unlambda(*sum += _1);
counter(5); // ok, *sum = 5;
delete sum;
counter(3); // error, *sum does not exist anymore
</pre>
</p></div><div class="section"><div class="titlepage"><div><h3 class="title"><a name="id2808050"></a>8.2. Boost Bind</h3></div></div><p>
<span class="emphasis"><i>The Boost Bind</i></span> [<a href="bi01.html#cit:boost::bind" title="[bind]">bind</a>] library has partially overlapping functionality with the BLL.
Basically, the Boost Bind library (BB in the sequel) implements the bind expression part of BLL.
There are, however, some semantical differerences.
</p><p>
The BLL and BB evolved separately, and have different implementations.
This means that the bind expressions from the BB cannot be used within bind expressions, or within other type of lambda expressions, of the BLL.
The same holds for using BLL bind expressions in the BB.
The libraries can coexist, however, as
the names of the BB library are in <tt>boost</tt> namespace, whereas the BLL names are in <tt>boost::lambda</tt> namespace.
</p><p>
The BLL requires a compiler that is reasonably conformant to the C++ standard, whereas the BB library is more portable, and works witha a larger set of compilers.
</p><p>
The following two sections describe what are the semantic differences between the bind expressions in BB and BLL.
</p><div class="section"><div class="titlepage"><div><h4 class="title"><a name="id2808116"></a>8.2.1. First argument of bind expression</h4></div></div>
In BB the first argument of the bind expression, the target function, is treated differently from the other arguments,
as no argument substitution takes place within that argument.
In BLL the first argument is not a special case in this respect.
For example:
<pre class="programlisting">
template&lt;class F&gt;
int foo(const F&amp; f) {
int x;
..
bind(f, _1)(x);
...
}
</pre><pre class="programlisting">
int bar(int, int);
nested(bind(bar, 1, _1));
</pre>
The bind expression inside <tt>foo</tt> becomes:
<pre class="programlisting">
bind(bind(bar, 1, _1), _1)(x)
</pre>
The BLL interpretes this as:
<pre class="programlisting">
bar(1, x)(x)
</pre>
whereas the BB library as
<pre class="programlisting">
bar(1, x)
</pre>
To get this functionality in BLL, the bind expression inside the <tt>foo</tt> function can be written as:
<pre class="programlisting">
bind(unlambda(f), _1)(x);
</pre>
as explained in <a href="ar01s05.html#sect:unlambda" title="5.9.1.1. Unlambda">Section 5.9.1.1</a>.
</div><div class="section"><div class="titlepage"><div><h4 class="title"><a name="id2808206"></a>8.2.2.
Arity of function objects
</h4></div></div><p>
In both libraries, the highest placeholder index in a bind expression determines the arity of the resulting function object.
However, in the BB library, this is kind of a minimal arity, as the function object can take arbitrarily many arguments; those not needed are discarded.
Consider the two bind expressions and their invocations below:
<pre class="programlisting">
bind(g, _3, _3, _3)(x, y, z);
bind(g, _1, _1, _1)(x, y, z);
</pre>
This first line ends up making the call:
<pre class="programlisting">
g(z, z, z)
</pre>
in both libraries.
The second line is treated differently.
In BLL a compile time error will result, whereas BB will silently ignore the superfluous arguments and invoke:
<pre class="programlisting">
g(x, x, x)
</pre>
In this tradeoff between safety and flexibility, BLL takes the safer route.
Note however, that it is easy to write a lambda functor that would make the above call to
<tt>g(x, x, x)</tt> discarding all but the first argument:
<pre class="programlisting">
(_3, bind(g, _1, _1, _1))(x, y, z);
</pre>
This lambda expression takes three arguments.
The left-hand argument of the comma operator does nothing, and as comma returns the result of evaluating the right-hand argument we end up with the call
<tt>g(x, x, x)</tt>.
</p></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ar01s07.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="index.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="ar01s09.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">7. Practical considerations </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> 9. Contributors</td></tr></table></div></body></html>

13
doc/ar01s09.html Normal file
View File

@@ -0,0 +1,13 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head><meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type"><title>9. Contributors</title><meta name="generator" content="DocBook XSL Stylesheets V1.48"><link rel="home" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="up" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="previous" href="ar01s08.html" title="8. Relation to other Boost libraries"><link rel="next" href="bi01.html" title="Bibliography"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">9. Contributors</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ar01s08.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="bi01.html">Next</a></td></tr></table><hr></div><div class="section"><div class="titlepage"><div><h2 class="title" style="clear: both"><a name="id2808282"></a>9. Contributors</h2></div></div>
The main body of the library was written by Jaakko Järvi and Gary Powell.
We've got outside help, suggestions and ideas from Jeremy Siek, Peter Higley, Peter Dimov, Valentin Bonnard, William Kempf.
</div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ar01s08.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="index.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="bi01.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">8. Relation to other Boost libraries </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Bibliography</td></tr></table></div></body></html>

18
doc/bi01.html Normal file
View File

@@ -0,0 +1,18 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head><meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type"><title>Bibliography</title><meta name="generator" content="DocBook XSL Stylesheets V1.48"><link rel="home" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="up" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="previous" href="ar01s09.html" title="9. Contributors"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Bibliography</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ar01s09.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> </td></tr></table><hr></div><div id="id2808299" class="bibliography"><div class="titlepage"><div><h2 class="title"><a name="id2808299"></a>Bibliography</h2></div></div><div class="biblioentry"><a name="cit:stepanov:94"></a><p>[STL94] <span class="authorgroup">A. A. Stepanov and M. Lee. </span><span class="title"><I>The Standard Template Library</I>. </span><span class="orgname">Hewlett-Packard Laboratories. </span><span class="pubdate">1994. </span><span class="bibliomisc">
<a href="http://www.hpl.hp.com/techreports" target="_top">www.hpl.hp.com/techreports</a>
. </span></p></div><div class="biblioentry"><a name="cit:sgi:02"></a><p>[SGI02] <span class="title"><I>The SGI Standard Template Library</I>. </span><span class="pubdate">2002. </span><span class="bibliomisc"><a href="http://www.sgi.com/tech/stl/" target="_top">www.sgi.com/tech/stl/</a>. </span></p></div><div class="biblioentry"><a name="cit:c++:98"></a><p>[C++98] <span class="title"><I>International Standard, Programming Languages &#8211; C++</I>. </span><span class="subtitle">ISO/IEC:14882. </span><span class="pubdate">1998. </span></p></div><div class="biblioentry"><a name="cit:jarvi:99"></a><p>[Jär99] <span class="articleinfo">
<span class="author">Jaakko Järvi. </span>
<span class="title"><I>C++ Function Object Binders Made Easy</I>. </span>
. </span><span class="title"><I>Lecture Notes in Computer Science</I>. </span><span class="volumenum">1977. </span><span class="publishername">Springer. </span><span class="pubdate">2000. </span></p></div><div class="biblioentry"><a name="cit:jarvi:00"></a><p>[Jär00] <span class="author">Jaakko Järvi. </span><span class="author">Gary Powell. </span><span class="title"><I>The Lambda Library : Lambda Abstraction in C++</I>. </span><span class="orgname">Turku Centre for Computer Science. </span><span class="bibliomisc">Technical Report . </span><span class="issuenum">378. </span><span class="pubdate">2000. </span><span class="bibliomisc"><a href="http://www.tucs.fi/Publications/techreports/TR378.php" target="_top">www.tucs.fi/publications</a>. </span></p></div><div class="biblioentry"><a name="cit:jarvi:01"></a><p>[Jär01] <span class="author">Jaakko Järvi. </span><span class="author">Gary Powell. </span><span class="title"><I>The Lambda Library : Lambda Abstraction in C++</I>. </span><span class="confgroup"><span class="conftitle">Second Workshop on C++ Template Programming. </span><span class="address">Tampa Bay, OOPSLA'01. </span>. </span><span class="pubdate">2001. </span><span class="bibliomisc"><a href="http://www.oonumerics.org/tmpw01/" target="_top">www.oonumerics.org/tmpw01/</a>. </span></p></div><div class="biblioentry"><a name="cit:boost::tuple"></a><p>[tuple] <span class="title"><I>The Boost Tuple Library</I>. </span><span class="bibliomisc"><a href="http://www.boost.org/libs/tuple/doc/tuple_users_guide.html" target="_top">www.boost.org/libs/tuple/doc/tuple_users_guide.html</a>
. </span><span class="pubdate">2002. </span></p></div><div class="biblioentry"><a name="cit:boost::type_traits"></a><p>[type_traits] <span class="title"><I>The Boost type_traits</I>. </span><span class="bibliomisc"><a href="http://www.boost.org/libs/type_traits/index.htm" target="_top">www.boost.org/libs/type_traits/</a>
. </span><span class="pubdate">2002. </span></p></div><div class="biblioentry"><a name="cit:boost::ref"></a><p>[ref] <span class="title"><I>Boost ref</I>. </span><span class="bibliomisc"><a href="http://www.boost.org/libs/bind/ref.html" target="_top">www.boost.org/libs/bind/ref.html</a>
. </span><span class="pubdate">2002. </span></p></div><div class="biblioentry"><a name="cit:boost::bind"></a><p>[bind] <span class="title"><I>Boost Bind Library</I>. </span><span class="bibliomisc"><a href="http://www.boost.org/libs/bind/bind.html" target="_top">www.boost.org/libs/bind/bind.html</a>
. </span><span class="pubdate">2002. </span></p></div><div class="biblioentry"><a name="cit:boost::function"></a><p>[function] <span class="title"><I>Boost Function Library</I>. </span><span class="bibliomisc"><a href="http://www.boost.org/libs/function/" target="_top">www.boost.org/libs/function/</a>
. </span><span class="pubdate">2002. </span></p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ar01s09.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="index.html">Up</a></td><td width="40%" align="right"> </td></tr><tr><td width="40%" align="left" valign="top">9. Contributors </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> </td></tr></table></div></body></html>

View File

@@ -1,7 +0,0 @@
- lambda_doc.xml is a DocBook xml file from which the lambda docs are
generated
- lambda_doc_chunks.xsl loads the stylesheets that generate a separate
html-file for each section
- lambda_doc.xsl loads stylesheets that generate one big html-file
(you need to edit the paths in these files to make them work)

File diff suppressed because it is too large Load Diff

View File

@@ -1,19 +0,0 @@
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version='1.0'
xmlns="http://www.w3.org/TR/xhtml1/transitional"
exclude-result-prefixes="#default">
<xsl:import href="/u/jajarvi/dtd/docbook-xsl/html/docbook.xsl"/>
<!-- Add other variable definitions here -->
<xsl:variable name="shade.verbatim">0</xsl:variable>
<xsl:variable name="section.autolabel">1</xsl:variable>
<xsl:variable name="bibliography.collection">lambda_bib.xml</xsl:variable>
</xsl:stylesheet>

View File

@@ -1,19 +0,0 @@
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version='1.0'
xmlns="http://www.w3.org/TR/xhtml1/transitional"
exclude-result-prefixes="#default">
<xsl:import href="/u/jajarvi/dtd/docbook-xsl/html/chunk.xsl"/>
<!-- Add other variable definitions here -->
<xsl:variable name="shade.verbatim">0</xsl:variable>
<xsl:variable name="section.autolabel">1</xsl:variable>
<xsl:variable name="bibliography.collection">lambda_bib.xml</xsl:variable>
</xsl:stylesheet>

View File

@@ -1,12 +1,37 @@
<html>
<head>
<meta http-equiv="refresh" content="0; URL=../../../doc/html/lambda.html">
</head>
<body>
Automatic redirection failed, please go to <a href="../../../doc/html/lambda.html">www.boost.org/doc/html/lambda.html</a>&nbsp;<hr>
<p>© Copyright Beman Dawes, 2001</p>
<p>Distributed under the Boost Software License, Version 1.0. (See accompanying
file <a href="../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy
at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
</body>
</html>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head><meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type"><title>
C++ BOOST
The Boost Lambda Library</title><meta name="generator" content="DocBook XSL Stylesheets V1.48"><link rel="home" href="index.html" title="
C++ BOOST
The Boost Lambda Library"><link rel="next" href="ar01s02.html" title="2. Getting Started"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">
C++ BOOST
The Boost Lambda Library</th></tr><tr><td width="20%" align="left"> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="ar01s02.html">Next</a></td></tr></table><hr></div><div class="article"><div class="titlepage"><div><h1 class="title"><a name="id2733458"></a>
<span class="inlinemediaobject"><img src="../../../c++boost.gif" alt="C++ BOOST"></span>
The Boost Lambda Library</h1></div><div><p class="copyright">Copyright © 1999-2002 Jaakko Järvi, Gary Powell</p></div><div><div class="legalnotice"><p>
The Boost Lambda Library is free software; Permission to copy,
use, modify and distribute this software and its documentation is granted, provided this copyright
notice appears in all copies.
</p></div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt>1. <a href="index.html#introduction">In a nutshell</a></dt><dt>2. <a href="ar01s02.html">Getting Started</a></dt><dd><dl><dt>2.1. <a href="ar01s02.html#id2790112">Installing the library</a></dt><dt>2.2. <a href="ar01s02.html#id2742926">Conventions used in this document</a></dt></dl></dd><dt>3. <a href="ar01s03.html">Introduction</a></dt><dd><dl><dt>3.1. <a href="ar01s03.html#id2742980">Motivation</a></dt><dt>3.2. <a href="ar01s03.html#id2741408">Introduction to lambda expressions</a></dt></dl></dd><dt>4. <a href="ar01s04.html">Using the library</a></dt><dd><dl><dt>4.1. <a href="ar01s04.html#sect:introductory_examples">Introductory Examples</a></dt><dt>4.2. <a href="ar01s04.html#sect:parameter_and_return_types">Parameter and return types of lambda functors</a></dt><dt>4.3. <a href="ar01s04.html#sect:actual_arguments_to_lambda_functors">About actual arguments to lambda functors</a></dt><dt>4.4. <a href="ar01s04.html#sect:storing_bound_arguments">Storing bound arguments in lambda functions</a></dt></dl></dd><dt>5. <a href="ar01s05.html">Lambda expressions in details</a></dt><dd><dl><dt>5.1. <a href="ar01s05.html#sect:placeholders">Placeholders</a></dt><dt>5.2. <a href="ar01s05.html#sect:operator_expressions">Operator expressions</a></dt><dt>5.3. <a href="ar01s05.html#sect:bind_expressions">Bind expressions</a></dt><dt>5.4. <a href="ar01s05.html#sect:overriding_deduced_return_type">Overriding the deduced return type</a></dt><dt>5.5. <a href="ar01s05.html#sect:delaying_constants_and_variables">Delaying constants and variables</a></dt><dt>5.6. <a href="ar01s05.html#sect:lambda_expressions_for_control_structures">Lambda expressions for control structures</a></dt><dt>5.7. <a href="ar01s05.html#sect:exceptions">Exceptions</a></dt><dt>5.8. <a href="ar01s05.html#sect:construction_and_destruction">Construction and destruction</a></dt><dt>5.9. <a href="ar01s05.html#id2805233">Special lambda expressions</a></dt><dt>5.10. <a href="ar01s05.html#id2805803">Casts, sizeof and typeid</a></dt><dt>5.11. <a href="ar01s05.html#sect:nested_stl_algorithms">Nesting STL algorithm invocations</a></dt></dl></dd><dt>6. <a href="ar01s06.html">Extending return type deduction system</a></dt><dt>7. <a href="ar01s07.html">Practical considerations</a></dt><dd><dl><dt>7.1. <a href="ar01s07.html#id2807383">Performance</a></dt><dt>7.2. <a href="ar01s07.html#id2807426">About compiling</a></dt><dt>7.3. <a href="ar01s07.html#id2807495">Portability</a></dt></dl></dd><dt>8. <a href="ar01s08.html">Relation to other Boost libraries</a></dt><dd><dl><dt>8.1. <a href="ar01s08.html#id2807887">Boost Function</a></dt><dt>8.2. <a href="ar01s08.html#id2808050">Boost Bind</a></dt></dl></dd><dt>9. <a href="ar01s09.html">Contributors</a></dt><dt><a href="bi01.html">Bibliography</a></dt></dl></div><div class="section"><div class="titlepage"><div><h2 class="title" style="clear: both"><a name="introduction"></a>1. In a nutshell</h2></div></div><p>
The Boost Lambda Library (BLL in the sequel) is a C++ template
library, which implements form of <span class="emphasis"><i>lambda abstractions</i></span> for C++.
The term originates from functional programming and lambda calculus, where a lambda abstraction defines an unnamed function.
The primary motivation for the BLL is to provide flexible and
convenient means to define unnamed function objects for STL algorithms.
In explaining what the library is about, a line of code says more than a thousand words; the
following line outputs the elements of some STL container
<tt>a</tt> separated by spaces:
<pre class="programlisting">for_each(a.begin(), a.end(), std::cout &lt;&lt; _1 &lt;&lt; ' ');</pre>
The expression <tt>std::cout &lt;&lt; _1 &lt;&lt; ' '</tt> defines a unary function object.
The variable <tt>_1</tt> is the parameter of this function, a <span class="emphasis"><i>placeholder</i></span> for the actual argument.
Within each iteration of <tt>for_each</tt>, the function is
called with an element of <tt>a</tt> as the actual argument.
This actual argument is substituted for the placeholder, and the &#8216;body&#8217; of the function is evaluated.
</p><p>The essence of BLL is letting you define small unnamed function objects, such as the one above, directly on the call site of an STL algorithm.
</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="ar01s02.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top"> </td><td width="20%" align="center"> </td><td width="40%" align="right" valign="top"> 2. Getting Started</td></tr></table></div></body></html>

File diff suppressed because it is too large Load Diff

1646
doc/lambda_doc.html Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,82 @@
#include "boost/lambda/lambda.hpp"
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
#include <functional>
void begin_section(std::string name) {
std::cout << "-------------------------------------------------------\n";
std::cout << name << '\n';
std::cout << "-------------------------------------------------------\n";
return;
};
void end_section() {
std::cout << "-------------------------------------------------------\n";
return;
};
template<class Test>
void call_test(Test t, std::string name)
{
begin_section(name);
t();
end_section();
};
void introduction() {
using boost::lambda::_1;
std::cout << "Output should be: 1 2\n";
std::vector<int> a; a.push_back(1); a.push_back(2);
for_each(a.begin(), a.end(), std::cout << _1 << ' ');
std::cout << '\n';
return;
}
void motivation() {
using std::vector;
using std::ostream_iterator;
using std::cout;
using std::bind1st;
using std::plus;
using std::transform;
using std::for_each;
vector<int> a; a.push_back(1); a.push_back(2);
std::cout << "Output should be: 23 = 23 = 23\n";
transform(a.begin(), a.end(), ostream_iterator<int>(cout),
bind1st(plus<int>(), 1));
using boost::lambda::_1;
cout << " = ";
transform(a.begin(), a.end(), ostream_iterator<int>(cout), 1 + _1);
cout << " = ";
for_each(a.begin(), a.end(), cout << (_1 + 1));
std::cout << '\n';
return;
}
int main() {
using std::cout;
call_test(introduction, "introduction"); cout << '\n';
call_test(motivation, "Motivation"); cout << '\n';
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,16 @@
// -- bind.hpp -- Boost Lambda Library --------------------------------------
// Copyright (C) 1999-2001 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 1999-2001 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
// Gary Powell (gwpowell@hotmail.com)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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
@@ -14,11 +19,6 @@
#include "boost/lambda/core.hpp"
// Required for std::is_assignable to work on the result of bind()
#include "boost/lambda/detail/operator_actions.hpp"
#include "boost/lambda/detail/operator_lambda_func_base.hpp"
#include "boost/lambda/detail/operator_return_type_traits.hpp"
#include "boost/lambda/detail/bind_functions.hpp"
#endif

View File

@@ -1,11 +1,16 @@
// - casts.hpp -- BLambda Library -------------
//
// Copyright (C) 2000 Gary Powell (powellg@amazon.com)
// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2000 Gary Powell (gary.powell@sierra.com)
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
//
// 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)
// 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
@@ -14,17 +19,11 @@
#if !defined(BOOST_LAMBDA_CASTS_HPP)
#define BOOST_LAMBDA_CASTS_HPP
#include "boost/lambda/detail/suppress_unused.hpp"
#include "boost/lambda/core.hpp"
#include <typeinfo>
namespace boost {
namespace lambda {
template<class Act, class Args>
struct return_type_N;
template<class T> class cast_action;
template<class T> class static_cast_action;
@@ -33,10 +32,10 @@ template<class T> class const_cast_action;
template<class T> class reinterpret_cast_action;
class typeid_action;
class sizeof_action;
// Cast actions
template<class T> class cast_action<static_cast_action<T> >
{
public:
@@ -70,12 +69,11 @@ public:
}
};
// typeid action
// typedid action
class typeid_action {
public:
template<class RET, class Arg1>
static RET apply(Arg1 &a1) {
detail::suppress_unused_variable_warnings(a1);
return typeid(a1);
}
};
@@ -93,21 +91,28 @@ public:
// return types of casting lambda_functors (all "T" type.)
template<template <class> class cast_type, class T, class A>
struct return_type_N<cast_action< cast_type<T> >, A> {
template<template <class T> class cast_type, class T, class Args, int Code, class Open>
struct return_type<lambda_functor_args<action<1, cast_action< cast_type<T> > >, Args, Code>,
Open>
{
typedef T type;
};
// return type of typeid_action
template<class A>
struct return_type_N<typeid_action, A> {
template<class Args, int Code, class Open>
struct return_type<lambda_functor_args<action<1, typeid_action >, Args, Code>,
Open>
{
typedef std::type_info const & type;
};
// return type of sizeof_action
template<class A>
struct return_type_N<sizeof_action, A> {
template<class Args, int Code, class Open>
struct return_type<lambda_functor_args<action<1, sizeof_action >, Args, Code>,
Open >
{
typedef std::size_t type;
};
@@ -118,69 +123,85 @@ struct return_type_N<sizeof_action, A> {
// static_cast
template <class T, class Arg1>
inline const lambda_functor<
lambda_functor_base<
action<1, cast_action<static_cast_action<T> > >,
tuple<typename const_copy_argument <const Arg1>::type>
lambda_functor_args<
action<1,
cast_action<static_cast_action<T> >
>,
tuple<typename const_copy_argument <const Arg1>::type>,
dig_arity<Arg1>::value
>
>
ll_static_cast(const Arg1& a1) {
return
lambda_functor_base<
action<1, cast_action<static_cast_action<T> > >,
tuple<typename const_copy_argument <const Arg1>::type>
>
( tuple<typename const_copy_argument <const Arg1>::type>(a1));
return lambda_functor< lambda_functor_args<
action<1,
cast_action<static_cast_action<T> >
>,
tuple<typename const_copy_argument <const Arg1>::type>,
dig_arity<Arg1>::value> >
( tuple<typename const_copy_argument <const Arg1>::type>(a1));
}
// dynamic_cast
template <class T, class Arg1>
inline const lambda_functor<
lambda_functor_base<
action<1, cast_action<dynamic_cast_action<T> > >,
tuple<typename const_copy_argument <const Arg1>::type>
lambda_functor_args<
action<1,
cast_action<dynamic_cast_action<T> >
>,
tuple<typename const_copy_argument <const Arg1>::type>,
dig_arity<Arg1>::value
>
>
ll_dynamic_cast(const Arg1& a1) {
return
lambda_functor_base<
action<1, cast_action<dynamic_cast_action<T> > >,
tuple<typename const_copy_argument <const Arg1>::type>
>
( tuple<typename const_copy_argument <const Arg1>::type>(a1));
return lambda_functor< lambda_functor_args<
action<1,
cast_action<dynamic_cast_action<T> >
>,
tuple<typename const_copy_argument <const Arg1>::type>,
dig_arity<Arg1>::value> >
( tuple<typename const_copy_argument <const Arg1>::type>(a1));
}
// const_cast
template <class T, class Arg1>
inline const lambda_functor<
lambda_functor_base<
action<1, cast_action<const_cast_action<T> > >,
tuple<typename const_copy_argument <const Arg1>::type>
lambda_functor_args<
action<1,
cast_action<const_cast_action<T> >
>,
tuple<typename const_copy_argument <const Arg1>::type>,
dig_arity<Arg1>::value
>
>
ll_const_cast(const Arg1& a1) {
return
lambda_functor_base<
action<1, cast_action<const_cast_action<T> > >,
tuple<typename const_copy_argument <const Arg1>::type>
>
( tuple<typename const_copy_argument <const Arg1>::type>(a1));
return lambda_functor< lambda_functor_args<
action<1,
cast_action<const_cast_action<T> >
>,
tuple<typename const_copy_argument <const Arg1>::type>,
dig_arity<Arg1>::value> >
( tuple<typename const_copy_argument <const Arg1>::type>(a1));
}
// reinterpret_cast
template <class T, class Arg1>
inline const lambda_functor<
lambda_functor_base<
action<1, cast_action<reinterpret_cast_action<T> > >,
tuple<typename const_copy_argument <const Arg1>::type>
lambda_functor_args<
action<1,
cast_action<reinterpret_cast_action<T> >
>,
tuple<typename const_copy_argument <const Arg1>::type>,
dig_arity<Arg1>::value
>
>
ll_reinterpret_cast(const Arg1& a1) {
return
lambda_functor_base<
action<1, cast_action<reinterpret_cast_action<T> > >,
tuple<typename const_copy_argument <const Arg1>::type>
>
( tuple<typename const_copy_argument <const Arg1>::type>(a1));
return lambda_functor< lambda_functor_args<
action<1,
cast_action<reinterpret_cast_action<T> >
>,
tuple<typename const_copy_argument <const Arg1>::type>,
dig_arity<Arg1>::value> >
( tuple<typename const_copy_argument <const Arg1>::type>(a1));
}
// typeid
@@ -188,36 +209,44 @@ ll_reinterpret_cast(const Arg1& a1) {
// class object)
template <class Arg1>
inline const lambda_functor<
lambda_functor_base<
action<1, typeid_action>,
tuple<typename const_copy_argument <const Arg1>::type>
lambda_functor_args<
action<1,
typeid_action
>,
tuple<typename const_copy_argument <const Arg1>::type>,
dig_arity<Arg1>::value
>
>
ll_typeid(const Arg1& a1) {
return
lambda_functor_base<
action<1, typeid_action>,
tuple<typename const_copy_argument <const Arg1>::type>
>
( tuple<typename const_copy_argument <const Arg1>::type>(a1));
return lambda_functor<lambda_functor_args<
action<1,
typeid_action
>,
tuple<typename const_copy_argument <const Arg1>::type>,
dig_arity<Arg1>::value> >
( tuple<typename const_copy_argument <const Arg1>::type>(a1));
}
// sizeof(expression)
// Always takes a lambda expression (if not, built in sizeof will do)
template <class Arg1>
inline const lambda_functor<
lambda_functor_base<
lambda_functor_args<
action<1, sizeof_action>,
tuple<lambda_functor<Arg1> >
tuple<lambda_functor<Arg1> >,
dig_arity<Arg1>::value
>
>
ll_sizeof(const lambda_functor<Arg1>& a1) {
return
lambda_functor_base<
lambda_functor<
lambda_functor_args<
action<1, sizeof_action>,
tuple<lambda_functor<Arg1> >
tuple<lambda_functor<Arg1> >,
dig_arity<Arg1>::value
>
( tuple<lambda_functor<Arg1> >(a1));
>
( tuple<lambda_functor<Arg1> >(a1));
}
} // namespace lambda

View File

@@ -1,274 +0,0 @@
/*=============================================================================
Adaptable closures
Phoenix V0.9
Copyright (c) 2001-2002 Joel de Guzman
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)
URL: http://spirit.sourceforge.net/
==============================================================================*/
#ifndef BOOST_LAMBDA_CLOSURES_HPP
#define BOOST_LAMBDA_CLOSURES_HPP
///////////////////////////////////////////////////////////////////////////////
#include "boost/lambda/core.hpp"
///////////////////////////////////////////////////////////////////////////////
namespace boost {
namespace lambda {
///////////////////////////////////////////////////////////////////////////////
//
// Adaptable closures
//
// The framework will not be complete without some form of closures
// support. Closures encapsulate a stack frame where local
// variables are created upon entering a function and destructed
// upon exiting. Closures provide an environment for local
// variables to reside. Closures can hold heterogeneous types.
//
// Phoenix closures are true hardware stack based closures. At the
// very least, closures enable true reentrancy in lambda functions.
// A closure provides access to a function stack frame where local
// variables reside. Modeled after Pascal nested stack frames,
// closures can be nested just like nested functions where code in
// inner closures may access local variables from in-scope outer
// closures (accessing inner scopes from outer scopes is an error
// and will cause a run-time assertion failure).
//
// There are three (3) interacting classes:
//
// 1) closure:
//
// At the point of declaration, a closure does not yet create a
// stack frame nor instantiate any variables. A closure declaration
// declares the types and names[note] of the local variables. The
// closure class is meant to be subclassed. It is the
// responsibility of a closure subclass to supply the names for
// each of the local variable in the closure. Example:
//
// struct my_closure : closure<int, string, double> {
//
// member1 num; // names the 1st (int) local variable
// member2 message; // names the 2nd (string) local variable
// member3 real; // names the 3rd (double) local variable
// };
//
// my_closure clos;
//
// Now that we have a closure 'clos', its local variables can be
// accessed lazily using the dot notation. Each qualified local
// variable can be used just like any primitive actor (see
// primitives.hpp). Examples:
//
// clos.num = 30
// clos.message = arg1
// clos.real = clos.num * 1e6
//
// The examples above are lazily evaluated. As usual, these
// expressions return composite actors that will be evaluated
// through a second function call invocation (see operators.hpp).
// Each of the members (clos.xxx) is an actor. As such, applying
// the operator() will reveal its identity:
//
// clos.num() // will return the current value of clos.num
//
// *** [note] Acknowledgement: Juan Carlos Arevalo-Baeza (JCAB)
// introduced and initilally implemented the closure member names
// that uses the dot notation.
//
// 2) closure_member
//
// The named local variables of closure 'clos' above are actually
// closure members. The closure_member class is an actor and
// conforms to its conceptual interface. member1..memberN are
// predefined typedefs that correspond to each of the listed types
// in the closure template parameters.
//
// 3) closure_frame
//
// When a closure member is finally evaluated, it should refer to
// an actual instance of the variable in the hardware stack.
// Without doing so, the process is not complete and the evaluated
// member will result to an assertion failure. Remember that the
// closure is just a declaration. The local variables that a
// closure refers to must still be instantiated.
//
// The closure_frame class does the actual instantiation of the
// local variables and links these variables with the closure and
// all its members. There can be multiple instances of
// closure_frames typically situated in the stack inside a
// function. Each closure_frame instance initiates a stack frame
// with a new set of closure local variables. Example:
//
// void foo()
// {
// closure_frame<my_closure> frame(clos);
// /* do something */
// }
//
// where 'clos' is an instance of our closure 'my_closure' above.
// Take note that the usage above precludes locally declared
// classes. If my_closure is a locally declared type, we can still
// use its self_type as a paramater to closure_frame:
//
// closure_frame<my_closure::self_type> frame(clos);
//
// Upon instantiation, the closure_frame links the local variables
// to the closure. The previous link to another closure_frame
// instance created before is saved. Upon destruction, the
// closure_frame unlinks itself from the closure and relinks the
// preceding closure_frame prior to this instance.
//
// The local variables in the closure 'clos' above is default
// constructed in the stack inside function 'foo'. Once 'foo' is
// exited, all of these local variables are destructed. In some
// cases, default construction is not desirable and we need to
// initialize the local closure variables with some values. This
// can be done by passing in the initializers in a compatible
// tuple. A compatible tuple is one with the same number of
// elements as the destination and where each element from the
// destination can be constructed from each corresponding element
// in the source. Example:
//
// tuple<int, char const*, int> init(123, "Hello", 1000);
// closure_frame<my_closure> frame(clos, init);
//
// Here now, our closure_frame's variables are initialized with
// int: 123, char const*: "Hello" and int: 1000.
//
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//
// closure_frame class
//
///////////////////////////////////////////////////////////////////////////////
template <typename ClosureT>
class closure_frame : public ClosureT::tuple_t {
public:
closure_frame(ClosureT& clos)
: ClosureT::tuple_t(), save(clos.frame), frame(clos.frame)
{ clos.frame = this; }
template <typename TupleT>
closure_frame(ClosureT& clos, TupleT const& init)
: ClosureT::tuple_t(init), save(clos.frame), frame(clos.frame)
{ clos.frame = this; }
~closure_frame()
{ frame = save; }
private:
closure_frame(closure_frame const&); // no copy
closure_frame& operator=(closure_frame const&); // no assign
closure_frame* save;
closure_frame*& frame;
};
///////////////////////////////////////////////////////////////////////////////
//
// closure_member class
//
///////////////////////////////////////////////////////////////////////////////
template <int N, typename ClosureT>
class closure_member {
public:
typedef typename ClosureT::tuple_t tuple_t;
closure_member()
: frame(ClosureT::closure_frame_ref()) {}
template <typename TupleT>
struct sig {
typedef typename detail::tuple_element_as_reference<
N, typename ClosureT::tuple_t
>::type type;
};
template <class Ret, class A, class B, class C>
// typename detail::tuple_element_as_reference
// <N, typename ClosureT::tuple_t>::type
Ret
call(A&, B&, C&) const
{
assert(frame);
return boost::tuples::get<N>(*frame);
}
private:
typename ClosureT::closure_frame_t*& frame;
};
///////////////////////////////////////////////////////////////////////////////
//
// closure class
//
///////////////////////////////////////////////////////////////////////////////
template <
typename T0 = null_type,
typename T1 = null_type,
typename T2 = null_type,
typename T3 = null_type,
typename T4 = null_type
>
class closure {
public:
typedef tuple<T0, T1, T2, T3, T4> tuple_t;
typedef closure<T0, T1, T2, T3, T4> self_t;
typedef closure_frame<self_t> closure_frame_t;
closure()
: frame(0) { closure_frame_ref(&frame); }
closure_frame_t& context() { assert(frame); return frame; }
closure_frame_t const& context() const { assert(frame); return frame; }
typedef lambda_functor<closure_member<0, self_t> > member1;
typedef lambda_functor<closure_member<1, self_t> > member2;
typedef lambda_functor<closure_member<2, self_t> > member3;
typedef lambda_functor<closure_member<3, self_t> > member4;
typedef lambda_functor<closure_member<4, self_t> > member5;
private:
closure(closure const&); // no copy
closure& operator=(closure const&); // no assign
template <int N, typename ClosureT>
friend class closure_member;
template <typename ClosureT>
friend class closure_frame;
static closure_frame_t*&
closure_frame_ref(closure_frame_t** frame_ = 0)
{
static closure_frame_t** frame = 0;
if (frame_ != 0)
frame = frame_;
return *frame;
}
closure_frame_t* frame;
};
}}
// namespace
#endif

View File

@@ -1,11 +1,16 @@
// - construct.hpp -- Lambda Library -------------
//
// Copyright (C) 2000 Gary Powell (powellg@amazon.com)
// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2000 Gary Powell (gary.powell@sierra.com)
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
//
// 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)
// 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
//
@@ -14,14 +19,6 @@
#if !defined(BOOST_LAMBDA_CONSTRUCT_HPP)
#define BOOST_LAMBDA_CONSTRUCT_HPP
#include "boost/type_traits/remove_cv.hpp"
#include "boost/type_traits/is_pointer.hpp"
#include "boost/config.hpp"
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
#include <utility>
#endif
namespace boost {
namespace lambda {
@@ -31,14 +28,8 @@ namespace lambda {
template<class T> struct constructor {
template <class U> struct sig { typedef T type; };
typedef T result_type;
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <class... Args>
T operator()(Args&&... args) const {
return T(std::forward<Args>(args)...);
}
#else
T operator()() const {
return T();
}
@@ -92,7 +83,6 @@ template<class T> struct constructor {
T operator()(A1& a1, A2& a2, A3& a3, A4& a4, A5& a5, A6& a6, A7& a7, A8& a8, A9& a9, A10& a10) const {
return T(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
}
#endif
};
@@ -130,8 +120,8 @@ struct destructor_helper<true> {
// destructor funtion object
struct destructor {
template <class T> struct sig { typedef void type; };
typedef void result_type;
template<class A1>
void operator()(A1& a1) const {
typedef typename boost::remove_cv<A1>::type plainA1;
@@ -147,14 +137,8 @@ struct destructor {
template<class T> struct new_ptr {
template <class U> struct sig { typedef T* type; };
typedef T* result_type;
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <class... Args>
T* operator()(Args&&... args) const {
return new T(std::forward<Args>(args)...);
}
#else
T* operator()() const {
return new T();
}
@@ -208,7 +192,6 @@ template<class T> struct new_ptr {
T* operator()(A1& a1, A2& a2, A3& a3, A4& a4, A5& a5, A6& a6, A7& a7, A8& a8, A9& a9, A10& a10) const {
return new T(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
}
#endif
};
@@ -216,7 +199,7 @@ template<class T> struct new_ptr {
struct delete_ptr {
template <class U> struct sig { typedef void type; };
typedef void result_type;
template <class A1>
void operator()(A1& a1) const {
@@ -230,7 +213,7 @@ struct delete_ptr {
template<class T> struct new_array {
template <class U> struct sig { typedef T* type; };
typedef T* result_type;
T* operator()(int size) const {
return new T[size];
@@ -242,7 +225,7 @@ template<class T> struct new_array {
struct delete_array {
template <class U> struct sig { typedef void type; };
typedef void result_type;
template <class A1>
void operator()(A1& a1) const {

View File

@@ -1,9 +1,14 @@
// -- control_structures.hpp -- Boost Lambda Library --------------------------
// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
//
// 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)
// 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 www.boost.org
@@ -17,7 +22,6 @@
#include "boost/lambda/detail/operator_actions.hpp"
#include "boost/lambda/detail/operator_return_type_traits.hpp"
#include "boost/lambda/if.hpp"
#include "boost/lambda/loops.hpp"
#include "boost/lambda/detail/control_structures_impl.hpp"
#include "boost/lambda/detail/switch.hpp"
#endif

View File

@@ -1,13 +1,4 @@
// -- core.hpp -- Boost Lambda Library -------------------------------------
//
// Copyright (C) 2000 Gary Powell (powellg@amazon.com)
// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see www.boost.org
//
// Includes the core of LL, without any real features for client:
//
@@ -22,8 +13,6 @@
#ifndef BOOST_LAMBDA_CORE_HPP
#define BOOST_LAMBDA_CORE_HPP
#include "boost/config.hpp"
#include "boost/type_traits/transform_traits.hpp"
#include "boost/type_traits/cv_traits.hpp"
@@ -47,6 +36,7 @@ using ::boost::tuples::null_type;
#include "boost/lambda/detail/lambda_traits.hpp"
#include "boost/lambda/detail/function_adaptors.hpp"
#include "boost/lambda/detail/return_type_traits.hpp"
@@ -57,20 +47,20 @@ using ::boost::tuples::null_type;
#include "boost/lambda/detail/lambda_functors.hpp"
#include "boost/lambda/detail/ret.hpp"
#include "boost/lambda/detail/make_void.hpp"
namespace boost {
namespace lambda {
namespace {
// These are constants types and need to be initialised
boost::lambda::placeholder1_type free1 = boost::lambda::placeholder1_type();
boost::lambda::placeholder2_type free2 = boost::lambda::placeholder2_type();
boost::lambda::placeholder3_type free3 = boost::lambda::placeholder3_type();
boost::lambda::placeholder1_type free1;
boost::lambda::placeholder2_type free2;
boost::lambda::placeholder3_type free3;
boost::lambda::placeholder1_type& BOOST_ATTRIBUTE_UNUSED _1 = free1;
boost::lambda::placeholder2_type& BOOST_ATTRIBUTE_UNUSED _2 = free2;
boost::lambda::placeholder3_type& BOOST_ATTRIBUTE_UNUSED _3 = free3;
boost::lambda::placeholder1_type& _1 = free1;
boost::lambda::placeholder2_type& _2 = free2;
boost::lambda::placeholder3_type& _3 = free3;
// _1, _2, ... naming scheme by Peter Dimov
} // unnamed

View File

@@ -1,10 +1,15 @@
// -- Boost Lambda Library - actions.hpp ----------------------------------
// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
//
// 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)
// 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 www.boost.org
@@ -18,7 +23,7 @@ namespace lambda {
template<int Arity, class Act> class action;
template<int Arity, class Act> struct action;
// these need to be defined here, since the corresponding lambda
// functions are members of lambda_functor classes
@@ -26,38 +31,27 @@ template<int Arity, class Act> class action;
class assignment_action {};
class subscript_action {};
class identity_action {};
template <class Action> class other_action;
// action for specifying the explicit return type
template <class RET> class explicit_return_type_action {};
// action for preventing the expansion of a lambda expression
struct protect_action {};
// action for curried functions, I stands for the number of curried arguments
// (can be 1 or 2)
template <int I> class curry_action {};
template <class Action> class return_void_action;
// must be defined here, comma is a special case
struct comma_action {};
// actions, for which the existence of protect is checked in return type
// deduction.
template <class Action> struct is_protectable {
BOOST_STATIC_CONSTANT(bool, value = false);
};
// NOTE: comma action is protectable. Other protectable actions
// are listed in operator_actions.hpp
template<> struct is_protectable<other_action<comma_action> > {
BOOST_STATIC_CONSTANT(bool, value = true);
};
namespace detail {
// this type is used in return type deductions to signal that deduction
// did not find a result. It does not necessarily mean an error, it commonly
// means that something else should be tried.
class unspecified {};
}
@@ -67,15 +61,18 @@ namespace detail {
// argument of function_action template. Otherwise the argument gets the type
// 'unspecified'.
// This argument is only relevant in the return type deduction code
template <int I, class Result_type = detail::unspecified>
class function_action {};
template <int I, class Result_type = detail::unspecified> class function_action {};
// ---------------------------------------------------------
template<class T> class function_action<1, T> {
public:
template<class RET, class A1>
static RET apply(A1& a1) {
return function_adaptor<typename boost::remove_cv<A1>::type>::
template apply<RET>(a1);
return function_adaptor<typename boost::remove_const<A1>::type>::template apply<RET>(a1);
}
};
@@ -83,17 +80,23 @@ template<class T> class function_action<2, T> {
public:
template<class RET, class A1, class A2>
static RET apply(A1& a1, A2& a2) {
return function_adaptor<typename boost::remove_cv<A1>::type>::
template apply<RET>(a1, a2);
return function_adaptor<typename boost::remove_const<A1>::type>::template apply<RET>
(a1, a2);
}
};
template <class T> struct is_lambda_functor;
template<class T> class function_action<3, T> {
public:
template<class RET, class A1, class A2, class A3>
static RET apply(A1& a1, A2& a2, A3& a3) {
return function_adaptor<typename boost::remove_cv<A1>::type>::
template apply<RET>(a1, a2, a3);
return function_adaptor<typename boost::remove_const<A1>::type>::template apply<RET>
(a1, a2, a3);
}
};
@@ -101,8 +104,8 @@ template<class T> class function_action<4, T> {
public:
template<class RET, class A1, class A2, class A3, class A4>
static RET apply(A1& a1, A2& a2, A3& a3, A4& a4) {
return function_adaptor<typename boost::remove_cv<A1>::type>::
template apply<RET>(a1, a2, a3, a4);
return function_adaptor<typename boost::remove_const<A1>::type>::template apply<RET>
(a1, a2, a3, a4);
}
};
@@ -110,8 +113,8 @@ template<class T> class function_action<5, T> {
public:
template<class RET, class A1, class A2, class A3, class A4, class A5>
static RET apply(A1& a1, A2& a2, A3& a3, A4& a4, A5& a5) {
return function_adaptor<typename boost::remove_cv<A1>::type>::
template apply<RET>(a1, a2, a3, a4, a5);
return function_adaptor<typename boost::remove_const<A1>::type>::template apply<RET>
(a1, a2, a3, a4, a5);
}
};
@@ -120,8 +123,8 @@ public:
template<class RET, class A1, class A2, class A3, class A4, class A5,
class A6>
static RET apply(A1& a1, A2& a2, A3& a3, A4& a4, A5& a5, A6& a6) {
return function_adaptor<typename boost::remove_cv<A1>::type>::
template apply<RET>(a1, a2, a3, a4, a5, a6);
return function_adaptor<typename boost::remove_const<A1>::type>::template apply<RET>
(a1, a2, a3, a4, a5, a6);
}
};
@@ -130,8 +133,8 @@ public:
template<class RET, class A1, class A2, class A3, class A4, class A5,
class A6, class A7>
static RET apply(A1& a1, A2& a2, A3& a3, A4& a4, A5& a5, A6& a6, A7& a7) {
return function_adaptor<typename boost::remove_cv<A1>::type>::
template apply<RET>(a1, a2, a3, a4, a5, a6, a7);
return function_adaptor<typename boost::remove_const<A1>::type>::template apply<RET>
(a1, a2, a3, a4, a5, a6, a7);
}
};
@@ -141,8 +144,8 @@ public:
class A6, class A7, class A8>
static RET apply(A1& a1, A2& a2, A3& a3, A4& a4, A5& a5, A6& a6, A7& a7,
A8& a8) {
return function_adaptor<typename boost::remove_cv<A1>::type>::
template apply<RET>(a1, a2, a3, a4, a5, a6, a7, a8);
return function_adaptor<typename boost::remove_const<A1>::type>::template apply<RET>
(a1, a2, a3, a4, a5, a6, a7, a8);
}
};
@@ -152,8 +155,8 @@ public:
class A6, class A7, class A8, class A9>
static RET apply(A1& a1, A2& a2, A3& a3, A4& a4, A5& a5, A6& a6, A7& a7,
A8& a8, A9& a9) {
return function_adaptor<typename boost::remove_cv<A1>::type>::
template apply<RET>(a1, a2, a3, a4, a5, a6, a7, a8, a9);
return function_adaptor<typename boost::remove_const<A1>::type>::template apply<RET>
(a1, a2, a3, a4, a5, a6, a7, a8, a9);
}
};
@@ -163,11 +166,32 @@ public:
class A6, class A7, class A8, class A9, class A10>
static RET apply(A1& a1, A2& a2, A3& a3, A4& a4, A5& a5, A6& a6, A7& a7,
A8& a8, A9& a9, A10& a10) {
return function_adaptor<typename boost::remove_cv<A1>::type>::
template apply<RET>(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
return function_adaptor<typename boost::remove_const<A1>::type>::template apply<RET>
(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
}
};
// actions, for which the existence of protect is checked in return type
// deduction.
class protectable {};
namespace detail {
template<class T> struct is_protectable_action {
BOOST_STATIC_CONSTANT(bool, value = (boost::is_base_and_derived<protectable, T>::value));
};
template<> struct is_protectable_action<other_action<assignment_action> > {
BOOST_STATIC_CONSTANT(bool, value = true);
};
template<> struct is_protectable_action<other_action<comma_action> > {
BOOST_STATIC_CONSTANT(bool, value = true);
};
} // end detail
} // namespace lambda
} // namespace boost

View File

@@ -1,10 +1,15 @@
// -- Boost Lambda Library -------------------------------------------------
// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
//
// 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)
// 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 www.boost.org
@@ -27,80 +32,93 @@ namespace lambda {
// freeE placeholders and maybe free1 and free2 (EXCEPTION).
// RETHROW means, that a rethrow expression is used somewhere in the lambda_functor.
enum { NONE = 0x00, // Notice we are using bits as flags here.
FIRST = 0x01,
SECOND = 0x02,
THIRD = 0x04,
EXCEPTION = 0x08,
RETHROW = 0x10};
enum { NONE = 0x00, // Notice we are using bits as flags here.
FIRST = 0x01,
SECOND = 0x02,
THIRD = 0x04,
EXCEPTION = 0x08,
RETHROW = 0x10};
template<class T>
struct get_tuple_arity;
// -- dig the arity from lambda_functor_args;
template <class T> struct dig_arity;
namespace detail {
template <class T> struct get_arity_;
} // end detail;
template <class T> struct get_arity {
BOOST_STATIC_CONSTANT(int, value = detail::get_arity_<typename boost::remove_cv<typename boost::remove_reference<T>::type>::type>::value);
template <int Arity, int Step> struct reduce_arity
{
BOOST_STATIC_CONSTANT(int, value = Arity >> Step);
};
namespace detail {
template<class T>
struct get_arity_ {
BOOST_STATIC_CONSTANT(int, value = 0);
};
template<class T>
struct get_arity_<lambda_functor<T> > {
BOOST_STATIC_CONSTANT(int, value = get_arity<T>::value);
};
template<class Action, class Args>
struct get_arity_<lambda_functor_base<Action, Args> > {
BOOST_STATIC_CONSTANT(int, value = get_tuple_arity<Args>::value);
};
template<int I>
struct get_arity_<placeholder<I> > {
BOOST_STATIC_CONSTANT(int, value = I);
};
} // detail
template<class T>
struct get_tuple_arity {
BOOST_STATIC_CONSTANT(int, value = get_arity<typename T::head_type>::value | get_tuple_arity<typename T::tail_type>::value);
// The implementation template, do not instantiate this directly
template <class Arg> struct dig_arity_ {
static const int value = NONE;
};
template<>
struct get_tuple_arity<null_type> {
BOOST_STATIC_CONSTANT(int, value = 0);
template <class Args> struct dig_arity_<lambda_functor<Args> > {
static const int value = dig_arity<Args>::value;
// Args should be always plain, so it would be safe to instantiatie dig_arity_
// To be very sure, we use dig_arity
};
// Does T have placeholder<I> as it's subexpression?
template<class T, int I>
struct has_placeholder {
BOOST_STATIC_CONSTANT(bool, value = (get_arity<T>::value & I) != 0);
};
template<int I, int J>
struct includes_placeholder {
BOOST_STATIC_CONSTANT(bool, value = (J & I) != 0);
template <class Act, class Args, int ArityCode>
struct dig_arity_<lambda_functor_args<Act, Args, ArityCode> >{
static const int value = ArityCode;
};
template<int I, int J>
struct lacks_placeholder {
BOOST_STATIC_CONSTANT(bool, value = ((J & I) == 0));
template <int I> struct dig_arity_<placeholder<I> > {
static const int value = I;
};
} // namespace detail
// -- dig the arity from lambda_functor_args;
template <class Arg> struct dig_arity {
static const int value =
detail::dig_arity_<
typename boost::remove_cv<
typename boost::remove_reference<Arg>::type
>::type
>::value;
};
// compute the arity of a lambda expression (find the highest placeholder)
template <class A1 = boost::tuples::null_type,
class A2 = boost::tuples::null_type,
class A3 = boost::tuples::null_type,
class A4 = boost::tuples::null_type,
class A5 = boost::tuples::null_type,
class A6 = boost::tuples::null_type,
class A7 = boost::tuples::null_type,
class A8 = boost::tuples::null_type,
class A9 = boost::tuples::null_type,
class A10 = boost::tuples::null_type>
struct combine_arities {
static const int ored_value =
dig_arity<A1>::value |
dig_arity<A2>::value |
dig_arity<A3>::value |
dig_arity<A4>::value |
dig_arity<A5>::value |
dig_arity<A6>::value |
dig_arity<A7>::value |
dig_arity<A8>::value |
dig_arity<A9>::value |
dig_arity<A10>::value;
// leave the highest placeholder bit on, set the lower off
// EXCEPTION and RETHROW bits are retained as they are
static const int value = (ored_value & THIRD
? THIRD
: (ored_value & SECOND
? SECOND
: ored_value)) | ( (EXCEPTION | RETHROW) & ored_value);
};

File diff suppressed because it is too large Load Diff

View File

@@ -1,50 +0,0 @@
// Boost Lambda Library -- control_constructs_common.hpp -------------------
// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2000 Gary Powell (powellg@amazon.com)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see www.boost.org
// --------------------------------------------------------------------------
#if !defined(BOOST_CONTROL_CONSTRUCTS_COMMON_HPP)
#define BOOST_CONTROL_CONSTRUCTS_COMMON_HPP
namespace boost {
namespace lambda {
// special types of lambda functors, used with control structures
// to guarantee that they are composed correctly.
template<class Tag, class LambdaFunctor>
class tagged_lambda_functor;
template<class Tag, class Args>
class tagged_lambda_functor<Tag, lambda_functor<Args> >
: public lambda_functor<Args>
{
public:
tagged_lambda_functor(const Args& a) : lambda_functor<Args>(a) {}
tagged_lambda_functor(const lambda_functor<Args>& a)
: lambda_functor<Args>(a) {}
// for the no body cases in control structures.
tagged_lambda_functor() : lambda_functor<Args>() {}
};
} // lambda
} // boost
#endif // BOOST_CONTROL_CONSTRUCTS_COMMON_HPP

View File

@@ -0,0 +1,580 @@
// Boost Lambda Library -- control_structures_impl.hpp ---------------------
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2000 Gary Powell (gary.powell@sierra.com)
//
// 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 www.boost.org
// --------------------------------------------------------------------------
#if !defined(BOOST_LAMBDA_CONTROL_CONSTRUCTS_HPP)
#define BOOST_LAMBDA_CONTROL_CONSTRUCTS_HPP
namespace boost {
namespace lambda {
// -- void return control actions ----------------------
class forloop_action {};
class ifthen_action {};
class ifthenelse_action {};
class whileloop_action {};
class dowhileloop_action {};
// -- nonvoid return control actions ----------------------
class ifthenelsereturn_action {};
// For loop
template <class Arg1, class Arg2, class Arg3, class Arg4>
inline const
lambda_functor<
lambda_functor_args<
action<4, return_void_action<forloop_action> >,
tuple<lambda_functor<Arg1>, lambda_functor<Arg2>,
lambda_functor<Arg3>, lambda_functor<Arg4> >,
combine_arities<Arg1, Arg2, Arg3, Arg4>::value
>
>
for_loop(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2,
const lambda_functor<Arg3>& a3, const lambda_functor<Arg4>& a4) {
return
lambda_functor<
lambda_functor_args<
action<4, return_void_action<forloop_action> >,
tuple<lambda_functor<Arg1>, lambda_functor<Arg2>,
lambda_functor<Arg3>, lambda_functor<Arg4> >,
combine_arities<Arg1, Arg2, Arg3, Arg4>::value
>
>
( tuple<lambda_functor<Arg1>, lambda_functor<Arg2>,
lambda_functor<Arg3>, lambda_functor<Arg4> >(a1, a2, a3, a4)
);
}
// No body case.
template <class Arg1, class Arg2, class Arg3>
inline const
lambda_functor<
lambda_functor_args<
action<3, return_void_action<forloop_action> >,
tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, lambda_functor<Arg3> >,
combine_arities<Arg1, Arg2, Arg3>::value
>
>
for_loop(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2,
const lambda_functor<Arg3>& a3) {
return
lambda_functor<
lambda_functor_args<
action<3, return_void_action<forloop_action> >,
tuple<lambda_functor<Arg1>, lambda_functor<Arg2>,
lambda_functor<Arg3> >,
combine_arities<Arg1, Arg2, Arg3>::value
>
> ( tuple<lambda_functor<Arg1>, lambda_functor<Arg2>,
lambda_functor<Arg3> >(a1, a2, a3) );
}
// While loop
template <class Arg1, class Arg2>
inline const
lambda_functor<
lambda_functor_args<
action<2, return_void_action<whileloop_action> >,
tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >,
combine_arities<Arg1, Arg2>::value
>
>
while_loop(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2) {
return
lambda_functor<
lambda_functor_args<
action<2, return_void_action<whileloop_action> >,
tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >,
combine_arities<Arg1, Arg2>::value
>
> ( tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >(a1, a2));
}
// No body case.
template <class Arg1>
inline const
lambda_functor<
lambda_functor_args<
action<1, return_void_action<whileloop_action> >,
tuple<lambda_functor<Arg1> >,
combine_arities<Arg1>::value
>
>
while_loop(const lambda_functor<Arg1>& a1) {
return
lambda_functor<
lambda_functor_args<
action<1, return_void_action<whileloop_action> >,
tuple<lambda_functor<Arg1> >,
combine_arities<Arg1>::value
>
> ( tuple<lambda_functor<Arg1> >(a1) );
}
// Do While loop
template <class Arg1, class Arg2>
inline const
lambda_functor<
lambda_functor_args<
action<2, return_void_action<dowhileloop_action> >,
tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >,
combine_arities<Arg1, Arg2>::value
>
>
do_while_loop(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2) {
return
lambda_functor<
lambda_functor_args<
action<2, return_void_action<dowhileloop_action> >,
tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >,
combine_arities<Arg1, Arg2>::value
>
> ( tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >(a1, a2));
}
// No body case.
template <class Arg1>
inline const
lambda_functor<
lambda_functor_args<
action<1, return_void_action<dowhileloop_action> >,
tuple<lambda_functor<Arg1> >,
combine_arities<Arg1>::value
>
>
do_while_loop(const lambda_functor<Arg1>& a1) {
return
lambda_functor<
lambda_functor_args<
action<1, return_void_action<dowhileloop_action> >,
tuple<lambda_functor<Arg1> >,
combine_arities<Arg1>::value
>
> ( tuple<lambda_functor<Arg1> >(a1));
}
// If Then
template <class Arg1, class Arg2>
inline const
lambda_functor<
lambda_functor_args<
action<2, return_void_action<ifthen_action> >,
tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >,
combine_arities<Arg1, Arg2>::value
>
>
if_then(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2) {
return
lambda_functor<
lambda_functor_args<action<2, return_void_action<ifthen_action> >,
tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >,
combine_arities<Arg1, Arg2>::value
>
> ( tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >(a1, a2) );
}
// If then else
template <class Arg1, class Arg2, class Arg3>
inline const
lambda_functor<
lambda_functor_args<
action<3, return_void_action<ifthenelse_action> >,
tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, lambda_functor<Arg3> >,
combine_arities<Arg1, Arg2, Arg3>::value
>
>
if_then_else(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2,
const lambda_functor<Arg3>& a3) {
return
lambda_functor<
lambda_functor_args<
action<3, return_void_action<ifthenelse_action> >,
tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, lambda_functor<Arg3> >,
combine_arities<Arg1, Arg2, Arg3>::value
>
>
(tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, lambda_functor<Arg3> >
(a1, a2, a3) );
}
// Our version of operator?:()
template <class Arg1, class Arg2, class Arg3>
inline const
lambda_functor<
lambda_functor_args<action<3, other_action<ifthenelsereturn_action> >,
tuple<lambda_functor<Arg1>,
typename const_copy_argument<Arg2>::type,
typename const_copy_argument<Arg3>::type>,
combine_arities<Arg1, Arg2, Arg3>::value
>
>
if_then_else_return(const lambda_functor<Arg1>& a1,
const Arg2 & a2,
const Arg3 & a3) {
return
lambda_functor<
lambda_functor_args<
action<3, other_action<ifthenelsereturn_action> >,
tuple<lambda_functor<Arg1>,
typename const_copy_argument<Arg2>::type,
typename const_copy_argument<Arg3>::type>,
combine_arities<Arg1, Arg2, Arg3>::value
>
> ( tuple<lambda_functor<Arg1>,
typename const_copy_argument<Arg2>::type,
typename const_copy_argument<Arg3>::type> (a1, a2, a3) );
}
namespace detail {
// return type specialization for conditional expression begins -----------
// start reading below and move upwards
// PHASE 6:1
// check if A is conbertible to B and B to A
template<int Phase, bool AtoB, bool BtoA, bool SameType, class A, class B>
struct return_type_2_ifthenelsereturn;
// if A can be converted to B and vice versa -> ambiguous
template<int Phase, class A, class B>
struct return_type_2_ifthenelsereturn<Phase, true, true, false, A, B> {
typedef
detail::return_type_deduction_failure<return_type_2_ifthenelsereturn> type;
// ambiguous type in conditional expression
};
// if A can be converted to B and vice versa and are of same type
template<int Phase, class A, class B>
struct return_type_2_ifthenelsereturn<Phase, true, true, true, A, B> {
typedef A type;
};
// A can be converted to B
template<int Phase, class A, class B>
struct return_type_2_ifthenelsereturn<Phase, true, false, false, A, B> {
typedef B type;
};
// B can be converted to A
template<int Phase, class A, class B>
struct return_type_2_ifthenelsereturn<Phase, false, true, false, A, B> {
typedef A type;
};
// neither can be converted. Then we drop the potential references, and
// try again
template<class A, class B>
struct return_type_2_ifthenelsereturn<1, false, false, false, A, B> {
// it is safe to add const, since the result will be an rvalue and thus
// const anyway. The const are needed eg. if the types
// are 'const int*' and 'void *'. The remaining type should be 'const void*'
typedef const typename boost::remove_reference<A>::type plainA;
typedef const typename boost::remove_reference<B>::type plainB;
// TODO: Add support for volatile ?
typedef typename
return_type_2_ifthenelsereturn<
2,
boost::is_convertible<plainA,plainB>::value,
boost::is_convertible<plainB,plainA>::value,
boost::is_same<plainA,plainB>::value,
plainA,
plainB>::type type;
};
// PHASE 6:2
template<class A, class B>
struct return_type_2_ifthenelsereturn<2, false, false, false, A, B> {
typedef
detail::return_type_deduction_failure<return_type_2_ifthenelsereturn> type;
// types_do_not_match_in_conditional_expression
};
// PHASE 5: now we know that types are not arithmetic.
template<class A, class B>
struct non_numeric_types {
typedef typename
return_type_2_ifthenelsereturn<
1, // phase 1
is_convertible<A,B>::value,
is_convertible<B,A>::value,
is_same<A,B>::value,
A,
B>::type type;
};
// PHASE 4 :
// the base case covers arithmetic types with differing promote codes
// use the type deduction of arithmetic_actions
template<int CodeA, int CodeB, class A, class B>
struct arithmetic_or_not {
typedef typename
return_type_2<arithmetic_action<plus_action>, A, B>::type type;
// plus_action is just a random pick, has to be a concrete instance
};
// this case covers the case of artihmetic types with the same promote codes.
// non numeric deduction is used since e.g. integral promotion is not
// performed with operator ?:
template<int CodeA, class A, class B>
struct arithmetic_or_not<CodeA, CodeA, A, B> {
typedef typename non_numeric_types<A, B>::type type;
};
// if either A or B has promote code -1 it is not an arithmetic type
template<class A, class B>
struct arithmetic_or_not <-1, -1, A, B> {
typedef typename non_numeric_types<A, B>::type type;
};
template<int CodeB, class A, class B>
struct arithmetic_or_not <-1, CodeB, A, B> {
typedef typename non_numeric_types<A, B>::type type;
};
template<int CodeA, class A, class B>
struct arithmetic_or_not <CodeA, -1, A, B> {
typedef typename non_numeric_types<A, B>::type type;
};
// PHASE 3 : Are the types same?
// No, check if they are arithmetic or not
template <class A, class B>
struct same_or_not {
typedef typename detail::remove_reference_and_cv<A>::type plainA;
typedef typename detail::remove_reference_and_cv<B>::type plainB;
typedef typename
arithmetic_or_not<
detail::promote_code<plainA>::value,
detail::promote_code<plainB>::value,
A,
B>::type type;
};
// Yes, clear.
template <class A> struct same_or_not<A, A> {
typedef A type;
};
} // detail
// PHASE 2 : Perform first the potential array_to_pointer conversion
template<class A, class B>
struct return_type_2<other_action<ifthenelsereturn_action>, A, B> {
typedef typename detail::array_to_pointer<A>::type A1;
typedef typename detail::array_to_pointer<B>::type B1;
typedef typename
boost::add_const<typename detail::same_or_not<A1, B1>::type>::type type;
};
// PHASE 1 : Deduction is based on the second and third operand
template <class Args, int Code, class Open>
struct return_type<
lambda_functor_args<
action<3, other_action<ifthenelsereturn_action> >,
Args,
Code>,
Open
> {
typedef
typename return_type_2<
other_action<ifthenelsereturn_action>,
typename return_type<
typename detail::tuple_element_as_reference<1, Args>::type, Open
>::type,
typename return_type<
typename detail::tuple_element_as_reference<2, Args>::type, Open
>::type
>::type type;
};
// return type specialization for conditional expression ends -----------
// Control loop lambda_functor_base specializations.
// Specialization for for_loop.
template<class Args>
class
lambda_functor_base<action<4, return_void_action<forloop_action> >, Args> {
public:
Args args;
public:
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET, class A, class B, class C>
RET call(A& a, B& b, C& c) const {
for(detail::select(boost::tuples::get<0>(args), a, b, c);
detail::select(boost::tuples::get<1>(args), a, b, c);
detail::select(boost::tuples::get<2>(args), a, b, c))
detail::select(boost::tuples::get<3>(args), a, b, c);
}
};
// No body case
template<class Args>
class
lambda_functor_base<action<3, return_void_action<forloop_action> >, Args> {
public:
Args args;
public:
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET, class A, class B, class C>
RET call(A& a, B& b, C& c) const {
for(detail::select(boost::tuples::get<0>(args), a, b, c);
detail::select(boost::tuples::get<1>(args), a, b, c);
detail::select(boost::tuples::get<2>(args), a, b, c)) {}
}
};
// Specialization for while_loop.
template<class Args>
class
lambda_functor_base<action<2, return_void_action<whileloop_action> >, Args> {
public:
Args args;
public:
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET, class A, class B, class C>
RET call(A& a, B& b, C& c) const {
while(detail::select(boost::tuples::get<0>(args), a, b, c))
detail::select(boost::tuples::get<1>(args), a, b, c);
}
};
// No body case
template<class Args>
class
lambda_functor_base<action<1, return_void_action<whileloop_action> >, Args> {
public:
Args args;
public:
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET, class A, class B, class C>
RET call(A& a, B& b, C& c) const {
while(detail::select(boost::tuples::get<0>(args), a, b, c)) {}
}
};
// Specialization for do_while_loop.
// Note that the first argument is the condition.
template<class Args>
class
lambda_functor_base<action<2, return_void_action<dowhileloop_action> >, Args> {
public:
Args args;
public:
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET, class A, class B, class C>
RET call(A& a, B& b, C& c) const {
do {
detail::select(boost::tuples::get<1>(args), a, b, c);
} while (detail::select(boost::tuples::get<0>(args), a, b, c) );
}
};
// No body case
template<class Args>
class
lambda_functor_base<action<1, return_void_action<dowhileloop_action> >, Args> {
public:
Args args;
public:
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET, class A, class B, class C>
RET call(A& a, B& b, C& c) const {
do {} while (detail::select(boost::tuples::get<0>(args), a, b, c) );
}
};
// Specialization for if_then.
template<class Args>
class
lambda_functor_base<action<2, return_void_action<ifthen_action> >, Args> {
public:
Args args;
public:
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET, class A, class B, class C>
RET call(A& a, B& b, C& c) const {
if (detail::select(boost::tuples::get<0>(args), a, b, c)) detail::select(boost::tuples::get<1>(args), a, b, c);
}
};
// Specialization for if_then_else.
template<class Args>
class
lambda_functor_base<action<3, return_void_action<ifthenelse_action> >, Args> {
public:
Args args;
public:
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET, class A, class B, class C>
RET call(A& a, B& b, C& c) const {
if (detail::select(boost::tuples::get<0>(args), a, b, c))
detail::select(boost::tuples::get<1>(args), a, b, c);
else
detail::select(boost::tuples::get<2>(args), a, b, c);
}
};
// Specialization of lambda_functor_base for if_then_else_return.
template<class Args>
class
lambda_functor_base<action<3, other_action<ifthenelsereturn_action> >, Args> {
public:
Args args;
public:
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET, class A, class B, class C>
RET call(A& a, B& b, C& c) const {
return (detail::select(boost::tuples::get<0>(args), a, b, c)) ?
detail::select(boost::tuples::get<1>(args), a, b, c)
:
detail::select(boost::tuples::get<2>(args), a, b, c);
}
};
} // lambda
} // boost
#endif // BOOST_LAMBDA_CONTROL_CONSTRUCTS_HPP

View File

@@ -1,10 +1,15 @@
// Boost Lambda Library - function_adaptors.hpp ----------------------------
// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
//
// 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)
// 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 www.boost.org
@@ -12,170 +17,14 @@
#ifndef BOOST_LAMBDA_FUNCTION_ADAPTORS_HPP
#define BOOST_LAMBDA_FUNCTION_ADAPTORS_HPP
#include "boost/mpl/has_xxx.hpp"
#include "boost/tuple/tuple.hpp"
#include "boost/type_traits/same_traits.hpp"
#include "boost/type_traits/remove_reference.hpp"
#include "boost/type_traits/remove_cv.hpp"
#include "boost/type_traits/add_const.hpp"
#include "boost/type_traits/add_volatile.hpp"
#include "boost/utility/result_of.hpp"
namespace boost {
namespace lambda {
namespace detail {
BOOST_MPL_HAS_XXX_TEMPLATE_DEF(sig)
template<class Tuple>
struct remove_references_from_elements {
typedef typename boost::tuples::cons<
typename boost::remove_reference<typename Tuple::head_type>::type,
typename remove_references_from_elements<typename Tuple::tail_type>::type
> type;
};
template<>
struct remove_references_from_elements<boost::tuples::null_type> {
typedef boost::tuples::null_type type;
};
}
template <class Func> struct function_adaptor {
typedef typename detail::remove_reference_and_cv<Func>::type plainF;
#if !defined(BOOST_NO_RESULT_OF)
// Support functors that use the boost::result_of return type convention.
template<class Tuple, int Length, bool HasSig>
struct result_converter;
template<class Tuple, int Length>
struct result_converter<Tuple, Length, true>
: plainF::template sig<
typename detail::remove_references_from_elements<Tuple>::type
>
{};
template<class Tuple>
struct result_converter<Tuple, 0, false>
: result_of<plainF()>
{};
template<class Tuple>
struct result_converter<Tuple, 1, false>
: result_of<plainF(
typename tuples::element<1, Tuple>::type)
>
{};
template<class Tuple>
struct result_converter<Tuple, 2, false>
: result_of<plainF(
typename tuples::element<1, Tuple>::type,
typename tuples::element<2, Tuple>::type)
>
{};
template<class Tuple>
struct result_converter<Tuple, 3, false>
: result_of<plainF(
typename tuples::element<1, Tuple>::type,
typename tuples::element<2, Tuple>::type,
typename tuples::element<3, Tuple>::type)
>
{};
template<class Tuple>
struct result_converter<Tuple, 4, false>
: result_of<plainF(
typename tuples::element<1, Tuple>::type,
typename tuples::element<2, Tuple>::type,
typename tuples::element<3, Tuple>::type,
typename tuples::element<4, Tuple>::type)
>
{};
template<class Tuple>
struct result_converter<Tuple, 5, false>
: result_of<plainF(
typename tuples::element<1, Tuple>::type,
typename tuples::element<2, Tuple>::type,
typename tuples::element<3, Tuple>::type,
typename tuples::element<4, Tuple>::type,
typename tuples::element<5, Tuple>::type)
>
{};
template<class Tuple>
struct result_converter<Tuple, 6, false>
: result_of<plainF(
typename tuples::element<1, Tuple>::type,
typename tuples::element<2, Tuple>::type,
typename tuples::element<3, Tuple>::type,
typename tuples::element<4, Tuple>::type,
typename tuples::element<5, Tuple>::type,
typename tuples::element<6, Tuple>::type)
>
{};
template<class Tuple>
struct result_converter<Tuple, 7, false>
: result_of<plainF(
typename tuples::element<1, Tuple>::type,
typename tuples::element<2, Tuple>::type,
typename tuples::element<3, Tuple>::type,
typename tuples::element<4, Tuple>::type,
typename tuples::element<5, Tuple>::type,
typename tuples::element<6, Tuple>::type,
typename tuples::element<7, Tuple>::type)
>
{};
template<class Tuple>
struct result_converter<Tuple, 8, false>
: result_of<plainF(
typename tuples::element<1, Tuple>::type,
typename tuples::element<2, Tuple>::type,
typename tuples::element<3, Tuple>::type,
typename tuples::element<4, Tuple>::type,
typename tuples::element<5, Tuple>::type,
typename tuples::element<6, Tuple>::type,
typename tuples::element<7, Tuple>::type,
typename tuples::element<8, Tuple>::type)
>
{};
template<class Tuple>
struct result_converter<Tuple, 9, false>
: result_of<plainF(
typename tuples::element<1, Tuple>::type,
typename tuples::element<2, Tuple>::type,
typename tuples::element<3, Tuple>::type,
typename tuples::element<4, Tuple>::type,
typename tuples::element<5, Tuple>::type,
typename tuples::element<6, Tuple>::type,
typename tuples::element<7, Tuple>::type,
typename tuples::element<8, Tuple>::type,
typename tuples::element<9, Tuple>::type)
>
{};
// we do not know the return type off-hand, we must ask it from Func
// To sig we pass a cons list, where the head is the function object type
// itself (potentially cv-qualified)
// and the tail contains the types of the actual arguments to be passed
// to the function object. The arguments can be cv qualified
// as well.
template <class Args>
struct sig
: result_converter<
Args
, tuples::length<typename Args::tail_type>::value
, detail::has_sig<plainF>::value
>
{};
#else // BOOST_NO_RESULT_OF
template <class Args> class sig {
typedef typename detail::remove_reference_and_cv<Func>::type plainF;
public:
typedef typename plainF::template sig<
typename detail::remove_references_from_elements<Args>::type
>::type type;
};
#endif
typedef detail::unspecified type;
template<class RET, class A1>
static RET apply(A1& a1) {
@@ -227,81 +76,11 @@ template <class Func> struct function_adaptor {
}
};
template <class Func> struct function_adaptor<const Func>; // error
// -- function adaptors with data member access
template <class Object, class T>
struct function_adaptor<T Object::*> {
// typedef detail::unspecified type;
// T can have qualifiers and can be a reference type
// We get the return type by adding const, if the object through which
// the data member is accessed is const, and finally adding a reference
template<class Args> class sig {
typedef typename boost::tuples::element<1, Args>::type argument_type;
typedef typename boost::remove_reference<
argument_type
>::type unref_type;
typedef typename detail::IF<boost::is_const<unref_type>::value,
typename boost::add_const<T>::type,
T
>::RET properly_consted_return_type;
typedef typename detail::IF<boost::is_volatile<unref_type>::value,
typename boost::add_volatile<properly_consted_return_type>::type,
properly_consted_return_type
>::RET properly_cvd_return_type;
public:
typedef typename detail::IF<boost::is_reference<argument_type>::value,
typename boost::add_reference<properly_cvd_return_type>::type,
typename boost::remove_cv<T>::type
>::RET type;
};
template <class RET>
static RET apply( T Object::*data, Object& o) {
return o.*data;
}
template <class RET>
static RET apply( T Object::*data, const Object& o) {
return o.*data;
}
template <class RET>
static RET apply( T Object::*data, volatile Object& o) {
return o.*data;
}
template <class RET>
static RET apply( T Object::*data, const volatile Object& o) {
return o.*data;
}
template <class RET>
static RET apply( T Object::*data, Object* o) {
return o->*data;
}
template <class RET>
static RET apply( T Object::*data, const Object* o) {
return o->*data;
}
template <class RET>
static RET apply( T Object::*data, volatile Object* o) {
return o->*data;
}
template <class RET>
static RET apply( T Object::*data, const volatile Object* o) {
return o->*data;
}
};
// -- function adaptors with 1 argument apply
template <class Result>
struct function_adaptor<Result (void)> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET>
static Result apply(Result (*func)()) {
return func();
@@ -310,8 +89,7 @@ struct function_adaptor<Result (void)> {
template <class Result>
struct function_adaptor<Result (*)(void)> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET>
static Result apply(Result (*func)()) {
return func();
@@ -322,8 +100,7 @@ struct function_adaptor<Result (*)(void)> {
// -- function adaptors with 2 argument apply
template <class Object, class Result>
struct function_adaptor<Result (Object::*)() const> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET>
static Result apply( Result (Object::*func)() const, const Object* o) {
return (o->*func)();
@@ -336,8 +113,7 @@ struct function_adaptor<Result (Object::*)() const> {
template <class Object, class Result>
struct function_adaptor<Result (Object::*)()> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET>
static Result apply( Result (Object::*func)(), Object* o) {
return (o->*func)();
@@ -350,8 +126,7 @@ struct function_adaptor<Result (Object::*)()> {
template <class Arg1, class Result>
struct function_adaptor<Result (Arg1)> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1>
static Result apply(Result (*func)(Arg1), A1& a1) {
return func(a1);
@@ -360,8 +135,7 @@ struct function_adaptor<Result (Arg1)> {
template <class Arg1, class Result>
struct function_adaptor<Result (*)(Arg1)> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1>
static Result apply(Result (*func)(Arg1), A1& a1) {
return func(a1);
@@ -372,24 +146,20 @@ struct function_adaptor<Result (*)(Arg1)> {
// -- function adaptors with 3 argument apply
template <class Object, class Arg1, class Result>
struct function_adaptor<Result (Object::*)(Arg1) const> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1>
static Result apply( Result (Object::*func)(Arg1) const, const Object* o,
A1& a1) {
static Result apply( Result (Object::*func)(Arg1) const, const Object* o, A1& a1) {
return (o->*func)(a1);
}
template <class RET, class A1>
static Result apply( Result (Object::*func)(Arg1) const, const Object& o,
A1& a1) {
static Result apply( Result (Object::*func)(Arg1) const, const Object& o, A1& a1) {
return (o.*func)(a1);
}
};
template <class Object, class Arg1, class Result>
struct function_adaptor<Result (Object::*)(Arg1)> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1>
static Result apply( Result (Object::*func)(Arg1), Object* o, A1& a1) {
return (o->*func)(a1);
@@ -402,8 +172,7 @@ struct function_adaptor<Result (Object::*)(Arg1)> {
template <class Arg1, class Arg2, class Result>
struct function_adaptor<Result (Arg1, Arg2)> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1, class A2>
static Result apply(Result (*func)(Arg1, Arg2), A1& a1, A2& a2) {
return func(a1, a2);
@@ -412,8 +181,7 @@ struct function_adaptor<Result (Arg1, Arg2)> {
template <class Arg1, class Arg2, class Result>
struct function_adaptor<Result (*)(Arg1, Arg2)> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1, class A2>
static Result apply(Result (*func)(Arg1, Arg2), A1& a1, A2& a2) {
return func(a1, a2);
@@ -424,8 +192,7 @@ struct function_adaptor<Result (*)(Arg1, Arg2)> {
// -- function adaptors with 4 argument apply
template <class Object, class Arg1, class Arg2, class Result>
struct function_adaptor<Result (Object::*)(Arg1, Arg2) const> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1, class A2>
static Result apply( Result (Object::*func)(Arg1, Arg2) const, const Object* o, A1& a1, A2& a2) {
return (o->*func)(a1, a2);
@@ -438,8 +205,7 @@ struct function_adaptor<Result (Object::*)(Arg1, Arg2) const> {
template <class Object, class Arg1, class Arg2, class Result>
struct function_adaptor<Result (Object::*)(Arg1, Arg2)> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1, class A2>
static Result apply( Result (Object::*func)(Arg1, Arg2), Object* o, A1& a1, A2& a2) {
return (o->*func)(a1, a2);
@@ -452,8 +218,7 @@ struct function_adaptor<Result (Object::*)(Arg1, Arg2)> {
template <class Arg1, class Arg2, class Arg3, class Result>
struct function_adaptor<Result (Arg1, Arg2, Arg3)> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1, class A2, class A3>
static Result apply(Result (*func)(Arg1, Arg2, Arg3), A1& a1, A2& a2, A3& a3) {
return func(a1, a2, a3);
@@ -462,8 +227,7 @@ struct function_adaptor<Result (Arg1, Arg2, Arg3)> {
template <class Arg1, class Arg2, class Arg3, class Result>
struct function_adaptor<Result (*)(Arg1, Arg2, Arg3)> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1, class A2, class A3>
static Result apply(Result (*func)(Arg1, Arg2, Arg3), A1& a1, A2& a2, A3& a3) {
return func(a1, a2, a3);
@@ -474,8 +238,7 @@ struct function_adaptor<Result (*)(Arg1, Arg2, Arg3)> {
// -- function adaptors with 5 argument apply
template <class Object, class Arg1, class Arg2, class Arg3, class Result>
struct function_adaptor<Result (Object::*)(Arg1, Arg2, Arg3) const> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1, class A2, class A3>
static Result apply( Result (Object::*func)(Arg1, Arg2, Arg3) const, const Object* o, A1& a1, A2& a2, A3& a3) {
return (o->*func)(a1, a2, a3);
@@ -488,8 +251,7 @@ struct function_adaptor<Result (Object::*)(Arg1, Arg2, Arg3) const> {
template <class Object, class Arg1, class Arg2, class Arg3, class Result>
struct function_adaptor<Result (Object::*)(Arg1, Arg2, Arg3)> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1, class A2, class A3>
static Result apply( Result (Object::*func)(Arg1, Arg2, Arg3), Object* o, A1& a1, A2& a2, A3& a3) {
return (o->*func)(a1, a2, a3);
@@ -502,8 +264,7 @@ struct function_adaptor<Result (Object::*)(Arg1, Arg2, Arg3)> {
template <class Arg1, class Arg2, class Arg3, class Arg4, class Result>
struct function_adaptor<Result (Arg1, Arg2, Arg3, Arg4)> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1, class A2, class A3, class A4>
static Result apply(Result (*func)(Arg1, Arg2, Arg3, Arg4), A1& a1, A2& a2, A3& a3, A4& a4) {
return func(a1, a2, a3, a4);
@@ -512,8 +273,7 @@ struct function_adaptor<Result (Arg1, Arg2, Arg3, Arg4)> {
template <class Arg1, class Arg2, class Arg3, class Arg4, class Result>
struct function_adaptor<Result (*)(Arg1, Arg2, Arg3, Arg4)> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1, class A2, class A3, class A4>
static Result apply(Result (*func)(Arg1, Arg2, Arg3, Arg4), A1& a1, A2& a2, A3& a3, A4& a4) {
return func(a1, a2, a3, a4);
@@ -524,8 +284,7 @@ struct function_adaptor<Result (*)(Arg1, Arg2, Arg3, Arg4)> {
// -- function adaptors with 6 argument apply
template <class Object, class Arg1, class Arg2, class Arg3, class Arg4, class Result>
struct function_adaptor<Result (Object::*)(Arg1, Arg2, Arg3, Arg4) const> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1, class A2, class A3, class A4>
static Result apply( Result (Object::*func)(Arg1, Arg2, Arg3, Arg4) const, const Object* o, A1& a1, A2& a2, A3& a3, A4& a4) {
return (o->*func)(a1, a2, a3, a4);
@@ -538,8 +297,7 @@ struct function_adaptor<Result (Object::*)(Arg1, Arg2, Arg3, Arg4) const> {
template <class Object, class Arg1, class Arg2, class Arg3, class Arg4, class Result>
struct function_adaptor<Result (Object::*)(Arg1, Arg2, Arg3, Arg4)> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1, class A2, class A3, class A4>
static Result apply( Result (Object::*func)(Arg1, Arg2, Arg3, Arg4), Object* o, A1& a1, A2& a2, A3& a3, A4& a4) {
return (o->*func)(a1, a2, a3, a4);
@@ -552,8 +310,7 @@ struct function_adaptor<Result (Object::*)(Arg1, Arg2, Arg3, Arg4)> {
template <class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Result>
struct function_adaptor<Result (Arg1, Arg2, Arg3, Arg4, Arg5)> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1, class A2, class A3, class A4, class A5>
static Result apply(Result (*func)(Arg1, Arg2, Arg3, Arg4, Arg5), A1& a1, A2& a2, A3& a3, A4& a4, A5& a5) {
return func(a1, a2, a3, a4, a5);
@@ -562,8 +319,7 @@ struct function_adaptor<Result (Arg1, Arg2, Arg3, Arg4, Arg5)> {
template <class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Result>
struct function_adaptor<Result (*)(Arg1, Arg2, Arg3, Arg4, Arg5)> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1, class A2, class A3, class A4, class A5>
static Result apply(Result (*func)(Arg1, Arg2, Arg3, Arg4, Arg5), A1& a1, A2& a2, A3& a3, A4& a4, A5& a5) {
return func(a1, a2, a3, a4, a5);
@@ -574,8 +330,7 @@ struct function_adaptor<Result (*)(Arg1, Arg2, Arg3, Arg4, Arg5)> {
// -- function adaptors with 7 argument apply
template <class Object, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Result>
struct function_adaptor<Result (Object::*)(Arg1, Arg2, Arg3, Arg4, Arg5) const> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1, class A2, class A3, class A4, class A5>
static Result apply( Result (Object::*func)(Arg1, Arg2, Arg3, Arg4, Arg5) const, const Object* o, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5) {
return (o->*func)(a1, a2, a3, a4, a5);
@@ -588,8 +343,7 @@ struct function_adaptor<Result (Object::*)(Arg1, Arg2, Arg3, Arg4, Arg5) const>
template <class Object, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Result>
struct function_adaptor<Result (Object::*)(Arg1, Arg2, Arg3, Arg4, Arg5)> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1, class A2, class A3, class A4, class A5>
static Result apply( Result (Object::*func)(Arg1, Arg2, Arg3, Arg4, Arg5), Object* o, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5) {
return (o->*func)(a1, a2, a3, a4, a5);
@@ -602,8 +356,7 @@ struct function_adaptor<Result (Object::*)(Arg1, Arg2, Arg3, Arg4, Arg5)> {
template <class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6, class Result>
struct function_adaptor<Result (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1, class A2, class A3, class A4, class A5, class A6>
static Result apply(Result (*func)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6), A1& a1, A2& a2, A3& a3, A4& a4, A5& a5, A6& a6) {
return func(a1, a2, a3, a4, a5, a6);
@@ -612,8 +365,7 @@ struct function_adaptor<Result (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)> {
template <class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6, class Result>
struct function_adaptor<Result (*)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1, class A2, class A3, class A4, class A5, class A6>
static Result apply(Result (*func)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6), A1& a1, A2& a2, A3& a3, A4& a4, A5& a5, A6& a6) {
return func(a1, a2, a3, a4, a5, a6);
@@ -624,8 +376,7 @@ struct function_adaptor<Result (*)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)> {
// -- function adaptors with 8 argument apply
template <class Object, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6, class Result>
struct function_adaptor<Result (Object::*)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) const> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1, class A2, class A3, class A4, class A5, class A6>
static Result apply( Result (Object::*func)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) const, const Object* o, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5, A6& a6) {
return (o->*func)(a1, a2, a3, a4, a5, a6);
@@ -638,8 +389,7 @@ struct function_adaptor<Result (Object::*)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) c
template <class Object, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6, class Result>
struct function_adaptor<Result (Object::*)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1, class A2, class A3, class A4, class A5, class A6>
static Result apply( Result (Object::*func)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6), Object* o, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5, A6& a6) {
return (o->*func)(a1, a2, a3, a4, a5, a6);
@@ -652,8 +402,7 @@ struct function_adaptor<Result (Object::*)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)>
template <class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6, class Arg7, class Result>
struct function_adaptor<Result (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7)> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
static Result apply(Result (*func)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7), A1& a1, A2& a2, A3& a3, A4& a4, A5& a5, A6& a6, A7& a7) {
return func(a1, a2, a3, a4, a5, a6, a7);
@@ -662,8 +411,7 @@ struct function_adaptor<Result (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7)> {
template <class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6, class Arg7, class Result>
struct function_adaptor<Result (*)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7)> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
static Result apply(Result (*func)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7), A1& a1, A2& a2, A3& a3, A4& a4, A5& a5, A6& a6, A7& a7) {
return func(a1, a2, a3, a4, a5, a6, a7);
@@ -674,8 +422,7 @@ struct function_adaptor<Result (*)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7)> {
// -- function adaptors with 9 argument apply
template <class Object, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6, class Arg7, class Result>
struct function_adaptor<Result (Object::*)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7) const> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
static Result apply( Result (Object::*func)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7) const, const Object* o, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5, A6& a6, A7& a7) {
return (o->*func)(a1, a2, a3, a4, a5, a6, a7);
@@ -688,8 +435,7 @@ struct function_adaptor<Result (Object::*)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, A
template <class Object, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6, class Arg7, class Result>
struct function_adaptor<Result (Object::*)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7)> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
static Result apply( Result (Object::*func)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7), Object* o, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5, A6& a6, A7& a7) {
return (o->*func)(a1, a2, a3, a4, a5, a6, a7);
@@ -702,8 +448,7 @@ struct function_adaptor<Result (Object::*)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, A
template <class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6, class Arg7, class Arg8, class Result>
struct function_adaptor<Result (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8)> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
static Result apply(Result (*func)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8), A1& a1, A2& a2, A3& a3, A4& a4, A5& a5, A6& a6, A7& a7, A8& a8) {
return func(a1, a2, a3, a4, a5, a6, a7, a8);
@@ -712,8 +457,7 @@ struct function_adaptor<Result (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8)>
template <class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6, class Arg7, class Arg8, class Result>
struct function_adaptor<Result (*)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8)> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
static Result apply(Result (*func)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8), A1& a1, A2& a2, A3& a3, A4& a4, A5& a5, A6& a6, A7& a7, A8& a8) {
return func(a1, a2, a3, a4, a5, a6, a7, a8);
@@ -724,8 +468,7 @@ struct function_adaptor<Result (*)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg
// -- function adaptors with 10 argument apply
template <class Object, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6, class Arg7, class Arg8, class Result>
struct function_adaptor<Result (Object::*)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8) const> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
static Result apply( Result (Object::*func)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8) const, const Object* o, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5, A6& a6, A7& a7, A8& a8) {
return (o->*func)(a1, a2, a3, a4, a5, a6, a7, a8);
@@ -738,8 +481,7 @@ struct function_adaptor<Result (Object::*)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, A
template <class Object, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6, class Arg7, class Arg8, class Result>
struct function_adaptor<Result (Object::*)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8)> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
static Result apply( Result (Object::*func)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8), Object* o, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5, A6& a6, A7& a7, A8& a8) {
return (o->*func)(a1, a2, a3, a4, a5, a6, a7, a8);
@@ -752,8 +494,7 @@ struct function_adaptor<Result (Object::*)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, A
template <class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6, class Arg7, class Arg8, class Arg9, class Result>
struct function_adaptor<Result (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9)> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
static Result apply(Result (*func)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9), A1& a1, A2& a2, A3& a3, A4& a4, A5& a5, A6& a6, A7& a7, A8& a8, A9& a9) {
return func(a1, a2, a3, a4, a5, a6, a7, a8, a9);
@@ -762,14 +503,83 @@ struct function_adaptor<Result (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8,
template <class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6, class Arg7, class Arg8, class Arg9, class Result>
struct function_adaptor<Result (*)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9)> {
template<class T> struct sig { typedef Result type; };
typedef Result type;
template <class RET, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
static Result apply(Result (*func)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9), A1& a1, A2& a2, A3& a3, A4& a4, A5& a5, A6& a6, A7& a7, A8& a8, A9& a9) {
return func(a1, a2, a3, a4, a5, a6, a7, a8, a9);
}
};
// we want to instantiate function adaptor from different places.
// sometimes Func does not have the result_type defined. It is therefore
// queried in a separate subclass.
// Thus the super class can be
// instantiated even with a Func that does no have result_type
struct has_sig {};
namespace detail {
template <class F> struct get_result_type {
typedef typename F::result_type type;
};
template <class Args> class get_sig_result_type {
typedef typename Args::head_type Func;
typedef typename detail::remove_reference_and_cv<Func>::type plainF;
public:
// To sig we pass a cons list, where the head is the function object type
// itself (potentially cv-qualified, always a reference type)
// and the tail contains the types of the actual arguments to be passed
// to the function object. The arguments are reference types
typedef typename plainF::template sig<Args>::type type;
};
// check for a member typedef return_type or an member class template sig
template <class Args> class get_functor_result_type {
typedef typename Args::head_type Func;
typedef typename detail::remove_reference_and_cv<Func>::type plain_F;
public:
// if the function object inherits from has_sig, we check for sig
// otherwise for result_type typedef
typedef typename
detail::IF_type<
boost::is_base_and_derived<has_sig, plain_F>::value,
detail::get_sig_result_type<Args>,
detail::get_result_type<plain_F>
>::type type;
};
} // end detail
template <class Args>
class function_adaptor_with_actuals
{
typedef typename Args::head_type Func;
typedef typename detail::remove_reference_and_cv<Func>::type plain_Func;
typedef typename function_adaptor<plain_Func>::type type1;
public:
typedef typename
detail::IF_type<
boost::is_same<type1, detail::unspecified>::value,
detail::get_functor_result_type<
Args // old code: boost::tuples::cons<Func, typename Args::tail_type>
>, // it's ok to try this (an arbitrary func. object)
function_adaptor<plain_Func>
// Here we know Func's ret type
// (func is a member function or function pointer/reference)
>::type type;
};
} // namespace lambda
} // namespace boost

View File

@@ -1,10 +1,15 @@
// Boost Lambda Library - is_instance_of.hpp ---------------------
// Copyright (C) 2001 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2001 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
//
// 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)
// 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 www.boost.org
@@ -38,9 +43,9 @@
// Now we only have one version of is_instance_of templates, which delagate
// all the nasty compiler tricks to is_convertible.
#define BOOST_LAMBDA_CLASS(z, N,A) BOOST_PP_COMMA_IF(N) class
#define BOOST_LAMBDA_CLASS_ARG(z, N,A) BOOST_PP_COMMA_IF(N) class A##N
#define BOOST_LAMBDA_ARG(z, N,A) BOOST_PP_COMMA_IF(N) A##N
#define BOOST_LAMBDA_CLASS(N,A) BOOST_PP_COMMA_IF(N) class
#define BOOST_LAMBDA_CLASS_ARG(N,A) BOOST_PP_COMMA_IF(N) class A##N
#define BOOST_LAMBDA_ARG(N,A) BOOST_PP_COMMA_IF(N) A##N
#define BOOST_LAMBDA_CLASS_LIST(n, NAME) BOOST_PP_REPEAT(n, BOOST_LAMBDA_CLASS, NAME)
@@ -51,34 +56,34 @@
namespace boost {
namespace lambda {
#define BOOST_LAMBDA_IS_INSTANCE_OF_TEMPLATE(INDEX) \
\
namespace detail { \
\
template <template<BOOST_LAMBDA_CLASS_LIST(INDEX,T)> class F> \
struct BOOST_PP_CAT(conversion_tester_,INDEX) { \
template<BOOST_LAMBDA_CLASS_ARG_LIST(INDEX,A)> \
BOOST_PP_CAT(conversion_tester_,INDEX) \
(const F<BOOST_LAMBDA_ARG_LIST(INDEX,A)>&); \
}; \
\
} /* end detail */ \
\
#define BOOST_LAMBDA_IS_INSTANCE_OF_TEMPLATE(INDEX) \
\
namespace detail { \
\
template <template<BOOST_LAMBDA_CLASS_LIST(INDEX,T)> class F> \
struct BOOST_PP_CAT(conversion_tester_,INDEX) { \
template<BOOST_LAMBDA_CLASS_ARG_LIST(INDEX,A)> \
BOOST_PP_CAT(conversion_tester_,INDEX) \
(const F<BOOST_LAMBDA_ARG_LIST(INDEX,A)>&); \
}; \
\
} /* end detail */ \
\
template <class From, template <BOOST_LAMBDA_CLASS_LIST(INDEX,T)> class To> \
struct BOOST_PP_CAT(is_instance_of_,INDEX) \
{ \
private: \
typedef ::boost::is_convertible< \
From, \
BOOST_PP_CAT(detail::conversion_tester_,INDEX)<To> \
> helper_type; \
\
public: \
BOOST_STATIC_CONSTANT(bool, value = helper_type::value); \
struct BOOST_PP_CAT(is_instance_of_,INDEX) \
{ \
private: \
typedef ::boost::is_convertible< \
From, \
BOOST_PP_CAT(detail::conversion_tester_,INDEX)<To> \
> helper_type; \
\
public: \
BOOST_STATIC_CONSTANT(bool, value = helper_type::value); \
};
#define BOOST_LAMBDA_HELPER(z, N, A) BOOST_LAMBDA_IS_INSTANCE_OF_TEMPLATE( BOOST_PP_INC(N) )
#define BOOST_LAMBDA_HELPER(N, A) BOOST_LAMBDA_IS_INSTANCE_OF_TEMPLATE( BOOST_PP_INC(N) )
// Generate the traits for 1-4 argument templates

View File

@@ -1,10 +1,15 @@
// Boost Lambda Library - lambda_config.hpp ------------------------------
// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
//
// 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)
// 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 www.boost.org
@@ -18,16 +23,16 @@
# if defined __GNUC__
# if (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
# define BOOST_REF_TO_FUNC_CONFLICTS_WITH_REF_TO_T
# define BOOST_LAMBDA_INCORRECT_BIND_OVERLOADING
# endif
# endif // __GNUC__
# if (__GNUC__ == 2 && __GNUC_MINOR__ <= 97)
#define BOOST_NO_TEMPLATED_STREAMS
#define BOOST_LAMBDA_INCORRECT_BIND_OVERLOADING
#endif
#endif // __GNUC__
#if defined __KCC
#define BOOST_NO_FDECL_TEMPLATES_AS_TEMPLATE_TEMPLATE_PARAMS
# if defined __KCC
#define BOOST_NO_FORWARD_DECLARADED_TEMPLATES_AS_TEMPLATE_TEMPLATE_PARAMETERS
#endif // __KCC

View File

@@ -1,10 +1,15 @@
// Boost Lambda Library lambda_functor_base.hpp -----------------------------
//
// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
//
// 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)
// 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 www.boost.org
@@ -13,256 +18,35 @@
#ifndef BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_HPP
#define BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_HPP
#include "boost/type_traits/add_reference.hpp"
#include "boost/type_traits/add_const.hpp"
#include "boost/type_traits/remove_const.hpp"
#include "boost/lambda/detail/lambda_fwd.hpp"
#include "boost/lambda/detail/lambda_traits.hpp"
namespace boost {
namespace lambda {
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
#pragma warning(push)
#pragma warning(disable:4512) //assignment operator could not be generated
#endif
// for return type deductions we wrap bound argument to this class,
// which fulfils the base class contract for lambda_functors
template <class T>
class identity {
T elem;
public:
typedef T element_t;
// take all parameters as const references. Note that non-const references
// stay as they are.
typedef typename boost::add_reference<
typename boost::add_const<T>::type
>::type par_t;
explicit identity(par_t t) : elem(t) {}
template <typename SigArgs>
struct sig { typedef typename boost::remove_const<element_t>::type type; };
template<class RET, CALL_TEMPLATE_ARGS>
RET call(CALL_FORMAL_ARGS) const { CALL_USE_ARGS; return elem; }
};
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
#pragma warning(pop)
#endif
template <class T>
inline lambda_functor<identity<T&> > var(T& t) { return identity<T&>(t); }
// for lambda functors, var is an identity operator. It was forbidden
// at some point, but we might want to var something that can be a
// non-lambda functor or a lambda functor.
template <class T>
lambda_functor<T> var(const lambda_functor<T>& t) { return t; }
template <class T> struct var_type {
typedef lambda_functor<identity<T&> > type;
};
template <class T>
inline
lambda_functor<identity<typename bound_argument_conversion<const T>::type> >
constant(const T& t) {
return identity<typename bound_argument_conversion<const T>::type>(t);
}
template <class T>
lambda_functor<T> constant(const lambda_functor<T>& t) { return t; }
template <class T> struct constant_type {
typedef
lambda_functor<
identity<typename bound_argument_conversion<const T>::type>
> type;
};
template <class T>
inline lambda_functor<identity<const T&> > constant_ref(const T& t) {
return identity<const T&>(t);
}
template <class T>
lambda_functor<T> constant_ref(const lambda_functor<T>& t) { return t; }
template <class T> struct constant_ref_type {
typedef
lambda_functor<identity<const T&> > type;
};
// as_lambda_functor turns any types to lambda functors
// non-lambda_functors will be bound argument types
template <class T>
struct as_lambda_functor {
typedef typename
detail::remove_reference_and_cv<T>::type plain_T;
typedef typename
detail::IF<is_lambda_functor<plain_T>::value,
plain_T,
lambda_functor<
identity<typename bound_argument_conversion<T>::type>
>
>::RET type;
};
// turns arbitrary objects into lambda functors
template <class T>
inline
lambda_functor<identity<typename bound_argument_conversion<const T>::type> >
to_lambda_functor(const T& t) {
return identity<typename bound_argument_conversion<const T>::type>(t);
}
template <class T>
inline lambda_functor<T>
to_lambda_functor(const lambda_functor<T>& t) {
return t;
}
namespace detail {
// In a call constify_rvals<T>::go(x)
// x should be of type T. If T is a non-reference type, do
// In a call make_rvalues_const<T>::exec(x)
// x should be of type T. If T is a non-reference type, exec
// returns x as const reference.
// Otherwise the type doesn't change.
// The purpose of this class is to avoid
// 'cannot bind temporaries to non-const references' errors.
template <class T> struct constify_rvals {
template <class T> struct make_rvalues_const {
template<class U>
static inline const U& go(const U& u) { return u; }
static const U& exec(const U& u) { return u; }
};
template <class T> struct constify_rvals<T&> {
template <class T> struct make_rvalues_const<T&> {
template<class U>
static inline U& go(U& u) { return u; }
static U& exec(U& u) { return u; }
};
// check whether one of the elements of a tuple (cons list) is of type
// null_type. Needed, because the compiler goes ahead and instantiates
// sig template for nullary case even if the nullary operator() is not
// called
template <class T> struct is_null_type
{ BOOST_STATIC_CONSTANT(bool, value = false); };
template <> struct is_null_type<null_type>
{ BOOST_STATIC_CONSTANT(bool, value = true); };
template<class Tuple> struct has_null_type {
BOOST_STATIC_CONSTANT(bool, value = (is_null_type<typename Tuple::head_type>::value || has_null_type<typename Tuple::tail_type>::value));
template <int N, class Args, class A, class B, class C>
struct nth_return_type {
typedef typename
return_type<
typename tuple_element_as_reference<N, Args>::type,
open_args<A, B, C>
>::type type;
};
template<> struct has_null_type<null_type> {
BOOST_STATIC_CONSTANT(bool, value = false);
};
// helpers -------------------
template<class Args, class SigArgs>
class deduce_argument_types_ {
typedef typename as_lambda_functor<typename Args::head_type>::type lf_t;
typedef typename lf_t::inherited::template sig<SigArgs>::type el_t;
public:
typedef
boost::tuples::cons<
el_t,
typename deduce_argument_types_<typename Args::tail_type, SigArgs>::type
> type;
};
template<class SigArgs>
class deduce_argument_types_<null_type, SigArgs> {
public:
typedef null_type type;
};
// // note that tuples cannot have plain function types as elements.
// // Hence, all other types will be non-const, except references to
// // functions.
// template <class T> struct remove_reference_except_from_functions {
// typedef typename boost::remove_reference<T>::type t;
// typedef typename detail::IF<boost::is_function<t>::value, T, t>::RET type;
// };
template<class Args, class SigArgs>
class deduce_non_ref_argument_types_ {
typedef typename as_lambda_functor<typename Args::head_type>::type lf_t;
typedef typename lf_t::inherited::template sig<SigArgs>::type el_t;
public:
typedef
boost::tuples::cons<
// typename detail::remove_reference_except_from_functions<el_t>::type,
typename boost::remove_reference<el_t>::type,
typename deduce_non_ref_argument_types_<typename Args::tail_type, SigArgs>::type
> type;
};
template<class SigArgs>
class deduce_non_ref_argument_types_<null_type, SigArgs> {
public:
typedef null_type type;
};
// -------------
// take stored Args and Open Args, and return a const list with
// deduced elements (real return types)
template<class Args, class SigArgs>
class deduce_argument_types {
typedef typename deduce_argument_types_<Args, SigArgs>::type t1;
public:
typedef typename detail::IF<
has_null_type<t1>::value, null_type, t1
>::RET type;
};
// take stored Args and Open Args, and return a const list with
// deduced elements (references are stripped from the element types)
template<class Args, class SigArgs>
class deduce_non_ref_argument_types {
typedef typename deduce_non_ref_argument_types_<Args, SigArgs>::type t1;
public:
typedef typename detail::IF<
has_null_type<t1>::value, null_type, t1
>::RET type;
};
template <int N, class Args, class SigArgs>
struct nth_return_type_sig {
typedef typename
as_lambda_functor<
typename boost::tuples::element<N, Args>::type
// typename tuple_element_as_reference<N, Args>::type
>::type lf_type;
typedef typename lf_type::inherited::template sig<SigArgs>::type type;
};
template<int N, class Tuple> struct element_or_null {
typedef typename boost::tuples::element<N, Tuple>::type type;
};
template<int N> struct element_or_null<N, null_type> {
typedef null_type type;
};
} // end detail
@@ -271,28 +55,28 @@ template<int N> struct element_or_null<N, null_type> {
// the explicit_return_type_action case -----------------------------------
template<class RET, class Args>
class lambda_functor_base<explicit_return_type_action<RET>, Args>
class lambda_functor_base<action<1, explicit_return_type_action<RET> >, Args>
{
public:
Args args;
public:
typedef RET result_type;
explicit lambda_functor_base(const Args& a) : args(a) {}
template <class SigArgs> struct sig { typedef RET type; };
template<class RET_, CALL_TEMPLATE_ARGS>
RET call(CALL_FORMAL_ARGS) const
template<class RET_, class A, class B, class C>
RET call(A& a, B& b, C& c) const
// TODO: RET and RET_ should be the same type, add a compile time assert?
{
return detail::constify_rvals<RET>::go(
detail::r_select<RET>::go(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS));
return detail::make_rvalues_const<RET>::exec(
detail::ret_selector<RET>::select(boost::tuples::get<0>(args), a, b, c));
}
};
// the protect_action case -----------------------------------
template<class Args>
class lambda_functor_base<protect_action, Args>
class lambda_functor_base<action<1, protect_action >, Args>
{
public:
Args args;
@@ -300,308 +84,280 @@ public:
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET, CALL_TEMPLATE_ARGS>
RET call(CALL_FORMAL_ARGS) const
template<class RET, class A, class B, class C>
RET call(A& a, B& b, C& c) const
{
CALL_USE_ARGS;
return boost::tuples::get<0>(args);
}
template<class SigArgs> struct sig {
// typedef typename detail::tuple_element_as_reference<0, SigArgs>::type type;
typedef typename boost::tuples::element<0, Args>::type type;
};
};
// Do nothing --------------------------------------------------------
class do_nothing_action {};
// The work of curry action is not defined in action class apply,
// but rather directly in lambda_functor_base::call
// The argument substitution would be messed up otherwise.
// the curry_action 2-ary lambda_functor, one curried arg -------------------
template<class Args>
class lambda_functor_base<do_nothing_action, Args> {
// Args args;
class lambda_functor_base<action<3, curry_action<1> >, Args>
{
public:
Args args;
public:
// explicit lambda_functor_base(const Args& a) {}
lambda_functor_base() {}
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET, CALL_TEMPLATE_ARGS> RET call(CALL_FORMAL_ARGS) const {
return CALL_USE_ARGS;
template<class RET, class A, class B, class C>
RET call(A& a, B& b, C& c) const
{
return boost::tuples::get<0>(args).template ret_call<RET>(
boost::tuples::get<1>(args), a);
}
};
template<class SigArgs> struct sig { typedef void type; };
};
// the curry_action case, 3-ary lambda functor, one curried arg --------------
template<class Args>
class lambda_functor_base<action<4, curry_action<1> >, Args>
{
public:
Args args;
public:
explicit lambda_functor_base(const Args& a) : args(a) {}
// These specializations provide a shorter notation to define actions.
// These lambda_functor_base instances take care of the recursive evaluation
// of the arguments and pass the evaluated arguments to the apply function
// of an action class. To make action X work with these classes, one must
// instantiate the lambda_functor_base as:
// lambda_functor_base<action<ARITY, X>, Args>
// Where ARITY is the arity of the apply function in X
template<class RET, class A, class B, class C>
RET call(A& a, B& b, C& c) const
{
return boost::tuples::get<0>(args).template ret_call<RET>(
boost::tuples::get<1>(args), a, b);
}
};
// The return type is queried as:
// return_type_N<X, EvaluatedArgumentTypes>::type
// for which there must be a specialization.
// the curry_action case, 3-ary lambda functor, two curried args -------------
template<class Args>
class lambda_functor_base<action<4, curry_action<2> >, Args>
{
public:
Args args;
public:
// Function actions, casts, throws,... all go via these classes.
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class Act, class Args>
class lambda_functor_base<action<0, Act>, Args>
{
public:
// Args args; not needed
explicit lambda_functor_base(const Args& /*a*/) {}
template<class SigArgs> struct sig {
typedef typename return_type_N<Act, null_type>::type type;
};
template<class RET, CALL_TEMPLATE_ARGS>
RET call(CALL_FORMAL_ARGS) const {
CALL_USE_ARGS;
return Act::template apply<RET>();
template<class RET, class A, class B, class C>
RET call(A& a, B& b, C& c) const
{
return boost::tuples::get<0>(args).template ret_call<RET>(
boost::tuples::get<1>(args), boost::tuples::get<2>(args), a);
}
};
#if defined BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART
#error "Multiple defines of BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART"
#endif
#define BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART(ARITY) \
template<class Act, class Args> \
class lambda_functor_base<action<ARITY, Act>, Args> \
{ \
public: \
Args args; \
\
explicit lambda_functor_base(const Args& a) : args(a) {} \
\
template<class SigArgs> struct sig { \
typedef typename \
detail::deduce_argument_types<Args, SigArgs>::type rets_t; \
public: \
typedef typename \
return_type_N_prot<Act, rets_t>::type type; \
}; \
\
\
template<class RET, CALL_TEMPLATE_ARGS> \
RET call(CALL_FORMAL_ARGS) const { \
using boost::tuples::get; \
using detail::constify_rvals; \
using detail::r_select; \
using detail::element_or_null; \
using detail::deduce_argument_types;
#if defined BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART
#error "Multiple defines of BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART"
#endif
#define BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART(ARITY) \
template<class Act, class Args>\
class lambda_functor_base<action<ARITY, Act>, Args> \
{\
public:\
Args args;\
public:\
\
explicit lambda_functor_base(const Args& a) : args(a) {}\
\
template<class RET, class A, class B, class C>\
RET call(A& a, B& b, C& c) const {\
\
BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART(0)
return Act::template apply<RET>(
);
}
};
BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART(1)
typedef typename
deduce_argument_types<Args, tuple<CALL_REFERENCE_TYPES> >::type rets_t;
typedef typename element_or_null<0, rets_t>::type rt0;
typedef typename detail::nth_return_type<0, Args, A&, B&, C&>::type ret0;
return Act::template apply<RET>(
constify_rvals<rt0>::go(r_select<rt0>::go(get<0>(args), CALL_ACTUAL_ARGS))
return Act::template apply<RET>(
detail::make_rvalues_const<ret0>::exec(detail::ret_selector<ret0>::select(boost::tuples::get<0>(args), a, b, c))
);
}
};
BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART(2)
typedef typename
deduce_argument_types<Args, tuple<CALL_REFERENCE_TYPES> >::type rets_t;
typedef typename element_or_null<0, rets_t>::type rt0;
typedef typename element_or_null<1, rets_t>::type rt1;
return Act::template apply<RET>(
constify_rvals<rt0>::go(r_select<rt0>::go(get<0>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt1>::go(r_select<rt1>::go(get<1>(args), CALL_ACTUAL_ARGS))
typedef typename detail::nth_return_type<0, Args, A&, B&, C&>::type ret0;
typedef typename detail::nth_return_type<1, Args, A&, B&, C&>::type ret1;
return Act::template apply<RET>(
detail::make_rvalues_const<ret0>::exec(detail::ret_selector<ret0>::select(boost::tuples::get<0>(args), a, b, c)),
detail::make_rvalues_const<ret1>::exec(detail::ret_selector<ret1>::select(boost::tuples::get<1>(args), a, b, c))
);
}
};
BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART(3)
typedef typename detail::nth_return_type<0, Args, A&, B&, C&>::type ret0;
typedef typename detail::nth_return_type<1, Args, A&, B&, C&>::type ret1;
typedef typename detail::nth_return_type<2, Args, A&, B&, C&>::type ret2;
typedef typename
deduce_argument_types<Args, tuple<CALL_REFERENCE_TYPES> >::type rets_t;
typedef typename element_or_null<0, rets_t>::type rt0;
typedef typename element_or_null<1, rets_t>::type rt1;
typedef typename element_or_null<2, rets_t>::type rt2;
return Act::template apply<RET>(
constify_rvals<rt0>::go(r_select<rt0>::go(get<0>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt1>::go(r_select<rt1>::go(get<1>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt2>::go(r_select<rt2>::go(get<2>(args), CALL_ACTUAL_ARGS))
return Act::template apply<RET>(
detail::make_rvalues_const<ret0>::exec(detail::ret_selector<ret0>::select(boost::tuples::get<0>(args), a, b, c)),
detail::make_rvalues_const<ret1>::exec(detail::ret_selector<ret1>::select(boost::tuples::get<1>(args), a, b, c)),
detail::make_rvalues_const<ret2>::exec(detail::ret_selector<ret2>::select(boost::tuples::get<2>(args), a, b, c))
);
}
};
BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART(4)
typedef typename
deduce_argument_types<Args, tuple<CALL_REFERENCE_TYPES> >::type rets_t;
typedef typename element_or_null<0, rets_t>::type rt0;
typedef typename element_or_null<1, rets_t>::type rt1;
typedef typename element_or_null<2, rets_t>::type rt2;
typedef typename element_or_null<3, rets_t>::type rt3;
typedef typename detail::nth_return_type<0, Args, A&, B&, C&>::type ret0;
typedef typename detail::nth_return_type<1, Args, A&, B&, C&>::type ret1;
typedef typename detail::nth_return_type<2, Args, A&, B&, C&>::type ret2;
typedef typename detail::nth_return_type<3, Args, A&, B&, C&>::type ret3;
return Act::template apply<RET>(
constify_rvals<rt0>::go(r_select<rt0>::go(get<0>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt1>::go(r_select<rt1>::go(get<1>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt2>::go(r_select<rt2>::go(get<2>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt3>::go(r_select<rt3>::go(get<3>(args), CALL_ACTUAL_ARGS))
return Act::template apply<RET>(
detail::make_rvalues_const<ret0>::exec(detail::ret_selector<ret0>::select(boost::tuples::get<0>(args), a, b, c)),
detail::make_rvalues_const<ret1>::exec(detail::ret_selector<ret1>::select(boost::tuples::get<1>(args), a, b, c)),
detail::make_rvalues_const<ret2>::exec(detail::ret_selector<ret2>::select(boost::tuples::get<2>(args), a, b, c)),
detail::make_rvalues_const<ret3>::exec(detail::ret_selector<ret3>::select(boost::tuples::get<3>(args), a, b, c))
);
}
};
BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART(5)
typedef typename
deduce_argument_types<Args, tuple<CALL_REFERENCE_TYPES> >::type rets_t;
typedef typename element_or_null<0, rets_t>::type rt0;
typedef typename element_or_null<1, rets_t>::type rt1;
typedef typename element_or_null<2, rets_t>::type rt2;
typedef typename element_or_null<3, rets_t>::type rt3;
typedef typename element_or_null<4, rets_t>::type rt4;
typedef typename detail::nth_return_type<0, Args, A&, B&, C&>::type ret0;
typedef typename detail::nth_return_type<1, Args, A&, B&, C&>::type ret1;
typedef typename detail::nth_return_type<2, Args, A&, B&, C&>::type ret2;
typedef typename detail::nth_return_type<3, Args, A&, B&, C&>::type ret3;
typedef typename detail::nth_return_type<4, Args, A&, B&, C&>::type ret4;
return Act::template apply<RET>(
constify_rvals<rt0>::go(r_select<rt0>::go(get<0>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt1>::go(r_select<rt1>::go(get<1>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt2>::go(r_select<rt2>::go(get<2>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt3>::go(r_select<rt3>::go(get<3>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt4>::go(r_select<rt4>::go(get<4>(args), CALL_ACTUAL_ARGS))
return Act::template apply<RET>(
detail::make_rvalues_const<ret0>::exec(detail::ret_selector<ret0>::select(boost::tuples::get<0>(args), a, b, c)),
detail::make_rvalues_const<ret1>::exec(detail::ret_selector<ret1>::select(boost::tuples::get<1>(args), a, b, c)),
detail::make_rvalues_const<ret2>::exec(detail::ret_selector<ret2>::select(boost::tuples::get<2>(args), a, b, c)),
detail::make_rvalues_const<ret3>::exec(detail::ret_selector<ret3>::select(boost::tuples::get<3>(args), a, b, c)),
detail::make_rvalues_const<ret4>::exec(detail::ret_selector<ret4>::select(boost::tuples::get<4>(args), a, b, c))
);
}
};
BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART(6)
typedef typename
deduce_argument_types<Args, tuple<CALL_REFERENCE_TYPES> >::type rets_t;
typedef typename element_or_null<0, rets_t>::type rt0;
typedef typename element_or_null<1, rets_t>::type rt1;
typedef typename element_or_null<2, rets_t>::type rt2;
typedef typename element_or_null<3, rets_t>::type rt3;
typedef typename element_or_null<4, rets_t>::type rt4;
typedef typename element_or_null<5, rets_t>::type rt5;
typedef typename detail::nth_return_type<0, Args, A&, B&, C&>::type ret0;
typedef typename detail::nth_return_type<1, Args, A&, B&, C&>::type ret1;
typedef typename detail::nth_return_type<2, Args, A&, B&, C&>::type ret2;
typedef typename detail::nth_return_type<3, Args, A&, B&, C&>::type ret3;
typedef typename detail::nth_return_type<4, Args, A&, B&, C&>::type ret4;
typedef typename detail::nth_return_type<5, Args, A&, B&, C&>::type ret5;
return Act::template apply<RET>(
constify_rvals<rt0>::go(r_select<rt0>::go(get<0>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt1>::go(r_select<rt1>::go(get<1>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt2>::go(r_select<rt2>::go(get<2>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt3>::go(r_select<rt3>::go(get<3>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt4>::go(r_select<rt4>::go(get<4>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt5>::go(r_select<rt5>::go(get<5>(args), CALL_ACTUAL_ARGS))
detail::make_rvalues_const<ret0>::exec(detail::ret_selector<ret0>::select(boost::tuples::get<0>(args), a, b, c)),
detail::make_rvalues_const<ret1>::exec(detail::ret_selector<ret1>::select(boost::tuples::get<1>(args), a, b, c)),
detail::make_rvalues_const<ret2>::exec(detail::ret_selector<ret2>::select(boost::tuples::get<2>(args), a, b, c)),
detail::make_rvalues_const<ret3>::exec(detail::ret_selector<ret3>::select(boost::tuples::get<3>(args), a, b, c)),
detail::make_rvalues_const<ret4>::exec(detail::ret_selector<ret4>::select(boost::tuples::get<4>(args), a, b, c)),
detail::make_rvalues_const<ret5>::exec(detail::ret_selector<ret5>::select(boost::tuples::get<5>(args), a, b, c))
);
}
};
BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART(7)
typedef typename
deduce_argument_types<Args, tuple<CALL_REFERENCE_TYPES> >::type rets_t;
typedef typename element_or_null<0, rets_t>::type rt0;
typedef typename element_or_null<1, rets_t>::type rt1;
typedef typename element_or_null<2, rets_t>::type rt2;
typedef typename element_or_null<3, rets_t>::type rt3;
typedef typename element_or_null<4, rets_t>::type rt4;
typedef typename element_or_null<5, rets_t>::type rt5;
typedef typename element_or_null<6, rets_t>::type rt6;
typedef typename detail::nth_return_type<0, Args, A&, B&, C&>::type ret0;
typedef typename detail::nth_return_type<1, Args, A&, B&, C&>::type ret1;
typedef typename detail::nth_return_type<2, Args, A&, B&, C&>::type ret2;
typedef typename detail::nth_return_type<3, Args, A&, B&, C&>::type ret3;
typedef typename detail::nth_return_type<4, Args, A&, B&, C&>::type ret4;
typedef typename detail::nth_return_type<5, Args, A&, B&, C&>::type ret5;
typedef typename detail::nth_return_type<6, Args, A&, B&, C&>::type ret6;
return Act::template apply<RET>(
constify_rvals<rt0>::go(r_select<rt0>::go(get<0>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt1>::go(r_select<rt1>::go(get<1>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt2>::go(r_select<rt2>::go(get<2>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt3>::go(r_select<rt3>::go(get<3>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt4>::go(r_select<rt4>::go(get<4>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt5>::go(r_select<rt5>::go(get<5>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt6>::go(r_select<rt6>::go(get<6>(args), CALL_ACTUAL_ARGS))
return Act::template apply<RET>(
detail::make_rvalues_const<ret0>::exec(detail::ret_selector<ret0>::select(boost::tuples::get<0>(args), a, b, c)),
detail::make_rvalues_const<ret1>::exec(detail::ret_selector<ret1>::select(boost::tuples::get<1>(args), a, b, c)),
detail::make_rvalues_const<ret2>::exec(detail::ret_selector<ret2>::select(boost::tuples::get<2>(args), a, b, c)),
detail::make_rvalues_const<ret3>::exec(detail::ret_selector<ret3>::select(boost::tuples::get<3>(args), a, b, c)),
detail::make_rvalues_const<ret4>::exec(detail::ret_selector<ret4>::select(boost::tuples::get<4>(args), a, b, c)),
detail::make_rvalues_const<ret5>::exec(detail::ret_selector<ret5>::select(boost::tuples::get<5>(args), a, b, c)),
detail::make_rvalues_const<ret6>::exec(detail::ret_selector<ret6>::select(boost::tuples::get<6>(args), a, b, c))
);
}
};
BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART(8)
typedef typename
deduce_argument_types<Args, tuple<CALL_REFERENCE_TYPES> >::type rets_t;
typedef typename element_or_null<0, rets_t>::type rt0;
typedef typename element_or_null<1, rets_t>::type rt1;
typedef typename element_or_null<2, rets_t>::type rt2;
typedef typename element_or_null<3, rets_t>::type rt3;
typedef typename element_or_null<4, rets_t>::type rt4;
typedef typename element_or_null<5, rets_t>::type rt5;
typedef typename element_or_null<6, rets_t>::type rt6;
typedef typename element_or_null<7, rets_t>::type rt7;
typedef typename detail::nth_return_type<0, Args, A&, B&, C&>::type ret0;
typedef typename detail::nth_return_type<1, Args, A&, B&, C&>::type ret1;
typedef typename detail::nth_return_type<2, Args, A&, B&, C&>::type ret2;
typedef typename detail::nth_return_type<3, Args, A&, B&, C&>::type ret3;
typedef typename detail::nth_return_type<4, Args, A&, B&, C&>::type ret4;
typedef typename detail::nth_return_type<5, Args, A&, B&, C&>::type ret5;
typedef typename detail::nth_return_type<6, Args, A&, B&, C&>::type ret6;
typedef typename detail::nth_return_type<7, Args, A&, B&, C&>::type ret7;
return Act::template apply<RET>(
constify_rvals<rt0>::go(r_select<rt0>::go(get<0>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt1>::go(r_select<rt1>::go(get<1>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt2>::go(r_select<rt2>::go(get<2>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt3>::go(r_select<rt3>::go(get<3>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt4>::go(r_select<rt4>::go(get<4>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt5>::go(r_select<rt5>::go(get<5>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt6>::go(r_select<rt6>::go(get<6>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt7>::go(r_select<rt7>::go(get<7>(args), CALL_ACTUAL_ARGS))
return Act::template apply<RET>(
detail::make_rvalues_const<ret0>::exec(detail::ret_selector<ret0>::select(boost::tuples::get<0>(args), a, b, c)),
detail::make_rvalues_const<ret1>::exec(detail::ret_selector<ret1>::select(boost::tuples::get<1>(args), a, b, c)),
detail::make_rvalues_const<ret2>::exec(detail::ret_selector<ret2>::select(boost::tuples::get<2>(args), a, b, c)),
detail::make_rvalues_const<ret3>::exec(detail::ret_selector<ret3>::select(boost::tuples::get<3>(args), a, b, c)),
detail::make_rvalues_const<ret4>::exec(detail::ret_selector<ret4>::select(boost::tuples::get<4>(args), a, b, c)),
detail::make_rvalues_const<ret5>::exec(detail::ret_selector<ret5>::select(boost::tuples::get<5>(args), a, b, c)),
detail::make_rvalues_const<ret6>::exec(detail::ret_selector<ret6>::select(boost::tuples::get<6>(args), a, b, c)),
detail::make_rvalues_const<ret7>::exec(detail::ret_selector<ret7>::select(boost::tuples::get<7>(args), a, b, c))
);
}
};
BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART(9)
typedef typename
deduce_argument_types<Args, tuple<CALL_REFERENCE_TYPES> >::type rets_t;
typedef typename element_or_null<0, rets_t>::type rt0;
typedef typename element_or_null<1, rets_t>::type rt1;
typedef typename element_or_null<2, rets_t>::type rt2;
typedef typename element_or_null<3, rets_t>::type rt3;
typedef typename element_or_null<4, rets_t>::type rt4;
typedef typename element_or_null<5, rets_t>::type rt5;
typedef typename element_or_null<6, rets_t>::type rt6;
typedef typename element_or_null<7, rets_t>::type rt7;
typedef typename element_or_null<8, rets_t>::type rt8;
return Act::template apply<RET>(
constify_rvals<rt0>::go(r_select<rt0>::go(get<0>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt1>::go(r_select<rt1>::go(get<1>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt2>::go(r_select<rt2>::go(get<2>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt3>::go(r_select<rt3>::go(get<3>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt4>::go(r_select<rt4>::go(get<4>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt5>::go(r_select<rt5>::go(get<5>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt6>::go(r_select<rt6>::go(get<6>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt7>::go(r_select<rt7>::go(get<7>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt8>::go(r_select<rt8>::go(get<8>(args), CALL_ACTUAL_ARGS))
typedef typename detail::nth_return_type<0, Args, A&, B&, C&>::type ret0;
typedef typename detail::nth_return_type<1, Args, A&, B&, C&>::type ret1;
typedef typename detail::nth_return_type<2, Args, A&, B&, C&>::type ret2;
typedef typename detail::nth_return_type<3, Args, A&, B&, C&>::type ret3;
typedef typename detail::nth_return_type<4, Args, A&, B&, C&>::type ret4;
typedef typename detail::nth_return_type<5, Args, A&, B&, C&>::type ret5;
typedef typename detail::nth_return_type<6, Args, A&, B&, C&>::type ret6;
typedef typename detail::nth_return_type<7, Args, A&, B&, C&>::type ret7;
typedef typename detail::nth_return_type<8, Args, A&, B&, C&>::type ret8;
return Act::template apply<RET>(
detail::make_rvalues_const<ret0>::exec(detail::ret_selector<ret0>::select(boost::tuples::get<0>(args), a, b, c)),
detail::make_rvalues_const<ret1>::exec(detail::ret_selector<ret1>::select(boost::tuples::get<1>(args), a, b, c)),
detail::make_rvalues_const<ret2>::exec(detail::ret_selector<ret2>::select(boost::tuples::get<2>(args), a, b, c)),
detail::make_rvalues_const<ret3>::exec(detail::ret_selector<ret3>::select(boost::tuples::get<3>(args), a, b, c)),
detail::make_rvalues_const<ret4>::exec(detail::ret_selector<ret4>::select(boost::tuples::get<4>(args), a, b, c)),
detail::make_rvalues_const<ret5>::exec(detail::ret_selector<ret5>::select(boost::tuples::get<5>(args), a, b, c)),
detail::make_rvalues_const<ret6>::exec(detail::ret_selector<ret6>::select(boost::tuples::get<6>(args), a, b, c)),
detail::make_rvalues_const<ret7>::exec(detail::ret_selector<ret7>::select(boost::tuples::get<7>(args), a, b, c)),
detail::make_rvalues_const<ret8>::exec(detail::ret_selector<ret8>::select(boost::tuples::get<8>(args), a, b, c))
);
}
};
BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART(10)
typedef typename
deduce_argument_types<Args, tuple<CALL_REFERENCE_TYPES> >::type rets_t;
typedef typename element_or_null<0, rets_t>::type rt0;
typedef typename element_or_null<1, rets_t>::type rt1;
typedef typename element_or_null<2, rets_t>::type rt2;
typedef typename element_or_null<3, rets_t>::type rt3;
typedef typename element_or_null<4, rets_t>::type rt4;
typedef typename element_or_null<5, rets_t>::type rt5;
typedef typename element_or_null<6, rets_t>::type rt6;
typedef typename element_or_null<7, rets_t>::type rt7;
typedef typename element_or_null<8, rets_t>::type rt8;
typedef typename element_or_null<9, rets_t>::type rt9;
return Act::template apply<RET>(
constify_rvals<rt0>::go(r_select<rt0>::go(get<0>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt1>::go(r_select<rt1>::go(get<1>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt2>::go(r_select<rt2>::go(get<2>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt3>::go(r_select<rt3>::go(get<3>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt4>::go(r_select<rt4>::go(get<4>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt5>::go(r_select<rt5>::go(get<5>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt6>::go(r_select<rt6>::go(get<6>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt7>::go(r_select<rt7>::go(get<7>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt8>::go(r_select<rt8>::go(get<8>(args), CALL_ACTUAL_ARGS)),
constify_rvals<rt9>::go(r_select<rt9>::go(get<9>(args), CALL_ACTUAL_ARGS))
typedef typename detail::nth_return_type<0, Args, A&, B&, C&>::type ret0;
typedef typename detail::nth_return_type<1, Args, A&, B&, C&>::type ret1;
typedef typename detail::nth_return_type<2, Args, A&, B&, C&>::type ret2;
typedef typename detail::nth_return_type<3, Args, A&, B&, C&>::type ret3;
typedef typename detail::nth_return_type<4, Args, A&, B&, C&>::type ret4;
typedef typename detail::nth_return_type<5, Args, A&, B&, C&>::type ret5;
typedef typename detail::nth_return_type<6, Args, A&, B&, C&>::type ret6;
typedef typename detail::nth_return_type<7, Args, A&, B&, C&>::type ret7;
typedef typename detail::nth_return_type<8, Args, A&, B&, C&>::type ret8;
typedef typename detail::nth_return_type<9, Args, A&, B&, C&>::type ret9;
return Act::template apply<RET>(
detail::make_rvalues_const<ret0>::exec(detail::ret_selector<ret0>::select(boost::tuples::get<0>(args), a, b, c)),
detail::make_rvalues_const<ret1>::exec(detail::ret_selector<ret1>::select(boost::tuples::get<1>(args), a, b, c)),
detail::make_rvalues_const<ret2>::exec(detail::ret_selector<ret2>::select(boost::tuples::get<2>(args), a, b, c)),
detail::make_rvalues_const<ret3>::exec(detail::ret_selector<ret3>::select(boost::tuples::get<3>(args), a, b, c)),
detail::make_rvalues_const<ret4>::exec(detail::ret_selector<ret4>::select(boost::tuples::get<4>(args), a, b, c)),
detail::make_rvalues_const<ret5>::exec(detail::ret_selector<ret5>::select(boost::tuples::get<5>(args), a, b, c)),
detail::make_rvalues_const<ret6>::exec(detail::ret_selector<ret6>::select(boost::tuples::get<6>(args), a, b, c)),
detail::make_rvalues_const<ret7>::exec(detail::ret_selector<ret7>::select(boost::tuples::get<7>(args), a, b, c)),
detail::make_rvalues_const<ret8>::exec(detail::ret_selector<ret8>::select(boost::tuples::get<8>(args), a, b, c)),
detail::make_rvalues_const<ret9>::exec(detail::ret_selector<ret9>::select(boost::tuples::get<9>(args), a, b, c))
);
}
};

View File

@@ -1,10 +1,15 @@
// Boost Lambda Library - lambda_functors.hpp -------------------------------
// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
//
// 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)
// 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
@@ -13,31 +18,6 @@
#ifndef BOOST_LAMBDA_LAMBDA_FUNCTORS_HPP
#define BOOST_LAMBDA_LAMBDA_FUNCTORS_HPP
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/utility/result_of.hpp>
#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
#include <boost/mpl/or.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_array.hpp>
#define BOOST_LAMBDA_DISABLE_IF_ARRAY1(A1, R1)\
typename lazy_disable_if<is_array<A1>, typename R1 >::type
#define BOOST_LAMBDA_DISABLE_IF_ARRAY2(A1, A2, R1, R2) \
typename lazy_disable_if<mpl::or_<is_array<A1>, is_array<A2> >, typename R1, R2 >::type
#define BOOST_LAMBDA_DISABLE_IF_ARRAY3(A1, A2, A3, R1, R2, R3) \
typename lazy_disable_if<mpl::or_<is_array<A1>, is_array<A2>, is_array<A3> >, typename R1, R2, R3 >::type
#else
#define BOOST_LAMBDA_DISABLE_IF_ARRAY1(A1, R1) typename R1::type
#define BOOST_LAMBDA_DISABLE_IF_ARRAY2(A1, A2, R1, R2) typename R1, R2::type
#define BOOST_LAMBDA_DISABLE_IF_ARRAY3(A1, A2, A3, R1, R2, R3) typename R1, R2, R3::type
#endif
namespace boost {
namespace lambda {
@@ -54,304 +34,558 @@ namespace {
} // unnamed
} // detail
class unused {};
#define const_null_type() detail::constant_null_type
#define cnull_type() detail::constant_null_type
#if defined BOOST_LAMBDA_LAMBDA_FUNCTOR_ASSIGNMENT
#error "Multiple defines of BOOST_LAMBDA_LAMBDA_FUNCTOR_ASSIGNMENT"
#endif
#define BOOST_LAMBDA_LAMBDA_FUNCTOR_ASSIGNMENT\
template<class A>\
const lambda_functor<lambda_functor_args<\
action<2, other_action<assignment_action> >,\
boost::tuple<lambda_functor, \
typename const_copy_argument <const A>::type>,\
combine_arities<lambda_functor,A>::value> >\
operator=(const A& a) const { \
return lambda_functor<lambda_functor_args<\
action<2, other_action<assignment_action> >,\
boost::tuple<lambda_functor, \
typename const_copy_argument <const A>::type>,\
combine_arities<lambda_functor,A>::value> >\
( boost::tuple<lambda_functor, \
typename const_copy_argument <const A>::type>(*this, a) );\
}\
\
#if defined BOOST_LAMBDA_LAMBDA_FUNCTOR_SUBSCRIPT
#error "Multiple defines of BOOST_LAMBDA_LAMBDA_FUNCTOR_SUBSCRIPT"
#endif
#define BOOST_LAMBDA_LAMBDA_FUNCTOR_SUBSCRIPT\
template<class A>\
const lambda_functor<lambda_functor_args<\
action<2, other_action<subscript_action> >,\
boost::tuple<lambda_functor, \
typename const_copy_argument <const A>::type>,\
combine_arities<lambda_functor,A>::value> >\
operator[](const A& a) const { \
return lambda_functor<lambda_functor_args<\
action<2, other_action<subscript_action> >,\
boost::tuple<lambda_functor, \
typename const_copy_argument <const A>::type>,\
combine_arities<lambda_functor,A>::value> >\
( boost::tuple<lambda_functor, \
typename const_copy_argument <const A>::type>(*this, a ) );\
}\
\
template <int I>
class lambda_functor<placeholder<I> > {
public:
lambda_functor() {}
// default constructor (do nothing)
// bug in gcc 2.95.2 for const template objects.
BOOST_LAMBDA_LAMBDA_FUNCTOR_ASSIGNMENT
BOOST_LAMBDA_LAMBDA_FUNCTOR_SUBSCRIPT
};
// -- free variables types --------------------------------------------------
// helper to work around the case where the nullary return type deduction
// is always performed, even though the functor is not nullary
namespace detail {
template<int N, class Tuple> struct get_element_or_null_type {
// helpers
template <class T> struct identity { typedef T type; };
// take the Nth element in the tuple, or null_type if tuple is not
// long enough
template <int N, class T>
struct element_or_null_type {
typedef typename
detail::IF_type<
(N < boost::tuples::length<T>::value),
boost::tuples::element<N, T>,
identity<null_type>
>::type type;
};
// Lambda functors all provide the sig member template for
// querying their return type.
// these type mappings implement the tools for that deduction
//type mapping to compute the new lambda functor resulting from a curried
// call.
template<class LF, int Args_expected, class SigArgs>
struct curry_sig {
// First arg in SigArgs is the lambda functor type, that's why the -1
BOOST_STATIC_CONSTANT(int, acount = boost::tuples::length<SigArgs>::value-1);
// currying is only supported for 2- and 3-ary lambda functors, and
// must be called by 1 or 2 arguments.
// acount 1 or 2, dig_arity<LF>::value SECOND or THIRD
typedef typename detail::element_or_null_type<1, SigArgs>::type el_1;
typedef typename detail::element_or_null_type<2, SigArgs>::type el_2;
typedef lambda_functor<
lambda_functor_args<
action<Args_expected + 1, curry_action<acount> >,
// remove_const_refernce takes care that const null_type will
// be null_type, that arrays are always stored as const refs,
// that nonconst refs remain nonconst refs, and everything else goes
// to const copy.
tuple<
LF,
typename detail::remove_const_reference<el_1>::type,
typename detail::remove_const_reference<el_2>::type
>,
detail::reduce_arity<dig_arity<LF>::value, acount>::value
>
> type;
};
// enter the normal return type deduction
template <class LF, class SigArgs>
struct eval_sig
{
typedef typename
detail::tuple_element_as_reference<N, Tuple>::type type;
};
template<int N> struct get_element_or_null_type<N, null_type> {
typedef null_type type;
};
}
template <int I> struct placeholder;
template<> struct placeholder<FIRST> {
template<class SigArgs> struct sig {
typedef typename detail::get_element_or_null_type<0, SigArgs>::type type;
return_type<
LF,
open_args<
typename detail::element_or_null_type<1, SigArgs>::type,
typename detail::element_or_null_type<2, SigArgs>::type,
typename detail::element_or_null_type<3, SigArgs>::type
>
>::type type;
};
template<class RET, CALL_TEMPLATE_ARGS>
RET call(CALL_FORMAL_ARGS) const {
BOOST_STATIC_ASSERT(boost::is_reference<RET>::value);
CALL_USE_ARGS; // does nothing, prevents warnings for unused args
return a;
// either a normal evaluation, or a curried call
template <class LF, int Args_expected, class SigArgs>
struct lambda_functor_sig
{
typedef typename
detail::IF_type<
(boost::tuples::length<SigArgs>::value - 1 < Args_expected),
detail::curry_sig<LF, Args_expected, SigArgs>,
detail::eval_sig<LF, SigArgs>
>::type type;
};
} // end detail
// -- lambda_functor NONE ------------------------------------------------
template <class Action, class Args>
class lambda_functor<lambda_functor_args<Action, Args, NONE> >
: public lambda_functor_base<Action, Args>, public has_sig
{
public:
typedef lambda_functor_base<Action, Args> inherited;
explicit lambda_functor(const Args& args)
: inherited(args) {}
// lambda functors can be copied, if arity and action are the same
// and Args tuples are copyable
template <class Args2> lambda_functor
(const lambda_functor<lambda_functor_args<Action, Args2, NONE> >& f)
: inherited(f.args) {}
template <class SigArgs> struct sig {
typedef typename
detail::lambda_functor_sig<lambda_functor, 0, SigArgs>::type type;
};
typename return_type<
lambda_functor,
open_args<null_type, null_type, null_type>
>::type
operator()() const {
return inherited::template
call<
typename return_type<
lambda_functor,
open_args<null_type, null_type, null_type> >::type
>(const_null_type(), const_null_type(), const_null_type());
}
template<class RET>
RET ret_call() const {
return inherited:: template call<RET>(const_null_type(),
const_null_type(),
const_null_type());
}
BOOST_LAMBDA_LAMBDA_FUNCTOR_ASSIGNMENT
BOOST_LAMBDA_LAMBDA_FUNCTOR_SUBSCRIPT
};
// -- lambda_functor FIRST -------------------------------------------------
template <class Action, class Args>
class lambda_functor<lambda_functor_args<Action, Args, FIRST> >
: public lambda_functor_base<Action, Args>
{
public:
typedef lambda_functor_base<Action, Args> inherited;
explicit lambda_functor(const Args& args)
: inherited(args) {}
// lambda functors can be copied, if arity and action are the same
// and Args tuples copyable
template <class Args2> lambda_functor
(const lambda_functor<lambda_functor_args<Action, Args2, FIRST> >& f)
: inherited(f.args) {}
template <class SigArgs> struct sig {
typedef typename
detail::lambda_functor_sig<lambda_functor, 1, SigArgs>::type type;
};
template<class A>
typename
return_type<lambda_functor, open_args<A&, null_type, null_type> >::type
operator()(A& a) const
{
return inherited::template call<
typename return_type<
lambda_functor, open_args<A&, null_type, null_type>
>::type
>(a, const_null_type(), const_null_type());
}
template<class RET, class A>
RET ret_call(A& a) const
{
return inherited:: template call<RET>(a, const_null_type(), const_null_type());
}
BOOST_LAMBDA_LAMBDA_FUNCTOR_ASSIGNMENT
BOOST_LAMBDA_LAMBDA_FUNCTOR_SUBSCRIPT
};
// -- lambda_functor SECOND -------------------------------------------------
template <class Action, class Args>
class lambda_functor<lambda_functor_args<Action, Args, SECOND> >
: public lambda_functor_base<Action, Args>, public has_sig
{
public:
typedef lambda_functor_base<Action, Args> inherited;
explicit lambda_functor(const Args& args)
: inherited(args) {}
// lambda functors can be copied, if arity and action are the same
// and Args tuples copyable
template <class Args2> lambda_functor
(const lambda_functor<lambda_functor_args<Action, Args2, SECOND> >& f)
: inherited(f.args) {}
template <class SigArgs> struct sig {
typedef typename
detail::lambda_functor_sig<lambda_functor, 2, SigArgs>::type type;
};
template<class A, class B>
typename return_type<lambda_functor, open_args<A&, B&, null_type> >::type
operator()(A& a, B& b) const
{
return inherited::template call<
typename return_type<
lambda_functor, open_args<A&, B&, null_type>
>::type>(a, b, const_null_type());
}
// currying call: creates another lambda functor
template<class A>
typename sig<tuple<const lambda_functor&, A&> >::type
operator()(A& a) const
{
return
typename sig<tuple<const lambda_functor&, A&> >::type
(
tuple<lambda_functor,
typename detail::remove_const_reference<A&>::type>(*this, a)
);
}
template<class RET, class A, class B>
RET ret_call(A& a, B& b) const {
return inherited::template call<RET>(a, b, const_null_type());
}
BOOST_LAMBDA_LAMBDA_FUNCTOR_ASSIGNMENT
BOOST_LAMBDA_LAMBDA_FUNCTOR_SUBSCRIPT
};
// -- lambda_functor THIRD -------------------------------------------------
template <class Action, class Args>
class lambda_functor<lambda_functor_args<Action, Args, THIRD> > : public lambda_functor_base<Action, Args>, public has_sig
{
public:
typedef lambda_functor_base<Action, Args> inherited;
explicit lambda_functor(const Args& args)
: inherited(args) {}
// lambda functors can be copied, if arity and action are the same
// and Args tuples copyable
template <class Args2> lambda_functor
(const lambda_functor<lambda_functor_args<Action, Args2, THIRD> >& f)
: inherited(f.args) {}
template <class SigArgs> struct sig {
typedef typename
detail::lambda_functor_sig<lambda_functor, 3, SigArgs>::type type;
};
template<class A, class B, class C>
typename return_type<lambda_functor, open_args<A&, B&, C&> >::type
operator()(A& a, B& b, C& c) const
{
return inherited::template call<
typename return_type<lambda_functor, open_args<A&, B&, C&>
>::type>(a, b, c);
}
template<class RET, class A, class B, class C>
RET ret_call(A& a, B& b, C& c) const {
return inherited::template call<RET>(a, b, c);
}
// currying call, one argument still missing
template<class A, class B>
typename sig<tuple<const lambda_functor&, A&, B&> >::type
operator()(A& a, B& b) const
{
return
typename sig<tuple<const lambda_functor&, A&, B&> >::type
( tuple<
lambda_functor,
typename detail::remove_const_reference<A&>::type,
typename detail::remove_const_reference<B&>::type
> (*this, a, b)
);
}
// currying call, two arguments still missing
// The return type is:
// lambda_functor<
// lambda_functor_args<
// action<4, curry_action<1> >,
// detail::bind_tuple_mapper<lambda_functor, const A>::type,
// SECOND
// >
// >
template<class A>
typename sig<tuple<const lambda_functor&, A&> >::type
operator()(A& a) const
{
return
typename sig<tuple<const lambda_functor&, A&> >::type
(
tuple<lambda_functor, typename detail::remove_const_reference<A&>::type>(*this, a)
);
}
BOOST_LAMBDA_LAMBDA_FUNCTOR_ASSIGNMENT
BOOST_LAMBDA_LAMBDA_FUNCTOR_SUBSCRIPT
};
// -- lambda_functor (Arbitrary Code) ---------------------------------------
// matches any arity code with EXCEPTION or RETHROW bits on
// This specialisation is only instantiated if delayed exception
// handling is used. See exceptions.hpp.
// ----------------------------------------------------------
template <class Action, class Args, int Code>
class lambda_functor<lambda_functor_args<Action, Args, Code> >
: public lambda_functor_base<Action, Args>
{
public:
typedef lambda_functor_base<Action, Args> inherited;
explicit lambda_functor(const Args& args)
: inherited(args) {}
// lambda functors can be copied, if arity and action are the same
// and Args tuples copyable
template <class Args2> lambda_functor
(const lambda_functor<lambda_functor_args<Action, Args2, Code> >& f)
: inherited(f.args) {}
// No operator() for this, since this lambda_functor can only be used
// in a catch_exception or catch_all
template<class RET, class A, class B, class C>
RET ret_call(A& a, B& b, C& c) const
{
return inherited::template call<RET>(a, b, c);
}
};
// any lambda functor can be turned into a const_incorrect_lambda_functor
// The operator() takes arguments as consts and then casts constness
// away. So this breaks const correctness!!! but is a necessary workaround
// in some cases due to language limitations.
// Note, that this is not a lambda_functor anymore, so it can not be used
// as a sub lambda expression.
template <class Arg>
struct const_incorrect_lambda_functor
: private lambda_functor<Arg> {
public:
BOOST_STATIC_ASSERT(dig_arity<Arg>::value <= THIRD);
// only allowed for normal lambda functions, not EXCEPTION ones
typedef lambda_functor<Arg> inherited;
explicit const_incorrect_lambda_functor(const lambda_functor<Arg>& lf)
: inherited(lf.args) {}
template <class SigArgs> struct sig {
typedef typename
::boost::lambda::lambda_functor<Arg>::template sig<SigArgs>::type type;
};
typename sig<tuple<const lambda_functor<Arg>& > >::type
operator()() const {
return inherited::template ret_call<typename sig<tuple<const lambda_functor<Arg>& > >::type>();
}
template<class A>
typename sig<tuple<const lambda_functor<Arg>&, A&> >::type
operator()(const A& a) const {
return inherited::template ret_call<typename sig<tuple<const lambda_functor<Arg>&, A&> >::type >(const_cast<A&>(a));
}
template<class A, class B>
typename sig<tuple<const lambda_functor<Arg>&, A&, B&> >::type
operator()(const A& a, const B& b) const {
return inherited::template ret_call<typename sig<tuple<const lambda_functor<Arg>&, A&, B&> >::type >(const_cast<A&>(a), const_cast<B&>(b));
}
template<class A, class B, class C>
typename sig<tuple<const lambda_functor<Arg>&, A&, B&, C&> >::type
operator()(const A& a, const B& b, const C& c) const {
return inherited::template ret_call<typename sig<tuple<const lambda_functor<Arg>&, A&, B&, C&> >::type>(const_cast<A&>(a), const_cast<B&>(b), const_cast<C&>(c));
}
};
template<> struct placeholder<SECOND> {
// ------------------------------------------------------------------------
// any lambda functor can be turned into a const_parameter_lambda_functor
// The operator() takes arguments as const.
// This is useful if lambda functors are called with non-const rvalues.
// Note, that this is not a lambda_functor anymore, so it can not be used
// as a sub lambda expression.
template<class SigArgs> struct sig {
typedef typename detail::get_element_or_null_type<1, SigArgs>::type type;
template <class Arg>
struct const_parameter_lambda_functor
: private lambda_functor<Arg> {
public:
BOOST_STATIC_ASSERT(dig_arity<Arg>::value <= THIRD);
// only allowed for normal lambda functions, not EXCEPTION ones
typedef lambda_functor<Arg> inherited;
explicit const_parameter_lambda_functor(const lambda_functor<Arg>& lf)
: inherited(lf.args) {}
template <class SigArgs> struct sig {
typedef typename
::boost::lambda::lambda_functor<Arg>::template sig<SigArgs>::type type;
};
template<class RET, CALL_TEMPLATE_ARGS>
RET call(CALL_FORMAL_ARGS) const { CALL_USE_ARGS; return b; }
// This is provided just for completeness; no arguments, no constness
// problems.
typename sig<tuple<const lambda_functor<Arg>& > >::type
operator()() const {
return inherited::template ret_call<typename sig<tuple<const lambda_functor<Arg>& > >::type>();
}
template<class A>
typename sig<tuple<const lambda_functor<Arg>&, const A&> >::type
operator()(const A& a) const {
return inherited::template ret_call<typename sig<tuple<const lambda_functor<Arg>&, const A&> >::type >(a);
}
template<class A, class B>
typename sig<tuple<const lambda_functor<Arg>&, const A&, const B&> >::type
operator()(const A& a, const B& b) const {
return inherited::template ret_call<typename sig<tuple<const lambda_functor<Arg>&, const A&, const B&> >::type >(a, b);
}
template<class A, class B, class C>
typename sig<tuple<const lambda_functor<Arg>&, const A&, const B&, const C&> >::type
operator()(const A& a, const B& b, const C& c) const {
return inherited::template ret_call<typename sig<tuple<const lambda_functor<Arg>&, const A&, const B&, const C&> >::type>(a, b, c);
}
};
template<> struct placeholder<THIRD> {
template<class SigArgs> struct sig {
typedef typename detail::get_element_or_null_type<2, SigArgs>::type type;
};
template<class RET, CALL_TEMPLATE_ARGS>
RET call(CALL_FORMAL_ARGS) const { CALL_USE_ARGS; return c; }
};
template<> struct placeholder<EXCEPTION> {
template<class SigArgs> struct sig {
typedef typename detail::get_element_or_null_type<3, SigArgs>::type type;
};
template<class RET, CALL_TEMPLATE_ARGS>
RET call(CALL_FORMAL_ARGS) const { CALL_USE_ARGS; return env; }
};
// -- free variables types --------------------------------------------------
template <int I> class placeholder {};
typedef const lambda_functor<placeholder<FIRST> > placeholder1_type;
typedef const lambda_functor<placeholder<SECOND> > placeholder2_type;
typedef const lambda_functor<placeholder<THIRD> > placeholder3_type;
///////////////////////////////////////////////////////////////////////////////
// free variables are lambda_functors. This is to allow uniform handling with
// other lambda_functors.
// -------------------------------------------------------------------
// Tagged lambda_functor -------------
// This is a generic class for special types of lambda functors,
// e.g. certain parameters of switch_statement must be case_statements,
// rather than arbitrary lambda functors
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
#pragma warning(push)
#pragma warning(disable:4512) //assignment operator could not be generated
#endif
// -- lambda_functor NONE ------------------------------------------------
template <class T>
class lambda_functor : public T
template<class Tag, class LambdaFunctor>
class tagged_lambda_functor;
template<class Tag, class Args>
class tagged_lambda_functor<Tag, lambda_functor<Args> >
: public lambda_functor<Args>
{
BOOST_STATIC_CONSTANT(int, arity_bits = get_arity<T>::value);
public:
typedef T inherited;
template<class T>
tagged_lambda_functor(const lambda_functor<T>& a)
: lambda_functor<Args>(a) {}
lambda_functor() {}
lambda_functor(const lambda_functor& l) : inherited(l) {}
lambda_functor(const T& t) : inherited(t) {}
template <class SigArgs> struct sig {
typedef typename inherited::template
sig<typename SigArgs::tail_type>::type type;
};
// Note that this return type deduction template is instantiated, even
// if the nullary
// operator() is not called at all. One must make sure that it does not fail.
typedef typename
inherited::template sig<null_type>::type
nullary_return_type;
// Support for boost::result_of.
template <class Sig> struct result;
template <class F>
struct result<F()> {
typedef nullary_return_type type;
};
template <class F, class A>
struct result<F(A)> {
typedef typename sig<tuple<F, A> >::type type;
};
template <class F, class A, class B>
struct result<F(A, B)> {
typedef typename sig<tuple<F, A, B> >::type type;
};
template <class F, class A, class B, class C>
struct result<F(A, B, C)> {
typedef typename sig<tuple<F, A, B, C> >::type type;
};
nullary_return_type operator()() const {
return inherited::template
call<nullary_return_type>
(cnull_type(), cnull_type(), cnull_type(), cnull_type());
}
template<class A>
typename inherited::template sig<tuple<A&> >::type
operator()(A& a) const {
return inherited::template call<
typename inherited::template sig<tuple<A&> >::type
>(a, cnull_type(), cnull_type(), cnull_type());
}
template<class A>
BOOST_LAMBDA_DISABLE_IF_ARRAY1(A, inherited::template sig<tuple<A const&> >)
operator()(A const& a) const {
return inherited::template call<
typename inherited::template sig<tuple<A const&> >::type
>(a, cnull_type(), cnull_type(), cnull_type());
}
template<class A, class B>
typename inherited::template sig<tuple<A&, B&> >::type
operator()(A& a, B& b) const {
return inherited::template call<
typename inherited::template sig<tuple<A&, B&> >::type
>(a, b, cnull_type(), cnull_type());
}
template<class A, class B>
BOOST_LAMBDA_DISABLE_IF_ARRAY2(A, B, inherited::template sig<tuple<A const&, B&> >)
operator()(A const& a, B& b) const {
return inherited::template call<
typename inherited::template sig<tuple<A const&, B&> >::type
>(a, b, cnull_type(), cnull_type());
}
template<class A, class B>
BOOST_LAMBDA_DISABLE_IF_ARRAY2(A, B, inherited::template sig<tuple<A&, B const&> >)
operator()(A& a, B const& b) const {
return inherited::template call<
typename inherited::template sig<tuple<A&, B const&> >::type
>(a, b, cnull_type(), cnull_type());
}
template<class A, class B>
BOOST_LAMBDA_DISABLE_IF_ARRAY2(A, B, inherited::template sig<tuple<A const&, B const&> >)
operator()(A const& a, B const& b) const {
return inherited::template call<
typename inherited::template sig<tuple<A const&, B const&> >::type
>(a, b, cnull_type(), cnull_type());
}
template<class A, class B, class C>
typename inherited::template sig<tuple<A&, B&, C&> >::type
operator()(A& a, B& b, C& c) const
{
return inherited::template call<
typename inherited::template sig<tuple<A&, B&, C&> >::type
>(a, b, c, cnull_type());
}
template<class A, class B, class C>
BOOST_LAMBDA_DISABLE_IF_ARRAY3(A, B, C, inherited::template sig<tuple<A const&, B const&, C const&> >)
operator()(A const& a, B const& b, C const& c) const
{
return inherited::template call<
typename inherited::template sig<tuple<A const&, B const&, C const&> >::type
>(a, b, c, cnull_type());
}
// for internal calls with env
template<CALL_TEMPLATE_ARGS>
typename inherited::template sig<tuple<CALL_REFERENCE_TYPES> >::type
internal_call(CALL_FORMAL_ARGS) const {
return inherited::template
call<typename inherited::template
sig<tuple<CALL_REFERENCE_TYPES> >::type>(CALL_ACTUAL_ARGS);
}
template<class A>
const lambda_functor<lambda_functor_base<
other_action<assignment_action>,
boost::tuple<lambda_functor,
typename const_copy_argument <const A>::type> > >
operator=(const A& a) const {
return lambda_functor_base<
other_action<assignment_action>,
boost::tuple<lambda_functor,
typename const_copy_argument <const A>::type> >
( boost::tuple<lambda_functor,
typename const_copy_argument <const A>::type>(*this, a) );
}
template<class A>
const lambda_functor<lambda_functor_base<
other_action<subscript_action>,
boost::tuple<lambda_functor,
typename const_copy_argument <const A>::type> > >
operator[](const A& a) const {
return lambda_functor_base<
other_action<subscript_action>,
boost::tuple<lambda_functor,
typename const_copy_argument <const A>::type> >
( boost::tuple<lambda_functor,
typename const_copy_argument <const A>::type>(*this, a ) );
}
// only works for the no body case.
explicit tagged_lambda_functor() : lambda_functor<Args>( null_type() ) {}
};
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
#pragma warning(pop)
#endif
#undef BOOST_LAMBDA_LAMBDA_FUNCTOR_ASSIGNMENT
#undef BOOST_LAMBDA_LAMBDA_FUNCTOR_ADDRESSOF
#undef BOOST_LAMBDA_LAMBDA_FUNCTOR_SUBSCRIPT
} // namespace lambda
} // namespace boost
namespace boost {
#if !defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_NO_CXX11_DECLTYPE)
template<class T>
struct result_of<boost::lambda::lambda_functor<T>()>
{
typedef typename boost::lambda::lambda_functor<T>::nullary_return_type type;
};
template<class T>
struct result_of<const boost::lambda::lambda_functor<T>()>
{
typedef typename boost::lambda::lambda_functor<T>::nullary_return_type type;
};
#endif
template<class T>
struct tr1_result_of<boost::lambda::lambda_functor<T>()>
{
typedef typename boost::lambda::lambda_functor<T>::nullary_return_type type;
};
template<class T>
struct tr1_result_of<const boost::lambda::lambda_functor<T>()>
{
typedef typename boost::lambda::lambda_functor<T>::nullary_return_type type;
};
}
// is_placeholder
#include <boost/is_placeholder.hpp>
namespace boost
{
template<> struct is_placeholder< lambda::lambda_functor< lambda::placeholder<lambda::FIRST> > >
{
enum _vt { value = 1 };
};
template<> struct is_placeholder< lambda::lambda_functor< lambda::placeholder<lambda::SECOND> > >
{
enum _vt { value = 2 };
};
template<> struct is_placeholder< lambda::lambda_functor< lambda::placeholder<lambda::THIRD> > >
{
enum _vt { value = 3 };
};
} // namespace boost
#endif

View File

@@ -1,10 +1,15 @@
// lambda_fwd.hpp - Boost Lambda Library -------------------------------
// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
//
// 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)
// 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 www.boost.org
@@ -23,16 +28,26 @@ template<class T> struct generate_error;
}
// -- placeholders --------------------------------------------
template <int I> struct placeholder;
template <int I> class placeholder;
// function_adaptors
template <class Func>
struct function_adaptor;
// The return_type traits class:
template <class Action, class Open>
class return_type;
template <int I, class Act> class action;
template <class Base>
class lambda_functor;
template <class BinderArgs>
struct lambda_functor;
template <class Action,
class Args,
int ArityCode>
class lambda_functor_args;
template <class Act, class Args>
class lambda_functor_base;
@@ -41,34 +56,4 @@ class lambda_functor_base;
} // namespace boost
// #define CALL_TEMPLATE_ARGS class A, class Env
// #define CALL_FORMAL_ARGS A& a, Env& env
// #define CALL_ACTUAL_ARGS a, env
// #define CALL_ACTUAL_ARGS_NO_ENV a
// #define CALL_REFERENCE_TYPES A&, Env&
// #define CALL_PLAIN_TYPES A, Env
#define CALL_TEMPLATE_ARGS class A, class B, class C, class Env
#define CALL_FORMAL_ARGS A& a, B& b, C& c, Env& env
#define CALL_ACTUAL_ARGS a, b, c, env
#define CALL_ACTUAL_ARGS_NO_ENV a, b, c
#define CALL_REFERENCE_TYPES A&, B&, C&, Env&
#define CALL_PLAIN_TYPES A, B, C, Env
namespace boost {
namespace lambda {
namespace detail {
template<class A1, class A2, class A3, class A4>
void do_nothing(A1&, A2&, A3&, A4&) {}
} // detail
} // lambda
} // boost
// prevent the warnings from unused arguments
#define CALL_USE_ARGS \
::boost::lambda::detail::do_nothing(a, b, c, env)
#endif

View File

@@ -1,10 +1,15 @@
// - lambda_traits.hpp --- Boost Lambda Library ----------------------------
//
// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
//
// 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)
// 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 www.boost.org
// -------------------------------------------------------------------------
@@ -16,7 +21,6 @@
#include "boost/type_traits/cv_traits.hpp"
#include "boost/type_traits/function_traits.hpp"
#include "boost/type_traits/object_traits.hpp"
#include "boost/tuple/tuple.hpp"
namespace boost {
namespace lambda {
@@ -54,9 +58,6 @@ struct IF_type
IF_type_<typename IF<C, T, E>::RET >::type type;
};
// helper that can be used to give typedef T to some type
template <class T> struct identity_mapping { typedef T type; };
// An if construct for finding an integral constant 'value'
// Does not instantiate the non-matching branch
// Called as IF_value<condition, A, B>::value
@@ -102,11 +103,13 @@ template<class T> struct remove_reference_and_cv {
// returns a reference to the element of tuple T
// If the element is stored as a copy, the reference is to
// const type. Constness of reference type elements remain unchanged.
template<int N, class T> struct tuple_element_as_reference {
typedef typename
boost::tuples::access_traits<
typename boost::tuples::element<N, T>::type
>::non_const_type type;
>::const_type type;
};
// returns the cv and reverence stripped type of a tuple element
@@ -164,8 +167,7 @@ struct parameter_traits_ {
// Do not instantiate with reference types
template<class T, class Any> struct parameter_traits_<T&, Any> {
typedef typename
generate_error<T&>::
parameter_traits_class_instantiated_with_reference_type type;
generate_error<T&>::parameter_traits_class_instantiated_with_reference_type type;
};
// Arrays can't be stored as plain types; convert them to references
@@ -212,28 +214,6 @@ template<class Any>
struct parameter_traits_<void, Any> {
typedef void type;
};
template<class Arg, class Any>
struct parameter_traits_<lambda_functor<Arg>, Any > {
typedef lambda_functor<Arg> type;
};
template<class Arg, class Any>
struct parameter_traits_<const lambda_functor<Arg>, Any > {
typedef lambda_functor<Arg> type;
};
// Are the volatile versions needed?
template<class Arg, class Any>
struct parameter_traits_<volatile lambda_functor<Arg>, Any > {
typedef lambda_functor<Arg> type;
};
template<class Arg, class Any>
struct parameter_traits_<const volatile lambda_functor<Arg>, Any > {
typedef lambda_functor<Arg> type;
};
} // end namespace detail
@@ -272,32 +252,15 @@ template<class T, int n> struct const_copy_argument <volatile T[n]> {
};
template<class T>
struct const_copy_argument<T&> {};
// do not instantiate with references
// typedef typename detail::generate_error<T&>::references_not_allowed type;
struct const_copy_argument<T&> {
typedef typename detail::generate_error<T&>::references_not_allowed type;
};
template<>
struct const_copy_argument<void> {
typedef void type;
};
template<>
struct const_copy_argument<void const> {
typedef void type;
};
// Does the same as const_copy_argument, but passes references through as such
template<class T>
struct bound_argument_conversion {
typedef typename const_copy_argument<T>::type type;
};
template<class T>
struct bound_argument_conversion<T&> {
typedef T& type;
};
// The default is non-const reference -------------------------
// const T -> const T&,
@@ -436,56 +399,6 @@ struct bind_traits<const volatile T[n]> {
typedef const volatile T (&type)[n];
};
template<class R>
struct bind_traits<R()> {
typedef R(&type)();
};
template<class R, class Arg1>
struct bind_traits<R(Arg1)> {
typedef R(&type)(Arg1);
};
template<class R, class Arg1, class Arg2>
struct bind_traits<R(Arg1, Arg2)> {
typedef R(&type)(Arg1, Arg2);
};
template<class R, class Arg1, class Arg2, class Arg3>
struct bind_traits<R(Arg1, Arg2, Arg3)> {
typedef R(&type)(Arg1, Arg2, Arg3);
};
template<class R, class Arg1, class Arg2, class Arg3, class Arg4>
struct bind_traits<R(Arg1, Arg2, Arg3, Arg4)> {
typedef R(&type)(Arg1, Arg2, Arg3, Arg4);
};
template<class R, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5>
struct bind_traits<R(Arg1, Arg2, Arg3, Arg4, Arg5)> {
typedef R(&type)(Arg1, Arg2, Arg3, Arg4, Arg5);
};
template<class R, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6>
struct bind_traits<R(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)> {
typedef R(&type)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6);
};
template<class R, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6, class Arg7>
struct bind_traits<R(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7)> {
typedef R(&type)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7);
};
template<class R, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6, class Arg7, class Arg8>
struct bind_traits<R(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8)> {
typedef R(&type)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8);
};
template<class R, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6, class Arg7, class Arg8, class Arg9>
struct bind_traits<R(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9)> {
typedef R(&type)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9);
};
template<class T>
struct bind_traits<reference_wrapper<T> >{
typedef T& type;
@@ -560,9 +473,10 @@ class bind_type_generator {
public:
typedef
lambda_functor<
lambda_functor_base<
lambda_functor_args<
action_type,
args_t
args_t,
combine_arities<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>::value
>
> type;
@@ -580,4 +494,4 @@ template <class T> inline const T& make_const(const T& t) { return t; }
#endif // BOOST_LAMBDA_TRAITS_HPP
#endif // BOOST_LAMBDA_TRAITS_HPP

View File

@@ -0,0 +1,117 @@
// -- Boost Lambda Library -- exceptions.hpp ----------------
//
// Copyright (C) 2000 Gary Powell (gwpowell@hotmail.com)
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
//
// 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
// -----------------------------------------------------
// make_void( x ) turns a lambda functor x with some return type y into
// another lambda functor, which has a void return type
// when called, the original return type is discarded
#if !defined(BOOST_LAMBDA_MAKE_VOID_HPP)
#define BOOST_LAMBDA_MAKE_VOID_HPP
namespace boost {
namespace lambda {
template<> struct return_void_action<other_action<identity_action> > {
template<class RET, class A>
static RET apply(A& a) {}
};
template<class Arg1>
inline const
lambda_functor<
lambda_functor_args<
action<1, return_void_action<other_action<identity_action> > >,
tuple<lambda_functor<Arg1> >,
combine_arities<Arg1>::value
>
>
make_void(const lambda_functor<Arg1>& a1) {
return
lambda_functor<
lambda_functor_args<
action<1, return_void_action<other_action<identity_action> > >,
tuple<lambda_functor<Arg1> >,
combine_arities<Arg1>::value
>
>
(tuple<lambda_functor<Arg1> > (a1));
}
// if its already returning void don't add another layer.
template <class ActionType, class Args, int Code>
inline const lambda_functor<lambda_functor_args<action<1, return_void_action<ActionType> >,
Args, Code > >
make_void(const lambda_functor<lambda_functor_args<action<1, return_void_action<ActionType> >,
Args, Code > >& a1) {
return lambda_functor<lambda_functor_args<action<1, return_void_action<ActionType> >,
Args, Code > >
(a1);
}
template <class ActionType, class Args, int Code>
inline const lambda_functor<lambda_functor_args<action<2, return_void_action<ActionType> >,
Args,
Code > >
make_void(const lambda_functor<lambda_functor_args<action<2, return_void_action<ActionType> >,
Args,
Code > >& a1) {
return lambda_functor<lambda_functor_args<action<2, return_void_action<ActionType> >,
Args,
Code > >
(a1);
}
template <class ActionType, class Args, int Code>
inline const lambda_functor<lambda_functor_args<action<3, return_void_action<ActionType> >,
Args, Code > >
make_void(const lambda_functor<lambda_functor_args<action<3, return_void_action<ActionType> >,
Args, Code > >& a1) {
return lambda_functor<lambda_functor_args<action<3, return_void_action<ActionType> >,
Args, Code > >
(a1);
}
template <class ActionType, int N, class Args, int Code>
inline const lambda_functor<lambda_functor_args<action<N, return_void_action<ActionType> >,
Args, Code > >
make_void(const lambda_functor<lambda_functor_args<action<N, return_void_action<ActionType> >,
Args, Code > >& a1) {
return lambda_functor<lambda_functor_args<action<N, return_void_action<ActionType> >,
Args, Code > >
(a1);
}
} // namespace lambda
} // namespace boost
#endif

View File

@@ -1,11 +1,16 @@
// Boost Lambda Library -- member_ptr.hpp ---------------------
// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2000 Gary Powell (gary.powell@sierra.com)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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 of its suitability for any purpose.
//
// For more information, see www.boost.org
@@ -17,10 +22,6 @@
namespace boost {
namespace lambda {
class member_pointer_action {};
namespace detail {
// the boost type_traits member_pointer traits are not enough,
@@ -431,10 +432,10 @@ namespace detail {
template<class RET, class A, class B>
class member_pointer_caller {
A a; B b;
A a;
B b;
public:
member_pointer_caller(const A& aa, const B& bb) : a(aa), b(bb) {}
member_pointer_caller(A aa, B bb) : a(aa), b(bb) {}
RET operator()() const { return (a->*b)(); }
@@ -506,7 +507,6 @@ struct member_pointer_action_helper;
template <>
struct member_pointer_action_helper<true, false> {
public:
template<class RET, class A, class B>
static RET apply(A& a, B& b) {
return a->*b;
@@ -514,22 +514,14 @@ public:
template<class A, class B>
struct return_type {
private:
typedef typename detail::remove_reference_and_cv<B>::type plainB;
typedef typename detail::member_pointer<plainB>::type type0;
// we remove the reference now, as we may have to add cv:s
typedef typename boost::remove_reference<type0>::type type1;
typedef typename detail::member_pointer<plainB>::type type1;
// A is a reference to pointer
// remove the top level cv qualifiers and reference
typedef typename
detail::remove_reference_and_cv<A>::type non_ref_A;
// A is a pointer type
typedef typename ::boost::remove_pointer<A>::type non_pointer_A;
// A is a pointer type, so take the type pointed to
typedef typename ::boost::remove_pointer<non_ref_A>::type non_pointer_A;
public:
// For non-reference types, we must add const and/or volatile if
// the pointer type has these qualifiers
// If the member is a reference, these do not have any effect
@@ -544,7 +536,6 @@ public:
typename ::boost::add_volatile<type2>::type,
type2
>::RET type3;
// add reference back
typedef typename ::boost::add_reference<type3>::type type;
};
};
@@ -560,14 +551,9 @@ public:
}
// an overloaded member pointer operators, user should have specified
// the return type
// At this point we know that there is no matching specialization for
// return_type_2, so try return_type_2_plain
template<class A, class B>
struct return_type {
typedef typename plain_return_type_2<
other_action<member_pointer_action>, A, B
>::type type;
typedef detail::unspecified type;
};
};
@@ -584,37 +570,35 @@ struct member_pointer_action_helper<false, true> {
template<class RET, class A, class B>
static RET apply(A& a, B& b) {
typedef typename ::boost::remove_cv<B>::type plainB;
typedef typename detail::member_pointer<plainB>::type ret_t;
typedef typename ::boost::remove_cv<A>::type plainA;
// we always strip cv:s to
// make the two routes (calling and type deduction)
// to give the same results (and the const does not make any functional
// difference)
return detail::member_pointer_caller<ret_t, plainA, plainB>(a, b);
return detail::member_pointer_caller<ret_t, A&, B&>(a, b);
}
template<class A, class B>
struct return_type {
typedef typename detail::remove_reference_and_cv<B>::type plainB;
typedef typename detail::member_pointer<plainB>::type ret_t;
typedef typename detail::remove_reference_and_cv<A>::type plainA;
typedef detail::member_pointer_caller<ret_t, plainA, plainB> type;
typedef detail::member_pointer_caller<ret_t, A, B> type;
};
};
} // detail
class member_pointer_action {};
template<> class other_action<member_pointer_action> {
public:
template<class RET, class A, class B>
static RET apply(A& a, B& b) {
typedef typename
::boost::remove_cv<B>::type plainB;
return detail::member_pointer_action_helper<
return
detail::member_pointer_action_helper<
boost::is_pointer<A>::value &&
detail::member_pointer<plainB>::is_data_member,
boost::is_pointer<A>::value &&
@@ -638,13 +622,14 @@ public:
// In such a case either ret<> must be used, or a return_type_2 user
// defined specialization must be provided
template<class A, class B>
struct return_type_2<other_action<member_pointer_action>, A, B> {
private:
typedef typename
detail::remove_reference_and_cv<B>::type plainB;
public:
typedef typename
detail::member_pointer<plainB>::qualified_class_type B_class;
typedef typename
detail::member_pointer_action_helper<
detail::member_pointer<plainB>::is_data_member,
@@ -652,74 +637,69 @@ public:
>::template return_type<A, B>::type type;
};
// this is the way the generic lambda_functor_base functions instantiate
// return type deduction. We turn it into return_type_2, so that the
// user can provide specializations on that level.
template<class Args>
struct return_type_N<other_action<member_pointer_action>, Args> {
typedef typename boost::tuples::element<0, Args>::type A;
typedef typename boost::tuples::element<1, Args>::type B;
typedef typename
return_type_2<other_action<member_pointer_action>,
typename boost::remove_reference<A>::type,
typename boost::remove_reference<B>::type
>::type type;
};
template<class Arg1, class Arg2>
inline const
lambda_functor<
lambda_functor_base<
lambda_functor_args<
action<2, other_action<member_pointer_action> >,
tuple<lambda_functor<Arg1>, typename const_copy_argument<Arg2>::type>
tuple<lambda_functor<Arg1>, typename const_copy_argument<Arg2>::type>,
combine_arities<Arg1, Arg2>::value
>
>
operator->*(const lambda_functor<Arg1>& a1, const Arg2& a2)
{
return
lambda_functor_base<
lambda_functor<
lambda_functor_args<
action<2, other_action<member_pointer_action> >,
tuple<lambda_functor<Arg1>, typename const_copy_argument<Arg2>::type>
tuple<lambda_functor<Arg1>, typename const_copy_argument<Arg2>::type>,
combine_arities<Arg1, Arg2>::value
>
(tuple<lambda_functor<Arg1>,
> (tuple<lambda_functor<Arg1>,
typename const_copy_argument<Arg2>::type>(a1, a2));
}
template<class Arg1, class Arg2>
inline const
lambda_functor<
lambda_functor_base<
lambda_functor_args<
action<2, other_action<member_pointer_action> >,
tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >
tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >,
combine_arities<Arg1, Arg2>::value
>
>
operator->*(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2)
{
return
lambda_functor_base<
lambda_functor<
lambda_functor_args<
action<2, other_action<member_pointer_action> >,
tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >
tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >,
combine_arities<Arg1, Arg2>::value
>
(tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >(a1, a2));
> (tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >(a1, a2));
}
template<class Arg1, class Arg2>
inline const
lambda_functor<
lambda_functor_base<
lambda_functor_args<
action<2, other_action<member_pointer_action> >,
tuple<typename const_copy_argument<Arg1>::type, lambda_functor<Arg2> >
tuple<typename const_copy_argument<Arg1>::type, lambda_functor<Arg2> >,
combine_arities<Arg1, Arg2>::value
>
>
operator->*(const Arg1& a1, const lambda_functor<Arg2>& a2)
{
return
lambda_functor_base<
lambda_functor<
lambda_functor_args<
action<2, other_action<member_pointer_action> >,
tuple<typename const_copy_argument<Arg1>::type, lambda_functor<Arg2> >
tuple<typename const_copy_argument<Arg1>::type, lambda_functor<Arg2> >,
combine_arities<Arg1, Arg2>::value
>
(tuple<typename const_copy_argument<Arg1>::type,
> (tuple<typename const_copy_argument<Arg1>::type,
lambda_functor<Arg2> >(a1, a2));
}

View File

@@ -1,10 +1,15 @@
// -- operator_actions.hpp - Boost Lambda Library ----------------------
// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
//
// 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)
// 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://lambda.cs.utu.fi
@@ -52,6 +57,8 @@ class decrement_action {};
// -- void return ------------------------------
class do_nothing_action {};
// -- other ------------------------------
class addressof_action {};
@@ -73,67 +80,122 @@ template <class Action> class pre_increment_decrement_action;
template <class Action> class post_increment_decrement_action;
// ---------------------------------------------------------
#if defined BOOST_LAMBDA_BINARY_ACTION
#error "Multiple defines of BOOST_LAMBDA_BINARY_ACTION"
#endif
// actions, for which the existence of protect is checked in return type
// deduction.
#define BOOST_LAMBDA_BINARY_ACTION(OPER_SYMBOL, GROUP, OPER_NAME) \
template<> class GROUP < OPER_NAME> : public protectable {\
public: \
template<class RET, class A, class B>\
static RET apply(A& a, B& b) { \
return a OPER_SYMBOL b; }\
};\
\
template <class Act> struct is_protectable<arithmetic_action<Act> > {
BOOST_STATIC_CONSTANT(bool, value = true);
};
template <class Act> struct is_protectable<bitwise_action<Act> > {
BOOST_STATIC_CONSTANT(bool, value = true);
};
template <class Act> struct is_protectable<logical_action<Act> > {
BOOST_STATIC_CONSTANT(bool, value = true);
};
template <class Act> struct is_protectable<relational_action<Act> > {
BOOST_STATIC_CONSTANT(bool, value = true);
};
template <class Act>
struct is_protectable<arithmetic_assignment_action<Act> > {
BOOST_STATIC_CONSTANT(bool, value = true);
};
template <class Act> struct is_protectable<bitwise_assignment_action<Act> > {
BOOST_STATIC_CONSTANT(bool, value = true);
};
template <class Act> struct is_protectable<unary_arithmetic_action<Act> > {
BOOST_STATIC_CONSTANT(bool, value = true);
};
template <class Act>
struct is_protectable<pre_increment_decrement_action<Act> > {
BOOST_STATIC_CONSTANT(bool, value = true);
};
template <class Act> struct
is_protectable<post_increment_decrement_action<Act> > {
BOOST_STATIC_CONSTANT(bool, value = true);
BOOST_LAMBDA_BINARY_ACTION(+,arithmetic_action,plus_action)
BOOST_LAMBDA_BINARY_ACTION(-,arithmetic_action,minus_action)
BOOST_LAMBDA_BINARY_ACTION(*,arithmetic_action,multiply_action)
BOOST_LAMBDA_BINARY_ACTION(/,arithmetic_action,divide_action)
BOOST_LAMBDA_BINARY_ACTION(%,arithmetic_action,remainder_action)
BOOST_LAMBDA_BINARY_ACTION(<<,bitwise_action,leftshift_action)
BOOST_LAMBDA_BINARY_ACTION(>>,bitwise_action,rightshift_action)
BOOST_LAMBDA_BINARY_ACTION(&,bitwise_action,and_action)
BOOST_LAMBDA_BINARY_ACTION(|,bitwise_action,or_action)
BOOST_LAMBDA_BINARY_ACTION(^,bitwise_action,xor_action)
BOOST_LAMBDA_BINARY_ACTION(<,relational_action,less_action)
BOOST_LAMBDA_BINARY_ACTION(>,relational_action,greater_action)
BOOST_LAMBDA_BINARY_ACTION(<=,relational_action,lessorequal_action)
BOOST_LAMBDA_BINARY_ACTION(>=,relational_action,greaterorequal_action)
BOOST_LAMBDA_BINARY_ACTION(==,relational_action,equal_action)
BOOST_LAMBDA_BINARY_ACTION(!=,relational_action,notequal_action)
BOOST_LAMBDA_BINARY_ACTION(+=,arithmetic_assignment_action,plus_action)
BOOST_LAMBDA_BINARY_ACTION(-=,arithmetic_assignment_action,minus_action)
BOOST_LAMBDA_BINARY_ACTION(*=,arithmetic_assignment_action,multiply_action)
BOOST_LAMBDA_BINARY_ACTION(/=,arithmetic_assignment_action,divide_action)
BOOST_LAMBDA_BINARY_ACTION(%=,arithmetic_assignment_action,remainder_action)
BOOST_LAMBDA_BINARY_ACTION(<<=,bitwise_assignment_action,leftshift_action)
BOOST_LAMBDA_BINARY_ACTION(>>=,bitwise_assignment_action,rightshift_action)
BOOST_LAMBDA_BINARY_ACTION(&=,bitwise_assignment_action,and_action)
BOOST_LAMBDA_BINARY_ACTION(|=,bitwise_assignment_action,or_action)
BOOST_LAMBDA_BINARY_ACTION(^=,bitwise_assignment_action,xor_action)
// && and || are defined directly in specializations for lambda_functor_base
// to achieve short circuiting
// Still we define some empty action classes for them, as they are instantiated:
template<> class logical_action<or_action> : public protectable {};
template<> class logical_action<and_action> : public protectable {};
BOOST_LAMBDA_BINARY_ACTION(=,other_action, assignment_action)
// subscript is done directly because BOOST_LAMBDA_BINARY_ACTION currently doesn't handle it.
template<> class other_action<subscript_action> : public protectable {
public:
template<class RET, class A, class B>
static RET apply(A& a, B& b) { return a[b]; }
};
template <> struct is_protectable<other_action<addressof_action> > {
BOOST_STATIC_CONSTANT(bool, value = true);
};
template <> struct is_protectable<other_action<contentsof_action> > {
BOOST_STATIC_CONSTANT(bool, value = true);
// do_nothing_action is also specified directly for the same reason.
template<> class return_void_action<do_nothing_action> {
public:
template<class RET>
static RET apply() {}
};
template<> struct is_protectable<other_action<subscript_action> > {
BOOST_STATIC_CONSTANT(bool, value = true);
};
template<> struct is_protectable<other_action<assignment_action> > {
BOOST_STATIC_CONSTANT(bool, value = true);
};
// comma_action removed, a specialisation is provided to lambda_functor_base
// This is to handle void arguments (built-in comma operator can take void
// arguments whereas a user-defined function can't) (JJ)
// NOTE: comma action is also protectable, but the specialization is
// in actions.hpp
#if defined BOOST_LAMBDA_PREFIX_UNARY_ACTION
#error "Multiple defines of BOOST_LAMBDA_PREFIX_UNARY_ACTION"
#endif
#define BOOST_LAMBDA_PREFIX_UNARY_ACTION(OPER_SYMBOL, GROUP, OPER_NAME) \
template<> class GROUP <OPER_NAME> : public protectable {\
public: \
template<class RET, class A>\
static RET apply(A& a) { return OPER_SYMBOL a; }\
};\
\
BOOST_LAMBDA_PREFIX_UNARY_ACTION(+, unary_arithmetic_action,plus_action)
BOOST_LAMBDA_PREFIX_UNARY_ACTION(-, unary_arithmetic_action,minus_action)
BOOST_LAMBDA_PREFIX_UNARY_ACTION(~, bitwise_action,not_action)
BOOST_LAMBDA_PREFIX_UNARY_ACTION(!, logical_action,not_action)
BOOST_LAMBDA_PREFIX_UNARY_ACTION(++, pre_increment_decrement_action,increment_action)
BOOST_LAMBDA_PREFIX_UNARY_ACTION(--, pre_increment_decrement_action,decrement_action)
BOOST_LAMBDA_PREFIX_UNARY_ACTION(&,other_action, addressof_action)
BOOST_LAMBDA_PREFIX_UNARY_ACTION(*,other_action, contentsof_action)
BOOST_LAMBDA_PREFIX_UNARY_ACTION( , other_action, identity_action)
#if defined BOOST_LAMBDA_POSTFIX_UNARY_ACTION
#error "Multiple defines of BOOST_LAMBDA_POSTFIX_UNARY_ACTION"
#endif
#define BOOST_LAMBDA_POSTFIX_UNARY_ACTION(OPER_SYMBOL, GROUP, OPER_NAME) \
template<> class GROUP <OPER_NAME> : public protectable {\
public: \
template<class RET, class A>\
static RET apply(A& a) { return a OPER_SYMBOL; }\
};\
\
BOOST_LAMBDA_POSTFIX_UNARY_ACTION(++, post_increment_decrement_action,increment_action)
BOOST_LAMBDA_POSTFIX_UNARY_ACTION(--, post_increment_decrement_action,decrement_action)
#undef BOOST_LAMBDA_BINARY_ACTION
#undef BOOST_LAMBDA_PREFIX_UNARY_ACTION
#undef BOOST_LAMBDA_POSTFIX_UNARY_ACTION
} // namespace lambda
} // namespace boost
#endif

View File

@@ -1,271 +0,0 @@
// Boost Lambda Library - operator_lambda_func_base.hpp -----------------
//
// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see www.boost.org
// ------------------------------------------------------------
#ifndef BOOST_LAMBDA_OPERATOR_LAMBDA_FUNC_BASE_HPP
#define BOOST_LAMBDA_OPERATOR_LAMBDA_FUNC_BASE_HPP
namespace boost {
namespace lambda {
// These operators cannot be implemented as apply functions of action
// templates
// Specialization for comma.
template<class Args>
class lambda_functor_base<other_action<comma_action>, Args> {
public:
Args args;
public:
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET, CALL_TEMPLATE_ARGS>
RET call(CALL_FORMAL_ARGS) const {
return detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS),
detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS);
}
template<class SigArgs> struct sig {
private:
typedef typename
detail::deduce_argument_types<Args, SigArgs>::type rets_t;
public:
typedef typename return_type_2_comma< // comma needs special handling
typename detail::element_or_null<0, rets_t>::type,
typename detail::element_or_null<1, rets_t>::type
>::type type;
};
};
namespace detail {
// helper traits to make the expression shorter, takes binary action
// bound argument tuple, open argument tuple and gives the return type
template<class Action, class Bound, class Open> class binary_rt {
private:
typedef typename
detail::deduce_argument_types<Bound, Open>::type rets_t;
public:
typedef typename return_type_2_prot<
Action,
typename detail::element_or_null<0, rets_t>::type,
typename detail::element_or_null<1, rets_t>::type
>::type type;
};
// same for unary actions
template<class Action, class Bound, class Open> class unary_rt {
private:
typedef typename
detail::deduce_argument_types<Bound, Open>::type rets_t;
public:
typedef typename return_type_1_prot<
Action,
typename detail::element_or_null<0, rets_t>::type
>::type type;
};
} // end detail
// Specialization for logical and (to preserve shortcircuiting)
// this could be done with a macro as the others, code used to be different
template<class Args>
class lambda_functor_base<logical_action<and_action>, Args> {
public:
Args args;
public:
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET, CALL_TEMPLATE_ARGS>
RET call(CALL_FORMAL_ARGS) const {
return detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS) &&
detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS);
}
template<class SigArgs> struct sig {
typedef typename
detail::binary_rt<logical_action<and_action>, Args, SigArgs>::type type;
};
};
// Specialization for logical or (to preserve shortcircuiting)
// this could be done with a macro as the others, code used to be different
template<class Args>
class lambda_functor_base<logical_action< or_action>, Args> {
public:
Args args;
public:
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET, CALL_TEMPLATE_ARGS>
RET call(CALL_FORMAL_ARGS) const {
return detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS) ||
detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS);
}
template<class SigArgs> struct sig {
typedef typename
detail::binary_rt<logical_action<or_action>, Args, SigArgs>::type type;
};
};
// Specialization for subscript
template<class Args>
class lambda_functor_base<other_action<subscript_action>, Args> {
public:
Args args;
public:
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET, CALL_TEMPLATE_ARGS>
RET call(CALL_FORMAL_ARGS) const {
return detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS)
[detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS)];
}
template<class SigArgs> struct sig {
typedef typename
detail::binary_rt<other_action<subscript_action>, Args, SigArgs>::type
type;
};
};
#define BOOST_LAMBDA_BINARY_ACTION(SYMBOL, ACTION_CLASS) \
template<class Args> \
class lambda_functor_base<ACTION_CLASS, Args> { \
public: \
Args args; \
public: \
explicit lambda_functor_base(const Args& a) : args(a) {} \
\
template<class RET, CALL_TEMPLATE_ARGS> \
RET call(CALL_FORMAL_ARGS) const { \
return detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS) \
SYMBOL \
detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS); \
} \
template<class SigArgs> struct sig { \
typedef typename \
detail::binary_rt<ACTION_CLASS, Args, SigArgs>::type type; \
}; \
};
#define BOOST_LAMBDA_PREFIX_UNARY_ACTION(SYMBOL, ACTION_CLASS) \
template<class Args> \
class lambda_functor_base<ACTION_CLASS, Args> { \
public: \
Args args; \
public: \
explicit lambda_functor_base(const Args& a) : args(a) {} \
\
template<class RET, CALL_TEMPLATE_ARGS> \
RET call(CALL_FORMAL_ARGS) const { \
return SYMBOL \
detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS); \
} \
template<class SigArgs> struct sig { \
typedef typename \
detail::unary_rt<ACTION_CLASS, Args, SigArgs>::type type; \
}; \
};
#define BOOST_LAMBDA_POSTFIX_UNARY_ACTION(SYMBOL, ACTION_CLASS) \
template<class Args> \
class lambda_functor_base<ACTION_CLASS, Args> { \
public: \
Args args; \
public: \
explicit lambda_functor_base(const Args& a) : args(a) {} \
\
template<class RET, CALL_TEMPLATE_ARGS> \
RET call(CALL_FORMAL_ARGS) const { \
return \
detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS) SYMBOL; \
} \
template<class SigArgs> struct sig { \
typedef typename \
detail::unary_rt<ACTION_CLASS, Args, SigArgs>::type type; \
}; \
};
BOOST_LAMBDA_BINARY_ACTION(+,arithmetic_action<plus_action>)
BOOST_LAMBDA_BINARY_ACTION(-,arithmetic_action<minus_action>)
BOOST_LAMBDA_BINARY_ACTION(*,arithmetic_action<multiply_action>)
BOOST_LAMBDA_BINARY_ACTION(/,arithmetic_action<divide_action>)
BOOST_LAMBDA_BINARY_ACTION(%,arithmetic_action<remainder_action>)
BOOST_LAMBDA_BINARY_ACTION(<<,bitwise_action<leftshift_action>)
BOOST_LAMBDA_BINARY_ACTION(>>,bitwise_action<rightshift_action>)
BOOST_LAMBDA_BINARY_ACTION(&,bitwise_action<and_action>)
BOOST_LAMBDA_BINARY_ACTION(|,bitwise_action<or_action>)
BOOST_LAMBDA_BINARY_ACTION(^,bitwise_action<xor_action>)
BOOST_LAMBDA_BINARY_ACTION(<,relational_action<less_action>)
BOOST_LAMBDA_BINARY_ACTION(>,relational_action<greater_action>)
BOOST_LAMBDA_BINARY_ACTION(<=,relational_action<lessorequal_action>)
BOOST_LAMBDA_BINARY_ACTION(>=,relational_action<greaterorequal_action>)
BOOST_LAMBDA_BINARY_ACTION(==,relational_action<equal_action>)
BOOST_LAMBDA_BINARY_ACTION(!=,relational_action<notequal_action>)
BOOST_LAMBDA_BINARY_ACTION(+=,arithmetic_assignment_action<plus_action>)
BOOST_LAMBDA_BINARY_ACTION(-=,arithmetic_assignment_action<minus_action>)
BOOST_LAMBDA_BINARY_ACTION(*=,arithmetic_assignment_action<multiply_action>)
BOOST_LAMBDA_BINARY_ACTION(/=,arithmetic_assignment_action<divide_action>)
BOOST_LAMBDA_BINARY_ACTION(%=,arithmetic_assignment_action<remainder_action>)
BOOST_LAMBDA_BINARY_ACTION(<<=,bitwise_assignment_action<leftshift_action>)
BOOST_LAMBDA_BINARY_ACTION(>>=,bitwise_assignment_action<rightshift_action>)
BOOST_LAMBDA_BINARY_ACTION(&=,bitwise_assignment_action<and_action>)
BOOST_LAMBDA_BINARY_ACTION(|=,bitwise_assignment_action<or_action>)
BOOST_LAMBDA_BINARY_ACTION(^=,bitwise_assignment_action<xor_action>)
BOOST_LAMBDA_BINARY_ACTION(=,other_action< assignment_action>)
BOOST_LAMBDA_PREFIX_UNARY_ACTION(+, unary_arithmetic_action<plus_action>)
BOOST_LAMBDA_PREFIX_UNARY_ACTION(-, unary_arithmetic_action<minus_action>)
BOOST_LAMBDA_PREFIX_UNARY_ACTION(~, bitwise_action<not_action>)
BOOST_LAMBDA_PREFIX_UNARY_ACTION(!, logical_action<not_action>)
BOOST_LAMBDA_PREFIX_UNARY_ACTION(++, pre_increment_decrement_action<increment_action>)
BOOST_LAMBDA_PREFIX_UNARY_ACTION(--, pre_increment_decrement_action<decrement_action>)
BOOST_LAMBDA_PREFIX_UNARY_ACTION(&,other_action<addressof_action>)
BOOST_LAMBDA_PREFIX_UNARY_ACTION(*,other_action<contentsof_action>)
BOOST_LAMBDA_POSTFIX_UNARY_ACTION(++, post_increment_decrement_action<increment_action>)
BOOST_LAMBDA_POSTFIX_UNARY_ACTION(--, post_increment_decrement_action<decrement_action>)
#undef BOOST_LAMBDA_POSTFIX_UNARY_ACTION
#undef BOOST_LAMBDA_PREFIX_UNARY_ACTION
#undef BOOST_LAMBDA_BINARY_ACTION
} // namespace lambda
} // namespace boost
#endif

View File

@@ -0,0 +1,77 @@
// Boost Lambda Library - operator_lambda_functor_base.hpp -----------------
//
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
//
// 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 www.boost.org
// ------------------------------------------------------------
#ifndef BOOST_LAMBDA_OPERATOR_LAMBDA_FUNCTOR_BASE_HPP
#define BOOST_LAMBDA_OPERATOR_LAMBDA_FUNCTOR_BASE_HPP
namespace boost {
namespace lambda {
// These operators cannot be implemented as apply functions of action
// templates
// Specialization for comma.
template<class Args>
class lambda_functor_base<action<2, other_action<comma_action> >, Args> {
public:
Args args;
public:
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET, class A, class B, class C>
RET call(A& a, B& b, C& c) const {
return detail::select(boost::tuples::get<0>(args), a, b, c),
detail::select(boost::tuples::get<1>(args), a, b, c);
}
};
// Specialization for logical and (to preserve shortcircuiting)
template<class Args>
class lambda_functor_base<action<2, logical_action<and_action> >, Args> {
public:
Args args;
public:
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET, class A, class B, class C>
RET call(A& a, B& b, C& c) const {
return detail::select(boost::tuples::get<0>(args), a, b, c) &&
detail::select(boost::tuples::get<1>(args), a, b, c);
}
};
// Specialization for logical or (to preserve shortcircuiting)
template<class Args>
class lambda_functor_base<action<2, logical_action< or_action> >, Args> {
public:
Args args;
public:
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET, class A, class B, class C>
RET call(A& a, B& b, C& c) const {
return detail::select(boost::tuples::get<0>(args), a, b, c) ||
detail::select(boost::tuples::get<1>(args), a, b, c);
}
};
} // namespace lambda
} // namespace boost
#endif

View File

@@ -1,10 +1,15 @@
// operator_return_type_traits.hpp -- Boost Lambda Library ------------------
// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
//
// 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)
// 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 www.boost.org
@@ -12,16 +17,7 @@
#define BOOST_LAMBDA_OPERATOR_RETURN_TYPE_TRAITS_HPP
#include "boost/lambda/detail/is_instance_of.hpp"
#include "boost/type_traits/is_same.hpp"
#include "boost/type_traits/is_pointer.hpp"
#include "boost/type_traits/is_float.hpp"
#include "boost/type_traits/is_convertible.hpp"
#include "boost/type_traits/remove_pointer.hpp"
#include "boost/type_traits/remove_const.hpp"
#include "boost/type_traits/remove_reference.hpp"
#include "boost/indirect_reference.hpp"
#include "boost/detail/container_fwd.hpp"
#include "boost/type_traits/same_traits.hpp"
#include <cstddef> // needed for the ptrdiff_t
#include <iosfwd> // for istream and ostream
@@ -65,6 +61,10 @@ template <> struct promote_code<long double> { static const int value = 700; };
} // namespace lambda
} // namespace boost
namespace std {
template<class T> class complex;
}
namespace boost {
namespace lambda {
namespace detail {
@@ -87,11 +87,11 @@ template <> struct promote_to_int<short int> { typedef int type; };
// of unsigned short int, otherwise go to unsigned int.
template <> struct promote_to_int<unsigned short int>
{
typedef
detail::IF<sizeof(int) <= sizeof(unsigned short int),
typedef
detail::IF<sizeof(int) <= sizeof(unsigned short int),
// I had the logic reversed but ">" messes up the parsing.
unsigned int,
int>::RET type;
unsigned int,
int>::RET type;
};
@@ -139,9 +139,14 @@ template<class A> struct return_type_1<bitwise_action<not_action>, A> {
>::type type;
};
// identity_action
template<class A> struct return_type_1<other_action<identity_action>, A> {
typedef A type;
};
// prefix increment and decrement operators return
// their argument by default as a non-const reference
// prefix increment and decrement operators return the default is
// a non-const reference
template<class Act, class A>
struct plain_return_type_1<pre_increment_decrement_action<Act>, A> {
typedef A& type;
@@ -221,25 +226,38 @@ namespace detail {
// A is a nonreference type
template <class A> struct contentsof_type {
typedef typename boost::indirect_reference<A>::type type;
typedef typename std::iterator_traits<A>::reference type;
};
// this is since the nullary () in lambda_functor is always instantiated
template <> struct contentsof_type<null_type> {
typedef detail::unspecified type;
};
template <class A> struct contentsof_type<const A> {
typedef typename contentsof_type<A>::type type;
typedef typename contentsof_type<A>::type type1;
// return a reference to the underlying const type
// the IF is because the A::reference in the primary template could
// be some class type rather than a real reference, hence
// we do not want to make it a reference here either
typedef typename detail::IF<
is_reference<type1>::value,
const typename boost::remove_reference<type1>::type &,
const type1
>::RET type;
};
template <class A> struct contentsof_type<volatile A> {
typedef typename contentsof_type<A>::type type;
typedef typename contentsof_type<A>::type type1;
typedef typename detail::IF<
is_reference<type1>::value,
volatile typename boost::remove_reference<type1>::type &,
volatile type1
>::RET type;
};
template <class A> struct contentsof_type<const volatile A> {
typedef typename contentsof_type<A>::type type;
typedef typename contentsof_type<A>::type type1;
typedef typename detail::IF<
is_reference<type1>::value,
const volatile typename boost::remove_reference<type1>::type &,
const volatile type1
>::RET type;
};
// standard iterator traits should take care of the pointer types
@@ -279,7 +297,6 @@ template<class A, int N> struct contentsof_type<const volatile A[N]> {
template<class A>
struct return_type_1<other_action<contentsof_action>, A> {
typedef
typename plain_return_type_1<
other_action<contentsof_action>,
@@ -294,7 +311,10 @@ struct return_type_1<other_action<contentsof_action>, A> {
detail::contentsof_type<
typename boost::remove_reference<A>::type
>,
detail::identity_mapping<type1>
plain_return_type_1<
other_action<contentsof_action>,
typename detail::remove_reference_and_cv<A>::type
>
>::type type;
};
@@ -471,21 +491,22 @@ struct return_type_2_arithmetic_phase_2 {
// struct so I don't have to type this twice.
struct promotion_of_unsigned_int
{
typedef
detail::IF<sizeof(long) <= sizeof(unsigned int),
unsigned long,
long>::RET type;
typedef
detail::IF<sizeof(long) <= sizeof(unsigned int),
// I had the logic reversed but ">" messes up the parsing.
unsigned long,
long>::RET type;
};
template<>
struct return_type_2_arithmetic_phase_2<unsigned int, long>
{
typedef promotion_of_unsigned_int::type type;
typedef promotion_of_unsigned_int::type type;
};
template<>
struct return_type_2_arithmetic_phase_2<long, unsigned int>
{
typedef promotion_of_unsigned_int::type type;
typedef promotion_of_unsigned_int::type type;
};
@@ -542,43 +563,46 @@ struct return_type_2<bitwise_action<Act>, A, B>
namespace detail {
template <class T> struct get_ostream_type {
typedef std::basic_ostream<typename T::char_type,
typename T::traits_type>& type;
};
template <class T> struct get_istream_type {
typedef std::basic_istream<typename T::char_type,
typename T::traits_type>& type;
};
template<class A, class B>
struct leftshift_type {
private:
typedef typename boost::remove_reference<A>::type plainA;
public:
typedef typename detail::IF_type<
is_instance_of_2<plainA, std::basic_ostream>::value,
get_ostream_type<plainA>, //reference to the stream
detail::remove_reference_and_cv<A>
>::type type;
typedef typename detail::IF<
#ifdef BOOST_NO_TEMPLATED_STREAMS
boost::is_convertible<
typename boost::remove_reference<A>::type*,
std::ostream*
>::value,
#else
is_instance_of_2<
typename boost::remove_reference<A>::type,
std::basic_ostream
>::value,
#endif
A, //reference to the stream
typename detail::remove_reference_and_cv<A>::type
>::RET type;
};
template<class A, class B>
struct rightshift_type {
private:
typedef typename boost::remove_reference<A>::type plainA;
public:
typedef typename detail::IF_type<
is_instance_of_2<plainA, std::basic_istream>::value,
get_istream_type<plainA>, //reference to the stream
detail::remove_reference_and_cv<A>
>::type type;
typedef typename detail::IF<
#ifdef BOOST_NO_TEMPLATED_STREAMS
boost::is_convertible<
typename boost::remove_reference<A>::type*,
std::istream*
>::value,
#else
is_instance_of_2<
typename boost::remove_reference<A>::type,
std::basic_istream
>::value,
#endif
A, //reference to the stream
typename detail::remove_reference_and_cv<A>::type
>::RET type;
};
} // end detail
// ostream
@@ -658,8 +682,8 @@ struct return_type_2<relational_action<Act>, A, B> {
};
// Assingment actions -----------------------------------------------
// return type is the type of the first argument as reference
// return type is the type of the first argument
// (note: other templates guarantee that it is a referece).
// note that cv-qualifiers are preserved.
// Yes, assignment operator can be const!
@@ -679,7 +703,7 @@ struct return_type_2<arithmetic_assignment_action<Act>, A, B> {
typedef typename
detail::IF<
boost::is_same<type1, detail::unspecified>::value,
typename boost::add_reference<A>::type,
A,
type1
>::RET type;
};
@@ -698,7 +722,7 @@ struct return_type_2<bitwise_assignment_action<Act>, A, B> {
typedef typename
detail::IF<
boost::is_same<type1, detail::unspecified>::value,
typename boost::add_reference<A>::type,
A,
type1
>::RET type;
};
@@ -716,7 +740,7 @@ struct return_type_2<other_action<assignment_action>, A, B> {
typedef typename
detail::IF<
boost::is_same<type1, detail::unspecified>::value,
typename boost::add_reference<A>::type,
A,
type1
>::RET type;
};
@@ -726,22 +750,26 @@ struct return_type_2<other_action<assignment_action>, A, B> {
// comma action ----------------------------------
// Note: this may not be true for some weird user-defined types,
// NOTE! This only tries the plain_return_type_2 layer and gives
// detail::unspecified as default. If no such specialization is found, the
// type rule in the spcecialization of the return_type_2_prot is used
// to give the type of the right argument (which can be a reference too)
// NOTE! A and B in comma_action can be non-reference types too!!!
// (The built in operator, can return a l- or rvalue).
template<class A, class B>
struct return_type_2<other_action<comma_action>, A, B> {
typedef typename detail::remove_reference_and_cv<A>::type plain_A;
typedef typename detail::remove_reference_and_cv<B>::type plain_B;
typedef typename
plain_return_type_2<
other_action<comma_action>, plain_A, plain_B
>::type type;
};
>::type type1;
typedef typename
detail::IF<
boost::is_same<type1, detail::unspecified>::value,
B,
type1
>::RET type;
};
// subscript action -----------------------------------------------
@@ -806,6 +834,23 @@ struct return_type_2<other_action<subscript_action>, A, B> {
};
} // namespace lambda
} // namespace boost
namespace std {
template <class Key, class T, class Cmp, class Allocator> class map;
template <class Key, class T, class Cmp, class Allocator> class multimap;
template <class T, class Allocator> class vector;
template <class T, class Allocator> class deque;
template <class Char, class Traits, class Allocator> class basic_string;
}
namespace boost {
namespace lambda {
template<class Key, class T, class Cmp, class Allocator, class B>
struct plain_return_type_2<other_action<subscript_action>, std::map<Key, T, Cmp, Allocator>, B> {
typedef T& type;
@@ -848,41 +893,6 @@ struct plain_return_type_2<other_action<subscript_action>, const std::basic_stri
typedef typename std::basic_string<Char, Traits, Allocator>::const_reference type;
};
template<class Char, class Traits, class Allocator>
struct plain_return_type_2<arithmetic_action<plus_action>,
std::basic_string<Char, Traits, Allocator>,
std::basic_string<Char, Traits, Allocator> > {
typedef std::basic_string<Char, Traits, Allocator> type;
};
template<class Char, class Traits, class Allocator>
struct plain_return_type_2<arithmetic_action<plus_action>,
const Char*,
std::basic_string<Char, Traits, Allocator> > {
typedef std::basic_string<Char, Traits, Allocator> type;
};
template<class Char, class Traits, class Allocator>
struct plain_return_type_2<arithmetic_action<plus_action>,
std::basic_string<Char, Traits, Allocator>,
const Char*> {
typedef std::basic_string<Char, Traits, Allocator> type;
};
template<class Char, class Traits, class Allocator, std::size_t N>
struct plain_return_type_2<arithmetic_action<plus_action>,
Char[N],
std::basic_string<Char, Traits, Allocator> > {
typedef std::basic_string<Char, Traits, Allocator> type;
};
template<class Char, class Traits, class Allocator, std::size_t N>
struct plain_return_type_2<arithmetic_action<plus_action>,
std::basic_string<Char, Traits, Allocator>,
Char[N]> {
typedef std::basic_string<Char, Traits, Allocator> type;
};
} // namespace lambda
} // namespace boost

View File

@@ -1,140 +1,131 @@
// Boost Lambda Library - operators.hpp --------------------------------------
// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
//
// 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)
// 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 www.boost.org
// ---------------------------------------------------------------
#ifndef BOOST_LAMBDA_OPERATORS_HPP
#define BOOST_LAMBDA_OPERATORS_HPP
#ifndef BOOST_LAMBDA_BINARY_EXPRESSIONS_HPP
#define BOOST_LAMBDA_BINARY_EXPRESSIONS_HPP
#include "boost/lambda/detail/is_instance_of.hpp"
namespace boost {
namespace lambda {
#if defined BOOST_LAMBDA_BE1
#error "Multiple defines of BOOST_LAMBDA_BE1"
#if defined BOOST_LAMBDA_BINARY_EXPRESSION1
#error "Multiple defines of BOOST_LAMBDA_BINARY_EXPRESSION1"
#endif
// For all BOOSTA_LAMBDA_BE* macros:
#define BOOST_LAMBDA_BINARY_EXPRESSION1(OPER_FUNC_NAME, OPER_NAME, CONSTA, CONSTB, CONST_CONVERSION) template<class Arg, class B> \
inline const lambda_functor<lambda_functor_args<action<2, OPER_NAME >, \
tuple<lambda_functor<Arg>, \
typename CONST_CONVERSION <CONSTB B>::type>,\
dig_arity<Arg>::value> >\
OPER_FUNC_NAME (const lambda_functor<Arg>& a, \
CONSTB B& b)\
{\
return lambda_functor<lambda_functor_args<action<2, OPER_NAME >, \
tuple<lambda_functor<Arg>, typename CONST_CONVERSION <CONSTB B>::type>, \
dig_arity<Arg>::value> >\
(\
tuple<lambda_functor<Arg>, typename CONST_CONVERSION <CONSTB B>::type>(a, b)\
);\
}\
\
// CONSTA must be either 'A' or 'const A'
// CONSTB must be either 'B' or 'const B'
// It is stupid to have the names A and B as macro arguments, but it avoids
// the need to pass in emtpy macro arguments, which gives warnings on some
// compilers
#define BOOST_LAMBDA_BE1(OPER_NAME, ACTION, CONSTA, CONSTB, CONVERSION) \
template<class Arg, class B> \
inline const \
lambda_functor< \
lambda_functor_base< \
ACTION, \
tuple<lambda_functor<Arg>, typename const_copy_argument <CONSTB>::type> \
> \
> \
OPER_NAME (const lambda_functor<Arg>& a, CONSTB& b) { \
return \
lambda_functor_base< \
ACTION, \
tuple<lambda_functor<Arg>, typename const_copy_argument <CONSTB>::type>\
> \
(tuple<lambda_functor<Arg>, typename const_copy_argument <CONSTB>::type>(a, b)); \
}
#if defined BOOST_LAMBDA_BE2
#error "Multiple defines of BOOST_LAMBDA_BE2"
#if defined BOOST_LAMBDA_BINARY_EXPRESSION2
#error "Multiple defines of BOOST_LAMBDA_BINARY_EXPRESSION2"
#endif
#define BOOST_LAMBDA_BE2(OPER_NAME, ACTION, CONSTA, CONSTB, CONVERSION) \
template<class A, class Arg> \
inline const \
lambda_functor< \
lambda_functor_base< \
ACTION, \
tuple<typename CONVERSION <CONSTA>::type, lambda_functor<Arg> > \
> \
> \
OPER_NAME (CONSTA& a, const lambda_functor<Arg>& b) { \
return \
lambda_functor_base< \
ACTION, \
tuple<typename CONVERSION <CONSTA>::type, lambda_functor<Arg> > \
> \
(tuple<typename CONVERSION <CONSTA>::type, lambda_functor<Arg> >(a, b)); \
}
#define BOOST_LAMBDA_BINARY_EXPRESSION2(OPER_FUNC_NAME, OPER_NAME, CONSTA, CONSTB, CONST_CONVERSION) template<class A, class Arg> \
inline const lambda_functor<lambda_functor_args<action<2, OPER_NAME >,\
tuple<typename CONST_CONVERSION <CONSTA A>::type, \
lambda_functor<Arg> >,\
dig_arity<Arg>::value> >\
OPER_FUNC_NAME (CONSTA A& a,\
const lambda_functor<Arg>& b)\
{\
return lambda_functor<lambda_functor_args<action<2, OPER_NAME >, \
tuple<typename CONST_CONVERSION <CONSTA A>::type, lambda_functor<Arg> >, \
dig_arity<Arg>::value> >\
(\
tuple<typename CONST_CONVERSION <CONSTA A>::type, lambda_functor<Arg> >(a, b)\
);\
}\
\
#if defined BOOST_LAMBDA_BE3
#error "Multiple defines of BOOST_LAMBDA_BE3"
#if defined BOOST_LAMBDA_BINARY_EXPRESSION3
#error "Multiple defines of BOOST_LAMBDA_BINARY_EXPRESSION3"
#endif
#define BOOST_LAMBDA_BE3(OPER_NAME, ACTION, CONSTA, CONSTB, CONVERSION) \
template<class ArgA, class ArgB> \
inline const \
lambda_functor< \
lambda_functor_base< \
ACTION, \
tuple<lambda_functor<ArgA>, lambda_functor<ArgB> > \
> \
> \
OPER_NAME (const lambda_functor<ArgA>& a, const lambda_functor<ArgB>& b) { \
return \
lambda_functor_base< \
ACTION, \
tuple<lambda_functor<ArgA>, lambda_functor<ArgB> > \
> \
(tuple<lambda_functor<ArgA>, lambda_functor<ArgB> >(a, b)); \
}
#define BOOST_LAMBDA_BINARY_EXPRESSION3(OPER_FUNC_NAME, OPER_NAME, CONSTA, CONSTB, CONST_CONVERSION) template<class ArgA, class ArgB> \
inline const lambda_functor<lambda_functor_args<action<2, OPER_NAME >,\
tuple<lambda_functor<ArgA>, \
lambda_functor<ArgB> >,\
combine_arities<ArgA, ArgB>::value> >\
OPER_FUNC_NAME (const lambda_functor<ArgA>& a, \
const lambda_functor<ArgB>& b)\
{\
return lambda_functor<lambda_functor_args<action<2, OPER_NAME >, \
tuple<lambda_functor<ArgA>, \
lambda_functor<ArgB> >,\
combine_arities<ArgA, ArgB>::value> >\
(\
boost::make_tuple(a, b)\
);\
}\
\
#if defined BOOST_LAMBDA_BE
#error "Multiple defines of BOOST_LAMBDA_BE"
#if defined BOOST_LAMBDA_BINARY_EXPRESSION
#error "Multiple defines of BOOST_LAMBDA_BINARY_EXPRESSION"
#endif
#define BOOST_LAMBDA_BE(OPER_NAME, ACTION, CONSTA, CONSTB, CONST_CONVERSION) \
BOOST_LAMBDA_BE1(OPER_NAME, ACTION, CONSTA, CONSTB, CONST_CONVERSION) \
BOOST_LAMBDA_BE2(OPER_NAME, ACTION, CONSTA, CONSTB, CONST_CONVERSION) \
BOOST_LAMBDA_BE3(OPER_NAME, ACTION, CONSTA, CONSTB, CONST_CONVERSION)
#define BOOST_LAMBDA_BINARY_EXPRESSION(OPER_FUNC_NAME, OPER_NAME, CONSTA, CONSTB, CONST_CONVERSION) \
BOOST_LAMBDA_BINARY_EXPRESSION1(OPER_FUNC_NAME, OPER_NAME, CONSTA, CONSTB, CONST_CONVERSION)\
BOOST_LAMBDA_BINARY_EXPRESSION2(OPER_FUNC_NAME, OPER_NAME, CONSTA, CONSTB, CONST_CONVERSION)\
BOOST_LAMBDA_BINARY_EXPRESSION3(OPER_FUNC_NAME, OPER_NAME, CONSTA, CONSTB, CONST_CONVERSION)
#define BOOST_LAMBDA_EMPTY()
BOOST_LAMBDA_BE(operator+, arithmetic_action<plus_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator-, arithmetic_action<minus_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator*, arithmetic_action<multiply_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator/, arithmetic_action<divide_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator%, arithmetic_action<remainder_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator<<, bitwise_action<leftshift_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator>>, bitwise_action<rightshift_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator&, bitwise_action<and_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator|, bitwise_action<or_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator^, bitwise_action<xor_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator&&, logical_action<and_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator||, logical_action<or_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator<, relational_action<less_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator>, relational_action<greater_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator<=, relational_action<lessorequal_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator>=, relational_action<greaterorequal_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator==, relational_action<equal_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE(operator!=, relational_action<notequal_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BINARY_EXPRESSION(operator+, arithmetic_action< plus_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BINARY_EXPRESSION(operator-, arithmetic_action< minus_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BINARY_EXPRESSION(operator*, arithmetic_action< multiply_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BINARY_EXPRESSION(operator/, arithmetic_action< divide_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BINARY_EXPRESSION(operator%, arithmetic_action< remainder_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BINARY_EXPRESSION(operator<<, bitwise_action< leftshift_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BINARY_EXPRESSION(operator>>, bitwise_action< rightshift_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BINARY_EXPRESSION(operator&, bitwise_action< and_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BINARY_EXPRESSION(operator|, bitwise_action< or_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BINARY_EXPRESSION(operator^, bitwise_action< xor_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BINARY_EXPRESSION(operator&&, logical_action< and_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BINARY_EXPRESSION(operator||, logical_action< or_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BINARY_EXPRESSION(operator<, relational_action< less_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BINARY_EXPRESSION(operator>, relational_action< greater_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BINARY_EXPRESSION(operator<=, relational_action< lessorequal_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BINARY_EXPRESSION(operator>=, relational_action< greaterorequal_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BINARY_EXPRESSION(operator==, relational_action< equal_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BINARY_EXPRESSION(operator!=, relational_action< notequal_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BE(operator+=, arithmetic_assignment_action<plus_action>, A, const B, reference_argument)
BOOST_LAMBDA_BE(operator-=, arithmetic_assignment_action<minus_action>, A, const B, reference_argument)
BOOST_LAMBDA_BE(operator*=, arithmetic_assignment_action<multiply_action>, A, const B, reference_argument)
BOOST_LAMBDA_BE(operator/=, arithmetic_assignment_action<divide_action>, A, const B, reference_argument)
BOOST_LAMBDA_BE(operator%=, arithmetic_assignment_action<remainder_action>, A, const B, reference_argument)
BOOST_LAMBDA_BE(operator<<=, bitwise_assignment_action<leftshift_action>, A, const B, reference_argument)
BOOST_LAMBDA_BE(operator>>=, bitwise_assignment_action<rightshift_action>, A, const B, reference_argument)
BOOST_LAMBDA_BE(operator&=, bitwise_assignment_action<and_action>, A, const B, reference_argument)
BOOST_LAMBDA_BE(operator|=, bitwise_assignment_action<or_action>, A, const B, reference_argument)
BOOST_LAMBDA_BE(operator^=, bitwise_assignment_action<xor_action>, A, const B, reference_argument)
BOOST_LAMBDA_BINARY_EXPRESSION(operator+=, arithmetic_assignment_action< plus_action>, , const, reference_argument)
BOOST_LAMBDA_BINARY_EXPRESSION(operator-=, arithmetic_assignment_action< minus_action>, , const, reference_argument)
BOOST_LAMBDA_BINARY_EXPRESSION(operator*=, arithmetic_assignment_action< multiply_action>, , const, reference_argument)
BOOST_LAMBDA_BINARY_EXPRESSION(operator/=, arithmetic_assignment_action< divide_action>, , const, reference_argument)
BOOST_LAMBDA_BINARY_EXPRESSION(operator%=, arithmetic_assignment_action< remainder_action>, , const, reference_argument)
BOOST_LAMBDA_BINARY_EXPRESSION(operator<<=, bitwise_assignment_action< leftshift_action>, , const, reference_argument)
BOOST_LAMBDA_BINARY_EXPRESSION(operator>>=, bitwise_assignment_action< rightshift_action>, , const, reference_argument)
BOOST_LAMBDA_BINARY_EXPRESSION(operator&=, bitwise_assignment_action< and_action>, , const, reference_argument)
BOOST_LAMBDA_BINARY_EXPRESSION(operator|=, bitwise_assignment_action< or_action>, , const, reference_argument)
BOOST_LAMBDA_BINARY_EXPRESSION(operator^=, bitwise_assignment_action< xor_action>, , const, reference_argument)
// A special trick for comma operator for correct preprocessing
@@ -144,9 +135,9 @@ BOOST_LAMBDA_BE(operator^=, bitwise_assignment_action<xor_action>, A, const B, r
#define BOOST_LAMBDA_COMMA_OPERATOR_NAME operator,
BOOST_LAMBDA_BE1(BOOST_LAMBDA_COMMA_OPERATOR_NAME, other_action<comma_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE2(BOOST_LAMBDA_COMMA_OPERATOR_NAME, other_action<comma_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BE3(BOOST_LAMBDA_COMMA_OPERATOR_NAME, other_action<comma_action>, const A, const B, const_copy_argument)
BOOST_LAMBDA_BINARY_EXPRESSION1(BOOST_LAMBDA_COMMA_OPERATOR_NAME, other_action< comma_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BINARY_EXPRESSION2(BOOST_LAMBDA_COMMA_OPERATOR_NAME, other_action< comma_action>, const, const, const_copy_argument)
BOOST_LAMBDA_BINARY_EXPRESSION3(BOOST_LAMBDA_COMMA_OPERATOR_NAME, other_action< comma_action>, const, const, const_copy_argument)
@@ -161,6 +152,23 @@ namespace detail {
// Note that the overloading is const vs. non-const first argument
#ifdef BOOST_NO_TEMPLATED_STREAMS
template<class T> struct convert_ostream_to_ref_others_to_c_plain_by_default {
typedef typename detail::IF<
boost::is_convertible<T*, std::ostream*>::value,
T&,
typename const_copy_argument <T>::type
>::RET type;
};
template<class T> struct convert_istream_to_ref_others_to_c_plain_by_default {
typedef typename detail::IF<
boost::is_convertible<T*, std::istream*>::value,
T&,
typename const_copy_argument <T>::type
>::RET type;
};
#else
template<class T> struct convert_ostream_to_ref_others_to_c_plain_by_default {
typedef typename detail::IF<
@@ -181,11 +189,12 @@ template<class T> struct convert_istream_to_ref_others_to_c_plain_by_default {
typename const_copy_argument <T>::type
>::RET type;
};
#endif
} // detail
BOOST_LAMBDA_BE2(operator<<, bitwise_action< leftshift_action>, A, const B, detail::convert_ostream_to_ref_others_to_c_plain_by_default)
BOOST_LAMBDA_BE2(operator>>, bitwise_action< rightshift_action>, A, const B, detail::convert_istream_to_ref_others_to_c_plain_by_default)
BOOST_LAMBDA_BINARY_EXPRESSION2(operator<<, bitwise_action< leftshift_action>, , const, detail::convert_ostream_to_ref_others_to_c_plain_by_default)
BOOST_LAMBDA_BINARY_EXPRESSION2(operator>>, bitwise_action< rightshift_action>, , const, detail::convert_istream_to_ref_others_to_c_plain_by_default)
// special case for io_manipulators.
@@ -196,37 +205,43 @@ BOOST_LAMBDA_BE2(operator>>, bitwise_action< rightshift_action>, A, const B, det
template<class Arg, class Ret, class ManipArg>
inline const
lambda_functor<
lambda_functor_base<
bitwise_action<leftshift_action>,
tuple<lambda_functor<Arg>, Ret(&)(ManipArg)>
lambda_functor_args<
action<2, bitwise_action<leftshift_action> >,
tuple<lambda_functor<Arg>, Ret(&)(ManipArg)>,
dig_arity<Arg>::value
>
>
operator<<(const lambda_functor<Arg>& a, Ret(&b)(ManipArg))
{
return
lambda_functor_base<
bitwise_action<leftshift_action>,
tuple<lambda_functor<Arg>, Ret(&)(ManipArg)>
lambda_functor<
lambda_functor_args<
action<2, bitwise_action<leftshift_action> >,
tuple<lambda_functor<Arg>, Ret(&)(ManipArg)>,
dig_arity<Arg>::value
>
( tuple<lambda_functor<Arg>, Ret(&)(ManipArg)>(a, b) );
> ( tuple<lambda_functor<Arg>, Ret(&)(ManipArg)>(a, b) );
}
template<class Arg, class Ret, class ManipArg>
inline const
lambda_functor<
lambda_functor_base<
bitwise_action<rightshift_action>,
tuple<lambda_functor<Arg>, Ret(&)(ManipArg)>
lambda_functor_args<
action<2, bitwise_action<rightshift_action> >,
tuple<lambda_functor<Arg>, Ret(&)(ManipArg)>,
dig_arity<Arg>::value
>
>
operator>>(const lambda_functor<Arg>& a, Ret(&b)(ManipArg))
{
return
lambda_functor_base<
bitwise_action<rightshift_action>,
tuple<lambda_functor<Arg>, Ret(&)(ManipArg)>
lambda_functor<
lambda_functor_args<
action<2, bitwise_action<rightshift_action> >,
tuple<lambda_functor<Arg>, Ret(&)(ManipArg)>,
dig_arity<Arg>::value
>
( tuple<lambda_functor<Arg>, Ret(&)(ManipArg)>(a, b) );
> ( tuple<lambda_functor<Arg>, Ret(&)(ManipArg)>(a, b) );
}
@@ -236,115 +251,123 @@ operator>>(const lambda_functor<Arg>& a, Ret(&b)(ManipArg))
// the result of a+1 would be const
// To make the latter work too,
// non-const arrays are taken as non-const and stored as non-const as well.
#if defined BOOST_LAMBDA_PTR_ARITHMETIC_E1
#error "Multiple defines of BOOST_LAMBDA_PTR_ARITHMETIC_E1"
#if defined BOOST_LAMBDA_PTR_ARITHMETIC_EXPRESSION1
#error "Multiple defines of BOOST_LAMBDA_PTR_ARITHMETIC_EXPRESSION1"
#endif
#define BOOST_LAMBDA_PTR_ARITHMETIC_E1(OPER_NAME, ACTION, CONSTB) \
template<class Arg, int N, class B> \
inline const \
lambda_functor< \
lambda_functor_base<ACTION, tuple<lambda_functor<Arg>, CONSTB(&)[N]> > \
> \
OPER_NAME (const lambda_functor<Arg>& a, CONSTB(&b)[N]) \
{ \
return \
lambda_functor_base<ACTION, tuple<lambda_functor<Arg>, CONSTB(&)[N]> > \
(tuple<lambda_functor<Arg>, CONSTB(&)[N]>(a, b)); \
}
#define BOOST_LAMBDA_PTR_ARITHMETIC_EXPRESSION1(OPER_FUNC_NAME, OPER_NAME, CONST) template<class Arg, int N, class B> \
inline const lambda_functor<lambda_functor_args<action<2, OPER_NAME >, \
tuple<lambda_functor<Arg>, \
CONST B (&) [N]>,\
dig_arity<Arg>::value> > \
OPER_FUNC_NAME (const lambda_functor<Arg>& a, \
CONST B (&b) [N])\
{\
return lambda_functor<lambda_functor_args<action<2, OPER_NAME >, \
tuple<lambda_functor<Arg>, CONST B (&) [N]>, \
dig_arity<Arg>::value> >\
(\
tuple<lambda_functor<Arg>, CONST B (&) [N]>(a, b)\
);\
}\
\
#if defined BOOST_LAMBDA_PTR_ARITHMETIC_E2
#error "Multiple defines of BOOST_LAMBDA_PTR_ARITHMETIC_E2"
#if defined BOOST_LAMBDA_PTR_ARITHMETIC_EXPRESSION2
#error "Multiple defines of BOOST_LAMBDA_PTR_ARITHMETIC_EXPRESSION2"
#endif
#define BOOST_LAMBDA_PTR_ARITHMETIC_E2(OPER_NAME, ACTION, CONSTA) \
template<int N, class A, class Arg> \
inline const \
lambda_functor< \
lambda_functor_base<ACTION, tuple<CONSTA(&)[N], lambda_functor<Arg> > > \
> \
OPER_NAME (CONSTA(&a)[N], const lambda_functor<Arg>& b) \
{ \
return \
lambda_functor_base<ACTION, tuple<CONSTA(&)[N], lambda_functor<Arg> > > \
(tuple<CONSTA(&)[N], lambda_functor<Arg> >(a, b)); \
}
#define BOOST_LAMBDA_PTR_ARITHMETIC_EXPRESSION2(OPER_FUNC_NAME, OPER_NAME, CONST) template<int N, class A, class Arg> \
inline const lambda_functor<lambda_functor_args<action<2, OPER_NAME >, \
tuple<CONST A (&) [N], lambda_functor<Arg> >, \
dig_arity<Arg>::value> > \
OPER_FUNC_NAME (CONST A (&a) [N], const lambda_functor<Arg>& b) \
{\
return lambda_functor<lambda_functor_args<action<2, OPER_NAME >, \
tuple<CONST A (&) [N], lambda_functor<Arg> >, \
dig_arity<Arg>::value> >\
(\
tuple<CONST A (&) [N], lambda_functor<Arg> >(a, b)\
);\
}\
\
BOOST_LAMBDA_PTR_ARITHMETIC_EXPRESSION1(operator+, arithmetic_action< plus_action>,)
BOOST_LAMBDA_PTR_ARITHMETIC_EXPRESSION2(operator+, arithmetic_action< plus_action>,)
BOOST_LAMBDA_PTR_ARITHMETIC_EXPRESSION1(operator+, arithmetic_action< plus_action>,const)
BOOST_LAMBDA_PTR_ARITHMETIC_EXPRESSION2(operator+, arithmetic_action< plus_action>,const)
BOOST_LAMBDA_PTR_ARITHMETIC_E1(operator+, arithmetic_action<plus_action>, B)
BOOST_LAMBDA_PTR_ARITHMETIC_E2(operator+, arithmetic_action<plus_action>, A)
BOOST_LAMBDA_PTR_ARITHMETIC_E1(operator+, arithmetic_action<plus_action>,const B)
BOOST_LAMBDA_PTR_ARITHMETIC_E2(operator+, arithmetic_action<plus_action>,const A)
//BOOST_LAMBDA_PTR_ARITHMETIC_E1(operator-, arithmetic_action<minus_action>)
//BOOST_LAMBDA_PTR_ARITHMETIC_EXPRESSION1(operator-, arithmetic_action<minus_action>)
// This is not needed, since the result of ptr-ptr is an rvalue anyway
BOOST_LAMBDA_PTR_ARITHMETIC_E2(operator-, arithmetic_action<minus_action>, A)
BOOST_LAMBDA_PTR_ARITHMETIC_E2(operator-, arithmetic_action<minus_action>, const A)
BOOST_LAMBDA_PTR_ARITHMETIC_EXPRESSION2(operator-, arithmetic_action< minus_action>, )
BOOST_LAMBDA_PTR_ARITHMETIC_EXPRESSION2(operator-, arithmetic_action< minus_action>, const)
#undef BOOST_LAMBDA_BE1
#undef BOOST_LAMBDA_BE2
#undef BOOST_LAMBDA_BE3
#undef BOOST_LAMBDA_BE
#undef BOOST_LAMBDA_BINARY_EXPRESSION1
#undef BOOST_LAMBDA_BINARY_EXPRESSION2
#undef BOOST_LAMBDA_BINARY_EXPRESSION3
#undef BOOST_LAMBDA_BINARY_EXPRESSION
#undef BOOST_LAMBDA_COMMA_OPERATOR_NAME
#undef BOOST_LAMBDA_PTR_ARITHMETIC_E1
#undef BOOST_LAMBDA_PTR_ARITHMETIC_E2
#undef BOOST_LAMBDA_PTR_ARITHMETIC_EXPRESSION1
#undef BOOST_LAMBDA_PTR_ARITHMETIC_EXPRESSION2
// ---------------------------------------------------------------------
// unary operators -----------------------------------------------------
// ---------------------------------------------------------------------
#if defined BOOST_LAMBDA_UE
#error "Multiple defines of BOOST_LAMBDA_UE"
#if defined BOOST_LAMBDA_UNARY_EXPRESSION
#error "Multiple defines of BOOST_LAMBDA_UNARY_EXPRESSION"
#endif
#define BOOST_LAMBDA_UE(OPER_NAME, ACTION) \
template<class Arg> \
inline const \
lambda_functor<lambda_functor_base<ACTION, tuple<lambda_functor<Arg> > > > \
OPER_NAME (const lambda_functor<Arg>& a) \
{ \
return \
lambda_functor_base<ACTION, tuple<lambda_functor<Arg> > > \
( tuple<lambda_functor<Arg> >(a) ); \
}
#define BOOST_LAMBDA_UNARY_EXPRESSION(FUNCTION_NAME, ACTION_NAME) \
template<class Arg>\
inline const lambda_functor<lambda_functor_args<action<1, ACTION_NAME >,\
tuple<lambda_functor<Arg> >,\
dig_arity<Arg>::value> >\
FUNCTION_NAME (const lambda_functor<Arg>& a)\
{\
return lambda_functor<lambda_functor_args<action<1, ACTION_NAME >,\
tuple<lambda_functor<Arg> >,\
dig_arity<Arg>::value> >\
( make_tuple(a) );\
}\
\
BOOST_LAMBDA_UNARY_EXPRESSION(operator+, unary_arithmetic_action<plus_action>)
BOOST_LAMBDA_UNARY_EXPRESSION(operator-, unary_arithmetic_action<minus_action>)
BOOST_LAMBDA_UNARY_EXPRESSION(operator~, bitwise_action<not_action>)
BOOST_LAMBDA_UNARY_EXPRESSION(operator!, logical_action<not_action>)
BOOST_LAMBDA_UNARY_EXPRESSION(operator++, pre_increment_decrement_action<increment_action>)
BOOST_LAMBDA_UNARY_EXPRESSION(operator--, pre_increment_decrement_action<decrement_action>)
BOOST_LAMBDA_UNARY_EXPRESSION(operator*, other_action<contentsof_action>)
BOOST_LAMBDA_UNARY_EXPRESSION(operator&, other_action<addressof_action>)
BOOST_LAMBDA_UE(operator+, unary_arithmetic_action<plus_action>)
BOOST_LAMBDA_UE(operator-, unary_arithmetic_action<minus_action>)
BOOST_LAMBDA_UE(operator~, bitwise_action<not_action>)
BOOST_LAMBDA_UE(operator!, logical_action<not_action>)
BOOST_LAMBDA_UE(operator++, pre_increment_decrement_action<increment_action>)
BOOST_LAMBDA_UE(operator--, pre_increment_decrement_action<decrement_action>)
BOOST_LAMBDA_UE(operator*, other_action<contentsof_action>)
BOOST_LAMBDA_UE(operator&, other_action<addressof_action>)
#if defined BOOST_LAMBDA_POSTFIX_UE
#error "Multiple defines of BOOST_LAMBDA_POSTFIX_UE"
#if defined BOOST_LAMBDA_POSTFIX_UNARY_EXPRESSION
#error "Multiple defines of BOOST_LAMBDA_POSTFIX_UNARY_EXPRESSION"
#endif
#define BOOST_LAMBDA_POSTFIX_UE(OPER_NAME, ACTION) \
template<class Arg> \
inline const \
lambda_functor<lambda_functor_base<ACTION, tuple<lambda_functor<Arg> > > > \
OPER_NAME (const lambda_functor<Arg>& a, int) \
{ \
return \
lambda_functor_base<ACTION, tuple<lambda_functor<Arg> > > \
( tuple<lambda_functor<Arg> >(a) ); \
}
#define BOOST_LAMBDA_POSTFIX_UNARY_EXPRESSION(FUNCTION_NAME, ACTION_NAME) \
template<class Arg>\
inline const lambda_functor<lambda_functor_args<action<1, ACTION_NAME >,\
tuple<lambda_functor<Arg> >,\
dig_arity<Arg>::value> >\
FUNCTION_NAME (const lambda_functor<Arg>& a, int)\
{\
return lambda_functor<lambda_functor_args<action<1, ACTION_NAME >,\
tuple<lambda_functor<Arg> >,\
dig_arity<Arg>::value> >\
( make_tuple(a) );\
}\
\
BOOST_LAMBDA_POSTFIX_UNARY_EXPRESSION(operator++, post_increment_decrement_action<increment_action>)
BOOST_LAMBDA_POSTFIX_UNARY_EXPRESSION(operator--, post_increment_decrement_action<decrement_action>)
BOOST_LAMBDA_POSTFIX_UE(operator++, post_increment_decrement_action<increment_action>)
BOOST_LAMBDA_POSTFIX_UE(operator--, post_increment_decrement_action<decrement_action>)
#undef BOOST_LAMBDA_UE
#undef BOOST_LAMBDA_POSTFIX_UE
#undef BOOST_LAMBDA_UNARY_EXPRESSION
#undef BOOST_LAMBDA_POSTFIX_UNARY_EXPRESSION
} // namespace lambda
} // namespace boost

View File

@@ -1,10 +1,15 @@
// Boost Lambda Library ret.hpp -----------------------------------------
// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
//
// 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)
// 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 www.boost.org
@@ -38,19 +43,22 @@ namespace lambda {
template<class RET, class Arg>
inline const
lambda_functor<
lambda_functor_base<
explicit_return_type_action<RET>,
tuple<lambda_functor<Arg> >
lambda_functor_args<
action<1, explicit_return_type_action<RET> >,
tuple<lambda_functor<Arg> >,
dig_arity<Arg>::value
>
>
ret(const lambda_functor<Arg>& a1)
{
return
lambda_functor_base<
explicit_return_type_action<RET>,
tuple<lambda_functor<Arg> >
>
(tuple<lambda_functor<Arg> >(a1));
return lambda_functor<
lambda_functor_args<
action<1, explicit_return_type_action<RET> >,
tuple<lambda_functor<Arg> >,
dig_arity<Arg>::value
>
>
(tuple<lambda_functor<Arg> >(a1));
}
// protect ------------------
@@ -62,21 +70,101 @@ inline const T& protect(const T& t) { return t; }
template<class Arg>
inline const
lambda_functor<
lambda_functor_base<
protect_action,
tuple<lambda_functor<Arg> >
lambda_functor_args<
action<1, protect_action>,
tuple<lambda_functor<Arg> >,
NONE
>
>
protect(const lambda_functor<Arg>& a1)
{
return
lambda_functor_base<
protect_action,
tuple<lambda_functor<Arg> >
return lambda_functor<
lambda_functor_args<
action<1, protect_action>,
tuple<lambda_functor<Arg> >,
NONE
>
>
(tuple<lambda_functor<Arg> >(a1));
}
// -- identity -------------------------
// identity templates
template<class Arg>
inline const
lambda_functor<
lambda_functor_args<
action<1, other_action<identity_action> >,
tuple<typename const_copy_argument<const Arg>::type>,
NONE> >
constant(const Arg& a)
{
return
lambda_functor<
lambda_functor_args<
action<1, other_action<identity_action> >,
tuple<typename const_copy_argument<const Arg>::type>,
NONE
>
> (tuple<typename const_copy_argument<const Arg>::type>(a));
}
// since typedef's can't take template arguments,
// I made this struct so you can use
// constant_type<TYPE>::type constant_name(constant(value)); (GWP)
template<class Arg>
class constant_type {
public:
typedef const
lambda_functor<
lambda_functor_args<
action<1, other_action<identity_action> >,
tuple<typename const_copy_argument<const Arg>::type>,
NONE
>
> type;
};
template<class Arg>
inline const
lambda_functor<
lambda_functor_args<
action<1, other_action<identity_action> >,
tuple<typename reference_argument<Arg>::type>,
NONE
>
>
var(Arg& a)
{
return
lambda_functor<
lambda_functor_args<
action<1, other_action<identity_action> >,
tuple<typename reference_argument<Arg>::type>,
NONE
>
> (tuple<typename reference_argument<Arg>::type>(a));
}
// since typedef's can't take template arguments, I made this struct so
// you can use var_type<TYPE>::type var_name(var(i)); (GWP)
template<class Arg>
class var_type {
public:
typedef
lambda_functor<
lambda_functor_args<
action<1, other_action<identity_action> >,
tuple<typename reference_argument<Arg>::type>,
NONE
>
> type;
};
// -------------------------------------------------------------------
// Hides the lambda functorness of a lambda functor.
@@ -87,46 +175,51 @@ protect(const lambda_functor<Arg>& a1)
// note, unlambda and protect are different things. Protect hides the lambda
// functor for one application, unlambda for good.
template <class LambdaFunctor>
class non_lambda_functor
{
LambdaFunctor lf;
template <class Arg>
class non_lambda_functor : public has_sig {
lambda_functor<Arg> lf; // a lambda functor
public:
// This functor defines the result_type typedef.
// The result type must be deducible without knowing the arguments
// TODO: check that passing unspecified as open args fails
// typedef typename
// return_type<Arg,
// open_args<detail::unspecified,
// detail::unspecified,
// detail::unspecified> >::type
// result_type;
template <class SigArgs> struct sig {
typedef typename
LambdaFunctor::inherited::
template sig<typename SigArgs::tail_type>::type type;
lambda_functor<Arg>::template sig<SigArgs>::type type;
};
explicit non_lambda_functor(const LambdaFunctor& a) : lf(a) {}
non_lambda_functor(const lambda_functor<Arg>& a) : lf(a) {}
typename LambdaFunctor::nullary_return_type
typename sig<tuple<lambda_functor<Arg> > >::type
operator()() const {
return lf.template
call<typename LambdaFunctor::nullary_return_type>
(cnull_type(), cnull_type(), cnull_type(), cnull_type());
return lf.template ret_call<typename sig<tuple<lambda_functor<Arg> > >::type>();
}
template<class A>
typename sig<tuple<const non_lambda_functor, A&> >::type
typename sig<tuple<lambda_functor<Arg>, A&> >::type
operator()(A& a) const {
return lf.template call<typename sig<tuple<const non_lambda_functor, A&> >::type >(a, cnull_type(), cnull_type(), cnull_type());
return lf.template ret_call<typename sig<tuple<lambda_functor<Arg>, A&> >::type >(a);
}
template<class A, class B>
typename sig<tuple<const non_lambda_functor, A&, B&> >::type
typename sig<tuple<lambda_functor<Arg>, A&, B&> >::type
operator()(A& a, B& b) const {
return lf.template call<typename sig<tuple<const non_lambda_functor, A&, B&> >::type >(a, b, cnull_type(), cnull_type());
return lf.template ret_call<typename sig<tuple<lambda_functor<Arg>, A&, B&> >::type >(a, b);
}
template<class A, class B, class C>
typename sig<tuple<const non_lambda_functor, A&, B&, C&> >::type
typename sig<tuple<lambda_functor<Arg>, A&, B&, C&> >::type
operator()(A& a, B& b, C& c) const {
return lf.template call<typename sig<tuple<const non_lambda_functor, A&, B&, C&> >::type>(a, b, c, cnull_type());
return lf.template ret_call<typename sig<tuple<lambda_functor<Arg>, A&, B&, C&> >::type>(a, b, c);
}
};
@@ -134,10 +227,9 @@ template <class Arg>
inline const Arg& unlambda(const Arg& a) { return a; }
template <class Arg>
inline const non_lambda_functor<lambda_functor<Arg> >
unlambda(const lambda_functor<Arg>& a)
inline const non_lambda_functor<Arg> unlambda(const lambda_functor<Arg>& a)
{
return non_lambda_functor<lambda_functor<Arg> >(a);
return non_lambda_functor<Arg>(a);
}
// Due to a language restriction, lambda functors cannot be made to
@@ -145,173 +237,21 @@ unlambda(const lambda_functor<Arg>& a)
// temporaries, but sometimes they do. That's why a workaround is provided.
// Note, that this potentially breaks const correctness, so be careful!
// any lambda functor can be turned into a const_incorrect_lambda_functor
// The operator() takes arguments as consts and then casts constness
// away. So this breaks const correctness!!! but is a necessary workaround
// in some cases due to language limitations.
// Note, that this is not a lambda_functor anymore, so it can not be used
// as a sub lambda expression.
template <class LambdaFunctor>
struct const_incorrect_lambda_functor {
LambdaFunctor lf;
public:
explicit const_incorrect_lambda_functor(const LambdaFunctor& a) : lf(a) {}
template <class SigArgs> struct sig {
typedef typename
LambdaFunctor::inherited::template
sig<typename SigArgs::tail_type>::type type;
};
// The nullary case is not needed (no arguments, no parameter type problems)
template<class A>
typename sig<tuple<const const_incorrect_lambda_functor, A&> >::type
operator()(const A& a) const {
return lf.template call<typename sig<tuple<const const_incorrect_lambda_functor, A&> >::type >(const_cast<A&>(a), cnull_type(), cnull_type(), cnull_type());
}
template<class A, class B>
typename sig<tuple<const const_incorrect_lambda_functor, A&, B&> >::type
operator()(const A& a, const B& b) const {
return lf.template call<typename sig<tuple<const const_incorrect_lambda_functor, A&, B&> >::type >(const_cast<A&>(a), const_cast<B&>(b), cnull_type(), cnull_type());
}
template<class A, class B, class C>
typename sig<tuple<const const_incorrect_lambda_functor, A&, B&, C&> >::type
operator()(const A& a, const B& b, const C& c) const {
return lf.template call<typename sig<tuple<const const_incorrect_lambda_functor, A&, B&, C&> >::type>(const_cast<A&>(a), const_cast<B&>(b), const_cast<C&>(c), cnull_type());
}
};
// ------------------------------------------------------------------------
// any lambda functor can be turned into a const_parameter_lambda_functor
// The operator() takes arguments as const.
// This is useful if lambda functors are called with non-const rvalues.
// Note, that this is not a lambda_functor anymore, so it can not be used
// as a sub lambda expression.
template <class LambdaFunctor>
struct const_parameter_lambda_functor {
LambdaFunctor lf;
public:
explicit const_parameter_lambda_functor(const LambdaFunctor& a) : lf(a) {}
template <class SigArgs> struct sig {
typedef typename
LambdaFunctor::inherited::template
sig<typename SigArgs::tail_type>::type type;
};
// The nullary case is not needed: no arguments, no constness problems.
template<class A>
typename sig<tuple<const const_parameter_lambda_functor, const A&> >::type
operator()(const A& a) const {
return lf.template call<typename sig<tuple<const const_parameter_lambda_functor, const A&> >::type >(a, cnull_type(), cnull_type(), cnull_type());
}
template<class A, class B>
typename sig<tuple<const const_parameter_lambda_functor, const A&, const B&> >::type
operator()(const A& a, const B& b) const {
return lf.template call<typename sig<tuple<const const_parameter_lambda_functor, const A&, const B&> >::type >(a, b, cnull_type(), cnull_type());
}
template<class A, class B, class C>
typename sig<tuple<const const_parameter_lambda_functor, const A&, const B&, const C&>
>::type
operator()(const A& a, const B& b, const C& c) const {
return lf.template call<typename sig<tuple<const const_parameter_lambda_functor, const A&, const B&, const C&> >::type>(a, b, c, cnull_type());
}
};
template <class Arg>
inline const const_incorrect_lambda_functor<lambda_functor<Arg> >
inline const const_incorrect_lambda_functor<Arg>
break_const(const lambda_functor<Arg>& lf)
{
return const_incorrect_lambda_functor<lambda_functor<Arg> >(lf);
}
return const_incorrect_lambda_functor<Arg>(lf);
}
template <class Arg>
inline const const_parameter_lambda_functor<lambda_functor<Arg> >
inline const const_parameter_lambda_functor<Arg>
const_parameters(const lambda_functor<Arg>& lf)
{
return const_parameter_lambda_functor<lambda_functor<Arg> >(lf);
return const_parameter_lambda_functor<Arg>(lf);
}
// make void ------------------------------------------------
// make_void( x ) turns a lambda functor x with some return type y into
// another lambda functor, which has a void return type
// when called, the original return type is discarded
// we use this action. The action class will be called, which means that
// the wrapped lambda functor is evaluated, but we just don't do anything
// with the result.
struct voidifier_action {
template<class Ret, class A> static void apply(A&) {}
};
template<class Args> struct return_type_N<voidifier_action, Args> {
typedef void type;
};
template<class Arg1>
inline const
lambda_functor<
lambda_functor_base<
action<1, voidifier_action>,
tuple<lambda_functor<Arg1> >
>
>
make_void(const lambda_functor<Arg1>& a1) {
return
lambda_functor_base<
action<1, voidifier_action>,
tuple<lambda_functor<Arg1> >
>
(tuple<lambda_functor<Arg1> > (a1));
}
// for non-lambda functors, make_void does nothing
// (the argument gets evaluated immediately)
template<class Arg1>
inline const
lambda_functor<
lambda_functor_base<do_nothing_action, null_type>
>
make_void(const Arg1&) {
return
lambda_functor_base<do_nothing_action, null_type>();
}
// std_functor -----------------------------------------------------
// The STL uses the result_type typedef as the convention to let binders know
// the return type of a function object.
// LL uses the sig template.
// To let LL know that the function object has the result_type typedef
// defined, it can be wrapped with the std_functor function.
// Just inherit form the template parameter (the standard functor),
// and provide a sig template. So we have a class which is still the
// same functor + the sig template.
template<class T>
struct result_type_to_sig : public T {
template<class Args> struct sig { typedef typename T::result_type type; };
result_type_to_sig(const T& t) : T(t) {}
};
template<class F>
inline result_type_to_sig<F> std_functor(const F& f) { return f; }
} // namespace lambda
} // namespace boost

View File

@@ -1,10 +1,15 @@
// return_type_traits.hpp -- Boost Lambda Library ---------------------------
// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
//
// 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)
// 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 www.boost.org
@@ -12,30 +17,11 @@
#ifndef BOOST_LAMBDA_RETURN_TYPE_TRAITS_HPP
#define BOOST_LAMBDA_RETURN_TYPE_TRAITS_HPP
#include "boost/mpl/has_xxx.hpp"
#include <cstddef> // needed for the ptrdiff_t
namespace boost {
namespace lambda {
// Much of the type deduction code for standard arithmetic types
// from Gary Powell
// different arities:
template <class Act, class A1> struct return_type_1; // 1-ary actions
template <class Act, class A1, class A2> struct return_type_2; // 2-ary
template <class Act, class Args> struct return_type_N; // >3- ary
template <class Act, class A1> struct return_type_1_prot;
template <class Act, class A1, class A2> struct return_type_2_prot; // 2-ary
template <class Act, class A1> struct return_type_N_prot; // >3-ary
namespace detail {
template<class> class return_type_deduction_failure {};
// In some cases return type deduction should fail (an invalid lambda
// expression). Sometimes the lambda expression can be ok, the return type
// just is not deducible (user defined operators). Then return type deduction
@@ -51,44 +37,43 @@ template<class> class return_type_deduction_failure {};
// fail directly, but rather result in a valid but wrong return type,
// causing a compile time error only if the function is really called.
namespace detail {
template<class> class return_type_deduction_failure {};
} // end detail
}
// Much of the type deduction code for standard arithmetic types
// from Gary Powell
// return_type_X_prot classes --------------------------------------------
// These classes are the first layer that gets instantiated from the
// lambda_functor_base sig templates. It will check whether
// the action is protectable and one of arguments is "protected" or its
// evaluation will otherwise result in another lambda functor.
// If this is a case, the result type will be another lambda functor.
// The arguments are always non-reference types, except for comma action
// where the right argument can be a reference too. This is because it
// matters (in the builtin case) whether the argument is an lvalue or
// rvalue: int i; i, 1 -> rvalue; 1, i -> lvalue
template <class Act, class A> struct return_type_1_prot {
public:
typedef typename
detail::IF<
is_protectable<Act>::value && is_lambda_functor<A>::value,
lambda_functor<
lambda_functor_base<
Act,
tuple<typename detail::remove_reference_and_cv<A>::type>
>
>,
typename return_type_1<Act, A>::type
>::RET type;
template<class A, class B, class C>
struct open_args {
typedef A type1;
typedef B type2;
typedef C type3;
};
// take care of the unavoidable instantiation for nullary case
template<class Act> struct return_type_1_prot<Act, null_type> {
typedef null_type type;
// -- return type -------------------------------------
// does not handle lambda_functor lambda_functors
// e.g. if the lambda_functor action is a lambda_functor
// The primary template:
// if we know nothing about Arg, it is not a lambda_functor.
// Hence the return type is Arg itself.
template <class Arg, class Open>
struct return_type {
typedef Arg type;
};
// different arities:
template <class Act, class A1> class return_type_1; // 1-ary actions
template <class Act, class A1, class A2> class return_type_2; // 2-ary
template <class Act, class Args> class return_type_N; // >3- ary
// Unary actions (result from unary operators)
// do not have a default return type.
template<class Act, class A> struct return_type_1 {
@@ -97,25 +82,55 @@ template<class Act, class A> struct return_type_1 {
};
// read the comments for return_type_2_protect
namespace detail {
template <class T>
class protect_conversion {
typedef typename boost::remove_reference<T>::type non_ref_T;
public:
template <class A>
class protect_conversion {
// T -> const T
// T& -> T&
// const T& -> const T
// function& -> function&
// const array& -> const array&
// lambda functors are not stored as references
// function reference types are function reference types
typedef typename boost::remove_reference<A>::type A1;
// add const to rvalues, so that all rvalues are stored as const in
// the args tuple
typedef typename detail::IF_type<
boost::is_reference<T>::value && !boost::is_const<non_ref_T>::value,
detail::identity_mapping<T>,
const_copy_argument<non_ref_T> // handles funtion and array
>::type type; // types correctly
};
public:
typedef typename detail::IF<
boost::is_reference<A>::value
&& !boost::is_const<A1>::value
&& !is_lambda_functor<A1>::value,
A,
typename const_copy_argument<A1>::type // handles funtion and array type correctly
>::RET type;
};
} // end detail
template <class Act, class A, class B> struct return_type_2_prot {
template <class Act, class A> struct return_type_1_protect {
typedef typename
detail::IF<
is_lambda_functor<A>::value,
lambda_functor<
lambda_functor_args<
action<1, Act>,
tuple<typename detail::protect_conversion<A>::type>,
dig_arity<A>::value
>
>,
typename return_type_1<Act, A>::type
>::RET type;
};
// binary actions ---------------------------------------------------
template <class Act, class A, class B> struct return_type_2;
// experimental feature
// We may have a lambda functor as a result type of a subexpression
@@ -125,8 +140,8 @@ template <class Act, class A, class B> struct return_type_2_prot {
// We need to make a conservative choise here.
// The resulting lambda functor stores all const reference arguments as
// const copies. References to non-const are stored as such.
// So if the source of the argument is a const open argument, a bound
// argument stored as a const reference, or a function returning a
// So if the source of the argument is an const open argument, a bound
// argument stroed as a const reference, or a function returning a
// const reference, that information is lost. There is no way of
// telling apart 'real const references' from just 'LL internal
// const references' (or it would be really hard)
@@ -136,127 +151,460 @@ template <class Act, class A, class B> struct return_type_2_prot {
// action type and code, and a copy compatible argument tuple.
typedef typename boost::remove_reference<A>::type non_ref_A;
typedef typename boost::remove_reference<B>::type non_ref_B;
template <class Act, class A, class B> struct return_type_2_protect {
// typedef typename boost::remove_reference<A>::type A1;
// typedef typename boost::remove_reference<B>::type B1;
// // adding const to a function type fails, these tests are to
// // avoid that. Note that only the true branch is instantiated with this IF
// typedef typename
// detail::IF_type<
// !is_lambda_functor<A1>::value && (boost::is_function<A1>::value || !(boost::is_const<A1>::value)),
// boost::add_reference<A1>,
// boost::add_const<A1>
// >::type A2;
// typedef typename
// detail::IF_type<
// !is_lambda_functor<B1>::value && ( boost::is_function<B1>::value || !(boost::is_const<B1>::value)),
// boost::add_reference<B1>,
// boost::add_const<B1>
// >::type B2;
typedef typename
detail::IF<
is_protectable<Act>::value &&
(is_lambda_functor<A>::value || is_lambda_functor<B>::value),
is_lambda_functor<A>::value || is_lambda_functor<B>::value,
lambda_functor<
lambda_functor_base<
Act,
lambda_functor_args<
action<2, Act>,
tuple<typename detail::protect_conversion<A>::type,
typename detail::protect_conversion<B>::type>
typename detail::protect_conversion<B>::type>,
combine_arities<A, B>::value
>
>,
typename return_type_2<Act, non_ref_A, non_ref_B>::type
typename return_type_2<Act, A, B>::type
>::RET type;
};
// take care of the unavoidable instantiation for nullary case
template<class Act> struct return_type_2_prot<Act, null_type, null_type> {
typedef null_type type;
// // unary function action (it is binary action)
// // If a function object overloads operator(), the return type could depend
// // on the argument types. This is not taken into consideration.
// template<class A, class B, class Ret>
// struct return_type_2<function_action<2, Ret>, A, B> {
// typedef typename return_type_1<function_action<1, Ret>, A>::type type;
// };
// reduce to lambda_functor_args
// to be on the safe side, constness and references are stripped away,
// though the type should always be plain
template <class Arg, class Open>
struct return_type<lambda_functor<Arg>, Open> {
typedef typename return_type<Arg, Open>::type type;
};
// take care of the unavoidable instantiation for nullary case
template<class Act, class Other> struct return_type_2_prot<Act, Other, null_type> {
typedef null_type type;
template <class Arg, class Open>
struct return_type<const lambda_functor<Arg>, Open> {
typedef typename return_type<Arg, Open>::type type;
};
// take care of the unavoidable instantiation for nullary case
template<class Act, class Other> struct return_type_2_prot<Act, null_type, Other> {
typedef null_type type;
template <class Arg, class Open>
struct return_type<lambda_functor<Arg>&, Open> {
typedef typename return_type<Arg, Open>::type type;
};
template <class Arg, class Open>
struct return_type<const lambda_functor<Arg>&, Open> {
typedef typename return_type<Arg, Open>::type type;
};
// comma is a special case, as the user defined operator can return
// an lvalue (reference) too, hence it must be handled at this level.
template<class A, class B>
struct return_type_2_comma
{
typedef typename boost::remove_reference<A>::type non_ref_A;
typedef typename boost::remove_reference<B>::type non_ref_B;
typedef typename
detail::IF<
is_protectable<other_action<comma_action> >::value && // it is protectable
(is_lambda_functor<A>::value || is_lambda_functor<B>::value),
lambda_functor<
lambda_functor_base<
other_action<comma_action>,
tuple<typename detail::protect_conversion<A>::type,
typename detail::protect_conversion<B>::type>
>
>,
typename
return_type_2<other_action<comma_action>, non_ref_A, non_ref_B>::type
>::RET type1;
// if no user defined return_type_2 (or plain_return_type_2) specialization
// matches, then return the righthand argument
typedef typename
detail::IF<
boost::is_same<type1, detail::unspecified>::value,
B,
type1
>::RET type;
// placeholders
// to be on the safe side, constness and references are stripped away,
// though the type should always be plain
template<int I, class Open>
struct return_type<const placeholder<I>, Open> {
typedef typename return_type<placeholder<I>, Open>::type type;
};
template<int I, class Open>
struct return_type<placeholder<I>&, Open> {
typedef typename return_type<placeholder<I>, Open>::type type;
};
template<int I, class Open>
struct return_type<const placeholder<I>&, Open> {
typedef typename return_type<placeholder<I>, Open>::type type;
};
// currently there are no protectable actions with > 2 args
template<class Act, class Args> struct return_type_N_prot {
typedef typename return_type_N<Act, Args>::type type;
template <class Open>
struct return_type<placeholder<FIRST>, Open> {
typedef typename Open::type1 type;
};
// take care of the unavoidable instantiation for nullary case
template<class Act> struct return_type_N_prot<Act, null_type> {
typedef null_type type;
template <class Open>
struct return_type<placeholder<SECOND>, Open> {
typedef typename Open::type2 type;
};
template <class Open>
struct return_type<placeholder<THIRD>, Open> {
typedef typename Open::type2 type;
};
// the exception placeholder deduction, the third placeholder slot
// is reused
template <class Open>
struct return_type<placeholder<EXCEPTION>, Open> {
typedef typename Open::type3 type;
};
// handle different kind of actions ------------------------
// function action: this covers all arities:
// If a function object overloads operator(), the return type could depend
// on the argument types. This is not taken into consideration.
// use the return type given in the bind invocation as bind<Ret>(...)
template<class A, class Ret>
struct return_type_1<function_action<1, Ret>, A > {
typedef Ret type;
};
template<class A, class B, class Ret>
struct return_type_2<function_action<2, Ret>, A, B > {
typedef Ret type;
};
template<int I, class Args, class Ret>
struct return_type_N<function_action<I, Ret>, Args> {
typedef Ret type;
};
// ::result_type support
namespace detail
{
BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type)
template<class F> struct get_result_type
{
typedef typename F::result_type type;
};
template<class F, class A> struct get_sig
{
typedef typename function_adaptor<F>::template sig<A>::type type;
};
} // namespace detail
// Ret is detail::unspecified, so try to deduce return type
template<class A>
struct return_type_1<function_action<1, detail::unspecified>, A > {
typedef typename function_adaptor_with_actuals<typename tuple<A>::inherited>::type type;
};
template<class A, class B>
struct return_type_2<function_action<2, detail::unspecified>, A, B > {
typedef typename function_adaptor_with_actuals<typename tuple<A, B>::inherited>::type type;
};
template<int I, class Args>
struct return_type_N<function_action<I, detail::unspecified>, Args > {
typedef typename function_adaptor_with_actuals<Args>::type type;
};
// in the case of function action, the first element in Args is
// some type of function
typedef typename Args::head_type Func;
typedef typename detail::remove_reference_and_cv<Func>::type plain_Func;
public:
// pass the function to function_adaptor, and get the return type from
// that
typedef typename detail::IF<
detail::has_result_type<plain_Func>::value,
detail::get_result_type<plain_Func>,
detail::get_sig<plain_Func, Args>
>::RET::type type;
namespace detail {
template <class T, class Open>
struct map_to_return_types {
typedef typename return_type<
typename boost::tuples::access_traits<typename T::head_type>::const_type,
Open
>::type ret_type;
// const and reference is added, so that specializations for return_type_1
// become easier (we can rely on the Args always being references, so the
// number of specializations doesn't explode.
// Note! If T is already a reference to nonconst, it will remain that way
// To return type deduction, const T& is the same as rvalue T
typedef typename boost::add_reference<
typename boost::add_const<ret_type>::type
>::type ref_to_const_ret_type;
typedef boost::tuples::cons<
ref_to_const_ret_type,
typename map_to_return_types<typename T::tail_type, Open>::type
> type;
};
template <class Open>
struct map_to_return_types<boost::tuples::null_type, Open> {
typedef boost::tuples::null_type type;
};
} // end detail
// general unary and binary actions
template<class Act, class Args, int Code, class Open>
struct return_type<lambda_functor_args<action<1, Act>, Args, Code>, Open> {
typedef typename return_type<
typename detail::tuple_element_as_reference<0, Args>::type,
Open
>::type A_type;
// const and reference is added, so that specializations for return_type_1
// become easier (we can rely on the Args always being references, so the
// number of specializations doesn't explode.
// Note! If T is already a reference to nonconst, it will remain that way
// To return type deduction, const T& is the same as rvalue T
typedef typename boost::add_reference<
typename boost::add_const<A_type>::type
>::type refc_A_type;
public:
typedef typename
detail::IF_type<
detail::is_protectable_action<Act>::value,
return_type_1_protect<Act, refc_A_type>,
return_type_1<Act, refc_A_type>
>::type type;
};
template<class Act, class Args, int Code, class Open>
class return_type<lambda_functor_args<action<2, Act>, Args, Code>, Open> {
typedef typename return_type<
typename detail::tuple_element_as_reference<0, Args>::type,
Open
>::type A_type;
typedef typename return_type<
typename detail::tuple_element_as_reference<1, Args>::type,
Open
>::type B_type;
typedef typename boost::add_reference<
typename boost::add_const<A_type>::type
>::type refc_A_type;
typedef typename boost::add_reference<
typename boost::add_const<B_type>::type
>::type refc_B_type;
public:
typedef typename
detail::IF_type<
detail::is_protectable_action<Act>::value,
return_type_2_protect<Act, refc_A_type, refc_B_type>,
return_type_2<Act, refc_A_type, refc_B_type>
>::type type;
};
// This is the general case. Will match any action with arity >= 3
template<int I, class Act, class Args, int Code, class Open>
class return_type<lambda_functor_args<action<I, Act>, Args, Code>, Open> {
typedef typename detail::map_to_return_types<Args, Open>::type actual_args;
public:
typedef typename return_type_N<Act, actual_args>::type type;
};
// template<class Act, class Args, int Code, class Open>
// class return_type<lambda_functor_args<action<3, Act>, Args, Code>, Open> {
// typedef typename return_type<
// typename detail::tuple_element_as_reference<0, Args>::type,
// Open
// >::type A_type;
// typedef typename return_type<
// typename detail::tuple_element_as_reference<1, Args>::type,
// Open
// >::type B_type;
// typedef typename return_type<
// typename detail::tuple_element_as_reference<2, Args>::type,
// Open
// >::type C_type;
// typedef typename boost::add_reference<
// typename boost::add_const<A_type>::type
// >::type refc_A_type;
// typedef typename boost::add_reference<
// typename boost::add_const<B_type>::type
// >::type refc_B_type;
// typedef typename boost::add_reference<
// typename boost::add_const<C_type>::type
// >::type refc_C_type;
// public:
// // no 3- or higher ary protectable actions exist, no need to check
// typedef typename return_type_3<Act, refc_A_type, refc_B_type, refc_C_type>::type type;
// };
// // 4 args or more (must be a function action)
// template<int I, class Act, class Args, int Code, class Open>
// class return_type<lambda_functor_args<action<I, Act>, Args, Code>, Open> {
// typedef typename return_type<
// typename detail::tuple_element_as_reference<0, Args>::type,
// Open
// >::type A_type;
// typedef typename return_type<
// typename detail::tuple_element_as_reference<1, Args>::type,
// Open
// >::type B_type;
// typedef typename return_type<
// typename detail::tuple_element_as_reference<2, Args>::type,
// Open
// >::type C_type;
// typedef typename return_type<
// typename detail::tuple_element_as_reference<3, Args>::type,
// Open
// >::type D_type;
// typedef typename boost::add_reference<
// typename boost::add_const<A_type>::type
// >::type refc_A_type;
// typedef typename boost::add_reference<
// typename boost::add_const<B_type>::type
// >::type refc_B_type;
// typedef typename boost::add_reference<
// typename boost::add_const<C_type>::type
// >::type refc_C_type;
// typedef typename boost::add_reference<
// typename boost::add_const<D_type>::type
// >::type refc_D_type;
// public:
// typedef typename return_type_4<Act, refc_A_type, refc_B_type, refc_C_type, refc_D_type>::type type;
// };
// special case for comma action:
// As the return type needs to be exactly the type of the rightmost argument,
// we cannot add a const and reference (we need to preserve rvalueness)
// note, that return_type_2_protect is still called, so user can overload
// return_type_2 for user defined types.
template<class Args, int Code, class Open>
class return_type<lambda_functor_args<action<2, other_action<comma_action> >, Args, Code>, Open> {
typedef typename return_type<
typename detail::tuple_element_as_reference<0, Args>::type,
Open
>::type A_type;
typedef typename return_type<
typename detail::tuple_element_as_reference<1, Args>::type,
Open
>::type B_type;
public:
typedef typename
return_type_2_protect<other_action<comma_action>, A_type, B_type>::type type;
};
// protect action:
// the return type is the lambda_functor wrapped inside protect
template<class Args, int Code, class Open>
struct return_type<lambda_functor_args<action<1, protect_action>, Args, Code>, Open> {
typedef typename detail::tuple_element_as_reference<0,Args>::type type;
};
// curry action:
template<class Args, int Code, class Open>
struct return_type<lambda_functor_args<action<3, curry_action<1> >,
Args, Code>, Open> {
// take one stored argument type and push it to the open args
typedef typename
return_type<
typename boost::tuples::element<0,Args>::type,
open_args<typename boost::tuples::element<1,Args>::type,
typename Open::type1,
typename Open::type2> >::type
type;
};
template<class Args, int Code, class Open>
struct return_type<lambda_functor_args<action<4, curry_action<1> >, Args, Code>, Open> {
// take one stored argument type and push it to the open args
typedef typename
return_type<typename boost::tuples::element<0,Args>::type,
open_args<typename boost::tuples::element<1,Args>::type,
typename Open::type1,
typename Open::type2> >::type
type;
};
template<class Args, int Code, class Open>
struct return_type<lambda_functor_args<action<4, curry_action<2> >, Args, Code>, Open> {
// take two stored arguments type and push them to the open args
typedef typename
return_type<typename boost::tuples::element<0,Args>::type,
open_args<typename boost::tuples::element<1,Args>::type,
typename boost::tuples::element<2,Args>::type,
typename Open::type1> >::type
type;
};
// // 3 arguments or more ---------------------------------------------
// // this must be a function_action. Note that the previous unary and binary
// // specalisations take care of nullary and unary function adaptors, that is,
// // unary and binary actions.
// // Since function_actions determine the return type based on the function
// // object only, we can ignore the arguments and reuse return_type_1.
// template <int I, class Act, class Args, int Code, class Open>
// class return_type<lambda_functor_args<action<I, Act>, Args, Code>, Open> {
// typedef typename return_type<
// typename detail::tuple_element_as_reference<0, Args>::type,
// Open
// >::type A_type;
// // reference is added, so that specializations for return_type_1
// // become easier.
// typedef typename boost::add_reference<
// typename boost::add_const<A_type>::type
// >::type refc_A_type;
// public:
// typedef typename return_type_1_protect<Act, refc_A_type>::type type;
// };
// The explicit return type action case, it is unary
template<class RET, class Args, int Code, class Open>
struct return_type<
lambda_functor_args<
action<1, explicit_return_type_action<RET> >,
Args,
Code>,
Open>
{
typedef RET type;
};
// return types of control constructs (all return void)
template<class Act, class Args, int Code, class Open>
struct return_type<lambda_functor_args<action<1, return_void_action<Act> >,
Args, Code>, Open >
{
typedef void type;
};
template<class Act, class Args, int Code, class Open>
struct return_type<lambda_functor_args<action<2, return_void_action<Act> >,
Args, Code>, Open >
{
typedef void type;
};
template<class Act, class Args, int Code, class Open>
struct return_type<lambda_functor_args<action<3, return_void_action<Act> >,
Args, Code>, Open >
{
typedef void type;
};
template<int I, class Act, class Args, int Code, class Open>
struct return_type<lambda_functor_args<action<I, return_void_action<Act> >,
Args, Code>, Open >
{
typedef void type;
};

View File

@@ -1,12 +1,17 @@
// -- select_functions.hpp -- Boost Lambda Library --------------------------
// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
//
// 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)
// 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.
//
// For more information, see http://www.boost.org
// 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://lambda.cs.utu.fi
#ifndef BOOST_LAMBDA_SELECT_FUNCTIONS_HPP
@@ -16,29 +21,104 @@ namespace boost {
namespace lambda {
namespace detail {
// selector<ArityCode>::select functions ---------------------------------
// called from select functions
template <int Code> struct selector;
// The primary template covers all lambda functors with the EXCEPTION
// placeholder as a subexpression
template <int Code> struct selector {
template<class RET, class Op, class A, class B, class C>
static RET select(Op& op, A& a, B& b, C& c) {
return op.template ret_call<RET>(a, b, c);
}
};
// The cases cover all other placeholders
template <> struct selector<NONE> {
template<class RET, class Op, class A, class B, class C>
static RET select(Op& op, A& a, B& b, C& c) {
return op.template ret_call<RET>();
}
};
template <> struct selector<FIRST> {
template<class RET, class Op, class A, class B, class C>
static RET select(Op& op, A& a, B& b, C& c) {
return op.template ret_call<RET>(a);
}
};
template <> struct selector<SECOND> {
template<class RET, class Op, class A, class B, class C>
static RET select(Op& op, A& a, B& b, C& c) {
return op.template ret_call<RET>(a, b);
}
};
template <> struct selector<THIRD> {
template<class RET, class Op, class A, class B, class C>
static RET select(Op& op, A& a, B& b, C& c) {
return op.template ret_call<RET>(a, b, c);
}
};
// select functions -------------------------------
template<class Any, CALL_TEMPLATE_ARGS>
inline Any& select(Any& any, CALL_FORMAL_ARGS) { CALL_USE_ARGS; return any; }
template<class Any, class A, class B, class C>
inline Any& select(Any& any, A&, B&, C&) { return any; }
template<class Arg, CALL_TEMPLATE_ARGS>
inline typename Arg::template sig<tuple<CALL_REFERENCE_TYPES> >::type
select ( const lambda_functor<Arg>& op, CALL_FORMAL_ARGS ) {
return op.template call<
typename Arg::template sig<tuple<CALL_REFERENCE_TYPES> >::type
>(CALL_ACTUAL_ARGS);
template<class A, class B, class C>
inline A& select(const lambda_functor<placeholder<FIRST> >&, A& a, B&, C&) {
return a;
}
template<class Arg, CALL_TEMPLATE_ARGS>
inline typename Arg::template sig<tuple<CALL_REFERENCE_TYPES> >::type
select ( lambda_functor<Arg>& op, CALL_FORMAL_ARGS) {
return op.template call<
typename Arg::template sig<tuple<CALL_REFERENCE_TYPES> >::type
>(CALL_ACTUAL_ARGS);
template<class A, class B, class C>
inline A& select(lambda_functor<placeholder<FIRST> >&, A& a, B&, C&) {
return a;
}
template<class A, class B, class C>
inline B& select(const lambda_functor<placeholder<SECOND> >&, A&, B& b, C&) {
return b;
}
template<class A, class B, class C>
inline B& select(lambda_functor<placeholder<SECOND> >&, A&, B& b, C&) {
return b;
}
template<class A, class B, class C>
inline C& select(const lambda_functor<placeholder<THIRD> >&, A&, B&, C& c) {
return c;
}
template<class A, class B, class C>
inline C& select(lambda_functor<placeholder<THIRD> >&, A&, B&, C& c) {
return c;
}
// Exception placeholder reuses the third argument position
template<class A, class B, class C>
inline C& select(const lambda_functor<placeholder<EXCEPTION> >&, A&, B&, C& c)
{
return c;
}
template<class A, class B, class C>
inline C& select(lambda_functor<placeholder<EXCEPTION> >&, A&, B&, C& c) {
return c;
}
template<class Arg, class A, class B, class C>
inline typename return_type<lambda_functor<Arg>, open_args<A&, B&, C&> >::type
select ( const lambda_functor<Arg>& op, A& a, B& b, C& c ) {
return selector<dig_arity<Arg>::value>::template select<typename return_type<lambda_functor<Arg>, open_args<A&, B&, C&> >::type>(op, a, b, c);
}
template<class Arg, class A, class B, class C>
inline typename return_type<lambda_functor<Arg>, open_args<A&, B&, C&> >::type
select ( lambda_functor<Arg>& op, A& a, B& b, C& c) {
return selector<dig_arity<Arg>::value>::template select<typename return_type<lambda_functor<Arg>, open_args<A&, B&, C&> >::type>(op, a, b, c);
}
// ------------------------------------------------------------------------
// select functions where the return type is explicitly given
// selector functions where the return type is explicitly given
// Note: on many functions, this return type is just discarded.
// The select functions are inside a class template, and the return type
// is a class template argument.
@@ -46,24 +126,62 @@ select ( lambda_functor<Arg>& op, CALL_FORMAL_ARGS) {
// specified template parameter.
// However, this resulted in ambiguous calls (at least with gcc 2.95.2
// and edg 2.44). Not sure whether the compilers were right or wrong.
template<class RET> struct r_select {
template<class RET> struct ret_selector
{
// Any == RET
template<class Any, CALL_TEMPLATE_ARGS>
static
inline RET go (Any& any, CALL_FORMAL_ARGS) { CALL_USE_ARGS; return any; }
// TODO: add checks that RET is of correct type
template<class Any, class A, class B, class C>
static Any& select(Any& any, A&, B&, C&) { return any; }
template<class Arg, CALL_TEMPLATE_ARGS>
static
inline RET go (const lambda_functor<Arg>& op, CALL_FORMAL_ARGS ) {
return op.template call<RET>(CALL_ACTUAL_ARGS);
template<class A, class B, class C>
static A& select(const lambda_functor<placeholder<FIRST> >&, A& a, B&, C&) {
return a;
}
template<class Arg, CALL_TEMPLATE_ARGS>
static
inline RET go (lambda_functor<Arg>& op, CALL_FORMAL_ARGS ) {
return op.template call<RET>(CALL_ACTUAL_ARGS);
template<class A, class B, class C>
static A& select(lambda_functor<placeholder<FIRST> >&, A& a, B&, C&) {
return a;
}
template<class A, class B, class C>
static B& select(const lambda_functor<placeholder<SECOND> >&, A&, B& b, C&) { return b;
}
template<class A, class B, class C>
static B& select(lambda_functor<placeholder<SECOND> >&, A&, B& b, C&) {
return b;
}
template<class A, class B, class C>
static C& select(const lambda_functor<placeholder<THIRD> >&, A&, B&, C& c) {
return c;
}
template<class A, class B, class C>
static C& select(lambda_functor<placeholder<THIRD> >&, A&, B&, C& c) {
return c;
}
// Exception placeholder reuses the third argument position
template<class A, class B, class C>
static inline C&
select(const lambda_functor<placeholder<EXCEPTION> >&, A&, B&, C& c) {
return c;
}
template<class A, class B, class C>
static inline C&
select(lambda_functor<placeholder<EXCEPTION> >&, A&, B&, C& c) {
return c;
}
template<class Arg, class A, class B, class C>
static RET select (const lambda_functor<Arg>& op, A& a, B& b, C& c ) {
return selector<dig_arity<Arg>::value>::template select<RET>(op, a, b, c);
}
template<class Arg, class A, class B, class C>
static RET select (lambda_functor<Arg>& op, A& a, B& b, C& c ) {
return selector<dig_arity<Arg>::value>::template select<RET>(op, a, b, c);
}
};

View File

@@ -1,27 +0,0 @@
// Boost Lambda Library suppress_unused.hpp -----------------------------
//
// Copyright (C) 2009 Steven Watanabe
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see www.boost.org
// ------------------------------------------------------------
#ifndef BOOST_LAMBDA_SUPPRESS_UNUSED_HPP
#define BOOST_LAMBDA_SUPPRESS_UNUSED_HPP
namespace boost {
namespace lambda {
namespace detail {
template<class T>
inline void suppress_unused_variable_warnings(const T&) {}
}
}
}
#endif

View File

@@ -0,0 +1,539 @@
// Boost Lambda Library -- switch.hpp -----------------------------------
//
// Copyright (C) 2000 Gary Powell (gary.powell@sierra.com)
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
//
// 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 www.boost.org
// --------------------------------------------------------------------------
#if !defined(BOOST_LAMBDA_SWITCH_HPP)
#define BOOST_LAMBDA_SWITCH_HPP
#include "boost/preprocessor/enum_shifted_params.hpp"
#include "boost/preprocessor/repeat_2nd.hpp"
#include "boost/preprocessor/tuple.hpp"
namespace boost {
namespace lambda {
// Switch actions
template <class Switch1 = null_type, class Switch2 = null_type,
class Switch3 = null_type, class Switch4 = null_type,
class Switch5 = null_type, class Switch6 = null_type,
class Switch7 = null_type, class Switch8 = null_type,
class Switch9 = null_type>
struct switch_action {};
namespace detail {
// templates to represent special lambda functors for the cases in
// switch statements
template <int Value> struct case_label {};
struct default_label {};
template<class Type> struct switch_case_tag {};
// a normal case is represented as:
// tagged_lambda_functor<switch_case_tag<case_label<N> > >, LambdaFunctor>
// the default case as:
// tagged_lambda_functor<switch_case_tag<default_label> >, LambdaFunctor>
} // end detail
/// create switch_case_tag tagged_lambda_functors
template <int CaseValue, class Arg>
inline const
tagged_lambda_functor<
detail::switch_case_tag<detail::case_label<CaseValue> >,
lambda_functor<Arg>
>
case_statement(const lambda_functor<Arg>& a) {
return
tagged_lambda_functor<
detail::switch_case_tag<detail::case_label<CaseValue> >,
lambda_functor<Arg>
>(a);
}
// No case body case.
template <int CaseValue>
inline const
tagged_lambda_functor<
detail::switch_case_tag<detail::case_label<CaseValue> >,
lambda_functor<
lambda_functor_args<
action<0, return_void_action<do_nothing_action> >,
null_type,
NONE
>
>
>
case_statement() {
return
tagged_lambda_functor<
detail::switch_case_tag<detail::case_label<CaseValue> >,
lambda_functor<
lambda_functor_args<
action<0, return_void_action<do_nothing_action> >,
null_type,
NONE
>
>
> () ;
}
// default label
template <class Arg>
inline const
tagged_lambda_functor<
detail::switch_case_tag<detail::default_label>,
lambda_functor<Arg>
>
default_statement(const lambda_functor<Arg>& a) {
return
tagged_lambda_functor<
detail::switch_case_tag<detail::default_label>,
lambda_functor<Arg>
>(a);
}
// default lable, no case body case.
inline const
tagged_lambda_functor<
detail::switch_case_tag<detail::default_label>,
lambda_functor<
lambda_functor_args<
action<0, return_void_action<do_nothing_action> >,
null_type,
NONE
>
>
>
default_statement() {
return
tagged_lambda_functor<
detail::switch_case_tag<detail::default_label>,
lambda_functor<
lambda_functor_args<
action<0, return_void_action<do_nothing_action> >,
null_type,
NONE
>
>
> () ;
}
// Specializations for lambda_functor_base of case_statement -----------------
// 0 case type:
// useless (just the condition part) but provided for completeness.
template<class Args>
class
lambda_functor_base<
action<1, return_void_action<switch_action< > > >,
Args
>
{
public:
Args args;
public:
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET, class A, class B, class C>
RET call(A& a, B& b, C& c) const {
detail::select(::boost::tuples::get<1>(args), a, b, c);
}
};
// 1 case type:
// template<class Args, int Case1>
// class
// lambda_functor_base<
// action<
// 2,
// return_void_action<switch_action<detail::case_label<Case1> > >
// >,
// Args
// >
// {
// Args args;
// public:
// explicit lambda_functor_base(const Args& a) : args(a) {}
// template<class RET, class A, class B, class C>
// RET call(A& a, B& b, C& c) const {
// switch( detail::select(::boost::tuples::get<0>(args), a, b, c) )
// {
// case Case1:
// detail::select(::boost::tuples::get<1>(args), a, b, c);
// break;
// }
// }
// };
// switch with default being the sole label - doesn't make much sense but
// it is there for completeness
// template<class Args>
// class
// lambda_functor_base<
// action<
// 2,
// return_void_action<switch_action<detail::default_label> >
// >,
// Args
// >
// {
// Args args;
// public:
// explicit lambda_functor_base(const Args& a) : args(a) {}
//
// template<class RET, class A, class B, class C>
// RET call(A& a, B& b, C& c) const {
// switch( detail::select(::boost::tuples::get<0>(args), a, b, c) )
// {
// default:
// detail::select(::boost::tuples::get<1>(args), a, b, c);
// break;
// }
// }
// };
// // 2 case type:
// The different specializations are generated with Vesa Karvonen's
// preprocessor library.
// This is just a comment to show what the generated classes look like
// template<class Args, int Case1, int Case2>
// class
// lambda_functor_base<
// action<3,
// return_void_action<
// switch_action<
// detail::case_label<Case1>,
// detail::case_label<Case2>
// >
// >
// >,
// Args
// >
// {
// Args args;
// public:
// explicit lambda_functor_base(const Args& a) : args(a) {}
// template<class RET, class A, class B, class C>
// RET call(A& a, B& b, C& c) const {
// switch( detail::select(::boost::tuples::get<0>(args), a, b, c) )
// {
// case Case1:
// detail::select(::boost::tuples::get<1>(args), a, b, c);
// break;
// case Case2:
// detail::select(::boost::tuples::get<2>(args), a, b, c);
// break;
// }
// }
// };
// template<class Args, int Case1>
// class
// lambda_functor_base<
// action<3,
// return_void_action<
// switch_action<
// detail::case_label<Case1>,
// detail::default_label
// >
// >
// >,
// Args
// >
// {
// Args args;
// public:
// explicit lambda_functor_base(const Args& a) : args(a) {}
// template<class RET, class A, class B, class C>
// RET call(A& a, B& b, C& c) const {
// switch( detail::select(::boost::tuples::get<0>(args), a, b, c) )
// {
// case Case1:
// detail::select(::boost::tuples::get<1>(args), a, b, c);
// break;
// default:
// detail::select(::boost::tuples::get<2>(args), a, b, c);
// break;
// }
// }
// };
// -------------------------
// Some helper preprocessor macros ---------------------------------
// BOOST_LAMBDA_A_I_LIST(N, X) is a list of form X0, X1, ..., XN
// BOOST_LAMBDA_A_I_B_LIST(N, X, Y) is a list of form X0 Y, X1 Y, ..., XN Y
// BOOST_LAMBDA_A_I_B_LIST(N, X, Y) is a list of form X0 Y0, X1 Y1, ..., XN YN
#define BOOST_LAMBDA_A_I(i, A) \
BOOST_PP_COMMA_IF(i) BOOST_PP_CAT(A,i)
#define BOOST_LAMBDA_A_I_B(i, T) \
BOOST_PP_COMMA_IF(i) BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2,0,T),i) BOOST_PP_TUPLE_ELEM(2,1,T)
#define BOOST_LAMBDA_A_I_B_I(i, A, B) \
BOOST_PP_COMMA_IF(i) \
BOOST_PP_CAT(A,i) \
BOOST_PP_CAT(B,i)
#define BOOST_LAMBDA_A_I_LIST(i, A) \
BOOST_PP_REPEAT(i,BOOST_LAMBDA_A_I, A)
#define BOOST_LAMBDA_A_I_B_LIST(i, A, B) \
BOOST_PP_REPEAT(i,BOOST_LAMBDA_A_I_B, (A,B))
//#define BOOST_LAMBDA_A_I_B_I_LIST(i, A, B) \
//BOOST_PP_REPEAT(i, BOOST_LAMBDA_A_I_B_I, A)
// Switch related macros -------------------------------------------
#define BOOST_LAMBDA_SWITCH_CASE_BLOCK(N, A) \
case Case##N: \
detail::select(::boost::tuples::get<BOOST_PP_INC(N)>(args), a, b, c); \
break;
#define BOOST_LAMBDA_SWITCH_CASE_BLOCK_LIST(N) \
BOOST_PP_REPEAT(N, BOOST_LAMBDA_SWITCH_CASE_BLOCK, FOO)
// 2 case type:
#define BOOST_LAMBDA_SWITCH_NO_DEFAULT_CASE(N) \
template<class Args, BOOST_LAMBDA_A_I_LIST(N, int Case)> \
class \
lambda_functor_base< \
action<BOOST_PP_INC(N), \
return_void_action< \
switch_action< \
BOOST_LAMBDA_A_I_B_LIST(N, detail::case_label<Case,>) \
> \
> \
>, \
Args \
> \
{ \
public: \
Args args; \
public: \
explicit lambda_functor_base(const Args& a) : args(a) {} \
\
template<class RET, class A, class B, class C> \
RET call(A& a, B& b, C& c) const { \
switch( detail::select(::boost::tuples::get<0>(args), a, b, c) ) \
{ \
BOOST_LAMBDA_SWITCH_CASE_BLOCK_LIST(N) \
} \
} \
};
#define BOOST_LAMBDA_SWITCH_WITH_DEFAULT_CASE(N) \
template< \
class Args BOOST_PP_COMMA_IF(BOOST_PP_DEC(N)) \
BOOST_LAMBDA_A_I_LIST(BOOST_PP_DEC(N), int Case) \
> \
class \
lambda_functor_base< \
action<BOOST_PP_INC(N), \
return_void_action< \
switch_action< \
BOOST_LAMBDA_A_I_B_LIST(BOOST_PP_DEC(N), \
detail::case_label<Case, >) \
BOOST_PP_COMMA_IF(BOOST_PP_DEC(N)) \
detail::default_label \
> \
> \
>, \
Args \
> \
{ \
public: \
Args args; \
public: \
explicit lambda_functor_base(const Args& a) : args(a) {} \
\
template<class RET, class A, class B, class C> \
RET call(A& a, B& b, C& c) const { \
switch( detail::select(::boost::tuples::get<0>(args), a, b, c) ) \
{ \
BOOST_LAMBDA_SWITCH_CASE_BLOCK_LIST(BOOST_PP_DEC(N)) \
default: \
detail::select(::boost::tuples::get<N>(args), a, b, c); \
break; \
} \
} \
};
// switch_statement bind functions -------------------------------------
// The zero argument case, for completeness sake
inline const
lambda_functor<
lambda_functor_args<
action<0, return_void_action<do_nothing_action> >,
null_type,
NONE
>
>
switch_statement() {
return
lambda_functor<
lambda_functor_args<
action<0, return_void_action<do_nothing_action> >,
null_type,
NONE
>
>
( null_type());
}
// 1 argument case, this is useless as well, just the condition part
template <class TestArg>
inline const
lambda_functor<
lambda_functor_args<
action<1, return_void_action<switch_action<> > >,
tuple<lambda_functor<TestArg> >,
dig_arity<TestArg>::value
>
>
switch_statement(const lambda_functor<TestArg>& a1) {
return
lambda_functor<
lambda_functor_args<
action<1, return_void_action<switch_action<> > >,
tuple< lambda_functor<TestArg> >,
dig_arity<TestArg >::value
>
>
( tuple<lambda_functor<TestArg> >(a1));
}
#define HELPER(N, FOO) \
BOOST_PP_COMMA_IF(N) \
BOOST_PP_CAT( \
const tagged_lambda_functor<detail::switch_case_tag<TagData, \
N>) \
BOOST_PP_COMMA() Arg##N>& a##N
#define HELPER_LIST(N) BOOST_PP_REPEAT(N, HELPER, FOO)
#define BOOST_LAMBDA_SWITCH_STATEMENT(N) \
template <class TestArg, \
BOOST_LAMBDA_A_I_LIST(N, class TagData), \
BOOST_LAMBDA_A_I_LIST(N, class Arg)> \
inline const \
lambda_functor< \
lambda_functor_args< \
action<BOOST_PP_INC(N), \
return_void_action< \
switch_action< \
BOOST_LAMBDA_A_I_LIST(N, TagData) \
> \
> \
>, \
tuple<lambda_functor<TestArg>, BOOST_LAMBDA_A_I_LIST(N, Arg)>, \
combine_arities< TestArg, BOOST_LAMBDA_A_I_LIST(N, Arg)>::value \
> \
> \
switch_statement( \
const lambda_functor<TestArg>& ta, \
HELPER_LIST(N) \
) \
{ \
return \
lambda_functor< \
lambda_functor_args< \
action<BOOST_PP_INC(N), \
return_void_action< \
switch_action< \
BOOST_LAMBDA_A_I_LIST(N, TagData) \
> \
> \
>, \
tuple<lambda_functor<TestArg>, BOOST_LAMBDA_A_I_LIST(N, Arg)>, \
combine_arities< TestArg, BOOST_LAMBDA_A_I_LIST(N, Arg)>::value \
> \
> \
( tuple<lambda_functor<TestArg>, BOOST_LAMBDA_A_I_LIST(N, Arg)> \
(ta, BOOST_LAMBDA_A_I_LIST(N, a) )); \
}
// Here's the actual generation
#define BOOST_LAMBDA_SWITCH(N) \
BOOST_LAMBDA_SWITCH_NO_DEFAULT_CASE(N) \
BOOST_LAMBDA_SWITCH_WITH_DEFAULT_CASE(N)
// Use this to avoid case 0, these macros work only from case 1 upwards
#define BOOST_LAMBDA_SWITCH_HELPER(N, A) \
BOOST_LAMBDA_SWITCH( BOOST_PP_INC(N) )
// Use this to avoid cases 0 and 1, these macros work only from case 2 upwards
#define BOOST_LAMBDA_SWITCH_STATEMENT_HELPER(N, A) \
BOOST_LAMBDA_SWITCH_STATEMENT(BOOST_PP_INC(N))
// up to 9 cases supported (counting default:)
BOOST_PP_REPEAT_2ND(9,BOOST_LAMBDA_SWITCH_HELPER,FOO)
BOOST_PP_REPEAT_2ND(9,BOOST_LAMBDA_SWITCH_STATEMENT_HELPER,FOO)
} // namespace lambda
} // namespace boost
#undef HELPER
#undef HELPER_LIST
#undef BOOST_LAMBDA_SWITCH_HELPER
#undef BOOST_LAMBDA_SWITCH
#undef BOOST_LAMBDA_SWITCH_NO_DEFAULT_CASE
#undef BOOST_LAMBDA_SWITCH_WITH_DEFAULT_CASE
#undef BOOST_LAMBDA_SWITCH_CASE_BLOCK
#undef BOOST_LAMBDA_SWITCH_CASE_BLOCK_LIST
#undef BOOST_LAMBDA_SWITCH_STATEMENT
#undef BOOST_LAMBDA_SWITCH_STATEMENT_HELPER
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,462 +0,0 @@
// Boost Lambda Library -- if.hpp ------------------------------------------
// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2000 Gary Powell (powellg@amazon.com)
// Copyright (C) 2001-2002 Joel de Guzman
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see www.boost.org
// --------------------------------------------------------------------------
#if !defined(BOOST_LAMBDA_IF_HPP)
#define BOOST_LAMBDA_IF_HPP
#include "boost/lambda/core.hpp"
// Arithmetic type promotion needed for if_then_else_return
#include "boost/lambda/detail/operator_actions.hpp"
#include "boost/lambda/detail/operator_return_type_traits.hpp"
namespace boost {
namespace lambda {
// -- if control construct actions ----------------------
class ifthen_action {};
class ifthenelse_action {};
class ifthenelsereturn_action {};
// Specialization for if_then.
template<class Args>
class
lambda_functor_base<ifthen_action, Args> {
public:
Args args;
template <class T> struct sig { typedef void type; };
public:
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET, CALL_TEMPLATE_ARGS>
RET call(CALL_FORMAL_ARGS) const {
if (detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS))
detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS);
}
};
// If Then
template <class Arg1, class Arg2>
inline const
lambda_functor<
lambda_functor_base<
ifthen_action,
tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >
>
>
if_then(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2) {
return
lambda_functor_base<
ifthen_action,
tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >
>
( tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >(a1, a2) );
}
// Specialization for if_then_else.
template<class Args>
class
lambda_functor_base<ifthenelse_action, Args> {
public:
Args args;
template <class T> struct sig { typedef void type; };
public:
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET, CALL_TEMPLATE_ARGS>
RET call(CALL_FORMAL_ARGS) const {
if (detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS))
detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS);
else
detail::select(boost::tuples::get<2>(args), CALL_ACTUAL_ARGS);
}
};
// If then else
template <class Arg1, class Arg2, class Arg3>
inline const
lambda_functor<
lambda_functor_base<
ifthenelse_action,
tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, lambda_functor<Arg3> >
>
>
if_then_else(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2,
const lambda_functor<Arg3>& a3) {
return
lambda_functor_base<
ifthenelse_action,
tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, lambda_functor<Arg3> >
>
(tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, lambda_functor<Arg3> >
(a1, a2, a3) );
}
// Our version of operator?:()
template <class Arg1, class Arg2, class Arg3>
inline const
lambda_functor<
lambda_functor_base<
other_action<ifthenelsereturn_action>,
tuple<lambda_functor<Arg1>,
typename const_copy_argument<Arg2>::type,
typename const_copy_argument<Arg3>::type>
>
>
if_then_else_return(const lambda_functor<Arg1>& a1,
const Arg2 & a2,
const Arg3 & a3) {
return
lambda_functor_base<
other_action<ifthenelsereturn_action>,
tuple<lambda_functor<Arg1>,
typename const_copy_argument<Arg2>::type,
typename const_copy_argument<Arg3>::type>
> ( tuple<lambda_functor<Arg1>,
typename const_copy_argument<Arg2>::type,
typename const_copy_argument<Arg3>::type> (a1, a2, a3) );
}
namespace detail {
// return type specialization for conditional expression begins -----------
// start reading below and move upwards
// PHASE 6:1
// check if A is conbertible to B and B to A
template<int Phase, bool AtoB, bool BtoA, bool SameType, class A, class B>
struct return_type_2_ifthenelsereturn;
// if A can be converted to B and vice versa -> ambiguous
template<int Phase, class A, class B>
struct return_type_2_ifthenelsereturn<Phase, true, true, false, A, B> {
typedef
detail::return_type_deduction_failure<return_type_2_ifthenelsereturn> type;
// ambiguous type in conditional expression
};
// if A can be converted to B and vice versa and are of same type
template<int Phase, class A, class B>
struct return_type_2_ifthenelsereturn<Phase, true, true, true, A, B> {
typedef A type;
};
// A can be converted to B
template<int Phase, class A, class B>
struct return_type_2_ifthenelsereturn<Phase, true, false, false, A, B> {
typedef B type;
};
// B can be converted to A
template<int Phase, class A, class B>
struct return_type_2_ifthenelsereturn<Phase, false, true, false, A, B> {
typedef A type;
};
// neither can be converted. Then we drop the potential references, and
// try again
template<class A, class B>
struct return_type_2_ifthenelsereturn<1, false, false, false, A, B> {
// it is safe to add const, since the result will be an rvalue and thus
// const anyway. The const are needed eg. if the types
// are 'const int*' and 'void *'. The remaining type should be 'const void*'
typedef const typename boost::remove_reference<A>::type plainA;
typedef const typename boost::remove_reference<B>::type plainB;
// TODO: Add support for volatile ?
typedef typename
return_type_2_ifthenelsereturn<
2,
boost::is_convertible<plainA,plainB>::value,
boost::is_convertible<plainB,plainA>::value,
boost::is_same<plainA,plainB>::value,
plainA,
plainB>::type type;
};
// PHASE 6:2
template<class A, class B>
struct return_type_2_ifthenelsereturn<2, false, false, false, A, B> {
typedef
detail::return_type_deduction_failure<return_type_2_ifthenelsereturn> type;
// types_do_not_match_in_conditional_expression
};
// PHASE 5: now we know that types are not arithmetic.
template<class A, class B>
struct non_numeric_types {
typedef typename
return_type_2_ifthenelsereturn<
1, // phase 1
is_convertible<A,B>::value,
is_convertible<B,A>::value,
is_same<A,B>::value,
A,
B>::type type;
};
// PHASE 4 :
// the base case covers arithmetic types with differing promote codes
// use the type deduction of arithmetic_actions
template<int CodeA, int CodeB, class A, class B>
struct arithmetic_or_not {
typedef typename
return_type_2<arithmetic_action<plus_action>, A, B>::type type;
// plus_action is just a random pick, has to be a concrete instance
};
// this case covers the case of artihmetic types with the same promote codes.
// non numeric deduction is used since e.g. integral promotion is not
// performed with operator ?:
template<int CodeA, class A, class B>
struct arithmetic_or_not<CodeA, CodeA, A, B> {
typedef typename non_numeric_types<A, B>::type type;
};
// if either A or B has promote code -1 it is not an arithmetic type
template<class A, class B>
struct arithmetic_or_not <-1, -1, A, B> {
typedef typename non_numeric_types<A, B>::type type;
};
template<int CodeB, class A, class B>
struct arithmetic_or_not <-1, CodeB, A, B> {
typedef typename non_numeric_types<A, B>::type type;
};
template<int CodeA, class A, class B>
struct arithmetic_or_not <CodeA, -1, A, B> {
typedef typename non_numeric_types<A, B>::type type;
};
// PHASE 3 : Are the types same?
// No, check if they are arithmetic or not
template <class A, class B>
struct same_or_not {
typedef typename detail::remove_reference_and_cv<A>::type plainA;
typedef typename detail::remove_reference_and_cv<B>::type plainB;
typedef typename
arithmetic_or_not<
detail::promote_code<plainA>::value,
detail::promote_code<plainB>::value,
A,
B>::type type;
};
// Yes, clear.
template <class A> struct same_or_not<A, A> {
typedef A type;
};
} // detail
// PHASE 2 : Perform first the potential array_to_pointer conversion
template<class A, class B>
struct return_type_2<other_action<ifthenelsereturn_action>, A, B> {
typedef typename detail::array_to_pointer<A>::type A1;
typedef typename detail::array_to_pointer<B>::type B1;
typedef typename
boost::add_const<typename detail::same_or_not<A1, B1>::type>::type type;
};
// PHASE 1 : Deduction is based on the second and third operand
// return type specialization for conditional expression ends -----------
// Specialization of lambda_functor_base for if_then_else_return.
template<class Args>
class
lambda_functor_base<other_action<ifthenelsereturn_action>, Args> {
public:
Args args;
template <class SigArgs> struct sig {
private:
typedef typename detail::nth_return_type_sig<1, Args, SigArgs>::type ret1;
typedef typename detail::nth_return_type_sig<2, Args, SigArgs>::type ret2;
public:
typedef typename return_type_2<
other_action<ifthenelsereturn_action>, ret1, ret2
>::type type;
};
public:
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET, CALL_TEMPLATE_ARGS>
RET call(CALL_FORMAL_ARGS) const {
return (detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS)) ?
detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS)
:
detail::select(boost::tuples::get<2>(args), CALL_ACTUAL_ARGS);
}
};
// The code below is from Joel de Guzman, some name changes etc.
// has been made.
///////////////////////////////////////////////////////////////////////////////
//
// if_then_else_composite
//
// This composite has two (2) forms:
//
// if_(condition)
// [
// statement
// ]
//
// and
//
// if_(condition)
// [
// true_statement
// ]
// .else_
// [
// false_statement
// ]
//
// where condition is an lambda_functor that evaluates to bool. If condition
// is true, the true_statement (again an lambda_functor) is executed
// otherwise, the false_statement (another lambda_functor) is executed. The
// result type of this is void. Note the trailing underscore after
// if_ and the leading dot and the trailing underscore before
// and after .else_.
//
///////////////////////////////////////////////////////////////////////////////
template <typename CondT, typename ThenT, typename ElseT>
struct if_then_else_composite {
typedef if_then_else_composite<CondT, ThenT, ElseT> self_t;
template <class SigArgs>
struct sig { typedef void type; };
if_then_else_composite(
CondT const& cond_,
ThenT const& then_,
ElseT const& else__)
: cond(cond_), then(then_), else_(else__) {}
template <class Ret, CALL_TEMPLATE_ARGS>
Ret call(CALL_FORMAL_ARGS) const
{
if (cond.internal_call(CALL_ACTUAL_ARGS))
then.internal_call(CALL_ACTUAL_ARGS);
else
else_.internal_call(CALL_ACTUAL_ARGS);
}
CondT cond; ThenT then; ElseT else_; // lambda_functors
};
//////////////////////////////////
template <typename CondT, typename ThenT>
struct else_gen {
else_gen(CondT const& cond_, ThenT const& then_)
: cond(cond_), then(then_) {}
template <typename ElseT>
lambda_functor<if_then_else_composite<CondT, ThenT,
typename as_lambda_functor<ElseT>::type> >
operator[](ElseT const& else_)
{
typedef if_then_else_composite<CondT, ThenT,
typename as_lambda_functor<ElseT>::type>
result;
return result(cond, then, to_lambda_functor(else_));
}
CondT cond; ThenT then;
};
//////////////////////////////////
template <typename CondT, typename ThenT>
struct if_then_composite {
template <class SigArgs>
struct sig { typedef void type; };
if_then_composite(CondT const& cond_, ThenT const& then_)
: cond(cond_), then(then_), else_(cond, then) {}
template <class Ret, CALL_TEMPLATE_ARGS>
Ret call(CALL_FORMAL_ARGS) const
{
if (cond.internal_call(CALL_ACTUAL_ARGS))
then.internal_call(CALL_ACTUAL_ARGS);
}
CondT cond; ThenT then; // lambda_functors
else_gen<CondT, ThenT> else_;
};
//////////////////////////////////
template <typename CondT>
struct if_gen {
if_gen(CondT const& cond_)
: cond(cond_) {}
template <typename ThenT>
lambda_functor<if_then_composite<
typename as_lambda_functor<CondT>::type,
typename as_lambda_functor<ThenT>::type> >
operator[](ThenT const& then) const
{
typedef if_then_composite<
typename as_lambda_functor<CondT>::type,
typename as_lambda_functor<ThenT>::type>
result;
return result(
to_lambda_functor(cond),
to_lambda_functor(then));
}
CondT cond;
};
//////////////////////////////////
template <typename CondT>
inline if_gen<CondT>
if_(CondT const& cond)
{
return if_gen<CondT>(cond);
}
} // lambda
} // boost
#endif // BOOST_LAMBDA_IF_HPP

View File

@@ -1,9 +1,14 @@
// -- lambda.hpp -- Boost Lambda Library -----------------------------------
// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
//
// 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)
// 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://lambda.cs.utu.fi
@@ -13,17 +18,15 @@
#include "boost/lambda/core.hpp"
#ifdef BOOST_NO_FDECL_TEMPLATES_AS_TEMPLATE_TEMPLATE_PARAMS
#include "boost/lambda/detail/operator_actions.hpp"
#include "boost/lambda/detail/operator_lambda_functor_base.hpp"
#include "boost/lambda/detail/operator_return_type_traits.hpp"
#ifdef BOOST_NO_FORWARD_DECLARADED_TEMPLATES_AS_TEMPLATE_TEMPLATE_PARAMETERS
#include <istream>
#include <ostream>
#endif
#include "boost/lambda/detail/operator_actions.hpp"
#include "boost/lambda/detail/operator_lambda_func_base.hpp"
#include "boost/lambda/detail/operator_return_type_traits.hpp"
#include "boost/lambda/detail/operators.hpp"
#include "boost/lambda/detail/member_ptr.hpp"
#endif

View File

@@ -1,505 +0,0 @@
// Boost Lambda Library -- loops.hpp ----------------------------------------
// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2000 Gary Powell (powellg@amazon.com)
// Copyright (c) 2001-2002 Joel de Guzman
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see www.boost.org
// --------------------------------------------------------------------------
#if !defined(BOOST_LAMBDA_LOOPS_HPP)
#define BOOST_LAMBDA_LOOPS_HPP
#include "boost/lambda/core.hpp"
namespace boost {
namespace lambda {
// -- loop control structure actions ----------------------
class forloop_action {};
class forloop_no_body_action {};
class whileloop_action {};
class whileloop_no_body_action {};
class dowhileloop_action {};
class dowhileloop_no_body_action {};
// For loop
template <class Arg1, class Arg2, class Arg3, class Arg4>
inline const
lambda_functor<
lambda_functor_base<
forloop_action,
tuple<lambda_functor<Arg1>, lambda_functor<Arg2>,
lambda_functor<Arg3>, lambda_functor<Arg4> >
>
>
for_loop(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2,
const lambda_functor<Arg3>& a3, const lambda_functor<Arg4>& a4) {
return
lambda_functor_base<
forloop_action,
tuple<lambda_functor<Arg1>, lambda_functor<Arg2>,
lambda_functor<Arg3>, lambda_functor<Arg4> >
>
( tuple<lambda_functor<Arg1>, lambda_functor<Arg2>,
lambda_functor<Arg3>, lambda_functor<Arg4> >(a1, a2, a3, a4)
);
}
// No body case.
template <class Arg1, class Arg2, class Arg3>
inline const
lambda_functor<
lambda_functor_base<
forloop_no_body_action,
tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, lambda_functor<Arg3> >
>
>
for_loop(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2,
const lambda_functor<Arg3>& a3) {
return
lambda_functor_base<
forloop_no_body_action,
tuple<lambda_functor<Arg1>, lambda_functor<Arg2>,
lambda_functor<Arg3> >
>
( tuple<lambda_functor<Arg1>, lambda_functor<Arg2>,
lambda_functor<Arg3> >(a1, a2, a3) );
}
// While loop
template <class Arg1, class Arg2>
inline const
lambda_functor<
lambda_functor_base<
whileloop_action,
tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >
>
>
while_loop(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2) {
return
lambda_functor_base<
whileloop_action,
tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >
>
( tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >(a1, a2));
}
// No body case.
template <class Arg1>
inline const
lambda_functor<
lambda_functor_base<
whileloop_no_body_action,
tuple<lambda_functor<Arg1> >
>
>
while_loop(const lambda_functor<Arg1>& a1) {
return
lambda_functor_base<
whileloop_no_body_action,
tuple<lambda_functor<Arg1> >
>
( tuple<lambda_functor<Arg1> >(a1) );
}
// Do While loop
template <class Arg1, class Arg2>
inline const
lambda_functor<
lambda_functor_base<
dowhileloop_action,
tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >
>
>
do_while_loop(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2) {
return
lambda_functor_base<
dowhileloop_action,
tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >
>
( tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >(a1, a2));
}
// No body case.
template <class Arg1>
inline const
lambda_functor<
lambda_functor_base<
dowhileloop_no_body_action,
tuple<lambda_functor<Arg1> >
>
>
do_while_loop(const lambda_functor<Arg1>& a1) {
return
lambda_functor_base<
dowhileloop_no_body_action,
tuple<lambda_functor<Arg1> >
>
( tuple<lambda_functor<Arg1> >(a1));
}
// Control loop lambda_functor_base specializations.
// Specialization for for_loop.
template<class Args>
class
lambda_functor_base<forloop_action, Args> {
public:
Args args;
template <class T> struct sig { typedef void type; };
public:
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET, CALL_TEMPLATE_ARGS>
RET call(CALL_FORMAL_ARGS) const {
for(detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS);
detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS);
detail::select(boost::tuples::get<2>(args), CALL_ACTUAL_ARGS))
detail::select(boost::tuples::get<3>(args), CALL_ACTUAL_ARGS);
}
};
// No body case
template<class Args>
class
lambda_functor_base<forloop_no_body_action, Args> {
public:
Args args;
template <class T> struct sig { typedef void type; };
public:
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET, CALL_TEMPLATE_ARGS>
RET call(CALL_FORMAL_ARGS) const {
for(detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS);
detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS);
detail::select(boost::tuples::get<2>(args), CALL_ACTUAL_ARGS)) {}
}
};
// Specialization for while_loop.
template<class Args>
class
lambda_functor_base<whileloop_action, Args> {
public:
Args args;
template <class T> struct sig { typedef void type; };
public:
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET, CALL_TEMPLATE_ARGS>
RET call(CALL_FORMAL_ARGS) const {
while(detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS))
detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS);
}
};
// No body case
template<class Args>
class
lambda_functor_base<whileloop_no_body_action, Args> {
public:
Args args;
template <class T> struct sig { typedef void type; };
public:
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET, CALL_TEMPLATE_ARGS>
RET call(CALL_FORMAL_ARGS) const {
while(detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS)) {}
}
};
// Specialization for do_while_loop.
// Note that the first argument is the condition.
template<class Args>
class
lambda_functor_base<dowhileloop_action, Args> {
public:
Args args;
template <class T> struct sig { typedef void type; };
public:
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET, CALL_TEMPLATE_ARGS>
RET call(CALL_FORMAL_ARGS) const {
do {
detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS);
} while (detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS) );
}
};
// No body case
template<class Args>
class
lambda_functor_base<dowhileloop_no_body_action, Args> {
public:
Args args;
template <class T> struct sig { typedef void type; };
public:
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET, CALL_TEMPLATE_ARGS>
RET call(CALL_FORMAL_ARGS) const {
do {} while (detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS) );
}
};
// The code below is from Joel de Guzman, some name changes etc.
// has been made.
///////////////////////////////////////////////////////////////////////////////
//
// while_composite
//
// This composite has the form:
//
// while_(condition)
// [
// statement
// ]
//
// While the condition (an lambda_functor) evaluates to true, statement
// (another lambda_functor) is executed. The result type of this is void.
// Note the trailing underscore after while_.
//
///////////////////////////////////////////////////////////////////////////////
template <typename CondT, typename DoT>
struct while_composite {
typedef while_composite<CondT, DoT> self_t;
template <class SigArgs>
struct sig { typedef void type; };
while_composite(CondT const& cond_, DoT const& do__)
: cond(cond_), do_(do__) {}
template <class Ret, CALL_TEMPLATE_ARGS>
Ret call(CALL_FORMAL_ARGS) const
{
while (cond.internal_call(CALL_ACTUAL_ARGS))
do_.internal_call(CALL_ACTUAL_ARGS);
}
CondT cond;
DoT do_;
};
//////////////////////////////////
template <typename CondT>
struct while_gen {
while_gen(CondT const& cond_)
: cond(cond_) {}
template <typename DoT>
lambda_functor<while_composite<
typename as_lambda_functor<CondT>::type,
typename as_lambda_functor<DoT>::type> >
operator[](DoT const& do_) const
{
typedef while_composite<
typename as_lambda_functor<CondT>::type,
typename as_lambda_functor<DoT>::type>
result;
return result(
to_lambda_functor(cond),
to_lambda_functor(do_));
}
CondT cond;
};
//////////////////////////////////
template <typename CondT>
inline while_gen<CondT>
while_(CondT const& cond)
{
return while_gen<CondT>(cond);
}
///////////////////////////////////////////////////////////////////////////////
//
// do_composite
//
// This composite has the form:
//
// do_
// [
// statement
// ]
// .while_(condition)
//
// While the condition (an lambda_functor) evaluates to true, statement
// (another lambda_functor) is executed. The statement is executed at least
// once. The result type of this is void. Note the trailing
// underscore after do_ and the leading dot and the trailing
// underscore before and after .while_.
//
///////////////////////////////////////////////////////////////////////////////
template <typename DoT, typename CondT>
struct do_composite {
typedef do_composite<DoT, CondT> self_t;
template <class SigArgs>
struct sig { typedef void type; };
do_composite(DoT const& do__, CondT const& cond_)
: do_(do__), cond(cond_) {}
template <class Ret, CALL_TEMPLATE_ARGS>
Ret call(CALL_FORMAL_ARGS) const
{
do
do_.internal_call(CALL_ACTUAL_ARGS);
while (cond.internal_call(CALL_ACTUAL_ARGS));
}
DoT do_;
CondT cond;
};
////////////////////////////////////
template <typename DoT>
struct do_gen2 {
do_gen2(DoT const& do__)
: do_(do__) {}
template <typename CondT>
lambda_functor<do_composite<
typename as_lambda_functor<DoT>::type,
typename as_lambda_functor<CondT>::type> >
while_(CondT const& cond) const
{
typedef do_composite<
typename as_lambda_functor<DoT>::type,
typename as_lambda_functor<CondT>::type>
result;
return result(
to_lambda_functor(do_),
to_lambda_functor(cond));
}
DoT do_;
};
////////////////////////////////////
struct do_gen {
template <typename DoT>
do_gen2<DoT>
operator[](DoT const& do_) const
{
return do_gen2<DoT>(do_);
}
};
do_gen const do_ = do_gen();
///////////////////////////////////////////////////////////////////////////////
//
// for_composite
//
// This statement has the form:
//
// for_(init, condition, step)
// [
// statement
// ]
//
// Where init, condition, step and statement are all lambda_functors. init
// is executed once before entering the for-loop. The for-loop
// exits once condition evaluates to false. At each loop iteration,
// step and statement is called. The result of this statement is
// void. Note the trailing underscore after for_.
//
///////////////////////////////////////////////////////////////////////////////
template <typename InitT, typename CondT, typename StepT, typename DoT>
struct for_composite {
template <class SigArgs>
struct sig { typedef void type; };
for_composite(
InitT const& init_,
CondT const& cond_,
StepT const& step_,
DoT const& do__)
: init(init_), cond(cond_), step(step_), do_(do__) {}
template <class Ret, CALL_TEMPLATE_ARGS>
Ret
call(CALL_FORMAL_ARGS) const
{
for (init.internal_call(CALL_ACTUAL_ARGS); cond.internal_call(CALL_ACTUAL_ARGS); step.internal_call(CALL_ACTUAL_ARGS))
do_.internal_call(CALL_ACTUAL_ARGS);
}
InitT init; CondT cond; StepT step; DoT do_; // lambda_functors
};
//////////////////////////////////
template <typename InitT, typename CondT, typename StepT>
struct for_gen {
for_gen(
InitT const& init_,
CondT const& cond_,
StepT const& step_)
: init(init_), cond(cond_), step(step_) {}
template <typename DoT>
lambda_functor<for_composite<
typename as_lambda_functor<InitT>::type,
typename as_lambda_functor<CondT>::type,
typename as_lambda_functor<StepT>::type,
typename as_lambda_functor<DoT>::type> >
operator[](DoT const& do_) const
{
typedef for_composite<
typename as_lambda_functor<InitT>::type,
typename as_lambda_functor<CondT>::type,
typename as_lambda_functor<StepT>::type,
typename as_lambda_functor<DoT>::type>
result;
return result(
to_lambda_functor(init),
to_lambda_functor(cond),
to_lambda_functor(step),
to_lambda_functor(do_));
}
InitT init; CondT cond; StepT step;
};
//////////////////////////////////
template <typename InitT, typename CondT, typename StepT>
inline for_gen<InitT, CondT, StepT>
for_(InitT const& init, CondT const& cond, StepT const& step)
{
return for_gen<InitT, CondT, StepT>(init, cond, step);
}
} // lambda
} // boost
#endif // BOOST_LAMBDA_LOOPS_HPP

View File

@@ -1,119 +0,0 @@
// -- numeric.hpp -- Boost Lambda Library -----------------------------------
// Copyright (C) 2002 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2002 Gary Powell (gwpowell@hotmail.com)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see http://www.boost.org
#ifndef BOOST_LAMBDA_NUMERIC_HPP
#define BOOST_LAMBDA_NUMERIC_HPP
#include "boost/lambda/core.hpp"
#include <numeric>
namespace boost {
namespace lambda {
namespace ll {
// accumulate ---------------------------------
struct accumulate {
template <class Args>
struct sig {
typedef typename boost::remove_const<
typename boost::tuples::element<3, Args>::type
>::type type;
};
template <class A, class B, class C>
C
operator()(A a, B b, C c) const
{ return ::std::accumulate(a, b, c); }
template <class A, class B, class C, class D>
C
operator()(A a, B b, C c, D d) const
{ return ::std::accumulate(a, b, c, d); }
};
// inner_product ---------------------------------
struct inner_product {
template <class Args>
struct sig {
typedef typename boost::remove_const<
typename boost::tuples::element<4, Args>::type
>::type type;
};
template <class A, class B, class C, class D>
D
operator()(A a, B b, C c, D d) const
{ return ::std::inner_product(a, b, c, d); }
template <class A, class B, class C, class D, class E, class F>
D
operator()(A a, B b, C c, D d, E e, F f) const
{ return ::std::inner_product(a, b, c, d, e, f); }
};
// partial_sum ---------------------------------
struct partial_sum {
template <class Args>
struct sig {
typedef typename boost::remove_const<
typename boost::tuples::element<3, Args>::type
>::type type;
};
template <class A, class B, class C>
C
operator()(A a, B b, C c) const
{ return ::std::partial_sum(a, b, c); }
template <class A, class B, class C, class D>
C
operator()(A a, B b, C c, D d) const
{ return ::std::partial_sum(a, b, c, d); }
};
// adjacent_difference ---------------------------------
struct adjacent_difference {
template <class Args>
struct sig {
typedef typename boost::remove_const<
typename boost::tuples::element<3, Args>::type
>::type type;
};
template <class A, class B, class C>
C
operator()(A a, B b, C c) const
{ return ::std::adjacent_difference(a, b, c); }
template <class A, class B, class C, class D>
C
operator()(A a, B b, C c, D d) const
{ return ::std::adjacent_difference(a, b, c, d); }
};
} // end of ll namespace
} // end of lambda namespace
} // end of boost namespace
#endif

View File

@@ -1,508 +0,0 @@
// Boost Lambda Library -- switch.hpp -----------------------------------
//
// Copyright (C) 2000 Gary Powell (powellg@amazon.com)
// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see www.boost.org
// --------------------------------------------------------------------------
#if !defined(BOOST_LAMBDA_SWITCH_HPP)
#define BOOST_LAMBDA_SWITCH_HPP
#include "boost/lambda/core.hpp"
#include "boost/lambda/detail/control_constructs_common.hpp"
#include "boost/preprocessor/enum_shifted_params.hpp"
#include "boost/preprocessor/repeat_2nd.hpp"
#include "boost/preprocessor/tuple.hpp"
namespace boost {
namespace lambda {
// Switch actions
template <int N, class Switch1 = null_type, class Switch2 = null_type,
class Switch3 = null_type, class Switch4 = null_type,
class Switch5 = null_type, class Switch6 = null_type,
class Switch7 = null_type, class Switch8 = null_type,
class Switch9 = null_type>
struct switch_action {};
namespace detail {
// templates to represent special lambda functors for the cases in
// switch statements
template <int Value> struct case_label {};
struct default_label {};
template<class Type> struct switch_case_tag {};
// a normal case is represented as:
// tagged_lambda_functor<switch_case_tag<case_label<N> > >, LambdaFunctor>
// the default case as:
// tagged_lambda_functor<switch_case_tag<default_label> >, LambdaFunctor>
} // end detail
/// create switch_case_tag tagged_lambda_functors
template <int CaseValue, class Arg>
inline const
tagged_lambda_functor<
detail::switch_case_tag<detail::case_label<CaseValue> >,
lambda_functor<Arg>
>
case_statement(const lambda_functor<Arg>& a) {
return
tagged_lambda_functor<
detail::switch_case_tag<detail::case_label<CaseValue> >,
lambda_functor<Arg>
>(a);
}
// No case body case.
template <int CaseValue>
inline const
tagged_lambda_functor<
detail::switch_case_tag<detail::case_label<CaseValue> >,
lambda_functor<
lambda_functor_base<
do_nothing_action,
null_type
>
>
>
case_statement() {
return
tagged_lambda_functor<
detail::switch_case_tag<detail::case_label<CaseValue> >,
lambda_functor<
lambda_functor_base<
do_nothing_action,
null_type
>
>
> () ;
}
// default label
template <class Arg>
inline const
tagged_lambda_functor<
detail::switch_case_tag<detail::default_label>,
lambda_functor<Arg>
>
default_statement(const lambda_functor<Arg>& a) {
return
tagged_lambda_functor<
detail::switch_case_tag<detail::default_label>,
lambda_functor<Arg>
>(a);
}
// default lable, no case body case.
inline const
tagged_lambda_functor<
detail::switch_case_tag<detail::default_label>,
lambda_functor<
lambda_functor_base<
do_nothing_action,
null_type
>
>
>
default_statement() {
return
lambda_functor_base<
do_nothing_action,
null_type
> () ;
}
// Specializations for lambda_functor_base of case_statement -----------------
// 0 case type:
// useless (just the condition part) but provided for completeness.
template<class Args>
class
lambda_functor_base<
switch_action<1>,
Args
>
{
public:
Args args;
template <class SigArgs> struct sig { typedef void type; };
public:
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET, CALL_TEMPLATE_ARGS>
RET call(CALL_FORMAL_ARGS) const {
detail::select(::boost::tuples::get<1>(args), CALL_ACTUAL_ARGS);
}
};
// 1 case type:
// template<class Args, int Case1>
// class
// lambda_functor_base<
// action<
// 2,
// return_void_action<switch_action<detail::case_label<Case1> > >
// >,
// Args
// >
// {
// Args args;
// public:
// explicit lambda_functor_base(const Args& a) : args(a) {}
// template<class RET, class A, class B, class C>
// RET call(A& a, B& b, C& c) const {
// switch( detail::select(::boost::tuples::get<0>(args), a, b, c) )
// {
// case Case1:
// detail::select(::boost::tuples::get<1>(args), a, b, c);
// break;
// }
// }
// };
// switch with default being the sole label - doesn't make much sense but
// it is there for completeness
// template<class Args>
// class
// lambda_functor_base<
// action<
// 2,
// return_void_action<switch_action<detail::default_label> >
// >,
// Args
// >
// {
// Args args;
// public:
// explicit lambda_functor_base(const Args& a) : args(a) {}
//
// template<class RET, class A, class B, class C>
// RET call(A& a, B& b, C& c) const {
// switch( detail::select(::boost::tuples::get<0>(args), a, b, c) )
// {
// default:
// detail::select(::boost::tuples::get<1>(args), a, b, c);
// break;
// }
// }
// };
// // 2 case type:
// The different specializations are generated with Vesa Karvonen's
// preprocessor library.
// This is just a comment to show what the generated classes look like
// template<class Args, int Case1, int Case2>
// class
// lambda_functor_base<
// action<3,
// return_void_action<
// switch_action<
// detail::case_label<Case1>,
// detail::case_label<Case2>
// >
// >
// >,
// Args
// >
// {
// Args args;
// public:
// explicit lambda_functor_base(const Args& a) : args(a) {}
// template<class RET, class A, class B, class C>
// RET call(A& a, B& b, C& c) const {
// switch( detail::select(::boost::tuples::get<0>(args), a, b, c) )
// {
// case Case1:
// detail::select(::boost::tuples::get<1>(args), a, b, c);
// break;
// case Case2:
// detail::select(::boost::tuples::get<2>(args), a, b, c);
// break;
// }
// }
// };
// template<class Args, int Case1>
// class
// lambda_functor_base<
// action<3,
// return_void_action<
// switch_action<
// detail::case_label<Case1>,
// detail::default_label
// >
// >
// >,
// Args
// >
// {
// Args args;
// public:
// explicit lambda_functor_base(const Args& a) : args(a) {}
// template<class RET, class A, class B, class C>
// RET call(A& a, B& b, C& c) const {
// switch( detail::select(::boost::tuples::get<0>(args), a, b, c) )
// {
// case Case1:
// detail::select(::boost::tuples::get<1>(args), a, b, c);
// break;
// default:
// detail::select(::boost::tuples::get<2>(args), a, b, c);
// break;
// }
// }
// };
// -------------------------
// Some helper preprocessor macros ---------------------------------
// BOOST_LAMBDA_A_I_LIST(N, X) is a list of form X0, X1, ..., XN
// BOOST_LAMBDA_A_I_B_LIST(N, X, Y) is a list of form X0 Y, X1 Y, ..., XN Y
#define BOOST_LAMBDA_A_I(z, i, A) \
BOOST_PP_COMMA_IF(i) BOOST_PP_CAT(A,i)
#define BOOST_LAMBDA_A_I_B(z, i, T) \
BOOST_PP_COMMA_IF(i) BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2,0,T),i) BOOST_PP_TUPLE_ELEM(2,1,T)
#define BOOST_LAMBDA_A_I_LIST(i, A) \
BOOST_PP_REPEAT(i,BOOST_LAMBDA_A_I, A)
#define BOOST_LAMBDA_A_I_B_LIST(i, A, B) \
BOOST_PP_REPEAT(i,BOOST_LAMBDA_A_I_B, (A,B))
// Switch related macros -------------------------------------------
#define BOOST_LAMBDA_SWITCH_CASE_BLOCK(z, N, A) \
case Case##N: \
detail::select(::boost::tuples::get<BOOST_PP_INC(N)>(args), CALL_ACTUAL_ARGS); \
break;
#define BOOST_LAMBDA_SWITCH_CASE_BLOCK_LIST(N) \
BOOST_PP_REPEAT(N, BOOST_LAMBDA_SWITCH_CASE_BLOCK, FOO)
// 2 case type:
#define BOOST_LAMBDA_SWITCH_NO_DEFAULT_CASE(N) \
template<class Args, BOOST_LAMBDA_A_I_LIST(N, int Case)> \
class \
lambda_functor_base< \
switch_action<BOOST_PP_INC(N), \
BOOST_LAMBDA_A_I_B_LIST(N, detail::case_label<Case,>) \
>, \
Args \
> \
{ \
public: \
Args args; \
template <class SigArgs> struct sig { typedef void type; }; \
public: \
explicit lambda_functor_base(const Args& a) : args(a) {} \
\
template<class RET, CALL_TEMPLATE_ARGS> \
RET call(CALL_FORMAL_ARGS) const { \
switch( detail::select(::boost::tuples::get<0>(args), CALL_ACTUAL_ARGS) ) \
{ \
BOOST_LAMBDA_SWITCH_CASE_BLOCK_LIST(N) \
} \
} \
};
#define BOOST_LAMBDA_SWITCH_WITH_DEFAULT_CASE(N) \
template< \
class Args BOOST_PP_COMMA_IF(BOOST_PP_DEC(N)) \
BOOST_LAMBDA_A_I_LIST(BOOST_PP_DEC(N), int Case) \
> \
class \
lambda_functor_base< \
switch_action<BOOST_PP_INC(N), \
BOOST_LAMBDA_A_I_B_LIST(BOOST_PP_DEC(N), \
detail::case_label<Case, >) \
BOOST_PP_COMMA_IF(BOOST_PP_DEC(N)) \
detail::default_label \
>, \
Args \
> \
{ \
public: \
Args args; \
template <class SigArgs> struct sig { typedef void type; }; \
public: \
explicit lambda_functor_base(const Args& a) : args(a) {} \
\
template<class RET, CALL_TEMPLATE_ARGS> \
RET call(CALL_FORMAL_ARGS) const { \
switch( detail::select(::boost::tuples::get<0>(args), CALL_ACTUAL_ARGS) ) \
{ \
BOOST_LAMBDA_SWITCH_CASE_BLOCK_LIST(BOOST_PP_DEC(N)) \
default: \
detail::select(::boost::tuples::get<N>(args), CALL_ACTUAL_ARGS); \
break; \
} \
} \
};
// switch_statement bind functions -------------------------------------
// The zero argument case, for completeness sake
inline const
lambda_functor<
lambda_functor_base<
do_nothing_action,
null_type
>
>
switch_statement() {
return
lambda_functor_base<
do_nothing_action,
null_type
>
();
}
// 1 argument case, this is useless as well, just the condition part
template <class TestArg>
inline const
lambda_functor<
lambda_functor_base<
switch_action<1>,
tuple<lambda_functor<TestArg> >
>
>
switch_statement(const lambda_functor<TestArg>& a1) {
return
lambda_functor_base<
switch_action<1>,
tuple< lambda_functor<TestArg> >
>
( tuple<lambda_functor<TestArg> >(a1));
}
#define HELPER(z, N, FOO) \
BOOST_PP_COMMA_IF(N) \
BOOST_PP_CAT( \
const tagged_lambda_functor<detail::switch_case_tag<TagData, \
N>) \
BOOST_PP_COMMA() Arg##N>& a##N
#define HELPER_LIST(N) BOOST_PP_REPEAT(N, HELPER, FOO)
#define BOOST_LAMBDA_SWITCH_STATEMENT(N) \
template <class TestArg, \
BOOST_LAMBDA_A_I_LIST(N, class TagData), \
BOOST_LAMBDA_A_I_LIST(N, class Arg)> \
inline const \
lambda_functor< \
lambda_functor_base< \
switch_action<BOOST_PP_INC(N), \
BOOST_LAMBDA_A_I_LIST(N, TagData) \
>, \
tuple<lambda_functor<TestArg>, BOOST_LAMBDA_A_I_LIST(N, Arg)> \
> \
> \
switch_statement( \
const lambda_functor<TestArg>& ta, \
HELPER_LIST(N) \
) \
{ \
return \
lambda_functor_base< \
switch_action<BOOST_PP_INC(N), \
BOOST_LAMBDA_A_I_LIST(N, TagData) \
>, \
tuple<lambda_functor<TestArg>, BOOST_LAMBDA_A_I_LIST(N, Arg)> \
> \
( tuple<lambda_functor<TestArg>, BOOST_LAMBDA_A_I_LIST(N, Arg)> \
(ta, BOOST_LAMBDA_A_I_LIST(N, a) )); \
}
// Here's the actual generation
#define BOOST_LAMBDA_SWITCH(N) \
BOOST_LAMBDA_SWITCH_NO_DEFAULT_CASE(N) \
BOOST_LAMBDA_SWITCH_WITH_DEFAULT_CASE(N)
// Use this to avoid case 0, these macros work only from case 1 upwards
#define BOOST_LAMBDA_SWITCH_HELPER(z, N, A) \
BOOST_LAMBDA_SWITCH( BOOST_PP_INC(N) )
// Use this to avoid cases 0 and 1, these macros work only from case 2 upwards
#define BOOST_LAMBDA_SWITCH_STATEMENT_HELPER(z, N, A) \
BOOST_LAMBDA_SWITCH_STATEMENT(BOOST_PP_INC(N))
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4065)
#endif
// up to 9 cases supported (counting default:)
BOOST_PP_REPEAT_2ND(9,BOOST_LAMBDA_SWITCH_HELPER,FOO)
BOOST_PP_REPEAT_2ND(9,BOOST_LAMBDA_SWITCH_STATEMENT_HELPER,FOO)
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
} // namespace lambda
} // namespace boost
#undef HELPER
#undef HELPER_LIST
#undef BOOST_LAMBDA_SWITCH_HELPER
#undef BOOST_LAMBDA_SWITCH
#undef BOOST_LAMBDA_SWITCH_NO_DEFAULT_CASE
#undef BOOST_LAMBDA_SWITCH_WITH_DEFAULT_CASE
#undef BOOST_LAMBDA_SWITCH_CASE_BLOCK
#undef BOOST_LAMBDA_SWITCH_CASE_BLOCK_LIST
#undef BOOST_LAMBDA_SWITCH_STATEMENT
#undef BOOST_LAMBDA_SWITCH_STATEMENT_HELPER
#endif

View File

@@ -1,12 +0,0 @@
<html>
<head>
<meta http-equiv="refresh" content="0; URL=../../doc/html/lambda.html">
</head>
<body>
Automatic redirection failed, please go to <a href="../../doc/html/lambda.html">www.boost.org/doc/html/lambda.html</a>&nbsp;<hr>
<p>© Copyright Beman Dawes, 2001</p>
<p>Distributed under the Boost Software License, Version 1.0. (See accompanying
file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy
at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
</body>
</html>

View File

@@ -1,16 +0,0 @@
{
"key": "lambda",
"name": "Lambda",
"authors": [
"Jaakko Järvi",
"Gary Powell"
],
"description": "Define small unnamed function objects at the actual call site, and more.",
"category": [
"Function-objects"
],
"maintainers": [
"Jaakko Jarvi <jarvi -at- cs.tamu.edu>"
],
"cxxstd": "03"
}

View File

@@ -1,11 +0,0 @@
# 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 LINK_LIBRARIES Boost::lambda Boost::core Boost::any Boost::function Boost::smart_ptr)
endif()

View File

@@ -1,34 +0,0 @@
# Lambda library
# Copyright (C) 2001-2003 Jaakko Järvi
# 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/
import testing ;
run algorithm_test.cpp ;
run bind_tests_advanced.cpp ;
run bind_tests_simple.cpp ;
run bind_tests_simple_f_refs.cpp ;
run bll_and_function.cpp ;
run cast_test.cpp ;
run constructor_tests.cpp ;
run control_structures.cpp ;
run exception_test.cpp
: : : <toolset>msvc-14.0,<variant>release:<build>no # crash with 8 catch blocks
;
run extending_rt_traits.cpp ;
run is_instance_of_test.cpp ;
run istreambuf_test.cpp ;
run member_pointer_test.cpp ;
run operator_tests_simple.cpp ;
run phoenix_control_structures.cpp ;
run result_of_tests.cpp ;
run ret_test.cpp ;
run rvalue_test.cpp ;
run switch_construct.cpp ;
link issue24_test.cpp ;

19
test/Makefile Normal file → Executable file
View File

@@ -1,7 +1,7 @@
BOOST = ../../..
CXX = g++
EXTRAFLAGS = -pedantic -Wno-long-long -Wno-long-double -ftemplate-depth-50
CXX = gcc
EXTRAFLAGS = -pedantic -Wno-long-long -ftemplate-depth-50
LIBS = -lstdc++
#CXX = KCC
@@ -23,18 +23,17 @@ AR = ar
SOURCES = \
is_instance_of_test.cpp \
operator_tests_simple.cpp \
member_pointer_test.cpp \
control_structures.cpp \
switch_construct.cpp \
cast_test.cpp \
operator_tests_simple.cpp \
bind_tests_simple.cpp \
bind_tests_advanced.cpp \
bll_and_function.cpp \
constructor_tests.cpp \
extending_rt_traits.cpp \
bind_tests_simple_f_refs.cpp \
cast_test.cpp \
phoenix_control_structures.cpp \
extending_return_type_traits.cpp \
bind_tests_simple_function_references.cpp \
exception_test.cpp \
@@ -70,14 +69,13 @@ run:
./operator_tests_simple.exe
./control_structures.exe
./switch_construct.exe
./extending_rt_traits.exe
./extending_return_type_traits.exe
./constructor_tests.exe
./cast_test.exe
./bind_tests_simple.exe
./bind_tests_advanced.exe
./bll_and_function.exe
./bind_tests_simple_f_refs.exe
./phoenix_control_structures.exe
./bind_tests_simple_function_references.exe
./exception_test.exe
@@ -87,3 +85,4 @@ run:

View File

@@ -1,55 +0,0 @@
// bll_and_function.cpp - The Boost Lambda Library -----------------------
//
// Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see www.boost.org
// test using BLL and boost::function
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#include "boost/lambda/lambda.hpp"
#include "boost/lambda/bind.hpp"
#include "boost/lambda/algorithm.hpp"
#include <vector>
#include <map>
#include <set>
#include <string>
#include <iostream>
void test_foreach() {
using namespace boost::lambda;
int a[10][20];
int sum = 0;
std::for_each(a, a + 10,
bind(ll::for_each(), _1, _1 + 20,
protect((_1 = var(sum), ++var(sum)))));
sum = 0;
std::for_each(a, a + 10,
bind(ll::for_each(), _1, _1 + 20,
protect((sum += _1))));
BOOST_CHECK(sum == (199 + 1)/ 2 * 199);
}
// More tests needed (for all algorithms)
int main() {
test_foreach();
return boost::report_errors();
}

View File

@@ -1,29 +1,12 @@
// bind_tests_advanced.cpp -- The Boost Lambda Library ------------------
//
// Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com)
// Copyright (C) 2010 Steven Watanabe
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see www.boost.org
// bind_tests_advanced.cpp --------------------------------
// -----------------------------------------------------------------------
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
#include <boost/test/test_tools.hpp> // see "Header Implementation Option"
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#include "boost/lambda/lambda.hpp"
#include "boost/lambda/bind.hpp"
#include "boost/lambda/lambda.hpp"
#include "boost/any.hpp"
#include "boost/type_traits/is_reference.hpp"
#include "boost/mpl/assert.hpp"
#include "boost/mpl/if.hpp"
#include <iostream>
@@ -32,8 +15,7 @@
#include <algorithm>
using namespace boost::lambda;
namespace bl = boost::lambda;
using namespace boost::lambda;
int sum_0() { return 0; }
int sum_1(int a) { return a; }
@@ -51,8 +33,6 @@ fptr_type sum_or_product(bool x) {
// returns a pointer to a binary function.
struct which_one {
typedef fptr_type (*result_type)(bool x);
template <class T> struct sig { typedef result_type type; };
result_type operator()() const { return sum_or_product; }
};
@@ -66,16 +46,16 @@ void test_nested_binds()
bool condition;
condition = true;
BOOST_CHECK(bind(bind(&sum_or_product, _1), 1, 2)(condition)==3);
BOOST_CHECK(bind(bind(&sum_or_product, _1), _2, _3)(condition, j, k)==5);
BOOST_TEST(bind(bind(&sum_or_product, _1), 1, 2)(condition)==3);
BOOST_TEST(bind(bind(&sum_or_product, _1), _2, _3)(condition, j, k)==5);
condition = false;
BOOST_CHECK(bind(bind(&sum_or_product, _1), 1, 2)(condition)==2);
BOOST_CHECK(bind(bind(&sum_or_product, _1), _2, _3)(condition, j, k)==6);
BOOST_TEST(bind(bind(&sum_or_product, _1), 1, 2)(condition)==2);
BOOST_TEST(bind(bind(&sum_or_product, _1), _2, _3)(condition, j, k)==6);
which_one wo;
BOOST_CHECK(bind(bind(bind(wo), _1), _2, _3)(condition, j, k)==6);
BOOST_TEST(bind(bind(bind(wo), _1), _2, _3)(condition, j, k)==6);
return;
@@ -97,7 +77,7 @@ int call_with_100(const F& f) {
// This would result in;
// bind(_1 + 1, _1)(make_const(100)) , which would be a compile time error
return bl::bind(unlambda(f), _1)(make_const(100));
return bind(unlambda(f), _1)(make_const(100));
// for other functors than lambda functors, unlambda has no effect
// (except for making them const)
@@ -106,58 +86,31 @@ int call_with_100(const F& f) {
template<class F>
int call_with_101(const F& f) {
return bind(unlambda(f), _1)(make_const(101));
return bind(unlambda(ret<int>(f)), _1)(make_const(101));
// the ret must be inside of unlambda, since unlambda requires its argument
// to define result_type.
// if F is not a lambda functor ret<int>(f) fails at compile time!
}
void test_unlambda() {
int i = 1;
BOOST_TEST(call_with_100(ret<int>(_1 + 1)) == 101);
// note, that the functor must define the result_type typedef, as the bind
// int the called function does not do that.
BOOST_CHECK(unlambda(_1 + _2)(i, i) == 2);
BOOST_CHECK(unlambda(++var(i))() == 2);
BOOST_CHECK(call_with_100(_1 + 1) == 101);
BOOST_TEST(call_with_101(_1 + 1) == 102);
// This one leaves the return type to be specified by the bind in the
// called function, and that makes things kind of hard in the called
// function
BOOST_TEST(call_with_100(std::bind1st(std::plus<int>(), 1)) == 101);
BOOST_CHECK(call_with_101(_1 + 1) == 102);
#if defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
BOOST_CHECK(call_with_100(bl::bind(std_functor(std::bind1st(std::plus<int>(), 1)), _1)) == 101);
#elif BOOST_CXX_VERSION > 201703L
// In C++20, standard functors no longer have ::result_type
BOOST_CHECK(call_with_100(bl::bind(std::bind(std::plus<int>(), 1, std::placeholders::_1), _1)) == 101);
#elif defined(BOOST_MSVC) && BOOST_MSVC < 1900
// Mysterious failures under msvc-12.0 and below
#else
BOOST_CHECK(call_with_100(bl::bind(std_functor(std::bind(std::plus<int>(), 1, std::placeholders::_1)), _1)) == 101);
#endif
#if BOOST_CXX_VERSION <= 201703L
// std_functor insturcts LL that the functor defines a result_type typedef
// rather than a sig template.
bl::bind(std_functor(std::plus<int>()), _1, _2)(i, i);
#else
// In C++20, standard functors no longer have ::result_type
bl::bind(std::plus<int>(), _1, _2)(i, i);
#endif
// BOOST_TEST(call_with_101(std::bind1st(std::plus<int>(), 1)) == 102);
// this would fail, as it would lead to ret being called with other than
// a lambda functor
}
// protect ------------------------------------------------------------
// protect protects a lambda functor from argument substitution.
@@ -165,14 +118,21 @@ void test_unlambda() {
namespace ll {
struct for_each {
struct for_each : public has_sig {
// note, std::for_each returns it's last argument
// We want the same behaviour from our ll::for_each.
// However, the functor can be called with any arguments, and
// the return type thus depends on the argument types.
// The basic mechanism (provide a result_type typedef) does not
// work.
// There is an alternative for this kind of situations, which LL
// borrows from FC++ (by Yannis Smaragdakis and Brian McNamara).
// 1. Provide a sig class member template:
// If you want to use this mechanism, your function object class needs to
// 1. inhertit publicly from has_sig
// 2. Provide a sig class member template:
// The return type deduction system instantiate this class as:
// sig<Args>::type, where Args is a boost::tuples::cons-list
@@ -188,14 +148,17 @@ struct for_each {
// if the functor has several operator()'s, even if they have different
// number of arguments.
// Note, that the argument types in Args are guaranteed to be non-reference
// types, but they can have cv-qualifiers.
template <class Args>
// Note, that the argument types in Args can be arbitrary types, particularly
// they can be reference types and can have qualifiers or both.
// So some care will be needed in this respect.
template <class Args>
struct sig {
typedef typename boost::remove_const<
typename boost::tuples::element<3, Args>::type
>::type type;
typename boost::remove_reference<
typename boost::tuples::element<3, Args>::type
>::type
>::type type;
};
template <class A, class B, class C>
@@ -215,42 +178,41 @@ void test_protect()
for(int j=0; j<3; ++j) a[j] = b[j];
std::for_each(a, a+3,
bind(ll::for_each(), _1, _1 + 5, protect(_1 = ++var(i))));
bind(ll::for_each(), _1, _1 + 5, protect(_1 = ++var(i))));
// This is how you could output the values (it is uncommented, no output
// from a regression test file):
// std::for_each(a, a+3,
// bind(ll::for_each(), _1, _1 + 5,
// std::cout << constant("\nLine ") << (&_1 - a) << " : "
// << protect(_1)
// )
// << protect(_1)
// )
// );
int sum = 0;
std::for_each(a, a+3,
bind(ll::for_each(), _1, _1 + 5,
bind(ll::for_each(), _1, _1 + 5,
protect(sum += _1))
);
BOOST_CHECK(sum == (1+15)*15/2);
BOOST_TEST(sum == (1+15)*15/2);
sum = 0;
std::for_each(a, a+3,
bind(ll::for_each(), _1, _1 + 5,
bind(ll::for_each(), _1, _1 + 5,
sum += 1 + protect(_1)) // add element count
);
BOOST_CHECK(sum == (1+15)*15/2 + 15);
BOOST_TEST(sum == (1+15)*15/2 + 15);
(1 + protect(_1))(sum);
int k = 0;
((k += constant(1)) += protect(constant(2)))();
BOOST_CHECK(k==1);
BOOST_TEST(k==1);
k = 0;
((k += constant(1)) += protect(constant(2)))()();
BOOST_CHECK(k==3);
BOOST_TEST(k==3);
// note, the following doesn't work:
@@ -270,15 +232,10 @@ void test_protect()
// something like this:
// (protect(std::cout << _1), bind(ref, std::cout << _1))(i)(j);
// the stuff below works, but we do not want extra output to
// cout, must be changed to stringstreams but stringstreams do not
// work due to a bug in the type deduction. Will be fixed...
#if 0
// But for now, ref is not bindable. There are other ways around this:
int x = 1, y = 2;
(protect(std::cout << _1), (std::cout << _1, 0))(x)(y);
// int x = 1, y = 2;
// (protect(std::cout << _1), (std::cout << _1, 0))(x)(y);
// added one dummy value to make the argument to comma an int
// instead of ostream&
@@ -286,10 +243,7 @@ void test_protect()
// Note, the same problem is more apparent without protect
// (std::cout << 1, std::cout << constant(2))(); // does not work
(boost::ref(std::cout << 1), std::cout << constant(2))(); // this does
#endif
// (boost::ref(std::cout << 1), std::cout << constant(2))(); // this does
}
@@ -300,22 +254,17 @@ void test_lambda_functors_as_arguments_to_lambda_functors() {
// Note however, that the argument/type substitution is not entered again.
// This means, that something like this will not work:
(_1 + _2)(_1, make_const(7));
(_1 + _2)(bind(&sum_0), make_const(7));
(_1 + _2)(bind(&sum_0), make_const(7));
// or it does work, but the effect is not to call
// sum_0() + 7, but rather
// bind(sum_0) + 7, which results in another lambda functor
// (lambda functor + int) and can be called again
BOOST_CHECK((_1 + _2)(bind(&sum_0), make_const(7))() == 7);
BOOST_TEST((_1 + _2)(bind(&sum_0), make_const(7))() == 7);
int i = 3, j = 12;
BOOST_CHECK((_1 - _2)(_2, _1)(i, j) == j - i);
// also, note that lambda functor are no special case for bind if received
// as a parameter. In oder to be bindable, the functor must
// defint the sig template, or then
// either define the result_type typedef, have the sig template, or then
// the return type must be defined within the bind call. Lambda functors
// do define the sig template, so if the return type deduction system
// covers the case, there is no need to specify the return type
@@ -323,125 +272,105 @@ void test_lambda_functors_as_arguments_to_lambda_functors() {
int a = 5, b = 6;
// Let type deduction find out the return type
BOOST_CHECK(bind(_1, _2, _3)(unlambda(_1 + _2), a, b) == 11);
// Let type deduction take find out the return type
BOOST_TEST(bind(_1, _2, _3)(_1 + _2, a, b) == 11);
//specify it yourself:
BOOST_CHECK(bind(_1, _2, _3)(ret<int>(_1 + _2), a, b) == 11);
BOOST_CHECK(ret<int>(bind(_1, _2, _3))(_1 + _2, a, b) == 11);
BOOST_CHECK(bind<int>(_1, _2, _3)(_1 + _2, a, b) == 11);
BOOST_TEST(bind(_1, _2, _3)(ret<int>(_1 + _2), a, b) == 11);
BOOST_TEST(ret<int>(bind(_1, _2, _3))(_1 + _2, a, b) == 11);
BOOST_TEST(bind<int>(_1, _2, _3)(_1 + _2, a, b) == 11);
bind(_1,1.0)(_1+_1);
return;
}
void test_currying() {
int a = 1, b = 2, c = 3;
// lambda functors support currying:
// binary functor can be called with just one argument, the result is
// a unary lambda functor.
// 3-ary functor can be called with one or two arguments (and with 3
// of course)
BOOST_TEST((_1 + _2)(a)(b) == 3);
BOOST_TEST((_1 + _2 + _3)(a, b)(c) == 6);
BOOST_TEST((_1 + _2 + _3)(a)(b, c) == 6);
BOOST_TEST((_1 + _2 + _3)(a)(b)(c) == 6);
// Also, lambda functors passed as arguments end up being curryable
BOOST_TEST(bind(_1, _2, _3)(_1 + _2 + _3, a, b)(c) == 6);
BOOST_TEST(bind(_1, _2)(_1 + _2 + _3, a)(b, c) == 6);
BOOST_TEST(bind(_1, _2)(_1 + _2 + _3, a)(b)(c) == 6);
bind(_1, _2)(_1 += (_2 + _3), a)(b)(c);
BOOST_TEST(a == 6);
bind(_1, _2)(a += (_1 + _2 + _3), c)(c)(c);
BOOST_TEST(a == 6+3*c);
a = 1, b = 2, c = 3;
// and protecting should work as well
BOOST_TEST(bind(_1, _2)(_1 + _2 + _3 + protect(_1), a)(b)(c)(a) == 7);
return;
}
void test_const_parameters() {
// (_1 + _2)(1, 2); // this would fail,
// Either make arguments const:
BOOST_CHECK((_1 + _2)(make_const(1), make_const(2)) == 3);
BOOST_TEST((_1 + _2)(make_const(1), make_const(2)) == 3);
// Or use const_parameters:
BOOST_CHECK(const_parameters(_1 + _2)(1, 2) == 3);
BOOST_TEST(const_parameters(_1 + _2)(1, 2) == 3);
}
void test_rvalue_arguments()
{
// Not quite working yet.
// Problems with visual 7.1
// BOOST_CHECK((_1 + _2)(1, 2) == 3);
}
void test_break_const()
{
// break_const is currently unnecessary, as LL supports perfect forwarding
// for up to there argument lambda functors, and LL does not support
// lambda functors with more than 3 args.
// I'll keep the test case around anyway, if more arguments will be supported
// in the future.
// break_const breaks constness! Be careful!
// You need this only if you need to have side effects on some argument(s)
// and some arguments are non-const rvalues and your lambda functors
// take more than 3 arguments.
// and some arguments are non-const rvalues:
// E.g.
int i = 1;
// OLD COMMENT: (_1 += _2)(i, 2) // fails, 2 is a non-const rvalue
// OLD COMMENT: const_parameters(_1 += _2)(i, 2) // fails, side-effect to i
// (_1 += _2)(i, 2) // fails, 2 is a non-const rvalue
// const_parameters(_1 += _2)(i, 2) // fails, side-effect to i
break_const(_1 += _2)(i, 2); // ok
BOOST_CHECK(i == 3);
BOOST_TEST(i == 3);
}
template<class T>
struct func {
template<class Args>
struct sig {
typedef typename boost::tuples::element<1, Args>::type arg1;
// If the argument type is not the same as the expected type,
// return void, which will cause an error. Note that we
// can't just assert that the types are the same, because
// both const and non-const versions can be instantiated
// even though only one is ultimately used.
typedef typename boost::mpl::if_<boost::is_same<arg1, T>,
typename boost::remove_const<arg1>::type,
void
>::type type;
};
template<class U>
U operator()(const U& arg) const {
return arg;
}
};
void test_sig()
{
int i = 1;
BOOST_CHECK(bind(func<int>(), 1)() == 1);
BOOST_CHECK(bind(func<const int>(), _1)(static_cast<const int&>(i)) == 1);
BOOST_CHECK(bind(func<int>(), _1)(i) == 1);
}
class base {
public:
virtual int foo() = 0;
};
class derived : public base {
public:
virtual int foo() {
return 1;
}
};
void test_abstract()
{
derived d;
base& b = d;
BOOST_CHECK(bind(&base::foo, var(b))() == 1);
BOOST_CHECK(bind(&base::foo, *_1)(&b) == 1);
}
int main() {
int test_main(int, char *[]) {
test_nested_binds();
test_unlambda();
test_protect();
test_lambda_functors_as_arguments_to_lambda_functors();
test_currying();
test_const_parameters();
test_rvalue_arguments();
test_break_const();
test_sig();
test_abstract();
return boost::report_errors();
return 0;
}

View File

@@ -1,25 +1,15 @@
// bind_tests_simple.cpp -- The Boost Lambda Library ------------------
//
// Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see www.boost.org
// bind_tests_simple.cpp --------------------------------
// -----------------------------------------------------------------------
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
#include <boost/test/test_tools.hpp> // see "Header Implementation Option"
#include "boost/lambda/bind.hpp"
#include <iostream>
using namespace boost::lambda;
using namespace std;
using namespace boost::lambda;
int sum_of_args_0() { return 0; }
@@ -41,18 +31,6 @@ class A {
public:
A(int n) : i(n) {};
int add(const int& j) { return i + j; }
int add2(int a1, int a2) { return i + a1 + a2; }
int add3(int a1, int a2, int a3) { return i + a1 + a2 + a3; }
int add4(int a1, int a2, int a3, int a4) { return i + a1 + a2 + a3 + a4; }
int add5(int a1, int a2, int a3, int a4, int a5)
{ return i + a1 + a2 + a3 + a4 + a5; }
int add6(int a1, int a2, int a3, int a4, int a5, int a6)
{ return i + a1 + a2 + a3 + a4 + a5 + a6; }
int add7(int a1, int a2, int a3, int a4, int a5, int a6, int a7)
{ return i + a1 + a2 + a3 + a4 + a5 + a6 + a7; }
int add8(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8)
{ return i + a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8; }
};
void test_member_functions()
@@ -61,99 +39,71 @@ void test_member_functions()
A a(10);
int i = 1;
BOOST_CHECK(bind(&A::add, ref(a), _1)(i) == 11);
BOOST_CHECK(bind(&A::add, &a, _1)(i) == 11);
BOOST_CHECK(bind(&A::add, _1, 1)(a) == 11);
BOOST_CHECK(bind(&A::add, _1, 1)(make_const(&a)) == 11);
BOOST_CHECK(bind(&A::add2, _1, 1, 1)(a) == 12);
BOOST_CHECK(bind(&A::add3, _1, 1, 1, 1)(a) == 13);
BOOST_CHECK(bind(&A::add4, _1, 1, 1, 1, 1)(a) == 14);
BOOST_CHECK(bind(&A::add5, _1, 1, 1, 1, 1, 1)(a) == 15);
BOOST_CHECK(bind(&A::add6, _1, 1, 1, 1, 1, 1, 1)(a) == 16);
BOOST_CHECK(bind(&A::add7, _1, 1, 1, 1, 1, 1, 1, 1)(a) == 17);
BOOST_CHECK(bind(&A::add8, _1, 1, 1, 1, 1, 1, 1, 1, 1)(a) == 18);
BOOST_TEST(bind(&A::add, ref(a), _1)(i) == 11);
BOOST_TEST(bind(&A::add, &a, _1)(i) == 11);
BOOST_TEST(bind(&A::add, _1, 1)(a) == 11);
BOOST_TEST(bind(&A::add, _1, 1)(make_const(&a)) == 11);
// This should fail, as lambda functors store arguments as const
// bind(&A::add, a, _1);
}
struct B {
B(int n) : i(n) {};
int i;
};
void test_data_members()
{
using boost::ref;
B b(10);
BOOST_CHECK(bind(&B::i, ref(b))() == 10);
BOOST_CHECK(bind(&B::i, b)() == 10);
BOOST_CHECK(bind(&B::i, _1)(b) == 10);
BOOST_CHECK(bind(&B::i, _1)(B(11)) == 11);
bind(&B::i, ref(b))() = 1;
BOOST_CHECK(b.i == 1);
}
int main() {
int test_main(int, char *[]) {
int i = 1; int j = 2; int k = 3;
int result;
// bind all parameters
BOOST_CHECK(bind(&sum_of_args_0)()==0);
BOOST_CHECK(bind(&sum_of_args_1, 1)()==1);
BOOST_CHECK(bind(&sum_of_args_2, 1, 2)()==3);
BOOST_CHECK(bind(&sum_of_args_3, 1, 2, 3)()==6);
BOOST_CHECK(bind(&sum_of_args_4, 1, 2, 3, 4)()==10);
BOOST_CHECK(bind(&sum_of_args_5, 1, 2, 3, 4, 5)()==15);
BOOST_CHECK(bind(&sum_of_args_6, 1, 2, 3, 4, 5, 6)()==21);
BOOST_CHECK(bind(&sum_of_args_7, 1, 2, 3, 4, 5, 6, 7)()==28);
BOOST_CHECK(bind(&sum_of_args_8, 1, 2, 3, 4, 5, 6, 7, 8)()==36);
BOOST_CHECK(bind(&sum_of_args_9, 1, 2, 3, 4, 5, 6, 7, 8, 9)()==45);
BOOST_TEST(bind(&sum_of_args_0)()==0);
BOOST_TEST(bind(&sum_of_args_1, 1)()==1);
BOOST_TEST(bind(&sum_of_args_2, 1, 2)()==3);
BOOST_TEST(bind(&sum_of_args_3, 1, 2, 3)()==6);
BOOST_TEST(bind(&sum_of_args_4, 1, 2, 3, 4)()==10);
BOOST_TEST(bind(&sum_of_args_5, 1, 2, 3, 4, 5)()==15);
BOOST_TEST(bind(&sum_of_args_6, 1, 2, 3, 4, 5, 6)()==21);
BOOST_TEST(bind(&sum_of_args_7, 1, 2, 3, 4, 5, 6, 7)()==28);
BOOST_TEST(bind(&sum_of_args_8, 1, 2, 3, 4, 5, 6, 7, 8)()==36);
BOOST_TEST(bind(&sum_of_args_9, 1, 2, 3, 4, 5, 6, 7, 8, 9)()==45);
// first parameter open
BOOST_CHECK(bind(&sum_of_args_0)()==0);
BOOST_CHECK(bind(&sum_of_args_1, _1)(i)==1);
BOOST_CHECK(bind(&sum_of_args_2, _1, 2)(i)==3);
BOOST_CHECK(bind(&sum_of_args_3, _1, 2, 3)(i)==6);
BOOST_CHECK(bind(&sum_of_args_4, _1, 2, 3, 4)(i)==10);
BOOST_CHECK(bind(&sum_of_args_5, _1, 2, 3, 4, 5)(i)==15);
BOOST_CHECK(bind(&sum_of_args_6, _1, 2, 3, 4, 5, 6)(i)==21);
BOOST_CHECK(bind(&sum_of_args_7, _1, 2, 3, 4, 5, 6, 7)(i)==28);
BOOST_CHECK(bind(&sum_of_args_8, _1, 2, 3, 4, 5, 6, 7, 8)(i)==36);
BOOST_CHECK(bind(&sum_of_args_9, _1, 2, 3, 4, 5, 6, 7, 8, 9)(i)==45);
BOOST_TEST(bind(&sum_of_args_0)()==0);
BOOST_TEST(bind(&sum_of_args_1, _1)(i)==1);
BOOST_TEST(bind(&sum_of_args_2, _1, 2)(i)==3);
BOOST_TEST(bind(&sum_of_args_3, _1, 2, 3)(i)==6);
BOOST_TEST(bind(&sum_of_args_4, _1, 2, 3, 4)(i)==10);
BOOST_TEST(bind(&sum_of_args_5, _1, 2, 3, 4, 5)(i)==15);
BOOST_TEST(bind(&sum_of_args_6, _1, 2, 3, 4, 5, 6)(i)==21);
BOOST_TEST(bind(&sum_of_args_7, _1, 2, 3, 4, 5, 6, 7)(i)==28);
BOOST_TEST(bind(&sum_of_args_8, _1, 2, 3, 4, 5, 6, 7, 8)(i)==36);
BOOST_TEST(bind(&sum_of_args_9, _1, 2, 3, 4, 5, 6, 7, 8, 9)(i)==45);
// two open arguments
BOOST_CHECK(bind(&sum_of_args_0)()==0);
BOOST_CHECK(bind(&sum_of_args_1, _1)(i)==1);
BOOST_CHECK(bind(&sum_of_args_2, _1, _2)(i, j)==3);
BOOST_CHECK(bind(&sum_of_args_3, _1, _2, 3)(i, j)==6);
BOOST_CHECK(bind(&sum_of_args_4, _1, _2, 3, 4)(i, j)==10);
BOOST_CHECK(bind(&sum_of_args_5, _1, _2, 3, 4, 5)(i, j)==15);
BOOST_CHECK(bind(&sum_of_args_6, _1, _2, 3, 4, 5, 6)(i, j)==21);
BOOST_CHECK(bind(&sum_of_args_7, _1, _2, 3, 4, 5, 6, 7)(i, j)==28);
BOOST_CHECK(bind(&sum_of_args_8, _1, _2, 3, 4, 5, 6, 7, 8)(i, j)==36);
BOOST_CHECK(bind(&sum_of_args_9, _1, _2, 3, 4, 5, 6, 7, 8, 9)(i, j)==45);
BOOST_TEST(bind(&sum_of_args_0)()==0);
BOOST_TEST(bind(&sum_of_args_1, _1)(i)==1);
BOOST_TEST(bind(&sum_of_args_2, _1, _2)(i, j)==3);
BOOST_TEST(bind(&sum_of_args_3, _1, _2, 3)(i, j)==6);
BOOST_TEST(bind(&sum_of_args_4, _1, _2, 3, 4)(i, j)==10);
BOOST_TEST(bind(&sum_of_args_5, _1, _2, 3, 4, 5)(i, j)==15);
BOOST_TEST(bind(&sum_of_args_6, _1, _2, 3, 4, 5, 6)(i, j)==21);
BOOST_TEST(bind(&sum_of_args_7, _1, _2, 3, 4, 5, 6, 7)(i, j)==28);
BOOST_TEST(bind(&sum_of_args_8, _1, _2, 3, 4, 5, 6, 7, 8)(i, j)==36);
BOOST_TEST(bind(&sum_of_args_9, _1, _2, 3, 4, 5, 6, 7, 8, 9)(i, j)==45);
// three open arguments
BOOST_CHECK(bind(&sum_of_args_0)()==0);
BOOST_CHECK(bind(&sum_of_args_1, _1)(i)==1);
BOOST_CHECK(bind(&sum_of_args_2, _1, _2)(i, j)==3);
BOOST_CHECK(bind(&sum_of_args_3, _1, _2, _3)(i, j, k)==6);
BOOST_CHECK(bind(&sum_of_args_4, _1, _2, _3, 4)(i, j, k)==10);
BOOST_CHECK(bind(&sum_of_args_5, _1, _2, _3, 4, 5)(i, j, k)==15);
BOOST_CHECK(bind(&sum_of_args_6, _1, _2, _3, 4, 5, 6)(i, j, k)==21);
BOOST_CHECK(bind(&sum_of_args_7, _1, _2, _3, 4, 5, 6, 7)(i, j, k)==28);
BOOST_CHECK(bind(&sum_of_args_8, _1, _2, _3, 4, 5, 6, 7, 8)(i, j, k)==36);
BOOST_CHECK(bind(&sum_of_args_9, _1, _2, _3, 4, 5, 6, 7, 8, 9)(i, j, k)==45);
BOOST_TEST(bind(&sum_of_args_0)()==0);
BOOST_TEST(bind(&sum_of_args_1, _1)(i)==1);
BOOST_TEST(bind(&sum_of_args_2, _1, _2)(i, j)==3);
BOOST_TEST(bind(&sum_of_args_3, _1, _2, _3)(i, j, k)==6);
BOOST_TEST(bind(&sum_of_args_4, _1, _2, _3, 4)(i, j, k)==10);
BOOST_TEST(bind(&sum_of_args_5, _1, _2, _3, 4, 5)(i, j, k)==15);
BOOST_TEST(bind(&sum_of_args_6, _1, _2, _3, 4, 5, 6)(i, j, k)==21);
BOOST_TEST(bind(&sum_of_args_7, _1, _2, _3, 4, 5, 6, 7)(i, j, k)==28);
BOOST_TEST(bind(&sum_of_args_8, _1, _2, _3, 4, 5, 6, 7, 8)(i, j, k)==36);
BOOST_TEST(bind(&sum_of_args_9, _1, _2, _3, 4, 5, 6, 7, 8, 9)(i, j, k)==45);
// function compositions with bind
BOOST_CHECK(bind(&sum_of_args_3, bind(&sum_of_args_2, _1, 2), 2, 3)(i)==8);
BOOST_CHECK(
BOOST_TEST(bind(&sum_of_args_3, bind(&sum_of_args_2, _1, 2), 2, 3)(i)==8);
BOOST_TEST(
bind(&sum_of_args_9,
bind(&sum_of_args_0), // 0
bind(&sum_of_args_1, _1), // 1
@@ -170,19 +120,19 @@ int main() {
result =
bind(&sum_of_args_1, // 12
bind(&sum_of_args_4, // 12
bind(&sum_of_args_2, // 3
bind(&sum_of_args_1, // 1
bind(&sum_of_args_1, _1) // 1
),
_2),
_2,
_3,
4)
bind(&sum_of_args_2, // 3
bind(&sum_of_args_1, // 1
bind(&sum_of_args_1, _1) // 1
),
_2),
_2,
_3,
4)
)(i, j, k);
BOOST_CHECK(result == 12);
BOOST_TEST(result == 12);
test_member_functions();
return boost::report_errors();
return 0;
}

View File

@@ -1,149 +0,0 @@
// bind_tests_simple.cpp -- The Boost Lambda Library ------------------
//
// Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see www.boost.org
// -----------------------------------------------------------------------
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#include "boost/lambda/bind.hpp"
#include <iostream>
using namespace boost::lambda;
int sum_of_args_0() { return 0; }
int sum_of_args_1(int a) { return a; }
int sum_of_args_2(int a, int b) { return a+b; }
int sum_of_args_3(int a, int b, int c) { return a+b+c; }
int sum_of_args_4(int a, int b, int c, int d) { return a+b+c+d; }
int sum_of_args_5(int a, int b, int c, int d, int e) { return a+b+c+d+e; }
int sum_of_args_6(int a, int b, int c, int d, int e, int f) { return a+b+c+d+e+f; }
int sum_of_args_7(int a, int b, int c, int d, int e, int f, int g) { return a+b+c+d+e+f+g; }
int sum_of_args_8(int a, int b, int c, int d, int e, int f, int g, int h) { return a+b+c+d+e+f+g+h; }
int sum_of_args_9(int a, int b, int c, int d, int e, int f, int g, int h, int i) { return a+b+c+d+e+f+g+h+i; }
// ----------------------------
class A {
int i;
public:
A(int n) : i(n) {};
int add(const int& j) { return i + j; }
};
void test_member_functions()
{
using boost::ref;
A a(10);
int i = 1;
BOOST_CHECK(bind(&A::add, ref(a), _1)(i) == 11);
BOOST_CHECK(bind(&A::add, &a, _1)(i) == 11);
BOOST_CHECK(bind(&A::add, _1, 1)(a) == 11);
BOOST_CHECK(bind(&A::add, _1, 1)(make_const(&a)) == 11);
// This should fail, as lambda functors store arguments as const
// bind(&A::add, a, _1);
}
int main() {
int i = 1; int j = 2; int k = 3;
int result;
// bind all parameters
BOOST_CHECK(bind(sum_of_args_0)()==0);
BOOST_CHECK(bind(sum_of_args_1, 1)()==1);
BOOST_CHECK(bind(sum_of_args_2, 1, 2)()==3);
BOOST_CHECK(bind(sum_of_args_3, 1, 2, 3)()==6);
BOOST_CHECK(bind(sum_of_args_4, 1, 2, 3, 4)()==10);
BOOST_CHECK(bind(sum_of_args_5, 1, 2, 3, 4, 5)()==15);
BOOST_CHECK(bind(sum_of_args_6, 1, 2, 3, 4, 5, 6)()==21);
BOOST_CHECK(bind(sum_of_args_7, 1, 2, 3, 4, 5, 6, 7)()==28);
BOOST_CHECK(bind(sum_of_args_8, 1, 2, 3, 4, 5, 6, 7, 8)()==36);
BOOST_CHECK(bind(sum_of_args_9, 1, 2, 3, 4, 5, 6, 7, 8, 9)()==45);
// first parameter open
BOOST_CHECK(bind(sum_of_args_0)()==0);
BOOST_CHECK(bind(sum_of_args_1, _1)(i)==1);
BOOST_CHECK(bind(sum_of_args_2, _1, 2)(i)==3);
BOOST_CHECK(bind(sum_of_args_3, _1, 2, 3)(i)==6);
BOOST_CHECK(bind(sum_of_args_4, _1, 2, 3, 4)(i)==10);
BOOST_CHECK(bind(sum_of_args_5, _1, 2, 3, 4, 5)(i)==15);
BOOST_CHECK(bind(sum_of_args_6, _1, 2, 3, 4, 5, 6)(i)==21);
BOOST_CHECK(bind(sum_of_args_7, _1, 2, 3, 4, 5, 6, 7)(i)==28);
BOOST_CHECK(bind(sum_of_args_8, _1, 2, 3, 4, 5, 6, 7, 8)(i)==36);
BOOST_CHECK(bind(sum_of_args_9, _1, 2, 3, 4, 5, 6, 7, 8, 9)(i)==45);
// two open arguments
BOOST_CHECK(bind(sum_of_args_0)()==0);
BOOST_CHECK(bind(sum_of_args_1, _1)(i)==1);
BOOST_CHECK(bind(sum_of_args_2, _1, _2)(i, j)==3);
BOOST_CHECK(bind(sum_of_args_3, _1, _2, 3)(i, j)==6);
BOOST_CHECK(bind(sum_of_args_4, _1, _2, 3, 4)(i, j)==10);
BOOST_CHECK(bind(sum_of_args_5, _1, _2, 3, 4, 5)(i, j)==15);
BOOST_CHECK(bind(sum_of_args_6, _1, _2, 3, 4, 5, 6)(i, j)==21);
BOOST_CHECK(bind(sum_of_args_7, _1, _2, 3, 4, 5, 6, 7)(i, j)==28);
BOOST_CHECK(bind(sum_of_args_8, _1, _2, 3, 4, 5, 6, 7, 8)(i, j)==36);
BOOST_CHECK(bind(sum_of_args_9, _1, _2, 3, 4, 5, 6, 7, 8, 9)(i, j)==45);
// three open arguments
BOOST_CHECK(bind(sum_of_args_0)()==0);
BOOST_CHECK(bind(sum_of_args_1, _1)(i)==1);
BOOST_CHECK(bind(sum_of_args_2, _1, _2)(i, j)==3);
BOOST_CHECK(bind(sum_of_args_3, _1, _2, _3)(i, j, k)==6);
BOOST_CHECK(bind(sum_of_args_4, _1, _2, _3, 4)(i, j, k)==10);
BOOST_CHECK(bind(sum_of_args_5, _1, _2, _3, 4, 5)(i, j, k)==15);
BOOST_CHECK(bind(sum_of_args_6, _1, _2, _3, 4, 5, 6)(i, j, k)==21);
BOOST_CHECK(bind(sum_of_args_7, _1, _2, _3, 4, 5, 6, 7)(i, j, k)==28);
BOOST_CHECK(bind(sum_of_args_8, _1, _2, _3, 4, 5, 6, 7, 8)(i, j, k)==36);
BOOST_CHECK(bind(sum_of_args_9, _1, _2, _3, 4, 5, 6, 7, 8, 9)(i, j, k)==45);
// function compositions with bind
BOOST_CHECK(bind(sum_of_args_3, bind(sum_of_args_2, _1, 2), 2, 3)(i)==8);
BOOST_CHECK(
bind(sum_of_args_9,
bind(sum_of_args_0), // 0
bind(sum_of_args_1, _1), // 1
bind(sum_of_args_2, _1, _2), // 3
bind(sum_of_args_3, _1, _2, _3), // 6
bind(sum_of_args_4, _1, _2, _3, 4), // 10
bind(sum_of_args_5, _1, _2, _3, 4, 5), // 15
bind(sum_of_args_6, _1, _2, _3, 4, 5, 6), // 21
bind(sum_of_args_7, _1, _2, _3, 4, 5, 6, 7), // 28
bind(sum_of_args_8, _1, _2, _3, 4, 5, 6, 7, 8) // 36
)(i, j, k) == 120);
// deeper nesting
result =
bind(sum_of_args_1, // 12
bind(sum_of_args_4, // 12
bind(sum_of_args_2, // 3
bind(sum_of_args_1, // 1
bind(sum_of_args_1, _1) // 1
),
_2),
_2,
_3,
4)
)(i, j, k);
BOOST_CHECK(result == 12);
test_member_functions();
return boost::report_errors();
}

View File

@@ -0,0 +1,139 @@
// bind_tests_simple.cpp --------------------------------
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
#include <boost/test/test_tools.hpp> // see "Header Implementation Option"
#include "boost/lambda/bind.hpp"
#include <iostream>
using namespace std;
using namespace boost::lambda;
int sum_of_args_0() { return 0; }
int sum_of_args_1(int a) { return a; }
int sum_of_args_2(int a, int b) { return a+b; }
int sum_of_args_3(int a, int b, int c) { return a+b+c; }
int sum_of_args_4(int a, int b, int c, int d) { return a+b+c+d; }
int sum_of_args_5(int a, int b, int c, int d, int e) { return a+b+c+d+e; }
int sum_of_args_6(int a, int b, int c, int d, int e, int f) { return a+b+c+d+e+f; }
int sum_of_args_7(int a, int b, int c, int d, int e, int f, int g) { return a+b+c+d+e+f+g; }
int sum_of_args_8(int a, int b, int c, int d, int e, int f, int g, int h) { return a+b+c+d+e+f+g+h; }
int sum_of_args_9(int a, int b, int c, int d, int e, int f, int g, int h, int i) { return a+b+c+d+e+f+g+h+i; }
// ----------------------------
class A {
int i;
public:
A(int n) : i(n) {};
int add(const int& j) { return i + j; }
};
void test_member_functions()
{
using boost::ref;
A a(10);
int i = 1;
BOOST_TEST(bind(&A::add, ref(a), _1)(i) == 11);
BOOST_TEST(bind(&A::add, &a, _1)(i) == 11);
BOOST_TEST(bind(&A::add, _1, 1)(a) == 11);
BOOST_TEST(bind(&A::add, _1, 1)(make_const(&a)) == 11);
// This should fail, as lambda functors store arguments as const
// bind(&A::add, a, _1);
}
int test_main(int, char *[]) {
int i = 1; int j = 2; int k = 3;
int result;
// bind all parameters
BOOST_TEST(bind(sum_of_args_0)()==0);
BOOST_TEST(bind(sum_of_args_1, 1)()==1);
BOOST_TEST(bind(sum_of_args_2, 1, 2)()==3);
BOOST_TEST(bind(sum_of_args_3, 1, 2, 3)()==6);
BOOST_TEST(bind(sum_of_args_4, 1, 2, 3, 4)()==10);
BOOST_TEST(bind(sum_of_args_5, 1, 2, 3, 4, 5)()==15);
BOOST_TEST(bind(sum_of_args_6, 1, 2, 3, 4, 5, 6)()==21);
BOOST_TEST(bind(sum_of_args_7, 1, 2, 3, 4, 5, 6, 7)()==28);
BOOST_TEST(bind(sum_of_args_8, 1, 2, 3, 4, 5, 6, 7, 8)()==36);
BOOST_TEST(bind(sum_of_args_9, 1, 2, 3, 4, 5, 6, 7, 8, 9)()==45);
// first parameter open
BOOST_TEST(bind(sum_of_args_0)()==0);
BOOST_TEST(bind(sum_of_args_1, _1)(i)==1);
BOOST_TEST(bind(sum_of_args_2, _1, 2)(i)==3);
BOOST_TEST(bind(sum_of_args_3, _1, 2, 3)(i)==6);
BOOST_TEST(bind(sum_of_args_4, _1, 2, 3, 4)(i)==10);
BOOST_TEST(bind(sum_of_args_5, _1, 2, 3, 4, 5)(i)==15);
BOOST_TEST(bind(sum_of_args_6, _1, 2, 3, 4, 5, 6)(i)==21);
BOOST_TEST(bind(sum_of_args_7, _1, 2, 3, 4, 5, 6, 7)(i)==28);
BOOST_TEST(bind(sum_of_args_8, _1, 2, 3, 4, 5, 6, 7, 8)(i)==36);
BOOST_TEST(bind(sum_of_args_9, _1, 2, 3, 4, 5, 6, 7, 8, 9)(i)==45);
// two open arguments
BOOST_TEST(bind(sum_of_args_0)()==0);
BOOST_TEST(bind(sum_of_args_1, _1)(i)==1);
BOOST_TEST(bind(sum_of_args_2, _1, _2)(i, j)==3);
BOOST_TEST(bind(sum_of_args_3, _1, _2, 3)(i, j)==6);
BOOST_TEST(bind(sum_of_args_4, _1, _2, 3, 4)(i, j)==10);
BOOST_TEST(bind(sum_of_args_5, _1, _2, 3, 4, 5)(i, j)==15);
BOOST_TEST(bind(sum_of_args_6, _1, _2, 3, 4, 5, 6)(i, j)==21);
BOOST_TEST(bind(sum_of_args_7, _1, _2, 3, 4, 5, 6, 7)(i, j)==28);
BOOST_TEST(bind(sum_of_args_8, _1, _2, 3, 4, 5, 6, 7, 8)(i, j)==36);
BOOST_TEST(bind(sum_of_args_9, _1, _2, 3, 4, 5, 6, 7, 8, 9)(i, j)==45);
// three open arguments
BOOST_TEST(bind(sum_of_args_0)()==0);
BOOST_TEST(bind(sum_of_args_1, _1)(i)==1);
BOOST_TEST(bind(sum_of_args_2, _1, _2)(i, j)==3);
BOOST_TEST(bind(sum_of_args_3, _1, _2, _3)(i, j, k)==6);
BOOST_TEST(bind(sum_of_args_4, _1, _2, _3, 4)(i, j, k)==10);
BOOST_TEST(bind(sum_of_args_5, _1, _2, _3, 4, 5)(i, j, k)==15);
BOOST_TEST(bind(sum_of_args_6, _1, _2, _3, 4, 5, 6)(i, j, k)==21);
BOOST_TEST(bind(sum_of_args_7, _1, _2, _3, 4, 5, 6, 7)(i, j, k)==28);
BOOST_TEST(bind(sum_of_args_8, _1, _2, _3, 4, 5, 6, 7, 8)(i, j, k)==36);
BOOST_TEST(bind(sum_of_args_9, _1, _2, _3, 4, 5, 6, 7, 8, 9)(i, j, k)==45);
// function compositions with bind
BOOST_TEST(bind(sum_of_args_3, bind(sum_of_args_2, _1, 2), 2, 3)(i)==8);
BOOST_TEST(
bind(sum_of_args_9,
bind(sum_of_args_0), // 0
bind(sum_of_args_1, _1), // 1
bind(sum_of_args_2, _1, _2), // 3
bind(sum_of_args_3, _1, _2, _3), // 6
bind(sum_of_args_4, _1, _2, _3, 4), // 10
bind(sum_of_args_5, _1, _2, _3, 4, 5), // 15
bind(sum_of_args_6, _1, _2, _3, 4, 5, 6), // 21
bind(sum_of_args_7, _1, _2, _3, 4, 5, 6, 7), // 28
bind(sum_of_args_8, _1, _2, _3, 4, 5, 6, 7, 8) // 36
)(i, j, k) == 120);
// deeper nesting
result =
bind(sum_of_args_1, // 12
bind(sum_of_args_4, // 12
bind(sum_of_args_2, // 3
bind(sum_of_args_1, // 1
bind(sum_of_args_1, _1) // 1
),
_2),
_2,
_3,
4)
)(i, j, k);
BOOST_TEST(result == 12);
test_member_functions();
return 0;
}

View File

@@ -1,18 +1,9 @@
// bll_and_function.cpp - The Boost Lambda Library -----------------------
//
// Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see www.boost.org
// bll_and_function.cpp --------------------------------
// test using BLL and boost::function
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
#include <boost/test/test_tools.hpp> // see "Header Implementation Option"
#include "boost/lambda/lambda.hpp"
@@ -30,23 +21,27 @@ using namespace std;
void test_function() {
boost::function<int (int, int)> f;
f = _1 + _2;
boost::function<int, int, int> f;
f = unlambda(_1 + _2);
BOOST_CHECK(f(1, 2)== 3);
// unlambda must be used, because boost::function tries to take the
// address of the function object that is assigned. However, the
// operator& is overloaded for lambda functors, which creates a conflict
BOOST_TEST(f(1, 2)== 3);
int i=1; int j=2;
boost::function<int& (int&, int)> g = _1 += _2;
boost::function<int&, int&, int> g = unlambda(_1 += _2);
g(i, j);
BOOST_CHECK(i==3);
BOOST_TEST(i==3);
int* sum = new int();
*sum = 0;
boost::function<int& (int)> counter = *sum += _1;
boost::function<int&, int> counter = unlambda(*sum += _1);
counter(5); // ok, sum* = 5;
BOOST_CHECK(*sum == 5);
BOOST_TEST(*sum == 5);
delete sum;
// The next statement would lead to a dangling reference
@@ -55,9 +50,15 @@ void test_function() {
}
int main() {
int test_main(int, char *[]) {
test_function();
return boost::report_errors();
return 0;
}

View File

@@ -1,19 +1,7 @@
// cast_tests.cpp -- The Boost Lambda Library ------------------
//
// Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see www.boost.org
// cast_tests.cpp --------------------------------
// -----------------------------------------------------------------------
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
#include <boost/test/test_tools.hpp> // see "Header Implementation Option"
#include "boost/lambda/lambda.hpp"
@@ -30,7 +18,7 @@ class base {
public:
virtual std::string class_name() const { return "const base"; }
virtual std::string class_name() { return "base"; }
virtual ~base() {}
};
class derived : public base {
@@ -54,46 +42,46 @@ void do_test() {
(var(b) = ll_static_cast<base *>(p_derived))();
(var(d) = ll_static_cast<derived *>(b))();
BOOST_CHECK(b->class_name() == "derived");
BOOST_CHECK(d->class_name() == "derived");
BOOST_TEST(b->class_name() == "derived");
BOOST_TEST(d->class_name() == "derived");
(var(b) = ll_dynamic_cast<derived *>(b))();
BOOST_CHECK(b != 0);
BOOST_CHECK(b->class_name() == "derived");
BOOST_TEST(b != 0);
BOOST_TEST(b->class_name() == "derived");
(var(d) = ll_dynamic_cast<derived *>(p_base))();
BOOST_CHECK(d == 0);
BOOST_TEST(d == 0);
const derived* p_const_derived = p_derived;
BOOST_CHECK(p_const_derived->class_name() == "const derived");
BOOST_TEST(p_const_derived->class_name() == "const derived");
(var(d) = ll_const_cast<derived *>(p_const_derived))();
BOOST_CHECK(d->class_name() == "derived");
BOOST_TEST(d->class_name() == "derived");
int i = 10;
char* cp = reinterpret_cast<char*>(&i);
int* ip;
(var(ip) = ll_reinterpret_cast<int *>(cp))();
BOOST_CHECK(*ip == 10);
BOOST_TEST(*ip == 10);
// typeid
BOOST_CHECK(string(ll_typeid(d)().name()) == string(typeid(d).name()));
BOOST_TEST(string(ll_typeid(d)().name()) == string(typeid(d).name()));
// sizeof
BOOST_CHECK(ll_sizeof(_1)(p_derived) == sizeof(p_derived));
BOOST_CHECK(ll_sizeof(_1)(*p_derived) == sizeof(*p_derived));
BOOST_CHECK(ll_sizeof(_1)(p_base) == sizeof(p_base));
BOOST_CHECK(ll_sizeof(_1)(*p_base) == sizeof(*p_base));
BOOST_TEST(ll_sizeof(_1)(p_derived) == sizeof(p_derived));
BOOST_TEST(ll_sizeof(_1)(*p_derived) == sizeof(*p_derived));
BOOST_TEST(ll_sizeof(_1)(p_base) == sizeof(p_base));
BOOST_TEST(ll_sizeof(_1)(*p_base) == sizeof(*p_base));
int an_array[100];
BOOST_CHECK(ll_sizeof(_1)(an_array) == 100 * sizeof(int));
BOOST_TEST(ll_sizeof(_1)(an_array) == 100 * sizeof(int));
delete p_derived;
delete p_base;
@@ -101,8 +89,8 @@ void do_test() {
}
int main() {
int test_main(int, char *[]) {
do_test();
return boost::report_errors();
return 0;
}

View File

@@ -1,18 +0,0 @@
# 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_lambda REQUIRED)
find_package(boost_core REQUIRED)
add_executable(quick ../quick.cpp)
target_link_libraries(quick Boost::lambda Boost::core)
enable_testing()
add_test(quick quick)
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C $<CONFIG>)

View File

@@ -1,21 +0,0 @@
# Copyright 2018, 2019, 2021 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_subdir_test LANGUAGES CXX)
set(BOOST_INCLUDE_LIBRARIES lambda)
add_subdirectory(../../../../ deps/boost)
# --target check
add_executable(quick ../quick.cpp)
target_link_libraries(quick Boost::lambda Boost::core)
enable_testing()
add_test(quick quick)
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C $<CONFIG>)

View File

@@ -1,19 +1,7 @@
// constructor_tests.cpp -- The Boost Lambda Library ------------------
//
// Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see www.boost.org
// constructor_tests.cpp --------------------------------
// -----------------------------------------------------------------------
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
#include <boost/test/test_tools.hpp> // see "Header Implementation Option"
#include "boost/lambda/lambda.hpp"
@@ -25,12 +13,8 @@
#include <algorithm>
#include <vector>
#ifdef BOOST_MSVC
#pragma warning(disable:4512)
#endif
using namespace boost::lambda;
namespace bl = boost::lambda;
using namespace std;
template<class T>
bool check_tuple(int n, const T& t)
@@ -39,7 +23,7 @@ bool check_tuple(int n, const T& t)
}
template <>
bool check_tuple(int /*n*/, const null_type& ) { return true; }
bool check_tuple(int n, const null_type& ) { return true; }
void constructor_all_lengths()
@@ -50,63 +34,63 @@ void constructor_all_lengths()
bind(constructor<tuple<int> >(),
1)()
);
BOOST_CHECK(ok);
BOOST_TEST(ok);
ok = check_tuple(
1,
bind(constructor<tuple<int, int> >(),
1, 2)()
);
BOOST_CHECK(ok);
BOOST_TEST(ok);
ok = check_tuple(
1,
bind(constructor<tuple<int, int, int> >(),
1, 2, 3)()
);
BOOST_CHECK(ok);
BOOST_TEST(ok);
ok = check_tuple(
1,
bind(constructor<tuple<int, int, int, int> >(),
1, 2, 3, 4)()
);
BOOST_CHECK(ok);
BOOST_TEST(ok);
ok = check_tuple(
1,
bind(constructor<tuple<int, int, int, int, int> >(),
1, 2, 3, 4, 5)()
);
BOOST_CHECK(ok);
BOOST_TEST(ok);
ok = check_tuple(
1,
bind(constructor<tuple<int, int, int, int, int, int> >(),
1, 2, 3, 4, 5, 6)()
);
BOOST_CHECK(ok);
BOOST_TEST(ok);
ok = check_tuple(
1,
bind(constructor<tuple<int, int, int, int, int, int, int> >(),
1, 2, 3, 4, 5, 6, 7)()
);
BOOST_CHECK(ok);
BOOST_TEST(ok);
ok = check_tuple(
1,
bind(constructor<tuple<int, int, int, int, int, int, int, int> >(),
1, 2, 3, 4, 5, 6, 7, 8)()
);
BOOST_CHECK(ok);
BOOST_TEST(ok);
ok = check_tuple(
1,
bind(constructor<tuple<int, int, int, int, int, int, int, int, int> >(),
1, 2, 3, 4, 5, 6, 7, 8, 9)()
);
BOOST_CHECK(ok);
BOOST_TEST(ok);
}
@@ -118,63 +102,63 @@ void new_ptr_all_lengths()
*(bind(new_ptr<tuple<int> >(),
1))()
);
BOOST_CHECK(ok);
BOOST_TEST(ok);
ok = check_tuple(
1,
*(bind(new_ptr<tuple<int, int> >(),
1, 2))()
);
BOOST_CHECK(ok);
BOOST_TEST(ok);
ok = check_tuple(
1,
*(bind(new_ptr<tuple<int, int, int> >(),
1, 2, 3))()
);
BOOST_CHECK(ok);
BOOST_TEST(ok);
ok = check_tuple(
1,
*(bind(new_ptr<tuple<int, int, int, int> >(),
1, 2, 3, 4))()
);
BOOST_CHECK(ok);
BOOST_TEST(ok);
ok = check_tuple(
1,
*(bind(new_ptr<tuple<int, int, int, int, int> >(),
1, 2, 3, 4, 5))()
);
BOOST_CHECK(ok);
BOOST_TEST(ok);
ok = check_tuple(
1,
*(bind(new_ptr<tuple<int, int, int, int, int, int> >(),
1, 2, 3, 4, 5, 6))()
);
BOOST_CHECK(ok);
BOOST_TEST(ok);
ok = check_tuple(
1,
*(bind(new_ptr<tuple<int, int, int, int, int, int, int> >(),
1, 2, 3, 4, 5, 6, 7))()
);
BOOST_CHECK(ok);
BOOST_TEST(ok);
ok = check_tuple(
1,
*(bind(new_ptr<tuple<int, int, int, int, int, int, int, int> >(),
1, 2, 3, 4, 5, 6, 7, 8))()
);
BOOST_CHECK(ok);
BOOST_TEST(ok);
ok = check_tuple(
1,
*(bind(new_ptr<tuple<int, int, int, int, int, int, int, int, int> >(),
1, 2, 3, 4, 5, 6, 7, 8, 9))()
);
BOOST_CHECK(ok);
BOOST_TEST(ok);
}
@@ -188,17 +172,17 @@ public:
void test_destructor ()
{
char space[sizeof(is_destructor_called)];
bool flag = false;
bool flag;
is_destructor_called* idc = new(space) is_destructor_called(flag);
BOOST_CHECK(flag == false);
BOOST_TEST(flag == false);
bind(destructor(), _1)(idc);
BOOST_CHECK(flag == true);
BOOST_TEST(flag == true);
idc = new(space) is_destructor_called(flag);
BOOST_CHECK(flag == false);
BOOST_TEST(flag == false);
bind(destructor(), _1)(*idc);
BOOST_CHECK(flag == true);
BOOST_TEST(flag == true);
}
@@ -213,18 +197,18 @@ int count_deletes::count = 0;
void test_news_and_deletes ()
{
int* i[10];
std::for_each(i, i+10, _1 = bind(new_ptr<int>(), 2));
for_each(i, i+10, _1 = bind(new_ptr<int>(), 2));
int count_errors = 0;
std::for_each(i, i+10, (*_1 == 2) || ++var(count_errors));
BOOST_CHECK(count_errors == 0);
for_each(i, i+10, (*_1 == 2) || ++var(count_errors));
BOOST_TEST(count_errors == 0);
count_deletes* ct[10];
std::for_each(ct, ct+10, _1 = bind(new_ptr<count_deletes>()));
for_each(ct, ct+10, _1 = bind(new_ptr<count_deletes>()));
count_deletes::count = 0;
std::for_each(ct, ct+10, bind(delete_ptr(), _1));
BOOST_CHECK(count_deletes::count == 10);
for_each(ct, ct+10, bind(delete_ptr(), _1));
BOOST_TEST(count_deletes::count == 10);
}
@@ -235,25 +219,25 @@ void test_array_new_and_delete()
count_deletes::count = 0;
bind(delete_array(), _1)(c);
BOOST_CHECK(count_deletes::count == 5);
BOOST_TEST(count_deletes::count == 5);
}
void delayed_construction()
{
std::vector<int> x(3);
std::vector<int> y(3);
vector<int> x(3);
vector<int> y(3);
std::fill(x.begin(), x.end(), 0);
std::fill(y.begin(), y.end(), 1);
fill(x.begin(), x.end(), 0);
fill(y.begin(), y.end(), 1);
std::vector<std::pair<int, int> > v;
vector<pair<int, int> > v;
std::transform(x.begin(), x.end(), y.begin(), std::back_inserter(v),
bl::bind(constructor<std::pair<int, int> >(), _1, _2) );
transform(x.begin(), x.end(), y.begin(), back_inserter(v),
bind(constructor<pair<int, int> >(), _1, _2) );
}
int main() {
int test_main(int, char *[]) {
constructor_all_lengths();
new_ptr_all_lengths();
@@ -262,5 +246,5 @@ int main() {
test_news_and_deletes();
test_array_new_and_delete();
return boost::report_errors();
return 0;
}

View File

@@ -1,40 +1,15 @@
// -- control_structures.cpp -- The Boost Lambda Library ------------------
//
// Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see www.boost.org
// -----------------------------------------------------------------------
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
#include <boost/test/test_tools.hpp> // see "Header Implementation Option"
#include "boost/lambda/lambda.hpp"
#include "boost/lambda/if.hpp"
#include "boost/lambda/loops.hpp"
#include "boost/lambda/control_structures.hpp"
#include <iostream>
#include <algorithm>
#include <vector>
using namespace boost;
using boost::lambda::constant;
using boost::lambda::_1;
using boost::lambda::_2;
using boost::lambda::_3;
using boost::lambda::make_const;
using boost::lambda::for_loop;
using boost::lambda::while_loop;
using boost::lambda::do_while_loop;
using boost::lambda::if_then;
using boost::lambda::if_then_else;
using boost::lambda::if_then_else_return;
using namespace boost::lambda;
// 2 container for_each
template <class InputIter1, class InputIter2, class Function>
@@ -51,41 +26,41 @@ void simple_loops() {
int i;
int arithmetic_series = 0;
for_loop(_1 = 0, _1 < 10, _1++, arithmetic_series += _1)(i);
BOOST_CHECK(arithmetic_series == 45);
BOOST_TEST(arithmetic_series == 45);
// no body case
for_loop(boost::lambda::var(i) = 0, boost::lambda::var(i) < 100, ++boost::lambda::var(i))();
BOOST_CHECK(i == 100);
for_loop(var(i) = 0, var(i) < 100, ++var(i))();
BOOST_TEST(i == 100);
// while loops -------------------------------------------------------
int a = 0, b = 0, c = 0;
while_loop((_1 + _2) >= (_1 * _2), (++_1, ++_2, ++_3))(a, b, c);
BOOST_CHECK(c == 3);
BOOST_TEST(c == 3);
int count;
count = 0; i = 0;
while_loop(_1++ < 10, ++boost::lambda::var(count))(i);
BOOST_CHECK(count == 10);
while_loop(_1++ < 10, ++var(count))(i);
BOOST_TEST(count == 10);
// note that the first parameter of do_while_loop is the condition
count = 0; i = 0;
do_while_loop(_1++ < 10, ++boost::lambda::var(count))(i);
BOOST_CHECK(count == 11);
do_while_loop(_1++ < 10, ++var(count))(i);
BOOST_TEST(count == 11);
a = 0;
do_while_loop(constant(false), _1++)(a);
BOOST_CHECK(a == 1);
BOOST_TEST(a == 1);
// no body cases
a = 40; b = 30;
while_loop(--_1 > _2)(a, b);
BOOST_CHECK(a == b);
BOOST_TEST(a == b);
// (the no body case for do_while_loop is pretty redundant)
a = 40; b = 30;
do_while_loop(--_1 > _2)(a, b);
BOOST_CHECK(a == b);
BOOST_TEST(a == b);
}
@@ -94,31 +69,31 @@ void simple_ifs () {
int value = 42;
if_then(_1 < 0, _1 = 0)(value);
BOOST_CHECK(value == 42);
BOOST_TEST(value == 42);
value = -42;
if_then(_1 < 0, _1 = -_1)(value);
BOOST_CHECK(value == 42);
BOOST_TEST(value == 42);
int min;
if_then_else(_1 < _2, boost::lambda::var(min) = _1, boost::lambda::var(min) = _2)
if_then_else(_1 < _2, var(min) = _1, var(min) = _2)
(make_const(1), make_const(2));
BOOST_CHECK(min == 1);
BOOST_TEST(min == 1);
if_then_else(_1 < _2, boost::lambda::var(min) = _1, boost::lambda::var(min) = _2)
if_then_else(_1 < _2, var(min) = _1, var(min) = _2)
(make_const(5), make_const(3));
BOOST_CHECK(min == 3);
BOOST_TEST(min == 3);
int x, y;
x = -1; y = 1;
BOOST_CHECK(if_then_else_return(_1 < _2, _2, _1)(x, y) == (std::max)(x ,y));
BOOST_CHECK(if_then_else_return(_1 < _2, _2, _1)(y, x) == (std::max)(x ,y));
BOOST_TEST(if_then_else_return(_1 < _2, _2, _1)(x, y) == std::max(x ,y));
BOOST_TEST(if_then_else_return(_1 < _2, _2, _1)(y, x) == std::max(x ,y));
}
int main()
int test_main(int, char *[])
{
simple_loops();
simple_ifs();
return boost::report_errors();
return 0;
}

View File

@@ -1,18 +1,5 @@
// -- exception_test.cpp -- The Boost Lambda Library ------------------
//
// Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see www.boost.org
// -----------------------------------------------------------------------
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
#include <boost/test/test_tools.hpp> // see "Header Implementation Option"
#include "boost/lambda/lambda.hpp"
@@ -30,7 +17,7 @@ using namespace boost::lambda;
using namespace std;
// to prevent unused variables warnings
template <class T> void dummy(const T&) {}
template <class T> void dummy(const T& t) {}
void erroneous_exception_related_lambda_expressions() {
@@ -46,11 +33,11 @@ void erroneous_exception_related_lambda_expressions() {
// this should fail too for the same reason
// try_catch(rethrow(), catch_all(cout << constant("Howdy")))();
// this fails too (_e outside of catch_exception)
// (_1 + _2 + _e)(i, i, i);
// this fails too (_E outside of catch_exception)
// (_1 + _2 + _E)(i, i, i);
// and this (_e outside of catch_exception)
// try_catch( throw_exception(1), catch_all(cout << _e));
// and this (_E outside of catch_exception)
// try_catch( throw_exception(1), catch_all(cout << _E));
// and this (_3 in catch_exception
// try_catch( throw_exception(1), catch_exception<int>(cout << _3));
@@ -99,7 +86,7 @@ void test_different_number_of_catch_blocks() {
)
)(i);
}
BOOST_CHECK(ecount == 1);
BOOST_TEST(ecount == 1);
ecount = 0;
for(int i=1; i<=2; i++)
@@ -114,7 +101,7 @@ void test_different_number_of_catch_blocks() {
)
)(i);
}
BOOST_CHECK(ecount == 2);
BOOST_TEST(ecount == 2);
ecount = 0;
for(int i=1; i<=3; i++)
@@ -132,7 +119,7 @@ void test_different_number_of_catch_blocks() {
)
)(i);
}
BOOST_CHECK(ecount == 3);
BOOST_TEST(ecount == 3);
ecount = 0;
for(int i=1; i<=4; i++)
@@ -153,7 +140,7 @@ void test_different_number_of_catch_blocks() {
)
)(i);
}
BOOST_CHECK(ecount == 4);
BOOST_TEST(ecount == 4);
ecount = 0;
for(int i=1; i<=5; i++)
@@ -177,7 +164,7 @@ void test_different_number_of_catch_blocks() {
)
)(i);
}
BOOST_CHECK(ecount == 5);
BOOST_TEST(ecount == 5);
ecount = 0;
for(int i=1; i<=6; i++)
@@ -204,7 +191,7 @@ void test_different_number_of_catch_blocks() {
)
)(i);
}
BOOST_CHECK(ecount == 6);
BOOST_TEST(ecount == 6);
ecount = 0;
for(int i=1; i<=7; i++)
@@ -234,7 +221,7 @@ void test_different_number_of_catch_blocks() {
)
)(i);
}
BOOST_CHECK(ecount == 7);
BOOST_TEST(ecount == 7);
ecount = 0;
for(int i=1; i<=8; i++)
@@ -267,7 +254,7 @@ void test_different_number_of_catch_blocks() {
)
)(i);
}
BOOST_CHECK(ecount == 8);
BOOST_TEST(ecount == 8);
ecount = 0;
for(int i=1; i<=9; i++)
@@ -303,7 +290,7 @@ void test_different_number_of_catch_blocks() {
)
)(i);
}
BOOST_CHECK(ecount == 9);
BOOST_TEST(ecount == 9);
// with catch(...) blocks
@@ -318,7 +305,7 @@ void test_different_number_of_catch_blocks() {
)
)(i);
}
BOOST_CHECK(ecount == 1);
BOOST_TEST(ecount == 1);
ecount = 0;
for(int i=1; i<=2; i++)
@@ -333,7 +320,7 @@ void test_different_number_of_catch_blocks() {
)
)(i);
}
BOOST_CHECK(ecount == 2);
BOOST_TEST(ecount == 2);
ecount = 0;
for(int i=1; i<=3; i++)
@@ -351,7 +338,7 @@ void test_different_number_of_catch_blocks() {
)
)(i);
}
BOOST_CHECK(ecount == 3);
BOOST_TEST(ecount == 3);
ecount = 0;
for(int i=1; i<=4; i++)
@@ -372,7 +359,7 @@ void test_different_number_of_catch_blocks() {
)
)(i);
}
BOOST_CHECK(ecount == 4);
BOOST_TEST(ecount == 4);
ecount = 0;
for(int i=1; i<=5; i++)
@@ -396,7 +383,7 @@ void test_different_number_of_catch_blocks() {
)
)(i);
}
BOOST_CHECK(ecount == 5);
BOOST_TEST(ecount == 5);
ecount = 0;
for(int i=1; i<=6; i++)
@@ -423,7 +410,7 @@ void test_different_number_of_catch_blocks() {
)
)(i);
}
BOOST_CHECK(ecount == 6);
BOOST_TEST(ecount == 6);
ecount = 0;
for(int i=1; i<=7; i++)
@@ -453,7 +440,7 @@ void test_different_number_of_catch_blocks() {
)
)(i);
}
BOOST_CHECK(ecount == 7);
BOOST_TEST(ecount == 7);
ecount = 0;
for(int i=1; i<=8; i++)
@@ -486,7 +473,7 @@ void test_different_number_of_catch_blocks() {
)
)(i);
}
BOOST_CHECK(ecount == 8);
BOOST_TEST(ecount == 8);
ecount = 0;
for(int i=1; i<=9; i++)
@@ -522,20 +509,7 @@ void test_different_number_of_catch_blocks() {
)
)(i);
}
BOOST_CHECK(ecount == 9);
}
void test_empty_catch_blocks() {
try_catch(
bind(throw_AX, _1),
catch_exception<A1>()
)(make_const(1));
try_catch(
bind(throw_AX, _1),
catch_all()
)(make_const(1));
BOOST_TEST(ecount == 9);
}
@@ -552,12 +526,12 @@ void return_type_matching() {
int i = 1;
BOOST_CHECK(
BOOST_TEST(
try_catch(
_1 + 1,
catch_exception<int>((&_1, rethrow())), // no match, but ok since throws
catch_exception<char>(_e) // ok, char convertible to int
catch_exception<char>(_E) // ok, char convertible to int
)(i)
== 2
@@ -568,22 +542,22 @@ void return_type_matching() {
// try_catch(
// _1 += 1,
// catch_exception<char>(_e) // NOT ok, char not convertible to int&
// catch_exception<char>(_E) // NOT ok, char not convertible to int&
// )(i);
// if you don't care about the return type, you can use make_void
try_catch(
make_void(_1 += 1),
catch_exception<char>(_e) // since try is void, catch can return anything
catch_exception<char>(_E) // since try is void, catch can return anything
)(i);
BOOST_CHECK(i == 2);
BOOST_TEST(i == 2);
try_catch(
(_1 += 1, throw_exception('a')),
catch_exception<char>(_e) // since try throws, it is void,
catch_exception<char>(_E) // since try throws, it is void,
// so catch can return anything
)(i);
BOOST_CHECK(i == 3);
BOOST_TEST(i == 3);
char a = 'a';
try_catch(
@@ -591,28 +565,74 @@ void return_type_matching() {
throw_exception(1),
catch_exception<int>(throw_exception('b'))
),
catch_exception<char>( _1 = _e )
catch_exception<char>( _1 = _E )
)(a);
BOOST_CHECK(a == 'b');
BOOST_TEST(a == 'b');
}
int main() {
int test_main(int, char *[]) {
try
{
test_different_number_of_catch_blocks();
return_type_matching();
test_empty_catch_blocks();
}
catch (int)
catch (int x)
{
BOOST_CHECK(false);
BOOST_TEST(false);
}
catch(...)
{
BOOST_CHECK(false);
BOOST_TEST(false);
}
return boost::report_errors();
return EXIT_SUCCESS;
}
// cout << "Before make void call. i ="<< i << "\n";
// (make_void(free1 += 3))(i);
// cout << "After make void call, should be += 3 i = " << i << "\n";
// int j =0;
// var_type<int>::type vj(var(j));
// (make_void(for_loop(vj = 0, vj < free1, ++vj, cout << vj << "\n")))(i);
// try_catch( make_void(free1 += 3 + free2),
// catch_exception<int>( cout << constant("Should work: ") << free1 + free2 << "\n" )
// )
// (i, i);
// try_catch( make_void(free1 += 3),
// catch_exception<int>( cout << constant("Should work: ") << free1 + free2 << "\n" )
// )
// (i, i);
// try_catch( throw_exception(1),
// catch_exception<int>(
// throw_exception(2) )
// )
// ();
// try_catch( throw_exception(1),
// catch_exception<int>(
// ((cout << constant("caught int: ") << free1 + free2 << "\n")
// ,throw_exception(2) )
// ),
// catch_all(
// ((cout << constant("catch all: ") << free1 + free2 << "\n")
// ,rethrow())
// )
// )(i,i);
// // try_catch which returns (10 is added, so that the try return type is int
// cout << "\n -------------- \n" <<
// try_catch( (throw_exception(5), 10),
// catch_exception<int>( free1 + free2 + freeE ) // returns int
// )
// (i, i) << "\n";

View File

@@ -1,23 +1,10 @@
// extending_return_type_traits.cpp -- The Boost Lambda Library --------
//
// Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see www.boost.org
// extending_return_type_traits.cpp --------------------------------
// -----------------------------------------------------------------------
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
#include <boost/test/test_tools.hpp> // see "Header Implementation Option"
#include "boost/lambda/bind.hpp"
#include "boost/lambda/lambda.hpp"
#include "boost/lambda/detail/suppress_unused.hpp"
#include <iostream>
@@ -25,8 +12,6 @@
#include <algorithm>
using boost::lambda::detail::suppress_unused_variable_warnings;
class A {};
class B {};
@@ -85,7 +70,7 @@ struct plain_return_type_1<other_action<contentsof_action>, A> {
} // lambda
} // boost
void ok(B /*b*/) {}
void ok(B b) {}
void test_unary_operators()
{
@@ -100,7 +85,7 @@ void test_unary_operators()
ok((&_1)(a));
ok((*_1)(a));
BOOST_CHECK((*_1)(make_const(&i)) == 1);
BOOST_TEST((*_1)(make_const(&i)) == 1);
}
class X {};
@@ -131,7 +116,7 @@ class my_vector {};
template<class A, class B>
my_vector<typename return_type_2<arithmetic_action<plus_action>, A&, B&>::type>
operator+(const my_vector<A>& /*a*/, const my_vector<B>& /*b*/)
operator+(const my_vector<A>& a, const my_vector<B>& b)
{
typedef typename
return_type_2<arithmetic_action<plus_action>, A&, B&>::type res_type;
@@ -179,8 +164,8 @@ Z operator^=( X&, const Y&) { return Z(); }
// assignment
class Assign {
public:
void operator=(const Assign& /*a*/) {}
X operator[](const int& /*i*/) { return X(); }
void operator=(const Assign& a) {}
X operator[](const int& i) { return X(); }
};
@@ -203,19 +188,19 @@ struct plain_return_type_2<arithmetic_action<multiply_action>, X, Y> {
// if you want to make a distinction between differently cv-qualified
// types, you need to specialize on a different level:
template<>
struct return_type_2<arithmetic_action<multiply_action>, XX, YY> {
struct return_type_2<arithmetic_action<multiply_action>, XX&, YY&> {
typedef YY type;
};
template<>
struct return_type_2<arithmetic_action<multiply_action>, const XX, const YY> {
struct return_type_2<arithmetic_action<multiply_action>, const XX&, const YY&> {
typedef ZZ type;
};
template<>
struct return_type_2<arithmetic_action<multiply_action>, volatile XX, volatile YY> {
struct return_type_2<arithmetic_action<multiply_action>, volatile XX&, volatile YY&> {
typedef XX type;
};
template<>
struct return_type_2<arithmetic_action<multiply_action>, volatile const XX, const volatile YY> {
struct return_type_2<arithmetic_action<multiply_action>, volatile const XX&, const volatile YY&> {
typedef VV type;
};
@@ -333,16 +318,9 @@ void test_binary_operators() {
XX dummy3 = (_1 * _2)(vxx, vyy);
VV dummy4 = (_1 * _2)(cvxx, cvyy);
suppress_unused_variable_warnings(dummy1);
suppress_unused_variable_warnings(dummy2);
suppress_unused_variable_warnings(dummy3);
suppress_unused_variable_warnings(dummy4);
my_vector<int> v1; my_vector<double> v2;
my_vector<double> d = (_1 + _2)(v1, v2);
suppress_unused_variable_warnings(d);
// bitwise
(_1 << _2)(x, y);
@@ -382,8 +360,14 @@ void test_binary_operators() {
}
int main() {
int test_main(int, char *[]) {
test_unary_operators();
test_binary_operators();
return boost::report_errors();
return 0;
}

View File

@@ -1,19 +1,7 @@
// is_instance_of_test.cpp -- The Boost Lambda Library ------------------
//
// Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see www.boost.org
// is_convertible_to_template_test.cpp ----------------------------
// -----------------------------------------------------------------------
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
#include <boost/test/test_tools.hpp> // see "Header Implementation Option"
#include "boost/lambda/detail/is_instance_of.hpp"
@@ -46,7 +34,7 @@ template <bool b> class X {};
X<boost::lambda::is_instance_of_2<int, A2>::value> x;
int main() {
int test_main(int, char *[]) {
using boost::lambda::is_instance_of_1;
using boost::lambda::is_instance_of_2;
@@ -54,26 +42,27 @@ using boost::lambda::is_instance_of_3;
using boost::lambda::is_instance_of_4;
BOOST_CHECK((is_instance_of_1<B1, A1>::value == true));
BOOST_CHECK((is_instance_of_1<A1<float>, A1>::value == true));
BOOST_CHECK((is_instance_of_1<int, A1>::value == false));
BOOST_CHECK((is_instance_of_1<C1, A1>::value == false));
BOOST_TEST((is_instance_of_1<B1, A1>::value == true));
BOOST_TEST((is_instance_of_1<A1<float>, A1>::value == true));
BOOST_TEST((is_instance_of_1<int, A1>::value == false));
BOOST_TEST((is_instance_of_1<C1, A1>::value == false));
BOOST_CHECK((is_instance_of_2<B2, A2>::value == true));
BOOST_CHECK((is_instance_of_2<A2<int, float>, A2>::value == true));
BOOST_CHECK((is_instance_of_2<int, A2>::value == false));
BOOST_CHECK((is_instance_of_2<C2, A2>::value == false));
BOOST_TEST((is_instance_of_2<B2, A2>::value == true));
BOOST_TEST((is_instance_of_2<A2<int, float>, A2>::value == true));
BOOST_TEST((is_instance_of_2<int, A2>::value == false));
BOOST_TEST((is_instance_of_2<C2, A2>::value == false));
BOOST_CHECK((is_instance_of_3<B3, A3>::value == true));
BOOST_CHECK((is_instance_of_3<A3<int, float, char>, A3>::value == true));
BOOST_CHECK((is_instance_of_3<int, A3>::value == false));
BOOST_CHECK((is_instance_of_3<C3, A3>::value == false));
BOOST_TEST((is_instance_of_3<B3, A3>::value == true));
BOOST_TEST((is_instance_of_3<A3<int, float, char>, A3>::value == true));
BOOST_TEST((is_instance_of_3<int, A3>::value == false));
BOOST_TEST((is_instance_of_3<C3, A3>::value == false));
BOOST_CHECK((is_instance_of_4<B4, A4>::value == true));
BOOST_CHECK((is_instance_of_4<A4<int, float, char, double>, A4>::value == true));
BOOST_CHECK((is_instance_of_4<int, A4>::value == false));
BOOST_CHECK((is_instance_of_4<C4, A4>::value == false));
BOOST_TEST((is_instance_of_4<B4, A4>::value == true));
BOOST_TEST((is_instance_of_4<A4<int, float, char, double>, A4>::value == true));
BOOST_TEST((is_instance_of_4<int, A4>::value == false));
BOOST_TEST((is_instance_of_4<C4, A4>::value == false));
return boost::report_errors();
return 0;
}

View File

@@ -1,26 +0,0 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/lambda/bind.hpp>
#include <boost/config.hpp>
#include <functional>
#if defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE( "Skipping test because BOOST_NO_CXX11_HDR_FUNCTIONAL is defined" )
int main() {}
#else
void func()
{
}
int main()
{
std::function<void()>( boost::lambda::bind( func ) );
}
#endif

View File

@@ -1,30 +0,0 @@
// istreambuf_test - test lambda function objects with istreambuf_iterator
//
// Copyright (c) 2007 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/lambda/lambda.hpp>
#include <boost/core/lightweight_test.hpp>
#include <iterator>
#include <sstream>
#include <algorithm>
int main()
{
using namespace boost::lambda;
std::stringstream is( "ax2" );
std::istreambuf_iterator<char> b2( is );
std::istreambuf_iterator<char> e2;
std::istreambuf_iterator<char> i = std::find_if( b2, e2, _1 == 'x' );
BOOST_TEST( *i == 'x' );
BOOST_TEST( std::distance( i, e2 ) == 2 );
return boost::report_errors();
}

View File

@@ -1,24 +1,14 @@
// member_pointer_test.cpp -- The Boost Lambda Library ------------------
//
// Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see www.boost.org
// member_pointer_test.cpp --------------------------------
// -----------------------------------------------------------------------
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
#include <boost/test/test_tools.hpp> // see "Header Implementation Option"
#include "boost/lambda/lambda.hpp"
#include "boost/lambda/bind.hpp"
#include "boost/lambda/detail/member_ptr.hpp"
#include <string>
using namespace boost::lambda;
@@ -51,65 +41,65 @@ void pointer_to_data_member_tests() {
// int i = 0;
my_struct *y = &x;
BOOST_CHECK((_1 ->* &my_struct::mem)(y) == 3);
BOOST_TEST((_1 ->* &my_struct::mem)(y) == 3);
(_1 ->* &my_struct::mem)(y) = 4;
BOOST_CHECK(x.mem == 4);
BOOST_TEST(x.mem == 4);
((_1 ->* &my_struct::mem) = 5)(y);
BOOST_CHECK(x.mem == 5);
BOOST_TEST(x.mem == 5);
// &my_struct::mem is a temporary, must be constified
((y ->* _1) = 6)(make_const(&my_struct::mem));
BOOST_CHECK(x.mem == 6);
BOOST_TEST(x.mem == 6);
((_1 ->* _2) = 7)(y, make_const(&my_struct::mem));
BOOST_CHECK(x.mem == 7);
BOOST_TEST(x.mem == 7);
}
void pointer_to_member_function_tests() {
my_struct *y = new my_struct(1);
BOOST_CHECK( (_1 ->* &my_struct::foo)(y)() == (y->mem));
BOOST_CHECK( (_1 ->* &my_struct::fooc)(y)() == (y->mem));
BOOST_CHECK( (y ->* _1)(make_const(&my_struct::foo))() == (y->mem));
BOOST_CHECK( (y ->* _1)(make_const(&my_struct::fooc))() == (y->mem));
BOOST_CHECK( (_1 ->* _2)(y, make_const(&my_struct::foo))() == (y->mem));
BOOST_CHECK( (_1 ->* _2)(y, make_const(&my_struct::fooc))() == (y->mem));
BOOST_TEST( (_1 ->* &my_struct::foo)(y)() == (y->mem));
BOOST_TEST( (_1 ->* &my_struct::fooc)(y)() == (y->mem));
BOOST_TEST( (y ->* _1)(make_const(&my_struct::foo))() == (y->mem));
BOOST_TEST( (y ->* _1)(make_const(&my_struct::fooc))() == (y->mem));
BOOST_TEST( (_1 ->* _2)(y, make_const(&my_struct::foo))() == (y->mem));
BOOST_TEST( (_1 ->* _2)(y, make_const(&my_struct::fooc))() == (y->mem));
BOOST_CHECK( (_1 ->* &my_struct::foo1)(y)(1) == (y->mem+1));
BOOST_CHECK( (_1 ->* &my_struct::foo1c)(y)(1) == (y->mem+1));
BOOST_CHECK( (y ->* _1)(make_const(&my_struct::foo1))(1) == (y->mem+1));
BOOST_CHECK( (y ->* _1)(make_const(&my_struct::foo1c))(1) == (y->mem+1));
BOOST_CHECK( (_1 ->* _2)(y, make_const(&my_struct::foo1))(1) == (y->mem+1));
BOOST_CHECK( (_1 ->* _2)(y, make_const(&my_struct::foo1c))(1) == (y->mem+1));
BOOST_TEST( (_1 ->* &my_struct::foo1)(y)(1) == (y->mem+1));
BOOST_TEST( (_1 ->* &my_struct::foo1c)(y)(1) == (y->mem+1));
BOOST_TEST( (y ->* _1)(make_const(&my_struct::foo1))(1) == (y->mem+1));
BOOST_TEST( (y ->* _1)(make_const(&my_struct::foo1c))(1) == (y->mem+1));
BOOST_TEST( (_1 ->* _2)(y, make_const(&my_struct::foo1))(1) == (y->mem+1));
BOOST_TEST( (_1 ->* _2)(y, make_const(&my_struct::foo1c))(1) == (y->mem+1));
BOOST_CHECK( (_1 ->* &my_struct::foo2)(y)(1,2) == (y->mem+1+2));
BOOST_CHECK( (_1 ->* &my_struct::foo2c)(y)(1,2) == (y->mem+1+2));
BOOST_CHECK( (y ->* _1)(make_const(&my_struct::foo2))(1,2) == (y->mem+1+2));
BOOST_CHECK( (y ->* _1)(make_const(&my_struct::foo2c))(1,2) == (y->mem+1+2));
BOOST_CHECK( (_1 ->* _2)(y, make_const(&my_struct::foo2))(1,2) == (y->mem+1+2));
BOOST_CHECK( (_1 ->* _2)(y, make_const(&my_struct::foo2c))(1,2) == (y->mem+1+2));
BOOST_TEST( (_1 ->* &my_struct::foo2)(y)(1,2) == (y->mem+1+2));
BOOST_TEST( (_1 ->* &my_struct::foo2c)(y)(1,2) == (y->mem+1+2));
BOOST_TEST( (y ->* _1)(make_const(&my_struct::foo2))(1,2) == (y->mem+1+2));
BOOST_TEST( (y ->* _1)(make_const(&my_struct::foo2c))(1,2) == (y->mem+1+2));
BOOST_TEST( (_1 ->* _2)(y, make_const(&my_struct::foo2))(1,2) == (y->mem+1+2));
BOOST_TEST( (_1 ->* _2)(y, make_const(&my_struct::foo2c))(1,2) == (y->mem+1+2));
BOOST_CHECK( (_1 ->* &my_struct::foo3)(y)(1,2,3) == (y->mem+1+2+3));
BOOST_CHECK( (_1 ->* &my_struct::foo3c)(y)(1,2,3) == (y->mem+1+2+3));
BOOST_CHECK( (y ->* _1)(make_const(&my_struct::foo3))(1,2,3) == (y->mem+1+2+3));
BOOST_CHECK( (y ->* _1)(make_const(&my_struct::foo3c))(1,2,3) == (y->mem+1+2+3));
BOOST_CHECK( (_1 ->* _2)(y, make_const(&my_struct::foo3))(1,2,3) == (y->mem+1+2+3));
BOOST_CHECK( (_1 ->* _2)(y, make_const(&my_struct::foo3c))(1,2,3) == (y->mem+1+2+3));
BOOST_TEST( (_1 ->* &my_struct::foo3)(y)(1,2,3) == (y->mem+1+2+3));
BOOST_TEST( (_1 ->* &my_struct::foo3c)(y)(1,2,3) == (y->mem+1+2+3));
BOOST_TEST( (y ->* _1)(make_const(&my_struct::foo3))(1,2,3) == (y->mem+1+2+3));
BOOST_TEST( (y ->* _1)(make_const(&my_struct::foo3c))(1,2,3) == (y->mem+1+2+3));
BOOST_TEST( (_1 ->* _2)(y, make_const(&my_struct::foo3))(1,2,3) == (y->mem+1+2+3));
BOOST_TEST( (_1 ->* _2)(y, make_const(&my_struct::foo3c))(1,2,3) == (y->mem+1+2+3));
BOOST_CHECK( (_1 ->* &my_struct::foo4)(y)(1,2,3,4) == (y->mem+1+2+3+4));
BOOST_CHECK( (_1 ->* &my_struct::foo4c)(y)(1,2,3,4) == (y->mem+1+2+3+4));
BOOST_CHECK( (y ->* _1)(make_const(&my_struct::foo4))(1,2,3,4) == (y->mem+1+2+3+4));
BOOST_CHECK( (y ->* _1)(make_const(&my_struct::foo4c))(1,2,3,4) == (y->mem+1+2+3+4));
BOOST_CHECK( (_1 ->* _2)(y, make_const(&my_struct::foo4))(1,2,3,4) == (y->mem+1+2+3+4));
BOOST_CHECK( (_1 ->* _2)(y, make_const(&my_struct::foo4c))(1,2,3,4) == (y->mem+1+2+3+4));
BOOST_TEST( (_1 ->* &my_struct::foo4)(y)(1,2,3,4) == (y->mem+1+2+3+4));
BOOST_TEST( (_1 ->* &my_struct::foo4c)(y)(1,2,3,4) == (y->mem+1+2+3+4));
BOOST_TEST( (y ->* _1)(make_const(&my_struct::foo4))(1,2,3,4) == (y->mem+1+2+3+4));
BOOST_TEST( (y ->* _1)(make_const(&my_struct::foo4c))(1,2,3,4) == (y->mem+1+2+3+4));
BOOST_TEST( (_1 ->* _2)(y, make_const(&my_struct::foo4))(1,2,3,4) == (y->mem+1+2+3+4));
BOOST_TEST( (_1 ->* _2)(y, make_const(&my_struct::foo4c))(1,2,3,4) == (y->mem+1+2+3+4));
// member functions with default values do not work (inherent language issue)
// BOOST_CHECK( (_1 ->* &my_struct::foo3default)(y)() == (y->mem+1+2+3));
// BOOST_TEST( (_1 ->* &my_struct::foo3default)(y)() == (y->mem+1+2+3));
}
@@ -119,43 +109,40 @@ class C {};
class D {};
// ->* can be overloaded to do anything
bool operator->*(A /*a*/, B /*b*/) {
bool operator->*(A a, B b) {
return false;
}
bool operator->*(B /*b*/, A /*a*/) {
bool operator->*(B b, A a) {
return true;
}
// let's provide specializations to take care of the return type deduction.
// Note, that you need to provide all four cases for non-const and const
// or use the plain_return_type_2 template.
// references :(
namespace boost {
namespace lambda {
template <>
struct return_type_2<other_action<member_pointer_action>, B, A> {
struct return_type_2<other_action<member_pointer_action>, B&, A&> {
typedef bool type;
};
template<>
struct return_type_2<other_action<member_pointer_action>, const B, A> {
struct return_type_2<other_action<member_pointer_action>, const B&, A&> {
typedef bool type;
};
template<>
struct return_type_2<other_action<member_pointer_action>, B, const A> {
struct return_type_2<other_action<member_pointer_action>, B&, const A&> {
typedef bool type;
};
template<>
struct return_type_2<other_action<member_pointer_action>, const B, const A> {
struct return_type_2<other_action<member_pointer_action>, const B&, const A&> {
typedef bool type;
};
} // lambda
} // boost
@@ -164,29 +151,30 @@ void test_overloaded_pointer_to_member()
A a; B b;
// this won't work, can't deduce the return type
// BOOST_CHECK((_1->*_2)(a, b) == false);
// BOOST_TEST((_1->*_2)(a, b) == false);
// ret<bool> gives the return type
BOOST_CHECK(ret<bool>(_1->*_2)(a, b) == false);
BOOST_CHECK(ret<bool>(a->*_1)(b) == false);
BOOST_CHECK(ret<bool>(_1->*b)(a) == false);
BOOST_CHECK((ret<bool>((var(a))->*b))() == false);
BOOST_CHECK((ret<bool>((var(a))->*var(b)))() == false);
BOOST_TEST(ret<bool>(_1->*_2)(a, b) == false);
BOOST_TEST(ret<bool>(a->*_1)(b) == false);
BOOST_TEST(ret<bool>(_1->*b)(a) == false);
BOOST_TEST((ret<bool>((var(a))->*b))() == false);
BOOST_TEST((ret<bool>((var(a))->*var(b)))() == false);
// this is ok without ret<bool> due to the return_type_2 spcialization above
BOOST_CHECK((_1->*_2)(b, a) == true);
BOOST_CHECK((b->*_1)(a) == true);
BOOST_CHECK((_1->*a)(b) == true);
BOOST_CHECK((var(b)->*a)() == true);
BOOST_TEST((_1->*_2)(b, a) == true);
BOOST_TEST((b->*_1)(a) == true);
BOOST_TEST((_1->*a)(b) == true);
BOOST_TEST((var(b)->*a)() == true);
return;
}
int main() {
int test_main(int, char *[]) {
pointer_to_data_member_tests();
pointer_to_member_function_tests();
test_overloaded_pointer_to_member();
return boost::report_errors();
return 0;
}

View File

@@ -1,40 +1,15 @@
// operator_tests_simple.cpp -- The Boost Lambda Library ---------------
//
// Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see www.boost.org
// operator_tests_simple.cpp --------------------------------
// -----------------------------------------------------------------------
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
#include <boost/test/test_tools.hpp> // see "Header Implementation Option"
#include "boost/lambda/lambda.hpp"
#include "boost/lambda/detail/suppress_unused.hpp"
#include <boost/shared_ptr.hpp>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <iostream>
#ifndef BOOST_NO_STRINGSTREAM
#include <sstream>
#endif
using namespace std;
using namespace boost;
using namespace boost::lambda;
@@ -42,161 +17,121 @@ using namespace boost::lambda;
class unary_plus_tester {};
unary_plus_tester operator+(const unary_plus_tester& a) { return a; }
void cout_tests()
{
#ifndef BOOST_NO_STRINGSTREAM
using std::cout;
ostringstream os;
int i = 10;
(os << _1)(i);
(os << constant("FOO"))();
BOOST_CHECK(os.str() == std::string("10FOO"));
istringstream is("ABC 1");
std::string s;
int k;
is >> s;
is >> k;
BOOST_CHECK(s == std::string("ABC"));
BOOST_CHECK(k == 1);
// test for constant, constant_ref and var
i = 5;
constant_type<int>::type ci(constant(i));
var_type<int>::type vi(var(i));
(vi = _1)(make_const(100));
BOOST_CHECK((ci)() == 5);
BOOST_CHECK(i == 100);
int a;
constant_ref_type<int>::type cr(constant_ref(i));
(++vi, var(a) = cr)();
BOOST_CHECK(i == 101);
#endif
}
void arithmetic_operators() {
int i = 1; int j = 2; int k = 3;
using namespace std;
using namespace boost::lambda;
BOOST_CHECK((_1 + 1)(i)==2);
BOOST_CHECK(((_1 + 1) * _2)(i, j)==4);
BOOST_CHECK((_1 - 1)(i)==0);
BOOST_TEST((_1 + 1)(i)==2);
BOOST_TEST(((_1 + 1) * _2)(i, j)==4);
BOOST_TEST((_1 - 1)(i)==0);
BOOST_CHECK((_1 * 2)(j)==4);
BOOST_CHECK((_1 / 2)(j)==1);
BOOST_TEST((_1 * 2)(j)==4);
BOOST_TEST((_1 / 2)(j)==1);
BOOST_CHECK((_1 % 2)(k)==1);
BOOST_TEST((_1 % 2)(k)==1);
BOOST_CHECK((-_1)(i) == -1);
BOOST_CHECK((+_1)(i) == 1);
BOOST_TEST((-_1)(i) == -1);
BOOST_TEST((+_1)(i) == 1);
// test that unary plus really does something
unary_plus_tester u;
unary_plus_tester up = (+_1)(u);
boost::lambda::detail::suppress_unused_variable_warnings(up);
}
void bitwise_operators() {
unsigned int ui = 2;
BOOST_CHECK((_1 << 1)(ui)==(2 << 1));
BOOST_CHECK((_1 >> 1)(ui)==(2 >> 1));
BOOST_TEST((_1 << 1)(ui)==(2 << 1));
BOOST_TEST((_1 >> 1)(ui)==(2 >> 1));
BOOST_CHECK((_1 & 1)(ui)==(2 & 1));
BOOST_CHECK((_1 | 1)(ui)==(2 | 1));
BOOST_CHECK((_1 ^ 1)(ui)==(2 ^ 1));
BOOST_CHECK((~_1)(ui)==~2u);
BOOST_TEST((_1 & 1)(ui)==(2 & 1));
BOOST_TEST((_1 | 1)(ui)==(2 | 1));
BOOST_TEST((_1 ^ 1)(ui)==(2 ^ 1));
BOOST_TEST((~_1)(ui)==~2);
}
void comparison_operators() {
int i = 0, j = 1;
BOOST_CHECK((_1 < _2)(i, j) == true);
BOOST_CHECK((_1 <= _2)(i, j) == true);
BOOST_CHECK((_1 == _2)(i, j) == false);
BOOST_CHECK((_1 != _2)(i, j) == true);
BOOST_CHECK((_1 > _2)(i, j) == false);
BOOST_CHECK((_1 >= _2)(i, j) == false);
BOOST_TEST((_1 < _2)(i, j) == true);
BOOST_TEST((_1 <= _2)(i, j) == true);
BOOST_TEST((_1 == _2)(i, j) == false);
BOOST_TEST((_1 != _2)(i, j) == true);
BOOST_TEST((_1 > _2)(i, j) == false);
BOOST_TEST((_1 >= _2)(i, j) == false);
BOOST_CHECK((!(_1 < _2))(i, j) == false);
BOOST_CHECK((!(_1 <= _2))(i, j) == false);
BOOST_CHECK((!(_1 == _2))(i, j) == true);
BOOST_CHECK((!(_1 != _2))(i, j) == false);
BOOST_CHECK((!(_1 > _2))(i, j) == true);
BOOST_CHECK((!(_1 >= _2))(i, j) == true);
BOOST_TEST((!(_1 < _2))(i, j) == false);
BOOST_TEST((!(_1 <= _2))(i, j) == false);
BOOST_TEST((!(_1 == _2))(i, j) == true);
BOOST_TEST((!(_1 != _2))(i, j) == false);
BOOST_TEST((!(_1 > _2))(i, j) == true);
BOOST_TEST((!(_1 >= _2))(i, j) == true);
}
void logical_operators() {
bool t = true, f = false;
BOOST_CHECK((_1 && _2)(t, t) == true);
BOOST_CHECK((_1 && _2)(t, f) == false);
BOOST_CHECK((_1 && _2)(f, t) == false);
BOOST_CHECK((_1 && _2)(f, f) == false);
BOOST_TEST((_1 && _2)(t, t) == true);
BOOST_TEST((_1 && _2)(t, f) == false);
BOOST_TEST((_1 && _2)(f, t) == false);
BOOST_TEST((_1 && _2)(f, f) == false);
BOOST_CHECK((_1 || _2)(t, t) == true);
BOOST_CHECK((_1 || _2)(t, f) == true);
BOOST_CHECK((_1 || _2)(f, t) == true);
BOOST_CHECK((_1 || _2)(f, f) == false);
BOOST_TEST((_1 || _2)(t, t) == true);
BOOST_TEST((_1 || _2)(t, f) == true);
BOOST_TEST((_1 || _2)(f, t) == true);
BOOST_TEST((_1 || _2)(f, f) == false);
BOOST_CHECK((!_1)(t) == false);
BOOST_CHECK((!_1)(f) == true);
BOOST_TEST((!_1)(t) == false);
BOOST_TEST((!_1)(f) == true);
// test short circuiting
int i=0;
(false && ++_1)(i);
BOOST_CHECK(i==0);
BOOST_TEST(i==0);
i = 0;
(true && ++_1)(i);
BOOST_CHECK(i==1);
BOOST_TEST(i==1);
i = 0;
(false || ++_1)(i);
BOOST_CHECK(i==1);
BOOST_TEST(i==1);
i = 0;
(true || ++_1)(i);
BOOST_CHECK(i==0);
BOOST_TEST(i==0);
i = 0;
}
void unary_incs_and_decs() {
int i = 0;
BOOST_CHECK(_1++(i) == 0);
BOOST_CHECK(i == 1);
BOOST_TEST(_1++(i) == 0);
BOOST_TEST(i == 1);
i = 0;
BOOST_CHECK(_1--(i) == 0);
BOOST_CHECK(i == -1);
BOOST_TEST(_1--(i) == 0);
BOOST_TEST(i == -1);
i = 0;
BOOST_CHECK((++_1)(i) == 1);
BOOST_CHECK(i == 1);
BOOST_TEST((++_1)(i) == 1);
BOOST_TEST(i == 1);
i = 0;
BOOST_CHECK((--_1)(i) == -1);
BOOST_CHECK(i == -1);
BOOST_TEST((--_1)(i) == -1);
BOOST_TEST(i == -1);
i = 0;
// the result of prefix -- and ++ are lvalues
(++_1)(i) = 10;
BOOST_CHECK(i==10);
BOOST_TEST(i==10);
i = 0;
(--_1)(i) = 10;
BOOST_CHECK(i==10);
BOOST_TEST(i==10);
i = 0;
}
@@ -206,93 +141,77 @@ void compound_operators() {
// normal variable as the left operand
(i += _1)(make_const(1));
BOOST_CHECK(i == 2);
BOOST_TEST(i == 2);
(i -= _1)(make_const(1));
BOOST_CHECK(i == 1);
BOOST_TEST(i == 1);
(i *= _1)(make_const(10));
BOOST_CHECK(i == 10);
BOOST_TEST(i == 10);
(i /= _1)(make_const(2));
BOOST_CHECK(i == 5);
BOOST_TEST(i == 5);
(i %= _1)(make_const(2));
BOOST_CHECK(i == 1);
BOOST_TEST(i == 1);
// lambda expression as a left operand
(_1 += 1)(i);
BOOST_CHECK(i == 2);
BOOST_TEST(i == 2);
(_1 -= 1)(i);
BOOST_CHECK(i == 1);
BOOST_TEST(i == 1);
(_1 *= 10)(i);
BOOST_CHECK(i == 10);
BOOST_TEST(i == 10);
(_1 /= 2)(i);
BOOST_CHECK(i == 5);
BOOST_TEST(i == 5);
(_1 %= 2)(i);
BOOST_CHECK(i == 1);
// lambda expression as a left operand with rvalue on RHS
(_1 += (0 + 1))(i);
BOOST_CHECK(i == 2);
(_1 -= (0 + 1))(i);
BOOST_CHECK(i == 1);
(_1 *= (0 + 10))(i);
BOOST_CHECK(i == 10);
(_1 /= (0 + 2))(i);
BOOST_CHECK(i == 5);
(_1 %= (0 + 2))(i);
BOOST_CHECK(i == 1);
BOOST_TEST(i == 1);
// shifts
unsigned int ui = 2;
(_1 <<= 1)(ui);
BOOST_CHECK(ui==(2 << 1));
BOOST_TEST(ui==(2 << 1));
ui = 2;
(_1 >>= 1)(ui);
BOOST_CHECK(ui==(2 >> 1));
BOOST_TEST(ui==(2 >> 1));
ui = 2;
(ui <<= _1)(make_const(1));
BOOST_CHECK(ui==(2 << 1));
BOOST_TEST(ui==(2 << 1));
ui = 2;
(ui >>= _1)(make_const(1));
BOOST_CHECK(ui==(2 >> 1));
BOOST_TEST(ui==(2 >> 1));
// and, or, xor
ui = 2;
(_1 &= 1)(ui);
BOOST_CHECK(ui==(2 & 1));
BOOST_TEST(ui==(2 & 1));
ui = 2;
(_1 |= 1)(ui);
BOOST_CHECK(ui==(2 | 1));
BOOST_TEST(ui==(2 | 1));
ui = 2;
(_1 ^= 1)(ui);
BOOST_CHECK(ui==(2 ^ 1));
BOOST_TEST(ui==(2 ^ 1));
ui = 2;
(ui &= _1)(make_const(1));
BOOST_CHECK(ui==(2 & 1));
BOOST_TEST(ui==(2 & 1));
ui = 2;
(ui |= _1)(make_const(1));
BOOST_CHECK(ui==(2 | 1));
BOOST_TEST(ui==(2 | 1));
ui = 2;
(ui ^= _1)(make_const(1));
BOOST_CHECK(ui==(2 ^ 1));
BOOST_TEST(ui==(2 ^ 1));
}
@@ -306,24 +225,24 @@ void assignment_and_subscript() {
string s;
(_1 = "one")(s);
BOOST_CHECK(s == string("one"));
BOOST_TEST(s == string("one"));
(var(s) = "two")();
BOOST_CHECK(s == string("two"));
BOOST_TEST(s == string("two"));
BOOST_CHECK((var(s)[_1])(make_const(2)) == 'o');
BOOST_CHECK((_1[2])(s) == 'o');
BOOST_CHECK((_1[_2])(s, make_const(2)) == 'o');
BOOST_TEST((var(s)[_1])(make_const(2)) == 'o');
BOOST_TEST((_1[2])(s) == 'o');
BOOST_TEST((_1[_2])(s, make_const(2)) == 'o');
// subscript returns lvalue
(var(s)[_1])(make_const(1)) = 'o';
BOOST_CHECK(s == "too");
BOOST_TEST(s == "too");
(_1[1])(s) = 'a';
BOOST_CHECK(s == "tao");
BOOST_TEST(s == "tao");
(_1[_2])(s, make_const(0)) = 'm';
BOOST_CHECK(s == "mao");
BOOST_TEST(s == "mao");
// TODO: tests for vector, set, map, multimap
}
@@ -334,26 +253,16 @@ void address_of_and_dereference() {
A a; int i = 42;
BOOST_CHECK((&_1)(a) == &a);
BOOST_CHECK((*&_1)(i) == 42);
BOOST_TEST((&_1)(a) == &a);
BOOST_TEST((*&_1)(i) == 42);
std::vector<int> vi; vi.push_back(1);
std::vector<int>::iterator it = vi.begin();
(*_1 = 7)(it);
BOOST_CHECK(vi[0] == 7);
const std::vector<int>::iterator cit(it);
(*_1 = 8)(cit);
BOOST_CHECK(vi[0] == 8);
BOOST_TEST(vi[0] == 7);
// TODO: Add tests for more complex iterator types
boost::shared_ptr<int> ptr(new int(0));
(*_1 = 7)(ptr);
BOOST_CHECK(*ptr == 7);
const boost::shared_ptr<int> cptr(ptr);
(*_1 = 8)(cptr);
BOOST_CHECK(*ptr == 8);
}
@@ -361,7 +270,7 @@ void address_of_and_dereference() {
void comma() {
int i = 100;
BOOST_CHECK((_1 = 10, 2 * _1)(i) == 20);
BOOST_TEST((_1 = 10, 2 * _1)(i) == 20);
// TODO: that the return type is the exact type of the right argument
// (that r/l valueness is preserved)
@@ -380,36 +289,36 @@ void pointer_arithmetic() {
// non-const array
BOOST_CHECK((*(_1 + 1))(ia) == 2);
BOOST_TEST((*(_1 + 1))(ia) == 2);
// non-const pointer
BOOST_CHECK((*(_1 + 1))(ip) == 2);
BOOST_TEST((*(_1 + 1))(ip) == 2);
BOOST_CHECK((*(_1 - 1))(ia_last) == 3);
BOOST_TEST((*(_1 - 1))(ia_last) == 3);
// const array
BOOST_CHECK((*(_1 + 1))(cia) == 2);
BOOST_TEST((*(_1 + 1))(cia) == 2);
// const pointer
BOOST_CHECK((*(_1 + 1))(cip) == 2);
BOOST_CHECK((*(_1 - 1))(cia_last) == 3);
BOOST_TEST((*(_1 + 1))(cip) == 2);
BOOST_TEST((*(_1 - 1))(cia_last) == 3);
// pointer arithmetic should not make non-consts const
(*(_1 + 2))(ia) = 0;
(*(_1 + 3))(ip) = 0;
BOOST_CHECK(ia[2] == 0);
BOOST_CHECK(ia[3] == 0);
BOOST_TEST(ia[2] == 0);
BOOST_TEST(ia[3] == 0);
// pointer - pointer
BOOST_CHECK((_1 - _2)(ia_last, ia) == 3);
BOOST_CHECK((_1 - _2)(cia_last, cia) == 3);
BOOST_CHECK((ia_last - _1)(ia) == 3);
BOOST_CHECK((cia_last - _1)(cia) == 3);
BOOST_CHECK((cia_last - _1)(cip) == 3);
BOOST_TEST((_1 - _2)(ia_last, ia) == 3);
BOOST_TEST((_1 - _2)(cia_last, cia) == 3);
BOOST_TEST((ia_last - _1)(ia) == 3);
BOOST_TEST((cia_last - _1)(cia) == 3);
BOOST_TEST((cia_last - _1)(cip) == 3);
}
int main() {
int test_main(int, char *[]) {
arithmetic_operators();
bitwise_operators();
@@ -421,6 +330,12 @@ int main() {
address_of_and_dereference();
comma();
pointer_arithmetic();
cout_tests();
return boost::report_errors();
return 0;
}

View File

@@ -1,148 +0,0 @@
// phoenix_style_control_structures.cpp -- The Boost Lambda Library ------
//
// Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see www.boost.org
// -----------------------------------------------------------------------
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#include "boost/lambda/lambda.hpp"
#include "boost/lambda/if.hpp"
#include "boost/lambda/loops.hpp"
#include <iostream>
#include <vector>
#include <list>
#include <algorithm>
#include <cmath>
#include <cassert>
#include <functional>
using namespace boost::lambda;
using namespace std;
// If-else, while, do-while, for statements
int main() {
vector<int> v;
v.clear();
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
v.push_back(6);
v.push_back(7);
v.push_back(8);
v.push_back(9);
v.push_back(10);
int sum = 0;
//////////////////////////////////
for_each(v.begin(), v.end(),
if_(_1 > 3 && _1 <= 8)
[
sum += _1
]
);
BOOST_CHECK(sum == 4+5+6+7+8);
int gt = 0, eq = 0, lt = 0;
//////////////////////////////////
for_each(v.begin(), v.end(),
if_(_1 > 5)
[
++var(gt)
]
.else_
[
if_(_1 == 5)
[
++var(eq)
]
.else_
[
++var(lt)
]
]
);
BOOST_CHECK(lt==4);
BOOST_CHECK(eq==1);
BOOST_CHECK(gt==5);
vector<int> t = v;
int counta = 0;
int countb = 0;
//////////////////////////////////
for_each(v.begin(), v.end(),
(
while_(_1--)
[
++var(counta)
],
++var(countb)
)
);
BOOST_CHECK(counta == 55);
BOOST_CHECK(countb == 10);
v = t;
counta = 0; countb = 0;
//////////////////////////////////
for_each(v.begin(), v.end(),
(
do_
[
++var(counta)
]
.while_(_1--),
++var(countb)
)
);
BOOST_CHECK(counta == (2+11)*10/2);
BOOST_CHECK(countb == 10);
v = t;
counta = 0; countb = 0;
//////////////////////////////////
int iii;
for_each(v.begin(), v.end(),
(
for_(var(iii) = 0, var(iii) < _1, ++var(iii))
[
++var(counta)
],
++var(countb)
)
);
BOOST_CHECK(counta == (1+10)*10/2);
BOOST_CHECK(countb == 10);
v = t;
return boost::report_errors();
}

View File

@@ -1,15 +0,0 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/lambda/lambda.hpp>
#include <boost/core/lightweight_test.hpp>
int main()
{
using namespace boost::lambda;
BOOST_TEST_EQ( (_1 + _2)(1, 2), 3 );
return boost::report_errors();
}

View File

@@ -1,317 +0,0 @@
// result_of_tests.cpp -- The Boost Lambda Library ------------------
//
// Copyright (C) 2010 Steven Watanabe
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see www.boost.org
// -----------------------------------------------------------------------
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#include <boost/lambda/bind.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/is_same.hpp>
struct with_result_type {
typedef int result_type;
int operator()() const { return 0; }
int operator()(int) const { return 1; }
int operator()(int, int) const { return 2; }
int operator()(int, int, int) const { return 3; }
int operator()(int, int, int, int) const { return 4; }
int operator()(int, int, int, int, int) const { return 5; }
int operator()(int, int, int, int, int, int) const { return 6; }
int operator()(int, int, int, int, int, int, int) const { return 7; }
int operator()(int, int, int, int, int, int, int, int) const { return 8; }
int operator()(int, int, int, int, int, int, int, int, int) const { return 9; }
};
struct with_result_template_value {
template<class Sig>
struct result;
template<class This>
struct result<This()> {
typedef int type;
};
template<class This, class A1>
struct result<This(A1)> {
BOOST_MPL_ASSERT((boost::is_same<A1, int>));
typedef int type;
};
template<class This, class A1, class A2>
struct result<This(A1, A2)> {
BOOST_MPL_ASSERT((boost::is_same<A1, int>));
BOOST_MPL_ASSERT((boost::is_same<A2, int>));
typedef int type;
};
template<class This, class A1, class A2, class A3>
struct result<This(A1, A2, A3)> {
BOOST_MPL_ASSERT((boost::is_same<A1, int>));
BOOST_MPL_ASSERT((boost::is_same<A2, int>));
BOOST_MPL_ASSERT((boost::is_same<A3, int>));
typedef int type;
};
template<class This, class A1, class A2, class A3, class A4>
struct result<This(A1, A2, A3, A4)> {
BOOST_MPL_ASSERT((boost::is_same<A1, int>));
BOOST_MPL_ASSERT((boost::is_same<A2, int>));
BOOST_MPL_ASSERT((boost::is_same<A3, int>));
BOOST_MPL_ASSERT((boost::is_same<A4, int>));
typedef int type;
};
template<class This, class A1, class A2, class A3, class A4, class A5>
struct result<This(A1, A2, A3, A4, A5)> {
BOOST_MPL_ASSERT((boost::is_same<A1, int>));
BOOST_MPL_ASSERT((boost::is_same<A2, int>));
BOOST_MPL_ASSERT((boost::is_same<A3, int>));
BOOST_MPL_ASSERT((boost::is_same<A4, int>));
BOOST_MPL_ASSERT((boost::is_same<A5, int>));
typedef int type;
};
template<class This, class A1, class A2, class A3, class A4, class A5, class A6>
struct result<This(A1, A2, A3, A4, A5, A6)> {
BOOST_MPL_ASSERT((boost::is_same<A1, int>));
BOOST_MPL_ASSERT((boost::is_same<A2, int>));
BOOST_MPL_ASSERT((boost::is_same<A3, int>));
BOOST_MPL_ASSERT((boost::is_same<A4, int>));
BOOST_MPL_ASSERT((boost::is_same<A5, int>));
BOOST_MPL_ASSERT((boost::is_same<A6, int>));
typedef int type;
};
template<class This, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
struct result<This(A1, A2, A3, A4, A5, A6, A7)> {
BOOST_MPL_ASSERT((boost::is_same<A1, int>));
BOOST_MPL_ASSERT((boost::is_same<A2, int>));
BOOST_MPL_ASSERT((boost::is_same<A3, int>));
BOOST_MPL_ASSERT((boost::is_same<A4, int>));
BOOST_MPL_ASSERT((boost::is_same<A5, int>));
BOOST_MPL_ASSERT((boost::is_same<A6, int>));
BOOST_MPL_ASSERT((boost::is_same<A7, int>));
typedef int type;
};
template<class This, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
struct result<This(A1, A2, A3, A4, A5, A6, A7, A8)> {
BOOST_MPL_ASSERT((boost::is_same<A1, int>));
BOOST_MPL_ASSERT((boost::is_same<A2, int>));
BOOST_MPL_ASSERT((boost::is_same<A3, int>));
BOOST_MPL_ASSERT((boost::is_same<A4, int>));
BOOST_MPL_ASSERT((boost::is_same<A5, int>));
BOOST_MPL_ASSERT((boost::is_same<A6, int>));
BOOST_MPL_ASSERT((boost::is_same<A7, int>));
BOOST_MPL_ASSERT((boost::is_same<A8, int>));
typedef int type;
};
template<class This, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
struct result<This(A1, A2, A3, A4, A5, A6, A7, A8, A9)> {
BOOST_MPL_ASSERT((boost::is_same<A1, int>));
BOOST_MPL_ASSERT((boost::is_same<A2, int>));
BOOST_MPL_ASSERT((boost::is_same<A3, int>));
BOOST_MPL_ASSERT((boost::is_same<A4, int>));
BOOST_MPL_ASSERT((boost::is_same<A5, int>));
BOOST_MPL_ASSERT((boost::is_same<A6, int>));
BOOST_MPL_ASSERT((boost::is_same<A7, int>));
BOOST_MPL_ASSERT((boost::is_same<A8, int>));
BOOST_MPL_ASSERT((boost::is_same<A9, int>));
typedef int type;
};
int operator()() const { return 0; }
int operator()(int) const { return 1; }
int operator()(int, int) const { return 2; }
int operator()(int, int, int) const { return 3; }
int operator()(int, int, int, int) const { return 4; }
int operator()(int, int, int, int, int) const { return 5; }
int operator()(int, int, int, int, int, int) const { return 6; }
int operator()(int, int, int, int, int, int, int) const { return 7; }
int operator()(int, int, int, int, int, int, int, int) const { return 8; }
int operator()(int, int, int, int, int, int, int, int, int) const { return 9; }
};
struct with_result_template_reference {
template<class Sig>
struct result;
template<class This>
struct result<This()> {
typedef int type;
};
template<class This, class A1>
struct result<This(A1)> {
BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
typedef int type;
};
template<class This, class A1, class A2>
struct result<This(A1, A2)> {
BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
BOOST_MPL_ASSERT((boost::is_same<A2, int&>));
typedef int type;
};
template<class This, class A1, class A2, class A3>
struct result<This(A1, A2, A3)> {
BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
BOOST_MPL_ASSERT((boost::is_same<A2, int&>));
BOOST_MPL_ASSERT((boost::is_same<A3, int&>));
typedef int type;
};
template<class This, class A1, class A2, class A3, class A4>
struct result<This(A1, A2, A3, A4)> {
BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
BOOST_MPL_ASSERT((boost::is_same<A2, int&>));
BOOST_MPL_ASSERT((boost::is_same<A3, int&>));
BOOST_MPL_ASSERT((boost::is_same<A4, int&>));
typedef int type;
};
template<class This, class A1, class A2, class A3, class A4, class A5>
struct result<This(A1, A2, A3, A4, A5)> {
BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
BOOST_MPL_ASSERT((boost::is_same<A2, int&>));
BOOST_MPL_ASSERT((boost::is_same<A3, int&>));
BOOST_MPL_ASSERT((boost::is_same<A4, int&>));
BOOST_MPL_ASSERT((boost::is_same<A5, int&>));
typedef int type;
};
template<class This, class A1, class A2, class A3, class A4, class A5, class A6>
struct result<This(A1, A2, A3, A4, A5, A6)> {
BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
BOOST_MPL_ASSERT((boost::is_same<A2, int&>));
BOOST_MPL_ASSERT((boost::is_same<A3, int&>));
BOOST_MPL_ASSERT((boost::is_same<A4, int&>));
BOOST_MPL_ASSERT((boost::is_same<A5, int&>));
BOOST_MPL_ASSERT((boost::is_same<A6, int&>));
typedef int type;
};
template<class This, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
struct result<This(A1, A2, A3, A4, A5, A6, A7)> {
BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
BOOST_MPL_ASSERT((boost::is_same<A2, int&>));
BOOST_MPL_ASSERT((boost::is_same<A3, int&>));
BOOST_MPL_ASSERT((boost::is_same<A4, int&>));
BOOST_MPL_ASSERT((boost::is_same<A5, int&>));
BOOST_MPL_ASSERT((boost::is_same<A6, int&>));
BOOST_MPL_ASSERT((boost::is_same<A7, int&>));
typedef int type;
};
template<class This, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
struct result<This(A1, A2, A3, A4, A5, A6, A7, A8)> {
BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
BOOST_MPL_ASSERT((boost::is_same<A2, int&>));
BOOST_MPL_ASSERT((boost::is_same<A3, int&>));
BOOST_MPL_ASSERT((boost::is_same<A4, int&>));
BOOST_MPL_ASSERT((boost::is_same<A5, int&>));
BOOST_MPL_ASSERT((boost::is_same<A6, int&>));
BOOST_MPL_ASSERT((boost::is_same<A7, int&>));
BOOST_MPL_ASSERT((boost::is_same<A8, int&>));
typedef int type;
};
template<class This, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
struct result<This(A1, A2, A3, A4, A5, A6, A7, A8, A9)> {
BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
BOOST_MPL_ASSERT((boost::is_same<A2, int&>));
BOOST_MPL_ASSERT((boost::is_same<A3, int&>));
BOOST_MPL_ASSERT((boost::is_same<A4, int&>));
BOOST_MPL_ASSERT((boost::is_same<A5, int&>));
BOOST_MPL_ASSERT((boost::is_same<A6, int&>));
BOOST_MPL_ASSERT((boost::is_same<A7, int&>));
BOOST_MPL_ASSERT((boost::is_same<A8, int&>));
BOOST_MPL_ASSERT((boost::is_same<A9, int&>));
typedef int type;
};
int operator()() const { return 0; }
int operator()(int) const { return 1; }
int operator()(int, int) const { return 2; }
int operator()(int, int, int) const { return 3; }
int operator()(int, int, int, int) const { return 4; }
int operator()(int, int, int, int, int) const { return 5; }
int operator()(int, int, int, int, int, int) const { return 6; }
int operator()(int, int, int, int, int, int, int) const { return 7; }
int operator()(int, int, int, int, int, int, int, int) const { return 8; }
int operator()(int, int, int, int, int, int, int, int, int) const { return 9; }
};
template<class F>
typename boost::result_of<F()>::type apply0(F f) {
return f();
}
template<class A, class F>
typename boost::result_of<F(A)>::type apply1(F f, A a) {
return f(a);
}
template<class A, class B, class F>
typename boost::result_of<F(A, B)>::type apply2(F f, A a, B b) {
return f(a, b);
}
template<class A, class B, class C, class F>
typename boost::result_of<F(A, B, C)>::type apply3(F f, A a, B b, C c) {
return f(a, b, c);
}
using namespace boost::lambda;
int main() {
BOOST_CHECK(boost::lambda::bind(with_result_type())() == 0);
BOOST_CHECK(boost::lambda::bind(with_result_type(), 1)() == 1);
BOOST_CHECK(boost::lambda::bind(with_result_type(), 1, 2)() == 2);
BOOST_CHECK(boost::lambda::bind(with_result_type(), 1, 2, 3)() == 3);
BOOST_CHECK(boost::lambda::bind(with_result_type(), 1, 2, 3, 4)() == 4);
BOOST_CHECK(boost::lambda::bind(with_result_type(), 1, 2, 3, 4, 5)() == 5);
BOOST_CHECK(boost::lambda::bind(with_result_type(), 1, 2, 3, 4, 5, 6)() == 6);
BOOST_CHECK(boost::lambda::bind(with_result_type(), 1, 2, 3, 4, 5, 6, 7)() == 7);
BOOST_CHECK(boost::lambda::bind(with_result_type(), 1, 2, 3, 4, 5, 6, 7, 8)() == 8);
BOOST_CHECK(boost::lambda::bind(with_result_type(), 1, 2, 3, 4, 5, 6, 7, 8, 9)() == 9);
// Nullary result_of fails
//BOOST_CHECK(boost::lambda::bind(with_result_template_value())() == 0);
BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1)() == 1);
BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1, 2)() == 2);
BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1, 2, 3)() == 3);
BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1, 2, 3, 4)() == 4);
BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1, 2, 3, 4, 5)() == 5);
BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1, 2, 3, 4, 5, 6)() == 6);
BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1, 2, 3, 4, 5, 6, 7)() == 7);
BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1, 2, 3, 4, 5, 6, 7, 8)() == 8);
BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1, 2, 3, 4, 5, 6, 7, 8, 9)() == 9);
int one = 1,
two = 2,
three = 3,
four = 4,
five = 5,
six = 6,
seven = 7,
eight = 8,
nine = 9;
// Nullary result_of fails
//BOOST_CHECK(boost::lambda::bind(with_result_template_reference())() == 0);
BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one))() == 1);
BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one), var(two))() == 2);
BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three))() == 3);
BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three), var(four))() == 4);
BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three), var(four), var(five))() == 5);
BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three), var(four), var(five), var(six))() == 6);
BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three), var(four), var(five), var(six), var(seven))() == 7);
BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three), var(four), var(five), var(six), var(seven), var(eight))() == 8);
BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three), var(four), var(five), var(six), var(seven), var(eight), var(nine))() == 9);
// Check using result_of with lambda functors
BOOST_CHECK(apply0(constant(0)) == 0);
// returns local address and leads to undefined behavior
//~ BOOST_CHECK(apply1<int>(_1, one) == 1);
BOOST_CHECK(apply1<int&>(_1, one) == 1);
BOOST_CHECK(apply1<const int&>(_1, one) == 1);
BOOST_CHECK((apply2<int, int>(_1 + _2, one, two) == 3));
BOOST_CHECK((apply2<int&, int&>(_1 + _2, one, two) == 3));
BOOST_CHECK((apply2<const int&, const int&>(_1 + _2, one, two) == 3));
BOOST_CHECK((apply3<int, int, int>(_1 + _2 + _3, one, two, three) == 6));
BOOST_CHECK((apply3<int&, int&, int&>(_1 + _2 + _3, one, two, three) == 6));
BOOST_CHECK((apply3<const int&, const int&, const int&>(_1 + _2 + _3, one, two, three) == 6));
return boost::report_errors();
}

View File

@@ -1,54 +0,0 @@
// ret_test.cpp - The Boost Lambda Library -----------------------
//
// Copyright (C) 2009 Steven Watanabe
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see www.boost.org
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#include <boost/lambda/lambda.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/is_same.hpp>
template<class R, class F>
void test_ret(R r, F f) {
typename F::result_type x = f();
BOOST_MPL_ASSERT((boost::is_same<R, typename F::result_type>));
BOOST_CHECK(x == r);
}
template<class R, class F, class T1>
void test_ret(R r, F f, T1& t1) {
typename F::result_type x = f(t1);
BOOST_MPL_ASSERT((boost::is_same<R, typename F::result_type>));
BOOST_CHECK(x == r);
}
class add_result {
public:
add_result(int i = 0) : value(i) {}
friend bool operator==(const add_result& lhs, const add_result& rhs) {
return(lhs.value == rhs.value);
}
private:
int value;
};
class addable {};
add_result operator+(addable, addable) {
return add_result(7);
}
int main() {
addable test;
test_ret(add_result(7), boost::lambda::ret<add_result>(boost::lambda::_1 + test), test);
test_ret(8.0, boost::lambda::ret<double>(boost::lambda::constant(7) + 1));
return boost::report_errors();
}

View File

@@ -1,57 +0,0 @@
// rvalue_test - test lambda function objects with rvalue arguments
//
// Copyright (c) 2007 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/lambda/lambda.hpp>
#include <boost/core/lightweight_test.hpp>
int main()
{
using namespace boost::lambda;
int x = 0;
int const y = 1;
int const z = 2;
BOOST_TEST( _1( x ) == 0 );
BOOST_TEST( _1( y ) == 1 );
BOOST_TEST( _1( 2 ) == 2 );
BOOST_TEST( _2( x, x ) == 0 );
BOOST_TEST( _2( x, y ) == 1 );
BOOST_TEST( _2( x, 2 ) == 2 );
BOOST_TEST( _2( 4, x ) == 0 );
BOOST_TEST( _2( 4, y ) == 1 );
BOOST_TEST( _2( 4, 2 ) == 2 );
(_1 = _2)( x, y );
BOOST_TEST( x == y );
(_1 = _2)( x, 3 );
BOOST_TEST( x == 3 );
(_2 = _1)( z, x );
BOOST_TEST( x == z );
(_2 = _1)( 4, x );
BOOST_TEST( x == 4 );
BOOST_TEST( _3( x, x, x ) == x );
BOOST_TEST( _3( x, x, y ) == y );
BOOST_TEST( _3( x, x, 2 ) == 2 );
BOOST_TEST( _3( x, 5, x ) == x );
BOOST_TEST( _3( x, 5, y ) == y );
BOOST_TEST( _3( x, 5, 2 ) == 2 );
BOOST_TEST( _3( 9, 5, x ) == x );
BOOST_TEST( _3( 9, 5, y ) == y );
BOOST_TEST( _3( 9, 5, 2 ) == 2 );
return boost::report_errors();
}

View File

@@ -1,24 +1,11 @@
// switch_test.cpp -- The Boost Lambda Library --------------------------
//
// Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see www.boost.org
// switch_test.cpp --------------------------------
// -----------------------------------------------------------------------
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
#include <boost/test/test_tools.hpp> // see "Header Implementation Option"
#include "boost/lambda/lambda.hpp"
#include "boost/lambda/if.hpp"
#include "boost/lambda/switch.hpp"
#include "boost/lambda/control_structures.hpp"
#include <iostream>
#include <algorithm>
@@ -64,7 +51,7 @@ void do_switch_no_defaults_tests() {
)
);
BOOST_CHECK(check(w, 0));
BOOST_TEST(check(w, 0));
std::fill_n(w.begin(), 10, 0);
// ---
@@ -76,7 +63,7 @@ void do_switch_no_defaults_tests() {
)
);
BOOST_CHECK(check(w, 1));
BOOST_TEST(check(w, 1));
std::fill_n(w.begin(), 10, 0);
// ---
@@ -89,7 +76,7 @@ void do_switch_no_defaults_tests() {
)
);
BOOST_CHECK(check(w, 2));
BOOST_TEST(check(w, 2));
std::fill_n(w.begin(), 10, 0);
// ---
@@ -103,7 +90,7 @@ void do_switch_no_defaults_tests() {
)
);
BOOST_CHECK(check(w, 3));
BOOST_TEST(check(w, 3));
std::fill_n(w.begin(), 10, 0);
// ---
@@ -118,7 +105,7 @@ void do_switch_no_defaults_tests() {
)
);
BOOST_CHECK(check(w, 4));
BOOST_TEST(check(w, 4));
std::fill_n(w.begin(), 10, 0);
// ---
@@ -134,7 +121,7 @@ void do_switch_no_defaults_tests() {
)
);
BOOST_CHECK(check(w, 5));
BOOST_TEST(check(w, 5));
std::fill_n(w.begin(), 10, 0);
// ---
@@ -151,7 +138,7 @@ void do_switch_no_defaults_tests() {
)
);
BOOST_CHECK(check(w, 6));
BOOST_TEST(check(w, 6));
std::fill_n(w.begin(), 10, 0);
// ---
@@ -169,7 +156,7 @@ void do_switch_no_defaults_tests() {
)
);
BOOST_CHECK(check(w, 7));
BOOST_TEST(check(w, 7));
std::fill_n(w.begin(), 10, 0);
// ---
@@ -188,7 +175,7 @@ void do_switch_no_defaults_tests() {
)
);
BOOST_CHECK(check(w, 8));
BOOST_TEST(check(w, 8));
std::fill_n(w.begin(), 10, 0);
}
@@ -217,8 +204,8 @@ void do_switch_yes_defaults_tests() {
)
);
BOOST_CHECK(check(w, -1));
BOOST_CHECK(default_count == 10);
BOOST_TEST(check(w, -1));
BOOST_TEST(default_count == 10);
std::fill_n(w.begin(), 10, 0);
// ---
@@ -231,8 +218,8 @@ void do_switch_yes_defaults_tests() {
)
);
BOOST_CHECK(check(w, 0));
BOOST_CHECK(default_count == 9);
BOOST_TEST(check(w, 0));
BOOST_TEST(default_count == 9);
std::fill_n(w.begin(), 10, 0);
// ---
@@ -246,8 +233,8 @@ void do_switch_yes_defaults_tests() {
)
);
BOOST_CHECK(check(w, 1));
BOOST_CHECK(default_count == 8);
BOOST_TEST(check(w, 1));
BOOST_TEST(default_count == 8);
std::fill_n(w.begin(), 10, 0);
// ---
@@ -262,8 +249,8 @@ void do_switch_yes_defaults_tests() {
)
);
BOOST_CHECK(check(w, 2));
BOOST_CHECK(default_count == 7);
BOOST_TEST(check(w, 2));
BOOST_TEST(default_count == 7);
std::fill_n(w.begin(), 10, 0);
// ---
@@ -279,8 +266,8 @@ void do_switch_yes_defaults_tests() {
)
);
BOOST_CHECK(check(w, 3));
BOOST_CHECK(default_count == 6);
BOOST_TEST(check(w, 3));
BOOST_TEST(default_count == 6);
std::fill_n(w.begin(), 10, 0);
// ---
@@ -297,8 +284,8 @@ void do_switch_yes_defaults_tests() {
)
);
BOOST_CHECK(check(w, 4));
BOOST_CHECK(default_count == 5);
BOOST_TEST(check(w, 4));
BOOST_TEST(default_count == 5);
std::fill_n(w.begin(), 10, 0);
// ---
@@ -316,8 +303,8 @@ void do_switch_yes_defaults_tests() {
)
);
BOOST_CHECK(check(w, 5));
BOOST_CHECK(default_count == 4);
BOOST_TEST(check(w, 5));
BOOST_TEST(default_count == 4);
std::fill_n(w.begin(), 10, 0);
// ---
@@ -336,8 +323,8 @@ void do_switch_yes_defaults_tests() {
)
);
BOOST_CHECK(check(w, 6));
BOOST_CHECK(default_count == 3);
BOOST_TEST(check(w, 6));
BOOST_TEST(default_count == 3);
std::fill_n(w.begin(), 10, 0);
// ---
@@ -357,36 +344,18 @@ void do_switch_yes_defaults_tests() {
)
);
BOOST_CHECK(check(w, 7));
BOOST_CHECK(default_count == 2);
BOOST_TEST(check(w, 7));
BOOST_TEST(default_count == 2);
std::fill_n(w.begin(), 10, 0);
}
void test_empty_cases() {
using namespace boost::lambda;
// ---
switch_statement(
_1,
default_statement()
)(make_const(1));
switch_statement(
_1,
case_statement<1>()
)(make_const(1));
}
int main() {
int test_main(int, char* []) {
do_switch_no_defaults_tests();
do_switch_yes_defaults_tests();
test_empty_cases();
return boost::report_errors();
return EXIT_SUCCESS;
}