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

Compare commits

...

137 Commits

Author SHA1 Message Date
Daniel James
5350569878 Branch to work on filename handling without disturbing trunk.
[SVN r68345]
2011-01-21 09:17:08 +00:00
Steven Watanabe
2ed8d7f4df Fix return type deduction for pointers to data members. Fixes #4962. Fixes #4566.
[SVN r67640]
2011-01-03 22:31:21 +00:00
Daniel Walker
4091f55a4b removed arity detection from has_xxx_template
[SVN r63726]
2010-07-07 20:44:59 +00:00
Daniel James
45c6ba535c Update various libraries' documentation build.
Mostly to use the images and css files under doc/src instead of
doc/html, usually be deleting the settings in order to use the defaults.
Also add 'boost.root' to some builds in order to fix links which rely on
it.

[SVN r63146]
2010-06-20 18:00:48 +00:00
Steven Watanabe
57a605d7cc Revert [62617], since there is already a Jamfile for Lambda's tests
[SVN r62628]
2010-06-09 02:10:06 +00:00
Steven Watanabe
fcfcc42baf Enable using result_of with Boost.Lambda. Fixes #426. Fixes #864
[SVN r62627]
2010-06-09 01:39:48 +00:00
Jeremiah Willcock
c516504670 Changed compound assignment (and actually all binary operators) to copy their RHS arguments like the documentation said; added a test for this; fixes #4043
[SVN r62620]
2010-06-09 00:33:25 +00:00
Jeremiah Willcock
c479b3b7b7 Fixed warning
[SVN r62619]
2010-06-09 00:31:02 +00:00
Jeremiah Willcock
269ac93b1b Added Jamfile.v2 from Daniel Walker; refs #864
[SVN r62617]
2010-06-09 00:16:43 +00:00
Steven Watanabe
15d4e6ab79 Make sure that all top level headers in Lambda include their dependencies. Fixes #4203
[SVN r61881]
2010-05-09 20:07:07 +00:00
Steven Watanabe
77495bb7e1 Deal with warnings with /Za. Fixes #3485
[SVN r57479]
2009-11-08 04:11:21 +00:00
Troy D. Straszheim
c183b699bc rm cmake from trunk. I'm not entirely sure this is necessary to satisfy the inspect script, but I'm not taking any chances, and it is easy to put back
[SVN r56942]
2009-10-17 02:07:38 +00:00
Troy D. Straszheim
3d4a3e7050 Copyrights on CMakeLists.txt to keep them from clogging up the inspect
reports.  This is essentially the same commit as r55095 on the release
branch.



[SVN r55159]
2009-07-26 00:49:56 +00:00
Steven Watanabe
c14095472e Don't propagate constness from pointer to pointee. Fixes #1572
[SVN r53651]
2009-06-05 02:43:54 +00:00
Steven Watanabe
1afc4b6779 Use boost/detail/container_fwd.hpp. Fixes #2601
[SVN r53649]
2009-06-05 01:43:39 +00:00
Steven Watanabe
41eb864595 Add result_type to lambda::ret. Fixes #1222
[SVN r53648]
2009-06-05 01:20:06 +00:00
Jeremiah Willcock
0f60055086 Fixed tabs
[SVN r53343]
2009-05-28 14:49:25 +00:00
Steven Watanabe
9a8e5d7784 Fix lambda regression with msvc 7.1
[SVN r53261]
2009-05-25 21:52:12 +00:00
Steven Watanabe
6985fca6ee Avoid ambiguities between boost::lambda::bind and std::bind with VC10. Fixes #3075
[SVN r53233]
2009-05-24 22:58:52 +00:00
Steven Watanabe
04ae944c3c Avoid using namespace std; to prevent ambiguity between boost and std components. Fixes #3025
[SVN r53061]
2009-05-17 00:25:06 +00:00
Steven Watanabe
0c4e251ebe Supress warnings on gcc and msvc. Fixes #1515
[SVN r51448]
2009-02-26 02:33:15 +00:00
John Maddock
0faeb3f19e Add Jamfile to build PDF versions of all the docs.
Tweaked some existing Jamfiles so that PDF build finds all the necessary image files etc.
Tweaked fo.xsl to provide more options by default, and improve formatting.

[SVN r51104]
2009-02-08 16:59:14 +00:00
Steven Watanabe
150736273e Add <async-exceptions>on. Fixes #2446
[SVN r50999]
2009-02-03 21:47:58 +00:00
Steven Watanabe
d5a98758fa Add specializations of plain_return_type_2 for std::string. Fixes #781
[SVN r50516]
2009-01-08 16:58:48 +00:00
Marshall Clow
cd3d5fd03a Typo: fixes bug #2583
[SVN r50413]
2008-12-30 18:27:43 +00:00
Michael A. Jackson
48a89b7705 Updating dependency information for modularized libraries.
[SVN r49628]
2008-11-07 17:05:27 +00:00
Michael A. Jackson
ec350abf06 Updating CMake files to latest trunk. Added dependency information for regression tests and a few new macros for internal use.
[SVN r49627]
2008-11-07 17:02:56 +00:00
Michael A. Jackson
d56abd61ce Continuing merge of CMake build system files into trunk with the encouragement of Doug Gregor
[SVN r49510]
2008-11-01 13:15:41 +00:00
Beman Dawes
2788ede42a With his kind permission, change Jaakko "Järvi" to "Jarvi"
[SVN r46808]
2008-06-28 13:45:21 +00:00
Marshall Clow
1c953ed38c Updated docs re bug #1855
[SVN r45097]
2008-05-03 23:45:30 +00:00
Marshall Clow
b2dc95bb18 Applied patch (fixes bug #1307)
[SVN r43113]
2008-02-05 16:15:35 +00:00
Vladimir Prus
797b5756cf Update for V2
[SVN r38520]
2007-08-08 19:16:43 +00:00
Peter Dimov
bd4da55f0f Rvalue support
[SVN r38299]
2007-07-29 20:33:46 +00:00
Daniel James
47bf3df0ae Merge fixed links from RC_1_34_0.
[SVN r36660]
2007-01-07 23:50:56 +00:00
Jaakko Järvi
ff0929e6e3 fixed bug 1444052
[SVN r36200]
2006-11-29 19:21:46 +00:00
Jaakko Järvi
9b925abaff added ->* to the table of actions for return types deduction
[SVN r36199]
2006-11-29 18:54:18 +00:00
Beman Dawes
bf50f2fe7f Add copyright, license
[SVN r35905]
2006-11-07 19:11:57 +00:00
Daryle Walker
85630d55a6 Correct placement of base class declaration
[SVN r34533]
2006-07-14 08:04:08 +00:00
Peter Dimov
2e8c4eb8f3 is_placeholder, is_bind_expression added.
[SVN r34468]
2006-07-06 13:47:26 +00:00
Jaakko Järvi
24e8602cf1 typo
[SVN r31518]
2005-10-31 20:11:23 +00:00
Jaakko Järvi
7f77f987c1 Fixed typos in comments
[SVN r30381]
2005-08-02 17:43:37 +00:00
Jaakko Järvi
d854239945 Patch by Jonathan Wakely to expand special handling of GCC when used in
debug mode.


[SVN r28684]
2005-05-06 05:08:32 +00:00
Jaakko Järvi
4aef261258 added a flag to the test makefile
[SVN r28683]
2005-05-06 05:06:11 +00:00
Jaakko Järvi
6b67606f40 class to struct
[SVN r27493]
2005-02-24 05:27:28 +00:00
Stefan Slapeta
b0ce56c74f replaced BOOST_TEST
[SVN r27057]
2005-02-03 13:55:45 +00:00
Aleksey Gurtovoy
9e45d49139 merge RC_1_32_0 fixes
[SVN r26328]
2004-11-28 03:35:12 +00:00
Jaakko Järvi
e9ed0829b2 gcc 3.4. does not distinguish between bind overloads for function refrerences, and just const T&.
Not sure who is right, but now bind function overloads are special cased for g++ 3.4.


[SVN r25466]
2004-09-28 19:02:16 +00:00
Jaakko Järvi
17df366d20 added explicit qualification to var to avoid conflict with pthreads
[SVN r25042]
2004-09-13 15:13:59 +00:00
Aleksey Gurtovoy
485bcbdcd8 merge new MPL version from 'mplbook' branch
[SVN r24874]
2004-09-02 15:41:37 +00:00
John Maddock
023996e106 Updated to use the BSL (using permissions supplied in more/blanket-permission.txt)
[SVN r24804]
2004-08-29 10:29:46 +00:00
Douglas Gregor
3bd135028e Move to BSL
[SVN r24447]
2004-08-12 17:16:41 +00:00
Douglas Gregor
b6b0b9a03f Moved to BSL
[SVN r24446]
2004-08-12 17:13:07 +00:00
Douglas Gregor
0f0c53b1f9 Converted to Boost Software License, Version 1.0
[SVN r24096]
2004-07-27 03:43:34 +00:00
Rene Rivera
24ff929eb1 Remove tabs in file.
[SVN r24043]
2004-07-25 17:12:17 +00:00
Jaakko Järvi
5031c63f73 .
[SVN r23654]
2004-07-16 22:56:09 +00:00
Jaakko Järvi
a7ac9a8991 Back to minimal.hpp
[SVN r23653]
2004-07-16 22:05:56 +00:00
Jaakko Järvi
8a19479625 modernizing...
[SVN r23640]
2004-07-16 17:30:45 +00:00
Jaakko Järvi
4add858581 temporarily backing out from previous changes, problems with VC7.1
[SVN r23475]
2004-07-13 01:16:43 +00:00
Jaakko Järvi
14b8227ca6 adding overloads to cope with rvalue temporaries
[SVN r23401]
2004-07-07 20:31:02 +00:00
Jaakko Järvi
5ecd79ed2e .
[SVN r23397]
2004-07-07 20:02:29 +00:00
Jaakko Järvi
d718b75da3 Converting to boostbook
[SVN r23396]
2004-07-07 19:43:52 +00:00
Jaakko Järvi
f9689cc6a4 Converting to Boost Book
[SVN r23384]
2004-07-06 20:56:36 +00:00
Eric Niebler
a80b8a59a0 remove std_min and std_max, update minmax coding guidelines
[SVN r23162]
2004-06-23 04:49:48 +00:00
Jaakko Järvi
b99048eab3 Fix for gcc 3.4
[SVN r22673]
2004-04-20 18:05:05 +00:00
Jaakko Järvi
ec6cc563b1 patch for gcc3.4
[SVN r22575]
2004-04-01 00:00:55 +00:00
Jaakko Järvi
0196c57a0a A few typos
[SVN r22414]
2004-03-01 14:13:05 +00:00
Eric Niebler
282825b784 remove minmax hack from win32.hpp and fix all places that could be affected by the minmax macros
[SVN r22394]
2004-02-26 18:27:02 +00:00
Jaakko Järvi
b8d328c0fc Now BLL supports result_type too, Thanks Peter D.!
[SVN r22380]
2004-02-24 22:06:14 +00:00
Peter Dimov
c5704cd6e3 Enable ::result_type recognition
[SVN r22379]
2004-02-24 20:03:32 +00:00
Peter Dimov
6f607b3eef *_1 support for smart pointers
[SVN r22376]
2004-02-24 13:13:03 +00:00
Jaakko Järvi
8bb8820adb fixed a small typo in destructor example
[SVN r22304]
2004-02-17 15:53:35 +00:00
Jaakko Järvi
89fb84d751 supressed some gcc3.4 warnings, making it more explicit that a few
template functions return void


[SVN r21503]
2004-01-05 15:34:29 +00:00
Rene Rivera
be2b0df062 Fix tabs in file.
[SVN r21399]
2003-12-26 23:26:49 +00:00
Jaakko Järvi
666a3eca2d patch by Jim Apple to fix things here and there
[SVN r21213]
2003-12-10 19:15:05 +00:00
Jaakko Järvi
95d865285e new test for algorithms
[SVN r21212]
2003-12-10 19:12:06 +00:00
Jaakko Järvi
ec38046886 added a citation
[SVN r20326]
2003-10-09 19:30:59 +00:00
Jaakko Järvi
c713dc5e0c fixed a typo, thanks Dave A
[SVN r20295]
2003-10-07 20:55:29 +00:00
Jaakko Järvi
ff04032656 a typo fix
[SVN r18993]
2003-07-09 14:35:19 +00:00
Jaakko Järvi
6f63b3770f fixed a bad example
[SVN r18616]
2003-05-30 19:26:56 +00:00
Jaakko Järvi
22e7b9c779 fixed empty args to macros warnings
[SVN r18501]
2003-05-22 21:00:48 +00:00
Jaakko Järvi
68be6f6563 a fix for gcc 2.95.2
[SVN r18500]
2003-05-22 18:27:40 +00:00
Jaakko Järvi
02314ab550 typo
[SVN r17652]
2003-02-26 05:11:50 +00:00
Jaakko Järvi
9f032a7301 licences were missing, now added
[SVN r17236]
2003-02-05 15:47:51 +00:00
Jaakko Järvi
da56b773a0 licence fixes ...
[SVN r17235]
2003-02-05 15:41:29 +00:00
Jaakko Järvi
cd605ff48d licence fixe
[SVN r17234]
2003-02-05 15:40:23 +00:00
Jaakko Järvi
641babedf8 added a link
[SVN r17232]
2003-02-05 14:58:37 +00:00
Jaakko Järvi
f9a6b38845 remvoded tabs
[SVN r16828]
2003-01-09 14:15:09 +00:00
Jaakko Järvi
846a406b7a bugfix, added a missing sig template
[SVN r16094]
2002-11-04 16:25:33 +00:00
Jaakko Järvi
29794ee654 added more tests for different arities of member functions
[SVN r16093]
2002-11-04 16:24:38 +00:00
Jaakko Järvi
f74aae1241 bugfixes
[SVN r16025]
2002-10-30 21:10:03 +00:00
Jaakko Järvi
624a204462 a bug fixed
[SVN r15886]
2002-10-10 22:03:49 +00:00
Jaakko Järvi
b635d13d2c a typo fix
[SVN r15656]
2002-10-02 22:43:10 +00:00
Jaakko Järvi
403d82da66 changed a list to a vector (sort requires random access iterator) in one example
[SVN r15575]
2002-09-30 20:28:27 +00:00
Jaakko Järvi
0f29970c8b changing to the new boost::function style
[SVN r15510]
2002-09-25 16:56:06 +00:00
Jaakko Järvi
05b9bd64c4 converting to the new boost::function style
[SVN r15508]
2002-09-25 16:46:42 +00:00
Jaakko Järvi
e1b36955b7 changed <include> to <sysinclude>
[SVN r15306]
2002-09-13 16:46:08 +00:00
Paul Mensonides
c6030ac58d pp-lib update
[SVN r15214]
2002-09-08 22:03:22 +00:00
Beman Dawes
e6edfdf997 Initial commit
[SVN r14896]
2002-08-15 17:47:47 +00:00
Jaakko Järvi
aabd832db1 added a Jamfile to run tests locally
[SVN r14856]
2002-08-14 20:56:59 +00:00
Jaakko Järvi
2aec95e806 added a forgotten sig-template to 9-argument case
[SVN r14837]
2002-08-14 14:59:24 +00:00
Jaakko Järvi
95b82465e0 added docs for bind(&A::data_member, ... support
[SVN r14746]
2002-08-08 20:09:26 +00:00
Jaakko Järvi
c5dafd3db8 volatile support for bind(&A::data_member
[SVN r14745]
2002-08-08 19:54:58 +00:00
Jaakko Järvi
fefd81ede1 adding support for bind(&A::data_member, _1)
[SVN r14744]
2002-08-08 17:01:47 +00:00
Jaakko Järvi
a120795474 added support for bind(&A::data_member, _1) syntax
[SVN r14743]
2002-08-08 16:58:09 +00:00
Jaakko Järvi
94292237b4 bugfix: name conflict in template template parameter
[SVN r14699]
2002-08-05 16:16:00 +00:00
Jaakko Järvi
fbe72097b4 bugfix in make_void
[SVN r14042]
2002-05-24 19:33:24 +00:00
Jaakko Järvi
2f24d3f261 added tests for empty case statements
[SVN r14015]
2002-05-22 19:48:02 +00:00
Jaakko Järvi
e057f63a54 added tests for emtpy catch blocks
[SVN r14014]
2002-05-22 19:47:35 +00:00
Jaakko Järvi
6f32c54b5d indentation changes
[SVN r14013]
2002-05-22 19:46:57 +00:00
Jaakko Järvi
3d659d2c3b bugfix in empty case_statements
[SVN r14012]
2002-05-22 19:44:07 +00:00
Jaakko Järvi
e9721da0d0 bugfix on do_nothing_action case
[SVN r14011]
2002-05-22 19:42:33 +00:00
Jaakko Järvi
f329a3bf68 bugfix in empty catch blocks
[SVN r14010]
2002-05-22 19:41:46 +00:00
Jaakko Järvi
a396be0bf6 added u to an int literal to get rid of a warning for comparin unsigned and
signed


[SVN r13861]
2002-05-14 17:00:57 +00:00
Jaakko Järvi
eeb2c53b56 added dummy uses of arguments to prevent unused argument errors
[SVN r13860]
2002-05-14 16:59:33 +00:00
Jaakko Järvi
fcf0d30c4e removing tabs
[SVN r13782]
2002-05-09 17:08:29 +00:00
Jaakko Järvi
d65bfa94ca converted tabs to spaces
[SVN r13781]
2002-05-09 17:05:16 +00:00
Jaakko Järvi
2942562072 name changes to get under 31 chars
[SVN r13763]
2002-05-08 22:14:14 +00:00
Jaakko Järvi
01031ccddd renamimg files to get under 31 chars
[SVN r13761]
2002-05-08 22:09:24 +00:00
Jaakko Järvi
efdcc46d3a renaming file to get under 31 characters
[SVN r13760]
2002-05-08 22:07:14 +00:00
Jaakko Järvi
d60ae200a6 using ice_and, ice_or instead of && and || in compile time expressions
[SVN r13756]
2002-05-08 20:02:31 +00:00
Jaakko Järvi
ff11fbb20e ok
[SVN r13751]
2002-05-08 15:56:14 +00:00
Jaakko Järvi
705c230963 adding the docbook xml files that generate the documentation
[SVN r13750]
2002-05-08 15:53:15 +00:00
Jaakko Järvi
cd444c824a added documentation for algorithm.hpp and numeric.hpp
[SVN r13749]
2002-05-08 15:42:48 +00:00
Jaakko Järvi
50d9654200 added algorithm.hpp and numeric.hpp instructions
[SVN r13748]
2002-05-08 15:39:45 +00:00
Jaakko Järvi
937816e76e added a comment
[SVN r13734]
2002-05-07 22:24:22 +00:00
Jaakko Järvi
bc350d53bf added a config parameter for not handling the ::template correctly
[SVN r13733]
2002-05-07 22:22:01 +00:00
Jaakko Järvi
34133ee940 do not include member_ptr.hpp for compilers that cannot handle it
[SVN r13732]
2002-05-07 22:20:08 +00:00
Jaakko Järvi
38ffca82c9 removed some tests if sstreams not available
[SVN r13731]
2002-05-07 22:16:41 +00:00
Jaakko Järvi
1a2fb78541 inner product etc.
[SVN r13730]
2002-05-07 21:51:33 +00:00
Jaakko Järvi
b6d1367cec added tests for stringstreams and << >> operators
[SVN r13654]
2002-05-03 22:02:37 +00:00
Jaakko Järvi
ec9ba2becf fixed a bug in stringstream and fstream << >> operators
[SVN r13652]
2002-05-03 19:13:48 +00:00
Jaakko Järvi
2bdf3738c1 added all STL algorithms, removed has_sig
[SVN r13651]
2002-05-03 19:10:35 +00:00
Jaakko Järvi
c11fb1fe36 removed one struct/class inconsistency
[SVN r13559]
2002-04-24 12:43:53 +00:00
Jaakko Järvi
59ad507d3f adding lambda tests to the main trunk
[SVN r13538]
2002-04-19 19:49:20 +00:00
Jaakko Järvi
10c4216ddc lambda docs to the main trunk
[SVN r13536]
2002-04-19 19:45:20 +00:00
Jaakko Järvi
15baf78a58 Into the maintrunk
[SVN r13524]
2002-04-19 19:29:57 +00:00
Jaakko Järvi
f2b02864f9 lambda_development branch creation
[SVN r11711]
2001-11-15 20:47:16 +00:00
65 changed files with 24702 additions and 0 deletions

12
doc/Jamfile.v2 Normal file
View File

@@ -0,0 +1,12 @@
project boost/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)/
;

7
doc/detail/README Normal file
View File

@@ -0,0 +1,7 @@
- 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)

3456
doc/detail/lambda_doc.xml Normal file

File diff suppressed because it is too large Load Diff

19
doc/detail/lambda_doc.xsl Normal file
View File

@@ -0,0 +1,19 @@
<?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

@@ -0,0 +1,19 @@
<?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>

12
doc/index.html Normal file
View File

@@ -0,0 +1,12 @@
<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>

3452
doc/lambda.xml Normal file

File diff suppressed because it is too large Load Diff

0
dummy
View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,19 @@
// -- bind.hpp -- Boost Lambda Library --------------------------------------
// Copyright (C) 1999-2001 Jaakko Jarvi (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)
//
// For more information, see http://www.boost.org
#ifndef BOOST_LAMBDA_BIND_HPP
#define BOOST_LAMBDA_BIND_HPP
#include "boost/lambda/core.hpp"
#include "boost/lambda/detail/bind_functions.hpp"
#endif

View File

@@ -0,0 +1,226 @@
// - casts.hpp -- BLambda 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 http://www.boost.org
// -----------------------------------------------
#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;
template<class T> class dynamic_cast_action;
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:
template<class RET, class Arg1>
static RET apply(Arg1 &a1) {
return static_cast<RET>(a1);
}
};
template<class T> class cast_action<dynamic_cast_action<T> > {
public:
template<class RET, class Arg1>
static RET apply(Arg1 &a1) {
return dynamic_cast<RET>(a1);
}
};
template<class T> class cast_action<const_cast_action<T> > {
public:
template<class RET, class Arg1>
static RET apply(Arg1 &a1) {
return const_cast<RET>(a1);
}
};
template<class T> class cast_action<reinterpret_cast_action<T> > {
public:
template<class RET, class Arg1>
static RET apply(Arg1 &a1) {
return reinterpret_cast<RET>(a1);
}
};
// typeid action
class typeid_action {
public:
template<class RET, class Arg1>
static RET apply(Arg1 &a1) {
detail::suppress_unused_variable_warnings(a1);
return typeid(a1);
}
};
// sizeof action
class sizeof_action
{
public:
template<class RET, class Arg1>
static RET apply(Arg1 &a1) {
return sizeof(a1);
}
};
// 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> {
typedef T type;
};
// return type of typeid_action
template<class A>
struct return_type_N<typeid_action, A> {
typedef std::type_info const & type;
};
// return type of sizeof_action
template<class A>
struct return_type_N<sizeof_action, A> {
typedef std::size_t type;
};
// the four cast & typeid overloads.
// casts can take ordinary variables (not just lambda functors)
// 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>
>
>
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));
}
// 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>
>
>
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));
}
// 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>
>
>
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));
}
// 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>
>
>
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));
}
// typeid
// can be applied to a normal variable as well (can refer to a polymorphic
// class object)
template <class Arg1>
inline const lambda_functor<
lambda_functor_base<
action<1, typeid_action>,
tuple<typename const_copy_argument <const Arg1>::type>
>
>
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));
}
// sizeof(expression)
// Always takes a lambda expression (if not, built in sizeof will do)
template <class Arg1>
inline const lambda_functor<
lambda_functor_base<
action<1, sizeof_action>,
tuple<lambda_functor<Arg1> >
>
>
ll_sizeof(const lambda_functor<Arg1>& a1) {
return
lambda_functor_base<
action<1, sizeof_action>,
tuple<lambda_functor<Arg1> >
>
( tuple<lambda_functor<Arg1> >(a1));
}
} // namespace lambda
} // namespace boost
#endif

View File

@@ -0,0 +1,274 @@
/*=============================================================================
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 PHOENIX_CLOSURES_HPP
#define PHOENIX_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

@@ -0,0 +1,240 @@
// - construct.hpp -- 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 http://www.boost.org
//
// -----------------------------------------------
#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"
namespace boost {
namespace lambda {
// constructor is used together with bind. constructor<A> creates a bindable
// function object that passes its arguments forward to a constructor call
// of type A
template<class T> struct constructor {
template <class U> struct sig { typedef T type; };
T operator()() const {
return T();
}
template<class A1>
T operator()(A1& a1) const {
return T(a1);
}
template<class A1, class A2>
T operator()(A1& a1, A2& a2) const {
return T(a1, a2);
}
template<class A1, class A2, class A3>
T operator()(A1& a1, A2& a2, A3& a3) const {
return T(a1, a2, a3);
}
template<class A1, class A2, class A3, class A4>
T operator()(A1& a1, A2& a2, A3& a3, A4& a4) const {
return T(a1, a2, a3, a4);
}
template<class A1, class A2, class A3, class A4, class A5>
T operator()(A1& a1, A2& a2, A3& a3, A4& a4, A5& a5) const {
return T(a1, a2, a3, a4, a5);
}
template<class A1, class A2, class A3, class A4, class A5, class A6>
T operator()(A1& a1, A2& a2, A3& a3, A4& a4, A5& a5, A6& a6) const {
return T(a1, a2, a3, a4, a5, a6);
}
template<class A1, class A2, class A3, class A4, class A5, class A6, class A7>
T operator()(A1& a1, A2& a2, A3& a3, A4& a4, A5& a5, A6& a6, A7& a7) const {
return T(a1, a2, a3, a4, a5, a6, a7);
}
template<class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
T operator()(A1& a1, A2& a2, A3& a3, A4& a4, A5& a5, A6& a6, A7& a7, A8& a8) const {
return T(a1, a2, a3, a4, a5, a6, a7, a8);
}
template<class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
T operator()(A1& a1, A2& a2, A3& a3, A4& a4, A5& a5, A6& a6, A7& a7, A8& a8, A9& a9) const {
return T(a1, a2, a3, a4, a5, a6, a7, a8, a9);
}
template<class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
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);
}
};
namespace detail {
// A standard conforming compiler could disambiguate between
// A1* and A1&, but not all compilers do that, so we need the
// helpers
template <bool IsPointer>
struct destructor_helper {
template<class A1>
static void exec(A1& a1) {
// remove all the qualifiers, not sure whether it is necessary
typedef typename boost::remove_cv<A1>::type plainA1;
a1.~plainA1();
}
};
template <>
struct destructor_helper<true> {
template<class A1>
static void exec(A1* a1) {
typedef typename boost::remove_cv<A1>::type plainA1;
(*a1).~plainA1();
}
};
}
// destructor funtion object
struct destructor {
template <class T> struct sig { typedef void type; };
template<class A1>
void operator()(A1& a1) const {
typedef typename boost::remove_cv<A1>::type plainA1;
detail::destructor_helper<boost::is_pointer<plainA1>::value>::exec(a1);
}
};
// new_ptr is used together with bind.
// note: placement new is not supported
template<class T> struct new_ptr {
template <class U> struct sig { typedef T* type; };
T* operator()() const {
return new T();
}
template<class A1>
T* operator()(A1& a1) const {
return new T(a1);
}
template<class A1, class A2>
T* operator()(A1& a1, A2& a2) const {
return new T(a1, a2);
}
template<class A1, class A2, class A3>
T* operator()(A1& a1, A2& a2, A3& a3) const {
return new T(a1, a2, a3);
}
template<class A1, class A2, class A3, class A4>
T* operator()(A1& a1, A2& a2, A3& a3, A4& a4) const {
return new T(a1, a2, a3, a4);
}
template<class A1, class A2, class A3, class A4, class A5>
T* operator()(A1& a1, A2& a2, A3& a3, A4& a4, A5& a5) const {
return new T(a1, a2, a3, a4, a5);
}
template<class A1, class A2, class A3, class A4, class A5, class A6>
T* operator()(A1& a1, A2& a2, A3& a3, A4& a4, A5& a5, A6& a6) const {
return new T(a1, a2, a3, a4, a5, a6);
}
template<class A1, class A2, class A3, class A4, class A5, class A6, class A7>
T* operator()(A1& a1, A2& a2, A3& a3, A4& a4, A5& a5, A6& a6, A7& a7) const {
return new T(a1, a2, a3, a4, a5, a6, a7);
}
template<class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
T* operator()(A1& a1, A2& a2, A3& a3, A4& a4, A5& a5, A6& a6, A7& a7, A8& a8) const {
return new T(a1, a2, a3, a4, a5, a6, a7, a8);
}
template<class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
T* operator()(A1& a1, A2& a2, A3& a3, A4& a4, A5& a5, A6& a6, A7& a7, A8& a8, A9& a9) const {
return new T(a1, a2, a3, a4, a5, a6, a7, a8, a9);
}
template<class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
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);
}
};
// delete_ptr return void
struct delete_ptr {
template <class U> struct sig { typedef void type; };
template <class A1>
void operator()(A1& a1) const {
delete a1;
}
};
// new_array is used together with bind.
template<class T> struct new_array {
template <class U> struct sig { typedef T* type; };
T* operator()(int size) const {
return new T[size];
}
};
// delete_ptr return void
struct delete_array {
template <class U> struct sig { typedef void type; };
template <class A1>
void operator()(A1& a1) const {
delete[] a1;
}
};
} // namespace lambda
} // namespace boost
#endif

View File

@@ -0,0 +1,23 @@
// -- control_structures.hpp -- Boost Lambda Library --------------------------
// 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_CONTROL_STRUCTURES_HPP
#define BOOST_LAMBDA_CONTROL_STRUCTURES_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"
#include "boost/lambda/if.hpp"
#include "boost/lambda/loops.hpp"
#endif

View File

@@ -0,0 +1,79 @@
// -- 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:
//
// tuples, lambda functors, return type deduction templates,
// argument substitution mechanism (select functions)
//
// Some functionality comes as well:
// Assignment and subscript operators, as well as function
// call operator for placeholder variables.
// -------------------------------------------------------------------------
#ifndef BOOST_LAMBDA_CORE_HPP
#define BOOST_LAMBDA_CORE_HPP
#include "boost/type_traits/transform_traits.hpp"
#include "boost/type_traits/cv_traits.hpp"
#include "boost/tuple/tuple.hpp"
// inject some of the tuple names into lambda
namespace boost {
namespace lambda {
using ::boost::tuples::tuple;
using ::boost::tuples::null_type;
} // lambda
} // boost
#include "boost/lambda/detail/lambda_config.hpp"
#include "boost/lambda/detail/lambda_fwd.hpp"
#include "boost/lambda/detail/arity_code.hpp"
#include "boost/lambda/detail/actions.hpp"
#include "boost/lambda/detail/lambda_traits.hpp"
#include "boost/lambda/detail/function_adaptors.hpp"
#include "boost/lambda/detail/return_type_traits.hpp"
#include "boost/lambda/detail/select_functions.hpp"
#include "boost/lambda/detail/lambda_functor_base.hpp"
#include "boost/lambda/detail/lambda_functors.hpp"
#include "boost/lambda/detail/ret.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& _1 = free1;
boost::lambda::placeholder2_type& _2 = free2;
boost::lambda::placeholder3_type& _3 = free3;
// _1, _2, ... naming scheme by Peter Dimov
} // unnamed
} // lambda
} // boost
#endif //BOOST_LAMBDA_CORE_HPP

View File

@@ -0,0 +1,174 @@
// -- Boost Lambda Library - actions.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_ACTIONS_HPP
#define BOOST_LAMBDA_ACTIONS_HPP
namespace boost {
namespace lambda {
template<int Arity, class Act> class action;
// these need to be defined here, since the corresponding lambda
// functions are members of lambda_functor classes
class assignment_action {};
class subscript_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 {};
// 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 {};
}
// function action is a special case: bind functions can be called with
// the return type specialized explicitly e.g. bind<int>(foo);
// If this call syntax is used, the return type is stored in the latter
// 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<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);
}
};
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);
}
};
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);
}
};
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);
}
};
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);
}
};
template<class T> class function_action<6, T> {
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);
}
};
template<class T> class function_action<7, T> {
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);
}
};
template<class T> class function_action<8, T> {
public:
template<class RET, class A1, class A2, class A3, class A4, class A5,
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);
}
};
template<class T> class function_action<9, T> {
public:
template<class RET, class A1, class A2, class A3, class A4, class A5,
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);
}
};
template<class T> class function_action<10, T> {
public:
template<class RET, class A1, class A2, class A3, class A4, class A5,
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);
}
};
} // namespace lambda
} // namespace boost
#endif

View File

@@ -0,0 +1,110 @@
// -- Boost Lambda Library -------------------------------------------------
// 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_ARITY_CODE_HPP
#define BOOST_LAMBDA_ARITY_CODE_HPP
#include "boost/type_traits/cv_traits.hpp"
#include "boost/type_traits/transform_traits.hpp"
namespace boost {
namespace lambda {
// These constants state, whether a lambda_functor instantiation results from
// an expression which contains no placeholders (NONE),
// only free1 placeholders (FIRST),
// free2 placeholders and maybe free1 placeholders (SECOND),
// free3 and maybe free1 and free2 placeholders (THIRD),
// 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};
template<class T>
struct get_tuple_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);
};
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);
};
template<>
struct get_tuple_arity<null_type> {
BOOST_STATIC_CONSTANT(int, value = 0);
};
// 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<int I, int J>
struct lacks_placeholder {
BOOST_STATIC_CONSTANT(bool, value = ((J & I) == 0));
};
} // namespace lambda
} // namespace boost
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,50 @@
// 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,789 @@
// Boost Lambda Library - function_adaptors.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_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
template<class RET, class A1>
static RET apply(A1& a1) {
return a1();
}
template<class RET, class A1, class A2>
static RET apply(A1& a1, A2& a2) {
return a1(a2);
}
template<class RET, class A1, class A2, class A3>
static RET apply(A1& a1, A2& a2, A3& a3) {
return a1(a2, a3);
}
template<class RET, class A1, class A2, class A3, class A4>
static RET apply(A1& a1, A2& a2, A3& a3, A4& a4) {
return a1(a2, a3, a4);
}
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 a1(a2, a3, a4, a5);
}
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 a1(a2, a3, a4, a5, a6);
}
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 a1(a2, a3, a4, a5, a6, a7);
}
template<class RET, class A1, class A2, class A3, class A4, class A5, 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 a1(a2, a3, a4, a5, a6, a7, a8);
}
template<class RET, class A1, class A2, class A3, class A4, class A5, 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 a1(a2, a3, a4, a5, a6, a7, a8, a9);
}
template<class RET, class A1, class A2, class A3, class A4, class A5, 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 a1(a2, a3, a4, a5, a6, a7, a8, a9, a10);
}
};
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; };
template <class RET>
static Result apply(Result (*func)()) {
return func();
}
};
template <class Result>
struct function_adaptor<Result (*)(void)> {
template<class T> struct sig { typedef Result type; };
template <class RET>
static Result apply(Result (*func)()) {
return func();
}
};
// -- 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; };
template <class RET>
static Result apply( Result (Object::*func)() const, const Object* o) {
return (o->*func)();
}
template <class RET>
static Result apply( Result (Object::*func)() const, const Object& o) {
return (o.*func)();
}
};
template <class Object, class Result>
struct function_adaptor<Result (Object::*)()> {
template<class T> struct sig { typedef Result type; };
template <class RET>
static Result apply( Result (Object::*func)(), Object* o) {
return (o->*func)();
}
template <class RET>
static Result apply( Result (Object::*func)(), Object& o) {
return (o.*func)();
}
};
template <class Arg1, class Result>
struct function_adaptor<Result (Arg1)> {
template<class T> struct sig { typedef Result type; };
template <class RET, class A1>
static Result apply(Result (*func)(Arg1), A1& a1) {
return func(a1);
}
};
template <class Arg1, class Result>
struct function_adaptor<Result (*)(Arg1)> {
template<class T> struct sig { typedef Result type; };
template <class RET, class A1>
static Result apply(Result (*func)(Arg1), A1& a1) {
return func(a1);
}
};
// -- 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; };
template <class RET, class 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) {
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; };
template <class RET, class A1>
static Result apply( Result (Object::*func)(Arg1), Object* o, A1& a1) {
return (o->*func)(a1);
}
template <class RET, class A1>
static Result apply( Result (Object::*func)(Arg1), Object& o, A1& a1) {
return (o.*func)(a1);
}
};
template <class Arg1, class Arg2, class Result>
struct function_adaptor<Result (Arg1, Arg2)> {
template<class T> struct sig { 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);
}
};
template <class Arg1, class Arg2, class Result>
struct function_adaptor<Result (*)(Arg1, Arg2)> {
template<class T> struct sig { 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);
}
};
// -- 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; };
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);
}
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);
}
};
template <class Object, class Arg1, class Arg2, class Result>
struct function_adaptor<Result (Object::*)(Arg1, Arg2)> {
template<class T> struct sig { 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);
}
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);
}
};
template <class Arg1, class Arg2, class Arg3, class Result>
struct function_adaptor<Result (Arg1, Arg2, Arg3)> {
template<class T> struct sig { 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);
}
};
template <class Arg1, class Arg2, class Arg3, class Result>
struct function_adaptor<Result (*)(Arg1, Arg2, Arg3)> {
template<class T> struct sig { 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);
}
};
// -- 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; };
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);
}
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);
}
};
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; };
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);
}
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);
}
};
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; };
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);
}
};
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; };
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);
}
};
// -- 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; };
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);
}
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);
}
};
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; };
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);
}
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);
}
};
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; };
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);
}
};
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; };
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);
}
};
// -- 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; };
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);
}
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);
}
};
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; };
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);
}
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);
}
};
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; };
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);
}
};
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; };
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);
}
};
// -- 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; };
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);
}
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);
}
};
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; };
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);
}
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);
}
};
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; };
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);
}
};
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; };
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);
}
};
// -- 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; };
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);
}
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);
}
};
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; };
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);
}
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);
}
};
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; };
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);
}
};
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; };
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);
}
};
// -- 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; };
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);
}
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);
}
};
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; };
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);
}
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);
}
};
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; };
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);
}
};
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; };
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);
}
};
} // namespace lambda
} // namespace boost
#endif

View File

@@ -0,0 +1,104 @@
// Boost Lambda Library - is_instance_of.hpp ---------------------
// Copyright (C) 2001 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_IS_INSTANCE_OF
#define BOOST_LAMBDA_IS_INSTANCE_OF
#include "boost/config.hpp" // for BOOST_STATIC_CONSTANT
#include "boost/type_traits/conversion_traits.hpp" // for is_convertible
#include "boost/preprocessor/enum_shifted_params.hpp"
#include "boost/preprocessor/repeat_2nd.hpp"
// is_instance_of --------------------------------
//
// is_instance_of_n<A, B>::value is true, if type A is
// an instantiation of a template B, or A derives from an instantiation
// of template B
//
// n is the number of template arguments for B
//
// Example:
// is_instance_of_2<std::istream, basic_stream>::value == true
// The original implementation was somewhat different, with different versions
// for different compilers. However, there was still a problem
// with gcc.3.0.2 and 3.0.3 compilers, which didn't think regard
// is_instance_of_N<...>::value was a constant.
// John Maddock suggested the way around this problem by building
// is_instance_of templates using boost::is_convertible.
// 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_LIST(n, NAME) BOOST_PP_REPEAT(n, BOOST_LAMBDA_CLASS, NAME)
#define BOOST_LAMBDA_CLASS_ARG_LIST(n, NAME) BOOST_PP_REPEAT(n, BOOST_LAMBDA_CLASS_ARG, NAME)
#define BOOST_LAMBDA_ARG_LIST(n, NAME) BOOST_PP_REPEAT(n, BOOST_LAMBDA_ARG, NAME)
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 */ \
\
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); \
};
#define BOOST_LAMBDA_HELPER(z, N, A) BOOST_LAMBDA_IS_INSTANCE_OF_TEMPLATE( BOOST_PP_INC(N) )
// Generate the traits for 1-4 argument templates
BOOST_PP_REPEAT_2ND(4,BOOST_LAMBDA_HELPER,FOO)
#undef BOOST_LAMBDA_HELPER
#undef BOOST_LAMBDA_IS_INSTANCE_OF_TEMPLATE
#undef BOOST_LAMBDA_CLASS
#undef BOOST_LAMBDA_ARG
#undef BOOST_LAMBDA_CLASS_ARG
#undef BOOST_LAMBDA_CLASS_LIST
#undef BOOST_LAMBDA_ARG_LIST
#undef BOOST_LAMBDA_CLASS_ARG_LIST
} // lambda
} // boost
#endif

View File

@@ -0,0 +1,48 @@
// Boost Lambda Library - lambda_config.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_LAMBDA_CONFIG_HPP
#define BOOST_LAMBDA_LAMBDA_CONFIG_HPP
// add to boost/config.hpp
// for now
# 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
# if (__GNUC__ == 2 && __GNUC_MINOR__ <= 97)
# define BOOST_NO_TEMPLATED_STREAMS
# define BOOST_LAMBDA_INCORRECT_BIND_OVERLOADING
# endif
# if (__GNUC__ == 2 && __GNUC_MINOR__ <= 95)
# define BOOST_LAMBDA_FAILS_IN_TEMPLATE_KEYWORD_AFTER_SCOPE_OPER
# endif
# endif // __GNUC__
#if defined __KCC
#define BOOST_NO_FDECL_TEMPLATES_AS_TEMPLATE_TEMPLATE_PARAMS
#endif // __KCC
#endif

View File

@@ -0,0 +1,615 @@
// Boost Lambda Library lambda_functor_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_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
// 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 U>
static inline const U& go(const U& u) { return u; }
};
template <class T> struct constify_rvals<T&> {
template<class U>
static inline U& go(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<> 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
// -- lambda_functor base ---------------------
// the explicit_return_type_action case -----------------------------------
template<class RET, class Args>
class lambda_functor_base<explicit_return_type_action<RET>, Args>
{
public:
Args args;
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
{
return detail::constify_rvals<RET>::go(
detail::r_select<RET>::go(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS));
}
};
// the protect_action case -----------------------------------
template<class Args>
class lambda_functor_base<protect_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
{
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 {};
template<class Args>
class lambda_functor_base<do_nothing_action, Args> {
// Args args;
public:
// explicit lambda_functor_base(const Args& a) {}
lambda_functor_base() {}
template<class RET, CALL_TEMPLATE_ARGS> RET call(CALL_FORMAL_ARGS) const {
return CALL_USE_ARGS;
}
template<class SigArgs> struct sig { typedef void type; };
};
// 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
// The return type is queried as:
// return_type_N<X, EvaluatedArgumentTypes>::type
// for which there must be a specialization.
// Function actions, casts, throws,... all go via these classes.
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>();
}
};
#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;
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;
return Act::template apply<RET>(
constify_rvals<rt0>::go(r_select<rt0>::go(get<0>(args), CALL_ACTUAL_ARGS))
);
}
};
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))
);
}
};
BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART(3)
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))
);
}
};
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;
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))
);
}
};
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;
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))
);
}
};
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;
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))
);
}
};
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;
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))
);
}
};
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;
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))
);
}
};
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))
);
}
};
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))
);
}
};
#undef BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART
} // namespace lambda
} // namespace boost
#endif

View File

@@ -0,0 +1,324 @@
// Boost Lambda Library - lambda_functors.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 http://www.boost.org
// ------------------------------------------------
#ifndef BOOST_LAMBDA_LAMBDA_FUNCTORS_HPP
#define BOOST_LAMBDA_LAMBDA_FUNCTORS_HPP
#include <boost/config.hpp>
#include <boost/detail/workaround.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 {
// -- lambda_functor --------------------------------------------
// --------------------------------------------------------------
//inline const null_type const_null_type() { return null_type(); }
namespace detail {
namespace {
static const null_type constant_null_type = null_type();
} // unnamed
} // detail
class unused {};
#define cnull_type() detail::constant_null_type
// -- 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 {
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;
};
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;
}
};
template<> struct placeholder<SECOND> {
template<class SigArgs> struct sig {
typedef typename detail::get_element_or_null_type<1, SigArgs>::type type;
};
template<class RET, CALL_TEMPLATE_ARGS>
RET call(CALL_FORMAL_ARGS) const { CALL_USE_ARGS; return b; }
};
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; }
};
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.
// -------------------------------------------------------------------
#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
{
BOOST_STATIC_CONSTANT(int, arity_bits = get_arity<T>::value);
public:
typedef T inherited;
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 ) );
}
};
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
#pragma warning(pop)
#endif
} // namespace lambda
} // namespace boost
// 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

@@ -0,0 +1,74 @@
// lambda_fwd.hpp - Boost Lambda Library -------------------------------
// 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_FWD_HPP
#define BOOST_LAMBDA_FWD_HPP
namespace boost {
namespace lambda {
namespace detail {
template<class T> struct generate_error;
}
// -- placeholders --------------------------------------------
template <int I> struct placeholder;
// function_adaptors
template <class Func>
struct function_adaptor;
template <int I, class Act> class action;
template <class Base>
class lambda_functor;
template <class Act, class Args>
class lambda_functor_base;
} // namespace lambda
} // 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

@@ -0,0 +1,578 @@
// - lambda_traits.hpp --- Boost Lambda Library ----------------------------
//
// 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_LAMBDA_TRAITS_HPP
#define BOOST_LAMBDA_LAMBDA_TRAITS_HPP
#include "boost/type_traits/transform_traits.hpp"
#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 {
// -- if construct ------------------------------------------------
// Proposed by Krzysztof Czarnecki and Ulrich Eisenecker
namespace detail {
template <bool If, class Then, class Else> struct IF { typedef Then RET; };
template <class Then, class Else> struct IF<false, Then, Else> {
typedef Else RET;
};
// An if construct that doesn't instantiate the non-matching template:
// Called as:
// IF_type<condition, A, B>::type
// The matching template must define the typeded 'type'
// I.e. A::type if condition is true, B::type if condition is false
// Idea from Vesa Karvonen (from C&E as well I guess)
template<class T>
struct IF_type_
{
typedef typename T::type type;
};
template<bool C, class T, class E>
struct IF_type
{
typedef typename
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
// If condition is true A::value must be defined, otherwise B::value
template<class T>
struct IF_value_
{
BOOST_STATIC_CONSTANT(int, value = T::value);
};
template<bool C, class T, class E>
struct IF_value
{
BOOST_STATIC_CONSTANT(int, value = (IF_value_<typename IF<C, T, E>::RET>::value));
};
// --------------------------------------------------------------
// removes reference from other than function types:
template<class T> class remove_reference_if_valid
{
typedef typename boost::remove_reference<T>::type plainT;
public:
typedef typename IF<
boost::is_function<plainT>::value,
T,
plainT
>::RET type;
};
template<class T> struct remove_reference_and_cv {
typedef typename boost::remove_cv<
typename boost::remove_reference<T>::type
>::type type;
};
// returns a reference to the element of tuple T
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;
};
// returns the cv and reverence stripped type of a tuple element
template<int N, class T> struct tuple_element_stripped {
typedef typename
remove_reference_and_cv<
typename boost::tuples::element<N, T>::type
>::type type;
};
// is_lambda_functor -------------------------------------------------
template <class T> struct is_lambda_functor_ {
BOOST_STATIC_CONSTANT(bool, value = false);
};
template <class Arg> struct is_lambda_functor_<lambda_functor<Arg> > {
BOOST_STATIC_CONSTANT(bool, value = true);
};
} // end detail
template <class T> struct is_lambda_functor {
BOOST_STATIC_CONSTANT(bool,
value =
detail::is_lambda_functor_<
typename detail::remove_reference_and_cv<T>::type
>::value);
};
namespace detail {
// -- parameter_traits_ ---------------------------------------------
// An internal parameter type traits class that respects
// the reference_wrapper class.
// The conversions performed are:
// references -> compile_time_error
// T1 -> T2,
// reference_wrapper<T> -> T&
// const array -> ref to const array
// array -> ref to array
// function -> ref to function
// ------------------------------------------------------------------------
template<class T1, class T2>
struct parameter_traits_ {
typedef T2 type;
};
// 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;
};
// Arrays can't be stored as plain types; convert them to references
template<class T, int n, class Any> struct parameter_traits_<T[n], Any> {
typedef T (&type)[n];
};
template<class T, int n, class Any>
struct parameter_traits_<const T[n], Any> {
typedef const T (&type)[n];
};
template<class T, int n, class Any>
struct parameter_traits_<volatile T[n], Any> {
typedef volatile T (&type)[n];
};
template<class T, int n, class Any>
struct parameter_traits_<const volatile T[n], Any> {
typedef const volatile T (&type)[n];
};
template<class T, class Any>
struct parameter_traits_<boost::reference_wrapper<T>, Any >{
typedef T& type;
};
template<class T, class Any>
struct parameter_traits_<const boost::reference_wrapper<T>, Any >{
typedef T& type;
};
template<class T, class Any>
struct parameter_traits_<volatile boost::reference_wrapper<T>, Any >{
typedef T& type;
};
template<class T, class Any>
struct parameter_traits_<const volatile boost::reference_wrapper<T>, Any >{
typedef T& type;
};
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
// ------------------------------------------------------------------------
// traits classes for lambda expressions (bind functions, operators ...)
// must be instantiated with non-reference types
// The default is const plain type -------------------------
// const T -> const T,
// T -> const T,
// references -> compile_time_error
// reference_wrapper<T> -> T&
// array -> const ref array
template<class T>
struct const_copy_argument {
typedef typename
detail::parameter_traits_<
T,
typename detail::IF<boost::is_function<T>::value, T&, const T>::RET
>::type type;
};
// T may be a function type. Without the IF test, const would be added
// to a function type, which is illegal.
// all arrays are converted to const.
// This traits template is used for 'const T&' parameter passing
// and thus the knowledge of the potential
// non-constness of an actual argument is lost.
template<class T, int n> struct const_copy_argument <T[n]> {
typedef const T (&type)[n];
};
template<class T, int n> struct const_copy_argument <volatile T[n]> {
typedef const volatile T (&type)[n];
};
template<class T>
struct const_copy_argument<T&> {};
// do not instantiate with references
// typedef typename detail::generate_error<T&>::references_not_allowed type;
template<>
struct const_copy_argument<void> {
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&,
// T -> T&,
// references -> compile_time_error
// reference_wrapper<T> -> T&
template<class T>
struct reference_argument {
typedef typename detail::parameter_traits_<T, T&>::type type;
};
template<class T>
struct reference_argument<T&> {
typedef typename detail::generate_error<T&>::references_not_allowed type;
};
template<class Arg>
struct reference_argument<lambda_functor<Arg> > {
typedef lambda_functor<Arg> type;
};
template<class Arg>
struct reference_argument<const lambda_functor<Arg> > {
typedef lambda_functor<Arg> type;
};
// Are the volatile versions needed?
template<class Arg>
struct reference_argument<volatile lambda_functor<Arg> > {
typedef lambda_functor<Arg> type;
};
template<class Arg>
struct reference_argument<const volatile lambda_functor<Arg> > {
typedef lambda_functor<Arg> type;
};
template<>
struct reference_argument<void> {
typedef void type;
};
namespace detail {
// Array to pointer conversion
template <class T>
struct array_to_pointer {
typedef T type;
};
template <class T, int N>
struct array_to_pointer <const T[N]> {
typedef const T* type;
};
template <class T, int N>
struct array_to_pointer <T[N]> {
typedef T* type;
};
template <class T, int N>
struct array_to_pointer <const T (&) [N]> {
typedef const T* type;
};
template <class T, int N>
struct array_to_pointer <T (&) [N]> {
typedef T* type;
};
// ---------------------------------------------------------------------------
// The call_traits for bind
// Respects the reference_wrapper class.
// These templates are used outside of bind functions as well.
// the bind_tuple_mapper provides a shorter notation for default
// bound argument storing semantics, if all arguments are treated
// uniformly.
// from template<class T> foo(const T& t) : bind_traits<const T>::type
// from template<class T> foo(T& t) : bind_traits<T>::type
// Conversions:
// T -> const T,
// cv T -> cv T,
// T& -> T&
// reference_wrapper<T> -> T&
// const reference_wrapper<T> -> T&
// array -> const ref array
// make bound arguments const, this is a deliberate design choice, the
// purpose is to prevent side effects to bound arguments that are stored
// as copies
template<class T>
struct bind_traits {
typedef const T type;
};
template<class T>
struct bind_traits<T&> {
typedef T& type;
};
// null_types are an exception, we always want to store them as non const
// so that other templates can assume that null_type is always without const
template<>
struct bind_traits<null_type> {
typedef null_type type;
};
// the bind_tuple_mapper, bind_type_generators may
// introduce const to null_type
template<>
struct bind_traits<const null_type> {
typedef null_type type;
};
// Arrays can't be stored as plain types; convert them to references.
// All arrays are converted to const. This is because bind takes its
// parameters as const T& and thus the knowledge of the potential
// non-constness of actual argument is lost.
template<class T, int n> struct bind_traits <T[n]> {
typedef const T (&type)[n];
};
template<class T, int n>
struct bind_traits<const T[n]> {
typedef const T (&type)[n];
};
template<class T, int n> struct bind_traits<volatile T[n]> {
typedef const volatile T (&type)[n];
};
template<class T, int n>
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;
};
template<class T>
struct bind_traits<const reference_wrapper<T> >{
typedef T& type;
};
template<>
struct bind_traits<void> {
typedef void type;
};
template <
class T0 = null_type, class T1 = null_type, class T2 = null_type,
class T3 = null_type, class T4 = null_type, class T5 = null_type,
class T6 = null_type, class T7 = null_type, class T8 = null_type,
class T9 = null_type
>
struct bind_tuple_mapper {
typedef
tuple<typename bind_traits<T0>::type,
typename bind_traits<T1>::type,
typename bind_traits<T2>::type,
typename bind_traits<T3>::type,
typename bind_traits<T4>::type,
typename bind_traits<T5>::type,
typename bind_traits<T6>::type,
typename bind_traits<T7>::type,
typename bind_traits<T8>::type,
typename bind_traits<T9>::type> type;
};
// bind_traits, except map const T& -> const T
// this is needed e.g. in currying. Const reference arguments can
// refer to temporaries, so it is not safe to store them as references.
template <class T> struct remove_const_reference {
typedef typename bind_traits<T>::type type;
};
template <class T> struct remove_const_reference<const T&> {
typedef const T type;
};
// maps the bind argument types to the resulting lambda functor type
template <
class T0 = null_type, class T1 = null_type, class T2 = null_type,
class T3 = null_type, class T4 = null_type, class T5 = null_type,
class T6 = null_type, class T7 = null_type, class T8 = null_type,
class T9 = null_type
>
class bind_type_generator {
typedef typename
detail::bind_tuple_mapper<
T0, T1, T2, T3, T4, T5, T6, T7, T8, T9
>::type args_t;
BOOST_STATIC_CONSTANT(int, nof_elems = boost::tuples::length<args_t>::value);
typedef
action<
nof_elems,
function_action<nof_elems>
> action_type;
public:
typedef
lambda_functor<
lambda_functor_base<
action_type,
args_t
>
> type;
};
} // detail
template <class T> inline const T& make_const(const T& t) { return t; }
} // end of namespace lambda
} // end of namespace boost
#endif // BOOST_LAMBDA_TRAITS_HPP

View File

@@ -0,0 +1,737 @@
// Boost Lambda Library -- member_ptr.hpp ---------------------
// Copyright (C) 1999, 2000 Jaakko Jarvi (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)
//
// For more information, see www.boost.org
// --------------------------------------------------------------------------
#if !defined(BOOST_LAMBDA_MEMBER_PTR_HPP)
#define BOOST_LAMBDA_MEMBER_PTR_HPP
namespace boost {
namespace lambda {
class member_pointer_action {};
namespace detail {
// the boost type_traits member_pointer traits are not enough,
// need to know more details.
template<class T>
struct member_pointer {
typedef typename boost::add_reference<T>::type type;
typedef detail::unspecified class_type;
typedef detail::unspecified qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = false);
};
template<class T, class U>
struct member_pointer<T U::*> {
typedef typename boost::add_reference<T>::type type;
typedef U class_type;
typedef U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = true);
BOOST_STATIC_CONSTANT(bool, is_function_member = false);
};
template<class T, class U>
struct member_pointer<const T U::*> {
typedef typename boost::add_reference<const T>::type type;
typedef U class_type;
typedef const U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = true);
BOOST_STATIC_CONSTANT(bool, is_function_member = false);
};
template<class T, class U>
struct member_pointer<volatile T U::*> {
typedef typename boost::add_reference<volatile T>::type type;
typedef U class_type;
typedef volatile U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = true);
BOOST_STATIC_CONSTANT(bool, is_function_member = false);
};
template<class T, class U>
struct member_pointer<const volatile T U::*> {
typedef typename boost::add_reference<const volatile T>::type type;
typedef U class_type;
typedef const volatile U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = true);
BOOST_STATIC_CONSTANT(bool, is_function_member = false);
};
// -- nonconst member functions --
template<class T, class U>
struct member_pointer<T (U::*)()> {
typedef T type;
typedef U class_type;
typedef U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1>
struct member_pointer<T (U::*)(A1)> {
typedef T type;
typedef U class_type;
typedef U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1, class A2>
struct member_pointer<T (U::*)(A1, A2)> {
typedef T type;
typedef U class_type;
typedef U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1, class A2, class A3>
struct member_pointer<T (U::*)(A1, A2, A3)> {
typedef T type;
typedef U class_type;
typedef U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1, class A2, class A3, class A4>
struct member_pointer<T (U::*)(A1, A2, A3, A4)> {
typedef T type;
typedef U class_type;
typedef U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1, class A2, class A3, class A4, class A5>
struct member_pointer<T (U::*)(A1, A2, A3, A4, A5)> {
typedef T type;
typedef U class_type;
typedef U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1, class A2, class A3, class A4, class A5,
class A6>
struct member_pointer<T (U::*)(A1, A2, A3, A4, A5, A6)> {
typedef T type;
typedef U class_type;
typedef U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1, class A2, class A3, class A4, class A5,
class A6, class A7>
struct member_pointer<T (U::*)(A1, A2, A3, A4, A5, A6, A7)> {
typedef T type;
typedef U class_type;
typedef U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1, class A2, class A3, class A4, class A5,
class A6, class A7, class A8>
struct member_pointer<T (U::*)(A1, A2, A3, A4, A5, A6, A7, A8)> {
typedef T type;
typedef U class_type;
typedef U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1, class A2, class A3, class A4, class A5,
class A6, class A7, class A8, class A9>
struct member_pointer<T (U::*)(A1, A2, A3, A4, A5, A6, A7, A8, A9)> {
typedef T type;
typedef U class_type;
typedef U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
// -- const member functions --
template<class T, class U>
struct member_pointer<T (U::*)() const> {
typedef T type;
typedef U class_type;
typedef const U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1>
struct member_pointer<T (U::*)(A1) const> {
typedef T type;
typedef U class_type;
typedef const U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1, class A2>
struct member_pointer<T (U::*)(A1, A2) const> {
typedef T type;
typedef U class_type;
typedef const U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1, class A2, class A3>
struct member_pointer<T (U::*)(A1, A2, A3) const> {
typedef T type;
typedef U class_type;
typedef const U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1, class A2, class A3, class A4>
struct member_pointer<T (U::*)(A1, A2, A3, A4) const> {
typedef T type;
typedef U class_type;
typedef const U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1, class A2, class A3, class A4, class A5>
struct member_pointer<T (U::*)(A1, A2, A3, A4, A5) const> {
typedef T type;
typedef U class_type;
typedef const U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1, class A2, class A3, class A4, class A5,
class A6>
struct member_pointer<T (U::*)(A1, A2, A3, A4, A5, A6) const> {
typedef T type;
typedef U class_type;
typedef const U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1, class A2, class A3, class A4, class A5,
class A6, class A7>
struct member_pointer<T (U::*)(A1, A2, A3, A4, A5, A6, A7) const> {
typedef T type;
typedef U class_type;
typedef const U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1, class A2, class A3, class A4, class A5,
class A6, class A7, class A8>
struct member_pointer<T (U::*)(A1, A2, A3, A4, A5, A6, A7, A8) const> {
typedef T type;
typedef U class_type;
typedef const U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1, class A2, class A3, class A4, class A5,
class A6, class A7, class A8, class A9>
struct member_pointer<T (U::*)(A1, A2, A3, A4, A5, A6, A7, A8, A9) const> {
typedef T type;
typedef U class_type;
typedef const U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
// -- volatile --
template<class T, class U>
struct member_pointer<T (U::*)() volatile> {
typedef T type;
typedef U class_type;
typedef volatile U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1>
struct member_pointer<T (U::*)(A1) volatile> {
typedef T type;
typedef U class_type;
typedef volatile U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1, class A2>
struct member_pointer<T (U::*)(A1, A2) volatile> {
typedef T type;
typedef U class_type;
typedef volatile U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1, class A2, class A3>
struct member_pointer<T (U::*)(A1, A2, A3) volatile> {
typedef T type;
typedef U class_type;
typedef volatile U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1, class A2, class A3, class A4>
struct member_pointer<T (U::*)(A1, A2, A3, A4) volatile> {
typedef T type;
typedef U class_type;
typedef volatile U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1, class A2, class A3, class A4, class A5>
struct member_pointer<T (U::*)(A1, A2, A3, A4, A5) volatile> {
typedef T type;
typedef U class_type;
typedef volatile U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1, class A2, class A3, class A4, class A5,
class A6>
struct member_pointer<T (U::*)(A1, A2, A3, A4, A5, A6) volatile> {
typedef T type;
typedef U class_type;
typedef volatile U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1, class A2, class A3, class A4, class A5,
class A6, class A7>
struct member_pointer<T (U::*)(A1, A2, A3, A4, A5, A6, A7) volatile> {
typedef T type;
typedef U class_type;
typedef volatile U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1, class A2, class A3, class A4, class A5,
class A6, class A7, class A8>
struct member_pointer<T (U::*)(A1, A2, A3, A4, A5, A6, A7, A8) volatile> {
typedef T type;
typedef U class_type;
typedef volatile U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1, class A2, class A3, class A4, class A5,
class A6, class A7, class A8, class A9>
struct member_pointer<T (U::*)(A1, A2, A3, A4, A5, A6, A7, A8, A9) volatile> {
typedef T type;
typedef U class_type;
typedef volatile U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
// -- const volatile
template<class T, class U>
struct member_pointer<T (U::*)() const volatile> {
typedef T type;
typedef U class_type;
typedef const volatile U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1>
struct member_pointer<T (U::*)(A1) const volatile> {
typedef T type;
typedef U class_type;
typedef const volatile U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1, class A2>
struct member_pointer<T (U::*)(A1, A2) const volatile> {
typedef T type;
typedef U class_type;
typedef const volatile U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1, class A2, class A3>
struct member_pointer<T (U::*)(A1, A2, A3) const volatile> {
typedef T type;
typedef U class_type;
typedef const volatile U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1, class A2, class A3, class A4>
struct member_pointer<T (U::*)(A1, A2, A3, A4) const volatile> {
typedef T type;
typedef U class_type;
typedef const volatile U qualified_class_type;
};
template<class T, class U, class A1, class A2, class A3, class A4, class A5>
struct member_pointer<T (U::*)(A1, A2, A3, A4, A5) const volatile> {
typedef T type;
typedef U class_type;
typedef const volatile U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1, class A2, class A3, class A4, class A5,
class A6>
struct member_pointer<T (U::*)(A1, A2, A3, A4, A5, A6) const volatile> {
typedef T type;
typedef U class_type;
typedef const volatile U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1, class A2, class A3, class A4, class A5,
class A6, class A7>
struct member_pointer<T (U::*)(A1, A2, A3, A4, A5, A6, A7) const volatile> {
typedef T type;
typedef U class_type;
typedef const volatile U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1, class A2, class A3, class A4, class A5,
class A6, class A7, class A8>
struct member_pointer<T (U::*)(A1, A2, A3, A4, A5, A6, A7, A8) const volatile> {
typedef T type;
typedef U class_type;
typedef const volatile U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
template<class T, class U, class A1, class A2, class A3, class A4, class A5,
class A6, class A7, class A8, class A9>
struct member_pointer<T (U::*)(A1, A2, A3, A4, A5, A6, A7, A8, A9) const volatile> {
typedef T type;
typedef U class_type;
typedef const volatile U qualified_class_type;
BOOST_STATIC_CONSTANT(bool, is_data_member = false);
BOOST_STATIC_CONSTANT(bool, is_function_member = true);
};
} // detail
namespace detail {
// this class holds a pointer to a member function and the object.
// when called, it just calls the member function with the parameters
// provided
// It would have been possible to use existing lambda_functors to represent
// a bound member function like this, but to have a separate template is
// safer, since now this functor doesn't mix and match with lambda_functors
// only thing you can do with this is to call it
// note that previously instantiated classes
// (other_action<member_pointer_action> and member_pointer_action_helper
// guarantee, that A and B are
// such types, that for objects a and b of corresponding types, a->*b leads
// to the builtin ->* to be called. So types that would end in a call to
// a user defined ->* do not create a member_pointer_caller object.
template<class RET, class A, class B>
class member_pointer_caller {
A a; B b;
public:
member_pointer_caller(const A& aa, const B& bb) : a(aa), b(bb) {}
RET operator()() const { return (a->*b)(); }
template<class A1>
RET operator()(const A1& a1) const { return (a->*b)(a1); }
template<class A1, class A2>
RET operator()(const A1& a1, const A2& a2) const { return (a->*b)(a1, a2); }
template<class A1, class A2, class A3>
RET operator()(const A1& a1, const A2& a2, const A3& a3) const {
return (a->*b)(a1, a2, a3);
}
template<class A1, class A2, class A3, class A4>
RET operator()(const A1& a1, const A2& a2, const A3& a3,
const A4& a4) const {
return (a->*b)(a1, a2, a3, a4);
}
template<class A1, class A2, class A3, class A4, class A5>
RET operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
const A5& a5) const {
return (a->*b)(a1, a2, a3, a4, a5);
}
template<class A1, class A2, class A3, class A4, class A5, class A6>
RET operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
const A5& a5, const A6& a6) const {
return (a->*b)(a1, a2, a3, a4, a5, a6);
}
template<class A1, class A2, class A3, class A4, class A5, class A6,
class A7>
RET operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
const A5& a5, const A6& a6, const A7& a7) const {
return (a->*b)(a1, a2, a3, a4, a5, a6, a7);
}
template<class A1, class A2, class A3, class A4, class A5, class A6,
class A7, class A8>
RET operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
const A5& a5, const A6& a6, const A7& a7,
const A8& a8) const {
return (a->*b)(a1, a2, a3, a4, a5, a6, a7, a8);
}
template<class A1, class A2, class A3, class A4, class A5, class A6,
class A7, class A8, class A9>
RET operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
const A5& a5, const A6& a6, const A7& a7,
const A8& a8, const A9& a9) const {
return (a->*b)(a1, a2, a3, a4, a5, a6, a7, a8, a9);
}
};
// helper templates for return type deduction and action classes
// different cases for data member, function member, neither
// true-true case
template <bool Is_data_member, bool Is_function_member>
struct member_pointer_action_helper;
// cannot be both, no body provided
// data member case
// this means, that B is a data member and A is a pointer type,
// so either built-in ->* should be called, or there is an error
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;
}
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;
// 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, 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
// (cv T == T if T is a reference type)
typedef typename detail::IF<
::boost::is_const<non_pointer_A>::value,
typename ::boost::add_const<type1>::type,
type1
>::RET type2;
typedef typename detail::IF<
::boost::is_volatile<non_pointer_A>::value,
typename ::boost::add_volatile<type2>::type,
type2
>::RET type3;
// add reference back
typedef typename ::boost::add_reference<type3>::type type;
};
};
// neither case
template <>
struct member_pointer_action_helper<false, false> {
public:
template<class RET, class A, class B>
static RET apply(A& a, B& b) {
// not a built in member pointer operator, just call ->*
return a->*b;
}
// 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;
};
};
// member pointer function case
// This is a built in ->* call for a member function,
// the only thing that you can do with that, is to give it some arguments
// note, it is guaranteed that A is a pointer type, and thus it cannot
// be a call to overloaded ->*
template <>
struct member_pointer_action_helper<false, true> {
public:
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);
}
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;
};
};
} // detail
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<
boost::is_pointer<A>::value &&
detail::member_pointer<plainB>::is_data_member,
boost::is_pointer<A>::value &&
detail::member_pointer<plainB>::is_function_member
>::template apply<RET>(a, b);
}
};
// return type deduction --
// If the right argument is a pointer to data member,
// and the left argument is of compatible pointer to class type
// return type is a reference to the data member type
// if right argument is a pointer to a member function, and the left
// argument is of a compatible type, the return type is a
// member_pointer_caller (see above)
// Otherwise, return type deduction fails. There is either an error,
// or the user is trying to call an overloaded ->*
// 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_action_helper<
detail::member_pointer<plainB>::is_data_member,
detail::member_pointer<plainB>::is_function_member
>::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<
action<2, other_action<member_pointer_action> >,
tuple<lambda_functor<Arg1>, typename const_copy_argument<Arg2>::type>
>
>
operator->*(const lambda_functor<Arg1>& a1, const Arg2& a2)
{
return
lambda_functor_base<
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>(a1, a2));
}
template<class Arg1, class Arg2>
inline const
lambda_functor<
lambda_functor_base<
action<2, other_action<member_pointer_action> >,
tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >
>
>
operator->*(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2)
{
return
lambda_functor_base<
action<2, other_action<member_pointer_action> >,
tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >
>
(tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >(a1, a2));
}
template<class Arg1, class Arg2>
inline const
lambda_functor<
lambda_functor_base<
action<2, other_action<member_pointer_action> >,
tuple<typename const_copy_argument<Arg1>::type, lambda_functor<Arg2> >
>
>
operator->*(const Arg1& a1, const lambda_functor<Arg2>& a2)
{
return
lambda_functor_base<
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> >(a1, a2));
}
} // namespace lambda
} // namespace boost
#endif

View File

@@ -0,0 +1,139 @@
// -- operator_actions.hpp - Boost Lambda Library ----------------------
// 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 http://lambda.cs.utu.fi
#ifndef BOOST_LAMBDA_OPERATOR_ACTIONS_HPP
#define BOOST_LAMBDA_OPERATOR_ACTIONS_HPP
namespace boost {
namespace lambda {
// -- artihmetic ----------------------
class plus_action {};
class minus_action {};
class multiply_action {};
class divide_action {};
class remainder_action {};
// -- bitwise -------------------
class leftshift_action {};
class rightshift_action {};
class xor_action {};
// -- bitwise/logical -------------------
class and_action {};
class or_action {};
class not_action {};
// -- relational -------------------------
class less_action {};
class greater_action {};
class lessorequal_action {};
class greaterorequal_action {};
class equal_action {};
class notequal_action {};
// -- increment/decrement ------------------------------
class increment_action {};
class decrement_action {};
// -- void return ------------------------------
// -- other ------------------------------
class addressof_action {};
// class comma_action {}; // defined in actions.hpp
class contentsof_action {};
// class member_pointer_action {}; (defined in member_ptr.hpp)
// -- actioun group templates --------------------
template <class Action> class arithmetic_action;
template <class Action> class bitwise_action;
template <class Action> class logical_action;
template <class Action> class relational_action;
template <class Action> class arithmetic_assignment_action;
template <class Action> class bitwise_assignment_action;
template <class Action> class unary_arithmetic_action;
template <class Action> class pre_increment_decrement_action;
template <class Action> class post_increment_decrement_action;
// ---------------------------------------------------------
// actions, for which the existence of protect is checked in return type
// deduction.
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);
};
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);
};
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);
};
// NOTE: comma action is also protectable, but the specialization is
// in actions.hpp
} // namespace lambda
} // namespace boost
#endif

View File

@@ -0,0 +1,271 @@
// 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,917 @@
// operator_return_type_traits.hpp -- Boost Lambda Library ------------------
// 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_RETURN_TYPE_TRAITS_HPP
#define BOOST_LAMBDA_OPERATOR_RETURN_TYPE_TRAITS_HPP
#include "boost/lambda/detail/is_instance_of.hpp"
#include "boost/type_traits/same_traits.hpp"
#include "boost/indirect_reference.hpp"
#include "boost/detail/container_fwd.hpp"
#include <cstddef> // needed for the ptrdiff_t
#include <iosfwd> // for istream and ostream
#include <iterator> // needed for operator&
namespace boost {
namespace lambda {
namespace detail {
// -- general helper templates for type deduction ------------------
// Much of the type deduction code for standard arithmetic types from Gary Powell
template <class A> struct promote_code { static const int value = -1; };
// this means that a code is not defined for A
// -- the next 5 types are needed in if_then_else_return
// the promotion order is not important, but they must have distinct values.
template <> struct promote_code<bool> { static const int value = 10; };
template <> struct promote_code<char> { static const int value = 20; };
template <> struct promote_code<unsigned char> { static const int value = 30; };
template <> struct promote_code<signed char> { static const int value = 40; };
template <> struct promote_code<short int> { static const int value = 50; };
// ----------
template <> struct promote_code<int> { static const int value = 100; };
template <> struct promote_code<unsigned int> { static const int value = 200; };
template <> struct promote_code<long> { static const int value = 300; };
template <> struct promote_code<unsigned long> { static const int value = 400; };
template <> struct promote_code<float> { static const int value = 500; };
template <> struct promote_code<double> { static const int value = 600; };
template <> struct promote_code<long double> { static const int value = 700; };
// TODO: wchar_t
// forward delcaration of complex.
} // namespace detail
} // namespace lambda
} // namespace boost
namespace boost {
namespace lambda {
namespace detail {
template <> struct promote_code< std::complex<float> > { static const int value = 800; };
template <> struct promote_code< std::complex<double> > { static const int value = 900; };
template <> struct promote_code< std::complex<long double> > { static const int value = 1000; };
// -- int promotion -------------------------------------------
template <class T> struct promote_to_int { typedef T type; };
template <> struct promote_to_int<bool> { typedef int type; };
template <> struct promote_to_int<char> { typedef int type; };
template <> struct promote_to_int<unsigned char> { typedef int type; };
template <> struct promote_to_int<signed char> { typedef int type; };
template <> struct promote_to_int<short int> { typedef int type; };
// The unsigned short int promotion rule is this:
// unsigned short int to signed int if a signed int can hold all values
// 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),
// I had the logic reversed but ">" messes up the parsing.
unsigned int,
int>::RET type;
};
// TODO: think, should there be default behaviour for non-standard types?
} // namespace detail
// ------------------------------------------
// Unary actions ----------------------------
// ------------------------------------------
template<class Act, class A>
struct plain_return_type_1 {
typedef detail::unspecified type;
};
template<class Act, class A>
struct plain_return_type_1<unary_arithmetic_action<Act>, A> {
typedef A type;
};
template<class Act, class A>
struct return_type_1<unary_arithmetic_action<Act>, A> {
typedef
typename plain_return_type_1<
unary_arithmetic_action<Act>,
typename detail::remove_reference_and_cv<A>::type
>::type type;
};
template<class A>
struct plain_return_type_1<bitwise_action<not_action>, A> {
typedef A type;
};
// bitwise not, operator~()
template<class A> struct return_type_1<bitwise_action<not_action>, A> {
typedef
typename plain_return_type_1<
bitwise_action<not_action>,
typename detail::remove_reference_and_cv<A>::type
>::type type;
};
// prefix increment and decrement operators return
// their argument by default as a non-const reference
template<class Act, class A>
struct plain_return_type_1<pre_increment_decrement_action<Act>, A> {
typedef A& type;
};
template<class Act, class A>
struct return_type_1<pre_increment_decrement_action<Act>, A> {
typedef
typename plain_return_type_1<
pre_increment_decrement_action<Act>,
typename detail::remove_reference_and_cv<A>::type
>::type type;
};
// post decrement just returns the same plain type.
template<class Act, class A>
struct plain_return_type_1<post_increment_decrement_action<Act>, A> {
typedef A type;
};
template<class Act, class A>
struct return_type_1<post_increment_decrement_action<Act>, A>
{
typedef
typename plain_return_type_1<
post_increment_decrement_action<Act>,
typename detail::remove_reference_and_cv<A>::type
>::type type;
};
// logical not, operator!()
template<class A>
struct plain_return_type_1<logical_action<not_action>, A> {
typedef bool type;
};
template<class A>
struct return_type_1<logical_action<not_action>, A> {
typedef
typename plain_return_type_1<
logical_action<not_action>,
typename detail::remove_reference_and_cv<A>::type
>::type type;
};
// address of action ---------------------------------------
template<class A>
struct return_type_1<other_action<addressof_action>, A> {
typedef
typename plain_return_type_1<
other_action<addressof_action>,
typename detail::remove_reference_and_cv<A>::type
>::type type1;
// If no user defined specialization for A, then return the
// cv qualified pointer to A
typedef typename detail::IF<
boost::is_same<type1, detail::unspecified>::value,
typename boost::remove_reference<A>::type*,
type1
>::RET type;
};
// contentsof action ------------------------------------
// TODO: this deduction may lead to fail directly,
// (if A has no specialization for iterator_traits and has no
// typedef A::reference.
// There is no easy way around this, cause there doesn't seem to be a way
// to test whether a class is an iterator or not.
// The default works with std::iterators.
namespace detail {
// A is a nonreference type
template <class A> struct contentsof_type {
typedef typename boost::indirect_reference<A>::type 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;
};
template <class A> struct contentsof_type<volatile A> {
typedef typename contentsof_type<A>::type type;
};
template <class A> struct contentsof_type<const volatile A> {
typedef typename contentsof_type<A>::type type;
};
// standard iterator traits should take care of the pointer types
// but just to be on the safe side, we have the specializations here:
// these work even if A is cv-qualified.
template <class A> struct contentsof_type<A*> {
typedef A& type;
};
template <class A> struct contentsof_type<A* const> {
typedef A& type;
};
template <class A> struct contentsof_type<A* volatile> {
typedef A& type;
};
template <class A> struct contentsof_type<A* const volatile> {
typedef A& type;
};
template<class A, int N> struct contentsof_type<A[N]> {
typedef A& type;
};
template<class A, int N> struct contentsof_type<const A[N]> {
typedef const A& type;
};
template<class A, int N> struct contentsof_type<volatile A[N]> {
typedef volatile A& type;
};
template<class A, int N> struct contentsof_type<const volatile A[N]> {
typedef const volatile A& type;
};
} // end detail
template<class A>
struct return_type_1<other_action<contentsof_action>, A> {
typedef
typename plain_return_type_1<
other_action<contentsof_action>,
typename detail::remove_reference_and_cv<A>::type
>::type type1;
// If no user defined specialization for A, then return the
// cv qualified pointer to A
typedef typename
detail::IF_type<
boost::is_same<type1, detail::unspecified>::value,
detail::contentsof_type<
typename boost::remove_reference<A>::type
>,
detail::identity_mapping<type1>
>::type type;
};
// ------------------------------------------------------------------
// binary actions ---------------------------------------------------
// ------------------------------------------------------------------
// here the default case is: no user defined versions:
template <class Act, class A, class B>
struct plain_return_type_2 {
typedef detail::unspecified type;
};
namespace detail {
// error classes
class illegal_pointer_arithmetic{};
// pointer arithmetic type deductions ----------------------
// value = false means that this is not a pointer arithmetic case
// value = true means, that this can be a pointer arithmetic case, but not necessarily is
// This means, that for user defined operators for pointer types, say for some operator+(X, *Y),
// the deductions must be coded at an earliel level (return_type_2).
template<class Act, class A, class B>
struct pointer_arithmetic_traits { static const bool value = false; };
template<class A, class B>
struct pointer_arithmetic_traits<plus_action, A, B> {
typedef typename
array_to_pointer<typename boost::remove_reference<A>::type>::type AP;
typedef typename
array_to_pointer<typename boost::remove_reference<B>::type>::type BP;
static const bool is_pointer_A = boost::is_pointer<AP>::value;
static const bool is_pointer_B = boost::is_pointer<BP>::value;
static const bool value = is_pointer_A || is_pointer_B;
// can't add two pointers.
// note, that we do not check wether the other type is valid for
// addition with a pointer.
// the compiler will catch it in the apply function
typedef typename
detail::IF<
is_pointer_A && is_pointer_B,
detail::return_type_deduction_failure<
detail::illegal_pointer_arithmetic
>,
typename detail::IF<is_pointer_A, AP, BP>::RET
>::RET type;
};
template<class A, class B>
struct pointer_arithmetic_traits<minus_action, A, B> {
typedef typename
array_to_pointer<typename boost::remove_reference<A>::type>::type AP;
typedef typename
array_to_pointer<typename boost::remove_reference<B>::type>::type BP;
static const bool is_pointer_A = boost::is_pointer<AP>::value;
static const bool is_pointer_B = boost::is_pointer<BP>::value;
static const bool value = is_pointer_A || is_pointer_B;
static const bool same_pointer_type =
is_pointer_A && is_pointer_B &&
boost::is_same<
typename boost::remove_const<
typename boost::remove_pointer<
typename boost::remove_const<AP>::type
>::type
>::type,
typename boost::remove_const<
typename boost::remove_pointer<
typename boost::remove_const<BP>::type
>::type
>::type
>::value;
// ptr - ptr has type ptrdiff_t
// note, that we do not check if, in ptr - B, B is
// valid for subtraction with a pointer.
// the compiler will catch it in the apply function
typedef typename
detail::IF<
same_pointer_type, const std::ptrdiff_t,
typename detail::IF<
is_pointer_A,
AP,
detail::return_type_deduction_failure<detail::illegal_pointer_arithmetic>
>::RET
>::RET type;
};
} // namespace detail
// -- arithmetic actions ---------------------------------------------
namespace detail {
template<bool is_pointer_arithmetic, class Act, class A, class B>
struct return_type_2_arithmetic_phase_1;
template<class A, class B> struct return_type_2_arithmetic_phase_2;
template<class A, class B> struct return_type_2_arithmetic_phase_3;
} // namespace detail
// drop any qualifiers from the argument types within arithmetic_action
template<class A, class B, class Act>
struct return_type_2<arithmetic_action<Act>, 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<arithmetic_action<Act>, plain_A, plain_B>::type type1;
// if user defined return type, do not enter the whole arithmetic deductions
typedef typename
detail::IF_type<
boost::is_same<type1, detail::unspecified>::value,
detail::return_type_2_arithmetic_phase_1<
detail::pointer_arithmetic_traits<Act, A, B>::value, Act, A, B
>,
plain_return_type_2<arithmetic_action<Act>, plain_A, plain_B>
>::type type;
};
namespace detail {
// perform integral promotion, no pointer arithmetic
template<bool is_pointer_arithmetic, class Act, class A, class B>
struct return_type_2_arithmetic_phase_1
{
typedef typename
return_type_2_arithmetic_phase_2<
typename remove_reference_and_cv<A>::type,
typename remove_reference_and_cv<B>::type
>::type type;
};
// pointer_arithmetic
template<class Act, class A, class B>
struct return_type_2_arithmetic_phase_1<true, Act, A, B>
{
typedef typename
pointer_arithmetic_traits<Act, A, B>::type type;
};
template<class A, class B>
struct return_type_2_arithmetic_phase_2 {
typedef typename
return_type_2_arithmetic_phase_3<
typename promote_to_int<A>::type,
typename promote_to_int<B>::type
>::type type;
};
// specialization for unsigned int.
// We only have to do these two specialization because the value promotion will
// take care of the other cases.
// The unsigned int promotion rule is this:
// unsigned int to long if a long can hold all values of unsigned int,
// otherwise go to unsigned long.
// 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;
};
template<>
struct return_type_2_arithmetic_phase_2<unsigned int, long>
{
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;
};
template<class A, class B> struct return_type_2_arithmetic_phase_3 {
enum { promote_code_A_value = promote_code<A>::value,
promote_code_B_value = promote_code<B>::value }; // enums for KCC
typedef typename
detail::IF<
promote_code_A_value == -1 || promote_code_B_value == -1,
detail::return_type_deduction_failure<return_type_2_arithmetic_phase_3>,
typename detail::IF<
((int)promote_code_A_value > (int)promote_code_B_value),
A,
B
>::RET
>::RET type;
};
} // namespace detail
// -- bitwise actions -------------------------------------------
// note: for integral types deuduction is similar to arithmetic actions.
// drop any qualifiers from the argument types within arithmetic action
template<class A, class B, class Act>
struct return_type_2<bitwise_action<Act>, 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<bitwise_action<Act>, plain_A, plain_B>::type type1;
// if user defined return type, do not enter type deductions
typedef typename
detail::IF_type<
boost::is_same<type1, detail::unspecified>::value,
return_type_2<arithmetic_action<plus_action>, A, B>,
plain_return_type_2<bitwise_action<Act>, plain_A, plain_B>
>::type type;
// plus_action is just a random pick, has to be a concrete instance
// TODO: This check is only valid for built-in types, overloaded types might
// accept floating point operators
// bitwise operators not defined for floating point types
// these test are not strictly needed here, since the error will be caught in
// the apply function
BOOST_STATIC_ASSERT(!(boost::is_float<plain_A>::value && boost::is_float<plain_B>::value));
};
namespace detail {
#ifdef BOOST_NO_TEMPLATED_STREAMS
template<class A, class B>
struct leftshift_type {
typedef typename detail::IF<
boost::is_convertible<
typename boost::remove_reference<A>::type*,
std::ostream*
>::value,
std::ostream&,
typename detail::remove_reference_and_cv<A>::type
>::RET type;
};
template<class A, class B>
struct rightshift_type {
typedef typename detail::IF<
boost::is_convertible<
typename boost::remove_reference<A>::type*,
std::istream*
>::value,
std::istream&,
typename detail::remove_reference_and_cv<A>::type
>::RET type;
};
#else
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;
};
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;
};
#endif
} // end detail
// ostream
template<class A, class B>
struct return_type_2<bitwise_action<leftshift_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<bitwise_action<leftshift_action>, plain_A, plain_B>::type type1;
// if user defined return type, do not enter type deductions
typedef typename
detail::IF_type<
boost::is_same<type1, detail::unspecified>::value,
detail::leftshift_type<A, B>,
plain_return_type_2<bitwise_action<leftshift_action>, plain_A, plain_B>
>::type type;
};
// istream
template<class A, class B>
struct return_type_2<bitwise_action<rightshift_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<bitwise_action<rightshift_action>, plain_A, plain_B>::type type1;
// if user defined return type, do not enter type deductions
typedef typename
detail::IF_type<
boost::is_same<type1, detail::unspecified>::value,
detail::rightshift_type<A, B>,
plain_return_type_2<bitwise_action<rightshift_action>, plain_A, plain_B>
>::type type;
};
// -- logical actions ----------------------------------------
// always bool
// NOTE: this may not be true for some weird user-defined types,
template<class A, class B, class Act>
struct plain_return_type_2<logical_action<Act>, A, B> {
typedef bool type;
};
template<class A, class B, class Act>
struct return_type_2<logical_action<Act>, 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<logical_action<Act>, plain_A, plain_B>::type type;
};
// -- relational actions ----------------------------------------
// always bool
// NOTE: this may not be true for some weird user-defined types,
template<class A, class B, class Act>
struct plain_return_type_2<relational_action<Act>, A, B> {
typedef bool type;
};
template<class A, class B, class Act>
struct return_type_2<relational_action<Act>, 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<relational_action<Act>, plain_A, plain_B>::type type;
};
// Assingment actions -----------------------------------------------
// return type is the type of the first argument as reference
// note that cv-qualifiers are preserved.
// Yes, assignment operator can be const!
// NOTE: this may not be true for some weird user-defined types,
template<class A, class B, class Act>
struct return_type_2<arithmetic_assignment_action<Act>, 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<
arithmetic_assignment_action<Act>, plain_A, plain_B
>::type type1;
typedef typename
detail::IF<
boost::is_same<type1, detail::unspecified>::value,
typename boost::add_reference<A>::type,
type1
>::RET type;
};
template<class A, class B, class Act>
struct return_type_2<bitwise_assignment_action<Act>, 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<
bitwise_assignment_action<Act>, plain_A, plain_B
>::type type1;
typedef typename
detail::IF<
boost::is_same<type1, detail::unspecified>::value,
typename boost::add_reference<A>::type,
type1
>::RET type;
};
template<class A, class B>
struct return_type_2<other_action<assignment_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<assignment_action>, plain_A, plain_B
>::type type1;
typedef typename
detail::IF<
boost::is_same<type1, detail::unspecified>::value,
typename boost::add_reference<A>::type,
type1
>::RET type;
};
// -- other actions ----------------------------------------
// 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)
// (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;
};
// subscript action -----------------------------------------------
namespace detail {
// A and B are nonreference types
template <class A, class B> struct subscript_type {
typedef detail::unspecified type;
};
template <class A, class B> struct subscript_type<A*, B> {
typedef A& type;
};
template <class A, class B> struct subscript_type<A* const, B> {
typedef A& type;
};
template <class A, class B> struct subscript_type<A* volatile, B> {
typedef A& type;
};
template <class A, class B> struct subscript_type<A* const volatile, B> {
typedef A& type;
};
template<class A, class B, int N> struct subscript_type<A[N], B> {
typedef A& type;
};
// these 3 specializations are needed to make gcc <3 happy
template<class A, class B, int N> struct subscript_type<const A[N], B> {
typedef const A& type;
};
template<class A, class B, int N> struct subscript_type<volatile A[N], B> {
typedef volatile A& type;
};
template<class A, class B, int N> struct subscript_type<const volatile A[N], B> {
typedef const volatile A& type;
};
} // end detail
template<class A, class B>
struct return_type_2<other_action<subscript_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 boost::remove_reference<A>::type nonref_A;
typedef typename boost::remove_reference<B>::type nonref_B;
typedef typename
plain_return_type_2<
other_action<subscript_action>, plain_A, plain_B
>::type type1;
typedef typename
detail::IF_type<
boost::is_same<type1, detail::unspecified>::value,
detail::subscript_type<nonref_A, nonref_B>,
plain_return_type_2<other_action<subscript_action>, plain_A, plain_B>
>::type type;
};
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;
// T == std::map<Key, T, Cmp, Allocator>::mapped_type;
};
template<class Key, class T, class Cmp, class Allocator, class B>
struct plain_return_type_2<other_action<subscript_action>, std::multimap<Key, T, Cmp, Allocator>, B> {
typedef T& type;
// T == std::map<Key, T, Cmp, Allocator>::mapped_type;
};
// deque
template<class T, class Allocator, class B>
struct plain_return_type_2<other_action<subscript_action>, std::deque<T, Allocator>, B> {
typedef typename std::deque<T, Allocator>::reference type;
};
template<class T, class Allocator, class B>
struct plain_return_type_2<other_action<subscript_action>, const std::deque<T, Allocator>, B> {
typedef typename std::deque<T, Allocator>::const_reference type;
};
// vector
template<class T, class Allocator, class B>
struct plain_return_type_2<other_action<subscript_action>, std::vector<T, Allocator>, B> {
typedef typename std::vector<T, Allocator>::reference type;
};
template<class T, class Allocator, class B>
struct plain_return_type_2<other_action<subscript_action>, const std::vector<T, Allocator>, B> {
typedef typename std::vector<T, Allocator>::const_reference type;
};
// basic_string
template<class Char, class Traits, class Allocator, class B>
struct plain_return_type_2<other_action<subscript_action>, std::basic_string<Char, Traits, Allocator>, B> {
typedef typename std::basic_string<Char, Traits, Allocator>::reference type;
};
template<class Char, class Traits, class Allocator, class B>
struct plain_return_type_2<other_action<subscript_action>, const std::basic_string<Char, Traits, Allocator>, B> {
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
#endif

View File

@@ -0,0 +1,370 @@
// Boost Lambda Library - operators.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_OPERATORS_HPP
#define BOOST_LAMBDA_OPERATORS_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"
#endif
// For all BOOSTA_LAMBDA_BE* macros:
// 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"
#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)); \
}
#if defined BOOST_LAMBDA_BE3
#error "Multiple defines of BOOST_LAMBDA_BE3"
#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)); \
}
#if defined BOOST_LAMBDA_BE
#error "Multiple defines of BOOST_LAMBDA_BE"
#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_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_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)
// A special trick for comma operator for correct preprocessing
#if defined BOOST_LAMBDA_COMMA_OPERATOR_NAME
#error "Multiple defines of BOOST_LAMBDA_COMMA_OPERATOR_NAME"
#endif
#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)
namespace detail {
// special cases for ostream& << Any and istream& >> Any ---------------
// the actual stream classes may vary and thus a specialisation for,
// say ostream& does not match (the general case above is chosen).
// Therefore we specialise for non-const reference:
// if the left argument is a stream, we store the stream as reference
// if it is something else, we store a const plain by default
// 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<
is_instance_of_2<
T, std::basic_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<
is_instance_of_2<
T, std::basic_istream
>::value,
T&,
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)
// special case for io_manipulators.
// function references cannot be given as arguments to lambda operator
// expressions in general. With << and >> the use of manipulators is
// so common, that specializations are provided to make them work.
template<class Arg, class Ret, class ManipArg>
inline const
lambda_functor<
lambda_functor_base<
bitwise_action<leftshift_action>,
tuple<lambda_functor<Arg>, Ret(&)(ManipArg)>
>
>
operator<<(const lambda_functor<Arg>& a, Ret(&b)(ManipArg))
{
return
lambda_functor_base<
bitwise_action<leftshift_action>,
tuple<lambda_functor<Arg>, Ret(&)(ManipArg)>
>
( 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)>
>
>
operator>>(const lambda_functor<Arg>& a, Ret(&b)(ManipArg))
{
return
lambda_functor_base<
bitwise_action<rightshift_action>,
tuple<lambda_functor<Arg>, Ret(&)(ManipArg)>
>
( tuple<lambda_functor<Arg>, Ret(&)(ManipArg)>(a, b) );
}
// (+ and -) take their arguments as const references.
// This has consquences with pointer artihmetic
// E.g int a[]; ... *a = 1 works but not *(a+1) = 1.
// 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"
#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)); \
}
#if defined BOOST_LAMBDA_PTR_ARITHMETIC_E2
#error "Multiple defines of BOOST_LAMBDA_PTR_ARITHMETIC_E2"
#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)); \
}
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>)
// 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)
#undef BOOST_LAMBDA_BE1
#undef BOOST_LAMBDA_BE2
#undef BOOST_LAMBDA_BE3
#undef BOOST_LAMBDA_BE
#undef BOOST_LAMBDA_COMMA_OPERATOR_NAME
#undef BOOST_LAMBDA_PTR_ARITHMETIC_E1
#undef BOOST_LAMBDA_PTR_ARITHMETIC_E2
// ---------------------------------------------------------------------
// unary operators -----------------------------------------------------
// ---------------------------------------------------------------------
#if defined BOOST_LAMBDA_UE
#error "Multiple defines of BOOST_LAMBDA_UE"
#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) ); \
}
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"
#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) ); \
}
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
} // namespace lambda
} // namespace boost
#endif

View File

@@ -0,0 +1,325 @@
// Boost Lambda Library ret.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_RET_HPP
#define BOOST_LAMBDA_RET_HPP
namespace boost {
namespace lambda {
// TODO:
// Add specializations for function references for ret, protect and unlambda
// e.g void foo(); unlambda(foo); fails, as it would add a const qualifier
// for a function type.
// on the other hand unlambda(*foo) does work
// -- ret -------------------------
// the explicit return type template
// TODO: It'd be nice to make ret a nop for other than lambda functors
// but causes an ambiguiyty with gcc (not with KCC), check what is the
// right interpretation.
// // ret for others than lambda functors has no effect
// template <class U, class T>
// inline const T& ret(const T& t) { return t; }
template<class RET, class Arg>
inline const
lambda_functor<
lambda_functor_base<
explicit_return_type_action<RET>,
tuple<lambda_functor<Arg> >
>
>
ret(const lambda_functor<Arg>& a1)
{
return
lambda_functor_base<
explicit_return_type_action<RET>,
tuple<lambda_functor<Arg> >
>
(tuple<lambda_functor<Arg> >(a1));
}
// protect ------------------
// protecting others than lambda functors has no effect
template <class T>
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> >
>
>
protect(const lambda_functor<Arg>& a1)
{
return
lambda_functor_base<
protect_action,
tuple<lambda_functor<Arg> >
>
(tuple<lambda_functor<Arg> >(a1));
}
// -------------------------------------------------------------------
// Hides the lambda functorness of a lambda functor.
// After this, the functor is immune to argument substitution, etc.
// This can be used, e.g. to make it safe to pass lambda functors as
// arguments to functions, which might use them as target functions
// 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;
public:
// This functor defines the result_type typedef.
// The result type must be deducible without knowing the arguments
template <class SigArgs> struct sig {
typedef typename
LambdaFunctor::inherited::
template sig<typename SigArgs::tail_type>::type type;
};
explicit non_lambda_functor(const LambdaFunctor& a) : lf(a) {}
typename LambdaFunctor::nullary_return_type
operator()() const {
return lf.template
call<typename LambdaFunctor::nullary_return_type>
(cnull_type(), cnull_type(), cnull_type(), cnull_type());
}
template<class A>
typename sig<tuple<const non_lambda_functor, 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());
}
template<class A, class B>
typename sig<tuple<const non_lambda_functor, 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());
}
template<class A, class B, class C>
typename sig<tuple<const non_lambda_functor, 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());
}
};
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)
{
return non_lambda_functor<lambda_functor<Arg> >(a);
}
// Due to a language restriction, lambda functors cannot be made to
// accept non-const rvalue arguments. Usually iterators do not return
// 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> >
break_const(const lambda_functor<Arg>& lf)
{
return const_incorrect_lambda_functor<lambda_functor<Arg> >(lf);
}
template <class Arg>
inline const const_parameter_lambda_functor<lambda_functor<Arg> >
const_parameters(const lambda_functor<Arg>& lf)
{
return const_parameter_lambda_functor<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& a1) {
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
#endif

View File

@@ -0,0 +1,282 @@
// return_type_traits.hpp -- Boost Lambda Library ---------------------------
// 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_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 {
using ::boost::type_traits::ice_and;
using ::boost::type_traits::ice_or;
using ::boost::type_traits::ice_not;
// 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
// should never be entered at all, and the use of ret<> does this.
// However, for nullary lambda functors, return type deduction is always
// entered, and there seems to be no way around this.
// (the return type is part of the prototype of the non-template
// operator()(). The prototype is instantiated, even though the body
// is not.)
// So, in the case the return type deduction should fail, it should not
// fail directly, but rather result in a valid but wrong return type,
// causing a compile time error only if the function is really called.
} // end detail
// 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,
ice_and<is_protectable<Act>::value, is_lambda_functor<A>::value>::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;
};
// take care of the unavoidable instantiation for nullary case
template<class Act> struct return_type_1_prot<Act, null_type> {
typedef null_type type;
};
// Unary actions (result from unary operators)
// do not have a default return type.
template<class Act, class A> struct return_type_1 {
typedef typename
detail::return_type_deduction_failure<return_type_1> type;
};
namespace detail {
template <class T>
class protect_conversion {
typedef typename boost::remove_reference<T>::type non_ref_T;
public:
// 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,
ice_and<boost::is_reference<T>::value,
ice_not<boost::is_const<non_ref_T>::value>::value>::value,
detail::identity_mapping<T>,
const_copy_argument<non_ref_T> // handles funtion and array
>::type type; // types correctly
};
} // end detail
template <class Act, class A, class B> struct return_type_2_prot {
// experimental feature
// We may have a lambda functor as a result type of a subexpression
// (if protect) has been used.
// Thus, if one of the parameter types is a lambda functor, the result
// is a lambda functor as well.
// 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
// 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)
// The return type is a subclass of lambda_functor, which has a converting
// copy constructor. It can copy any lambda functor, that has the same
// 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;
typedef typename
detail::IF<
// is_protectable<Act>::value &&
// (is_lambda_functor<A>::value || is_lambda_functor<B>::value),
ice_and<is_protectable<Act>::value,
ice_or<is_lambda_functor<A>::value,
is_lambda_functor<B>::value>::value>::value,
lambda_functor<
lambda_functor_base<
Act,
tuple<typename detail::protect_conversion<A>::type,
typename detail::protect_conversion<B>::type>
>
>,
typename return_type_2<Act, non_ref_A, non_ref_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;
};
// 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;
};
// 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;
};
// 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),
ice_and<is_protectable<other_action<comma_action> >::value, // it is protectable
ice_or<is_lambda_functor<A>::value,
is_lambda_functor<B>::value>::value>::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;
};
// 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;
};
// take care of the unavoidable instantiation for nullary case
template<class Act> struct return_type_N_prot<Act, null_type> {
typedef null_type type;
};
// handle different kind of actions ------------------------
// use the return type given in the bind invocation as bind<Ret>(...)
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<int I, class Args>
struct return_type_N<function_action<I, detail::unspecified>, Args > {
// 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 lambda
} // namespace boost
#endif

View File

@@ -0,0 +1,74 @@
// -- select_functions.hpp -- Boost Lambda Library --------------------------
// 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 http://www.boost.org
#ifndef BOOST_LAMBDA_SELECT_FUNCTIONS_HPP
#define BOOST_LAMBDA_SELECT_FUNCTIONS_HPP
namespace boost {
namespace lambda {
namespace detail {
// select functions -------------------------------
template<class Any, CALL_TEMPLATE_ARGS>
inline Any& select(Any& any, CALL_FORMAL_ARGS) { CALL_USE_ARGS; 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 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);
}
// ------------------------------------------------------------------------
// select 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.
// The first implementation used function templates with an explicitly
// 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 {
// Any == RET
template<class Any, CALL_TEMPLATE_ARGS>
static
inline RET go (Any& any, CALL_FORMAL_ARGS) { CALL_USE_ARGS; 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 Arg, CALL_TEMPLATE_ARGS>
static
inline RET go (lambda_functor<Arg>& op, CALL_FORMAL_ARGS ) {
return op.template call<RET>(CALL_ACTUAL_ARGS);
}
};
} // namespace detail
} // namespace lambda
} // namespace boost
#endif

View File

@@ -0,0 +1,27 @@
// 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_SUPRESS_UNUSED_HPP
#define BOOST_LAMBDA_SUPRESS_UNUSED_HPP
namespace boost {
namespace lambda {
namespace detail {
template<class T>
inline void suppress_unused_variable_warnings(const T&) {}
}
}
}
#endif

File diff suppressed because it is too large Load Diff

462
include/boost/lambda/if.hpp Normal file
View File

@@ -0,0 +1,462 @@
// 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 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

@@ -0,0 +1,34 @@
// -- lambda.hpp -- Boost Lambda Library -----------------------------------
// 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 http://lambda.cs.utu.fi
#ifndef BOOST_LAMBDA_LAMBDA_HPP
#define BOOST_LAMBDA_LAMBDA_HPP
#include "boost/lambda/core.hpp"
#ifdef BOOST_NO_FDECL_TEMPLATES_AS_TEMPLATE_TEMPLATE_PARAMS
#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"
#ifndef BOOST_LAMBDA_FAILS_IN_TEMPLATE_KEYWORD_AFTER_SCOPE_OPER
// sorry, member ptr does not work with gcc2.95
#include "boost/lambda/detail/member_ptr.hpp"
#endif
#endif

View File

@@ -0,0 +1,505 @@
// 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 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

@@ -0,0 +1,119 @@
// -- 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

@@ -0,0 +1,508 @@
// 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

12
index.html Normal file
View File

@@ -0,0 +1,12 @@
<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>

35
test/Jamfile Normal file
View File

@@ -0,0 +1,35 @@
# 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 ;
project
: requirements <toolset>msvc:<asynch-exceptions>on
;
test-suite lambda
: [ run algorithm_test.cpp ]
[ run bind_tests_simple.cpp ]
[ run bind_tests_advanced.cpp ]
[ run bind_tests_simple_f_refs.cpp ]
[ run bll_and_function.cpp ]
[ run cast_test.cpp : : : : lambda_cast_test ]
[ run constructor_tests.cpp ]
[ run control_structures.cpp ]
[ run exception_test.cpp ]
[ run extending_rt_traits.cpp ]
[ run is_instance_of_test.cpp ]
[ run member_pointer_test.cpp ]
[ run operator_tests_simple.cpp ]
[ run phoenix_control_structures.cpp ]
[ run switch_construct.cpp ]
[ run result_of_tests.cpp ]
[ run ret_test.cpp ]
;

89
test/Makefile Normal file
View File

@@ -0,0 +1,89 @@
BOOST = ../../..
CXX = g++
EXTRAFLAGS = -pedantic -Wno-long-long -Wno-long-double -ftemplate-depth-50
LIBS = -lstdc++
#CXX = KCC
#EXTRAFLAGS = --strict --display_error_number --diag_suppress 450 --max_pending_instantiations 50
#LIBS =
INCLUDES = -I$(BOOST)
CXXFLAGS = $(INCLUDES) $(EXTRAFLAGS)
LIBFLAGS = $(LIBS)
AR = ar
.SUFFIXES: .cpp .o
SOURCES = \
is_instance_of_test.cpp \
operator_tests_simple.cpp \
member_pointer_test.cpp \
control_structures.cpp \
switch_construct.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 \
exception_test.cpp \
# Create lists of object files from the source file lists.
OBJECTS = ${SOURCES:.cpp=.o}
TARGETS = ${SOURCES:.cpp=.exe}
all: $(TARGETS)
%.exe: %.o
$(CXX) $(LIBFLAGS) $(CXXFLAGS) -o $@ $<
%.o: %.cpp
$(CXX) $(CXXFLAGS) -o $@ -c $<
%.dep: %.cpp
set -e; $(CXX) -M $(INCLUDES) -c $< \
| sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
[ -s $@ ] || rm -f $@
DEP_FILES = $(SOURCES:.cpp=.dep)
include $(DEP_FILES)
clean:
/bin/rm -rf $(TARGETS) $(OBJECTS) $(DEP_FILES)
run:
./is_instance_of_test.exe
./member_pointer_test.exe
./operator_tests_simple.exe
./control_structures.exe
./switch_construct.exe
./extending_rt_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
./exception_test.exe

View File

@@ -0,0 +1,6 @@
gcc 2.96
cannot compile
exception_test.cpp (internal compiler error)

60
test/algorithm_test.cpp Normal file
View File

@@ -0,0 +1,60 @@
// 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/test/minimal.hpp> // see "Header Implementation Option"
#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 test_main(int, char *[]) {
test_foreach();
return 0;
}

View File

@@ -0,0 +1,420 @@
// 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
// -----------------------------------------------------------------------
#include <boost/test/minimal.hpp> // see "Header Implementation Option"
#include "boost/lambda/lambda.hpp"
#include "boost/lambda/bind.hpp"
#include "boost/any.hpp"
#include "boost/type_traits/is_reference.hpp"
#include "boost/mpl/assert.hpp"
#include "boost/mpl/if.hpp"
#include <iostream>
#include <functional>
#include <algorithm>
using namespace boost::lambda;
namespace bl = boost::lambda;
int sum_0() { return 0; }
int sum_1(int a) { return a; }
int sum_2(int a, int b) { return a+b; }
int product_2(int a, int b) { return a*b; }
// unary function that returns a pointer to a binary function
typedef int (*fptr_type)(int, int);
fptr_type sum_or_product(bool x) {
return x ? sum_2 : product_2;
}
// a nullary functor that returns a pointer to a unary function that
// 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; }
};
void test_nested_binds()
{
int j = 2; int k = 3;
// bind calls can be nested (the target function can be a lambda functor)
// The interpretation is, that the innermost lambda functor returns something
// that is bindable (another lambda functor, function pointer ...)
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);
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);
which_one wo;
BOOST_CHECK(bind(bind(bind(wo), _1), _2, _3)(condition, j, k)==6);
return;
}
// unlambda -------------------------------------------------
// Sometimes it may be necessary to prevent the argument substitution of
// taking place. For example, we may end up with a nested bind expression
// inadvertently when using the target function is received as a parameter
template<class F>
int call_with_100(const F& f) {
// bind(f, _1)(make_const(100));
// 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));
// for other functors than lambda functors, unlambda has no effect
// (except for making them const)
}
template<class F>
int call_with_101(const F& f) {
return bind(unlambda(f), _1)(make_const(101));
}
void test_unlambda() {
int i = 1;
BOOST_CHECK(unlambda(_1 + _2)(i, i) == 2);
BOOST_CHECK(unlambda(++var(i))() == 2);
BOOST_CHECK(call_with_100(_1 + 1) == 101);
BOOST_CHECK(call_with_101(_1 + 1) == 102);
BOOST_CHECK(call_with_100(bl::bind(std_functor(std::bind1st(std::plus<int>(), 1)), _1)) == 101);
// 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);
}
// protect ------------------------------------------------------------
// protect protects a lambda functor from argument substitution.
// protect is useful e.g. with nested stl algorithm calls.
namespace ll {
struct for_each {
// 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.
// 1. 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
// The head type is the function object type itself
// cv-qualified (so it is possilbe to provide different return types
// for differently cv-qualified operator()'s.
// The tail type is the list of the types of the actual arguments the
// function was called with.
// So sig should contain a typedef type, which defines a mapping from
// the operator() arguments to its return type.
// Note, that it is possible to provide different sigs for the same functor
// 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>
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()(const A& a, const B& b, const C& c) const
{ return std::for_each(a, b, c);}
};
} // end of ll namespace
void test_protect()
{
int i = 0;
int b[3][5];
int* a[3];
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))));
// 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)
// )
// );
int sum = 0;
std::for_each(a, a+3,
bind(ll::for_each(), _1, _1 + 5,
protect(sum += _1))
);
BOOST_CHECK(sum == (1+15)*15/2);
sum = 0;
std::for_each(a, a+3,
bind(ll::for_each(), _1, _1 + 5,
sum += 1 + protect(_1)) // add element count
);
BOOST_CHECK(sum == (1+15)*15/2 + 15);
(1 + protect(_1))(sum);
int k = 0;
((k += constant(1)) += protect(constant(2)))();
BOOST_CHECK(k==1);
k = 0;
((k += constant(1)) += protect(constant(2)))()();
BOOST_CHECK(k==3);
// note, the following doesn't work:
// ((var(k) = constant(1)) = protect(constant(2)))();
// (var(k) = constant(1))() returns int& and thus the
// second assignment fails.
// We should have something like:
// bind(var, var(k) = constant(1)) = protect(constant(2)))();
// But currently var is not bindable.
// The same goes with ret. A bindable ret could be handy sometimes as well
// (protect(std::cout << _1), std::cout << _1)(i)(j); does not work
// because the comma operator tries to store the result of the evaluation
// of std::cout << _1 as a copy (and you can't copy std::ostream).
// 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);
// added one dummy value to make the argument to comma an int
// instead of ostream&
// 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
}
void test_lambda_functors_as_arguments_to_lambda_functors() {
// lambda functor is a function object, and can therefore be used
// as an argument to another lambda functors function call object.
// 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));
// 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);
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
// 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
// explicitly.
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);
//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);
bind(_1,1.0)(_1+_1);
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);
// Or use const_parameters:
BOOST_CHECK(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.
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
break_const(_1 += _2)(i, 2); // ok
BOOST_CHECK(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 test_main(int, char *[]) {
test_nested_binds();
test_unlambda();
test_protect();
test_lambda_functors_as_arguments_to_lambda_functors();
test_const_parameters();
test_rvalue_arguments();
test_break_const();
test_sig();
test_abstract();
return 0;
}

187
test/bind_tests_simple.cpp Normal file
View File

@@ -0,0 +1,187 @@
// 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/test/minimal.hpp> // see "Header Implementation Option"
#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; }
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()
{
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);
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);
// 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 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);
// 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 0;
}

View File

@@ -0,0 +1,148 @@
// 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/test/minimal.hpp> // see "Header Implementation Option"
#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 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);
// 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 0;
}

68
test/bll_and_function.cpp Normal file
View File

@@ -0,0 +1,68 @@
// 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/test/minimal.hpp> // see "Header Implementation Option"
#include "boost/lambda/lambda.hpp"
#include "boost/function.hpp"
#include <vector>
#include <map>
#include <set>
#include <string>
using namespace boost::lambda;
using namespace std;
void test_function() {
boost::function<int (int, int)> f;
f = _1 + _2;
BOOST_CHECK(f(1, 2)== 3);
int i=1; int j=2;
boost::function<int& (int&, int)> g = _1 += _2;
g(i, j);
BOOST_CHECK(i==3);
int* sum = new int();
*sum = 0;
boost::function<int& (int)> counter = *sum += _1;
counter(5); // ok, sum* = 5;
BOOST_CHECK(*sum == 5);
delete sum;
// The next statement would lead to a dangling reference
// counter(3); // error, *sum does not exist anymore
}
int test_main(int, char *[]) {
test_function();
return 0;
}

107
test/cast_test.cpp Normal file
View File

@@ -0,0 +1,107 @@
// 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
// -----------------------------------------------------------------------
#include <boost/test/minimal.hpp> // see "Header Implementation Option"
#include "boost/lambda/lambda.hpp"
#include "boost/lambda/casts.hpp"
#include <string>
using namespace boost::lambda;
using namespace std;
class base {
int x;
public:
virtual std::string class_name() const { return "const base"; }
virtual std::string class_name() { return "base"; }
virtual ~base() {}
};
class derived : public base {
int y[100];
public:
virtual std::string class_name() const { return "const derived"; }
virtual std::string class_name() { return "derived"; }
};
void do_test() {
derived *p_derived = new derived;
base *p_base = new base;
base *b = 0;
derived *d = 0;
(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");
(var(b) = ll_dynamic_cast<derived *>(b))();
BOOST_CHECK(b != 0);
BOOST_CHECK(b->class_name() == "derived");
(var(d) = ll_dynamic_cast<derived *>(p_base))();
BOOST_CHECK(d == 0);
const derived* p_const_derived = p_derived;
BOOST_CHECK(p_const_derived->class_name() == "const derived");
(var(d) = ll_const_cast<derived *>(p_const_derived))();
BOOST_CHECK(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);
// typeid
BOOST_CHECK(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));
int an_array[100];
BOOST_CHECK(ll_sizeof(_1)(an_array) == 100 * sizeof(int));
delete p_derived;
delete p_base;
}
int test_main(int, char *[]) {
do_test();
return 0;
}

265
test/constructor_tests.cpp Normal file
View File

@@ -0,0 +1,265 @@
// 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
// -----------------------------------------------------------------------
#include <boost/test/minimal.hpp> // see "Header Implementation Option"
#include "boost/lambda/lambda.hpp"
#include "boost/lambda/bind.hpp"
#include "boost/lambda/construct.hpp"
#include <iostream>
#include <algorithm>
#include <vector>
#ifdef BOOST_MSVC
#pragma warning(disable:4512)
#endif
using namespace boost::lambda;
namespace bl = boost::lambda;
template<class T>
bool check_tuple(int n, const T& t)
{
return (t.get_head() == n) && check_tuple(n+1, t.get_tail());
}
template <>
bool check_tuple(int /*n*/, const null_type& ) { return true; }
void constructor_all_lengths()
{
bool ok;
ok = check_tuple(
1,
bind(constructor<tuple<int> >(),
1)()
);
BOOST_CHECK(ok);
ok = check_tuple(
1,
bind(constructor<tuple<int, int> >(),
1, 2)()
);
BOOST_CHECK(ok);
ok = check_tuple(
1,
bind(constructor<tuple<int, int, int> >(),
1, 2, 3)()
);
BOOST_CHECK(ok);
ok = check_tuple(
1,
bind(constructor<tuple<int, int, int, int> >(),
1, 2, 3, 4)()
);
BOOST_CHECK(ok);
ok = check_tuple(
1,
bind(constructor<tuple<int, int, int, int, int> >(),
1, 2, 3, 4, 5)()
);
BOOST_CHECK(ok);
ok = check_tuple(
1,
bind(constructor<tuple<int, int, int, int, int, int> >(),
1, 2, 3, 4, 5, 6)()
);
BOOST_CHECK(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);
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);
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);
}
void new_ptr_all_lengths()
{
bool ok;
ok = check_tuple(
1,
*(bind(new_ptr<tuple<int> >(),
1))()
);
BOOST_CHECK(ok);
ok = check_tuple(
1,
*(bind(new_ptr<tuple<int, int> >(),
1, 2))()
);
BOOST_CHECK(ok);
ok = check_tuple(
1,
*(bind(new_ptr<tuple<int, int, int> >(),
1, 2, 3))()
);
BOOST_CHECK(ok);
ok = check_tuple(
1,
*(bind(new_ptr<tuple<int, int, int, int> >(),
1, 2, 3, 4))()
);
BOOST_CHECK(ok);
ok = check_tuple(
1,
*(bind(new_ptr<tuple<int, int, int, int, int> >(),
1, 2, 3, 4, 5))()
);
BOOST_CHECK(ok);
ok = check_tuple(
1,
*(bind(new_ptr<tuple<int, int, int, int, int, int> >(),
1, 2, 3, 4, 5, 6))()
);
BOOST_CHECK(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);
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);
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);
}
class is_destructor_called {
bool& b;
public:
is_destructor_called(bool& bb) : b(bb) { b = false; }
~is_destructor_called() { b = true; }
};
void test_destructor ()
{
char space[sizeof(is_destructor_called)];
bool flag = false;
is_destructor_called* idc = new(space) is_destructor_called(flag);
BOOST_CHECK(flag == false);
bind(destructor(), _1)(idc);
BOOST_CHECK(flag == true);
idc = new(space) is_destructor_called(flag);
BOOST_CHECK(flag == false);
bind(destructor(), _1)(*idc);
BOOST_CHECK(flag == true);
}
class count_deletes {
public:
static int count;
~count_deletes() { ++count; }
};
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));
int count_errors = 0;
std::for_each(i, i+10, (*_1 == 2) || ++var(count_errors));
BOOST_CHECK(count_errors == 0);
count_deletes* ct[10];
std::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);
}
void test_array_new_and_delete()
{
count_deletes* c;
(_1 = bind(new_array<count_deletes>(), 5))(c);
count_deletes::count = 0;
bind(delete_array(), _1)(c);
BOOST_CHECK(count_deletes::count == 5);
}
void delayed_construction()
{
std::vector<int> x(3);
std::vector<int> y(3);
std::fill(x.begin(), x.end(), 0);
std::fill(y.begin(), y.end(), 1);
std::vector<std::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) );
}
int test_main(int, char *[]) {
constructor_all_lengths();
new_ptr_all_lengths();
delayed_construction();
test_destructor();
test_news_and_deletes();
test_array_new_and_delete();
return 0;
}

123
test/control_structures.cpp Normal file
View File

@@ -0,0 +1,123 @@
// -- 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/test/minimal.hpp> // see "Header Implementation Option"
#include "boost/lambda/lambda.hpp"
#include "boost/lambda/if.hpp"
#include "boost/lambda/loops.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;
// 2 container for_each
template <class InputIter1, class InputIter2, class Function>
Function for_each(InputIter1 first, InputIter1 last,
InputIter2 first2, Function f) {
for ( ; first != last; ++first, ++first2)
f(*first, *first2);
return f;
}
void simple_loops() {
// for loops ---------------------------------------------------------
int i;
int arithmetic_series = 0;
for_loop(_1 = 0, _1 < 10, _1++, arithmetic_series += _1)(i);
BOOST_CHECK(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);
// 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);
int count;
count = 0; i = 0;
while_loop(_1++ < 10, ++boost::lambda::var(count))(i);
BOOST_CHECK(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);
a = 0;
do_while_loop(constant(false), _1++)(a);
BOOST_CHECK(a == 1);
// no body cases
a = 40; b = 30;
while_loop(--_1 > _2)(a, b);
BOOST_CHECK(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);
}
void simple_ifs () {
int value = 42;
if_then(_1 < 0, _1 = 0)(value);
BOOST_CHECK(value == 42);
value = -42;
if_then(_1 < 0, _1 = -_1)(value);
BOOST_CHECK(value == 42);
int min;
if_then_else(_1 < _2, boost::lambda::var(min) = _1, boost::lambda::var(min) = _2)
(make_const(1), make_const(2));
BOOST_CHECK(min == 1);
if_then_else(_1 < _2, boost::lambda::var(min) = _1, boost::lambda::var(min) = _2)
(make_const(5), make_const(3));
BOOST_CHECK(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));
}
int test_main(int, char *[])
{
simple_loops();
simple_ifs();
return 0;
}

621
test/exception_test.cpp Normal file
View File

@@ -0,0 +1,621 @@
// -- 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/test/minimal.hpp> // see "Header Implementation Option"
#include "boost/lambda/lambda.hpp"
#include "boost/lambda/exceptions.hpp"
#include "boost/lambda/bind.hpp"
#include<iostream>
#include<algorithm>
#include <cstdlib>
#include <iostream>
using namespace boost::lambda;
using namespace std;
// to prevent unused variables warnings
template <class T> void dummy(const T&) {}
void erroneous_exception_related_lambda_expressions() {
int i = 0;
dummy(i);
// Uncommenting any of the below code lines should result in a compile
// time error
// this should fail (a rethrow binder outside of catch
// rethrow()();
// 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);
// 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));
}
class A1 {};
class A2 {};
class A3 {};
class A4 {};
class A5 {};
class A6 {};
class A7 {};
class A8 {};
class A9 {};
void throw_AX(int j) {
int i = j;
switch(i) {
case 1: throw A1();
case 2: throw A2();
case 3: throw A3();
case 4: throw A4();
case 5: throw A5();
case 6: throw A6();
case 7: throw A7();
case 8: throw A8();
case 9: throw A9();
}
}
void test_different_number_of_catch_blocks() {
int ecount;
// no catch(...) cases
ecount = 0;
for(int i=1; i<=1; i++)
{
try_catch(
bind(throw_AX, _1),
catch_exception<A1>(
var(ecount)++
)
)(i);
}
BOOST_CHECK(ecount == 1);
ecount = 0;
for(int i=1; i<=2; i++)
{
try_catch(
bind(throw_AX, _1),
catch_exception<A1>(
var(ecount)++
),
catch_exception<A2>(
var(ecount)++
)
)(i);
}
BOOST_CHECK(ecount == 2);
ecount = 0;
for(int i=1; i<=3; i++)
{
try_catch(
bind(throw_AX, _1),
catch_exception<A1>(
var(ecount)++
),
catch_exception<A2>(
var(ecount)++
),
catch_exception<A3>(
var(ecount)++
)
)(i);
}
BOOST_CHECK(ecount == 3);
ecount = 0;
for(int i=1; i<=4; i++)
{
try_catch(
bind(throw_AX, _1),
catch_exception<A1>(
var(ecount)++
),
catch_exception<A2>(
var(ecount)++
),
catch_exception<A3>(
var(ecount)++
),
catch_exception<A4>(
var(ecount)++
)
)(i);
}
BOOST_CHECK(ecount == 4);
ecount = 0;
for(int i=1; i<=5; i++)
{
try_catch(
bind(throw_AX, _1),
catch_exception<A1>(
var(ecount)++
),
catch_exception<A2>(
var(ecount)++
),
catch_exception<A3>(
var(ecount)++
),
catch_exception<A4>(
var(ecount)++
),
catch_exception<A5>(
var(ecount)++
)
)(i);
}
BOOST_CHECK(ecount == 5);
ecount = 0;
for(int i=1; i<=6; i++)
{
try_catch(
bind(throw_AX, _1),
catch_exception<A1>(
var(ecount)++
),
catch_exception<A2>(
var(ecount)++
),
catch_exception<A3>(
var(ecount)++
),
catch_exception<A4>(
var(ecount)++
),
catch_exception<A5>(
var(ecount)++
),
catch_exception<A6>(
var(ecount)++
)
)(i);
}
BOOST_CHECK(ecount == 6);
ecount = 0;
for(int i=1; i<=7; i++)
{
try_catch(
bind(throw_AX, _1),
catch_exception<A1>(
var(ecount)++
),
catch_exception<A2>(
var(ecount)++
),
catch_exception<A3>(
var(ecount)++
),
catch_exception<A4>(
var(ecount)++
),
catch_exception<A5>(
var(ecount)++
),
catch_exception<A6>(
var(ecount)++
),
catch_exception<A7>(
var(ecount)++
)
)(i);
}
BOOST_CHECK(ecount == 7);
ecount = 0;
for(int i=1; i<=8; i++)
{
try_catch(
bind(throw_AX, _1),
catch_exception<A1>(
var(ecount)++
),
catch_exception<A2>(
var(ecount)++
),
catch_exception<A3>(
var(ecount)++
),
catch_exception<A4>(
var(ecount)++
),
catch_exception<A5>(
var(ecount)++
),
catch_exception<A6>(
var(ecount)++
),
catch_exception<A7>(
var(ecount)++
),
catch_exception<A8>(
var(ecount)++
)
)(i);
}
BOOST_CHECK(ecount == 8);
ecount = 0;
for(int i=1; i<=9; i++)
{
try_catch(
bind(throw_AX, _1),
catch_exception<A1>(
var(ecount)++
),
catch_exception<A2>(
var(ecount)++
),
catch_exception<A3>(
var(ecount)++
),
catch_exception<A4>(
var(ecount)++
),
catch_exception<A5>(
var(ecount)++
),
catch_exception<A6>(
var(ecount)++
),
catch_exception<A7>(
var(ecount)++
),
catch_exception<A8>(
var(ecount)++
),
catch_exception<A9>(
var(ecount)++
)
)(i);
}
BOOST_CHECK(ecount == 9);
// with catch(...) blocks
ecount = 0;
for(int i=1; i<=1; i++)
{
try_catch(
bind(throw_AX, _1),
catch_all(
var(ecount)++
)
)(i);
}
BOOST_CHECK(ecount == 1);
ecount = 0;
for(int i=1; i<=2; i++)
{
try_catch(
bind(throw_AX, _1),
catch_exception<A1>(
var(ecount)++
),
catch_all(
var(ecount)++
)
)(i);
}
BOOST_CHECK(ecount == 2);
ecount = 0;
for(int i=1; i<=3; i++)
{
try_catch(
bind(throw_AX, _1),
catch_exception<A1>(
var(ecount)++
),
catch_exception<A2>(
var(ecount)++
),
catch_all(
var(ecount)++
)
)(i);
}
BOOST_CHECK(ecount == 3);
ecount = 0;
for(int i=1; i<=4; i++)
{
try_catch(
bind(throw_AX, _1),
catch_exception<A1>(
var(ecount)++
),
catch_exception<A2>(
var(ecount)++
),
catch_exception<A3>(
var(ecount)++
),
catch_all(
var(ecount)++
)
)(i);
}
BOOST_CHECK(ecount == 4);
ecount = 0;
for(int i=1; i<=5; i++)
{
try_catch(
bind(throw_AX, _1),
catch_exception<A1>(
var(ecount)++
),
catch_exception<A2>(
var(ecount)++
),
catch_exception<A3>(
var(ecount)++
),
catch_exception<A4>(
var(ecount)++
),
catch_all(
var(ecount)++
)
)(i);
}
BOOST_CHECK(ecount == 5);
ecount = 0;
for(int i=1; i<=6; i++)
{
try_catch(
bind(throw_AX, _1),
catch_exception<A1>(
var(ecount)++
),
catch_exception<A2>(
var(ecount)++
),
catch_exception<A3>(
var(ecount)++
),
catch_exception<A4>(
var(ecount)++
),
catch_exception<A5>(
var(ecount)++
),
catch_all(
var(ecount)++
)
)(i);
}
BOOST_CHECK(ecount == 6);
ecount = 0;
for(int i=1; i<=7; i++)
{
try_catch(
bind(throw_AX, _1),
catch_exception<A1>(
var(ecount)++
),
catch_exception<A2>(
var(ecount)++
),
catch_exception<A3>(
var(ecount)++
),
catch_exception<A4>(
var(ecount)++
),
catch_exception<A5>(
var(ecount)++
),
catch_exception<A6>(
var(ecount)++
),
catch_all(
var(ecount)++
)
)(i);
}
BOOST_CHECK(ecount == 7);
ecount = 0;
for(int i=1; i<=8; i++)
{
try_catch(
bind(throw_AX, _1),
catch_exception<A1>(
var(ecount)++
),
catch_exception<A2>(
var(ecount)++
),
catch_exception<A3>(
var(ecount)++
),
catch_exception<A4>(
var(ecount)++
),
catch_exception<A5>(
var(ecount)++
),
catch_exception<A6>(
var(ecount)++
),
catch_exception<A7>(
var(ecount)++
),
catch_all(
var(ecount)++
)
)(i);
}
BOOST_CHECK(ecount == 8);
ecount = 0;
for(int i=1; i<=9; i++)
{
try_catch(
bind(throw_AX, _1),
catch_exception<A1>(
var(ecount)++
),
catch_exception<A2>(
var(ecount)++
),
catch_exception<A3>(
var(ecount)++
),
catch_exception<A4>(
var(ecount)++
),
catch_exception<A5>(
var(ecount)++
),
catch_exception<A6>(
var(ecount)++
),
catch_exception<A7>(
var(ecount)++
),
catch_exception<A8>(
var(ecount)++
),
catch_all(
var(ecount)++
)
)(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));
}
void return_type_matching() {
// Rules for return types of the lambda functors in try and catch parts:
// 1. The try part dictates the return type of the whole
// try_catch lambda functor
// 2. If return type of try part is void, catch parts can return anything,
// but the return types are ignored
// 3. If the return type of the try part is A, then each catch return type
// must be implicitly convertible to A, or then it must throw for sure
int i = 1;
BOOST_CHECK(
try_catch(
_1 + 1,
catch_exception<int>((&_1, rethrow())), // no match, but ok since throws
catch_exception<char>(_e) // ok, char convertible to int
)(i)
== 2
);
// note that while e.g. char is convertible to int, it is not convertible
// to int&, (some lambda functors return references)
// try_catch(
// _1 += 1,
// 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
)(i);
BOOST_CHECK(i == 2);
try_catch(
(_1 += 1, throw_exception('a')),
catch_exception<char>(_e) // since try throws, it is void,
// so catch can return anything
)(i);
BOOST_CHECK(i == 3);
char a = 'a';
try_catch(
try_catch(
throw_exception(1),
catch_exception<int>(throw_exception('b'))
),
catch_exception<char>( _1 = _e )
)(a);
BOOST_CHECK(a == 'b');
}
int test_main(int, char *[]) {
try
{
test_different_number_of_catch_blocks();
return_type_matching();
test_empty_catch_blocks();
}
catch (int)
{
BOOST_CHECK(false);
}
catch(...)
{
BOOST_CHECK(false);
}
return EXIT_SUCCESS;
}

View File

@@ -0,0 +1,394 @@
// 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
// -----------------------------------------------------------------------
#include <boost/test/minimal.hpp> // see "Header Implementation Option"
#include "boost/lambda/bind.hpp"
#include "boost/lambda/lambda.hpp"
#include "boost/lambda/detail/suppress_unused.hpp"
#include <iostream>
#include <functional>
#include <algorithm>
using boost::lambda::detail::suppress_unused_variable_warnings;
class A {};
class B {};
using namespace boost::lambda;
B operator--(const A&, int) { return B(); }
B operator--(A&) { return B(); }
B operator++(const A&, int) { return B(); }
B operator++(A&) { return B(); }
B operator-(const A&) { return B(); }
B operator+(const A&) { return B(); }
B operator!(const A&) { return B(); }
B operator&(const A&) { return B(); }
B operator*(const A&) { return B(); }
namespace boost {
namespace lambda {
// unary + and -
template<class Act>
struct plain_return_type_1<unary_arithmetic_action<Act>, A > {
typedef B type;
};
// post incr/decr
template<class Act>
struct plain_return_type_1<post_increment_decrement_action<Act>, A > {
typedef B type;
};
// pre incr/decr
template<class Act>
struct plain_return_type_1<pre_increment_decrement_action<Act>, A > {
typedef B type;
};
// !
template<>
struct plain_return_type_1<logical_action<not_action>, A> {
typedef B type;
};
// &
template<>
struct plain_return_type_1<other_action<addressof_action>, A> {
typedef B type;
};
// *
template<>
struct plain_return_type_1<other_action<contentsof_action>, A> {
typedef B type;
};
} // lambda
} // boost
void ok(B /*b*/) {}
void test_unary_operators()
{
A a; int i = 1;
ok((++_1)(a));
ok((--_1)(a));
ok((_1++)(a));
ok((_1--)(a));
ok((+_1)(a));
ok((-_1)(a));
ok((!_1)(a));
ok((&_1)(a));
ok((*_1)(a));
BOOST_CHECK((*_1)(make_const(&i)) == 1);
}
class X {};
class Y {};
class Z {};
Z operator+(const X&, const Y&) { return Z(); }
Z operator-(const X&, const Y&) { return Z(); }
X operator*(const X&, const Y&) { return X(); }
Z operator/(const X&, const Y&) { return Z(); }
Z operator%(const X&, const Y&) { return Z(); }
class XX {};
class YY {};
class ZZ {};
class VV {};
// it is possible to support differently cv-qualified versions
YY operator*(XX&, YY&) { return YY(); }
ZZ operator*(const XX&, const YY&) { return ZZ(); }
XX operator*(volatile XX&, volatile YY&) { return XX(); }
VV operator*(const volatile XX&, const volatile YY&) { return VV(); }
// the traits can be more complex:
template <class T>
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*/)
{
typedef typename
return_type_2<arithmetic_action<plus_action>, A&, B&>::type res_type;
return my_vector<res_type>();
}
// bitwise ops:
X operator<<(const X&, const Y&) { return X(); }
Z operator>>(const X&, const Y&) { return Z(); }
Z operator&(const X&, const Y&) { return Z(); }
Z operator|(const X&, const Y&) { return Z(); }
Z operator^(const X&, const Y&) { return Z(); }
// comparison ops:
X operator<(const X&, const Y&) { return X(); }
Z operator>(const X&, const Y&) { return Z(); }
Z operator<=(const X&, const Y&) { return Z(); }
Z operator>=(const X&, const Y&) { return Z(); }
Z operator==(const X&, const Y&) { return Z(); }
Z operator!=(const X&, const Y&) { return Z(); }
// logical
X operator&&(const X&, const Y&) { return X(); }
Z operator||(const X&, const Y&) { return Z(); }
// arithh assignment
Z operator+=( X&, const Y&) { return Z(); }
Z operator-=( X&, const Y&) { return Z(); }
Y operator*=( X&, const Y&) { return Y(); }
Z operator/=( X&, const Y&) { return Z(); }
Z operator%=( X&, const Y&) { return Z(); }
// bitwise assignment
Z operator<<=( X&, const Y&) { return Z(); }
Z operator>>=( X&, const Y&) { return Z(); }
Y operator&=( X&, const Y&) { return Y(); }
Z operator|=( X&, const Y&) { return Z(); }
Z operator^=( X&, const Y&) { return Z(); }
// assignment
class Assign {
public:
void operator=(const Assign& /*a*/) {}
X operator[](const int& /*i*/) { return X(); }
};
namespace boost {
namespace lambda {
// you can do action groups
template<class Act>
struct plain_return_type_2<arithmetic_action<Act>, X, Y> {
typedef Z type;
};
// or specialize the exact action
template<>
struct plain_return_type_2<arithmetic_action<multiply_action>, X, Y> {
typedef X type;
};
// 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> {
typedef YY type;
};
template<>
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> {
typedef XX type;
};
template<>
struct return_type_2<arithmetic_action<multiply_action>, volatile const XX, const volatile YY> {
typedef VV type;
};
// the mapping can be more complex:
template<class A, class B>
struct plain_return_type_2<arithmetic_action<plus_action>, my_vector<A>, my_vector<B> > {
typedef typename
return_type_2<arithmetic_action<plus_action>, A&, B&>::type res_type;
typedef my_vector<res_type> type;
};
// bitwise binary:
// you can do action groups
template<class Act>
struct plain_return_type_2<bitwise_action<Act>, X, Y> {
typedef Z type;
};
// or specialize the exact action
template<>
struct plain_return_type_2<bitwise_action<leftshift_action>, X, Y> {
typedef X type;
};
// comparison binary:
// you can do action groups
template<class Act>
struct plain_return_type_2<relational_action<Act>, X, Y> {
typedef Z type;
};
// or specialize the exact action
template<>
struct plain_return_type_2<relational_action<less_action>, X, Y> {
typedef X type;
};
// logical binary:
// you can do action groups
template<class Act>
struct plain_return_type_2<logical_action<Act>, X, Y> {
typedef Z type;
};
// or specialize the exact action
template<>
struct plain_return_type_2<logical_action<and_action>, X, Y> {
typedef X type;
};
// arithmetic assignment :
// you can do action groups
template<class Act>
struct plain_return_type_2<arithmetic_assignment_action<Act>, X, Y> {
typedef Z type;
};
// or specialize the exact action
template<>
struct plain_return_type_2<arithmetic_assignment_action<multiply_action>, X, Y> {
typedef Y type;
};
// arithmetic assignment :
// you can do action groups
template<class Act>
struct plain_return_type_2<bitwise_assignment_action<Act>, X, Y> {
typedef Z type;
};
// or specialize the exact action
template<>
struct plain_return_type_2<bitwise_assignment_action<and_action>, X, Y> {
typedef Y type;
};
// assignment
template<>
struct plain_return_type_2<other_action<assignment_action>, Assign, Assign> {
typedef void type;
};
// subscript
template<>
struct plain_return_type_2<other_action<subscript_action>, Assign, int> {
typedef X type;
};
} // end lambda
} // end boost
void test_binary_operators() {
X x; Y y;
(_1 + _2)(x, y);
(_1 - _2)(x, y);
(_1 * _2)(x, y);
(_1 / _2)(x, y);
(_1 % _2)(x, y);
// make a distinction between differently cv-qualified operators
XX xx; YY yy;
const XX& cxx = xx;
const YY& cyy = yy;
volatile XX& vxx = xx;
volatile YY& vyy = yy;
const volatile XX& cvxx = xx;
const volatile YY& cvyy = yy;
ZZ dummy1 = (_1 * _2)(cxx, cyy);
YY dummy2 = (_1 * _2)(xx, yy);
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);
(_1 >> _2)(x, y);
(_1 | _2)(x, y);
(_1 & _2)(x, y);
(_1 ^ _2)(x, y);
// comparison
(_1 < _2)(x, y);
(_1 > _2)(x, y);
(_1 <= _2)(x, y);
(_1 >= _2)(x, y);
(_1 == _2)(x, y);
(_1 != _2)(x, y);
// logical
(_1 || _2)(x, y);
(_1 && _2)(x, y);
// arithmetic assignment
(_1 += _2)(x, y);
(_1 -= _2)(x, y);
(_1 *= _2)(x, y);
(_1 /= _2)(x, y);
(_1 %= _2)(x, y);
// bitwise assignment
(_1 <<= _2)(x, y);
(_1 >>= _2)(x, y);
(_1 |= _2)(x, y);
(_1 &= _2)(x, y);
(_1 ^= _2)(x, y);
}
int test_main(int, char *[]) {
test_unary_operators();
test_binary_operators();
return 0;
}

View File

@@ -0,0 +1,79 @@
// 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
// -----------------------------------------------------------------------
#include <boost/test/minimal.hpp> // see "Header Implementation Option"
#include "boost/lambda/detail/is_instance_of.hpp"
#include <iostream>
template <class T1> struct A1 {};
template <class T1, class T2> struct A2 {};
template <class T1, class T2, class T3> struct A3 {};
template <class T1, class T2, class T3, class T4> struct A4 {};
class B1 : public A1<int> {};
class B2 : public A2<int,int> {};
class B3 : public A3<int,int,int> {};
class B4 : public A4<int,int,int,int> {};
// classes that are convertible to classes that derive from A instances
// This is not enough to make the test succeed
class C1 { public: operator A1<int>() { return A1<int>(); } };
class C2 { public: operator B2() { return B2(); } };
class C3 { public: operator B3() { return B3(); } };
class C4 { public: operator B4() { return B4(); } };
// test that the result is really a constant
// (in an alternative implementation, gcc 3.0.2. claimed that it was
// a non-constant)
template <bool b> class X {};
// this should compile
X<boost::lambda::is_instance_of_2<int, A2>::value> x;
int test_main(int, char *[]) {
using boost::lambda::is_instance_of_1;
using boost::lambda::is_instance_of_2;
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_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_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_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));
return 0;
}

30
test/istreambuf_test.cpp Normal file
View File

@@ -0,0 +1,30 @@
// 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/detail/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

@@ -0,0 +1,192 @@
// 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
// -----------------------------------------------------------------------
#include <boost/test/minimal.hpp> // see "Header Implementation Option"
#include "boost/lambda/lambda.hpp"
#include "boost/lambda/bind.hpp"
#include <string>
using namespace boost::lambda;
using namespace std;
struct my_struct {
my_struct(int x) : mem(x) {};
int mem;
int fooc() const { return mem; }
int foo() { return mem; }
int foo1c(int y) const { return y + mem; }
int foo1(int y) { return y + mem; }
int foo2c(int y, int x) const { return y + x + mem; }
int foo2(int y, int x) { return y + x + mem; }
int foo3c(int y, int x, int z) const { return y + x + z + mem; }
int foo3(int y, int x, int z ){ return y + x + z + mem; }
int foo4c(int a1, int a2, int a3, int a4) const { return a1+a2+a3+a4+mem; }
int foo4(int a1, int a2, int a3, int a4){ return a1+a2+a3+a4+mem; }
int foo3default(int y = 1, int x = 2, int z = 3) { return y + x + z + mem; }
};
my_struct x(3);
void pointer_to_data_member_tests() {
// int i = 0;
my_struct *y = &x;
BOOST_CHECK((_1 ->* &my_struct::mem)(y) == 3);
(_1 ->* &my_struct::mem)(y) = 4;
BOOST_CHECK(x.mem == 4);
((_1 ->* &my_struct::mem) = 5)(y);
BOOST_CHECK(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);
((_1 ->* _2) = 7)(y, make_const(&my_struct::mem));
BOOST_CHECK(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_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_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_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_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));
// member functions with default values do not work (inherent language issue)
// BOOST_CHECK( (_1 ->* &my_struct::foo3default)(y)() == (y->mem+1+2+3));
}
class A {};
class B {};
class C {};
class D {};
// ->* can be overloaded to do anything
bool operator->*(A /*a*/, B /*b*/) {
return false;
}
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.
namespace boost {
namespace lambda {
template <>
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> {
typedef bool type;
};
template<>
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> {
typedef bool type;
};
} // lambda
} // boost
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);
// 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);
// 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);
return;
}
int test_main(int, char *[]) {
pointer_to_data_member_tests();
pointer_to_member_function_tests();
test_overloaded_pointer_to_member();
return 0;
}

View File

@@ -0,0 +1,431 @@
// 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
// -----------------------------------------------------------------------
#include <boost/test/minimal.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;
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_CHECK((_1 * 2)(j)==4);
BOOST_CHECK((_1 / 2)(j)==1);
BOOST_CHECK((_1 % 2)(k)==1);
BOOST_CHECK((-_1)(i) == -1);
BOOST_CHECK((+_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_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);
}
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_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);
}
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_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_CHECK((!_1)(t) == false);
BOOST_CHECK((!_1)(f) == true);
// test short circuiting
int i=0;
(false && ++_1)(i);
BOOST_CHECK(i==0);
i = 0;
(true && ++_1)(i);
BOOST_CHECK(i==1);
i = 0;
(false || ++_1)(i);
BOOST_CHECK(i==1);
i = 0;
(true || ++_1)(i);
BOOST_CHECK(i==0);
i = 0;
}
void unary_incs_and_decs() {
int i = 0;
BOOST_CHECK(_1++(i) == 0);
BOOST_CHECK(i == 1);
i = 0;
BOOST_CHECK(_1--(i) == 0);
BOOST_CHECK(i == -1);
i = 0;
BOOST_CHECK((++_1)(i) == 1);
BOOST_CHECK(i == 1);
i = 0;
BOOST_CHECK((--_1)(i) == -1);
BOOST_CHECK(i == -1);
i = 0;
// the result of prefix -- and ++ are lvalues
(++_1)(i) = 10;
BOOST_CHECK(i==10);
i = 0;
(--_1)(i) = 10;
BOOST_CHECK(i==10);
i = 0;
}
void compound_operators() {
int i = 1;
// normal variable as the left operand
(i += _1)(make_const(1));
BOOST_CHECK(i == 2);
(i -= _1)(make_const(1));
BOOST_CHECK(i == 1);
(i *= _1)(make_const(10));
BOOST_CHECK(i == 10);
(i /= _1)(make_const(2));
BOOST_CHECK(i == 5);
(i %= _1)(make_const(2));
BOOST_CHECK(i == 1);
// lambda expression as a left operand
(_1 += 1)(i);
BOOST_CHECK(i == 2);
(_1 -= 1)(i);
BOOST_CHECK(i == 1);
(_1 *= 10)(i);
BOOST_CHECK(i == 10);
(_1 /= 2)(i);
BOOST_CHECK(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);
// shifts
unsigned int ui = 2;
(_1 <<= 1)(ui);
BOOST_CHECK(ui==(2 << 1));
ui = 2;
(_1 >>= 1)(ui);
BOOST_CHECK(ui==(2 >> 1));
ui = 2;
(ui <<= _1)(make_const(1));
BOOST_CHECK(ui==(2 << 1));
ui = 2;
(ui >>= _1)(make_const(1));
BOOST_CHECK(ui==(2 >> 1));
// and, or, xor
ui = 2;
(_1 &= 1)(ui);
BOOST_CHECK(ui==(2 & 1));
ui = 2;
(_1 |= 1)(ui);
BOOST_CHECK(ui==(2 | 1));
ui = 2;
(_1 ^= 1)(ui);
BOOST_CHECK(ui==(2 ^ 1));
ui = 2;
(ui &= _1)(make_const(1));
BOOST_CHECK(ui==(2 & 1));
ui = 2;
(ui |= _1)(make_const(1));
BOOST_CHECK(ui==(2 | 1));
ui = 2;
(ui ^= _1)(make_const(1));
BOOST_CHECK(ui==(2 ^ 1));
}
void assignment_and_subscript() {
// assignment and subscript need to be defined as member functions.
// Hence, if you wish to use a normal variable as the left hand argument,
// you must wrap it with var to turn it into a lambda expression
using std::string;
string s;
(_1 = "one")(s);
BOOST_CHECK(s == string("one"));
(var(s) = "two")();
BOOST_CHECK(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');
// subscript returns lvalue
(var(s)[_1])(make_const(1)) = 'o';
BOOST_CHECK(s == "too");
(_1[1])(s) = 'a';
BOOST_CHECK(s == "tao");
(_1[_2])(s, make_const(0)) = 'm';
BOOST_CHECK(s == "mao");
// TODO: tests for vector, set, map, multimap
}
class A {};
void address_of_and_dereference() {
A a; int i = 42;
BOOST_CHECK((&_1)(a) == &a);
BOOST_CHECK((*&_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);
// 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);
}
void comma() {
int i = 100;
BOOST_CHECK((_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)
}
void pointer_arithmetic() {
int ia[4] = { 1, 2, 3, 4 };
int* ip = ia;
int* ia_last = &ia[3];
const int cia[4] = { 1, 2, 3, 4 };
const int* cip = cia;
const int* cia_last = &cia[3];
// non-const array
BOOST_CHECK((*(_1 + 1))(ia) == 2);
// non-const pointer
BOOST_CHECK((*(_1 + 1))(ip) == 2);
BOOST_CHECK((*(_1 - 1))(ia_last) == 3);
// const array
BOOST_CHECK((*(_1 + 1))(cia) == 2);
// const pointer
BOOST_CHECK((*(_1 + 1))(cip) == 2);
BOOST_CHECK((*(_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);
// 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);
}
int test_main(int, char *[]) {
arithmetic_operators();
bitwise_operators();
comparison_operators();
logical_operators();
unary_incs_and_decs();
compound_operators();
assignment_and_subscript();
address_of_and_dereference();
comma();
pointer_arithmetic();
cout_tests();
return 0;
}

View File

@@ -0,0 +1,148 @@
// 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/test/minimal.hpp> // see "Header Implementation Option"
#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 test_main(int, char *[]) {
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 0;
}

314
test/result_of_tests.cpp Normal file
View File

@@ -0,0 +1,314 @@
// 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/test/minimal.hpp> // see "Header Implementation Option"
#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 test_main(int, char *[]) {
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);
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 0;
}

53
test/ret_test.cpp Normal file
View File

@@ -0,0 +1,53 @@
// 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/test/minimal.hpp>
#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 test_main(int, char*[]) {
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 0;
}

57
test/rvalue_test.cpp Normal file
View File

@@ -0,0 +1,57 @@
// 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/detail/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();
}

392
test/switch_construct.cpp Normal file
View File

@@ -0,0 +1,392 @@
// 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
// -----------------------------------------------------------------------
#include <boost/test/minimal.hpp> // see "Header Implementation Option"
#include "boost/lambda/lambda.hpp"
#include "boost/lambda/if.hpp"
#include "boost/lambda/switch.hpp"
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
// Check that elements 0 -- index are 1, and the rest are 0
bool check(const std::vector<int>& v, int index) {
using namespace boost::lambda;
int counter = 0;
std::vector<int>::const_iterator
result = std::find_if(v.begin(), v.end(),
! if_then_else_return(
var(counter)++ <= index,
_1 == 1,
_1 == 0)
);
return result == v.end();
}
void do_switch_no_defaults_tests() {
using namespace boost::lambda;
int i = 0;
std::vector<int> v,w;
// elements from 0 to 9
std::generate_n(std::back_inserter(v),
10,
var(i)++);
std::fill_n(std::back_inserter(w), 10, 0);
// ---
std::for_each(v.begin(), v.end(),
switch_statement(
_1,
case_statement<0>(++var(w[0]))
)
);
BOOST_CHECK(check(w, 0));
std::fill_n(w.begin(), 10, 0);
// ---
std::for_each(v.begin(), v.end(),
switch_statement(
_1,
case_statement<0>(++var(w[0])),
case_statement<1>(++var(w[1]))
)
);
BOOST_CHECK(check(w, 1));
std::fill_n(w.begin(), 10, 0);
// ---
std::for_each(v.begin(), v.end(),
switch_statement(
_1,
case_statement<0>(++var(w[0])),
case_statement<1>(++var(w[1])),
case_statement<2>(++var(w[2]))
)
);
BOOST_CHECK(check(w, 2));
std::fill_n(w.begin(), 10, 0);
// ---
std::for_each(v.begin(), v.end(),
switch_statement(
_1,
case_statement<0>(++var(w[0])),
case_statement<1>(++var(w[1])),
case_statement<2>(++var(w[2])),
case_statement<3>(++var(w[3]))
)
);
BOOST_CHECK(check(w, 3));
std::fill_n(w.begin(), 10, 0);
// ---
std::for_each(v.begin(), v.end(),
switch_statement(
_1,
case_statement<0>(++var(w[0])),
case_statement<1>(++var(w[1])),
case_statement<2>(++var(w[2])),
case_statement<3>(++var(w[3])),
case_statement<4>(++var(w[4]))
)
);
BOOST_CHECK(check(w, 4));
std::fill_n(w.begin(), 10, 0);
// ---
std::for_each(v.begin(), v.end(),
switch_statement(
_1,
case_statement<0>(++var(w[0])),
case_statement<1>(++var(w[1])),
case_statement<2>(++var(w[2])),
case_statement<3>(++var(w[3])),
case_statement<4>(++var(w[4])),
case_statement<5>(++var(w[5]))
)
);
BOOST_CHECK(check(w, 5));
std::fill_n(w.begin(), 10, 0);
// ---
std::for_each(v.begin(), v.end(),
switch_statement(
_1,
case_statement<0>(++var(w[0])),
case_statement<1>(++var(w[1])),
case_statement<2>(++var(w[2])),
case_statement<3>(++var(w[3])),
case_statement<4>(++var(w[4])),
case_statement<5>(++var(w[5])),
case_statement<6>(++var(w[6]))
)
);
BOOST_CHECK(check(w, 6));
std::fill_n(w.begin(), 10, 0);
// ---
std::for_each(v.begin(), v.end(),
switch_statement(
_1,
case_statement<0>(++var(w[0])),
case_statement<1>(++var(w[1])),
case_statement<2>(++var(w[2])),
case_statement<3>(++var(w[3])),
case_statement<4>(++var(w[4])),
case_statement<5>(++var(w[5])),
case_statement<6>(++var(w[6])),
case_statement<7>(++var(w[7]))
)
);
BOOST_CHECK(check(w, 7));
std::fill_n(w.begin(), 10, 0);
// ---
std::for_each(v.begin(), v.end(),
switch_statement(
_1,
case_statement<0>(++var(w[0])),
case_statement<1>(++var(w[1])),
case_statement<2>(++var(w[2])),
case_statement<3>(++var(w[3])),
case_statement<4>(++var(w[4])),
case_statement<5>(++var(w[5])),
case_statement<6>(++var(w[6])),
case_statement<7>(++var(w[7])),
case_statement<8>(++var(w[8]))
)
);
BOOST_CHECK(check(w, 8));
std::fill_n(w.begin(), 10, 0);
}
void do_switch_yes_defaults_tests() {
using namespace boost::lambda;
int i = 0;
std::vector<int> v,w;
// elements from 0 to 9
std::generate_n(std::back_inserter(v),
10,
var(i)++);
std::fill_n(std::back_inserter(w), 10, 0);
int default_count;
// ---
default_count = 0;
std::for_each(v.begin(), v.end(),
switch_statement(
_1,
default_statement(++var(default_count))
)
);
BOOST_CHECK(check(w, -1));
BOOST_CHECK(default_count == 10);
std::fill_n(w.begin(), 10, 0);
// ---
default_count = 0;
std::for_each(v.begin(), v.end(),
switch_statement(
_1,
case_statement<0>(++var(w[0])),
default_statement(++var(default_count))
)
);
BOOST_CHECK(check(w, 0));
BOOST_CHECK(default_count == 9);
std::fill_n(w.begin(), 10, 0);
// ---
default_count = 0;
std::for_each(v.begin(), v.end(),
switch_statement(
_1,
case_statement<0>(++var(w[0])),
case_statement<1>(++var(w[1])),
default_statement(++var(default_count))
)
);
BOOST_CHECK(check(w, 1));
BOOST_CHECK(default_count == 8);
std::fill_n(w.begin(), 10, 0);
// ---
default_count = 0;
std::for_each(v.begin(), v.end(),
switch_statement(
_1,
case_statement<0>(++var(w[0])),
case_statement<1>(++var(w[1])),
case_statement<2>(++var(w[2])),
default_statement(++var(default_count))
)
);
BOOST_CHECK(check(w, 2));
BOOST_CHECK(default_count == 7);
std::fill_n(w.begin(), 10, 0);
// ---
default_count = 0;
std::for_each(v.begin(), v.end(),
switch_statement(
_1,
case_statement<0>(++var(w[0])),
case_statement<1>(++var(w[1])),
case_statement<2>(++var(w[2])),
case_statement<3>(++var(w[3])),
default_statement(++var(default_count))
)
);
BOOST_CHECK(check(w, 3));
BOOST_CHECK(default_count == 6);
std::fill_n(w.begin(), 10, 0);
// ---
default_count = 0;
std::for_each(v.begin(), v.end(),
switch_statement(
_1,
case_statement<0>(++var(w[0])),
case_statement<1>(++var(w[1])),
case_statement<2>(++var(w[2])),
case_statement<3>(++var(w[3])),
case_statement<4>(++var(w[4])),
default_statement(++var(default_count))
)
);
BOOST_CHECK(check(w, 4));
BOOST_CHECK(default_count == 5);
std::fill_n(w.begin(), 10, 0);
// ---
default_count = 0;
std::for_each(v.begin(), v.end(),
switch_statement(
_1,
case_statement<0>(++var(w[0])),
case_statement<1>(++var(w[1])),
case_statement<2>(++var(w[2])),
case_statement<3>(++var(w[3])),
case_statement<4>(++var(w[4])),
case_statement<5>(++var(w[5])),
default_statement(++var(default_count))
)
);
BOOST_CHECK(check(w, 5));
BOOST_CHECK(default_count == 4);
std::fill_n(w.begin(), 10, 0);
// ---
default_count = 0;
std::for_each(v.begin(), v.end(),
switch_statement(
_1,
case_statement<0>(++var(w[0])),
case_statement<1>(++var(w[1])),
case_statement<2>(++var(w[2])),
case_statement<3>(++var(w[3])),
case_statement<4>(++var(w[4])),
case_statement<5>(++var(w[5])),
case_statement<6>(++var(w[6])),
default_statement(++var(default_count))
)
);
BOOST_CHECK(check(w, 6));
BOOST_CHECK(default_count == 3);
std::fill_n(w.begin(), 10, 0);
// ---
default_count = 0;
std::for_each(v.begin(), v.end(),
switch_statement(
_1,
case_statement<0>(++var(w[0])),
case_statement<1>(++var(w[1])),
case_statement<2>(++var(w[2])),
case_statement<3>(++var(w[3])),
case_statement<4>(++var(w[4])),
case_statement<5>(++var(w[5])),
case_statement<6>(++var(w[6])),
case_statement<7>(++var(w[7])),
default_statement(++var(default_count))
)
);
BOOST_CHECK(check(w, 7));
BOOST_CHECK(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 test_main(int, char* []) {
do_switch_no_defaults_tests();
do_switch_yes_defaults_tests();
test_empty_cases();
return EXIT_SUCCESS;
}