1
0
mirror of https://git.suyu.dev/suyu/suyu synced 2025-09-16 02:58:00 -05:00

Initial commit

This commit is contained in:
Crimson-Hawk
2024-03-05 16:42:40 +08:00
commit f1e4595ebf
39576 changed files with 7006612 additions and 0 deletions

View File

View File

View File

@@ -0,0 +1,96 @@
* text=auto !eol svneol=native#text/plain
*.gitattributes text svneol=native#text/plain
# Scriptish formats
*.bat text svneol=native#text/plain
*.bsh text svneol=native#text/x-beanshell
*.cgi text svneol=native#text/plain
*.cmd text svneol=native#text/plain
*.js text svneol=native#text/javascript
*.php text svneol=native#text/x-php
*.pl text svneol=native#text/x-perl
*.pm text svneol=native#text/x-perl
*.py text svneol=native#text/x-python
*.sh eol=lf svneol=LF#text/x-sh
configure eol=lf svneol=LF#text/x-sh
# Image formats
*.bmp binary svneol=unset#image/bmp
*.gif binary svneol=unset#image/gif
*.ico binary svneol=unset#image/ico
*.jpeg binary svneol=unset#image/jpeg
*.jpg binary svneol=unset#image/jpeg
*.png binary svneol=unset#image/png
*.tif binary svneol=unset#image/tiff
*.tiff binary svneol=unset#image/tiff
*.svg text svneol=native#image/svg%2Bxml
# Data formats
*.pdf binary svneol=unset#application/pdf
*.avi binary svneol=unset#video/avi
*.doc binary svneol=unset#application/msword
*.dsp text svneol=crlf#text/plain
*.dsw text svneol=crlf#text/plain
*.eps binary svneol=unset#application/postscript
*.gz binary svneol=unset#application/gzip
*.mov binary svneol=unset#video/quicktime
*.mp3 binary svneol=unset#audio/mpeg
*.ppt binary svneol=unset#application/vnd.ms-powerpoint
*.ps binary svneol=unset#application/postscript
*.psd binary svneol=unset#application/photoshop
*.rdf binary svneol=unset#text/rdf
*.rss text svneol=unset#text/xml
*.rtf binary svneol=unset#text/rtf
*.sln text svneol=native#text/plain
*.swf binary svneol=unset#application/x-shockwave-flash
*.tgz binary svneol=unset#application/gzip
*.vcproj text svneol=native#text/xml
*.vcxproj text svneol=native#text/xml
*.vsprops text svneol=native#text/xml
*.wav binary svneol=unset#audio/wav
*.xls binary svneol=unset#application/vnd.ms-excel
*.zip binary svneol=unset#application/zip
# Text formats
.htaccess text svneol=native#text/plain
*.bbk text svneol=native#text/xml
*.cmake text svneol=native#text/plain
*.css text svneol=native#text/css
*.dtd text svneol=native#text/xml
*.htm text svneol=native#text/html
*.html text svneol=native#text/html
*.ini text svneol=native#text/plain
*.log text svneol=native#text/plain
*.mak text svneol=native#text/plain
*.qbk text svneol=native#text/plain
*.rst text svneol=native#text/plain
*.sql text svneol=native#text/x-sql
*.txt text svneol=native#text/plain
*.xhtml text svneol=native#text/xhtml%2Bxml
*.xml text svneol=native#text/xml
*.xsd text svneol=native#text/xml
*.xsl text svneol=native#text/xml
*.xslt text svneol=native#text/xml
*.xul text svneol=native#text/xul
*.yml text svneol=native#text/plain
boost-no-inspect text svneol=native#text/plain
CHANGES text svneol=native#text/plain
COPYING text svneol=native#text/plain
INSTALL text svneol=native#text/plain
Jamfile text svneol=native#text/plain
Jamroot text svneol=native#text/plain
Jamfile.v2 text svneol=native#text/plain
Jamrules text svneol=native#text/plain
Makefile* text svneol=native#text/plain
README text svneol=native#text/plain
TODO text svneol=native#text/plain
# Code formats
*.c text svneol=native#text/plain
*.cpp text svneol=native#text/plain
*.h text svneol=native#text/plain
*.hpp text svneol=native#text/plain
*.ipp text svneol=native#text/plain
*.tpp text svneol=native#text/plain
*.jam text svneol=native#text/plain
*.java text svneol=native#text/plain

View File

@@ -0,0 +1,323 @@
# Copyright 2016-2019 Peter Dimov
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
language: cpp
sudo: false
dist: trusty
branches:
only:
- master
- develop
- /feature\/.*/
env:
matrix:
- BOGUS_JOB=true
matrix:
exclude:
- env: BOGUS_JOB=true
include:
- os: linux
compiler: g++
env: TOOLSET=gcc COMPILER=g++ CXXSTD=03,11
- os: linux
compiler: g++-4.4
env: TOOLSET=gcc COMPILER=g++-4.4 CXXSTD=98,0x
addons:
apt:
packages:
- g++-4.4
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-4.6
env: TOOLSET=gcc COMPILER=g++-4.6 CXXSTD=03,0x
addons:
apt:
packages:
- g++-4.6
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-4.7
env: TOOLSET=gcc COMPILER=g++-4.7 CXXSTD=03,11
addons:
apt:
packages:
- g++-4.7
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-4.8
env: TOOLSET=gcc COMPILER=g++-4.8 CXXSTD=03,11
addons:
apt:
packages:
- g++-4.8
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-4.9
env: TOOLSET=gcc COMPILER=g++-4.9 CXXSTD=03,11
addons:
apt:
packages:
- g++-4.9
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-5
env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=03,11,14,1z
addons:
apt:
packages:
- g++-5
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-6
env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=03,11,14,1z
addons:
apt:
packages:
- g++-6
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-7
env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=03,11,14,17
addons:
apt:
packages:
- g++-7
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-8
env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=03,11,14,17,2a
addons:
apt:
packages:
- g++-8
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-9
env: TOOLSET=gcc COMPILER=g++-9 CXXSTD=03,11,14,17,2a
addons:
apt:
packages:
- g++-9
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-7
env: UBSAN=1 TOOLSET=gcc COMPILER=g++-7 CXXSTD=03,11,14,17 UBSAN_OPTIONS=print_stacktrace=1 LINKFLAGS=-fuse-ld=gold
addons:
apt:
packages:
- g++-7
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: clang++
env: TOOLSET=clang COMPILER=clang++ CXXSTD=03,11
- os: linux
compiler: /usr/bin/clang++
env: TOOLSET=clang COMPILER=/usr/bin/clang++ CXXSTD=03,11
addons:
apt:
packages:
- clang-3.3
- os: linux
compiler: /usr/bin/clang++
env: TOOLSET=clang COMPILER=/usr/bin/clang++ CXXSTD=03,11
addons:
apt:
packages:
- clang-3.4
- os: linux
compiler: clang++-3.5
env: TOOLSET=clang COMPILER=clang++-3.5 CXXSTD=03,11,14,1z
addons:
apt:
packages:
- clang-3.5
- libstdc++-4.9-dev
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.5
- os: linux
compiler: clang++-3.6
env: TOOLSET=clang COMPILER=clang++-3.6 CXXSTD=03,11,14,1z
addons:
apt:
packages:
- clang-3.6
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.6
- os: linux
compiler: clang++-3.7
env: TOOLSET=clang COMPILER=clang++-3.7 CXXSTD=03,11,14,1z
addons:
apt:
packages:
- clang-3.7
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.7
- os: linux
compiler: clang++-3.8
env: TOOLSET=clang COMPILER=clang++-3.8 CXXSTD=03,11,14,1z
addons:
apt:
packages:
- clang-3.8
- libstdc++-4.9-dev
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.8
- os: linux
compiler: clang++-3.9
env: TOOLSET=clang COMPILER=clang++-3.9 CXXSTD=03,11,14,1z
addons:
apt:
packages:
- clang-3.9
- libstdc++-4.9-dev
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.9
- os: linux
compiler: clang++-4.0
env: TOOLSET=clang COMPILER=clang++-4.0 CXXSTD=03,11,14,1z
addons:
apt:
packages:
- clang-4.0
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-4.0
- os: linux
compiler: clang++-5.0
env: TOOLSET=clang COMPILER=clang++-5.0 CXXSTD=03,11,14,1z
addons:
apt:
packages:
- clang-5.0
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-5.0
- os: linux
compiler: clang++-6.0
env: TOOLSET=clang COMPILER=clang++-6.0 CXXSTD=03,11,14,17,2a
addons:
apt:
packages:
- clang-6.0
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-6.0
- os: linux
compiler: clang++-7
env: TOOLSET=clang COMPILER=clang++-7 CXXSTD=03,11,14,17,2a
addons:
apt:
packages:
- clang-7
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-7
- os: linux
compiler: clang++-8
env: TOOLSET=clang COMPILER=clang++-8 CXXSTD=03,11,14,17,2a
addons:
apt:
packages:
- clang-8
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-8
- os: linux
compiler: clang++-7
env: UBSAN=1 TOOLSET=clang COMPILER=clang++-7 CXXSTD=03,11,14,17,2a UBSAN_OPTIONS=print_stacktrace=1
addons:
apt:
packages:
- clang-7
- libstdc++-5-dev
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-7
- os: linux
compiler: clang++-libc++
env: TOOLSET=clang COMPILER=clang++-libc++ CXXSTD=03,11,14,1z
addons:
apt:
packages:
- libc++-dev
- os: linux
compiler: clang++-libc++
env: UBSAN=1 TOOLSET=clang COMPILER=clang++-libc++ CXXSTD=03,11,14,1z UBSAN_OPTIONS=print_stacktrace=1
addons:
apt:
packages:
- libc++-dev
- os: osx
compiler: clang++
env: TOOLSET=clang COMPILER=clang++ CXXSTD=03,11,14,1z
install:
- BOOST_BRANCH=develop && [ "$TRAVIS_BRANCH" == "master" ] && BOOST_BRANCH=master || true
- cd ..
- git clone -b $BOOST_BRANCH https://github.com/boostorg/boost.git boost-root
- cd boost-root
- git submodule update --init tools/boostdep
- cp -r $TRAVIS_BUILD_DIR/* libs/proto
- python tools/boostdep/depinst/depinst.py proto
- ./bootstrap.sh
- ./b2 headers
script:
- |-
echo "using $TOOLSET : : $COMPILER ;" > ~/user-config.jam
- ./b2 -j3 libs/proto/test toolset=$TOOLSET cxxstd=$CXXSTD variant=debug,release ${UBSAN:+cxxflags=-fsanitize=undefined cxxflags=-fno-sanitize-recover=undefined linkflags=-fsanitize=undefined debug-symbols=on} ${LINKFLAGS:+linkflags=$LINKFLAGS}
notifications:
email:
on_success: always

View File

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

View File

@@ -0,0 +1,85 @@
# Copyright Eric Niebler 2007. Use, modification, and distribution are
# subject to the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
import os ;
import path ;
import quickbook ;
import boostbook ;
local admon-graphics-path = [ path.join [ boostbook.docbook-xsl-dir ] images ] ;
local callout-graphics-path = [ path.join $(admon-graphics-path) callouts ] ;
admon-graphics-path = [ path.native $(admon-graphics-path)/ ] ;
callout-graphics-path = [ path.native $(callout-graphics-path)/ ] ;
if [ os.name ] = CYGWIN
{
admon-graphics-path = $(admon-graphics-path:W) ;
callout-graphics-path = $(callout-graphics-path:W) ;
admon-graphics-path = $(admon-graphics-path:T) ;
callout-graphics-path = $(callout-graphics-path:T) ;
}
xml proto
:
proto.qbk
;
boostbook standalone
:
proto
:
<xsl:param>boost.root=../../../..
# HTML options first:
# Use graphics not text for navigation:
<xsl:param>navig.graphics=1
# How far down we chunk nested sections, basically all of them:
<xsl:param>chunk.section.depth=10
# Don't put the first section on the same page as the TOC:
<xsl:param>chunk.first.sections=1
# How far down sections get TOC's
<xsl:param>toc.section.depth=10
# Max depth in each TOC:
<xsl:param>toc.max.depth=4
# How far down we go with TOC's
<xsl:param>generate.section.toc.level=10
# Set the path to the boost-root so we find our graphics:
#<xsl:param>boost.root=$(BOOST_ROOT)
# location of the main index file so our links work:
#<xsl:param>boost.libraries=$(BOOST_ROOT)/libs/libraries.htm
# PDF Options:
# TOC Generation: this is needed for FOP-0.9 and later:
# <xsl:param>fop1.extensions=1
<format>pdf:<xsl:param>fop1.extensions=0
<format>pdf:<xsl:param>xep.extensions=1
# TOC generation: this is needed for FOP 0.2, but must not be set to zero for FOP-0.9!
<format>pdf:<xsl:param>fop.extensions=0
# No indent on body text:
<format>pdf:<xsl:param>body.start.indent=0pt
# Margin size:
<format>pdf:<xsl:param>page.margin.inner=0.5in
# Margin size:
<format>pdf:<xsl:param>page.margin.outer=0.5in
# Yes, we want graphics for admonishments:
<format>pdf:<xsl:param>admon.graphics=1
# Set this one for PDF generation *only*:
# default png graphics are awful in PDF form,
# better use SVG's instead:
#<format>pdf:<xsl:param>admon.graphics.extension=".svg"
#<format>pdf:<xsl:param>admon.graphics.path="$(admon-graphics-path)"
#<format>pdf:<xsl:param>callout.graphics.path="$(callout-graphics-path)"
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html
;
###############################################################################
alias boostdoc
: proto
:
:
: ;
explicit boostdoc ;
alias boostrelease ;
explicit boostrelease ;

View File

@@ -0,0 +1,24 @@
[/
/ Copyright (c) 2008 Eric Niebler
/
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
/]
[section:acknowledgements Appendix E: Acknowledgements]
I'd like to thank Joel de Guzman and Hartmut Kaiser for being willing to take a chance on using Proto for their work on Spirit-2 and Karma when Proto was little more than a vision. Their requirements and feedback have been indespensable.
Thanks also to Thomas Heller and again to Hartmut for their feedback and suggestions during the redesign of Phoenix. That effort yielded several valuable advanced features such as sub-domains, external transforms, and per-domain `as_child` customization.
Thanks to Daniel James for providing a patch to remove the dependence on deprecated configuration macros for C++0x features.
Thanks to Joel Falcou and Christophe Henry for their enthusiasm, support, feedback, and humor; and for volunteering to be Proto's co-maintainers.
Thanks to Dave Abrahams for an especially detailed review, and for making a VM with msvc-7.1 available so I could track down portability issues on that compiler.
Many thanks to Daniel Wallin who first implemented the code used to find the common domain among a set, accounting for super- and sub-domains. Thanks also to Jeremiah Willcock, John Bytheway and Krishna Achuthan who offered alternate solutions to this tricky programming problem.
Thanks also to the developers of _PETE_. I found many good ideas there.
[endsect]

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,289 @@
[/
/ Copyright (c) 2008 Eric Niebler
/
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
/]
[/=======================]
[section Hello Calculator]
[/=======================]
"Hello, world" is nice, but it doesn't get you very far. Let's use Proto to build a
EDSL (embedded domain-specific language) for a lazily-evaluated calculator. We'll
see how to define the terminals in your mini-language, how to compose them into
larger expressions, and how to define an evaluation context so that your
expressions can do useful work. When we're done, we'll have a mini-language that
will allow us to declare a lazily-evaluated arithmetic expression, such as
`(_2 - _1) / _2 * 100`, where `_1` and `_2` are placeholders for values to be
passed in when the expression is evaluated.
[/=========================]
[heading Defining Terminals]
[/=========================]
The first order of business is to define the placeholders `_1` and `_2`. For that,
we'll use the _terminal_ metafunction.
// Define a placeholder type
template<int I>
struct placeholder
{};
// Define the Protofied placeholder terminals
proto::terminal<placeholder<0> >::type const _1 = {{}};
proto::terminal<placeholder<1> >::type const _2 = {{}};
The initialization may look a little odd at first, but there is a good reason
for doing things this way. The objects `_1` and `_2` above do not require
run-time construction -- they are ['statically initialized], which means they
are essentially initialized at compile time. See the
[link boost_proto.appendices.rationale.static_initialization Static
Initialization] section in the [link boost_proto.appendices.rationale Rationale]
appendix for more information.
[/====================================]
[heading Constructing Expression Trees]
[/====================================]
Now that we have terminals, we can use Proto's operator overloads to combine
these terminals into larger expressions. So, for instance, we can immediately
say things like:
// This builds an expression template
(_2 - _1) / _2 * 100;
This creates an expression tree with a node for each operator. The type of the
resulting object is large and complex, but we are not terribly interested in it right now.
So far, the object is just a tree representing the expression. It has no
behavior. In particular, it is not yet a calculator. Below we'll see how
to make it a calculator by defining an evaluation context.
[/==================================]
[heading Evaluating Expression Trees]
[/==================================]
No doubt you want your expression templates to actually /do/ something. One
approach is to define an ['evaluation context]. The context is like a function
object that associates behaviors with the node types in your expression tree.
The following example should make it clear. It is explained below.
struct calculator_context
: proto::callable_context< calculator_context const >
{
// Values to replace the placeholders
std::vector<double> args;
// Define the result type of the calculator.
// (This makes the calculator_context "callable".)
typedef double result_type;
// Handle the placeholders:
template<int I>
double operator()(proto::tag::terminal, placeholder<I>) const
{
return this->args[I];
}
};
In `calculator_context`, we specify how Proto should evaluate the placeholder
terminals by defining the appropriate overloads of the function call operator.
For any other nodes in the expression tree (e.g., arithmetic operations or
non-placeholder terminals), Proto will evaluate the expression in the "default"
way. For example, a binary plus node is evaluated by first evaluating the left
and right operands and adding the results. Proto's default evaluator uses the
_typeof_ library to compute return types.
Now that we have an evaluation context for our calculator, we can use it to
evaluate our arithmetic expressions, as below:
calculator_context ctx;
ctx.args.push_back(45); // the value of _1 is 45
ctx.args.push_back(50); // the value of _2 is 50
// Create an arithmetic expression and immediately evaluate it
double d = proto::eval( (_2 - _1) / _2 * 100, ctx );
// This prints "10"
std::cout << d << std::endl;
Later, we'll see how to define more interesting evaluation contexts and
expression transforms that give you total control over how your expressions
are evaluated.
[/===================================]
[heading Customizing Expression Trees]
[/===================================]
Our calculator EDSL is already pretty useful, and for many EDSL scenarios, no more
would be needed. But let's keep going. Imagine how much nicer it would be if all
calculator expressions overloaded `operator()` so that they could be used as
function objects. We can do that by creating a calculator /domain/ and telling
Proto that all expressions in the calculator domain have extra members. Here is how
to define a calculator domain:
// Forward-declare an expression wrapper
template<typename Expr>
struct calculator;
// Define a calculator domain. Expression within
// the calculator domain will be wrapped in the
// calculator<> expression wrapper.
struct calculator_domain
: proto::domain< proto::generator<calculator> >
{};
The `calculator<>` type will be an expression wrapper. It will behave just like the
expression that it wraps, but it will have extra member functions that we will
define. The `calculator_domain` is what informs Proto about our wrapper. It is used
below in the definition of `calculator<>`. Read on for a description.
// Define a calculator expression wrapper. It behaves just like
// the expression it wraps, but with an extra operator() member
// function that evaluates the expression.
template<typename Expr>
struct calculator
: proto::extends<Expr, calculator<Expr>, calculator_domain>
{
typedef
proto::extends<Expr, calculator<Expr>, calculator_domain>
base_type;
calculator(Expr const &expr = Expr())
: base_type(expr)
{}
typedef double result_type;
// Overload operator() to invoke proto::eval() with
// our calculator_context.
double operator()(double a1 = 0, double a2 = 0) const
{
calculator_context ctx;
ctx.args.push_back(a1);
ctx.args.push_back(a2);
return proto::eval(*this, ctx);
}
};
The `calculator<>` struct is an expression /extension/. It uses `proto::extends<>` to effectively add additional members to an expression type. When composing larger expressions from smaller ones, Proto notes what domain the smaller expressions are in. The larger expression is in the same domain and is automatically wrapped in the domain's extension wrapper.
All that remains to be done is to put our placeholders in the calculator domain. We do that by wrapping them in our `calculator<>` wrapper, as below:
// Define the Protofied placeholder terminals, in the
// calculator domain.
calculator<proto::terminal<placeholder<0> >::type> const _1;
calculator<proto::terminal<placeholder<1> >::type> const _2;
Any larger expression that contain these placeholders will automatically be wrapped in the `calculator<>` wrapper and have our `operator()` overload. That means we can use them as function objects as follows.
double result = ((_2 - _1) / _2 * 100)(45.0, 50.0);
assert(result == (50.0 - 45.0) / 50.0 * 100));
Since calculator expressions are now valid function objects, we can use them with standard algorithms, as shown below:
double a1[4] = { 56, 84, 37, 69 };
double a2[4] = { 65, 120, 60, 70 };
double a3[4] = { 0 };
// Use std::transform() and a calculator expression
// to calculate percentages given two input sequences:
std::transform(a1, a1+4, a2, a3, (_2 - _1) / _2 * 100);
Now, let's use the calculator example to explore some other useful features of Proto.
[/====================================]
[heading Detecting Invalid Expressions]
[/====================================]
You may have noticed that you didn't have to define an overloaded `operator-()` or
`operator/()` -- Proto defined them for you. In fact, Proto overloads /all/ the
operators for you, even though they may not mean anything in your domain-specific
language. That means it may be possible to create expressions that are invalid in
your domain. You can detect invalid expressions with Proto by defining the
/grammar/ of your domain-specific language.
For simplicity, assume that our calculator EDSL should only allow addition,
subtraction, multiplication and division. Any expression involving any other
operator is invalid. Using Proto, we can state this requirement by defining the
grammar of the calculator EDSL. It looks as follows:
// Define the grammar of calculator expressions
struct calculator_grammar
: proto::or_<
proto::plus< calculator_grammar, calculator_grammar >
, proto::minus< calculator_grammar, calculator_grammar >
, proto::multiplies< calculator_grammar, calculator_grammar >
, proto::divides< calculator_grammar, calculator_grammar >
, proto::terminal< proto::_ >
>
{};
You can read the above grammar as follows: an expression tree conforms to the calculator grammar if it is a binary plus, minus, multiplies or divides node, where both child nodes also conform to the calculator grammar; or if it is a terminal. In a Proto grammar, _wild_ is a wildcard that matches any type, so `proto::terminal< proto::_ >` matches any terminal, whether it is a placeholder or a literal.
[note This grammar is actually a little looser than we would like. Only placeholders and literals that are convertible to doubles are valid terminals. Later on we'll see how to express things like that in Proto grammars.]
Once you have defined the grammar of your EDSL, you can use the _matches_ metafunction to check whether a given expression type conforms to the grammar. For instance, we might add the following to our `calculator::operator()` overload:
template<typename Expr>
struct calculator
: proto::extends< /* ... as before ... */ >
{
/* ... */
double operator()(double a1 = 0, double a2 = 0) const
{
// Check here that the expression we are about to
// evaluate actually conforms to the calculator grammar.
BOOST_MPL_ASSERT((proto::matches<Expr, calculator_grammar>));
/* ... */
}
};
The addition of the `BOOST_MPL_ASSERT()` line enforces at compile time that we only
evaluate expressions that conform to the calculator EDSL's grammar. With Proto
grammars, `proto::matches<>` and `BOOST_MPL_ASSERT()` it is very easy to give the
users of your EDSL short and readable compile-time errors when they accidentally
misuse your EDSL.
[note `BOOST_MPL_ASSERT()` is part of the Boost Metaprogramming Library. To use it,
just `#include <boost/mpl/assert.hpp>`.]
[/=====================================]
[heading Controlling Operator Overloads]
[/=====================================]
Grammars and `proto::matches<>` make it possible to detect when a user has created
an invalid expression and issue a compile-time error. But what if you want to
prevent users from creating invalid expressions in the first place? By using
grammars and domains together, you can disable any of Proto's operator overloads
that would create an invalid expression. It is as simple as specifying the EDSL's
grammar when you define the domain, as shown below:
// Define a calculator domain. Expression within
// the calculator domain will be wrapped in the
// calculator<> expression wrapper.
// NEW: Any operator overloads that would create an
// expression that does not conform to the
// calculator grammar is automatically disabled.
struct calculator_domain
: proto::domain< proto::generator<calculator>, calculator_grammar >
{};
The only thing we changed is we added `calculator_grammar` as the second template
parameter to the `proto::domain<>` template when defining `calculator_domain`. With
this simple addition, we disable any of Proto's operator overloads that would
create an invalid calculator expression.
[/========================]
[heading ... And Much More]
[/========================]
Hopefully, this gives you an idea of what sorts of things Proto can do for you. But
this only scratches the surface. The rest of this users' guide will describe all
these features and others in more detail.
Happy metaprogramming!
[endsect]

View File

@@ -0,0 +1,69 @@
[/
/ Copyright (c) 2008 Eric Niebler
/
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
/]
[/================================]
[section:naming Naming Conventions]
[/================================]
Proto is a large library and probably quite unlike any library you've used
before. Proto uses some consistent naming conventions to make it easier to
navigate, and they're described below.
[/================]
[heading Functions]
[/================]
All of Proto's functions are defined in the `boost::proto` namespace. For
example, there is a function called `value()` defined in `boost::proto` that
accepts a terminal expression and returns the terminal's value.
[/====================]
[heading Metafunctions]
[/====================]
Proto defines /metafunctions/ that correspond to each of Proto's free functions.
The metafunctions are used to compute the functions' return types. All of
Proto's metafunctions live in the `boost::proto::result_of` namespace and
have the same name as the functions to which they correspond. For instance,
there is a class template `boost::proto::result_of::value<>` that you can
use to compute the return type of the `boost::proto::value()` function.
[/=======================]
[heading Function Objects]
[/=======================]
Proto defines /function object/ equivalents of all of its free functions. (A
function object is an instance of a class type that defines an `operator()`
member function.) All of Proto's function object types are defined in the
`boost::proto::functional` namespace and have the same name as their
corresponding free functions. For example, `boost::proto::functional::value`
is a class that defines a function object that does the same thing as the
`boost::proto::value()` free function.
[/===========================]
[heading Primitive Transforms]
[/===========================]
Proto also defines /primitive transforms/ -- class types that can be used
to compose larger transforms for manipulating expression trees. Many of
Proto's free functions have corresponding primitive transforms. These live
in the `boost::proto` namespace and their names have a leading underscore.
For instance, the transform corresponding to the `value()` function is
called `boost::proto::_value`.
The following table summarizes the discussion above:
[table Proto Naming Conventions
[[Entity] [Example] ]
[[Free Function] [`boost::proto::value()`] ]
[[Metafunction] [`boost::proto::result_of::value<>`] ]
[[Function Object] [`boost::proto::functional::value`] ]
[[Transform] [`boost::proto::_value`] ]
]
[endsect]

View File

@@ -0,0 +1,172 @@
[/
/ Copyright (c) 2008 Eric Niebler
/
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
/]
[import ../example/hello.cpp]
[import ../example/calc1.cpp]
[import ../example/calc2.cpp]
[import ../example/calc3.cpp]
[import ../example/lazy_vector.cpp]
[import ../example/mixed.cpp]
[import ../example/rgb.cpp]
[import ../example/tarray.cpp]
[import ../example/vec3.cpp]
[import ../example/vector.cpp]
[import ../example/map_assign.cpp]
[import ../example/futures.cpp]
[import ../example/mini_lambda.cpp]
[import ../example/external_transforms.cpp]
[/===============]
[section Examples]
[/===============]
A code example is worth a thousand words ...
[/================================================================================]
[section:hello_world Hello World:
Building an Expression Template and Evaluating It]
[/================================================================================]
A trivial example which builds and expression template and evaluates it.
[HelloWorld]
[endsect]
[/==================================================]
[section:calc1 Calc1: Defining an Evaluation Context]
[/==================================================]
A simple example that builds a miniature embedded domain-specific language for lazy arithmetic expressions, with TR1 bind-style argument placeholders.
[Calc1]
[endsect]
[/============================================================]
[section:calc2 Calc2: Adding Members Using [^proto::extends<>]]
[/============================================================]
An extension of the Calc1 example that uses _extends_ to make calculator expressions valid function objects that can be used with STL algorithms.
[Calc2]
[endsect]
[/===============================================]
[section:calc3 Calc3: Defining a Simple Transform]
[/===============================================]
An extension of the Calc2 example that uses a Proto transform to calculate the arity of a calculator expression and statically assert that the correct number of arguments are passed.
[Calc3]
[endsect]
[/==============================================================]
[section:lazy_vector Lazy Vector: Controlling Operator Overloads]
[/==============================================================]
This example constructs a mini-library for linear algebra, using expression templates to eliminate the need for temporaries when adding vectors of numbers.
This example uses a domain with a grammar to prune the set of overloaded operators. Only those operators that produce valid lazy vector expressions are allowed.
[LazyVector]
[endsect]
[/========================================================]
[section:rgb RGB: Type Manipulations with Proto Transforms]
[/========================================================]
This is a simple example of doing arbitrary type manipulations with Proto transforms. It takes some expression involving primary colors and combines the colors according to arbitrary rules. It is a port of the RGB example from _PETE_.
[RGB]
[endsect]
[/=====================================================]
[section:tarray TArray: A Simple Linear Algebra Library]
[/=====================================================]
This example constructs a mini-library for linear algebra, using expression templates to eliminate the need for temporaries when adding arrays of numbers. It duplicates the TArray example from _PETE_.
[TArray]
[endsect]
[/========================================================]
[section:vec3 Vec3: Computing With Transforms and Contexts]
[/========================================================]
This is a simple example using `proto::extends<>` to extend a terminal type with additional behaviors, and using custom contexts and `proto::eval()` for evaluating expressions. It is a port of the Vec3 example from _PETE_.
[Vec3]
[endsect]
[/========================================================]
[section:vector Vector: Adapting a Non-Proto Terminal Type]
[/========================================================]
This is an example of using `BOOST_PROTO_DEFINE_OPERATORS()` to Protofy expressions using `std::vector<>`, a non-Proto type. It is a port of the Vector example from _PETE_.
[Vector]
[endsect]
[/=============================================================]
[section:mixed Mixed: Adapting Several Non-Proto Terminal Types]
[/=============================================================]
This is an example of using `BOOST_PROTO_DEFINE_OPERATORS()` to Protofy expressions using `std::vector<>` and `std::list<>`, non-Proto types. It is a port of the Mixed example from _PETE_.
[Mixed]
[endsect]
[/=======================================================]
[section:map_assign Map Assign: An Intermediate Transform]
[/=======================================================]
A demonstration of how to implement `map_list_of()` from the Boost.Assign library using Proto. `map_list_assign()` is used to conveniently initialize a `std::map<>`. By using Proto, we can avoid any dynamic allocation while building the intermediate representation.
[MapAssign]
[endsect]
[/===========================================================]
[section:future_group Future Group: A More Advanced Transform]
[/===========================================================]
An advanced example of a Proto transform that implements Howard Hinnant's design for /future groups/ that block for all or some asynchronous operations to complete and returns their results in a tuple of the appropriate type.
[FutureGroup]
[endsect]
[/========================================================]
[section:lambda Lambda: A Simple Lambda Library with Proto]
[/========================================================]
This is an advanced example that shows how to implement a simple lambda EDSL with Proto, like the Boost.Lambda_library. It uses contexts, transforms and expression extension.
[Lambda]
[endsect]
[/===============================================================================]
[section:checked_calc Checked Calculator: A Simple Example of External Transforms]
[/===============================================================================]
This is an advanced example that shows how to externally parameterize a grammar's transforms. It defines a calculator EDSL with a grammar that can perform either checked or unchecked arithmetic.
[CheckedCalc]
[endsect]
[endsect]

View File

@@ -0,0 +1,939 @@
[/
/ Copyright (c) 2007 Eric Niebler
/
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
/]
[/================================================================================]
[section:front_end Fronts Ends:
Defining Terminals and Non-Terminals of Your EDSL]
[/================================================================================]
Here is the fun part: designing your own mini-programming language. In this section we'll talk about the nuts and bolts of designing an EDSL interface using Proto. We'll cover the definition of terminals and lazy functions that the users of your EDSL will get to program with. We'll also talk about Proto's expression template-building operator overloads, and about ways to add additional members to expressions within your domain.
[/=======================]
[section Making Terminals]
[/=======================]
As we saw with the Calculator example from the Introduction, the simplest way to get an EDSL up and running is simply to define some terminals, as follows.
// Define a literal integer Proto expression.
proto::terminal<int>::type i = {0};
// This creates an expression template.
i + 1;
With some terminals and Proto's operator overloads, you can immediately start creating expression templates.
Defining terminals -- with aggregate initialization -- can be a little awkward at times. Proto provides an easier-to-use wrapper for literals that can be used to construct Protofied terminal expressions. It's called _literal_.
// Define a literal integer Proto expression.
proto::literal<int> i = 0;
// Proto literals are really just Proto terminal expressions.
// For example, this builds a Proto expression template:
i + 1;
There is also a _lit_ function for constructing a _literal_ in-place. The above expression can simply be written as:
// proto::lit(0) creates an integer terminal expression
proto::lit(0) + 1;
[endsect]
[/=================================]
[section Proto's Operator Overloads]
[/=================================]
Once we have some Proto terminals, expressions involving those terminals build expression trees for us. Proto defines overloads for each of C++'s overloadable operators in the `boost::proto` namespace. As long as one operand is a Proto expression, the result of the operation is a tree node representing that operation.
[note Proto's operator overloads live in the `boost::proto` namespace and are found via ADL (argument-dependent lookup). That is why expressions must be "tainted" with Proto-ness for Proto to be able to build trees out of expressions.]
As a result of Proto's operator overloads, we can say:
-_1; // OK, build a unary-negate tree node
_1 + 42; // OK, build a binary-plus tree node
For the most part, this Just Works and you don't need to think about it, but a few operators are special and it can be helpful to know how Proto handles them.
[/=========================================================]
[heading Assignment, Subscript, and Function Call Operators]
[/=========================================================]
Proto also overloads `operator=`, `operator[]`, and `operator()`, but these operators are member functions of the expression template rather than free functions in Proto's namespace. The following are valid Proto expressions:
_1 = 5; // OK, builds a binary assign tree node
_1[6]; // OK, builds a binary subscript tree node
_1(); // OK, builds a unary function tree node
_1(7); // OK, builds a binary function tree node
_1(8,9); // OK, builds a ternary function tree node
// ... etc.
For the first two lines, assignment and subscript, it should be fairly unsurprising that the resulting expression node should be binary. After all, there are two operands in each expression. It may be surprising at first that what appears to be a function call with no arguments, `_1()`, actually creates an expression node with one child. The child is `_1` itself. Likewise, the expression `_1(7)` has two children: `_1` and `7`.
Because these operators can only be defined as member functions, the following expressions are invalid:
int i;
i = _1; // ERROR: cannot assign _1 to an int
int *p;
p[_1]; // ERROR: cannot use _1 as an index
std::sin(_1); // ERROR: cannot call std::sin() with _1
Also, C++ has special rules for overloads of `operator->` that make it useless for building expression templates, so Proto does not overload it.
[/==============================]
[heading The Address-Of Operator]
[/==============================]
Proto overloads the address-of operator for expression types, so that the following code creates a new unary address-of tree node:
&_1; // OK, creates a unary address-of tree node
It does /not/ return the address of the `_1` object. However, there is special code in Proto such that a unary address-of node is implicitly convertible to a pointer to its child. In other words, the following code works and does what you might expect, but not in the obvious way:
typedef
proto::terminal< placeholder<0> >::type
_1_type;
_1_type const _1 = {{}};
_1_type const * p = &_1; // OK, &_1 implicitly converted
[endsect]
[/============================]
[section Making Lazy Functions]
[/============================]
If we limited ourselves to nothing but terminals and operator overloads, our embedded domain-specific languages wouldn't be very expressive. Imagine that we wanted to extend our calculator EDSL with a full suite of math functions like `sin()` and `pow()` that we could invoke lazily as follows.
// A calculator expression that takes one argument
// and takes the sine of it.
sin(_1);
We would like the above to create an expression template representing a function invocation. When that expression is evaluated, it should cause the function to be invoked. (At least, that's the meaning of function invocation we'd like the calculator EDSL to have.) You can define `sin` quite simply as follows.
// "sin" is a Proto terminal containing a function pointer
proto::terminal< double(*)(double) >::type const sin = {&std::sin};
In the above, we define `sin` as a Proto terminal containing a pointer to the `std::sin()` function. Now we can use `sin` as a lazy function. The `default_context` that we saw in the Introduction knows how to evaluate lazy functions. Consider the following:
double pi = 3.1415926535;
proto::default_context ctx;
// Create a lazy "sin" invocation and immediately evaluate it
std::cout << proto::eval( sin(pi/2), ctx ) << std::endl;
The above code prints out:
[pre 1]
I'm no expert at trigonometry, but that looks right to me.
We can write `sin(pi/2)` because the `sin` object, which is a Proto terminal, has an overloaded `operator()()` that builds a node representing a function call invocation. The actual type of `sin(pi/2)` is actually something like this:
// The type of the expression sin(pi/2):
proto::function<
proto::terminal< double(*)(double) >::type const &
proto::result_of::as_child< double const >::type
>::type
This type further expands to an unsightly node type with a /tag/ type of `proto::tag::function` and two children: the first representing the function to be invoked, and the second representing the argument to the function. (Node tag types describe the operation that created the node. The difference between `a + b` and `a - b` is that the former has tag type `proto::tag::plus` and the latter has tag type `proto::tag::minus`. Tag types are pure compile-time information.)
[note In the type computation above, `proto::result_of::as_child<>` is a metafunction that ensures its argument is a Proto expression type. If it isn't one already, it becomes a Proto terminal. We'll learn more about this metafunction, along with _as_child_, its runtime counterpart, [link boost_proto.users_guide.front_end.customizing_expressions_in_your_domain.per_domain_as_child later]. For now, you can forget about it.]
It is important to note that there is nothing special about terminals that contain function pointers. /Any/ Proto expression has an overloaded function call operator. Consider:
// This compiles!
proto::lit(1)(2)(3,4)(5,6,7,8);
That may look strange at first. It creates an integer terminal with _lit_, and then invokes it like a function again and again. What does it mean? Who knows?! You get to decide when you define an evaluation context or a transform. But more on that later.
[/=======================================]
[heading Making Lazy Functions, Continued]
[/=======================================]
Now, what if we wanted to add a `pow()` function to our calculator EDSL that users could invoke as follows?
// A calculator expression that takes one argument
// and raises it to the 2nd power
pow< 2 >(_1);
The simple technique described above of making `pow` a terminal containing a function pointer doesn't work here. If `pow` is an object, then the expression `pow< 2 >(_1)` is not valid C++. (Well, technically it is; it means, `pow` less than 2, greater than `(_1)`, which is nothing at all like what we want.) `pow` should be a real function template. But it must be an unusual function: one that returns an expression template.
With `sin`, we relied on Proto to provide an overloaded `operator()()` to build an expression node with tag type `proto::tag::function` for us. Now we'll need to do so ourselves. As before, the node will have two children: the function to invoke and the function's argument.
With `sin`, the function to invoke was a raw function pointer wrapped in a Proto terminal. In the case of `pow`, we want it to be a terminal containing TR1-style function object. This will allow us to parameterize the function on the exponent. Below is the implementation of a simple TR1-style wrapper for the `std::pow` function:
// Define a pow_fun function object
template< int Exp >
struct pow_fun
{
typedef double result_type;
double operator()(double d) const
{
return std::pow(d, Exp);
}
};
Following the `sin` example, we want `pow< 1 >( pi/2 )` to have a type like this:
// The type of the expression pow<1>(pi/2):
proto::function<
proto::terminal< pow_fun<1> >::type
proto::result_of::as_child< double const >::type
>::type
We could write a `pow()` function using code like this, but it's verbose and error prone; it's too easy to introduce subtle bugs by forgetting to call _as_child_ where necessary, resulting in code that seems to work but sometimes doesn't. Proto provides a better way to construct expression nodes: _make_expr_.
[/=====================================================]
[heading Lazy Functions Made Simple With [^make_expr()]]
[/=====================================================]
Proto provides a helper for building expression templates called _make_expr_. We can concisely define the `pow()` function with it as below.
// Define a lazy pow() function for the calculator EDSL.
// Can be used as: pow< 2 >(_1)
template< int Exp, typename Arg >
typename proto::result_of::make_expr<
proto::tag::function // Tag type
, pow_fun< Exp > // First child (by value)
, Arg const & // Second child (by reference)
>::type const
pow(Arg const &arg)
{
return proto::make_expr<proto::tag::function>(
pow_fun<Exp>() // First child (by value)
, boost::ref(arg) // Second child (by reference)
);
}
There are some things to notice about the above code. We use `proto::result_of::make_expr<>` to calculate the return type. The first template parameter is the tag type for the expression node we're building -- in this case, `proto::tag::function`.
Subsequent template parameters to `proto::result_of::make_expr<>` represent child nodes. If a child type is not already a Proto expression, it is automatically made into a terminal with _as_child_. A type such as `pow_fun<Exp>` results in terminal that is held by value, whereas a type like `Arg const &` (note the reference) indicates that the result should be held by reference.
In the function body is the runtime invocation of _make_expr_. It closely mirrors the return type calculation. _make_expr_ requires you to specify the node's tag type as a template parameter. The arguments to the function become the node's children. When a child should be stored by value, nothing special needs to be done. When a child should be stored by reference, you must use the `boost::ref()` function to wrap the argument.
And that's it! _make_expr_ is the lazy person's way to make a lazy funtion.
[endsect]
[/=============================================]
[section Customizing Expressions in Your Domain]
[/=============================================]
In this section, we'll learn all about /domains/. In particular, we'll learn:
* How to associate Proto expressions with a domain,
* How to add members to expressions within a domain,
* How to use a /generator/ to post-process all new expressions created in your domain,
* How to control which operators are overloaded in a domain,
* How to specify capturing policies for child expressions and non-Proto objects, and
* How to make expressions from separate domains interoperate.
[/==============]
[section Domains]
[/==============]
In the [link boost_proto.users_guide.getting_started.hello_calculator Hello Calculator] section, we looked into making calculator expressions directly usable as lambda expressions in calls to STL algorithms, as below:
double data[] = {1., 2., 3., 4.};
// Use the calculator EDSL to square each element ... HOW?
std::transform( data, data + 4, data, _1 * _1 );
The difficulty, if you recall, was that by default Proto expressions don't have interesting behaviors of their own. They're just trees. In particular, the expression `_1 * _1` won't have an `operator()` that takes a double and returns a double like `std::transform()` expects -- unless we give it one. To make this work, we needed to define an expression wrapper type that defined the `operator()` member function, and we needed to associate the wrapper with the calculator /domain/.
In Proto, the term /domain/ refers to a type that associates expressions in that domain to an expression /generator/. The generator is just a function object that accepts an expression and does something to it, like wrapping it in an expression wrapper.
You can also use a domain to associate expressions with a grammar. When you specify a domain's grammar, Proto ensures that all the expressions it generates in that domain conform to the domain's grammar. It does that by disabling any operator overloads that would create invalid expressions.
[endsect]
[/==================================================]
[section:extends The [^extends<>] Expression Wrapper]
[/==================================================]
The first step to giving your calculator expressions extra behaviors is to define a calculator domain. All expressions within the calculator domain will be imbued with calculator-ness, as we'll see.
// A type to be used as a domain tag (to be defined below)
struct calculator_domain;
We use this domain type when extending the _expr_ type, which we do with the _extends_ class template. Here is our expression wrapper, which imbues an expression with calculator-ness. It is described below.
// The calculator<> expression wrapper makes expressions
// function objects.
template< typename Expr >
struct calculator
: proto::extends< Expr, calculator< Expr >, calculator_domain >
{
typedef
proto::extends< Expr, calculator< Expr >, calculator_domain >
base_type;
calculator( Expr const &expr = Expr() )
: base_type( expr )
{}
// This is usually needed because by default, the compiler-
// generated assignment operator hides extends<>::operator=
BOOST_PROTO_EXTENDS_USING_ASSIGN(calculator)
typedef double result_type;
// Hide base_type::operator() by defining our own which
// evaluates the calculator expression with a calculator context.
result_type operator()( double d1 = 0.0, double d2 = 0.0 ) const
{
// As defined in the Hello Calculator section.
calculator_context ctx;
// ctx.args is a vector<double> that holds the values
// with which we replace the placeholders (e.g., _1 and _2)
// in the expression.
ctx.args.push_back( d1 ); // _1 gets the value of d1
ctx.args.push_back( d2 ); // _2 gets the value of d2
return proto::eval(*this, ctx ); // evaluate the expression
}
};
We want calculator expressions to be function objects, so we have to define an `operator()` that takes and returns doubles. The `calculator<>` wrapper above does that with the help of the _extends_ template. The first template to _extends_ parameter is the expression type we are extending. The second is the type of the wrapped expression. The third parameter is the domain that this wrapper is associated with. A wrapper type like `calculator<>` that inherits from _extends_ behaves just like the expression type it has extended, with any additional behaviors you choose to give it.
[note [*Why not just inherit from [^proto::expr<>]?]
You might be thinking that this expression extension business is unnecessarily complicated. After all, isn't this why C++ supports inheritance? Why can't [^calculator<Expr>] just inherit from [^Expr] directly? The reason is because [^Expr], which presumably is an instantiation of _expr_, has expression template-building operator overloads that will be incorrect for derived types. They will store `*this` by reference to `proto::expr<>`, effectively slicing off any derived parts. _extends_ gives your derived types operator overloads that don't slice off your additional members.]
Although not strictly necessary in this case, we bring `extends<>::operator=` into scope with the `BOOST_PROTO_EXTENDS_USING_ASSIGN()` macro. This is really only necessary if you want expressions like `_1 = 3` to create a lazily evaluated assignment. _extends_ defines the appropriate `operator=` for you, but the compiler-generated `calculator<>::operator=` will hide it unless you make it available with the macro.
Note that in the implementation of `calculator<>::operator()`, we evaluate the expression with the `calculator_context` we defined earlier. As we saw before, the context is what gives the operators their meaning. In the case of the calculator, the context is also what defines the meaning of the placeholder terminals.
Now that we have defined the `calculator<>` expression wrapper, we need to wrap the placeholders to imbue them with calculator-ness:
calculator< proto::terminal< placeholder<0> >::type > const _1;
calculator< proto::terminal< placeholder<1> >::type > const _2;
[/=======================================================]
[heading Retaining POD-ness with [^BOOST_PROTO_EXTENDS()]]
[/=======================================================]
To use _extends_, your extension type must derive from _extends_. Unfortunately, that means that your extension type is no longer POD and its instances cannot be /statically initialized/. (See the [link boost_proto.appendices.rationale.static_initialization Static
Initialization] section in the [link boost_proto.appendices.rationale Rationale] appendix for why this matters.) In particular, as defined above, the global placeholder objects `_1` and `_2` will need to be initialized at runtime, which could lead to subtle order of initialization bugs.
There is another way to make an expression extension that doesn't sacrifice POD-ness : the _EXTENDS_ macro. You can use it much like you use _extends_. We can use _EXTENDS_ to keep `calculator<>` a POD and our placeholders statically initialized.
// The calculator<> expression wrapper makes expressions
// function objects.
template< typename Expr >
struct calculator
{
// Use BOOST_PROTO_EXTENDS() instead of proto::extends<> to
// make this type a Proto expression extension.
BOOST_PROTO_EXTENDS(Expr, calculator<Expr>, calculator_domain)
typedef double result_type;
result_type operator()( double d1 = 0.0, double d2 = 0.0 ) const
{
/* ... as before ... */
}
};
With the new `calculator<>` type, we can redefine our placeholders to be statically initialized:
calculator< proto::terminal< placeholder<0> >::type > const _1 = {{{}}};
calculator< proto::terminal< placeholder<1> >::type > const _2 = {{{}}};
We need to make one additional small change to accommodate the POD-ness of our expression extension, which we'll describe below in the section on expression generators.
What does _EXTENDS_ do? It defines a data member of the expression type being extended; some nested typedefs that Proto requires; `operator=`, `operator[]` and `operator()` overloads for building expression templates; and a nested `result<>` template for calculating the return type of `operator()`. In this case, however, the `operator()` overloads and the `result<>` template are not needed because we are defining our own `operator()` in the `calculator<>` type. Proto provides additional macros for finer control over which member functions are defined. We could improve our `calculator<>` type as follows:
// The calculator<> expression wrapper makes expressions
// function objects.
template< typename Expr >
struct calculator
{
// Use BOOST_PROTO_BASIC_EXTENDS() instead of proto::extends<> to
// make this type a Proto expression extension:
BOOST_PROTO_BASIC_EXTENDS(Expr, calculator<Expr>, calculator_domain)
// Define operator[] to build expression templates:
BOOST_PROTO_EXTENDS_SUBSCRIPT()
// Define operator= to build expression templates:
BOOST_PROTO_EXTENDS_ASSIGN()
typedef double result_type;
result_type operator()( double d1 = 0.0, double d2 = 0.0 ) const
{
/* ... as before ... */
}
};
Notice that we are now using _BASIC_EXTENDS_ instead of _EXTENDS_. This just adds the data member and the nested typedefs but not any of the overloaded operators. Those are added separately with _EXTENDS_ASSIGN_ and _EXTENDS_SUBSCRIPT_. We are leaving out the function call operator and the nested `result<>` template that could have been defined with Proto's _EXTENDS_FUNCTION_ macro.
In summary, here are the macros you can use to define expression extensions, and a brief description of each.
[def __expression__ [~expression]]
[def __extension__ [~extension]]
[def __domain__ [~domain]]
[def __extends__ [macroref BOOST_PROTO_EXTENDS]]
[def __basic_extends__ [macroref BOOST_PROTO_BASIC_EXTENDS]]
[table Expression Extension Macros
[[Macro]
[Purpose]]
[[``__basic_extends__(
__expression__
, __extension__
, __domain__
)``]
[Defines a data member of type `__expression__` and some nested typedefs that Proto requires.]]
[[_EXTENDS_ASSIGN_]
[Defines `operator=`. Only valid when preceded by _BASIC_EXTENDS_.]]
[[_EXTENDS_SUBSCRIPT_]
[Defines `operator[]`. Only valid when preceded by _BASIC_EXTENDS_.]]
[[_EXTENDS_FUNCTION_]
[Defines `operator()` and a nested `result<>` template for return type calculation. Only valid when preceded by _BASIC_EXTENDS_.]]
[[``__extends__(
__expression__
, __extension__
, __domain__
)``]
[Equivalent to:``
__basic_extends__(__expression__, __extension__, __domain__)
_EXTENDS_ASSIGN_
_EXTENDS_SUBSCRIPT_
_EXTENDS_FUNCTION_``]]
]
[warning [*Argument-Dependent Lookup and _EXTENDS_]
Proto's operator overloads are defined in the `boost::proto` namespace and are found by argument-dependent lookup (ADL). This usually just works because expressions are made up of types that live in the `boost::proto` namespace. However, sometimes when you use _EXTENDS_ that is not the case. Consider:
`` template<class T>
struct my_complex
{
BOOST_PROTO_EXTENDS(
typename proto::terminal<std::complex<T> >::type
, my_complex<T>
, proto::default_domain
)
};
int main()
{
my_complex<int> c0, c1;
c0 + c1; // ERROR: operator+ not found
}
``
The problem has to do with how argument-dependent lookup works. The type `my_complex<int>` is not associated in any way with the `boost::proto` namespace, so the operators defined there are not considered. (Had we inherited from _extends_ instead of used _EXTENDS_, we would have avoided the problem because inheriting from a type in `boost::proto` namespace is enough to get ADL to kick in.)
So what can we do? By adding an extra dummy template parameter that defaults to a type in the `boost::proto` namespace, we can trick ADL into finding the right operator overloads. The solution looks like this:
`` template<class T, class Dummy = proto::is_proto_expr>
struct my_complex
{
BOOST_PROTO_EXTENDS(
typename proto::terminal<std::complex<T> >::type
, my_complex<T>
, proto::default_domain
)
};
int main()
{
my_complex<int> c0, c1;
c0 + c1; // OK, operator+ found now!
}
``
The type [classref boost::proto::is_proto_expr `proto::is_proto_expr`] is nothing but an empty struct, but by making it a template parameter we make `boost::proto` an associated namespace of `my_complex<int>`. Now ADL can successfully find Proto's operator overloads.
]
[endsect]
[/============================]
[section Expression Generators]
[/============================]
The last thing that remains to be done is to tell Proto that it needs to wrap all of our calculator expressions in our `calculator<>` wrapper. We have already wrapped the placeholders, but we want /all/ expressions that involve the calculator placeholders to be calculators. We can do that by specifying an expression generator when we define our `calculator_domain`, as follows:
// Define the calculator_domain we forward-declared above.
// Specify that all expression in this domain should be wrapped
// in the calculator<> expression wrapper.
struct calculator_domain
: proto::domain< proto::generator< calculator > >
{};
The first template parameter to `proto::domain<>` is the generator. "Generator" is just a fancy name for a function object that accepts an expression and does something to it. `proto::generator<>` is a very simple one --- it wraps an expression in the wrapper you specify. `proto::domain<>` inherits from its generator parameter, so all domains are themselves function objects.
If we used _EXTENDS_ to keep our expression extension type POD, then we need to use `proto::pod_generator<>` instead of `proto::generator<>`, as follows:
// If calculator<> uses BOOST_PROTO_EXTENDS() instead of
// use proto::extends<>, use proto::pod_generator<> instead
// of proto::generator<>.
struct calculator_domain
: proto::domain< proto::pod_generator< calculator > >
{};
[def __Domain__ [~Domain]]
After Proto has calculated a new expression type, it checks the domains of the child expressions. They must match. Assuming they do, Proto creates the new expression and passes it to `__Domain__::operator()` for any additional processing. If we don't specify a generator, the new expression gets passed through unchanged. But since we've specified a generator above, `calculator_domain::operator()` returns `calculator<>` objects.
Now we can use calculator expressions as function objects to STL algorithms, as follows:
double data[] = {1., 2., 3., 4.};
// Use the calculator EDSL to square each element ... WORKS! :-)
std::transform( data, data + 4, data, _1 * _1 );
[endsect]
[/==========================================================]
[section:inhibiting_overloads Controlling Operator Overloads]
[/==========================================================]
By default, Proto defines every possible operator overload for Protofied
expressions. This makes it simple to bang together an EDSL. In some cases, however, the presence of Proto's promiscuous overloads can lead to confusion or worse. When that happens, you'll have to disable some of Proto's overloaded operators. That is done by defining the grammar for your domain and specifying it as the second parameter of the _domain_ template.
In the [link boost_proto.users_guide.getting_started.hello_calculator Hello Calculator] section, we saw an example of a Proto grammar, which is repeated here:
// Define the grammar of calculator expressions
struct calculator_grammar
: proto::or_<
proto::plus< calculator_grammar, calculator_grammar >
, proto::minus< calculator_grammar, calculator_grammar >
, proto::multiplies< calculator_grammar, calculator_grammar >
, proto::divides< calculator_grammar, calculator_grammar >
, proto::terminal< proto::_ >
>
{};
We'll have much more to say about grammars in subsequent sections, but for now, we'll just say that the `calculator_grammar` struct describes a subset of all expression types -- the subset that comprise valid calculator expressions. We would like to prohibit Proto from creating a calculator expression that does not conform to this grammar. We do that by changing the definition of the `calculator_domain` struct.
[def __calculator_grammar__ [*calculator_grammar]]
// Define the calculator_domain. Expressions in the calculator
// domain are wrapped in the calculator<> wrapper, and they must
// conform to the calculator_grammar:
struct calculator_domain
: proto::domain< proto::generator< calculator >, __calculator_grammar__ >
{};
The only new addition is `calculator_grammar` as the second template parameter to the _domain_ template. That has the effect of disabling any of Proto's operator overloads that would create an invalid calculator expression.
Another common use for this feature would be to disable Proto's unary `operator&` overload. It may be surprising for users of your EDSL that they cannot take the address of their expressions! You can very easily disable Proto's unary `operator&` overload for your domain with a very simple grammar, as below:
// For expressions in my_domain, disable Proto's
// unary address-of operator.
struct my_domain
: proto::domain<
proto::generator< my_wrapper >
// A simple grammar that matches any expression that
// is not a unary address-of expression.
, proto::not_< proto::address_of< _ > >
>
{};
The type `proto::not_< proto::address_of< _ > >` is a very simple grammar that matches all expressions except unary address-of expressions. In the section describing Proto's intermediate form, we'll have much more to say about grammars.
[endsect]
[/=========================================================================]
[section:per_domain_as_child Controlling How Child Expressions Are Captured]
[/=========================================================================]
[note This is an advanced topic. Feel free to skip this if you're just getting started with Proto.]
Proto's operator overloads build expressions from sub-expressions. The sub-expressions become children of the new expression. By default, the children are stored in the parent by reference. This section describes how to change that default.
[/-----------------------------------------]
[heading Primer: [^as_child] vs. [^as_expr]]
[/-----------------------------------------]
Proto lets you independently customize the behavior of _as_child_ and _as_expr_. Both accept an object [^x] and return a Proto expression by turning [^x] it into a Proto terminal if necessary. Although similar, the two functions are used in different situations and have subtly different behavior by default. It's important to understand the difference so that you know which to customize to achieve the behavior you want.
To wit: _as_expr_ is typically used by /you/ to turn an object into a Proto expression that is to be held in a local variable, as so:
auto l = proto::as_expr(x); // Turn x into a Proto expression, hold the result in a local
The above works regardless of whether `x` is already a Proto expression or not. The object `l` is guaranteed to be a valid Proto expression. If `x` is a non-Proto object, it is turned into a terminal expression that holds `x` /by value/.[footnote It's not always possible to hold something by value. By default, _as_expr_ makes an exception for functions, abstract types, and iostreams (types derived from `std::ios_base`). These objects are held by reference. All others are held by value, even arrays.] If `x` is a Proto object already, _as_expr_ returns it /by value/ unmodified.
In contrast, _as_child_ is used internally by Proto to pre-process objects before making them children of another expression. Since it's internal to Proto, you don't see it explicitly, but it's there behind the scenes in expressions like this:
x + y; // Consider that y is a Proto expression, but x may or may not be.
In this case, Proto builds a plus node from the two children. Both are pre-processed by passing them to _as_child_ before making them children of the new node. If `x` is not a Proto expression, it becomes one by being wrapped in a Proto terminal that holds it /by reference/. If `x` is already a Proto expression, _as_child_ returns it /by reference/ unmodified. Contrast this with the above description for _as_expr_.
The table below summarizes the above description.
[table proto::as_expr() vs. proto::as_child()
[[[*Function]] [[*When [^t] is not a Proto expr...]] [[*When [^t] is a Proto expr...]]]
[[[^proto::as_expr(t)]] [Return (by value) a new Proto terminal holding [^t] by value.] [Return [^t] by value unmodified.]]
[[[^proto::as_child(t)]] [Return (by value) a new Proto terminal holding [^t] by reference.] [Return [^t] by reference unmodified.]]
]
[note There is one important place where Proto uses both `as_expr` /and/ `as_child`: _make_expr_. The _make_expr_ function requires you to specify for each child whether it should be held by value or by reference. Proto uses _as_expr_ to pre-process the children to be held by value, and _as_child_ for the ones to be held by reference.]
Now that you know what _as_child_ and _as_expr_ are, where they are used, and what they do by default, you may decide that one or both of these functions should have different behavior for your domain. For instance, given the above description of _as_child_, the following code is always wrong:
proto::literal<int> i(0);
auto l = i + 42; // This is WRONG! Don't do this.
Why is this wrong? Because _as_child_ will turn the integer literal 42 into a Proto terminal that holds a reference to a temporary integer initialized with 42. The lifetime of that temporary ends at the semicolon, guaranteeing that the local `l` is left holding a dangling reference to a deceased integer. What to do? One answer is to use _deep_copy_. Another is to customize the behavior of _as_child_ for your domain. Read on for the details.
[/-----------------------------]
[heading Per-Domain [^as_child]]
[/-----------------------------]
To control how Proto builds expressions out of sub-expressions in your domain, define your domain as usual, and then define a nested `as_child<>` class template within it, as follows:
[def __unspecified_expression_type__ ['[^unspecified-Proto-expr-type]]]
[def __unspecified_expression__ ['[^unspecified-Proto-expr-object]]]
class my_domain
: proto::domain< my_generator, my_grammar >
{
// Here is where you define how Proto should handle
// sub-expressions that are about to be glommed into
// a larger expression.
template< typename T >
struct as_child
{
typedef __unspecified_expression_type__ result_type;
result_type operator()( T & t ) const
{
return __unspecified_expression__;
}
};
};
There's one important thing to note: in the above code, the template parameter [^T] may or may not be a Proto expression type, but the result /must/ be a Proto expression type, or a reference to one. That means that most user-defined [^as_child<>] templates will need to check whether [^T] is an expression or not (using _is_expr_), and then turn non-expressions into Proto terminals by wrapping them as `proto::terminal< /* ... */ >::type` or equivalent.
[/----------------------------]
[heading Per-Domain [^as_expr]]
[/----------------------------]
Although less common, Proto also lets you customize the behavior of _as_expr_ on a per-domain basis. The technique is identical to that for [^as_child]. See below:
class my_domain
: proto::domain< my_generator, my_grammar >
{
// Here is where you define how Proto should handle
// objects that are to be turned into expressions
// fit for storage in local variables.
template< typename T >
struct as_expr
{
typedef __unspecified_expression_type__ result_type;
result_type operator()( T & t ) const
{
return __unspecified_expression__;
}
};
};
[/--------------------------------------------]
[heading Making Proto Expressions [^auto]-safe]
[/--------------------------------------------]
Let's look again at the problem described above involving the C++11 `auto` keyword and the default behavior of _as_child_.
proto::literal<int> i(0);
auto l = i + 42; // This is WRONG! Don't do this.
Recall that the problem is the lifetime of the temporary integer created to hold the value 42. The local `l` will be left holding a dangling reference to it after its lifetime is over. What if we want Proto to make expressions safe to store this way in local variables? We can do so very easily by making _as_child_ behave just like _as_expr_. The following code achieves this:
template< typename E >
struct my_expr;
struct my_generator
: proto::pod_generator< my_expr >
{};
struct my_domain
: proto::domain< my_generator >
{
// Make as_child() behave like as_expr() in my_domain.
// (proto_base_domain is a typedef for proto::domain< my_generator >
// that is defined in proto::domain<>.)
template< typename T >
struct as_child
: proto_base_domain::as_expr< T >
{};
};
template< typename E >
struct my_expr
{
BOOST_PROTO_EXTENDS( E, my_expr< E >, my_domain )
};
/* ... */
proto::literal< int, my_domain > i(0);
auto l = i + 42; // OK! Everything is stored by value here.
Notice that `my_domain::as_child<>` simply defers to the default implementation of `as_expr<>` found in _domain_. By simply cross-wiring our domain's `as_child<>` to `as_expr<>`, we guarantee that all terminals that can be held by value are, and that all child expressions are also held by value. This increases copying and may incur a runtime performance cost, but it eliminates any spector of lifetime management issues.
For another example, see the definition of `lldomain` in [^libs/proto/example/lambda.hpp]. That example is a complete reimplementation of the Boost Lambda Library (BLL) on top of Boost.Proto. The function objects the BLL generates are safe to be stored in local variables. To emulate this with Proto, the `lldomain` cross-wires `as_child<>` to `as_expr<>` as above, but with one extra twist: objects with array type are also stored by reference. Check it out.
[endsect]
[/======================================================]
[section:subdomains EDSL Interoperatability: Sub-Domains]
[/======================================================]
[note This is an advanced topic. Feel free to skip this if you're just getting started with Proto.]
The ability to /compose/ different EDSLs is one of their most exciting features. Consider how you build a parser using yacc. You write your grammar rules in yacc's domain-specific language. Then you embed semantic actions written in C within your grammar. Boost's Spirit parser generator gives you the same ability. You write grammar rules using Spirit.Qi and embed semantic actions using the Phoenix library. Phoenix and Spirit are both Proto-based domain-specific languages with their own distinct syntax and semantics. But you can freely embed Phoenix expressions within Spirit expressions. This section describes Proto's /sub-domain/ feature that lets you define families of interoperable domains.
[/======================]
[heading Dueling Domains]
[/======================]
When you try to create an expression from two sub-expressions in different domains, what is the domain of the resulting expression? This is the fundamental problem that is addressed by sub-domains. Consider the following code:
#include <boost/proto/proto.hpp>
namespace proto = boost::proto;
// Forward-declare two expression wrappers
template<typename E> struct spirit_expr;
template<typename E> struct phoenix_expr;
// Define two domains
struct spirit_domain : proto::domain<proto::generator<spirit_expr> > {};
struct phoenix_domain : proto::domain<proto::generator<phoenix_expr> > {};
// Implement the two expression wrappers
template<typename E>
struct spirit_expr
: proto::extends<E, spirit_expr<E>, spirit_domain>
{
spirit_expr(E const &e = E()) : spirit_expr::proto_extends(e) {}
};
template<typename E>
struct phoenix_expr
: proto::extends<E, phoenix_expr<E>, phoenix_domain>
{
phoenix_expr(E const &e = E()) : phoenix_expr::proto_extends(e) {}
};
int main()
{
proto::literal<int, spirit_domain> sp(0);
proto::literal<int, phoenix_domain> phx(0);
// Whoops! What does it mean to add two expressions in different domains?
sp + phx; // ERROR
}
Above, we define two domains called `spirit_domain` and `phoenix_domain` and declare two int literals in each. Then we try to compose them into a larger expression using Proto's binary plus operator, and it fails. Proto can't figure out whether the resulting expression should be in the Spirit domain or the Phoenix domain, and thus whether it should be an instance of `spirit_expr<>` or `phoenix_expr<>`. We have to tell Proto how to resolve the conflict. We can do that by declaring that Phoenix is a sub-domain of Spirit as in the following definition of `phoenix_domain`:
[def __spirit_domain__ [*spirit_domain]]
// Declare that phoenix_domain is a sub-domain of spirit_domain
struct phoenix_domain
: proto::domain<proto::generator<phoenix_expr>, proto::_, __spirit_domain__>
{};
The third template parameter to _domain_ is the super-domain. By defining `phoenix_domain` as above, we are saying that Phoenix expressions can be combined with Spirit expressions, and that when that happens, the resulting expression should be a Spirit expression.
[note If you are wondering what the purpose of `proto::_` is in the definition of `phoenix_domain` above, recall that the second template parameter to _domain_ is the domain's grammar. ["`proto::_`] is the default and signifies that the domain places no restrictions on the expressions that are valid within it.]
[/------------------------]
[heading Domain Resolution]
[/------------------------]
When there are multiple domains in play within a given expression, Proto uses some rules to figure out which domain "wins". The rules are loosely modeled on the rules for C++ inheritance. `Phoenix_domain` is a sub-domain of `spirit_domain`. You can liken that to a derived/base relationship that gives Phoenix expressions a kind of implicit conversion to Spirit expressions. And since Phoenix expressions can be "converted" to Spirit expressions, they can be freely combined with Spirit expressions and the result is a Spirit expression.
[note Super- and sub-domains are not actually implemented using inheritance. This is only a helpful mental model.]
The analogy with inheritance holds even in the case of three domains when two are sub-domains of the third. Imagine another domain called `foobar_domain` that was also a sub-domain of `spirit_domain`. Expressions in the `foobar_domain` could be combined with expressions in the `phoenix_domain` and the resulting expression would be in the `spirit_domain`. That's because expressions in the two sub-domains both have "conversions" to the super-domain, so the operation is allowed and the super-domain wins.
[/-------------------------]
[heading The Default Domain]
[/-------------------------]
When you don't assign a Proto expression to a particular domain, Proto considers it a member of the so-called default domain, `proto::default_domain`. Even non-Proto objects are treated as terminals in the default domain. Consider:
int main()
{
proto::literal<int, spirit_domain> sp(0);
// Add 1 to a spirit expression. Result is a spirit expression.
sp + 1;
}
Expressions in the default domain (or non-expressions like [^1]) have a kind of implicit conversion to expressions every other domain type. What's more, you can define your domain to be a sub-domain of the default domain. In so doing, you give expressions in your domain conversions to expressions in every other domain. This is like a ["free love] domain, because it will freely mix with all other domains.
Let's think again about the Phoenix EDSL. Since it provides generally useful lambda functionality, it's reasonable to assume that lots of other EDSLs besides Spirit might want the ability to embed Phoenix expressions. In other words, `phoenix_domain` should be a sub-domain of `proto::default_domain`, not `spirit_domain`:
// Declare that phoenix_domain is a sub-domain of proto::default_domain
struct phoenix_domain
: proto::domain<proto::generator<phoenix_expr>, proto::_, proto::default_domain>
{};
That's much better. Phoenix expressions can now be put anywhere.
[/-------------------------]
[heading Sub-Domain Summary]
[/-------------------------]
Use Proto sub-domains to make it possible to mix expressions from multiple domains. And when you want expressions in your domain to freely combine with /all/ expressions, make it a sub-domain of `proto::default_domain`.
[endsect]
[endsect]
[section:define_operators Adapting Existing Types to Proto]
The preceding discussions of defining Proto front ends have all made a big assumption: that you have the luxury of defining everything from scratch. What happens if you have existing types, say a matrix type and a vector type, that you would like to treat as if they were Proto terminals? Proto usually trades only in its own expression types, but with _DEFINE_OPERATORS_, it can accomodate your custom terminal types, too.
Let's say, for instance, that you have the following types and that you can't modify then to make them ["native] Proto terminal types.
namespace math
{
// A matrix type ...
struct matrix { /*...*/ };
// A vector type ...
struct vector { /*...*/ };
}
You can non-intrusively make objects of these types Proto terminals by defining the proper operator overloads using _DEFINE_OPERATORS_. The basic procedure is as follows:
# Define a trait that returns true for your types and false for all others.
# Reopen the namespace of your types and use _DEFINE_OPERATORS_ to define a set of
operator overloads, passing the name of the trait as the first macro parameter,
and the name of a Proto domain (e.g., _default_domain_) as the second.
The following code demonstrates how it works.
namespace math
{
template<typename T>
struct is_terminal
: mpl::false_
{};
// OK, "matrix" is a custom terminal type
template<>
struct is_terminal<matrix>
: mpl::true_
{};
// OK, "vector" is a custom terminal type
template<>
struct is_terminal<vector>
: mpl::true_
{};
// Define all the operator overloads to construct Proto
// expression templates, treating "matrix" and "vector"
// objects as if they were Proto terminals.
BOOST_PROTO_DEFINE_OPERATORS(is_terminal, proto::default_domain)
}
The invocation of the _DEFINE_OPERATORS_ macro defines a complete set of operator overloads that treat `matrix` and `vector` objects as if they were Proto terminals. And since the operators are defined in the same namespace as the `matrix` and `vector` types, the operators will be found by argument-dependent lookup. With the code above, we can now construct expression templates with matrices and vectors, as shown below.
math::matrix m1;
math::vector v1;
proto::literal<int> i(0);
m1 * 1; // custom terminal and literals are OK
m1 * i; // custom terminal and Proto expressions are OK
m1 * v1; // two custom terminals are OK, too.
[endsect]
[/=======================================================================]
[section:code_repetition Generating Repetitive Code with the Preprocessor]
[/=======================================================================]
Sometimes as an EDSL designer, to make the lives of your users easy, you have to make your own life hard. Giving your users natural and flexible syntax often involves writing large numbers of repetitive function overloads. It can be enough to give you repetitive stress injury! Before you hurt yourself, check out the macros Proto provides for automating many repetitive code-generation chores.
Imagine that we are writing a lambda EDSL, and we would like to enable syntax for constructing temporary objects of any type using the following syntax:
// A lambda expression that takes two arguments and
// uses them to construct a temporary std::complex<>
construct< std::complex<int> >( _1, _2 )
For the sake of the discussion, imagine that we already have a function object template `construct_impl<>` that accepts arguments and constructs new objects from them. We would want the above lambda expression to be equivalent to the following:
// The above lambda expression should be roughly equivalent
// to the following:
proto::make_expr<proto::tag::function>(
construct_impl<std::complex<int> >() // The function to invoke lazily
, boost::ref(_1) // The first argument to the function
, boost::ref(_2) // The second argument to the function
);
We can define our `construct()` function template as follows:
template<typename T, typename A0, typename A1>
typename proto::result_of::make_expr<
proto::tag::function
, construct_impl<T>
, A0 const &
, A1 const &
>::type const
construct(A0 const &a0, A1 const &a1)
{
return proto::make_expr<proto::tag::function>(
construct_impl<T>()
, boost::ref(a0)
, boost::ref(a1)
);
}
This works for two arguments, but we would like it to work for any number of arguments, up to (_MAX_ARITY_ - 1). (Why "- 1"? Because one child is taken up by the `construct_impl<T>()` terminal leaving room for only (_MAX_ARITY_ - 1) other children.)
For cases like this, Proto provides the _REPEAT_ and _REPEAT_FROM_TO_ macros. To use it, we turn the function definition above into a macro as follows:
#define M0(N, typename_A, A_const_ref, A_const_ref_a, ref_a) \
template<typename T, typename_A(N)> \
typename proto::result_of::make_expr< \
proto::tag::function \
, construct_impl<T> \
, A_const_ref(N) \
>::type const \
construct(A_const_ref_a(N)) \
{ \
return proto::make_expr<proto::tag::function>( \
construct_impl<T>() \
, ref_a(N) \
); \
}
Notice that we turned the function into a macro that takes 5 arguments. The first is the current iteration number. The rest are the names of other macros that generate different sequences. For instance, Proto passes as the second parameter the name of a macro that will expand to `typename A0, typename A1, ...`.
Now that we have turned our function into a macro, we can pass the macro to _REPEAT_FROM_TO_. Proto will invoke it iteratively, generating all the function overloads for us.
// Generate overloads of construct() that accept from
// 1 to BOOST_PROTO_MAX_ARITY-1 arguments:
BOOST_PROTO_REPEAT_FROM_TO(1, BOOST_PROTO_MAX_ARITY, M0)
#undef M0
[/============================]
[heading Non-Default Sequences]
[/============================]
As mentioned above, Proto passes as the last 4 arguments to your macro the names of other macros that generate various sequences. The macros _REPEAT_ and _REPEAT_FROM_TO_ select defaults for these parameters. If the defaults do not meet your needs, you can use _REPEAT_EX_ and _REPEAT_FROM_TO_EX_ and pass different macros that generate different sequences. Proto defines a number of such macros for use as parameters to _REPEAT_EX_ and _REPEAT_FROM_TO_EX_. Check the reference section for [headerref boost/proto/repeat.hpp] for all the details.
Also, check out _LOCAL_ITERATE_. It works similarly to _REPEAT_ and friends, but it can be easier to use when you want to change one macro argument and accept defaults for the others.
[endsect]
[endsect]

View File

@@ -0,0 +1,18 @@
[/
/ Copyright (c) 2008 Eric Niebler
/
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
/]
[section:getting_started Getting Started]
[include installation.qbk]
[include conventions.qbk]
[include hello_world.qbk]
[include calculator.qbk]
[endsect]

View File

@@ -0,0 +1,95 @@
[/
/ Copyright (c) 2008 Eric Niebler
/
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
/]
[/===============]
[section Glossary]
[/===============]
[def _T_ [~T]]
[template anchor[x] '''<anchor id="boost_proto.users_guide.glossary.'''[x]'''" />''']
[variablelist
[ [ [anchor callable_transform] callable transform]
[A transform of the form `R(A0,A1,...)` (i.e., a function type) where
`proto::is_callable<R>::value` is `true`. `R` is treated as a polymorphic
function object and the arguments are treated as transforms that yield the
arguments to the function object.] ]
[ [ [anchor context] context]
[In Proto, the term /context/ refers to an object that can be passed, along
with an expression to evaluate, to the `proto::eval()` function. The context
determines how the expression is evaluated. All context structs define a
nested `eval<>` template that, when instantiated with a node tag type (e.g.,
`proto::tag::plus`), is a binary polymorphic function object that accepts an
expression of that type and the context object. In this way, contexts
associate behaviors with expression nodes.] ]
[ [ [anchor domain] domain]
[In Proto, the term /domain/ refers to a type that associates expressions
within that domain with a /generator/ for that domain and optionally a
/grammar/ for the domain. Domains are used primarily to imbue expressions
within that domain with additional members and to restrict Proto's operator
overloads such that expressions not conforming to the domain's grammar are
never created. Domains are empty structs that inherit from
`proto::domain<>`.]]
[ [ [anchor dsl] domain-specific language]
[A programming language that targets a particular problem space by providing
programming idioms, abstractions and constructs that match the constructs
within that problem space.]]
[ [ [anchor edsl] embedded domain-specific language]
[A domain-specific language implemented as a library. The language in which
the library is written is called the "host" language, and the language
implemented by the library is called the "embedded" language.]]
[ [ [anchor expression] expression]
[In Proto, an /expression/ is a heterogeneous tree where each node is either
an instantiation of `boost::proto::expr<>`, `boost::proto::basic_expr<>` or
some type that is an extension (via `boost::proto::extends<>` or
`BOOST_PROTO_EXTENDS()`) of such an instantiation.]]
[ [ [anchor expression_template] expression template]
[A C++ technique using templates and operator overloading to cause
expressions to build trees that represent the expression for lazy evaluation
later, rather than evaluating the expression eagerly. Some C++ libraries use
expression templates to build embedded domain-specific languages.]]
[ [ [anchor generator] generator]
[In Proto, a /generator/ is a unary polymorphic function object that you
specify when defining a /domain/. After constructing a new expression, Proto
passes the expression to your domain's generator for further processing.
Often, the generator wraps the expression in an extension wrapper that adds
additional members to it.]]
[ [ [anchor grammar] grammar]
[In Proto, a /grammar/ is a type that describes a subset of Proto expression
types. Expressions in a domain must conform to that domain's grammar. The
`proto::matches<>` metafunction evaluates whether an expression type matches
a grammar. Grammars are either primitives such as `proto::_`, composites
such as `proto::plus<>`, control structures such as `proto::or_<>`, or some
type derived from a grammar.]]
[ [ [anchor object_transform] object transform]
[A transform of the form `R(A0,A1,...)` (i.e., a function type) where
`proto::is_callable<R>::value` is `false`. `R` is treated as the type of an
object to construct and the arguments are treated as transforms that yield
the parameters to the constructor.]]
[ [ [anchor polymorphic_function_object] polymorphic function object]
[An instance of a class type with an overloaded function call operator and a
nested `result_type` typedef or `result<>` template for calculating the
return type of the function call operator.]]
[ [ [anchor primitive_transform] primitive transform]
[A type that defines a kind of polymorphic function object that takes three
arguments: expression, state, and data. Primitive transforms can be used to
compose callable transforms and object transforms.]]
[ [ [anchor subdomain] sub-domain]
[A sub-domain is a domain that declares another domain as its super-domain.
Expressions in sub-domains can be combined with expressions in the
super-domain, and the resulting expression is in the super-domain.]]
[ [ [anchor transform] transform]
[Transforms are used to manipulate expression trees. They come in three
flavors: primitive transforms, callable transforms, or object transforms. A
transform `_T_` can be made into a ternary polymorphic function object with
`proto::when<>`, as in `proto::when<proto::_, _T_>`. Such a function object
accepts /expression/, /state/, and /data/ parameters, and computes a result
from them.]]
]
[endsect]

View File

@@ -0,0 +1,84 @@
[/
/ Copyright (c) 2008 Eric Niebler
/
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
/]
[/==================]
[section Hello World]
[/==================]
Below is a very simple program that uses Proto to build an expression template
and then execute it.
#include <iostream>
#include <boost/proto/proto.hpp>
#include <boost/typeof/std/ostream.hpp>
using namespace boost;
proto::terminal< std::ostream & >::type cout_ = { std::cout };
template< typename Expr >
void evaluate( Expr const & expr )
{
proto::default_context ctx;
proto::eval(expr, ctx);
}
int main()
{
evaluate( cout_ << "hello" << ',' << " world" );
return 0;
}
This program outputs the following:
[pre
hello, world
]
This program builds an object representing the output operation and passes
it to an `evaluate()` function, which then executes it.
The basic idea of expression templates is to overload all the operators so
that, rather than evaluating the expression immediately, they build a tree-like
representation of the expression so that it can be evaluated later. For each
operator in an expression, at least one operand must be Protofied in order
for Proto's operator overloads to be found. In the expression ...
cout_ << "hello" << ',' << " world"
... the Protofied sub-expression is `cout_`, which is the Proto-ification of
`std::cout`. The presence of `cout_` "infects" the expression, and brings
Proto's tree-building operator overloads into consideration. Any literals in
the expression are then Protofied by wrapping them in a Proto terminal before
they are combined into larger Proto expressions.
Once Proto's operator overloads have built the expression tree, the expression
can be lazily evaluated later by walking the tree. That is what `proto::eval()`
does. It is a general tree-walking expression evaluator, whose behavior is
customizable via a /context/ parameter. The use of _default_context_ assigns
the standard meanings to the operators in the expression. (By using a different
context, you could give the operators in your expressions different semantics.
By default, Proto makes no assumptions about what operators actually /mean/.)
[/==============================]
[heading Proto Design Philosophy]
[/==============================]
Before we continue, let's use the above example to illustrate an important
design principle of Proto's. The expression template created in the ['hello
world] example is totally general and abstract. It is not tied in any way to
any particular domain or application, nor does it have any particular meaning
or behavior on its own, until it is evaluated in a /context/. Expression
templates are really just heterogeneous trees, which might mean something in
one domain, and something else entirely in a different one.
As we'll see later, there is a way to create Proto expression trees that are
['not] purely abstract, and that have meaning and behaviors independent of any
context. There is also a way to control which operators are overloaded for your
particular domain. But that is not the default behavior. We'll see later why
the default is often a good thing.
[endsect]

View File

@@ -0,0 +1,69 @@
[/
/ Copyright (c) 2008 Eric Niebler
/
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
/]
[section:history Appendix B: History]
[variablelist
[
[August 13, 2010]
[Boost 1.44: Proto gets sub-domains and per-domain control of _as_expr_
and _as_child_ to meet the needs of Phoenix3.]
]
[
[August 11, 2008]
[Proto v4 is merged to Boost trunk with more powerful transform protocol.]
]
[
[April 7, 2008]
[Proto is accepted into Boost.]
]
[
[March 1, 2008]
[Proto's Boost review begins.]
]
[
[January 11, 2008]
[Boost.Proto v3 brings separation of grammars and transforms and a
"round" lambda syntax for defining transforms in-place.]
]
[
[April 15, 2007]
[Boost.Xpressive is ported from Proto compilers to Proto transforms.
Support for old Proto compilers is dropped.]
]
[
[April 4, 2007]
[Preliminary submission of Proto to Boost.]
]
[
[December 11, 2006]
[The idea for transforms that decorate grammar rules is born in a private
email discussion with Joel de Guzman and Hartmut Kaiser. The first
transforms are committed to CVS 5 days later on December 16.]
]
[
[November 1, 2006]
[The idea for `proto::matches<>` and the whole grammar facility is
hatched during a discussion with Hartmut Kaiser on the spirit-devel list.
The first version of `proto::matches<>` is checked into CVS 3 days later.
Message is [@http://osdir.com/ml/parsers.spirit.devel/2006-11/msg00003.html here].]
]
[
[October 28, 2006]
[Proto is reborn, this time with a uniform expression types that are POD.
Announcement is [@http://lists.boost.org/Archives/boost/2006/10/112453.php here].]
]
[
[April 20, 2005]
[Proto is born as a major refactorization of Boost.Xpressive's
meta-programming. Proto offers expression types, operator overloads and
"compilers", an early formulation of what later became transforms.
Announcement is [@http://lists.boost.org/Archives/boost/2005/04/85256.php here].]
]
]
[endsect]

View File

@@ -0,0 +1,174 @@
[/
/ Copyright (c) 2008 Eric Niebler
/
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
/]
[section:implementation Appendix D: Implementation Notes]
[section:sfinae Quick-n-Dirty Type Categorization]
Much has already been written about dispatching on type traits using
SFINAE (Substitution Failure Is Not An Error) techniques in C++. There
is a Boost library, Boost.Enable_if, to make the technique idiomatic.
Proto dispatches on type traits extensively, but it doesn't use
`enable_if<>` very often. Rather, it dispatches based on the presence
or absence of nested types, often typedefs for void.
Consider the implementation of `is_expr<>`. It could have been written
as something like this:
template<typename T>
struct is_expr
: is_base_and_derived<proto::some_expr_base, T>
{};
Rather, it is implemented as this:
template<typename T, typename Void = void>
struct is_expr
: mpl::false_
{};
template<typename T>
struct is_expr<T, typename T::proto_is_expr_>
: mpl::true_
{};
This relies on the fact that the specialization will be preferred
if `T` has a nested `proto_is_expr_` that is a typedef for `void`.
All Proto expression types have such a nested typedef.
Why does Proto do it this way? The reason is because, after running
extensive benchmarks while trying to improve compile times, I have
found that this approach compiles faster. It requires exactly one
template instantiation. The other approach requires at least 2:
`is_expr<>` and `is_base_and_derived<>`, plus whatever templates
`is_base_and_derived<>` may instantiate.
[endsect]
[section:function_arity Detecting the Arity of Function Objects]
In several places, Proto needs to know whether or not a function
object `Fun` can be called with certain parameters and take a
fallback action if not. This happens in _callable_context_ and
in the _call_ transform. How does Proto know? It involves some
tricky metaprogramming. Here's how.
Another way of framing the question is by trying to implement
the following `can_be_called<>` Boolean metafunction, which
checks to see if a function object `Fun` can be called with
parameters of type `A` and `B`:
template<typename Fun, typename A, typename B>
struct can_be_called;
First, we define the following `dont_care` struct, which has an
implicit conversion from anything. And not just any implicit
conversion; it has a ellipsis conversion, which is the worst possible
conversion for the purposes of overload resolution:
struct dont_care
{
dont_care(...);
};
We also need some private type known only to us with an overloaded
comma operator (!), and some functions that detect the presence of
this type and return types with different sizes, as follows:
struct private_type
{
private_type const &operator,(int) const;
};
typedef char yes_type; // sizeof(yes_type) == 1
typedef char (&no_type)[2]; // sizeof(no_type) == 2
template<typename T>
no_type is_private_type(T const &);
yes_type is_private_type(private_type const &);
Next, we implement a binary function object wrapper with a very
strange conversion operator, whose meaning will become clear later.
template<typename Fun>
struct funwrap2 : Fun
{
funwrap2();
typedef private_type const &(*pointer_to_function)(dont_care, dont_care);
operator pointer_to_function() const;
};
With all of these bits and pieces, we can implement `can_be_called<>` as
follows:
template<typename Fun, typename A, typename B>
struct can_be_called
{
static funwrap2<Fun> &fun;
static A &a;
static B &b;
static bool const value = (
sizeof(no_type) == sizeof(is_private_type( (fun(a,b), 0) ))
);
typedef mpl::bool_<value> type;
};
The idea is to make it so that `fun(a,b)` will always compile by adding
our own binary function overload, but doing it in such a way that we can
detect whether our overload was selected or not. And we rig it so that
our overload is selected if there is really no better option. What follows
is a description of how `can_be_called<>` works.
We wrap `Fun` in a type that has an implicit conversion to a pointer to
a binary function. An object `fun` of class type can be invoked as
`fun(a, b)` if it has such a conversion operator, but since it involves
a user-defined conversion operator, it is less preferred than an
overloaded `operator()`, which requires no such conversion.
The function pointer can accept any two arguments by virtue
of the `dont_care` type. The conversion sequence for each argument is
guaranteed to be the worst possible conversion sequence: an implicit
conversion through an ellipsis, and a user-defined conversion to
`dont_care`. In total, it means that `funwrap2<Fun>()(a, b)` will
always compile, but it will select our overload only if there really is
no better option.
If there is a better option --- for example if `Fun` has an overloaded
function call operator such as `void operator()(A a, B b)` --- then
`fun(a, b)` will resolve to that one instead. The question now is how
to detect which function got picked by overload resolution.
Notice how `fun(a, b)` appears in `can_be_called<>`: `(fun(a, b), 0)`.
Why do we use the comma operator there? The reason is because we are
using this expression as the argument to a function. If the return type
of `fun(a, b)` is `void`, it cannot legally be used as an argument to
a function. The comma operator sidesteps the issue.
This should also make plain the purpose of the overloaded comma operator
in `private_type`. The return type of the pointer to function is
`private_type`. If overload resolution selects our overload, then the
type of `(fun(a, b), 0)` is `private_type`. Otherwise, it is `int`.
That fact is used to dispatch to either overload of `is_private_type()`,
which encodes its answer in the size of its return type.
That's how it works with binary functions. Now repeat the above process
for functions up to some predefined function arity, and you're done.
[endsect]
[/
[section:ppmp_vs_tmp Avoiding Template Instiations With The Preprocessor]
TODO
[endsect]
]
[endsect]

View File

@@ -0,0 +1,52 @@
[/
/ Copyright (c) 2008 Eric Niebler
/
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
/]
[/=======================]
[section Installing Proto]
[/=======================]
[/====================]
[heading Getting Proto]
[/====================]
You can get Proto
by downloading Boost (Proto is in version 1.37 and later),
or by accessing Boost's SVN repository on SourceForge.net. Just go to
[@http://svn.boost.org/trac/boost/wiki/BoostSubversion]
and follow the instructions there for anonymous SVN access.
[/==========================]
[heading Building with Proto]
[/==========================]
Proto is a header-only template library, which means you don't need to alter
your build scripts or link to any separate lib file to use it. All you need
to do is `#include <boost/proto/proto.hpp>`. Or, you might decide to just
include the core of Proto (`#include <boost/proto/core.hpp>`) and whichever
contexts and transforms you happen to use.
[/===================]
[heading Requirements]
[/===================]
Proto depends on Boost. You must use either Boost version 1.34.1 or higher,
or the version in SVN trunk.
[/==========================]
[heading Supported Compilers]
[/==========================]
Currently, Boost.Proto is known to work on the following compilers:
* Visual C++ 8 and higher
* GNU C++ 3.4 and higher
* Intel on Linux 8.1 and higher
* Intel on Windows 9.1 and higher
[note Please send any questions, comments and bug reports to eric <at> boostpro <dot> com.]
[endsect]

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,69 @@
[/
/ Copyright (c) 2008 Eric Niebler
/
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
/]
[section Preface]
[:["There are more things in heaven and earth, Horatio, than are dreamt of in your
philosophy.]]
[:[*['-- William Shakespeare]]]
[heading Description]
Proto is a framework for building Embedded Domain-Specific Languages in C++. It provides tools for constructing, type-checking, transforming and executing ['expression templates][footnote See [@http://en.wikipedia.org/wiki/Expression_templates Expression Templates]].
More specifically, Proto provides:
* An expression tree data structure.
* A mechanism for giving expressions additional behaviors and members.
* Operator overloads for building the tree from an expression.
* Utilities for defining the grammar to which an expression must conform.
* An extensible mechanism for immediately executing an expression template.
* An extensible set of tree transformations to apply to expression trees.
[heading Motivation]
Expression Templates are an advanced technique that C++ library developers use to define embedded mini-languages that target specific problem domains. The technique has been used to create efficient and easy-to-use libraries for linear algebra as well as to define C++ parser generators with a readable syntax. But developing such a library involves writing an inordinate amount of unreadable and unmaintainable template mumbo-jumbo. Boost.Proto eases the development of [link boost_proto.users_guide.glossary.edsl domain-specific embedded languages (EDSLs)]. Use Proto to define the primitives of your mini-language and let Proto handle the operator overloading and the construction of the expression parse tree. Immediately evaluate the expression tree by passing it a function object. Or transform the expression tree by defining the grammar of your mini-language, decorated with an assortment of tree transforms provided by Proto or defined by you. Then use the grammar to give your users short and readable syntax errors for invalid expressions! No more mumbo-jumbo -- an expression template library developed with Proto is declarative and readable.
In short, Proto is an EDSL for defining EDSLs.
[/====================================]
[heading How to Use This Documentation]
[/====================================]
This documentation makes use of the following naming and formatting conventions.
* Code is in `fixed width font` and is syntax-highlighted.
* Replaceable text that you will need to supply is in [~italics].
* If a name refers to a free function, it is specified like this:
`free_function()`; that is, it is in code font and its name is followed by `()`
to indicate that it is a free function.
* If a name refers to a class template, it is specified like this:
`class_template<>`; that is, it is in code font and its name is followed by `<>`
to indicate that it is a class template.
* If a name refers to a function-like macro, it is specified like this: `MACRO()`;
that is, it is uppercase in code font and its name is followed by `()` to
indicate that it is a function-like macro. Object-like macros appear without the
trailing `()`.
* Names that refer to /concepts/ in the generic programming sense are
specified in CamelCase.
[note In addition, notes such as this one specify non-essential information that
provides additional background or rationale.]
Finally, you can mentally add the following to any code fragments in this document:
// Include all of Proto
#include <boost/proto/proto.hpp>
// Create some namespace aliases
namespace mpl = boost::mpl;
namespace fusion = boost::fusion;
namespace proto = boost::proto;
// Allow unqualified use of Proto's wildcard pattern
using proto::_;
[endsect]

View File

@@ -0,0 +1,10 @@
#!/bin/sh
# Copyright 2012 Eric Niebler
#
# 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)
rsync --delete --rsh=ssh --recursive -p html/* eric_niebler,boost-sandbox@web.sourceforge.net:/home/groups/b/bo/boost-sandbox/htdocs/libs/proto/doc/html
rsync --delete --rsh=ssh --recursive -p src/* eric_niebler,boost-sandbox@web.sourceforge.net:/home/groups/b/bo/boost-sandbox/htdocs/libs/proto/doc/src

View File

@@ -0,0 +1,306 @@
[library Boost.Proto
[quickbook 1.3]
[authors [Niebler, Eric]]
[copyright 2008 Eric Niebler]
[category template]
[id proto]
[dirname proto]
[purpose
Generic expression template, grammar and
tree-transformation framework.
]
[license
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
[@http://www.boost.org/LICENSE_1_0.txt])
]
]
[/
/ Copyright (c) 2008 Eric Niebler
/
/ 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)
/]
[/ QuickBook Document version 1.3 ]
[/ Images ]
[def __note__ [$images/note.png]]
[def __alert__ [$images/caution.png]]
[def __detail__ [$images/note.png]]
[def __tip__ [$images/tip.png]]
[/ Links ]
[def _PETE_
[@http://acts.nersc.gov/formertools/pete/index.html PETE]]
[def _spirit_fx_
[@http://spirit.sourceforge.net Spirit Parser Framework]]
[def _spirit_
[@http://spirit.sourceforge.net Spirit]]
[def _xpressive_
[@../../libs/xpressive/index.html Boost.Xpressive]]
[def _typeof_
[@../../libs/typeof/index.html Boost.Typeof]]
[def _expr_
[classref boost::proto::expr `proto::expr<>`]]
[def _basic_expr_
[classref boost::proto::basic_expr `proto::basic_expr<>`]]
[def _deep_copy_
[funcref boost::proto::deep_copy `proto::deep_copy()`]]
[def _domain_
[classref boost::proto::domain `proto::domain<>`]]
[def _default_domain_
[classref boost::proto::default_domain `proto::default_domain`]]
[def _extends_
[classref boost::proto::extends `proto::extends<>`]]
[def _external_transform_
[classref boost::proto::external_transform `proto::external_transform`]]
[def _external_transforms_
[classref boost::proto::external_transforms `proto::external_transforms<>`]]
[def _as_expr_
[funcref boost::proto::as_expr `proto::as_expr()`]]
[def _as_child_
[funcref boost::proto::as_child `proto::as_child()`]]
[def _make_expr_
[funcref boost::proto::make_expr `proto::make_expr()`]]
[def _unpack_expr_
[funcref boost::proto::unpack_expr `proto::unpack_expr()`]]
[def _display_expr_
[funcref boost::proto::display_expr `proto::display_expr()`]]
[def _matches_
[classref boost::proto::matches `proto::matches<>`]]
[def _or_
[classref boost::proto::or_ `proto::or_<>`]]
[def _and_
[classref boost::proto::and_ `proto::and_<>`]]
[def _if_
[classref boost::proto::if_ `proto::if_<>`]]
[def _not_
[classref boost::proto::not_ `proto::not_<>`]]
[def _switch_
[classref boost::proto::switch_ `proto::switch_<>`]]
[def _exact_
[classref boost::proto::exact `proto::exact<>`]]
[def _convertible_to_
[classref boost::proto::convertible_to `proto::convertible_to<>`]]
[def _is_expr_
[classref boost::proto::is_expr `proto::is_expr<>`]]
[def _tag_of_
[classref boost::proto::tag_of `proto::tag_of<>`]]
[def _arity_of_
[classref boost::proto::arity_of `proto::arity_of<>`]]
[def _child_
[funcref boost::proto::child `proto::child()`]]
[def _child_c_
[funcref boost::proto::child_c `proto::child_c()`]]
[def _eval_
[funcref boost::proto::eval `proto::eval()`]]
[def _left_
[funcref boost::proto::left `proto::left()`]]
[def _right_
[funcref boost::proto::right `proto::right()`]]
[def _value_
[funcref boost::proto::value `proto::value()`]]
[def _terminal_
[classref boost::proto::terminal `proto::terminal<>`]]
[def _unary_plus_
[classref boost::proto::unary_plus `proto::unary_plus<>`]]
[def _plus_
[classref boost::proto::plus `proto::plus<>`]]
[def _function_
[classref boost::proto::function `proto::function<>`]]
[def _unary_expr_
[classref boost::proto::unary_expr `proto::unary_expr<>`]]
[def _binary_expr_
[classref boost::proto::binary_expr `proto::binary_expr<>`]]
[def _nary_expr_
[classref boost::proto::nary_expr `proto::nary_expr<>`]]
[def _literal_
[classref boost::proto::literal `proto::literal<>`]]
[def _lit_
[funcref boost::proto::lit `proto::lit()`]]
[def _vararg_
[classref boost::proto::vararg `proto::vararg<>`]]
[def _default_context_
[classref boost::proto::context::default_context `proto::default_context`]]
[def _callable_context_
[classref boost::proto::context::callable_context `proto::callable_context<>`]]
[def _null_context_
[classref boost::proto::context::null_context `proto::null_context<>`]]
[def _when_
[classref boost::proto::when `proto::when<>`]]
[def _call_
[classref boost::proto::call `proto::call<>`]]
[def _make_
[classref boost::proto::make `proto::make<>`]]
[def _flatten_
[funcref boost::proto::flatten `proto::flatten()`]]
[def _value_pt_
[classref boost::proto::_value `proto::_value`]]
[def _child_c_pt_
[classref boost::proto::_child_c `proto::_child_c<>`]]
[def _child_pt_
[classref boost::proto::_child `proto::_child`]]
[def _left_pt_
[classref boost::proto::_left `proto::_left`]]
[def _right_pt_
[classref boost::proto::_right `proto::_right`]]
[def _wild_
[classref boost::proto::_ `proto::_`]]
[def _expr_pt_
[classref boost::proto::_expr `proto::_expr`]]
[def _state_pt_
[classref boost::proto::_state `proto::_state`]]
[def _data_pt_
[classref boost::proto::_data `proto::_data`]]
[def _call_pt_
[classref boost::proto::call `proto::call<>`]]
[def _make_pt_
[classref boost::proto::make `proto::make<>`]]
[def _default_pt_
[classref boost::proto::_default `proto::_default<>`]]
[def _fold_pt_
[classref boost::proto::fold `proto::fold<>`]]
[def _fold_tree_pt_
[classref boost::proto::fold_tree `proto::fold_tree<>`]]
[def _reverse_fold_pt_
[classref boost::proto::reverse_fold `proto::reverse_fold<>`]]
[def _reverse_fold_tree_pt_
[classref boost::proto::reverse_fold_tree `proto::reverse_fold_tree<>`]]
[def _generator_
[classref boost::proto::generator `proto::generator<>`]]
[def _pod_generator_
[classref boost::proto::pod_generator `proto::pod_generator<>`]]
[def _deduce_domain_
[classref boost::proto::deduce_domain `proto::deduce_domain`]]
[def _lazy_pt_
[classref boost::proto::lazy `proto::lazy<>`]]
[def _pack_
[classref boost::proto::pack `proto::pack`]]
[def _SYB_
[link boost_proto.users_guide.resources.SYB ["Scrap Your Boilerplate]]]
[def _result_of_value_
[classref boost::proto::result_of::value `proto::result_of::value<>`]]
[def _result_of_child_c_
[classref boost::proto::result_of::child_c `proto::result_of::child_c<>`]]
[def _result_of_child_
[classref boost::proto::result_of::child `proto::result_of::child<>`]]
[def _result_of_left_
[classref boost::proto::result_of::left `proto::result_of::left<>`]]
[def _result_of_right_
[classref boost::proto::result_of::right `proto::result_of::right<>`]]
[def _MAX_ARITY_
[^[macroref BOOST_PROTO_MAX_ARITY]]]
[def _MAX_LOGICAL_ARITY_
[^[macroref BOOST_PROTO_MAX_LOGICAL_ARITY]]]
[def _MAX_FUNCTION_CALL_ARITY_
[^[macroref BOOST_PROTO_MAX_FUNCTION_CALL_ARITY]]]
[def _BASIC_EXTENDS_
[^[macroref BOOST_PROTO_BASIC_EXTENDS]()]]
[def _EXTENDS_
[^[macroref BOOST_PROTO_EXTENDS]()]]
[def _EXTENDS_ASSIGN_
[^[macroref BOOST_PROTO_EXTENDS_ASSIGN]()]]
[def _EXTENDS_SUBSCRIPT_
[^[macroref BOOST_PROTO_EXTENDS_SUBSCRIPT]()]]
[def _EXTENDS_FUNCTION_
[^[macroref BOOST_PROTO_EXTENDS_FUNCTION]()]]
[def _DEFINE_OPERATORS_
[^[macroref BOOST_PROTO_DEFINE_OPERATORS]()]]
[def _AUTO_
[^[macroref BOOST_PROTO_AUTO]()]]
[def _REPEAT_
[^[macroref BOOST_PROTO_REPEAT]()]]
[def _REPEAT_FROM_TO_
[^[macroref BOOST_PROTO_REPEAT_FROM_TO]()]]
[def _REPEAT_EX_
[^[macroref BOOST_PROTO_REPEAT_EX]()]]
[def _REPEAT_FROM_TO_EX_
[^[macroref BOOST_PROTO_REPEAT_FROM_TO_EX]()]]
[def _LOCAL_ITERATE_
[^[macroref BOOST_PROTO_LOCAL_ITERATE]()]]
[def _BOOST_PROTO_typename_A_
[^[macroref BOOST_PROTO_typename_A]()]]
[def _BOOST_PROTO_A_
[^[macroref BOOST_PROTO_A]()]]
[def _BOOST_PROTO_A_const_
[^[macroref BOOST_PROTO_A_const]()]]
[def _BOOST_PROTO_A_ref_
[^[macroref BOOST_PROTO_A_ref]()]]
[def _BOOST_PROTO_A_const_ref_
[^[macroref BOOST_PROTO_A_const_ref]()]]
[def _BOOST_PROTO_A_ref_a_
[^[macroref BOOST_PROTO_A_ref_a]()]]
[def _BOOST_PROTO_A_const_ref_a_
[^[macroref BOOST_PROTO_A_const_ref_a]()]]
[def _BOOST_PROTO_a_
[^[macroref BOOST_PROTO_a]()]]
[def _BOOST_PROTO_ref_a_
[^[macroref BOOST_PROTO_ref_a]()]]
[include preface.qbk]
[/===============================]
[section:users_guide Users' Guide]
[/===============================]
[/===========================================================]
[heading Compilers, Compiler Construction Toolkits, and Proto]
[/===========================================================]
Most compilers have front ends and back ends. The front end parses the text of an input program into some intermediate form like an abstract syntax tree, and the back end takes the intermediate form and generates an executable from it.
A library built with Proto is essentially a compiler for an embedded domain-specific language (EDSL). It also has a front end, an intermediate form, and a back end. The front end is comprised of the symbols (a.k.a., terminals), members, operators and functions that make up the user-visible aspects of the EDSL. The back end is made of evaluation contexts and transforms that give meaning and behavior to the expression templates generated by the front end. In between is the intermediate form: the expression template itself, which is an abstract syntax tree in a very real sense.
To build a library with Proto, you will first decide what your interface will be; that is, you'll design a programming language for your domain and build the front end with tools provided by Proto. Then you'll design the back end by writing evaluation contexts and/or transforms that accept expression templates and do interesting things with them.
This users' guide is organized as follows. After a [link boost_proto.users_guide.getting_started Getting Started guide], we'll cover the tools Proto provides for defining and manipulating the three major parts of a compiler:
[variablelist
[[[link boost_proto.users_guide.front_end Front Ends]]
[How to define the aspects of your EDSL with which your users will interact directly.]]
[[[link boost_proto.users_guide.intermediate_form Intermediate Form]]
[What Proto expression templates look like, how to discover their structure and access their constituents.]]
[[[link boost_proto.users_guide.back_end Back Ends]]
[How to define evaluation contexts and transforms that make expression templates do interesting things.]]
]
After that, you may be interested in seeing some [link boost_proto.users_guide.examples Examples] to get a better idea of how the pieces all fit together.
[include getting_started.qbk]
[include front_end.qbk]
[include intermediate_form.qbk]
[include back_end.qbk]
[include examples.qbk]
[include resources.qbk]
[include glossary.qbk]
[endsect]
[xinclude reference.xml]
[/=================]
[section Appendices]
[/=================]
[include release_notes.qbk]
[include history.qbk]
[include rationale.qbk]
[include implementation.qbk]
[include acknowledgements.qbk]
[endsect]

View File

@@ -0,0 +1,51 @@
[/
/ Copyright (c) 2008 Eric Niebler
/
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
/]
[section:rationale Appendix C: Rationale]
[/==================================================]
[section:static_initialization Static Initialization]
[/==================================================]
Proto expression types are PODs (Plain Old Data), and do not have constructors. They are brace-initialized, as follows:
terminal<int>::type const _i = {1};
The reason is so that expression objects like `_i` above can be ['statically
initialized]. Why is static initialization important? The terminals of many embedded
domain-specific languages are likely to be global const objects, like `_1` and
`_2` from the Boost Lambda Library. Were these object to require run-time
initialization, it might be possible to use these objects before they are
initialized. That would be bad. Statically initialized objects cannot be misused
that way.
[endsect]
[/=========================================================]
[section:preprocessor Why Not Reuse MPL, Fusion, et cetera?]
[/=========================================================]
Anyone who has peeked at Proto's source code has probably wondered, "Why all the
dirty preprocessor gunk? Couldn't this have been all implemented cleanly on top of
libraries like MPL and Fusion?" The answer is that Proto could have been
implemented this way, and in fact was at one point. The problem is that template
metaprogramming (TMP) makes for longer compile times. As a foundation upon which
other TMP-heavy libraries will be built, Proto itself should be as lightweight as
possible. That is achieved by prefering preprocessor metaprogramming to template
metaprogramming. Expanding a macro is far more efficient than instantiating a
template. In some cases, the "clean" version takes 10x longer to compile than the
"dirty" version.
The "clean and slow" version of Proto can still be found at
http://svn.boost.org/svn/boost/branches/proto/v3. Anyone who is interested can
download it and verify that it is, in fact, unusably slow to compile. Note that
this branch's development was abandoned, and it does not conform exactly with
Proto's current interface.
[endsect]
[endsect]

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/args.hpp">
<para>
Contains definitions of the <computeroutput>
<classname alt="boost::proto::term">proto::term&lt;&gt;</classname></computeroutput>,
<computeroutput><classname alt="boost::proto::listN">proto::list1&lt;&gt;</classname></computeroutput>,
<computeroutput><classname alt="boost::proto::listN">proto::list2&lt;&gt;</classname></computeroutput>, etc.
class templates.
</para>
<namespace name="boost">
<namespace name="proto">
<!-- proto::term<> -->
<struct name="term">
<template>
<template-type-parameter name="T"/>
</template>
<purpose>A type sequence, for use as the 2<superscript>nd</superscript> parameter to the
<computeroutput><classname alt="proto::expr">proto::expr&lt;&gt;</classname></computeroutput> and
<computeroutput><classname alt="proto::basic_expr">proto::basic_expr&lt;&gt;</classname></computeroutput>
class templates.</purpose>
<description>
<para>
A type sequence with one element, for use as the 2<superscript>nd</superscript> parameter to the
<computeroutput><classname alt="proto::expr">proto::expr&lt;&gt;</classname></computeroutput> and
<computeroutput><classname alt="proto::basic_expr">proto::basic_expr&lt;&gt;</classname></computeroutput>
class templates. The sequence element represents the value of a terminal.
</para>
</description>
<data-member name="arity" specifiers="static">
<purpose><computeroutput>= 0;</computeroutput></purpose>
<type>const long</type>
</data-member>
<typedef name="child0">
<type>T</type>
</typedef>
</struct>
<!-- proto::list1<>, proto::list2<> ... -->
<struct name="listN">
<template>
<template-type-parameter name="Arg" pack="1"/>
</template>
<purpose><computeroutput>proto::list1&lt;&gt;</computeroutput>, <computeroutput>proto::list2&lt;&gt;</computeroutput>, etc.,
are type sequences for use as the 2<superscript>nd</superscript> parameter to the
<computeroutput><classname>proto::expr&lt;&gt;</classname></computeroutput> or
<computeroutput><classname>proto::basic_expr&lt;&gt;</classname></computeroutput> class templates.</purpose>
<description>
<para>
Type sequences, for use as the 2<superscript>nd</superscript> parameter to the
<computeroutput><classname>proto::expr&lt;&gt;</classname></computeroutput> or
<computeroutput><classname>proto::basic_expr&lt;&gt;</classname></computeroutput> class template. The
types in the sequence correspond to the children of a node in an expression tree.
There is no type literally named "<computeroutput>listN</computeroutput>"; rather, there is
a set of types named
<computeroutput>proto::list1&lt;&gt;</computeroutput>,
<computeroutput>proto::list2&lt;&gt;</computeroutput>, etc.
</para>
</description>
<data-member name="arity" specifiers="static">
<purpose><computeroutput>= N;</computeroutput></purpose>
<type>const long</type>
</data-member>
<typedef name="childM">
<purpose>For each <replaceable>M</replaceable> in <replaceable>[0,N)</replaceable></purpose>
<type>Arg<replaceable>M</replaceable></type>
</typedef>
</struct>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,92 @@
<?xml version="1.0" ?>
<concept name="BasicPrimitiveTransform" category="utility">
<!--
Copyright 2008 Eric Niebler
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)
-->
<param name="Fn" role="basic-primitive-transform-type" />
<param name="Expr" role="expression-type" />
<param name="State" role="state-type" />
<param name="Data" role="data-type" />
<models-sentence>
The type <arg num="1" /> must be a model of <self/>.
</models-sentence>
<description>
<para>
A BasicPrimitiveTransform is class type that
has a nested class template called impl that takes
three template parameters representing an expression
type, a state type and a data type. Specializations
of the nested impl template are ternary monomorphic
function objects that accept expression, state, and
data parameters.
</para>
</description>
<notation variables="fn">
<sample-value>
<type name="Fn" />
</sample-value>
</notation>
<notation variables="expr">
<sample-value>
<type name="Expr" />
</sample-value>
</notation>
<notation variables="state">
<sample-value>
<type name="State" />
</sample-value>
</notation>
<notation variables="data">
<sample-value>
<type name="Data" />
</sample-value>
</notation>
<associated-type name="result_type">
<get-member-type name="result_type">
<apply-template name="typename Fn::template impl">
<type name="Expr"/>
<type name="State"/>
<type name="Data"/>
</apply-template>
</get-member-type>
<description>
<simpara>The return type of the overloaded function call operator.</simpara>
</description>
</associated-type>
<valid-expression name="Monomorphic Function Call">
<apply-function name="typename Fn::template impl&lt; Expr, State, Data &gt;()">
<sample-value>
<type name="Expr" />
</sample-value>
<sample-value>
<type name="State" />
</sample-value>
<sample-value>
<type name="Data" />
</sample-value>
</apply-function>
<return-type>
<require-same-type testable="yes">
<type name="result_type"/>
</require-same-type>
</return-type>
<semantics>Applies the transform.</semantics>
</valid-expression>
<example-model>
<type name="boost::proto::terminal&lt; int &gt;" />
</example-model>
</concept>

View File

@@ -0,0 +1,93 @@
<?xml version="1.0" ?>
<!--
Copyright 2008 Eric Niebler
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)
-->
<concept name="CallableTransform" category="utility">
<param name="Fn" role="polymorphic-function-object-type" />
<param name="Tn" role="transform-type" />
<param name="Expr" role="expression-type" />
<param name="State" role="state-type" />
<param name="Data" role="data-type" />
<models-sentence>
The type <arg num="1" /> must be a model of <conceptname name="PolymorphicFunctionObject"/>.
The type <arg num="2" /> must be a model of <conceptname name="Transform"/>.
</models-sentence>
<description>
<para>
A CallableTransform is a function type or a function
pointer type where the return type Fn is a
PolymorphicFunctionObject and the arguments are
Transforms. is_callable&lt; Fn &gt;::value
must be true. The CallableTransform, when applied,
has the effect of invoking the polymorphic function
object Fn, passing as arguments the result(s)
of applying transform(s) Tn.
</para>
</description>
<notation variables="fn">
<sample-value>
<type name="Fn" />
</sample-value>
</notation>
<notation variables="expr">
<sample-value>
<type name="Expr" />
</sample-value>
</notation>
<notation variables="state">
<sample-value>
<type name="State" />
</sample-value>
</notation>
<notation variables="data">
<sample-value>
<type name="Data" />
</sample-value>
</notation>
<associated-type name="result_type">
<get-member-type name="type">
<apply-template name="boost::result_of">
<type name="Fn(Transform&lt;Tn, Expr, State, Data&gt;::result_type...)"/>
</apply-template>
</get-member-type>
<description>
<simpara>The result of applying the CallableTransform.</simpara>
</description>
</associated-type>
<valid-expression name="Apply Transform">
<apply-function name="when&lt; _, Fn(Tn...)&gt;()">
<sample-value>
<type name="Expr" />
</sample-value>
<sample-value>
<type name="State" />
</sample-value>
<sample-value>
<type name="Data" />
</sample-value>
</apply-function>
<return-type>
<require-same-type testable="yes">
<type name="result_type"/>
</require-same-type>
</return-type>
<semantics>Applies the transform.</semantics>
</valid-expression>
<example-model>
<type name="boost::proto::_child(boost::proto::_left)" />
</example-model>
</concept>

View File

@@ -0,0 +1,202 @@
<?xml version="1.0" ?>
<!--
Copyright 2010 Eric Niebler
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)
-->
<concept name="Domain" category="utility">
<param name="Domain" role="domain-type" />
<param name="Expr" role="expression-type" />
<param name="Object" role="object-type" />
<models-sentence>
The type <arg num="1" /> must be a model of <self/>. It also
models Unary Polymorphic Function.
</models-sentence>
<models-sentence>
The type <arg num="2" /> must be a model of <conceptname>Expr</conceptname>
</models-sentence>
<description>
<para>
A Domain creates an association between expressions and a so-called
generator, which is a function that maps an expression in the default
domain to an equivalent expression in this Domain. It also associates
an expression with a grammar, to which all expressions within this
Domain must conform.
</para>
</description>
<notation variables="d">
<sample-value>
<type name="Domain" />
</sample-value>
</notation>
<notation variables="e">
<sample-value>
<type name="Expr" />
</sample-value>
</notation>
<notation variables="o">
<sample-value>
<type name="Object" />
</sample-value>
</notation>
<associated-type name="proto_grammar">
<get-member-type name="proto_grammar">
<type name="Domain"/>
</get-member-type>
<description>
<simpara>The grammar to which every expression in this Domain
must conform.</simpara>
</description>
</associated-type>
<associated-type name="proto_generator">
<get-member-type name="proto_generator">
<type name="Domain"/>
</get-member-type>
<description>
<simpara>
A Unary Polymorphic Function that accepts expressions in the
default domain and emits expressions in this Domain.
</simpara>
</description>
</associated-type>
<associated-type name="proto_super_domain">
<get-member-type name="proto_super_domain">
<type name="Domain"/>
</get-member-type>
<description>
<simpara>
The Domain that is a super-domain of this domain, if
any such domain exists. If not, it is some unspecified
type.
</simpara>
</description>
</associated-type>
<associated-type name="result_type">
<get-member-type name="type">
<apply-template name="boost::result_of">
<type name="Domain(Expr)"/>
</apply-template>
</get-member-type>
<description>
<simpara>
The type of the result of applying
<computeroutput>proto_generator</computeroutput> to
the specified expression type. The result is required to
model <conceptname>Expr</conceptname>. The domain type
associated with <computeroutput>result_type</computeroutput>
(<computeroutput>result_type::proto_domain</computeroutput>)
is required to be the same type as this Domain.
</simpara>
</description>
</associated-type>
<associated-type name="as_expr_result_type">
<get-member-type name="result_type">
<apply-template name="Domain::as_expr">
<type name="Object"/>
</apply-template>
</get-member-type>
<description>
<simpara>
The result of converting some type to a Proto expression
type in this domain. This is used, for instance, when
calculating the type of a variable to hold a Proto
expression.
<computeroutput>as_expr_result_type</computeroutput>
models
<computeroutput><conceptname>Expr</conceptname></computeroutput>.
</simpara>
</description>
</associated-type>
<associated-type name="as_child_result_type">
<get-member-type name="result_type">
<apply-template name="Domain::as_child">
<type name="Object"/>
</apply-template>
</get-member-type>
<description>
<simpara>
The result of converting some type to a Proto expression
type in this domain. This is used, for instance, to
compute the type of an object suitable for storage
as a child in an expression tree.
<computeroutput>as_child_result_type</computeroutput>
models
<computeroutput><conceptname>Expr</conceptname></computeroutput>.
</simpara>
</description>
</associated-type>
<valid-expression name="Apply Generator">
<apply-function name="d">
<sample-value>
<type name="Expr"/>
</sample-value>
</apply-function>
<return-type>
<require-same-type testable="yes">
<type name="result_type"/>
</require-same-type>
</return-type>
<semantics>
The result of applying <computeroutput>proto_generator</computeroutput>
to the specified expression.
</semantics>
</valid-expression>
<valid-expression name="As Expression">
<apply-function name="Domain::as_expr&lt; Object &gt;()">
<sample-value>
<type name="Object"/>
</sample-value>
</apply-function>
<return-type>
<require-same-type testable="yes">
<type name="as_expr_result_type"/>
</require-same-type>
</return-type>
<semantics>
The result of converting some object to a Proto expression
in this domain. It returns a Proto expression object that
is suitable for storage in a variable. It should return a
new object, which may be a copy of the object passed in.
</semantics>
</valid-expression>
<valid-expression name="As Child">
<apply-function name="Domain::as_child&lt; Object &gt;()">
<sample-value>
<type name="Object"/>
</sample-value>
</apply-function>
<return-type>
<require-same-type testable="yes">
<type name="as_child_result_type"/>
</require-same-type>
</return-type>
<semantics>
The result of converting some object to a Proto expression
in this domain. It returns an object suitable for storage
as a child in an expression tree, which may simply be a
reference to the object passed in.
</semantics>
</valid-expression>
<example-model>
<type name="boost::proto::default_domain" />
</example-model>
</concept>

View File

@@ -0,0 +1,194 @@
<?xml version="1.0" ?>
<!--
Copyright 2010 Eric Niebler
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)
-->
<concept name="Expr" category="utility">
<param name="Expr" role="expession-type"/>
<param name="Tag" role="tag-type"/>
<param name="Domain" role="domain-type"/>
<param name="N" role="mpl-integral-constant-type"/>
<models-sentence>
The type <arg num="1"/> must be a model of <self/>.
</models-sentence>
<models-sentence>
The type <arg num="3"/> must be a model of <conceptname>Domain</conceptname>.
</models-sentence>
<models-sentence>
The type <arg num="4"/> must be a model of MPL Integral Constant.
</models-sentence>
<description>
<para>
An Expr represents a tagged node in an expression tree.
The children of the Expr must themselves satisfy the
Expr concept. The Expr has an arity representing the
number of children. If the number of children is zero,
the Expr also has a value. An Expr also has an associated
<conceptname>Domain</conceptname>.
</para>
</description>
<notation variables="e">
<sample-value>
<type name="Expr"/>
</sample-value>
</notation>
<associated-type name="proto_tag">
<get-member-type name="proto_tag">
<type name="Expr"/>
</get-member-type>
<description>
<simpara>The tag type of the Expr.</simpara>
</description>
</associated-type>
<associated-type name="proto_args">
<get-member-type name="proto_args">
<type name="Expr"/>
</get-member-type>
<description>
<simpara>A typelist representing either the types of the child nodes, or,
if the arity of the Expr is 0, of the value of the terminal.</simpara>
</description>
</associated-type>
<associated-type name="proto_arity">
<get-member-type name="proto_arity">
<type name="Expr"/>
</get-member-type>
<description>
<simpara>
The arity (number of child nodes) of the Expr.
<computeroutput>proto_arity</computeroutput> is an MPL Integral Constant.
</simpara>
</description>
</associated-type>
<associated-type name="proto_grammar">
<get-member-type name="proto_grammar">
<type name="Expr"/>
</get-member-type>
<description>
<simpara>
A typedef for an instantiation of
<classname alt="boost::proto::basic_expr">
<code>proto::basic_expr&lt;&gt;</code>
</classname>
that is equivalent to Expr. Expression types are equivalent if they have the
same <code>proto_tag</code>, <code>proto_args</code>, and <code>proto_arity</code>.
</simpara>
</description>
</associated-type>
<associated-type name="proto_base_expr">
<get-member-type name="proto_base_expr">
<type name="Expr"/>
</get-member-type>
<description>
<simpara>
A typedef for an instantiation of
<classname alt="boost::proto::expr"><code>proto::expr&lt;&gt;</code></classname> or
<classname alt="boost::proto::basic_expr"><code>proto::basic_expr&lt;&gt;</code></classname>
that is equivalent to Expr. Expression types are equivalent if they have the
same <code>proto_tag</code>, <code>proto_args</code>, and <code>proto_arity</code>.
</simpara>
</description>
</associated-type>
<associated-type name="proto_derived_expr">
<get-member-type name="proto_derived_expr">
<type name="Expr"/>
</get-member-type>
<description>
<simpara>
A typedef for <code>Expr</code>.
</simpara>
</description>
</associated-type>
<associated-type name="proto_domain">
<get-member-type name="proto_domain">
<type name="Expr"/>
</get-member-type>
<description>
<simpara>
The Domain of the Expr. <computeroutput>proto_domain</computeroutput>
models <conceptname>Domain</conceptname>.
</simpara>
</description>
</associated-type>
<associated-type name="proto_childN">
<get-member-type name="proto_childN">
<type name="Expr"/>
</get-member-type>
<description>
<simpara>The type of the Nth child of Expr. Requires
<code>0 == N::value || N::value &lt; proto_arity::value</code></simpara>
</description>
</associated-type>
<valid-expression name="Get N-th Child">
<apply-function name="boost::proto::child&lt; N &gt;">
<sample-value>
<type name="Expr"/>
</sample-value>
</apply-function>
<return-type>
<require-same-type testable="yes">
<type name="proto_childN"/>
</require-same-type>
</return-type>
<semantics>Extracts the Nth child from this Expr.
Requires <computeroutput>N::value &lt; proto_arity::value</computeroutput>.</semantics>
</valid-expression>
<valid-expression name="Get Terminal Value">
<apply-function name="boost::proto::value">
<sample-value>
<type name="Expr"/>
</sample-value>
</apply-function>
<return-type>
<require-same-type testable="yes">
<type name="proto_child0"/>
</require-same-type>
</return-type>
<semantics>
Extracts the value from a terminal Expr.
Requires <computeroutput>0 == proto_arity::value</computeroutput>.
</semantics>
</valid-expression>
<valid-expression name="Get Base">
<apply-method name="proto_base">
<sample-value>
<type name="Expr"/>
</sample-value>
</apply-method>
<return-type>
<require-same-type testable="yes">
<type name="proto_base_expr"/>
</require-same-type>
</return-type>
<semantics>
Returns an object of type
<classname alt="boost::proto::expr"><code>proto::expr&lt;&gt;</code></classname> or
<classname alt="boost::proto::basic_expr"><code>proto::basic_expr&lt;&gt;</code></classname>
that is equivalent to <code>e</code>.
</semantics>
</valid-expression>
<example-model>
<type name="boost::proto::literal&lt; int &gt;"/>
</example-model>
</concept>

View File

@@ -0,0 +1,94 @@
<?xml version="1.0" ?>
<!--
Copyright 2008 Eric Niebler
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)
-->
<concept name="ObjectTransform" category="utility">
<param name="Obj" role="object-type" />
<param name="Tn" role="transform-type" />
<param name="Expr" role="expression-type" />
<param name="State" role="state-type" />
<param name="Data" role="data-type" />
<models-sentence>
The type <arg num="1" /> must be a model of <conceptname name="Regular"/>, or
else it is a template specialization representing a lamda expression that,
subsequent to type substitution, is a type that models <conceptname name="Regular"/>.
The type <arg num="2" /> must be a model of <conceptname name="Transform"/>.
</models-sentence>
<description>
<para>
An ObjectTransform is a function type or a function
pointer type where the return type Obj is a
an object type and the arguments are
Transforms. is_callable&lt; Obj &gt;::value
must be false. The ObjectTransform, when applied,
has the effect of constructing an object of type
Obj' (see below), passing as construction parameters
the result(s) of applying transform(s) Tn.
</para>
<para>
The type Obj may be a template specialization representing
a compile-time lambda expression. For instance, if Obj is
std::pair&lt; proto::_value, int &gt;, the result type of the
ObjectTransform is computed by replacing the type proto::_value
with the result of applying the proto::_value transform. For
given types Obj, Expr, State and Data, we can say that the
type Obj' represents the type Obj after all nested transforms
have been replaced with the results of applying the transforms
with Expr, State and Data as transform arguments.
</para>
<para>
If the type Obj is not a template specialization representing
a compile-time lambda expression, then the result type Obj' is
the same as Obj.
</para>
</description>
<notation variables="expr">
<sample-value>
<type name="Expr" />
</sample-value>
</notation>
<notation variables="state">
<sample-value>
<type name="State" />
</sample-value>
</notation>
<notation variables="data">
<sample-value>
<type name="Data" />
</sample-value>
</notation>
<valid-expression name="Apply Transform">
<apply-function name="when&lt; _, Obj(Tn...)&gt;()">
<sample-value>
<type name="Expr" />
</sample-value>
<sample-value>
<type name="State" />
</sample-value>
<sample-value>
<type name="Data" />
</sample-value>
</apply-function>
<return-type>
<require-same-type testable="yes">
<type name="Obj'"/>
</require-same-type>
</return-type>
<semantics>Applies the transform.</semantics>
</valid-expression>
<example-model>
<type name="std::pair&lt; boost::proto::_value, int &gt;(boost::proto::_value, int())" />
</example-model>
</concept>

View File

@@ -0,0 +1,66 @@
<?xml version="1.0" ?>
<!--
Copyright 2008 Eric Niebler
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)
-->
<concept name="PolymorphicFunctionObject" category="utility">
<param name="Fn" role="polymorphic-function-object-type" />
<models-sentence>
The type <arg num="1" /> must be a model of <self/>.
</models-sentence>
<description>
<para>
A type that can be called and that follows the TR1 ResultOf
protocol for return type calculation.
</para>
</description>
<notation variables="fn">
<sample-value>
<type name="Fn" />
</sample-value>
</notation>
<notation variables="a0,...an">
<sample-value>
<type name="A0,...An" />
</sample-value>
</notation>
<associated-type name="result_type">
<get-member-type name="type">
<apply-template name="result_of">
<apply-function name="Fn">
<type name="A0,...An" />
</apply-function>
</apply-template>
</get-member-type>
<description>
<simpara>The result of calling the Polymorphic Function Object.</simpara>
</description>
</associated-type>
<valid-expression name="Function Call">
<apply-function name="fn">
<sample-value>
<type name="A0,...An" />
</sample-value>
</apply-function>
<return-type>
<require-same-type testable="yes">
<type name="result_type"/>
</require-same-type>
</return-type>
<semantics>Calls the function object.</semantics>
</valid-expression>
<example-model>
<type name="std::plus&lt;int&gt;" />
</example-model>
</concept>

View File

@@ -0,0 +1,147 @@
<?xml version="1.0" ?>
<!--
Copyright 2008 Eric Niebler
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)
-->
<concept name="PrimitiveTransform" category="utility">
<param name="Fn" role="primitive-transform-type" />
<param name="Expr" role="expression-type" />
<param name="State" role="state-type" />
<param name="Data" role="data-type" />
<models-sentence>
The type <arg num="1" /> must be a model of <self/>.
</models-sentence>
<description>
<para>
A PrimitiveTransform is a class type that
has a nested class template called
<computeroutput>impl&lt;&gt;</computeroutput> that takes
three template parameters representing an expression
type, a state type and a data type. Specializations
of the nested impl template are ternary monomorphic
function objects that accept expression, state, and
data parameters. A PrimitiveTransform is also a
<conceptname>PolymorphicFunctionObject</conceptname>
implemented in terms of the nested
<computeroutput>impl&lt;&gt;</computeroutput> template.
</para>
</description>
<notation variables="fn">
<sample-value>
<type name="Fn" />
</sample-value>
</notation>
<notation variables="expr">
<sample-value>
<type name="Expr" />
</sample-value>
</notation>
<notation variables="state">
<sample-value>
<type name="State" />
</sample-value>
</notation>
<notation variables="data">
<sample-value>
<type name="Data" />
</sample-value>
</notation>
<associated-type name="result_type">
<get-member-type name="result_type">
<apply-template name="typename Fn::template impl">
<type name="Expr"/>
<type name="State"/>
<type name="Data"/>
</apply-template>
</get-member-type>
<description>
<simpara>The return type of the overloaded function call operator.</simpara>
</description>
</associated-type>
<valid-expression name="Polymorphic Function Call 1">
<apply-function name="fn">
<sample-value>
<type name="Expr" />
</sample-value>
</apply-function>
<return-type>
<require-same-type testable="yes">
<type name="result_type"/>
</require-same-type>
</return-type>
<semantics>Applies the transform.</semantics>
</valid-expression>
<valid-expression name="Polymorphic Function Call 2">
<apply-function name="fn">
<sample-value>
<type name="Expr" />
</sample-value>
<sample-value>
<type name="State" />
</sample-value>
</apply-function>
<return-type>
<require-same-type testable="yes">
<type name="result_type"/>
</require-same-type>
</return-type>
<semantics>Applies the transform.</semantics>
</valid-expression>
<valid-expression name="Polymorphic Function Call 3">
<apply-function name="fn">
<sample-value>
<type name="Expr" />
</sample-value>
<sample-value>
<type name="State" />
</sample-value>
<sample-value>
<type name="Data" />
</sample-value>
</apply-function>
<return-type>
<require-same-type testable="yes">
<type name="result_type"/>
</require-same-type>
</return-type>
<semantics>Applies the transform.</semantics>
</valid-expression>
<valid-expression name="Monomorphic Function Call">
<apply-function name="typename Fn::template impl&lt; Expr, State, Data &gt;()">
<sample-value>
<type name="Expr" />
</sample-value>
<sample-value>
<type name="State" />
</sample-value>
<sample-value>
<type name="Data" />
</sample-value>
</apply-function>
<return-type>
<require-same-type testable="yes">
<type name="result_type"/>
</require-same-type>
</return-type>
<semantics>Applies the transform.</semantics>
</valid-expression>
<example-model>
<type name="boost::proto::_child_c&lt; 0 &gt;" />
</example-model>
</concept>

View File

@@ -0,0 +1,79 @@
<?xml version="1.0" ?>
<!--
Copyright 2008 Eric Niebler
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)
-->
<concept name="Transform" category="utility">
<param name="Tn" role="transform-type" />
<param name="Expr" role="expression-type" />
<param name="State" role="state-type" />
<param name="Data" role="data-type" />
<models-sentence>
The type <arg num="1" /> must be a model of <self/>.
</models-sentence>
<description>
<para>
A Transform is a PrimitiveTransform, a CallableTransform
or an ObjectTransform.
</para>
</description>
<notation variables="expr">
<sample-value>
<type name="Expr" />
</sample-value>
</notation>
<notation variables="state">
<sample-value>
<type name="State" />
</sample-value>
</notation>
<notation variables="data">
<sample-value>
<type name="Data" />
</sample-value>
</notation>
<associated-type name="result_type">
<get-member-type name="type">
<apply-template name="boost::result_of">
<type name="when&lt; _, Tn &gt;(Expr, State, Data)"/>
</apply-template>
</get-member-type>
<description>
<simpara>The result of applying the Transform.</simpara>
</description>
</associated-type>
<valid-expression name="Apply Transform">
<apply-function name="when&lt; _, Tn &gt;()">
<sample-value>
<type name="Expr" />
</sample-value>
<sample-value>
<type name="State" />
</sample-value>
<sample-value>
<type name="Data" />
</sample-value>
</apply-function>
<return-type>
<require-same-type testable="yes">
<type name="result_type"/>
</require-same-type>
</return-type>
<semantics>Applies the transform.</semantics>
</valid-expression>
<example-model>
<type name="boost::proto::_child(boost::proto::_left)" />
</example-model>
</concept>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/context.hpp">
<para>Includes all the built-in evaluation contexts of Proto.</para>
</header>

View File

@@ -0,0 +1,176 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/context/callable.hpp">
<para>Definintion of <computeroutput><classname alt="boost::proto::context::callable_context">proto::context::callable_context&lt;&gt;</classname></computeroutput>,
an evaluation context for <computeroutput><functionname alt="boost::proto::eval">proto::eval()</functionname></computeroutput>
that fans out each node and calls the derived context type with the expressions constituents. If the derived context
doesn't have an overload that handles this node, fall back to some other context. </para>
<namespace name="boost">
<namespace name="proto">
<namespace name="context">
<struct name="callable_eval">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="Context"/>
</template>
<purpose>A BinaryFunction that accepts a Proto expression and a callable context and calls
the context with the expression tag and children as arguments, effectively fanning the
expression out. </purpose>
<description>
<para>
<computeroutput>proto::context::callable_eval&lt;&gt;</computeroutput> requires that
<computeroutput>Context</computeroutput> is a <conceptname>PolymorphicFunctionObject</conceptname>
that can be invoked with <computeroutput>Expr</computeroutput>'s tag and children as
expressions, as follows:
<programlisting>context(typename Expr::proto_tag(), <functionname>proto::child_c</functionname>&lt;0&gt;(expr), ... <functionname>proto::child_c</functionname>&lt;N&gt;(expr))</programlisting>
</para>
</description>
<typedef name="result_type">
<type>typename boost::result_of&lt;
Context(
typename Expr::proto_tag,
typename proto::result_of::child_c&lt;0&gt;::type,
...
typename proto::result_of::child_c&lt;N&gt;::type,
)&gt;::type
</type>
</typedef>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>result_type</type>
<parameter name="expr">
<paramtype>Expr &amp;</paramtype>
<description>
<para>The current expression </para>
</description>
</parameter>
<parameter name="context">
<paramtype>Context &amp;</paramtype>
<description>
<para>The callable evaluation context </para>
</description>
</parameter>
<returns>
<para>
<computeroutput>
context(typename Expr::proto_tag(),
<functionname>proto::child_c</functionname>&lt;0&gt;(expr),...
<functionname>proto::child_c</functionname>&lt;N&gt;(expr))
</computeroutput>
</para>
</returns>
</method>
</method-group>
</struct>
<struct name="callable_context">
<template>
<template-type-parameter name="Context"/>
<template-type-parameter name="DefaultCtx">
<default><classname>proto::context::default_context</classname></default>
</template-type-parameter>
</template>
<purpose>An evaluation context adaptor that makes authoring a context a simple matter of
writing function overloads, rather then writing template specializations.</purpose>
<description>
<para>
<computeroutput>proto::callable_context&lt;&gt;</computeroutput> is a base class that
implements the context protocol by passing fanned-out expression nodes to the derived
context, making it easy to customize the handling of expression types by writing function
overloads. Only those expression types needing special handling require explicit handling.
All others are dispatched to a user-specified default context,
<computeroutput>DefaultCtx</computeroutput>.
</para>
<para>
<computeroutput>proto::callable_context&lt;&gt;</computeroutput> is defined simply as:
</para>
<para>
<programlisting>template&lt;typename Context, typename DefaultCtx = default_context&gt;
struct callable_context {
template&lt;typename Expr, typename ThisContext = Context&gt;
struct eval :
mpl::if_&lt;
is_expr_handled_&lt;Expr, Context&gt;, // For exposition
<classname>proto::context::callable_eval</classname>&lt;Expr, ThisContext&gt;,
typename DefaultCtx::template eval&lt;Expr, Context&gt;
&gt;::type
{};
};</programlisting>
</para>
<para>
The Boolean metafunction <computeroutput>is_expr_handled_&lt;&gt;</computeroutput> uses
metaprogramming tricks to determine whether <computeroutput>Context</computeroutput> has
an overloaded function call operator that accepts the fanned-out constituents of an
expression of type <computeroutput>Expr</computeroutput>. If so, the handling of the
expression is dispatched to
<computeroutput><classname>proto::context::callable_eval&lt;&gt;</classname></computeroutput>.
If not, it is dispatched to the user-specified <computeroutput>DefaultCtx</computeroutput>.
</para>
<para>
<emphasis role="bold">Example:</emphasis>
</para>
<para>
<programlisting>// An evaluation context that increments all
// integer terminals in-place.
struct increment_ints :
<classname>proto::context::callable_context</classname>&lt;
increment_ints const // derived context
<classname>proto::context::null_context</classname> const // fall-back context
&gt;
{
typedef void result_type;
// Handle int terminals here:
void operator()(proto::tag::terminal, int &amp;i) const
{
++i;
}
};</programlisting>
</para>
<para>
With <computeroutput>increment_ints</computeroutput>, we can do the following:
</para>
<para>
<programlisting><classname>proto::literal</classname>&lt;int&gt; i = 0, j = 10;
proto::eval( i - j * 3.14, increment_ints() );
assert( i.get() == 1 &amp;&amp; j.get() == 11 );</programlisting>
</para>
</description>
<struct name="eval">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="ThisContext">
<default>Context</default>
</template-type-parameter>
</template>
<description>
<para>
A BinaryFunction that accepts an <computeroutput>Expr</computeroutput> and a
<computeroutput>Context</computeroutput>, and either fans out the expression and passes
it to the context, or else hands off the expression to <computeroutput>DefaultCtx</computeroutput>.
</para>
<para>
If <computeroutput>Context</computeroutput> is a <conceptname>PolymorphicFunctionObject</conceptname>
such that it can be invoked with the tag and children of <computeroutput>Expr</computeroutput>, as
<computeroutput>ctx(typename Expr::proto_tag(), child_c&lt;0&gt;(expr),... child_c&lt;N&gt;(expr))</computeroutput>,
then <computeroutput>eval&lt;Expr, ThisContext&gt;</computeroutput> inherits from
<computeroutput><classname>proto::context::callable_eval</classname>&lt;Expr, ThisContext&gt;</computeroutput>.
Otherwise, <computeroutput>eval&lt;Expr, ThisContext&gt;</computeroutput> inherits from
<computeroutput>DefaultCtx::eval&lt;Expr, Context&gt;</computeroutput>.
</para>
</description>
<inherit><type><replaceable>see-below</replaceable></type></inherit>
</struct>
</struct>
</namespace>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,220 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/context/default.hpp">
<namespace name="boost">
<namespace name="proto">
<namespace name="context">
<struct name="default_eval">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="Context"/>
</template>
<purpose>
A BinaryFunction that accepts a Proto expression and a context, evaluates
each child expression with the context, and combines the result using the
standard C++ meaning for the operator represented by the current expression
node.
</purpose>
<description>
<para>
Let <computeroutput><computeroutput>OP</computeroutput></computeroutput> be the C++ operator
corresponding to <computeroutput>Expr::proto_tag</computeroutput>. (For example, if
<computeroutput>Tag</computeroutput> is <computeroutput>
<classname>proto::tag::plus</classname></computeroutput>, let <computeroutput>
<computeroutput>OP</computeroutput></computeroutput> be <computeroutput>+</computeroutput>.)
</para>
<para>
The behavior of this class is specified in terms of the C++0x <computeroutput>decltype</computeroutput>
keyword. In systems where this keyword is not available, Proto uses the Boost.Typeof library to
approximate the behavior.
</para>
</description>
<typedef name="Tag">
<purpose>For exposition only</purpose>
<type>typename Expr::tag_type</type>
</typedef>
<data-member name="s_expr" specifiers="static">
<purpose>For exposition only</purpose>
<type>Expr &amp;</type>
</data-member>
<data-member name="s_context" specifiers="static">
<purpose>For exposition only</purpose>
<type>Context &amp;</type>
</data-member>
<typedef name="result_type">
<type><emphasis>see-below</emphasis></type>
<description>
<itemizedlist>
<listitem>
<para>
If <computeroutput>Tag</computeroutput> corresponds to a unary prefix operator,
then the result type is
<programlisting>decltype(
OP <functionname>proto::eval</functionname>(<functionname>proto::child</functionname>(s_expr), s_context)
)</programlisting>
</para>
</listitem>
<listitem>
<para>
If <computeroutput>Tag</computeroutput> corresponds to a unary postfix operator,
then the result type is
<programlisting>decltype(
<functionname>proto::eval</functionname>(<functionname>proto::child</functionname>(s_expr), s_context) OP
)</programlisting>
</para>
</listitem>
<listitem>
<para>
If <computeroutput>Tag</computeroutput> corresponds to a binary infix operator,
then the result type is
<programlisting>decltype(
<functionname>proto::eval</functionname>(<functionname>proto::left</functionname>(s_expr), s_context) OP
<functionname>proto::eval</functionname>(<functionname>proto::right</functionname>(s_expr), s_context)
)</programlisting>
</para>
</listitem>
<listitem>
<para>
If <computeroutput>Tag</computeroutput> is <computeroutput>
<classname>proto::tag::subscript</classname>
</computeroutput>,
then the result type is
<programlisting>decltype(
<functionname>proto::eval</functionname>(<functionname>proto::left</functionname>(s_expr), s_context) [
<functionname>proto::eval</functionname>(<functionname>proto::right</functionname>(s_expr), s_context) ]
)</programlisting>
</para>
</listitem>
<listitem>
<para>
If <computeroutput>Tag</computeroutput> is <computeroutput>
<classname>proto::tag::if_else_</classname>
</computeroutput>,
then the result type is
<programlisting>decltype(
<functionname>proto::eval</functionname>(<functionname>proto::child_c</functionname>&lt;0&gt;(s_expr), s_context) ?
<functionname>proto::eval</functionname>(<functionname>proto::child_c</functionname>&lt;1&gt;(s_expr), s_context) :
<functionname>proto::eval</functionname>(<functionname>proto::child_c</functionname>&lt;2&gt;(s_expr), s_context)
)</programlisting>
</para>
</listitem>
<listitem>
<para>
If <computeroutput>Tag</computeroutput> is <computeroutput>
<classname>proto::tag::function</classname>
</computeroutput>,
then the result type is
<programlisting>decltype(
<functionname>proto::eval</functionname>(<functionname>proto::child_c</functionname>&lt;0&gt;(s_expr), s_context) (
<functionname>proto::eval</functionname>(<functionname>proto::child_c</functionname>&lt;1&gt;(s_expr), s_context),
...
<functionname>proto::eval</functionname>(<functionname>proto::child_c</functionname>&lt;N&gt;(s_expr), s_context) )
)</programlisting>
</para>
</listitem>
</itemizedlist>
</description>
</typedef>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>result_type</type>
<parameter name="expr">
<paramtype>Expr &amp;</paramtype>
<description>
<para>The current expression </para>
</description>
</parameter>
<parameter name="context">
<paramtype>Context &amp;</paramtype>
<description>
<para>The evaluation context </para>
</description>
</parameter>
<description>
<itemizedlist>
<listitem>
<para>
If <computeroutput>Tag</computeroutput> corresponds to a unary prefix operator,
then return
<programlisting>OP <functionname>proto::eval</functionname>(<functionname>proto::child</functionname>(expr), context)</programlisting>
</para>
</listitem>
<listitem>
<para>
If <computeroutput>Tag</computeroutput> corresponds to a unary postfix operator,
then return
<programlisting><functionname>proto::eval</functionname>(<functionname>proto::child</functionname>(expr), context) OP</programlisting>
</para>
</listitem>
<listitem>
<para>
If <computeroutput>Tag</computeroutput> corresponds to a binary infix operator,
then return
<programlisting><functionname>proto::eval</functionname>(<functionname>proto::left</functionname>(expr), context) OP
<functionname>proto::eval</functionname>(<functionname>proto::right</functionname>(expr), context)</programlisting>
</para>
</listitem>
<listitem>
<para>
If <computeroutput>Tag</computeroutput> is <computeroutput>
<classname>proto::tag::subscript</classname>
</computeroutput>,
then return
<programlisting><functionname>proto::eval</functionname>(<functionname>proto::left</functionname>(expr), context) [
<functionname>proto::eval</functionname>(<functionname>proto::right</functionname>(expr), context) ]</programlisting>
</para>
</listitem>
<listitem>
<para>
If <computeroutput>Tag</computeroutput> is <computeroutput>
<classname>proto::tag::if_else_</classname>
</computeroutput>,
then return
<programlisting><functionname>proto::eval</functionname>(<functionname>proto::child_c</functionname>&lt;0&gt;(expr), context) ?
<functionname>proto::eval</functionname>(<functionname>proto::child_c</functionname>&lt;1&gt;(expr), context) :
<functionname>proto::eval</functionname>(<functionname>proto::child_c</functionname>&lt;2&gt;(expr), context)</programlisting>
</para>
</listitem>
<listitem>
<para>
If <computeroutput>Tag</computeroutput> is <computeroutput>
<classname>proto::tag::function</classname>
</computeroutput>,
then return
<programlisting><functionname>proto::eval</functionname>(<functionname>proto::child_c</functionname>&lt;0&gt;(expr), context) (
<functionname>proto::eval</functionname>(<functionname>proto::child_c</functionname>&lt;1&gt;(expr), context),
...
<functionname>proto::eval</functionname>(<functionname>proto::child_c</functionname>&lt;N&gt;(expr), context) )</programlisting>
</para>
</listitem>
</itemizedlist>
</description>
</method>
</method-group>
</struct>
<struct name="default_context">
<purpose>An evaluation context that gives the operators their normal C++ semantics.</purpose>
<description>
<para>An evaluation context that gives the operators their normal C++ semantics.</para>
</description>
<struct name="eval">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="ThisContext">
<default>default_context const</default>
</template-type-parameter>
</template>
<inherit><classname>proto::context::default_eval</classname>&lt; Expr, ThisContext &gt;</inherit>
</struct>
</struct>
</namespace>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/context/null.hpp">
<para>
Definintion of
<computeroutput><classname alt="boost::proto::context::null_context">proto::context::null_context&lt;&gt;</classname></computeroutput>,
an evaluation context for
<computeroutput><functionname alt="boost::proto::eval">proto::eval()</functionname></computeroutput>
that simply evaluates each child expression, doesn't combine the results at all, and returns void.
</para>
<namespace name="boost">
<namespace name="proto">
<namespace name="context">
<struct name="null_eval">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="Context"/>
</template>
<typedef name="result_type">
<type>void</type>
</typedef>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>void</type>
<parameter name="expr">
<paramtype>Expr &amp;</paramtype>
</parameter>
<parameter name="context">
<paramtype>Context &amp;</paramtype>
</parameter>
<description>
<para>
For <computeroutput>N</computeroutput> in <computeroutput>[0,Expr arity)</computeroutput>,
evaluate:
<programlisting><functionname>proto::eval</functionname>(<functionname>proto::child_c</functionname>&lt;N&gt;(expr), context)</programlisting>
</para>
</description>
</method>
</method-group>
</struct>
<struct name="null_context">
<purpose>An evaluation context for <functionname alt="proto::eval">proto::eval()</functionname> that simply evaluates
each child expression, doesn't combine the results at all, and returns void.</purpose>
<struct name="eval">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="ThisContext">
<default>null_context const</default>
</template-type-parameter>
</template>
<inherit><classname>proto::context::null_eval</classname>&lt; Expr, ThisContext &gt;</inherit>
</struct>
</struct>
</namespace>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/core.hpp">
<para>Includes all of Proto, except the contexts, transforms, debug utilities and Boost.Typeof registrations.</para>
</header>

View File

@@ -0,0 +1,280 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/debug.hpp">
<para>Utilities for debugging Proto expression trees </para>
<namespace name="boost">
<namespace name="proto">
<namespace name="functional">
<!-- proto::functional::display_expr -->
<struct name="display_expr">
<purpose>Pretty-print a Proto expression tree. </purpose>
<description>
<para>
A <conceptname>PolymorphicFunctionObject</conceptname> which accepts a Proto expression tree and pretty-prints it to an <computeroutput>ostream</computeroutput> for debugging purposes.
</para>
</description>
<typedef name="result_type">
<type>void</type>
</typedef>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>void</type>
<template>
<template-type-parameter name="Expr"/>
</template>
<parameter name="expr">
<paramtype>Expr const &amp;</paramtype>
</parameter>
</method>
</method-group>
<constructor>
<parameter name="sout"><paramtype>std::ostream &amp;</paramtype><default>std::cout</default>
<description>
<para>
The <computeroutput>ostream</computeroutput> to which the expression tree will be written.
</para>
</description>
</parameter>
<parameter name="depth">
<paramtype>int</paramtype>
<default>0</default>
<description>
<para>
The starting indentation depth for this node. Children nodes will be displayed at a starting depth of <computeroutput>depth+4</computeroutput>.
</para>
</description>
</parameter>
</constructor>
</struct>
</namespace>
<!-- proto::display_expr -->
<overloaded-function name="display_expr">
<signature>
<type>void</type>
<template>
<template-type-parameter name="Expr"/>
</template>
<parameter name="expr">
<paramtype>Expr const &amp;</paramtype>
<description>
<para>The Proto expression tree to pretty-print </para>
</description>
</parameter>
<parameter name="sout">
<paramtype>std::ostream &amp;</paramtype>
<description>
<para>
The <computeroutput>ostream</computeroutput> to which the output should be written. If not specified, defaults to <computeroutput>std::cout</computeroutput>.
</para>
</description>
</parameter>
</signature>
<signature>
<type>void</type>
<template>
<template-type-parameter name="Expr"/>
</template>
<parameter name="expr">
<paramtype>Expr const &amp;</paramtype>
</parameter>
</signature>
<purpose>Pretty-print a Proto expression tree. </purpose>
<notes>
<para>
Equivalent to <computeroutput><classname alt="boost::proto::functional::display_expr">proto::functional::display_expr</classname>(0, sout)(expr)</computeroutput>.
</para>
</notes>
</overloaded-function>
<!-- proto::assert_matches -->
<function name="assert_matches">
<type>void</type>
<template>
<template-type-parameter name="Grammar"/>
<template-type-parameter name="Expr"/>
</template>
<parameter name="expr">
<paramtype>Expr const &amp;</paramtype>
<purpose>
The Proto expression to check againts <code>Grammar</code>.
</purpose>
</parameter>
<purpose>
Assert at compile time that a particular expression
matches the specified grammar.
</purpose>
<notes>
<para>
Equivalent to <code>BOOST_MPL_ASSERT((<classname alt="proto::matches">proto::matches</classname>&lt;Expr, Grammar&gt;))</code>.
</para>
</notes>
<description>
<para>
Use <code>proto::assert_matches()</code> to assert at compile-time that
an expression matches a grammar.
</para>
<para>
<emphasis role="bold">Example:</emphasis><programlisting>typedef proto::plus&lt; proto::terminal&lt; int &gt;, proto::terminal&lt; int &gt; &gt; PlusInts;
proto::assert_matches&lt;PlusInts&gt;( <functionname>proto::lit</functionname>(1) + 42 );</programlisting>
</para>
<para>
See also:
<itemizedlist>
<listitem>
<code><functionname>proto::assert_matches_not</functionname>()</code>
</listitem>
<listitem>
<code><macroname>BOOST_PROTO_ASSERT_MATCHES</macroname>()</code>
</listitem>
<listitem>
<code><macroname>BOOST_PROTO_ASSERT_MATCHES_NOT</macroname>()</code>
</listitem>
</itemizedlist>
</para>
</description>
</function>
<!-- proto::assert_matches_not -->
<function name="assert_matches_not">
<type>void</type>
<template>
<template-type-parameter name="Grammar"/>
<template-type-parameter name="Expr"/>
</template>
<parameter name="expr">
<paramtype>Expr const &amp;</paramtype>
<purpose>
The Proto expression to check againts <code>Grammar</code>.
</purpose>
</parameter>
<purpose>
Assert at compile time that a particular expression
does not match the specified grammar.
</purpose>
<notes>
<para>
Equivalent to <code>BOOST_MPL_ASSERT_NOT((<classname alt="proto::matches">proto::matches</classname>&lt;Expr, Grammar&gt;))</code>.
</para>
</notes>
<description>
<para>
Use <code>proto::assert_matches_not()</code> to assert at compile-time that
an expression does not match a grammar.
</para>
<para>
<emphasis role="bold">Example:</emphasis><programlisting>typedef proto::plus&lt; proto::terminal&lt; int &gt;, proto::terminal&lt; int &gt; &gt; PlusInts;
proto::assert_matches_not&lt;PlusInts&gt;( <functionname>proto::lit</functionname>("a string") + 42 );</programlisting>
</para>
<para>
See also:
<itemizedlist>
<listitem>
<code><functionname>proto::assert_matches</functionname>()</code>
</listitem>
<listitem>
<code><macroname>BOOST_PROTO_ASSERT_MATCHES</macroname>()</code>
</listitem>
<listitem>
<code><macroname>BOOST_PROTO_ASSERT_MATCHES_NOT</macroname>()</code>
</listitem>
</itemizedlist>
</para>
</description>
</function>
</namespace>
</namespace>
<macro name="BOOST_PROTO_ASSERT_MATCHES" kind="functionlike">
<macro-parameter name="expr"/>
<macro-parameter name="Grammar"/>
<purpose>
Assert at compile time that a particular expression
matches the specified grammar.
</purpose>
<notes>
<para>
Equivalent to <code><functionname alt="boost::proto::assert_matches">proto::assert_matches</functionname>&lt;Grammar&gt;(expr)</code>.
</para>
</notes>
<description>
<para>
Use <code>BOOST_PROTO_ASSERT_MATCHES()</code> to assert at compile-time that
an expression matches a grammar.
</para>
<para>
<emphasis role="bold">Example:</emphasis><programlisting>typedef <classname alt="boost::proto::plus">proto::plus</classname>&lt; <classname alt="boost::proto::terminal">proto::terminal</classname>&lt; int &gt;, <classname alt="boost::proto::terminal">proto::terminal</classname>&lt; int &gt; &gt; PlusInts;
BOOST_PROTO_ASSERT_MATCHES( <functionname alt="boost::proto::lit">proto::lit</functionname>(1) + 42, PlusInts );</programlisting>
</para>
<para>
See also:
<itemizedlist>
<listitem>
<code><functionname alt="boost::proto::assert_matches">proto::assert_matches</functionname>()</code>
</listitem>
<listitem>
<code><functionname alt="boost::proto::assert_matches_not">proto::assert_matches_not</functionname>()</code>
</listitem>
<listitem>
<code><macroname>BOOST_PROTO_ASSERT_MATCHES_NOT</macroname>()</code>
</listitem>
</itemizedlist>
</para>
</description>
</macro>
<macro name="BOOST_PROTO_ASSERT_MATCHES_NOT" kind="functionlike">
<macro-parameter name="expr"/>
<macro-parameter name="Grammar"/>
<purpose>
Assert at compile time that a particular expression
does not match the specified grammar.
</purpose>
<notes>
<para>
Equivalent to <code><functionname alt="boost::proto::assert_matches_not">proto::assert_matches_not</functionname>&lt;Grammar&gt;(expr)</code>.
</para>
</notes>
<description>
<para>
Use <code>BOOST_PROTO_ASSERT_MATCHES_NOT()</code> to assert at compile-time that
an expression does not match a grammar.
</para>
<para>
<emphasis role="bold">Example:</emphasis><programlisting>typedef <classname alt="boost::proto::plus">proto::plus</classname>&lt; <classname alt="boost::proto::terminal">proto::terminal</classname>&lt; int &gt;, <classname alt="boost::proto::terminal">proto::terminal</classname>&lt; int &gt; &gt; PlusInts;
BOOST_PROTO_ASSERT_MATCHES_NOT( <functionname alt="boost::proto::lit">proto::lit</functionname>("a string") + 42, PlusInts );</programlisting>
</para>
<para>
See also:
<itemizedlist>
<listitem>
<code><functionname alt="boost::proto::assert_matches">proto::assert_matches</functionname>()</code>
</listitem>
<listitem>
<code><functionname alt="boost::proto::assert_matches_not">proto::assert_matches_not</functionname>()</code>
</listitem>
<listitem>
<code><macroname>BOOST_PROTO_ASSERT_MATCHES</macroname>()</code>
</listitem>
</itemizedlist>
</para>
</description>
</macro>
</header>

View File

@@ -0,0 +1,106 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/deep_copy.hpp">
<para>Replace all nodes stored by reference by nodes stored by value.</para>
<namespace name="boost">
<namespace name="proto">
<namespace name="result_of">
<!-- proto::result_of::deep_copy -->
<struct name="deep_copy">
<template>
<template-type-parameter name="Expr"/>
</template>
<purpose>A metafunction for calculating the return type of <computeroutput>
<functionname alt="proto::deep_copy">proto::deep_copy()</functionname></computeroutput>.</purpose>
<description>
<para>
A metafunction for calculating the return type of <computeroutput>
<functionname alt="proto::deep_copy">proto::deep_copy()</functionname></computeroutput>. The type
parameter <computeroutput>Expr</computeroutput> should be the type of a Proto expression tree.
It should not be a reference type, nor should it be cv-qualified.
</para>
</description>
<typedef name="type">
<type><emphasis>unspecified</emphasis></type>
</typedef>
</struct>
</namespace>
<namespace name="functional">
<!-- proto::functional::deep_copy -->
<struct name="deep_copy">
<inherit>
<type><classname>proto::callable</classname></type>
</inherit>
<purpose>A <conceptname>PolymorphicFunctionObject</conceptname> type for deep-copying Proto
expression trees.</purpose>
<description>
<para>
A <conceptname>PolymorphicFunctionObject</conceptname> type for deep-copying Proto expression trees.
When a tree is deep-copied, all internal nodes and terminals held by reference are instead held by value.
The only exception is function references, which continue to be held by reference.
</para>
</description>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="Expr"/>
</template>
<specialization>
<template-arg>This(Expr)</template-arg>
</specialization>
<inherit>
<type><classname>result_of::deep_copy</classname>&lt;Expr&gt;</type>
</inherit>
</struct-specialization>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type><classname>result_of::deep_copy</classname>&lt;Expr&gt;::type</type>
<template>
<template-type-parameter name="Expr"/>
</template>
<parameter name="expr">
<paramtype>Expr const &amp;</paramtype>
</parameter>
<purpose>Deep-copies a Proto expression tree, turning all nodes and terminals held by
reference into ones held by value.</purpose>
</method>
</method-group>
</struct>
</namespace>
<!-- proto::deep_copy() -->
<function name="deep_copy">
<type>typename <classname>proto::result_of::deep_copy</classname>&lt;Expr&gt;::type</type>
<template>
<template-type-parameter name="Expr"/>
</template>
<parameter name="expr">
<paramtype>Expr const &amp;</paramtype>
</parameter>
<purpose>A function for deep-copying Proto expression trees. </purpose>
<description>
<para>
A function for deep-copying Proto expression trees. When a tree is deep-copied, all internal
nodes and terminals held by reference are instead held by value.</para>
</description>
<notes>
<para>
Terminals of reference-to-function type are left unchanged.
</para>
<para>
Equivalent to <computeroutput><classname>proto::functional::deep_copy</classname>()(expr)
</computeroutput>.
</para>
</notes>
</function>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,393 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/domain.hpp">
<para>
Contains definition of the <computeroutput><classname alt="boost::proto::domain">proto::domain&lt;&gt;</classname>
</computeroutput> class template and helpers for defining domains with a generator for customizing expression
construction and a grammar for controlling operator overloading.
</para>
<namespace name="boost">
<namespace name="proto">
<!-- proto::domain<> -->
<struct name="domain">
<template>
<template-type-parameter name="Generator">
<default><classname>proto::default_generator</classname></default>
</template-type-parameter>
<template-type-parameter name="Grammar">
<default><classname>proto::_</classname></default>
</template-type-parameter>
<template-type-parameter name="Super">
<default><replaceable>unspecified</replaceable></default>
</template-type-parameter>
</template>
<inherit><type>Generator</type></inherit>
<purpose>For use in defining domain tags to be used with <computeroutput>
<classname alt="proto::extends">proto::extends&lt;&gt;</classname></computeroutput>,
<computeroutput><macroname>BOOST_PROTO_EXTENDS</macroname>()</computeroutput> and
<computeroutput><macroname>BOOST_PROTO_DEFINE_OPERATORS</macroname>()</computeroutput>.
A <emphasis>domain</emphasis> associates an expression type with a <emphasis>generator</emphasis>,
and optionally a <emphasis>grammar</emphasis>. It may also have a super-domain. Expressions
in a sub-domain are interoperable (i.e. can be combined freely with) expressions in a
super-domain. Finally, domains control how non-Proto objects are turned into Proto
expressions and how they are combined to form larger Proto expressions.
</purpose>
<description>
<para>
The Generator parameter determines how new expressions in the domain are post-processed. Typically, a generator
wraps all new expressions in a wrapper that imparts domain-specific behaviors to expressions within
its domain. (See <computeroutput><classname alt="proto::extends">proto::extends&lt;&gt;</classname></computeroutput>.)
</para>
<para>
The Grammar parameter determines whether a given expression is valid within the domain, and automatically
disables any operator overloads which would cause an invalid expression to be created. By default,
the Grammar parameter defaults to the wildcard, <computeroutput><classname>proto::_</classname>
</computeroutput>, which makes all expressions valid within the domain.
</para>
<para>
The Super parameter declares the domain currently being defined to be a sub-domain of Super. An expression in
a sub-domain can be freely combined with expressions in its super-domain (and <emphasis>its</emphasis>
super-domain, etc.).
</para>
<para>
Example: <programlisting> template&lt;typename Expr&gt;
struct MyExpr;
struct MyGrammar
: <classname>proto::or_</classname>&lt; <classname>proto::terminal</classname>&lt;_&gt;, <classname>proto::plus</classname>&lt;MyGrammar, MyGrammar&gt; &gt;
{};
// Define MyDomain, in which all expressions are
// wrapped in MyExpr&lt;&gt; and only expressions that
// conform to MyGrammar are allowed.
struct MyDomain
: <classname>proto::domain</classname>&lt;<classname>proto::generator</classname>&lt;MyExpr&gt;, MyGrammar&gt;
{};
// Use MyDomain to define MyExpr
template&lt;typename Expr&gt;
struct MyExpr
: <classname>proto::extends</classname>&lt;Expr, MyExpr&lt;Expr&gt;, MyDomain&gt;
{
// ...
};
</programlisting>
</para>
<para>
The <computeroutput><classname>domain::as_expr</classname>&lt;&gt;</computeroutput> and
<computeroutput><classname>domain::as_child</classname>&lt;&gt;</computeroutput> member
templates define how non-Proto objects are turned into Proto terminals and how Proto
expressions should be processed before they are combined to form larger expressions.
They can be overridden in a derived domain for customization. See their descriptions to
understand how Proto uses these two templates and what their default behavior is.
</para>
</description>
<typedef name="proto_grammar">
<type>Grammar</type>
</typedef>
<typedef name="proto_generator">
<type>Generator</type>
</typedef>
<typedef name="proto_super_domain">
<type>Super</type>
</typedef>
<struct name="as_expr">
<template>
<template-type-parameter name="T"/>
</template>
<inherit><type><classname>proto::callable</classname></type></inherit>
<purpose>
A callable unary MonomorphicFunctionObject that specifies how objects are turned into
Proto expressions in this domain. The resulting expression object is suitable for storage
in a local variable.
</purpose>
<description>
<para>
A unary MonomorphicFunctionObject that specifies how objects are turned into Proto
expressions in this domain. The resulting expression object is suitable for storage
in a local variable. In that scenario, it is usually preferable to return
expressions by value; and, in the case of objects that are not yet Proto expressions,
to wrap them by value (if possible) in a new Proto terminal expression. (Contrast
this description with the description for
<computeroutput><classname>proto::domain::as_child</classname></computeroutput>.)
</para>
<para>
The <computeroutput>as_expr</computeroutput> function object turns objects into
Proto expressions, if they are not already, by making them Proto terminals held by
value if possible. Objects that are already Proto expressions are simply returned
by value. If
<computeroutput>wants_basic_expr&lt;Generator&gt;::value</computeroutput> is true,
then let <emphasis>E</emphasis> be
<computeroutput><classname>proto::basic_expr</classname></computeroutput>;
otherwise, let <emphasis>E</emphasis> be
<computeroutput><classname>proto::expr</classname></computeroutput>.
Given an lvalue <computeroutput>t</computeroutput> of type
<computeroutput>T</computeroutput>:
<itemizedlist>
<listitem>
If <computeroutput>T</computeroutput> is not a Proto expression type, the resulting
terminal is calculated as follows:
<itemizedlist>
<listitem>
If <computeroutput>T</computeroutput> is a function type, an abstract type, or
a type derived from <computeroutput>std::ios_base</computeroutput>, let
<replaceable>A</replaceable> be <computeroutput>T &amp;</computeroutput>.
</listitem>
<listitem>
Otherwise, let <replaceable>A</replaceable> be the type
<computeroutput>T</computeroutput> stripped of cv-qualifiers.
</listitem>
</itemizedlist>
Then, the result of <computeroutput>as_expr&lt;T&gt;()(t)</computeroutput> is
<computeroutput>Generator()(<replaceable>E</replaceable>&lt;tag::terminal,
term&lt; <replaceable>A</replaceable> &gt; &gt;::make(t))</computeroutput>.
</listitem>
<listitem>
Otherwise, the result is <computeroutput>t</computeroutput> converted to an
(un-const) rvalue.
</listitem>
</itemizedlist>
</para>
</description>
<typedef name="result_type">
<type><replaceable>see-below</replaceable></type>
</typedef>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>result_type</type>
<parameter name="t">
<paramtype>T &amp;</paramtype>
<description>
<para>The object to wrap.</para>
</description>
</parameter>
</method>
</method-group>
</struct>
<struct name="as_child">
<template>
<template-type-parameter name="T"/>
</template>
<inherit><type><classname>proto::callable</classname></type></inherit>
<purpose>
A callable unary MonomorphicFunctionObject that specifies how objects are turned into
Proto expressions in this domain, for use in scenarios where the resulting expression is
intended to be made a child of another expression.
</purpose>
<description>
<para>
A unary MonomorphicFunctionObject that specifies how objects are turned into Proto
expressions in this domain. The resulting expression object is suitable for storage
as a child of another expression. In that scenario, it is usually
preferable to store child expressions by reference; or, in the case of objects that
are not yet Proto expressions, to wrap them by reference in a new Proto terminal
expression. (Contrast this description with the description for
<computeroutput><classname>proto::domain::as_expr</classname></computeroutput>.)
</para>
<para>
The <computeroutput>as_child</computeroutput> function object turns objects into
Proto expressions, if they are not already, by making them Proto terminals held by
reference. Objects that are already Proto expressions are simply returned by
reference. If
<computeroutput>wants_basic_expr&lt;Generator&gt;::value</computeroutput> is true,
then let <emphasis>E</emphasis> be
<computeroutput><classname>proto::basic_expr</classname></computeroutput>;
otherwise, let <emphasis>E</emphasis> be
<computeroutput><classname>proto::expr</classname></computeroutput>.
Given an lvalue <computeroutput>t</computeroutput> of type
<computeroutput>T</computeroutput>:
<itemizedlist>
<listitem>
If <computeroutput>T</computeroutput> is not a Proto expression type, the resulting
terminal is
<computeroutput>Generator()(<replaceable>E</replaceable>&lt;tag::terminal,
term&lt; <computeroutput>T &amp;</computeroutput> &gt; &gt;::make(t))</computeroutput>.
</listitem>
<listitem>
Otherwise, the result is the lvalue <computeroutput>t</computeroutput>.
</listitem>
</itemizedlist>
</para>
</description>
<typedef name="result_type">
<type><replaceable>see-below</replaceable></type>
</typedef>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>result_type</type>
<parameter name="t">
<paramtype>T &amp;</paramtype>
<description>
<para>The object to wrap.</para>
</description>
</parameter>
</method>
</method-group>
</struct>
</struct>
<!-- proto::default_domain -->
<struct name="default_domain">
<inherit><classname>proto::domain</classname>&lt;&gt;</inherit>
<purpose>The domain expressions have by default, if <computeroutput>
<classname alt="proto::extends">proto::extends&lt;&gt;</classname></computeroutput> has not been used
to associate a domain with an expression.</purpose>
</struct>
<!-- proto::basic_default_domain -->
<struct name="basic_default_domain">
<inherit><classname>proto::domain</classname>&lt; <classname>proto::basic_default_generator</classname> &gt;</inherit>
<purpose>A domain similiar in purpose to <classname>proto::default_domain</classname>, except stating
a preference for <classname>proto::basic_expr</classname>&lt;&gt; over <classname>proto::expr</classname>&lt;&gt;.</purpose>
</struct>
<!-- proto::deduce_domain -->
<struct name="deduce_domain">
<purpose>A pseudo-domain for use in functions and metafunctions that require a domain parameter.
It indicates that the domain of the parent node should be inferred from the domains of the child nodes.</purpose>
<description>
<para>
When <computeroutput>proto::deduce_domain</computeroutput> is used as a domain &#x2014; either
explicitly or implicitly by
<computeroutput><functionname>proto::make_expr</functionname>()</computeroutput>,
<computeroutput><functionname>proto::unpack_expr</functionname>()</computeroutput>,
or Proto's operator overloads &#x2014; Proto will use the domains of the child expressions to
compute the domain of the parent. It is done in such a way that (A) expressions in domains
that share a common super-domain are interoperable, and (B) expressions that are in
the default domain (or a sub-domain thereof) are interoperable with <emphasis>all</emphasis>
expressions. The rules are as follows:
<itemizedlist>
<listitem>
A sub-domain is <emphasis>stronger</emphasis> than its super-domain.
</listitem>
<listitem>
<computeroutput><classname>proto::default_domain</classname></computeroutput>,
<computeroutput><classname>proto::basic_default_domain</classname></computeroutput>
and all their sub-domains are <emphasis>weaker</emphasis> than all other domains.
</listitem>
<listitem>
<computeroutput><classname>proto::basic_default_domain</classname></computeroutput>
is weaker than
<computeroutput><classname>proto::default_domain</classname></computeroutput>.
</listitem>
<listitem>
For each child, define a set of domains <emphasis>S<subscript>N</subscript></emphasis>
that includes the child's domain and all its super-domains.
</listitem>
<listitem>
Define a set <emphasis>I<subscript>S</subscript></emphasis> that is the intersection of
all the individual sets <emphasis>S<subscript>N</subscript></emphasis> that don't contain
<computeroutput><classname>proto::default_domain</classname></computeroutput> or
<computeroutput><classname>proto::basic_default_domain</classname></computeroutput>.
</listitem>
<listitem>
Define a set <emphasis>I<subscript>W</subscript></emphasis> that is the intersection of
all the individual sets <emphasis>S<subscript>N</subscript></emphasis> that contain
<computeroutput><classname>proto::default_domain</classname></computeroutput> or
<computeroutput><classname>proto::basic_default_domain</classname></computeroutput>.
</listitem>
<listitem>
Define a set <emphasis>P</emphasis> that is the union of
<emphasis>I<subscript>S</subscript></emphasis> and
<emphasis>I<subscript>W</subscript></emphasis>.
</listitem>
<listitem>
The common domain is the strongest domain in set <emphasis>P</emphasis>, with the
following caveats.
</listitem>
<listitem>
Let <emphasis>U</emphasis> be the union of all sets
<emphasis>S<subscript>N</subscript></emphasis>. If the result is
<computeroutput><classname>proto::default_domain</classname></computeroutput> or
<computeroutput><classname>proto::basic_default_domain</classname></computeroutput>
and <emphasis>U</emphasis> contains an element that is <emphasis>not </emphasis>
<computeroutput><classname>proto::default_domain</classname></computeroutput> or
<computeroutput><classname>proto::basic_default_domain</classname></computeroutput>,
it is an error.
</listitem>
</itemizedlist>
</para>
<para>
Note: the above description sounds like it would be expensive to compute at compile time.
In fact, it can all be done using C++ function overloading.
</para>
</description>
</struct>
<!-- proto::is_domain -->
<struct name="is_domain">
<template>
<template-type-parameter name="T"/>
</template>
<inherit>
<type>mpl::bool_&lt; <replaceable>true-or-false</replaceable> &gt;</type>
</inherit>
<description>
<para>
A metafunction that returns <computeroutput>mpl::true_</computeroutput> if the type
<computeroutput>T</computeroutput> is the type of a Proto domain;
<computeroutput>mpl::false_</computeroutput> otherwise. If <computeroutput>T</computeroutput>
inherits from <computeroutput><classname alt="proto::domain">proto::domain&lt;&gt;</classname></computeroutput>,
<computeroutput>is_domain&lt;T&gt;</computeroutput> is <computeroutput>mpl::true_</computeroutput>.
</para>
</description>
</struct>
<!-- proto::domain_of -->
<struct name="domain_of">
<template>
<template-type-parameter name="T"/>
</template>
<description>
<para>
A metafunction that returns the domain of a given type. If <computeroutput>T</computeroutput> is a Proto
expression type, it returns that expression's associated domain. If not, it returns
<computeroutput><classname>proto::default_domain</classname></computeroutput>.
</para>
</description>
<typedef name="type">
<type><replaceable>domain-of-T</replaceable></type>
</typedef>
</struct>
<!-- proto::base_expr --><!--
<struct name="base_expr">
<template>
<template-type-parameter name="Domain"/>
<template-type-parameter name="Tag"/>
<template-type-parameter name="Args"/>
</template>
<description>
<para>
Given a domain, a tag type and an argument list,
compute the type of the expression to generate. This is
either an instance of
<computeroutput><classname>proto::basic_expr</classname>&lt;&gt;</computeroutput> or
<computeroutput><classname>proto::expr</classname>&lt;&gt;</computeroutput>.
</para>
</description>
<typedef name="A">
<purpose>For exposition only</purpose>
<type><classname>proto::basic_expr</classname>&lt; Tag, Args &gt;</type>
</typedef>
<typedef name="B">
<purpose>For exposition only</purpose>
<type><classname>proto::expr</classname>&lt; Tag, Args &gt;</type>
</typedef>
<typedef name="type">
<type>typename mpl::if_&lt;<classname>proto::wants_basic_expr</classname>&lt; Domain &gt;, A, B&gt;::type</type>
</typedef>
</struct>-->
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,149 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/eval.hpp">
<para>
Contains the
<computeroutput>
<functionname alt="boost::proto::eval">proto::eval()</functionname>
</computeroutput> expression evaluator.
</para>
<namespace name="boost">
<namespace name="proto">
<namespace name="functional">
<!-- proto::functional::eval-->
<struct name="eval">
<purpose>A <conceptname>PolymorphicFunctionObject</conceptname> type for evaluating a given Proto
expression with a given context.</purpose>
<inherit>
<type><classname>proto::callable</classname></type>
</inherit>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="Expr"/>
<template-type-parameter name="Context"/>
</template>
<specialization>
<template-arg>This(Expr, Context)</template-arg>
</specialization>
<inherit>
<type>
<classname>proto::result_of::eval</classname>&lt;
typename boost::remove_reference&lt; Expr &gt;::type,
typename boost::remove_reference&lt; Context &gt;::type
&gt;</type>
</inherit>
</struct-specialization>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>typename <classname>proto::result_of::eval</classname>&lt; Expr, Context &gt;::type</type>
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="Context"/>
</template>
<parameter name="expr">
<paramtype>Expr &amp;</paramtype>
<description>
<para>The Proto expression to evaluate.</para>
</description>
</parameter>
<parameter name="context">
<paramtype>Context &amp;</paramtype>
<description>
<para>The context in which the expression should be evaluated. </para>
</description>
</parameter>
<purpose>Evaluate a given Proto expression with a given context. </purpose>
<returns>
<para>
<computeroutput>typename Context::template eval&lt;Expr&gt;()(expr, context)</computeroutput>
</para>
</returns>
</method>
<method name="operator()" cv="const">
<type>typename <classname>proto::result_of::eval</classname>&lt; Expr, Context &gt;::type</type>
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="Context"/>
</template>
<parameter name="expr">
<paramtype>Expr &amp;</paramtype>
</parameter>
<parameter name="context">
<paramtype>Context const &amp;</paramtype>
</parameter>
<description>
<para>
This is an overloaded member function, provided for convenience. It differs from the above
function only in what argument(s) it accepts.
</para>
</description>
</method>
</method-group>
</struct>
</namespace>
<namespace name="result_of">
<!-- proto::result_of::eval -->
<struct name="eval">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="Context"/>
</template>
<purpose>A metafunction for calculating the return type of <computeroutput>
<functionname alt="proto::eval">proto::eval()</functionname></computeroutput> given a
certain <computeroutput>Expr</computeroutput> and <computeroutput>Context</computeroutput> types.</purpose>
<typedef name="type">
<type>typename Context::template eval&lt; Expr &gt;::result_type</type>
</typedef>
</struct>
</namespace>
<!-- proto::eval() -->
<overloaded-function name="eval">
<signature>
<type>typename <classname>proto::result_of::eval</classname>&lt; Expr, Context &gt;::type</type>
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="Context"/>
</template>
<parameter name="expr">
<paramtype>Expr &amp;</paramtype>
<description>
<para>The Proto expression to evaluate.</para>
</description>
</parameter>
<parameter name="context">
<paramtype>Context &amp;</paramtype>
<description>
<para>The context in which the expression should be evaluated.</para>
</description>
</parameter>
</signature>
<signature>
<type>typename <classname>proto::result_of::eval</classname>&lt; Expr, Context &gt;::type</type>
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="Context"/>
</template>
<parameter name="expr">
<paramtype>Expr &amp;</paramtype>
</parameter>
<parameter name="context">
<paramtype>Context const &amp;</paramtype>
</parameter>
</signature>
<purpose>Evaluate a given Proto expression with a given context. </purpose>
<returns>
<para>
<computeroutput>typename Context::template eval&lt;Expr&gt;()(expr, context)</computeroutput>
</para>
</returns>
</overloaded-function>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,496 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/expr.hpp">
<namespace name="boost">
<namespace name="proto">
<!-- boost::proto::basic_expr -->
<struct name="basic_expr">
<template>
<template-type-parameter name="Tag"/>
<template-type-parameter name="Args"/>
<template-nontype-parameter name="Arity">
<type>long</type>
<default>Args::arity</default>
</template-nontype-parameter>
</template>
<purpose>Simplified representation of a node in an expression tree.</purpose>
<description>
<para>
<computeroutput>proto::basic_expr&lt;&gt;</computeroutput> is a node in an expression
template tree. It is a container for its child sub-trees. It also serves as the
terminal nodes of the tree.
</para>
<para>
<computeroutput>Tag</computeroutput> is type that represents the operation
encoded by this expression. It is typically one of the structs in the
<computeroutput>boost::proto::tag</computeroutput> namespace, but it doesn't
have to be. If <computeroutput>Arity</computeroutput> is 0 then this
<computeroutput>expr&lt;&gt;</computeroutput> type represents a leaf in the
expression tree.
</para>
<para>
<computeroutput>Args</computeroutput> is a list of types representing
the children of this expression. It is an instantiation of one of
<computeroutput><classname alt="proto::listN">proto::list1&lt;&gt;</classname></computeroutput>,
<computeroutput><classname alt="proto::listN">proto::list2&lt;&gt;</classname></computeroutput>,
etc. The child types
must all themselves be either <computeroutput>proto::expr&lt;&gt;</computeroutput>
or <computeroutput>proto::basic_expr&lt;&gt;&amp;</computeroutput> (or extensions thereof via
<computeroutput><classname>proto::extends&lt;&gt;</classname></computeroutput> or
<computeroutput><macroname>BOOST_PROTO_EXTENDS</macroname>()</computeroutput>), unless
<computeroutput>Arity</computeroutput> is 0, in which case
<computeroutput>Args</computeroutput> must be
<computeroutput>proto::term&lt;T&gt;</computeroutput>, where
<computeroutput>T</computeroutput> can be any type.
</para>
<para>
<computeroutput>proto::basic_expr&lt;&gt;</computeroutput> is a valid Fusion
random-access sequence, where the elements of the sequence are the child
expressions.
</para>
</description>
<!-- typedefs -->
<typedef name="proto_tag">
<type>Tag</type>
</typedef>
<typedef name="proto_args">
<type>Args</type>
</typedef>
<typedef name="proto_arity">
<type>mpl::long_&lt; Arity &gt;</type>
</typedef>
<typedef name="proto_domain">
<type><classname>proto::basic_default_domain</classname></type>
</typedef>
<typedef name="proto_grammar">
<type>basic_expr</type>
</typedef>
<typedef name="proto_base_expr">
<type>basic_expr</type>
</typedef>
<typedef name="proto_derived_expr">
<type>basic_expr</type>
</typedef>
<typedef name="proto_childN">
<type>typename Args::child<replaceable>N</replaceable></type>
<purpose>For each <replaceable>N</replaceable> in <replaceable>[0,max(Arity,1))</replaceable>.</purpose>
</typedef>
<method-group name="public static functions">
<!-- make -->
<method name="make" specifiers="static">
<type>basic_expr const</type>
<template>
<template-type-parameter name="A" pack="1"/>
</template>
<parameter name="a" pack="1">
<paramtype>A const &amp;</paramtype>
</parameter>
<requires>
<para>
The number of supplied arguments must be <computeroutput>max(Arity,1)</computeroutput>.
</para>
</requires>
<returns>
<para>
A new <computeroutput>basic_expr</computeroutput> object initialized with the specified arguments.
</para>
</returns>
</method>
</method-group>
<method-group name="public member functions">
<method name="proto_base">
<type>basic_expr &amp;</type>
<returns>
<para>
<computeroutput>*this</computeroutput>
</para>
</returns>
</method>
<method name="proto_base" cv="const">
<type>basic_expr const &amp;</type>
<description>
<para>
This is an overloaded member function, provided for convenience. It differs from
the above function only in what argument(s) it accepts.
</para>
</description>
</method>
</method-group>
</struct>
<!-- boost::proto::expr -->
<struct name="expr">
<template>
<template-type-parameter name="Tag"/>
<template-type-parameter name="Args"/>
<template-nontype-parameter name="Arity">
<type>long</type>
<default>Args::arity</default>
</template-nontype-parameter>
</template>
<purpose>Representation of a node in an expression tree.</purpose>
<description>
<para>
<computeroutput>proto::expr&lt;&gt;</computeroutput> is a node in an expression
template tree. It is a container for its child sub-trees. It also serves as the
terminal nodes of the tree.
</para>
<para>
<computeroutput>Tag</computeroutput> is type that represents the operation
encoded by this expression. It is typically one of the structs in the
<computeroutput>boost::proto::tag</computeroutput> namespace, but it doesn't
have to be. If <computeroutput>Arity</computeroutput> is 0 then this
<computeroutput>expr&lt;&gt;</computeroutput> type represents a leaf in the
expression tree.
</para>
<para>
<computeroutput>Args</computeroutput> is a list of types representing
the children of this expression. It is an instantiation of one of
<computeroutput><classname alt="proto::listN">proto::list1&lt;&gt;</classname></computeroutput>,
<computeroutput><classname alt="proto::listN">proto::list2&lt;&gt;</classname></computeroutput>,
etc. The child types
must all themselves be either <computeroutput>proto::expr&lt;&gt;</computeroutput>
or <computeroutput>proto::basic_expr&lt;&gt;&amp;</computeroutput> (or extensions thereof via
<computeroutput><classname>proto::extends&lt;&gt;</classname></computeroutput> or
<computeroutput><macroname>BOOST_PROTO_EXTENDS</macroname>()</computeroutput>), unless
<computeroutput>Arity</computeroutput> is 0, in which case
<computeroutput>Args</computeroutput> must be
<computeroutput>proto::term&lt;T&gt;</computeroutput>, where
<computeroutput>T</computeroutput> can be any type.
</para>
<para>
<computeroutput>proto::expr&lt;&gt;</computeroutput> is a valid Fusion
random-access sequence, where the elements of the sequence are the child
expressions.
</para>
</description>
<!-- typedefs -->
<typedef name="proto_tag">
<type>Tag</type>
</typedef>
<typedef name="proto_args">
<type>Args</type>
</typedef>
<typedef name="proto_arity">
<type>mpl::long_&lt; Arity &gt;</type>
</typedef>
<typedef name="proto_domain">
<type><classname>proto::default_domain</classname></type>
</typedef>
<typedef name="proto_grammar">
<type><classname>proto::basic_expr</classname>&lt; Tag, Args, Arity &gt;</type>
</typedef>
<typedef name="proto_base_expr">
<type>expr</type>
</typedef>
<typedef name="proto_derived_expr">
<type>expr</type>
</typedef>
<typedef name="proto_childN">
<type>typename Args::child<replaceable>N</replaceable></type>
<purpose>For each <replaceable>N</replaceable> in <replaceable>[0,max(Arity,1))</replaceable>.</purpose>
</typedef>
<struct name="result">
<template>
<template-type-parameter name="Signature"/>
</template>
<description>
<para>
Encodes the return type of <computeroutput><classname>proto::expr&lt;&gt;</classname>::operator()</computeroutput>.
Makes <computeroutput><classname>proto::expr&lt;&gt;</classname></computeroutput> a TR1-style function object type
usable with <computeroutput>boost::result_of&lt;&gt;</computeroutput>
</para>
</description>
<typedef name="type">
<type><replaceable>unspecified</replaceable></type>
</typedef>
</struct>
<method-group name="public static functions">
<!-- make -->
<method name="make" specifiers="static">
<type>expr const</type>
<template>
<template-type-parameter name="A" pack="1"/>
</template>
<parameter name="a" pack="1">
<paramtype>A const &amp;</paramtype>
</parameter>
<requires>
<para>
The number of supplied arguments must be <computeroutput>max(Arity,1)</computeroutput>.
</para>
</requires>
<returns>
<para>
A new <computeroutput>expr</computeroutput> object initialized with the specified arguments.
</para>
</returns>
</method>
</method-group>
<method-group name="public member functions">
<method name="proto_base">
<type>expr &amp;</type>
<returns><para><computeroutput>*this</computeroutput></para></returns>
</method>
<method name="proto_base" cv="const">
<type>expr const &amp;</type>
<description>
<para>This is an overloaded member function, provided for convenience. It differs from
the above function only in what argument(s) it accepts.</para>
</description>
</method>
<!-- operator= -->
<method name="operator=">
<type><replaceable>unspecified</replaceable></type>
<template>
<template-type-parameter name="A"/>
</template>
<parameter name="a">
<paramtype>A &amp;</paramtype>
</parameter>
<description>
<para>Lazy assignment expression</para>
</description>
<returns>
<para>A new expression node representing the assignment operation.</para>
</returns>
</method>
<method name="operator=">
<type><replaceable>unspecified</replaceable></type>
<template>
<template-type-parameter name="A"/>
</template>
<parameter name="a">
<paramtype>A const &amp;</paramtype>
</parameter>
<description>
<para>
This is an overloaded member function, provided for convenience. It differs from
the above function only in what argument(s) it accepts.
</para>
</description>
</method>
<method name="operator=" cv="const">
<type><replaceable>unspecified</replaceable></type>
<template>
<template-type-parameter name="A"/>
</template>
<parameter name="a">
<paramtype>A &amp;</paramtype>
</parameter>
<description>
<para>
This is an overloaded member function, provided for convenience. It differs from
the above function only in what argument(s) it accepts.
</para>
</description>
</method>
<method name="operator=" cv="const">
<type><replaceable>unspecified</replaceable></type>
<template>
<template-type-parameter name="A"/>
</template>
<parameter name="a">
<paramtype>A const &amp;</paramtype>
</parameter>
<description>
<para>
This is an overloaded member function, provided for convenience. It differs from
the above function only in what argument(s) it accepts.
</para>
</description>
</method>
<!-- operator[] -->
<method name="operator[]">
<type><replaceable>unspecified</replaceable></type>
<template>
<template-type-parameter name="A"/>
</template>
<parameter name="a">
<paramtype>A &amp;</paramtype>
</parameter>
<description>
<para>Lazy subscript expression</para>
</description>
<returns>
<para>A new expression node representing the subscript operation.</para>
</returns>
</method>
<method name="operator[]">
<type><replaceable>unspecified</replaceable></type>
<template>
<template-type-parameter name="A"/>
</template>
<parameter name="a">
<paramtype>A const &amp;</paramtype>
</parameter>
<description>
<para>
This is an overloaded member function, provided for convenience. It differs from
the above function only in what argument(s) it accepts.
</para>
</description>
</method>
<method name="operator[]" cv="const">
<type><replaceable>unspecified</replaceable></type>
<template>
<template-type-parameter name="A"/>
</template>
<parameter name="a">
<paramtype>A &amp;</paramtype>
</parameter>
<description>
<para>
This is an overloaded member function, provided for convenience. It differs from
the above function only in what argument(s) it accepts.
</para>
</description>
</method>
<method name="operator[]" cv="const">
<type><replaceable>unspecified</replaceable></type>
<template>
<template-type-parameter name="A"/>
</template>
<parameter name="a">
<paramtype>A const &amp;</paramtype>
</parameter>
<description>
<para>
This is an overloaded member function, provided for convenience. It differs from
the above function only in what argument(s) it accepts.
</para>
</description>
</method>
<!-- operator() -->
<method name="operator()">
<type><replaceable>unspecified</replaceable></type>
<template>
<template-type-parameter name="A" pack="1"/>
</template>
<parameter name="a" pack="1">
<paramtype>A const &amp;</paramtype>
</parameter>
<description>
<para>Lazy function call</para>
</description>
<returns>
<para>A new expression node representing the function call operation.</para>
</returns>
</method>
<method name="operator()" cv="const">
<type><replaceable>unspecified</replaceable></type>
<template>
<template-type-parameter name="A" pack="1"/>
</template>
<parameter name="a" pack="1">
<paramtype>A const &amp;</paramtype>
</parameter>
<description>
<para>
This is an overloaded member function, provided for convenience. It differs from
the above function only in what argument(s) it accepts.
</para>
</description>
</method>
</method-group>
<data-member name="childN">
<type>proto_child<replaceable>N</replaceable></type>
<purpose>For each <replaceable>N</replaceable> in <replaceable>[0,max(Arity,1))</replaceable>.</purpose>
</data-member>
<data-member name="proto_arity_c" specifiers="static">
<type>const long</type>
<purpose>
<computeroutput>= Arity;</computeroutput>
</purpose>
</data-member>
</struct>
<!-- proto::unexpr -->
<struct name="unexpr">
<template>
<template-type-parameter name="Expr"/>
</template>
<purpose>Lets you inherit the interface of an expression while hiding from Proto the fact that
the type is a Proto expression.</purpose>
<inherit><type>Expr</type></inherit>
<method-group name="public member functions"/>
<constructor>
<parameter name="expr">
<paramtype>Expr const &amp;</paramtype>
</parameter>
</constructor>
<description>
<para>
For an expression type <computeroutput>E</computeroutput>,
<computeroutput>
<classname>proto::is_expr</classname>&lt;E&gt;::value
</computeroutput> is <computeroutput>true</computeroutput>, but
<computeroutput>
<classname>proto::is_expr</classname>&lt;proto::unexpr&lt;E&gt; &gt;::value
</computeroutput> is <computeroutput>false</computeroutput>.
</para>
</description>
</struct>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,635 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/extends.hpp">
<para>Macros and a base class for defining end-user expression types </para>
<namespace name="boost">
<namespace name="proto">
<!-- proto::is_proto_expr -->
<struct name="is_proto_expr">
<purpose>Empty type to be used as a dummy template parameter of POD expression wrappers. It allows
argument-dependent lookup to find Proto's operator overloads.</purpose>
<description>
<para>
<computeroutput>proto::is_proto_expr</computeroutput> allows argument-dependent lookup to find Proto's operator overloads. For example:
</para>
<para>
<programlisting> template&lt;typename T, typename Dummy = <classname>proto::is_proto_expr</classname>&gt;
struct my_terminal
{
<macroname>BOOST_PROTO_BASIC_EXTENDS</macroname>(
typename <classname>proto::terminal</classname>&lt;T&gt;::type
, my_terminal&lt;T&gt;
, <classname>proto::default_domain</classname>
)
};
// ...
my_terminal&lt;int&gt; _1, _2;
_1 + _2; // OK, uses proto::operator+</programlisting>
</para>
<para>
Without the second <computeroutput>Dummy</computeroutput> template parameter, Proto's operator overloads
would not be considered by name lookup.
</para>
</description>
</struct>
<!-- proto::extends -->
<struct name="extends">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="Derived"/>
<template-type-parameter name="Domain">
<default><classname>proto::default_domain</classname></default>
</template-type-parameter>
</template>
<purpose>For adding behaviors to a Proto expression template.</purpose>
<description>
<para>
Use <computeroutput>proto::extends&lt;&gt;</computeroutput> to give expressions in your
domain custom data members and member functions.
</para>
<para>
Conceptually, using <computeroutput>proto::extends&lt;&gt;</computeroutput> is akin
to inheriting from <computeroutput><classname>proto::expr</classname>&lt;&gt;</computeroutput>
and adding your own members. Using <computeroutput>proto::extends&lt;&gt;</computeroutput> is
generally preferrable to straight inheritance because the members that would be inherited from
<computeroutput><classname>proto::expr</classname>&lt;&gt;</computeroutput> would
be wrong; they would incorrectly slice off your additional members when building
larger expressions from smaller ones. <computeroutput>proto::extends&lt;&gt;</computeroutput>
automatically gives your expression types the appropriate operator overloads that
preserve your domain-specific members when composing expression trees.
</para>
<para>
Expression extensions are typically defined as follows:
</para>
<para>
<programlisting>template&lt; typename Expr &gt;
struct my_expr
: proto::extends&lt;
Expr // The expression type we're extending
, my_expr&lt; Expr &gt; // The type we're defining
, my_domain // The domain associated with this expression extension
&gt;
{
// An expression extension is constructed from the expression
// it is extending.
my_expr( Expr const &amp; e = Expr() )
: my_expr::proto_extends( e )
{}
// Unhide proto::extends::operator=
// (This is only necessary if a lazy assignment operator
// makes sense for your domain-specific language.)
BOOST_PROTO_EXTENDS_USING_ASSIGN(my_expr)
/*
... domain-specific members go here ...
*/
};</programlisting>
</para>
<para>
See also:
<itemizedlist>
<listitem>
<computeroutput><macroname>BOOST_PROTO_EXTENDS</macroname>()</computeroutput>
</listitem>
<listitem>
<computeroutput><macroname>BOOST_PROTO_EXTENDS_USING_ASSIGN</macroname>()</computeroutput>
</listitem>
<listitem>
<computeroutput><macroname>BOOST_PROTO_EXTENDS_USING_ASSIGN_NON_DEPENDENT</macroname>()</computeroutput>
</listitem>
</itemizedlist>
</para>
</description>
<struct name="result">
<template>
<template-type-parameter name="Signature"/>
</template>
<typedef name="type">
<type><replaceable>unspecified</replaceable></type>
</typedef>
<description>
<para>So that <computeroutput>boost::result_of&lt;&gt;</computeroutput>
can compute the return type of <computeroutput>proto::extends::operator()</computeroutput>.
</para>
</description>
</struct>
<typedef name="proto_base_expr">
<type>typename Expr::proto_base_expr</type>
</typedef>
<typedef name="proto_domain">
<type>Domain</type>
</typedef>
<typedef name="proto_derived_expr">
<type>Derived</type>
</typedef>
<typedef name="proto_extends">
<type>extends</type>
</typedef>
<typedef name="proto_tag">
<type>typename proto_base_expr::proto_tag</type>
</typedef>
<typedef name="proto_args">
<type>typename proto_base_expr::proto_args</type>
</typedef>
<typedef name="proto_arity">
<type>typename proto_base_expr::proto_arity</type>
</typedef>
<typedef name="proto_grammar">
<type>typename proto_base_expr::proto_grammar</type>
</typedef>
<typedef name="proto_childN">
<purpose>For each <replaceable>N</replaceable> in <replaceable>[0,max(1,proto_arity_c))</replaceable></purpose>
<type>typename proto_base_expr::proto_child<replaceable>N</replaceable></type>
</typedef>
<!-- constructors -->
<constructor/>
<constructor>
<parameter name="that">
<paramtype><classname>extends</classname> const &amp;</paramtype>
</parameter>
</constructor>
<constructor>
<parameter name="expr_">
<paramtype>Expr const &amp;</paramtype>
</parameter>
</constructor>
<method-group name="public static functions">
<method name="make" specifiers="static">
<type>Derived const</type>
<parameter name="expr">
<paramtype>Expr const &amp;</paramtype>
</parameter>
<description>
<para>Construct an expression extension from the base expression.</para>
</description>
<return>Derived(expr)</return>
</method>
</method-group>
<method-group name="public member functions">
<!-- proto_base() -->
<method name="proto_base">
<type>proto_base_expr &amp;</type>
<returns><computeroutput>proto_expr_.proto_base()</computeroutput></returns>
<throws><simpara>Will not throw.</simpara></throws>
</method>
<method name="proto_base" cv="const">
<type>proto_base_expr const &amp;</type>
<returns><computeroutput>proto_expr_.proto_base()</computeroutput></returns>
<throws><simpara>Will not throw.</simpara></throws>
</method>
<!-- operator= -->
<method name="operator=">
<type><replaceable>unspecified</replaceable></type>
<template>
<template-type-parameter name="A"/>
</template>
<parameter name="a">
<paramtype>A &amp;</paramtype>
</parameter>
<description>
<para>Lazy assignment expression</para>
</description>
<returns>
<para>A new expression node representing the assignment operation.</para>
</returns>
</method>
<method name="operator=">
<type><replaceable>unspecified</replaceable></type>
<template>
<template-type-parameter name="A"/>
</template>
<parameter name="a">
<paramtype>A const &amp;</paramtype>
</parameter>
<description>
<para>
This is an overloaded member function, provided for convenience. It differs from
the above function only in what argument(s) it accepts.
</para>
</description>
</method>
<method name="operator=" cv="const">
<type><replaceable>unspecified</replaceable></type>
<template>
<template-type-parameter name="A"/>
</template>
<parameter name="a">
<paramtype>A &amp;</paramtype>
</parameter>
<description>
<para>
This is an overloaded member function, provided for convenience. It differs from
the above function only in what argument(s) it accepts.
</para>
</description>
</method>
<method name="operator=" cv="const">
<type><replaceable>unspecified</replaceable></type>
<template>
<template-type-parameter name="A"/>
</template>
<parameter name="a">
<paramtype>A const &amp;</paramtype>
</parameter>
<description>
<para>
This is an overloaded member function, provided for convenience. It differs from
the above function only in what argument(s) it accepts.
</para>
</description>
</method>
<!-- operator[] -->
<method name="operator[]">
<type><replaceable>unspecified</replaceable></type>
<template>
<template-type-parameter name="A"/>
</template>
<parameter name="a">
<paramtype>A &amp;</paramtype>
</parameter>
<description>
<para>Lazy subscript expression</para>
</description>
<returns>
<para>A new expression node representing the subscript operation.</para>
</returns>
</method>
<method name="operator[]">
<type><replaceable>unspecified</replaceable></type>
<template>
<template-type-parameter name="A"/>
</template>
<parameter name="a">
<paramtype>A const &amp;</paramtype>
</parameter>
<description>
<para>
This is an overloaded member function, provided for convenience. It differs from
the above function only in what argument(s) it accepts.
</para>
</description>
</method>
<method name="operator[]" cv="const">
<type><replaceable>unspecified</replaceable></type>
<template>
<template-type-parameter name="A"/>
</template>
<parameter name="a">
<paramtype>A &amp;</paramtype>
</parameter>
<description>
<para>
This is an overloaded member function, provided for convenience. It differs from
the above function only in what argument(s) it accepts.
</para>
</description>
</method>
<method name="operator[]" cv="const">
<type><replaceable>unspecified</replaceable></type>
<template>
<template-type-parameter name="A"/>
</template>
<parameter name="a">
<paramtype>A const &amp;</paramtype>
</parameter>
<description>
<para>
This is an overloaded member function, provided for convenience. It differs from
the above function only in what argument(s) it accepts.
</para>
</description>
</method>
<!-- operator() -->
<method name="operator()">
<type><replaceable>unspecified</replaceable></type>
<template>
<template-type-parameter name="A" pack="1"/>
</template>
<parameter name="a" pack="1">
<paramtype>A const &amp;</paramtype>
</parameter>
<description>
<para>Lazy function call</para>
</description>
<returns>
<para>A new expression node representing the function call operation.</para>
</returns>
</method>
<method name="operator()" cv="const">
<type><replaceable>unspecified</replaceable></type>
<template>
<template-type-parameter name="A" pack="1"/>
</template>
<parameter name="a" pack="1">
<paramtype>A const &amp;</paramtype>
</parameter>
<description>
<para>
This is an overloaded member function, provided for convenience. It differs from
the above function only in what argument(s) it accepts.
</para>
</description>
</method>
</method-group>
<data-member name="proto_expr_">
<type>Expr</type>
<purpose>For exposition only.</purpose>
</data-member>
<data-member name="proto_arity_c" specifiers="static">
<type>const long</type>
<purpose><computeroutput>= proto_base_expr::proto_arity_c;</computeroutput></purpose>
</data-member>
</struct>
</namespace>
</namespace>
<macro name="BOOST_PROTO_EXTENDS" kind="functionlike">
<macro-parameter name="Expr"/>
<macro-parameter name="Derived"/>
<macro-parameter name="Domain"/>
<purpose>For creating expression wrappers that add behaviors to a Proto expression template, like
<computeroutput><classname alt="boost::proto::extends">proto::extends&lt;&gt;</classname></computeroutput>,
but while retaining POD-ness of the expression wrapper.</purpose>
<description>
<para>
Equivalent to:
<programlisting><macroname>BOOST_PROTO_BASIC_EXTENDS</macroname>(Expr, Derived, Domain)
<macroname>BOOST_PROTO_EXTENDS_ASSIGN</macroname>()
<macroname>BOOST_PROTO_EXTENDS_SUBSCRIPT</macroname>()
<macroname>BOOST_PROTO_EXTENDS_FUNCTION</macroname>()</programlisting>
</para>
<para>If the <computeroutput>Domain</computeroutput> parameter is dependent, you can specify it as
<computeroutput>typename Domain</computeroutput>, as in
<computeroutput>BOOST_PROTO_EXTENDS(Expr, Derived, typename Domain)</computeroutput>
</para>
<para>
<emphasis role="bold">Example:</emphasis><programlisting>template&lt; class Expr &gt;
struct my_expr;
struct my_domain
: <classname alt="boost::proto::domain">proto::domain</classname>&lt; <classname alt="boost::proto::pod_generator">proto::pod_generator</classname>&lt; my_expr &gt; &gt;
{};
template&lt; class Expr &gt;
struct my_expr
{
// OK, this makes my_expr&lt;&gt; a valid Proto expression extension.
// my_expr&lt;&gt; has overloaded assignment, subscript,
// and function call operators that build expression templates.
<macroname>BOOST_PROTO_EXTENDS</macroname>(Expr, my_expr, my_domain)
};
// OK, my_expr&lt;&gt; is POD, so this is statically initialized:
my_expr&lt; <classname alt="boost::proto::terminal">proto::terminal</classname>&lt;int&gt;::type &gt; const _1 = {{1}};</programlisting>
</para>
</description>
</macro>
<macro name="BOOST_PROTO_BASIC_EXTENDS" kind="functionlike">
<macro-parameter name="Expr"/>
<macro-parameter name="Derived"/>
<macro-parameter name="Domain"/>
<purpose>For creating expression wrappers that add members to a Proto expression template, like
<computeroutput><classname alt="boost::proto::extends">proto::extends&lt;&gt;</classname></computeroutput>,
but while retaining POD-ness of the expression wrapper.</purpose>
<description>
<para>
<computeroutput>BOOST_PROTO_BASIC_EXTENDS()</computeroutput> adds the basic typedefs, member functions, and
data members necessary to make a struct a valid Proto expression extension. It does <emphasis>not</emphasis>
add any constructors, virtual functions or access control blocks that would render the containing
struct non-POD.
</para>
<para>
<computeroutput>Expr</computeroutput> is the Proto expression that the enclosing struct extends.
<computeroutput>Derived</computeroutput> is the type of the enclosing struct.
<computeroutput>Domain</computeroutput> is the Proto domain to which this expression extension belongs.
(See <computeroutput><classname alt="boost::proto::domain">proto::domain&lt;&gt;</classname></computeroutput>.)
Can be preceeded with "<computeroutput>typename</computeroutput>" if the specified domain is a dependent type.
</para>
<para><computeroutput>BOOST_PROTO_BASIC_EXTENDS()</computeroutput> adds to its enclosing struct
exactly one data member of type <computeroutput>Expr</computeroutput>.
</para>
<para>If the <computeroutput>Domain</computeroutput> parameter is dependent, you can specify it as
<computeroutput>typename Domain</computeroutput>, as in
<computeroutput>BOOST_PROTO_BASIC_EXTENDS(Expr, Derived, typename Domain)</computeroutput>
</para>
<para>
<emphasis role="bold">Example:</emphasis><programlisting>template&lt; class Expr &gt;
struct my_expr;
struct my_domain
: <classname alt="boost::proto::domain">proto::domain</classname>&lt; <classname alt="boost::proto::pod_generator">proto::pod_generator</classname>&lt; my_expr &gt; &gt;
{};
template&lt; class Expr &gt;
struct my_expr
{
// OK, this makes my_expr&lt;&gt; a valid Proto expression extension.
// my_expr&lt;&gt; does /not/ have overloaded assignment, subscript,
// and function call operators that build expression templates, however.
<macroname>BOOST_PROTO_BASIC_EXTENDS</macroname>(Expr, my_expr, my_domain)
};
// OK, my_expr&lt;&gt; is POD, so this is statically initialized:
my_expr&lt; <classname alt="boost::proto::terminal">proto::terminal</classname>&lt;int&gt;::type &gt; const _1 = {{1}};</programlisting>
</para>
<para>
See also:
<itemizedlist>
<listitem>
<computeroutput><macroname>BOOST_PROTO_EXTENDS_ASSIGN</macroname>()</computeroutput>
</listitem>
<listitem>
<computeroutput><macroname>BOOST_PROTO_EXTENDS_SUBSCRIPT</macroname>()</computeroutput>
</listitem>
<listitem>
<computeroutput><macroname>BOOST_PROTO_EXTENDS_FUNCTION</macroname>()</computeroutput>
</listitem>
<listitem>
<computeroutput><macroname>BOOST_PROTO_EXTENDS</macroname>()</computeroutput>
</listitem>
</itemizedlist>
</para>
</description>
</macro>
<macro name="BOOST_PROTO_EXTENDS_ASSIGN" kind="functionlike">
<purpose>For adding to an expression extension class an overloaded assignment operator that
builds an expression template.</purpose>
<description>
<para>
Use <computeroutput>BOOST_PROTO_EXTENDS_ASSIGN()</computeroutput> after <computeroutput>
<macroname>BOOST_PROTO_BASIC_EXTENDS</macroname>()</computeroutput> to give an expression
extension class an overloaded assignment operator that builds an expression template.
</para>
<para>
See also:
<itemizedlist>
<listitem>
<computeroutput><macroname>BOOST_PROTO_BASIC_EXTENDS</macroname>()</computeroutput>
</listitem>
<listitem>
<computeroutput><macroname>BOOST_PROTO_EXTENDS_SUBSCRIPT</macroname>()</computeroutput>
</listitem>
<listitem>
<computeroutput><macroname>BOOST_PROTO_EXTENDS_FUNCTION</macroname>()</computeroutput>
</listitem>
<listitem>
<computeroutput><macroname>BOOST_PROTO_EXTENDS</macroname>()</computeroutput>
</listitem>
</itemizedlist>
</para>
</description>
</macro>
<macro name="BOOST_PROTO_EXTENDS_FUNCTION" kind="functionlike">
<purpose>For adding to an expression extension class a set of overloaded function call operators
that build expression templates.</purpose>
<description>
<para>
Use <computeroutput>BOOST_PROTO_EXTENDS_FUNCTION()</computeroutput> after <computeroutput>
<macroname>BOOST_PROTO_BASIC_EXTENDS</macroname>()</computeroutput> to give an expression
extension class a set of overloaded function call operators that build expression templates.
In addition, <computeroutput>BOOST_PROTO_EXTENDS_FUNCTION()</computeroutput> adds a nested
<computeroutput>result&lt;&gt;</computeroutput> class template that is a metafunction for
calculating the return type of the overloaded function call operators.
</para>
<para>
See also:
<itemizedlist>
<listitem>
<computeroutput><macroname>BOOST_PROTO_BASIC_EXTENDS</macroname>()</computeroutput>
</listitem>
<listitem>
<computeroutput><macroname>BOOST_PROTO_EXTENDS_ASSIGN</macroname>()</computeroutput>
</listitem>
<listitem>
<computeroutput><macroname>BOOST_PROTO_EXTENDS_SUBSCRIPT</macroname>()</computeroutput>
</listitem>
<listitem>
<computeroutput><macroname>BOOST_PROTO_EXTENDS</macroname>()</computeroutput>
</listitem>
</itemizedlist>
</para>
</description>
</macro>
<macro name="BOOST_PROTO_EXTENDS_SUBSCRIPT" kind="functionlike">
<purpose>For adding to an expression extension class an overloaded subscript operator that
builds an expression template.</purpose>
<description>
<para>
Use <computeroutput>BOOST_PROTO_EXTENDS_SUBSCRIPT()</computeroutput> after <computeroutput>
<macroname>BOOST_PROTO_BASIC_EXTENDS</macroname>()</computeroutput> to give an expression
extension class an overloaded subscript operator that builds an expression template.
</para>
<para>
See also:
<itemizedlist>
<listitem>
<computeroutput><macroname>BOOST_PROTO_BASIC_EXTENDS</macroname>()</computeroutput>
</listitem>
<listitem>
<computeroutput><macroname>BOOST_PROTO_EXTENDS_ASSIGN</macroname>()</computeroutput>
</listitem>
<listitem>
<computeroutput><macroname>BOOST_PROTO_EXTENDS_FUNCTION</macroname>()</computeroutput>
</listitem>
<listitem>
<computeroutput><macroname>BOOST_PROTO_EXTENDS</macroname>()</computeroutput>
</listitem>
</itemizedlist>
</para>
</description>
</macro>
<macro name="BOOST_PROTO_EXTENDS_USING_ASSIGN" kind="functionlike">
<macro-parameter name="Derived"/>
<purpose>For exposing in classes that inherit from
<computeroutput><classname alt="boost::proto::extends">proto::extends&lt;&gt;</classname></computeroutput>
the overloaded assignment operators defined therein.</purpose>
<description>
<para>
The standard usage of
<computeroutput><classname alt="boost::proto::extends">proto::extends&lt;&gt;</classname></computeroutput>
is to inherit from it. However, the derived class automatically gets a compiler-generated assignment
operator that will hide the ones defined in
<computeroutput><classname alt="boost::proto::extends">proto::extends&lt;&gt;</classname></computeroutput>.
Use <code>BOOST_PROTO_EXTENDS_USING_ASSIGN()</code> in the derived class to unhide the assignment
operators defined in
<computeroutput><classname alt="boost::proto::extends">proto::extends&lt;&gt;</classname></computeroutput>.
</para>
<para>
See <computeroutput><classname alt="boost::proto::extends">proto::extends&lt;&gt;</classname></computeroutput>
for an example that demonstrates usage of <code>BOOST_PROTO_EXTENDS_USING_ASSIGN()</code>.
</para>
</description>
</macro>
<macro name="BOOST_PROTO_EXTENDS_USING_ASSIGN_NON_DEPENDENT" kind="functionlike">
<macro-parameter name="Derived"/>
<purpose>For exposing in classes that inherit from
<computeroutput><classname alt="boost::proto::extends">proto::extends&lt;&gt;</classname></computeroutput>
the overloaded assignment operators defined therein. Unlike the
<computeroutput><macroname>BOOST_PROTO_EXTENDS_USING_ASSIGN</macroname>()</computeroutput> macro,
<code>BOOST_PROTO_EXTENDS_USING_ASSIGN_NON_DEPENDENT()</code> is for use in non-dependent
contexts.
</purpose>
<description>
<para>
The standard usage of
<computeroutput><classname alt="boost::proto::extends">proto::extends&lt;&gt;</classname></computeroutput>
is to define a class template that inherits from it. The derived class template automatically gets a
compiler-generated assignment operator that hides the ones defined in
<computeroutput><classname alt="boost::proto::extends">proto::extends&lt;&gt;</classname></computeroutput>.
Using <code>BOOST_PROTO_EXTENDS_USING_ASSIGN()</code> in the derived class solves this problem.
</para>
<para>
However, if the expression extension is an ordinary class and not a class template, the usage of
<code>BOOST_PROTO_EXTENDS_USING_ASSIGN()</code> is in a so-called non-dependent context. In plain English,
it means it is illegal to use <code>typename</code> in some places where it is required in a class template.
In those cases, you should use <code>BOOST_PROTO_EXTENDS_USING_ASSIGN_NON_DEPENDENT()</code> instead.
</para>
<para>
See also:
<itemizedlist>
<listitem>
<computeroutput><classname alt="boost::proto::extends">proto::extends&lt;&gt;</classname></computeroutput>
</listitem>
<listitem>
<computeroutput><macroname>BOOST_PROTO_EXTENDS_USING_ASSIGN</macroname>()</computeroutput>
</listitem>
</itemizedlist>
</para>
</description>
</macro>
</header>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/functional.hpp">
<para>Includes all the functional extensions of Proto.</para>
</header>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/functional/fusion.hpp">
<para>Includes all the functional extensions to Proto for the Boost.Fusion library.</para>
</header>

View File

@@ -0,0 +1,83 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/functional/fusion/at.hpp">
<para>Includes Proto callable <computeroutput><classname>boost::proto::functional::at</classname></computeroutput>.</para>
<namespace name="boost">
<namespace name="proto">
<namespace name="functional">
<!-- proto::functional::at -->
<struct name="at">
<purpose>A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes the
<computeroutput>fusion::at()</computeroutput> accessor function on its arguments.</purpose>
<description>
<para>
A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes the
<computeroutput>fusion::at()</computeroutput> accessor function on its arguments.</para>
</description>
<inherit>
<type><classname>proto::callable</classname></type>
</inherit>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="Seq"/>
<template-type-parameter name="N"/>
</template>
<specialization>
<template-arg>This(Seq, N)</template-arg>
</specialization>
<inherit>
<type>fusion::result_of::at&lt;
typename boost::remove_reference&lt;Seq&gt;::type
, typename boost::remove_const&lt;typename boost::remove_reference&lt;N&gt;::type&gt;::type
&gt;</type>
</inherit>
</struct-specialization>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>typename fusion::result_of::at&lt; Seq, N &gt;::type</type>
<template>
<template-type-parameter name="Seq"/>
<template-type-parameter name="N"/>
</template>
<parameter name="seq">
<paramtype>Seq &amp;</paramtype>
</parameter>
<parameter name="n">
<paramtype>N const &amp;</paramtype>
</parameter>
<returns>
<para><computeroutput>fusion::at&lt;N&gt;(seq)</computeroutput></para>
</returns>
</method>
<method name="operator()" cv="const">
<type>typename fusion::result_of::at&lt; Seq const, N &gt;::type</type>
<template>
<template-type-parameter name="Seq"/>
<template-type-parameter name="N"/>
</template>
<parameter name="seq">
<paramtype>Seq const &amp;</paramtype>
</parameter>
<parameter name="n">
<paramtype>N const &amp;</paramtype>
</parameter>
<returns>
<para><computeroutput>fusion::at&lt;N&gt;(seq)</computeroutput></para>
</returns>
</method>
</method-group>
</struct>
</namespace>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/functional/fusion/pop_back.hpp">
<para>Includes Proto callable <computeroutput><classname>boost::proto::functional::pop_back</classname></computeroutput>.</para>
<namespace name="boost">
<namespace name="proto">
<namespace name="functional">
<!-- proto::functional::pop_back -->
<struct name="pop_back">
<purpose>A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes the
<computeroutput>fusion::pop_back()</computeroutput> algorithm on its argument.</purpose>
<description>
<para>
A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes the
<computeroutput>fusion::pop_back()</computeroutput> algorithm on its argument.
</para>
</description>
<inherit>
<type><classname>proto::callable</classname></type>
</inherit>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="Seq"/>
</template>
<specialization>
<template-arg>This(Seq)</template-arg>
</specialization>
<inherit>
<type>result&lt; This(Seq const &amp;) &gt;</type>
</inherit>
</struct-specialization>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="Seq"/>
</template>
<specialization>
<template-arg>This(Seq &amp;)</template-arg>
</specialization>
<inherit>
<type>fusion::result_of::pop_back&lt; Seq &gt;</type>
</inherit>
</struct-specialization>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>typename fusion::result_of::pop_back&lt; Seq &gt;::type</type>
<template>
<template-type-parameter name="Seq"/>
</template>
<parameter name="seq">
<paramtype>Seq &amp;</paramtype>
</parameter>
<returns>
<para><computeroutput>fusion::pop_back(seq)</computeroutput></para>
</returns>
</method>
<method name="operator()" cv="const">
<type>typename fusion::result_of::pop_back&lt; Seq const &gt;::type</type>
<template>
<template-type-parameter name="Seq"/>
</template>
<parameter name="seq">
<paramtype>Seq const &amp;</paramtype>
</parameter>
<returns>
<para><computeroutput>fusion::pop_back(seq)</computeroutput></para>
</returns>
</method>
</method-group>
</struct>
</namespace>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/functional/fusion/pop_front.hpp">
<para>Includes Proto callable <computeroutput><classname>boost::proto::functional::pop_front</classname></computeroutput>.</para>
<namespace name="boost">
<namespace name="proto">
<namespace name="functional">
<!-- proto::functional::pop_front -->
<struct name="pop_front">
<purpose>A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes the
<computeroutput>fusion::pop_front()</computeroutput> algorithm on its argument.</purpose>
<description>
<para>
A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes the
<computeroutput>fusion::pop_front()</computeroutput> algorithm on its argument. This is
useful for defining a <conceptname>CallableTransform</conceptname> such as
<computeroutput>pop_front(_)</computeroutput>, which removes the first child from a Proto
expression node. Such a transform might be used as the first argument to the
<computeroutput><classname alt="proto::fold">proto::fold&lt;&gt;</classname></computeroutput>
transform; that is, fold all but the first child.
</para>
</description>
<inherit>
<type><classname>proto::callable</classname></type>
</inherit>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="Seq"/>
</template>
<specialization>
<template-arg>This(Seq)</template-arg>
</specialization>
<inherit>
<type>result&lt; This(Seq const &amp;) &gt;</type>
</inherit>
</struct-specialization>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="Seq"/>
</template>
<specialization>
<template-arg>This(Seq &amp;)</template-arg>
</specialization>
<inherit>
<type>fusion::result_of::pop_front&lt; Seq &gt;</type>
</inherit>
</struct-specialization>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>typename fusion::result_of::pop_front&lt; Seq &gt;::type</type>
<template>
<template-type-parameter name="Seq"/>
</template>
<parameter name="seq">
<paramtype>Seq &amp;</paramtype>
</parameter>
<returns>
<para><computeroutput>fusion::pop_front(seq)</computeroutput></para>
</returns>
</method>
<method name="operator()" cv="const">
<type>typename fusion::result_of::pop_front&lt; Seq const &gt;::type</type>
<template>
<template-type-parameter name="Seq"/>
</template>
<parameter name="seq">
<paramtype>Seq const &amp;</paramtype>
</parameter>
<returns>
<para><computeroutput>fusion::pop_front(seq)</computeroutput></para>
</returns>
</method>
</method-group>
</struct>
</namespace>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/functional/fusion/push_back.hpp">
<para>Includes Proto callable <computeroutput><classname>boost::proto::functional::push_back</classname></computeroutput>.</para>
<namespace name="boost">
<namespace name="proto">
<namespace name="functional">
<!-- proto::functional::push_back -->
<struct name="push_back">
<purpose>A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes the
<computeroutput>fusion::push_back()</computeroutput> algorithm on its arguments.</purpose>
<description>
<para>
A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes the
<computeroutput>fusion::push_back()</computeroutput> algorithm on its arguments.</para>
</description>
<inherit>
<type><classname>proto::callable</classname></type>
</inherit>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="Seq"/>
<template-type-parameter name="T"/>
</template>
<specialization>
<template-arg>This(Seq, T)</template-arg>
</specialization>
<inherit>
<type>fusion::result_of::push_back&lt;
typename boost::add_const&lt;typename boost::remove_reference&lt;Seq&gt;::type&gt;::type
, typename boost::remove_const&lt;typename boost::remove_reference&lt;T&gt;::type&gt;::type
&gt;</type>
</inherit>
</struct-specialization>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>typename fusion::result_of::push_back&lt; Seq const, T &gt;::type</type>
<template>
<template-type-parameter name="Seq"/>
<template-type-parameter name="T"/>
</template>
<parameter name="seq">
<paramtype>Seq const &amp;</paramtype>
</parameter>
<parameter name="t">
<paramtype>T const &amp;</paramtype>
</parameter>
<returns>
<para><computeroutput>fusion::push_back(seq, t)</computeroutput></para>
</returns>
</method>
</method-group>
</struct>
</namespace>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/functional/fusion/push_front.hpp">
<para>Includes Proto callable <computeroutput><classname>boost::proto::functional::push_front</classname></computeroutput>.</para>
<namespace name="boost">
<namespace name="proto">
<namespace name="functional">
<!-- proto::functional::push_front -->
<struct name="push_front">
<purpose>A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes the
<computeroutput>fusion::push_front()</computeroutput> algorithm on its arguments.</purpose>
<description>
<para>
A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes the
<computeroutput>fusion::push_front()</computeroutput> algorithm on its arguments.</para>
</description>
<inherit>
<type><classname>proto::callable</classname></type>
</inherit>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="Seq"/>
<template-type-parameter name="T"/>
</template>
<specialization>
<template-arg>This(Seq, T)</template-arg>
</specialization>
<inherit>
<type>fusion::result_of::push_front&lt;
typename boost::add_const&lt;typename boost::remove_reference&lt;Seq&gt;::type&gt;::type
, typename boost::remove_const&lt;typename boost::remove_reference&lt;T&gt;::type&gt;::type
&gt;</type>
</inherit>
</struct-specialization>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>typename fusion::result_of::push_front&lt; Seq const, T &gt;::type</type>
<template>
<template-type-parameter name="Seq"/>
<template-type-parameter name="T"/>
</template>
<parameter name="seq">
<paramtype>Seq const &amp;</paramtype>
</parameter>
<parameter name="t">
<paramtype>T const &amp;</paramtype>
</parameter>
<returns>
<para><computeroutput>fusion::push_front(seq, t)</computeroutput></para>
</returns>
</method>
</method-group>
</struct>
</namespace>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,88 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/functional/fusion/reverse.hpp">
<para>Includes Proto callable <computeroutput><classname>boost::proto::functional::reverse</classname></computeroutput>.</para>
<namespace name="boost">
<namespace name="proto">
<namespace name="functional">
<!-- proto::functional::reverse -->
<struct name="reverse">
<purpose>A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes the
<computeroutput>fusion::reverse()</computeroutput> algorithm on its argument.
</purpose>
<description>
<para>
A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes the
<computeroutput>fusion::reverse()</computeroutput> algorithm on its argument. This is
useful for defining a <conceptname>CallableTransform</conceptname> like
<computeroutput>reverse(_)</computeroutput>, which reverses the order of the children
of a Proto expression node.
</para>
</description>
<inherit>
<type><classname>proto::callable</classname></type>
</inherit>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="Seq"/>
</template>
<specialization>
<template-arg>This(Seq)</template-arg>
</specialization>
<inherit>
<type>result&lt; This(Seq const &amp;) &gt;</type>
</inherit>
</struct-specialization>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="Seq"/>
</template>
<specialization>
<template-arg>This(Seq &amp;)</template-arg>
</specialization>
<inherit>
<type>fusion::result_of::reverse&lt; Seq &gt;</type>
</inherit>
</struct-specialization>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>typename fusion::result_of::reverse&lt; Seq &gt;::type</type>
<template>
<template-type-parameter name="Seq"/>
</template>
<parameter name="seq">
<paramtype>Seq &amp;</paramtype>
</parameter>
<returns>
<para><computeroutput>fusion::reverse(seq)</computeroutput></para>
</returns>
</method>
<method name="operator()" cv="const">
<type>typename fusion::result_of::reverse&lt; Seq const &gt;::type</type>
<template>
<template-type-parameter name="Seq"/>
</template>
<parameter name="seq">
<paramtype>Seq const &amp;</paramtype>
</parameter>
<returns>
<para><computeroutput>fusion::reverse(seq)</computeroutput></para>
</returns>
</method>
</method-group>
</struct>
</namespace>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/functional/range.hpp">
<para>Includes all the functional extensions to Proto for the Boost.Range library.</para>
</header>

View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/functional/range/begin.hpp">
<para>Includes Proto callable <code><classname>boost::proto::functional::begin</classname></code>.</para>
<namespace name="boost">
<namespace name="proto">
<namespace name="functional">
<!-- proto::functional::begin -->
<struct name="begin">
<purpose>A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes the
<code>boost::begin()</code> accessor function on its arguments.</purpose>
<description>
<para>
A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes the
<code>boost::begin()</code> accessor function on its arguments.</para>
</description>
<inherit>
<type><classname>proto::callable</classname></type>
</inherit>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="Range"/>
</template>
<specialization>
<template-arg>This(Range)</template-arg>
</specialization>
<inherit>
<type>boost::range_iterator&lt;
typename boost::remove_reference&lt;Range&gt;::type
&gt;</type>
</inherit>
</struct-specialization>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>typename boost::range_iterator&lt; Range &gt;::type</type>
<template>
<template-type-parameter name="Range"/>
</template>
<parameter name="rng">
<paramtype>Range &amp;</paramtype>
</parameter>
<returns>
<para><code>boost::begin(rng)</code></para>
</returns>
</method>
<method name="operator()" cv="const">
<type>typename boost::range_iterator&lt; Range const &gt;::type</type>
<template>
<template-type-parameter name="Range"/>
</template>
<parameter name="rng">
<paramtype>Range const &amp;</paramtype>
</parameter>
<returns>
<para><code>boost::begin(rng)</code></para>
</returns>
</method>
</method-group>
</struct>
</namespace>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/functional/range/empty.hpp">
<para>Includes Proto callable <code><classname>boost::proto::functional::empty</classname></code>.</para>
<namespace name="boost">
<namespace name="proto">
<namespace name="functional">
<!-- proto::functional::empty -->
<struct name="empty">
<purpose>A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes the
<code>boost::empty()</code> function on its arguments.</purpose>
<description>
<para>
A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes the
<code>boost::empty()</code> function on its arguments.</para>
</description>
<inherit>
<type><classname>proto::callable</classname></type>
</inherit>
<typedef name="result_type">
<type>bool</type>
</typedef>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>bool</type>
<template>
<template-type-parameter name="Range"/>
</template>
<parameter name="rng">
<paramtype>Range const &amp;</paramtype>
</parameter>
<returns>
<para><code>boost::empty(rng)</code></para>
</returns>
</method>
</method-group>
</struct>
</namespace>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/functional/range/end.hpp">
<para>Includes Proto callable <code><classname>boost::proto::functional::end</classname></code>.</para>
<namespace name="boost">
<namespace name="proto">
<namespace name="functional">
<!-- proto::functional::end -->
<struct name="end">
<purpose>A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes the
<code>boost::end()</code> accessor function on its arguments.</purpose>
<description>
<para>
A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes the
<code>boost::end()</code> accessor function on its arguments.</para>
</description>
<inherit>
<type><classname>proto::callable</classname></type>
</inherit>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="Range"/>
</template>
<specialization>
<template-arg>This(Range)</template-arg>
</specialization>
<inherit>
<type>boost::range_iterator&lt;
typename boost::remove_reference&lt;Range&gt;::type
&gt;</type>
</inherit>
</struct-specialization>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>typename boost::range_iterator&lt; Range &gt;::type</type>
<template>
<template-type-parameter name="Range"/>
</template>
<parameter name="rng">
<paramtype>Range &amp;</paramtype>
</parameter>
<returns>
<para><code>boost::end(rng)</code></para>
</returns>
</method>
<method name="operator()" cv="const">
<type>typename boost::range_iterator&lt; Range const &gt;::type</type>
<template>
<template-type-parameter name="Range"/>
</template>
<parameter name="rng">
<paramtype>Range const &amp;</paramtype>
</parameter>
<returns>
<para><code>boost::end(rng)</code></para>
</returns>
</method>
</method-group>
</struct>
</namespace>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/functional/range/rbegin.hpp">
<para>Includes Proto callable <code><classname>boost::proto::functional::rbegin</classname></code>.</para>
<namespace name="boost">
<namespace name="proto">
<namespace name="functional">
<!-- proto::functional::rbegin -->
<struct name="rbegin">
<purpose>A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes the
<code>boost::rbegin()</code> accessor function on its arguments.</purpose>
<description>
<para>
A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes the
<code>boost::rbegin()</code> accessor function on its arguments.</para>
</description>
<inherit>
<type><classname>proto::callable</classname></type>
</inherit>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="Range"/>
</template>
<specialization>
<template-arg>This(Range)</template-arg>
</specialization>
<inherit>
<type>boost::range_reverse_iterator&lt;
typename boost::remove_reference&lt;Range&gt;::type
&gt;</type>
</inherit>
</struct-specialization>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>typename boost::range_reverse_iterator&lt; Range &gt;::type</type>
<template>
<template-type-parameter name="Range"/>
</template>
<parameter name="rng">
<paramtype>Range &amp;</paramtype>
</parameter>
<returns>
<para><code>boost::rbegin(rng)</code></para>
</returns>
</method>
<method name="operator()" cv="const">
<type>typename boost::range_reverse_iterator&lt; Range const &gt;::type</type>
<template>
<template-type-parameter name="Range"/>
</template>
<parameter name="rng">
<paramtype>Range const &amp;</paramtype>
</parameter>
<returns>
<para><code>boost::rbegin(rng)</code></para>
</returns>
</method>
</method-group>
</struct>
</namespace>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/functional/range/rend.hpp">
<para>Includes Proto callable <code><classname>boost::proto::functional::rend</classname></code>.</para>
<namespace name="boost">
<namespace name="proto">
<namespace name="functional">
<!-- proto::functional::rend -->
<struct name="rend">
<purpose>A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes the
<code>boost::rend()</code> accessor function on its arguments.</purpose>
<description>
<para>
A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes the
<code>boost::rend()</code> accessor function on its arguments.</para>
</description>
<inherit>
<type><classname>proto::callable</classname></type>
</inherit>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="Range"/>
</template>
<specialization>
<template-arg>This(Range)</template-arg>
</specialization>
<inherit>
<type>boost::range_reverse_iterator&lt;
typename boost::remove_reference&lt;Range&gt;::type
&gt;</type>
</inherit>
</struct-specialization>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>typename boost::range_reverse_iterator&lt; Range &gt;::type</type>
<template>
<template-type-parameter name="Range"/>
</template>
<parameter name="rng">
<paramtype>Range &amp;</paramtype>
</parameter>
<returns>
<para><code>boost::rend(rng)</code></para>
</returns>
</method>
<method name="operator()" cv="const">
<type>typename boost::range_reverse_iterator&lt; Range const &gt;::type</type>
<template>
<template-type-parameter name="Range"/>
</template>
<parameter name="rng">
<paramtype>Range const &amp;</paramtype>
</parameter>
<returns>
<para><code>boost::rend(rng)</code></para>
</returns>
</method>
</method-group>
</struct>
</namespace>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/functional/range/size.hpp">
<para>Includes Proto callable <code><classname>boost::proto::functional::size</classname></code>.</para>
<namespace name="boost">
<namespace name="proto">
<namespace name="functional">
<!-- proto::functional::size -->
<struct name="size">
<purpose>A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes the
<code>boost::size()</code> function on its arguments.</purpose>
<description>
<para>
A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes the
<code>boost::size()</code> function on its arguments.</para>
</description>
<inherit>
<type><classname>proto::callable</classname></type>
</inherit>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="Range"/>
</template>
<specialization>
<template-arg>This(Range)</template-arg>
</specialization>
<inherit>
<type>boost::range_size&lt;
typename boost::remove_reference&lt;Range&gt;::type
&gt;</type>
</inherit>
</struct-specialization>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>typename boost::range_size&lt; Range const &gt;::type</type>
<template>
<template-type-parameter name="Range"/>
</template>
<parameter name="rng">
<paramtype>Range const &amp;</paramtype>
</parameter>
<returns>
<para><code>boost::size(rng)</code></para>
</returns>
</method>
</method-group>
</struct>
</namespace>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/functional/std.hpp">
<para>Includes all the functional extensions to Proto for the standard library.</para>
</header>

View File

@@ -0,0 +1,247 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/functional/std/iterator.hpp">
<para>Includes Proto callables for the functions found in the standard <code>&lt;iterator&gt; header</code>.</para>
<namespace name="boost">
<namespace name="proto">
<namespace name="functional">
<!-- proto::functional::advance -->
<struct name="advance">
<purpose>A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes the
<code>std::advance()</code> function on its arguments.</purpose>
<description>
<para>
A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes the
<code>std::advance()</code> function on its arguments.</para>
</description>
<inherit>
<type><classname>proto::callable</classname></type>
</inherit>
<typedef name="result_type">
<type>void</type>
</typedef>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>void</type>
<template>
<template-type-parameter name="InputIterator"/>
</template>
<template>
<template-type-parameter name="Distance"/>
</template>
<parameter name="x">
<paramtype>InputIterator &amp;</paramtype>
</parameter>
<parameter name="n">
<paramtype>Distance</paramtype>
</parameter>
<description>
<para>Calls <code>std::advance(x, n)</code></para>
</description>
</method>
</method-group>
</struct>
<!-- proto::functional::distance -->
<struct name="distance">
<purpose>A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes the
<code>std::distance()</code> function on its arguments.</purpose>
<description>
<para>
A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes the
<code>std::distance()</code> function on its arguments.</para>
</description>
<inherit>
<type><classname>proto::callable</classname></type>
</inherit>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="InputIterator"/>
</template>
<specialization>
<template-arg>This(InputIterator, InputIterator)</template-arg>
</specialization>
<typedef name="type">
<type>typename std::iterator_traits&lt;
typename boost::remove_const&lt;
typename boost::remove_reference&lt;InputIterator&gt;::type
&gt;::type
&gt;::difference_type</type>
</typedef>
</struct-specialization>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>void</type>
<template>
<template-type-parameter name="InputIterator"/>
</template>
<parameter name="first">
<paramtype>InputIterator</paramtype>
</parameter>
<parameter name="last">
<paramtype>InputIterator</paramtype>
</parameter>
<returns>
<para><code>std::distance(first, last)</code></para>
</returns>
</method>
</method-group>
</struct>
<!-- proto::functional::next -->
<struct name="next">
<purpose>A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes the
<code>std::next()</code> function on its arguments.</purpose>
<description>
<para>
A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes the
<code>std::next()</code> function on its arguments.</para>
</description>
<inherit>
<type><classname>proto::callable</classname></type>
</inherit>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="ForwardIterator"/>
</template>
<specialization>
<template-arg>This(ForwardIterator)</template-arg>
</specialization>
<typedef name="type">
<type>typename boost::remove_const&lt;
typename boost::remove_reference&lt;ForwardIterator&gt;::type
&gt;::type</type>
</typedef>
</struct-specialization>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="ForwardIterator"/>
<template-type-parameter name="Distance"/>
</template>
<specialization>
<template-arg>This(ForwardIterator, Distance)</template-arg>
</specialization>
<typedef name="type">
<type>typename boost::remove_const&lt;
typename boost::remove_reference&lt;ForwardIterator&gt;::type
&gt;::type</type>
</typedef>
</struct-specialization>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>void</type>
<template>
<template-type-parameter name="ForwardIterator"/>
</template>
<parameter name="x">
<paramtype>ForwardIterator</paramtype>
</parameter>
<returns>
<para><code>std::next(x)</code></para>
</returns>
</method>
<method name="operator()" cv="const">
<type>void</type>
<template>
<template-type-parameter name="ForwardIterator"/>
</template>
<parameter name="x">
<paramtype>ForwardIterator</paramtype>
</parameter>
<parameter name="n">
<paramtype>typename std::iterator_traits&lt;ForwardIterator&gt;::difference_type</paramtype>
</parameter>
<returns>
<para><code>std::next(x, n)</code></para>
</returns>
</method>
</method-group>
</struct>
<!-- proto::functional::prior -->
<struct name="prior">
<purpose>A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes the
<code>std::prior()</code> function on its arguments.</purpose>
<description>
<para>
A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes the
<code>std::prior()</code> function on its arguments.</para>
</description>
<inherit>
<type><classname>proto::callable</classname></type>
</inherit>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="BidirectionalIterator"/>
</template>
<specialization>
<template-arg>This(BidirectionalIterator)</template-arg>
</specialization>
<typedef name="type">
<type>typename boost::remove_const&lt;
typename boost::remove_reference&lt;BidirectionalIterator&gt;::type
&gt;::type</type>
</typedef>
</struct-specialization>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="BidirectionalIterator"/>
<template-type-parameter name="Distance"/>
</template>
<specialization>
<template-arg>This(BidirectionalIterator, Distance)</template-arg>
</specialization>
<typedef name="type">
<type>typename boost::remove_const&lt;
typename boost::remove_reference&lt;BidirectionalIterator&gt;::type
&gt;::type</type>
</typedef>
</struct-specialization>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>void</type>
<template>
<template-type-parameter name="BidirectionalIterator"/>
</template>
<parameter name="x">
<paramtype>BidirectionalIterator</paramtype>
</parameter>
<returns>
<para><code>std::prior(x)</code></para>
</returns>
</method>
<method name="operator()" cv="const">
<type>void</type>
<template>
<template-type-parameter name="BidirectionalIterator"/>
</template>
<parameter name="x">
<paramtype>BidirectionalIterator</paramtype>
</parameter>
<parameter name="n">
<paramtype>typename std::iterator_traits&lt;BidirectionalIterator&gt;::difference_type</paramtype>
</parameter>
<returns>
<para><code>std::prior(x, n)</code></para>
</returns>
</method>
</method-group>
</struct>
</namespace>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,232 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/functional/std/utility.hpp">
<para>Defines Proto callables <computeroutput><classname>boost::proto::functional::make_pair</classname></computeroutput>,
<computeroutput><classname>boost::proto::functional::first</classname></computeroutput> and
<computeroutput><classname>boost::proto::functional::second</classname></computeroutput>.</para>
<namespace name="boost">
<namespace name="proto">
<namespace name="functional">
<!-- proto::functional::make_pair -->
<struct name="make_pair">
<purpose>A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes
<computeroutput>std::make_pair()</computeroutput> on its arguments.</purpose>
<description>
<para>
A <conceptname>PolymorphicFunctionObject</conceptname> type that invokes
<computeroutput>std::make_pair()</computeroutput> on its arguments.</para>
</description>
<inherit>
<type><classname>proto::callable</classname></type>
</inherit>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="First"/>
<template-type-parameter name="Second"/>
</template>
<specialization>
<template-arg>This(First, Second)</template-arg>
</specialization>
<typedef name="type">
<type>std::pair&lt;
typename boost::remove_const&lt;typename boost::remove_reference&lt;First&gt;::type&gt;::type
, typename boost::remove_const&lt;typename boost::remove_reference&lt;Second&gt;::type&gt;::type
&gt;</type>
</typedef>
</struct-specialization>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>typename std::pair&lt; First, Second &gt;</type>
<template>
<template-type-parameter name="First"/>
<template-type-parameter name="Second"/>
</template>
<parameter name="first">
<paramtype>First const &amp;</paramtype>
</parameter>
<parameter name="second">
<paramtype>Second const &amp;</paramtype>
</parameter>
<returns>
<para><computeroutput>std::make_pair(first, second)</computeroutput></para>
</returns>
</method>
</method-group>
</struct>
<!-- proto::functional::first -->
<struct name="first">
<purpose>
A <conceptname>PolymorphicFunctionObject</conceptname> type that returns
the first element of a <computeroutput>std::pair&lt;&gt;</computeroutput>.
</purpose>
<description>
<para>
A <conceptname>PolymorphicFunctionObject</conceptname> type that returns
the first element of a <computeroutput>std::pair&lt;&gt;</computeroutput>.</para>
</description>
<inherit><type><classname>proto::callable</classname></type>
</inherit>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="Pair"/>
</template>
<specialization>
<template-arg>This(Pair)</template-arg>
</specialization>
<typedef name="type">
<type>typename Pair::first_type</type>
</typedef>
</struct-specialization>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="Pair"/>
</template>
<specialization>
<template-arg>This(Pair &amp;)</template-arg>
</specialization>
<typedef name="type">
<type>typename Pair::first_type &amp;</type>
</typedef>
</struct-specialization>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="Pair"/>
</template>
<specialization>
<template-arg>This(Pair const &amp;)</template-arg>
</specialization>
<typedef name="type">
<type>typename Pair::first_type const &amp;</type>
</typedef>
</struct-specialization>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>typename Pair::first_type &amp;</type>
<template>
<template-type-parameter name="Pair"/>
</template>
<parameter name="pair">
<paramtype>Pair &amp;</paramtype>
</parameter>
<returns>
<para>
<computeroutput>pair.first</computeroutput>
</para>
</returns>
</method>
<method name="operator()" cv="const">
<type>typename Pair::first_type const &amp;</type>
<template>
<template-type-parameter name="Pair"/>
</template>
<parameter name="pair">
<paramtype>Pair const &amp;</paramtype>
</parameter>
<returns>
<para>
<computeroutput>pair.first</computeroutput>
</para>
</returns>
</method>
</method-group>
</struct>
<!-- proto::functional::second -->
<struct name="second">
<purpose>
A <conceptname>PolymorphicFunctionObject</conceptname> type that returns
the second element of a <computeroutput>std::pair&lt;&gt;</computeroutput>.
</purpose>
<description>
<para>
A <conceptname>PolymorphicFunctionObject</conceptname> type that returns
the second element of a <computeroutput>std::pair&lt;&gt;</computeroutput>.
</para>
</description>
<inherit><type><classname>proto::callable</classname></type></inherit>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="Pair"/>
</template>
<specialization>
<template-arg>This(Pair)</template-arg>
</specialization>
<typedef name="type">
<type>typename Pair::second_type</type>
</typedef>
</struct-specialization>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="Pair"/>
</template>
<specialization>
<template-arg>This(Pair &amp;)</template-arg>
</specialization>
<typedef name="type">
<type>typename Pair::second_type &amp;</type>
</typedef>
</struct-specialization>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="Pair"/>
</template>
<specialization>
<template-arg>This(Pair const &amp;)</template-arg>
</specialization>
<typedef name="type">
<type>typename Pair::second_type const &amp;</type>
</typedef>
</struct-specialization>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>typename Pair::second_type &amp;</type>
<template>
<template-type-parameter name="Pair"/>
</template>
<parameter name="pair">
<paramtype>Pair &amp;</paramtype>
</parameter>
<returns>
<para>
<computeroutput>pair.second</computeroutput>
</para>
</returns>
</method>
<method name="operator()" cv="const">
<type>typename Pair::second_type const &amp;</type>
<template>
<template-type-parameter name="Pair"/>
</template>
<parameter name="pair">
<paramtype>Pair const &amp;</paramtype>
</parameter>
<returns>
<para>
<computeroutput>pair.second</computeroutput>
</para>
</returns>
</method>
</method-group>
</struct>
</namespace>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,146 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/fusion.hpp">
<para>Make any Proto expression a valid Fusion sequence </para>
<namespace name="boost">
<namespace name="proto">
<namespace name="functional">
<!-- proto::functional::flatten -->
<struct name="flatten">
<purpose>A <conceptname>PolymorphicFunctionObject</conceptname> type that returns a "flattened"
view of a Proto expression tree. </purpose>
<description>
<para>
A <conceptname>PolymorphicFunctionObject</conceptname> type that returns a "flattened" view
of a Proto expression tree. For a tree with a top-most node tag of type
<computeroutput>T</computeroutput>, the elements of the flattened sequence are determined by
recursing into each child node with the same tag type and returning those nodes of different
type. So for instance, the Proto expression tree corresponding to the expression
<computeroutput>a | b | c</computeroutput> has a flattened view with elements [a, b, c], even
though the tree is grouped as <computeroutput>((a | b) | c)</computeroutput>.
</para>
<para>
The resulting view is a Fusion Forward Sequence.
</para>
</description>
<inherit>
<type><classname>proto::callable</classname></type>
</inherit>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="Expr"/>
</template>
<specialization>
<template-arg>This(Expr)</template-arg>
</specialization>
<inherit>
<type>result&lt; This(Expr const &amp;) &gt;</type>
</inherit>
</struct-specialization>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="Expr"/>
</template>
<specialization>
<template-arg>This(Expr &amp;)</template-arg>
</specialization>
<inherit>
<type><classname>proto::result_of::flatten</classname>&lt; Expr &gt;</type>
</inherit>
</struct-specialization>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>typename <classname>proto::result_of::flatten</classname>&lt; Expr &gt;::type const</type>
<template>
<template-type-parameter name="Expr"/>
</template>
<parameter name="expr">
<paramtype>Expr &amp;</paramtype>
</parameter>
<description>
<para>
Returns a Fusion Forward Sequence representing a flattened view of <computeroutput>expr</computeroutput>.
</para>
</description>
</method>
<method name="operator()" cv="const">
<type>typename <classname>proto::result_of::flatten</classname>&lt; Expr const &gt;::type const</type>
<template>
<template-type-parameter name="Expr"/>
</template>
<parameter name="expr">
<paramtype>Expr const &amp;</paramtype>
</parameter>
<description>
<para>
Returns a Fusion Forward Sequence representing a flattened view of <computeroutput>expr</computeroutput>.
</para>
</description>
</method>
</method-group>
</struct>
</namespace>
<namespace name="result_of">
<!-- proto::result_of::flatten -->
<struct name="flatten">
<template>
<template-type-parameter name="Expr"/>
</template>
<purpose>Metafunction that computes the return type of <computeroutput>
<functionname alt="proto::flatten">proto::flatten()</functionname></computeroutput></purpose>
<typedef name="type">
<type><emphasis>unspecified</emphasis></type>
<purpose>A Fusion Forward Sequence</purpose>
</typedef>
</struct>
</namespace>
<!-- proto::flatten() -->
<overloaded-function name="flatten">
<signature>
<type>typename <classname>proto::result_of::flatten</classname>&lt; Expr &gt;::type const</type>
<template>
<template-type-parameter name="Expr"/>
</template>
<parameter name="expr">
<paramtype>Expr &amp;</paramtype>
</parameter>
</signature>
<signature>
<type>typename <classname>proto::result_of::flatten</classname>&lt; Expr const &gt;::type const</type>
<template>
<template-type-parameter name="Expr"/>
</template>
<parameter name="expr">
<paramtype>Expr const &amp;</paramtype>
</parameter>
</signature>
<purpose>A function that returns a "flattened" view of a Proto expression tree. </purpose>
<description>
<para>
For a tree with a top-most node tag of type <computeroutput>T</computeroutput>, the elements
of the flattened sequence are determined by recursing into each child node with the same tag
type and returning those nodes of different type. So for instance, the Proto expression tree
corresponding to the expression <computeroutput>a | b | c</computeroutput> has a flattened
view with elements [a, b, c], even though the tree is grouped as
<computeroutput>((a | b) | c)</computeroutput>.
</para>
<para>
The returned view is a Fusion Forward Sequence.
</para>
</description>
</overloaded-function>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,326 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/generate.hpp">
<para>Contains definition of
<computeroutput><classname alt="boost::proto::default_generator">proto::default_generator</classname></computeroutput>,
<computeroutput><classname alt="boost::proto::generator">proto::generator</classname>&lt;&gt;</computeroutput>,
<computeroutput><classname alt="boost::proto::pod_generator">proto::pod_generator</classname>&lt;&gt;</computeroutput>
and other utilities that users can use to post-process new expression objects that
Proto creates.</para>
<namespace name="boost">
<namespace name="proto">
<!-- proto::default_generator -->
<struct name="default_generator">
<purpose>A simple generator that passes an expression through unchanged.</purpose>
<description>
<para>
Generators are intended for use as the first template parameter to the
<computeroutput><classname alt="proto::domain">proto::domain&lt;&gt;</classname></computeroutput>
class template and control if and how expressions within that domain are to be customized.
The <computeroutput>proto::default_generator</computeroutput> makes no modifications to the
expressions passed to it.
</para>
</description>
<inherit>
<type><classname>proto::callable</classname></type>
</inherit>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="Expr"/>
</template>
<specialization>
<template-arg>This(Expr)</template-arg>
</specialization>
<typedef name="type">
<type>Expr</type>
</typedef>
</struct-specialization>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>Expr</type>
<template>
<template-type-parameter name="Expr"/>
</template>
<parameter name="expr">
<paramtype>Expr const &amp;</paramtype>
<description>
<para>A Proto expression</para>
</description>
</parameter>
<returns>
<para><computeroutput>expr</computeroutput></para>
</returns>
</method>
</method-group>
</struct>
<!-- proto::basic_default_generator -->
<struct name="basic_default_generator">
<purpose>
A simple generator that passes an expression through unchanged while stating
a preference for <classname>proto::basic_expr</classname>&lt;&gt; over
<classname>proto::expr</classname>&lt;&gt;.</purpose>
<inherit>
<type><classname>proto::use_basic_expr</classname>&lt; <classname>proto::default_generator</classname> &gt;</type>
</inherit>
</struct>
<!-- proto::generator -->
<struct name="generator">
<template>
<template-nontype-parameter name="Extends">
<type>template&lt; typename &gt; class</type>
</template-nontype-parameter>
</template>
<purpose>A generator that wraps expressions passed to it in the specified extension wrapper.</purpose>
<description>
<para>
Generators are intended for use as the first template parameter to the
<computeroutput><classname alt="proto::domain">proto::domain&lt;&gt;</classname></computeroutput>
class template and control if and how expressions within that domain are to be customized.
<computeroutput>proto::generator&lt;&gt;</computeroutput> wraps each expression passed to it in
the <computeroutput>Extends&lt;&gt;</computeroutput> wrapper.
</para>
</description>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="Expr"/>
</template>
<specialization>
<template-arg>This(Expr)</template-arg>
</specialization>
<typedef name="type">
<type>Extends&lt; Expr &gt;</type>
</typedef>
</struct-specialization>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>Extends&lt; Expr &gt;</type>
<template>
<template-type-parameter name="Expr"/>
</template>
<parameter name="expr">
<paramtype>Expr const &amp;</paramtype>
<description>
<para>A Proto expression</para>
</description>
</parameter>
<returns>
<para><computeroutput>Extends&lt;Expr&gt;(expr)</computeroutput></para>
</returns>
</method>
</method-group>
</struct>
<!-- proto::pod_generator -->
<struct name="pod_generator">
<template>
<template-nontype-parameter name="Extends">
<type>template&lt; typename &gt; class</type>
</template-nontype-parameter>
</template>
<purpose>A generator that wraps expressions passed to it in the specified extension wrapper and uses aggregate initialization for the wrapper. </purpose>
<description>
<para>
Generators are intended for use as the first template parameter to the
<computeroutput><classname alt="proto::domain">proto::domain&lt;&gt;</classname></computeroutput>
class template and control if and how expressions within that domain are to be customized.
<computeroutput>proto::pod_generator&lt;&gt;</computeroutput> wraps each expression passed
to it in the <computeroutput>Extends&lt;&gt;</computeroutput> wrapper, and uses aggregate
initialzation for the wrapped object.
</para>
</description>
<inherit>
<type><classname>proto::callable</classname></type>
</inherit>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="Expr"/>
</template>
<specialization>
<template-arg>This(Expr)</template-arg>
</specialization>
<typedef name="type">
<type>Extends&lt; Expr &gt;</type>
</typedef>
</struct-specialization>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>Extends&lt; Expr &gt;</type>
<template>
<template-type-parameter name="Expr"/>
</template>
<parameter name="expr">
<paramtype>Expr const &amp;</paramtype>
<description>
<para>A Proto expression</para>
</description>
</parameter>
<returns>
<para>
<computeroutput>Extends&lt;Expr&gt; that = {expr}; return that;</computeroutput>
</para>
</returns>
</method>
</method-group>
</struct>
<!-- by_value_generator -->
<struct name="by_value_generator">
<purpose>A generator that replaces child nodes held by reference with ones held by value.
Use with <computeroutput><classname alt="proto::compose_generators">proto::compose_generators&lt;&gt;</classname>
</computeroutput> to forward that result to another generator.
</purpose>
<description>
<para>
Generators are intended for use as the first template parameter to the
<computeroutput><classname alt="proto::domain">proto::domain&lt;&gt;</classname></computeroutput>
class template and control if and how expressions within that domain are to be customized.
<computeroutput>proto::by_value_generator</computeroutput> ensures all child nodes are held
by value. This generator is typically composed with a second generator for further processing,
as <computeroutput><classname>proto::compose_generators</classname>&lt;proto::by_value_generator,
MyGenerator&gt;</computeroutput>.
</para>
</description>
<inherit>
<type><classname>proto::callable</classname></type>
</inherit>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="Expr"/>
</template>
<specialization>
<template-arg>This(Expr)</template-arg>
</specialization>
<typedef name="type">
<type><emphasis>unspecified</emphasis></type>
</typedef>
</struct-specialization>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type><emphasis>unspecified</emphasis></type>
<template>
<template-type-parameter name="Expr"/>
</template>
<parameter name="expr">
<paramtype>Expr const &amp;</paramtype>
<description>
<para>A Proto expression.</para>
</description>
</parameter>
<returns>
<para>Equivalent to <computeroutput><functionname>proto::deep_copy</functionname>(expr)</computeroutput></para>
</returns>
</method>
</method-group>
</struct>
<!-- proto::compose_generator -->
<struct name="compose_generators">
<template>
<template-type-parameter name="First"/>
<template-type-parameter name="Second"/>
</template>
<purpose>A composite generator that first applies one transform to an expression and then forwards
the result on to another generator for further transformation.</purpose>
<description>
<para>
Generators are intended for use as the first template parameter to the
<computeroutput><classname alt="proto::domain">proto::domain&lt;&gt;</classname></computeroutput>
class template and control if and how expressions within that domain are to be customized.
<computeroutput>proto::compose_generators&lt;&gt;</computeroutput> is a composite generator
that first applies one transform to an expression and then forwards the result on to another
generator for further transformation.
</para>
</description>
<inherit>
<type><classname>proto::callable</classname></type>
</inherit>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="Expr"/>
</template>
<specialization>
<template-arg>This(Expr)</template-arg>
</specialization>
<inherit>
<type>
boost::result_of&lt;
Second(typename boost::result_of&lt;First(Expr)&gt;::type)
&gt;</type>
</inherit>
</struct-specialization>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>typename boost::result_of&lt;
Second(typename boost::result_of&lt;First(Expr)&gt;::type)
&gt;::type</type>
<template>
<template-type-parameter name="Expr"/>
</template>
<parameter name="expr">
<paramtype>Expr const &amp;</paramtype>
<description>
<para>A Proto expression.</para>
</description>
</parameter>
<returns>
<para><computeroutput>Second()(First()(expr))</computeroutput></para>
</returns>
</method>
</method-group>
</struct>
<!-- proto::use_basic_expr -->
<struct name="use_basic_expr">
<template>
<template-type-parameter name="Generator"/>
</template>
<inherit>
<type>Generator</type>
</inherit>
<description>
<para>
Annotate a generator to indicate that it would
prefer to be passed instances of
<computeroutput><classname>proto::basic_expr</classname>&lt;&gt;</computeroutput> rather than
<computeroutput><classname>proto::expr</classname>&lt;&gt;</computeroutput>.
</para>
<para>
<computeroutput>use_basic_expr&lt; Generator &gt;</computeroutput> is itself a generator.
</para>
</description>
</struct>
<!-- proto::wants_basic_expr -->
<struct name="wants_basic_expr">
<template>
<template-type-parameter name="Generator"/>
</template>
<inherit>
<type>mpl::bool_&lt; <replaceable>true-or-false</replaceable> &gt;</type>
</inherit>
<description>
<para>
A Boolean metafunction that tests a generator to see whether
it would prefer to be passed instances of
<computeroutput><classname>proto::basic_expr</classname>&lt;&gt;</computeroutput> rather than
<computeroutput><classname>proto::expr</classname>&lt;&gt;</computeroutput>.
</para>
</description>
</struct>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,138 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/literal.hpp">
<para>
The
<computeroutput><classname alt="boost::proto::literal">proto::literal&lt;&gt;</classname></computeroutput>
terminal wrapper, and the
<computeroutput><functionname alt="boost::proto::lit">proto::lit()</functionname></computeroutput>
function for creating
<computeroutput><classname alt="boost::proto::literal">proto::literal&lt;&gt;</classname></computeroutput>
wrappers.
</para>
<namespace name="boost">
<namespace name="proto">
<struct name="literal">
<template>
<template-type-parameter name="T"/>
<template-type-parameter name="Domain">
<default><classname>proto::default_domain</classname></default>
</template-type-parameter>
</template>
<inherit>
<type>
<classname>proto::extends</classname>&lt;<classname>proto::basic_expr</classname>&lt;<classname>proto::tag::terminal</classname>, <classname>proto::term</classname>&lt; T &gt; &gt;, proto::literal&lt;T, Domain&gt;, Domain&gt;</type>
</inherit>
<purpose>A simple wrapper for a terminal, provided for ease of use.</purpose>
<description>
<para>
A simple wrapper for a terminal, provided for ease of use. In all cases,
<computeroutput>proto::literal&lt;X&gt; l(x);</computeroutput> is equivalent to
<computeroutput><classname>proto::terminal</classname>&lt;X&gt;::type l = {x};</computeroutput>.
</para>
<para>
The <computeroutput>Domain</computeroutput> template parameter defaults to
<computeroutput><classname>proto::default_domain</classname></computeroutput>.
</para>
</description>
<typedef name="X">
<purpose>For exposition only</purpose>
<type><classname>proto::basic_expr</classname>&lt;<classname>proto::tag::terminal</classname>, <classname>proto::term</classname>&lt; T &gt; &gt;</type>
</typedef>
<typedef name="value_type">
<type>typename <classname>proto::result_of::value</classname>&lt;X&gt;::type</type>
</typedef>
<typedef name="reference">
<type>typename <classname>proto::result_of::value</classname>&lt;X &amp;&gt;::type</type>
</typedef>
<typedef name="const_reference">
<type>typename <classname>proto::result_of::value</classname>&lt;X const &amp;&gt;::type</type>
</typedef>
<method-group name="public member functions">
<method name="get">
<type>reference</type>
<returns>
<computeroutput><functionname>proto::value</functionname>(*this)</computeroutput>
</returns>
</method>
<method name="get" cv="const">
<type>const_reference</type>
<returns>
<computeroutput><functionname>proto::value</functionname>(*this)</computeroutput>
</returns>
</method>
</method-group>
<constructor/>
<constructor>
<template>
<template-type-parameter name="U"/>
</template>
<parameter name="u">
<paramtype>U &amp;</paramtype>
</parameter>
</constructor>
<constructor>
<template>
<template-type-parameter name="U"/>
</template>
<parameter name="u">
<paramtype>U const &amp;</paramtype>
</parameter>
</constructor>
<constructor>
<template>
<template-type-parameter name="U"/>
</template>
<parameter name="u">
<paramtype><classname>proto::literal</classname>&lt; U, Domain &gt; const &amp;</paramtype>
</parameter>
</constructor>
</struct>
<!-- proto::lit() -->
<overloaded-function name="lit">
<signature>
<type><classname>proto::literal</classname>&lt; T &amp; &gt; const</type>
<template>
<template-type-parameter name="T"/>
</template>
<parameter name="t">
<paramtype>T &amp;</paramtype>
<description>
<para>The object to wrap.</para>
</description>
</parameter>
</signature>
<signature>
<type><classname>proto::literal</classname>&lt; T const &amp; &gt; const</type>
<template>
<template-type-parameter name="T"/>
</template>
<parameter name="t">
<paramtype>T const &amp;</paramtype>
</parameter>
</signature>
<purpose>A helper function for creating a <computeroutput>
<classname alt="proto::literal">proto::literal&lt;&gt;</classname></computeroutput> wrapper.
</purpose>
<returns>
<para>
<computeroutput><classname>proto::literal</classname>&lt;T &amp;&gt;(t)</computeroutput>
</para>
</returns>
<throws>
<simpara>Will not throw.</simpara>
</throws>
<notes>
<para>The returned value holds the argument by reference. </para>
</notes>
</overloaded-function>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,489 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/make_expr.hpp">
<para>
Definition of the <computeroutput><functionname alt="boost::proto::make_expr">proto::make_expr()</functionname>
</computeroutput> and <computeroutput><functionname alt="boost::proto::unpack_expr">proto::unpack_expr()</functionname>
</computeroutput> utilities for building Proto expression nodes from child nodes or from a Fusion sequence of child
nodes, respectively.
</para>
<namespace name="boost">
<namespace name="proto">
<namespace name="functional">
<!-- proto::functional::make_expr -->
<struct name="make_expr">
<template>
<template-type-parameter name="Tag"/>
<template-type-parameter name="Domain">
<default><classname>proto::deduce_domain</classname></default>
</template-type-parameter>
</template>
<purpose>A <conceptname>PolymorphicFunctionObject</conceptname> equivalent to the <computeroutput>
<functionname alt="proto::make_expr">proto::make_expr()</functionname></computeroutput> function.</purpose>
<description>
<para>
In all cases, <computeroutput>proto::functional::make_expr&lt;Tag, Domain&gt;()(a...)</computeroutput>
is equivalent to <computeroutput><functionname>proto::make_expr</functionname>&lt;Tag, Domain&gt;(a...)</computeroutput>.
</para>
<para>
<computeroutput>proto::functional::make_expr&lt;Tag&gt;()(a...)</computeroutput> is equivalent to
<computeroutput><functionname>proto::make_expr</functionname>&lt;Tag&gt;(a...)</computeroutput>.
</para>
</description>
<inherit>
<type><classname>proto::callable</classname></type>
</inherit>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="A" pack="1"/>
</template>
<specialization>
<template-arg>This(A...)</template-arg>
</specialization>
<inherit>
<type>
<classname>proto::result_of::make_expr</classname>&lt; Tag, Domain, A... &gt;</type>
</inherit>
</struct-specialization>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>typename <classname>proto::result_of::make_expr</classname>&lt; Tag, Domain, A const... &gt;::type const</type>
<template>
<template-type-parameter name="A" pack="1"/>
</template>
<parameter name="a" pack="1">
<paramtype>A const &amp;</paramtype>
</parameter>
<description>
<para>
Construct an expression node with tag type <computeroutput>Tag</computeroutput> and in the
domain <computeroutput>Domain</computeroutput>.
</para>
<para>
</para>
</description>
<returns>
<para>
<computeroutput><functionname>proto::make_expr</functionname>&lt;Tag, Domain&gt;(a...)</computeroutput>
</para>
</returns>
</method>
</method-group>
</struct>
<!-- proto::functional::unpack_expr -->
<struct name="unpack_expr">
<template>
<template-type-parameter name="Tag"/>
<template-type-parameter name="Domain">
<default><classname>proto::deduce_domain</classname></default>
</template-type-parameter>
</template>
<purpose>A <conceptname>PolymorphicFunctionObject</conceptname> equivalent to the
<computeroutput><functionname alt="proto::unpack_expr">proto::unpack_expr()</functionname></computeroutput> function.
</purpose>
<description>
<para>
In all cases, <computeroutput>proto::functional::unpack_expr&lt;Tag, Domain&gt;()(seq)</computeroutput> is
equivalent to <computeroutput><functionname alt="proto::unpack_expr">proto::unpack_expr()</functionname>&lt;Tag,
Domain&gt;(seq)</computeroutput>.
</para>
<para>
<computeroutput>proto::functional::unpack_expr&lt;Tag&gt;()(seq)</computeroutput> is equivalent to
<computeroutput><functionname alt="proto::unpack_expr">proto::unpack_expr()</functionname>&lt;Tag&gt;(seq)</computeroutput>.
</para>
</description>
<inherit>
<type><classname>proto::callable</classname></type>
</inherit>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="Sequence"/>
</template>
<specialization>
<template-arg>This(Sequence)</template-arg>
</specialization>
<inherit>
<type>
<classname>proto::result_of::unpack_expr</classname>&lt;
Tag,
Domain,
typename boost::remove_reference&lt; Sequence &gt;::type
&gt;</type>
</inherit>
</struct-specialization>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>typename <classname>proto::result_of::unpack_expr</classname>&lt; Tag, Domain, Sequence const &gt;::type const</type>
<template>
<template-type-parameter name="Sequence"/>
</template>
<parameter name="sequence">
<paramtype>Sequence const &amp;</paramtype>
<description>
<para>A Fusion Forward Sequence </para>
</description>
</parameter>
<description>
<para>
Construct an expression node with tag type <computeroutput>Tag</computeroutput> and in the
domain <computeroutput>Domain</computeroutput>.
</para>
</description>
<returns>
<para>
<computeroutput><functionname>proto::unpack_expr</functionname>&lt;Tag, Domain&gt;(sequence)</computeroutput>
</para>
</returns>
</method>
</method-group>
</struct>
</namespace>
<namespace name="result_of">
<!-- proto::result_of::make_expr -->
<struct name="make_expr">
<template>
<template-type-parameter name="Tag"/>
<template-type-parameter name="A" pack="1"/>
</template>
<purpose>Metafunction that computes the return type of the
<computeroutput><functionname alt="proto::make_expr">proto::make_expr()</functionname></computeroutput>
function, with a domain deduced from the domains of the children.</purpose>
<description>
<para>
Computes the return type of the
<computeroutput><functionname alt="proto::make_expr">proto::make_expr()</functionname></computeroutput> function.
</para>
<para>
In this specialization, the domain is deduced from the domains of the child types.
If <computeroutput><classname>proto::is_domain</classname>&lt;A<subscript>0</subscript>&gt;::value</computeroutput>
is <computeroutput>true</computeroutput>, then another specialization is selected.
</para>
</description>
<typedef name="D">
<purpose>For exposition only</purpose>
<type><replaceable>domain-deduced-from-child-types</replaceable></type>
<description>
<para>
In this specialization, Proto uses the domains of the child expressions to compute the
domain of the parent. See
<computeroutput><classname>proto::deduce_domain</classname></computeroutput> for a full
description of the procedure used.
</para>
</description>
</typedef>
<typedef name="type">
<type>typename <classname>proto::result_of::make_expr</classname>&lt;Tag, D, A...&gt;::type</type>
</typedef>
</struct>
<struct-specialization name="make_expr">
<template>
<template-type-parameter name="Tag"/>
<template-type-parameter name="Domain"/>
<template-type-parameter name="A" pack="1"/>
</template>
<specialization>
<template-arg>Tag</template-arg>
<template-arg>Domain</template-arg>
<template-arg pack="1">A</template-arg>
</specialization>
<purpose>Metafunction that computes the return type of the
<computeroutput><functionname alt="proto::make_expr">proto::make_expr()</functionname></computeroutput>
function, within the specified domain.</purpose>
<description>
<para>
Computes the return type of the
<computeroutput><functionname alt="proto::make_expr">proto::make_expr()</functionname></computeroutput>
function.
</para>
</description>
<typedef name="type">
<description>
<para>
Let <computeroutput><replaceable>WRAP&lt;X&gt;</replaceable></computeroutput> be defined such that:
<itemizedlist>
<listitem>
<para>
If <computeroutput>X</computeroutput> is <computeroutput>Y &amp;</computeroutput>
or (possibly cv-qualified) <computeroutput>boost::reference_wrapper&lt;Y&gt;</computeroutput>,
then <computeroutput><replaceable>WRAP&lt;X&gt;</replaceable></computeroutput> is equivalent to
<computeroutput><classname>proto::result_of::as_child</classname>&lt;Y, Domain&gt;</computeroutput>.
</para>
</listitem>
<listitem>
<para>
Otherwise, <computeroutput><replaceable>WRAP&lt;X&gt;</replaceable></computeroutput> is equivalent to
<computeroutput><classname>proto::result_of::as_expr</classname>&lt;X, Domain&gt;</computeroutput>.
</para>
</listitem>
</itemizedlist>
</para>
<para>
If <computeroutput><classname>proto::wants_basic_expr</classname>&lt;typename Domain::proto_generator&gt;::value</computeroutput>
is true, then let <computeroutput><replaceable>E</replaceable></computeroutput> be
<computeroutput><classname>proto::basic_expr</classname></computeroutput>; otherwise,
let <computeroutput><replaceable>E</replaceable></computeroutput> be
<computeroutput><classname>proto::expr</classname></computeroutput>.
</para>
<para>
If <computeroutput>Tag</computeroutput> is
<computeroutput><classname>proto::tag::terminal</classname></computeroutput>, then
<computeroutput>type</computeroutput> is a typedef for
<computeroutput>typename <replaceable>WRAP&lt;A<subscript>0</subscript>&gt;</replaceable>::type</computeroutput>.
</para>
<para>
Otherwise, <computeroutput>type</computeroutput> is a typedef for
<computeroutput>boost::result_of&lt;Domain(<replaceable>E</replaceable>&lt;
Tag, <classname alt="proto::listN">proto::list<emphasis>N</emphasis></classname>&lt;
typename <replaceable>WRAP&lt;A&gt;</replaceable>::type...&gt; &gt;)&gt;::type</computeroutput>
</para>
</description>
<type><emphasis>see-below</emphasis></type>
</typedef>
</struct-specialization>
<!-- proto::result_of::unpack_expr -->
<struct name="unpack_expr">
<template>
<template-type-parameter name="Tag"/>
<template-type-parameter name="Sequence"/>
<template-type-parameter name="Void">
<default><type>void</type></default>
</template-type-parameter>
</template>
<purpose>Metafunction that computes the return type of the
<computeroutput><functionname alt="proto::unpack_expr">proto::unpack_expr()</functionname></computeroutput>
function, with a domain deduced from the domains of the children.
</purpose>
<description>
<para>
Compute the return type of the
<computeroutput><functionname alt="proto::unpack_expr">proto::unpack_expr()</functionname></computeroutput>
function.
</para>
<para>
<computeroutput>Sequence</computeroutput> is a Fusion Forward Sequence.
</para>
<para>
In this specialization, the domain is deduced from the domains of the child types.
If <computeroutput><classname>proto::is_domain</classname>&lt;Sequence&gt;::value</computeroutput>
is <computeroutput>true</computeroutput>, then another specialization is selected.
</para>
</description>
<typedef name="type">
<purpose>Where S is a Fusion RandomAccessSequence equivalent to Sequence, and N is the size of S.</purpose>
<type>
typename <classname>proto::result_of::make_expr</classname>&lt;
Tag,
typename fusion::result_of::value_at_c&lt;<replaceable>S</replaceable>, 0&gt;::type,
...
typename fusion::result_of::value_at_c&lt;<replaceable>S</replaceable>, <replaceable>N</replaceable>-1&gt;::type
&gt;::type
</type>
</typedef>
</struct>
<struct-specialization name="unpack_expr">
<template>
<template-type-parameter name="Tag"/>
<template-type-parameter name="Domain"/>
<template-type-parameter name="Sequence"/>
</template>
<specialization>
<template-arg>Tag</template-arg>
<template-arg>Domain</template-arg>
<template-arg>Sequence</template-arg>
</specialization>
<purpose>Metafunction that computes the return type of the
<computeroutput><functionname alt="proto::unpack_expr">proto::unpack_expr()</functionname></computeroutput>
function, within the specified domain.
</purpose>
<description>
<para>
Computes the return type of the
<computeroutput><functionname alt="proto::unpack_expr">proto::unpack_expr()</functionname></computeroutput>
function.
</para>
</description>
<typedef name="type">
<purpose>Where S is a RandomAccessSequence equivalent to Sequence, and N is the size of S.</purpose>
<type>
typename <classname>proto::result_of::make_expr</classname>&lt;
Tag,
Domain,
typename fusion::result_of::value_at_c&lt;<replaceable>S</replaceable>, 0&gt;::type,
...
typename fusion::result_of::value_at_c&lt;<replaceable>S</replaceable>, <replaceable>N</replaceable>-1&gt;::type
&gt;::type
</type>
</typedef>
</struct-specialization>
</namespace>
<!-- proto::make_expr() -->
<overloaded-function name="make_expr">
<signature>
<type>typename <classname>proto::result_of::make_expr</classname>&lt;Tag, A const...&gt;::type const</type>
<template>
<template-type-parameter name="Tag"/>
<template-type-parameter name="A" pack="1"/>
</template>
<parameter name="a" pack="1">
<paramtype>A const &amp;</paramtype>
</parameter>
</signature>
<signature>
<type>typename <classname>proto::result_of::make_expr</classname>&lt;Tag, Domain, A const...&gt;::type const</type>
<template>
<template-type-parameter name="Tag"/>
<template-type-parameter name="Domain"/>
<template-type-parameter name="A" pack="1"/>
</template>
<parameter name="a" pack="1">
<paramtype>A const &amp;</paramtype>
</parameter>
</signature>
<purpose>Construct an expression of the requested tag type with a domain and with the specified
arguments as children.</purpose>
<description>
<para>
This function template may be invoked either with or without specifying a
<computeroutput>Domain</computeroutput> template parameter. If no domain is specified, the domain
is deduced by examining domains of the given arguments. See
<computeroutput><classname>proto::deduce_domain</classname></computeroutput> for a full
description of the procedure used.
</para>
<para>
Let <computeroutput><replaceable>WRAP</replaceable>(x)</computeroutput> be defined such that:
<itemizedlist>
<listitem>
<para>
If <computeroutput>x</computeroutput> is a <computeroutput>boost::reference_wrapper&lt;&gt;</computeroutput>,
<computeroutput><replaceable>WRAP</replaceable>(x)</computeroutput> is equivalent to
<computeroutput><functionname>proto::as_child</functionname>&lt;Domain&gt;(x.get())</computeroutput>.
</para>
</listitem>
<listitem>
<para>
Otherwise, <computeroutput><replaceable>WRAP</replaceable>(x)</computeroutput> is equivalent to
<computeroutput><functionname>proto::as_expr</functionname>&lt;Domain&gt;(x)</computeroutput>.
</para>
</listitem>
</itemizedlist>
</para>
<para>
If <computeroutput><classname>proto::wants_basic_expr</classname>&lt;typename Domain::proto_generator&gt;::value</computeroutput>
is true, then let <computeroutput><replaceable>E</replaceable></computeroutput> be
<computeroutput><classname>proto::basic_expr</classname></computeroutput>; otherwise,
let <computeroutput><replaceable>E</replaceable></computeroutput> be
<computeroutput><classname>proto::expr</classname></computeroutput>.
</para>
<para>
Let <computeroutput><replaceable>MAKE</replaceable>(Tag, b...)</computeroutput> be defined as
<computeroutput><replaceable>E</replaceable>&lt;Tag,
<classname alt="proto::listN">proto::list<emphasis>N</emphasis></classname>&lt;decltype(b)...&gt; &gt;::make(b...)</computeroutput>.
</para>
<para>
If <computeroutput>Tag</computeroutput> is
<computeroutput><classname>proto::tag::terminal</classname></computeroutput>, then return
<computeroutput><replaceable>WRAP</replaceable>(a<subscript>0</subscript>)</computeroutput>.
</para>
<para>
Otherwise, return
<computeroutput>Domain()(<replaceable>MAKE</replaceable>(Tag, <replaceable>WRAP</replaceable>(a)...))</computeroutput>.
</para>
</description>
</overloaded-function>
<!-- proto::unpack_expr() -->
<overloaded-function name="unpack_expr">
<signature>
<type>typename <classname>proto::result_of::unpack_expr</classname>&lt;Tag, Sequence const&gt;::type const</type>
<template>
<template-type-parameter name="Tag"/>
<template-type-parameter name="Sequence"/>
</template>
<parameter name="sequence">
<paramtype>Sequence const &amp;</paramtype>
<description>
<para>A Fusion Forward Sequence.</para>
</description>
</parameter>
</signature>
<signature>
<type>typename <classname>proto::result_of::unpack_expr</classname>&lt;Tag, Domain, Sequence const&gt;::type const</type>
<template>
<template-type-parameter name="Tag"/>
<template-type-parameter name="Domain"/>
<template-type-parameter name="Sequence"/>
</template>
<parameter name="sequence">
<paramtype>Sequence const &amp;</paramtype>
</parameter>
</signature>
<purpose>Construct an expression of the requested tag type with a domain and with children
from the specified Fusion Forward Sequence.</purpose>
<description>
<para>
This function template may be invoked either with or without specifying a
<computeroutput>Domain</computeroutput> argument. If no domain is specified, the domain
is deduced by examining domains of each element of the sequence. See
<computeroutput><classname>proto::deduce_domain</classname></computeroutput> for a full
description of the procedure used.
</para>
<para>
Let <computeroutput>s</computeroutput> be a Fusion RandomAccessSequence equivalent to
<computeroutput>sequence</computeroutput>.
Let <computeroutput><replaceable>WRAP</replaceable>(N, s)</computeroutput> be defined such that:
<itemizedlist>
<listitem>
<para>
If <computeroutput>fusion::result_of::value_at_c&lt;decltype(s),N&gt;::type</computeroutput> is a reference type
or an instantiation of <computeroutput>boost::reference_wrapper&lt;&gt;</computeroutput>,
<computeroutput><replaceable>WRAP</replaceable>(N, s)</computeroutput> is equivalent to
<computeroutput><functionname>proto::as_child</functionname>&lt;Domain&gt;(fusion::at_c&lt;N&gt;(s))</computeroutput>.
</para>
</listitem>
<listitem>
<para>
Otherwise, <computeroutput><replaceable>WRAP</replaceable>(N, s)</computeroutput> is equivalent to
<computeroutput><functionname>proto::as_expr</functionname>&lt;Domain&gt;(fusion::at_c&lt;N&gt;(s))</computeroutput>.
</para>
</listitem>
</itemizedlist>
</para>
<para>
If <computeroutput><classname>proto::wants_basic_expr</classname>&lt;typename Domain::proto_generator&gt;::value</computeroutput>
is true, then let <computeroutput><replaceable>E</replaceable></computeroutput> be
<computeroutput><classname>proto::basic_expr</classname></computeroutput>; otherwise,
let <computeroutput><replaceable>E</replaceable></computeroutput> be
<computeroutput><classname>proto::expr</classname></computeroutput>.
</para>
<para>
Let <computeroutput><replaceable>MAKE</replaceable>(Tag, b...)</computeroutput> be defined as
<computeroutput><replaceable>E</replaceable>&lt;Tag,
<classname alt="proto::listN">proto::list<emphasis>N</emphasis></classname>&lt;decltype(b)...&gt; &gt;::make(b...)</computeroutput>.
</para>
<para>
If <computeroutput>Tag</computeroutput> is
<computeroutput><classname>proto::tag::terminal</classname></computeroutput>, then return
<computeroutput><replaceable>WRAP</replaceable>(0, s)</computeroutput>.
</para>
<para>
Otherwise, return
<computeroutput>Domain()(<replaceable>MAKE</replaceable>(Tag, <replaceable>WRAP</replaceable>(0, s),...
<replaceable>WRAP</replaceable>(<replaceable>N</replaceable>-1, s)))</computeroutput>, where
<replaceable>N</replaceable> is the size of <computeroutput>Sequence</computeroutput>.
</para>
</description>
</overloaded-function>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,837 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/matches.hpp">
<para>
Contains definition of the
<computeroutput>
<classname alt="boost::proto::matches">proto::matches&lt;&gt;</classname>
</computeroutput>
metafunction for determining if a given expression matches a given pattern.
</para>
<namespace name="boost">
<namespace name="proto">
<struct name="_">
<inherit><type><classname>proto::transform</classname>&lt;_&gt;</type></inherit>
<purpose>A wildcard grammar element that matches any expression, and a transform that returns
the current expression unchanged.</purpose>
<description>
<para>
The wildcard type, <computeroutput>proto::_</computeroutput>, is a grammar element such
that <computeroutput><classname>proto::matches</classname>&lt;E, proto::_&gt;::value</computeroutput>
is <computeroutput>true</computeroutput> for any expression type <computeroutput>E</computeroutput>.
</para>
<para>
The wildcard can also be used as a stand-in for a template argument when matching terminals.
For instance, the following is a grammar that will match any
<computeroutput>std::complex&lt;&gt;</computeroutput> terminal:<programlisting>BOOST_MPL_ASSERT((
<classname>proto::matches</classname>&lt;
<classname>proto::terminal</classname>&lt;std::complex&lt;double&gt; &gt;::type,
<emphasis role="bold"><classname>proto::terminal</classname>&lt;std::complex&lt; proto::_ &gt; &gt;</emphasis>
&gt;
));</programlisting>
</para>
<para>
When used as a transform, <computeroutput>proto::_</computeroutput> returns the current expression
unchanged. For instance, in the following, <computeroutput>proto::_</computeroutput> is used with
the <computeroutput><classname alt="proto::fold">proto::fold&lt;&gt;</classname></computeroutput>
transform to fold the children of a node:<programlisting>struct CountChildren :
<classname>proto::or_</classname>&lt;
// Terminals have no children
<classname>proto::when</classname>&lt;<classname>proto::terminal</classname>&lt;proto::_&gt;, mpl::int_&lt;0&gt;()&gt;,
// Use proto::fold&lt;&gt; to count the children of non-terminals
<classname>proto::otherwise</classname>&lt;
<classname>proto::fold</classname>&lt;
proto::_, // &lt;-- fold the current expression
mpl::int_&lt;0&gt;(),
mpl::plus&lt;<classname>proto::_state</classname>, mpl::int_&lt;1&gt; &gt;()
&gt;
&gt;
&gt;
{};</programlisting>
</para>
</description>
<struct name="impl">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="State"/>
<template-type-parameter name="Data"/>
</template>
<inherit><type><classname>proto::transform_impl</classname>&lt;Expr, State, Data&gt;</type></inherit>
<typedef name="result_type">
<type>Expr</type>
</typedef>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>Expr</type>
<parameter name="expr">
<paramtype>typename impl::expr_param</paramtype>
<description>
<para>An expression </para>
</description>
</parameter>
<parameter name="">
<paramtype>typename impl::state_param</paramtype>
</parameter>
<parameter name="">
<paramtype>typename impl::data_param</paramtype>
</parameter>
<returns>
<para>
<computeroutput>expr</computeroutput>
</para>
</returns>
</method>
</method-group>
</struct>
<typedef name="proto_grammar">
<type>_</type>
</typedef>
</struct>
<!-- proto::not_ -->
<struct name="not_">
<template>
<template-type-parameter name="Grammar"/>
</template>
<inherit><type><classname>proto::transform</classname>&lt;not_&lt;Grammar&gt; &gt;</type></inherit>
<purpose>Inverts the set of expressions matched by a grammar. When used as a transform,
<computeroutput>proto::not_&lt;&gt;</computeroutput> returns the current expression unchanged.
</purpose>
<description>
<para>
If an expression type <computeroutput>E</computeroutput> does not match a grammar
<computeroutput>G</computeroutput>, then <computeroutput>E</computeroutput> <emphasis>does</emphasis>
match <computeroutput>proto::not_&lt;G&gt;</computeroutput>. For example,
<computeroutput><classname>proto::not_</classname>&lt;<classname>proto::terminal</classname>&lt;<classname>proto::_</classname>&gt; &gt;</computeroutput>
will match any non-terminal.
</para>
</description>
<struct name="impl">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="State"/>
<template-type-parameter name="Data"/>
</template>
<inherit><type><classname>proto::transform_impl</classname>&lt;Expr, State, Data&gt;</type></inherit>
<typedef name="result_type">
<type>Expr</type>
</typedef>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>Expr</type>
<parameter name="expr">
<paramtype>typename impl::expr_param</paramtype>
<description>
<para>An expression </para>
</description>
</parameter>
<parameter name="">
<paramtype>typename impl::state_param</paramtype>
</parameter>
<parameter name="">
<paramtype>typename impl::data_param</paramtype>
</parameter>
<requires>
<para>
<computeroutput><classname>proto::matches</classname>&lt;Expr, proto::not_&gt;::value</computeroutput>
is <computeroutput>true</computeroutput>.
</para>
</requires>
<returns>
<para>
<computeroutput>expr</computeroutput>
</para>
</returns>
</method>
</method-group>
</struct>
<typedef name="proto_grammar">
<type>not_</type>
</typedef>
</struct>
<!-- proto::if_ -->
<struct name="if_">
<template>
<template-type-parameter name="If"/>
<template-type-parameter name="Then">
<default><type><classname>proto::_</classname></type></default>
</template-type-parameter>
<template-type-parameter name="Else">
<default><type><classname>proto::not_</classname>&lt;<classname>proto::_</classname>&gt;</type></default>
</template-type-parameter>
</template>
<inherit><classname>proto::transform</classname>&lt;if_&lt;If, Then, Else&gt; &gt;</inherit>
<purpose>Used to select one grammar or another based on the result of a compile-time Boolean.
When used as a transform, <computeroutput>proto::if_&lt;&gt;</computeroutput> selects between two
transforms based on a compile-time Boolean.</purpose>
<description>
<para>
When <computeroutput>proto::if_&lt;If, Then, Else&gt;</computeroutput> is used as a grammar,
<computeroutput>If</computeroutput> must be a Proto transform and
<computeroutput>Then</computeroutput> and <computeroutput>Else</computeroutput> must be grammars.
An expression type <computeroutput>E</computeroutput> matches
<computeroutput>proto::if_&lt;If, Then, Else&gt;</computeroutput> if
<computeroutput>boost::result_of&lt;<classname>proto::when</classname>&lt;<classname>proto::_</classname>, If&gt;(E)&gt;::type::value</computeroutput>
is <computeroutput>true</computeroutput> and
<computeroutput>E</computeroutput> matches <computeroutput>Then</computeroutput>; or, if
<computeroutput>boost::result_of&lt;<classname>proto::when</classname>&lt;<classname>proto::_</classname>, If&gt;(E)&gt;::type::value</computeroutput>
is <computeroutput>false</computeroutput> and <computeroutput>E</computeroutput> matches <computeroutput>Else</computeroutput>.
</para>
<para>
The template parameter <computeroutput>Then</computeroutput> defaults to <computeroutput><classname>proto::_</classname></computeroutput>
and <computeroutput>Else</computeroutput> defaults to
<computeroutput><classname>proto::not_</classname>&lt;<classname>proto::_</classname>&gt;</computeroutput>,
so an expression type <computeroutput>E</computeroutput> will match
<computeroutput>proto::if_&lt;If&gt;</computeroutput> if and only if
<computeroutput>boost::result_of&lt;<classname>proto::when</classname>&lt;<classname>proto::_</classname>, If&gt;(E)&gt;::type::value</computeroutput>
is <computeroutput>true</computeroutput>.
</para>
<para>
<programlisting>// A grammar that only matches integral terminals,
// using is_integral&lt;&gt; from Boost.Type_traits.
struct IsIntegral :
<classname>proto::and_</classname>&lt;
<classname>proto::terminal</classname>&lt;<classname>proto::_</classname>&gt;,
<classname>proto::if_</classname>&lt; boost::is_integral&lt;<classname>proto::_value</classname>&gt;()&gt;
&gt;
{};</programlisting>
</para>
<para>
When <computeroutput>proto::if_&lt;If, Then, Else&gt;</computeroutput> is used as a transform,
<computeroutput>If</computeroutput>, <computeroutput>Then</computeroutput> and
<computeroutput>Else</computeroutput> must be Proto transforms. When applying the transform to
an expression <computeroutput>E</computeroutput>, state <computeroutput>S</computeroutput> and
data <computeroutput>V</computeroutput>, if
<computeroutput>boost::result_of&lt;<classname>proto::when</classname>&lt;<classname>proto::_</classname>, If&gt;(E,S,V)&gt;::type::value</computeroutput>
is <computeroutput>true</computeroutput> then the <computeroutput>Then</computeroutput> transform
is applied; otherwise the <computeroutput>Else</computeroutput> transform is applied.
<programlisting>// Match a terminal. If the terminal is integral, return
// mpl::true_; otherwise, return mpl::false_.
struct IsIntegral2 :
<classname>proto::when</classname>&lt;
<classname>proto::terminal</classname>&lt;_&gt;,
proto::if_&lt;
boost::is_integral&lt;<classname>proto::_value</classname>&gt;(),
mpl::true_(),
mpl::false_()
&gt;
&gt;
{};</programlisting>
</para>
</description>
<struct name="impl">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="State"/>
<template-type-parameter name="Data"/>
</template>
<inherit><type><classname>proto::transform_impl</classname>&lt; Expr, State, Data &gt;</type></inherit>
<typedef name="result_type">
<type>typename mpl::if_&lt;
typename boost::result_of&lt;<classname>proto::when</classname>&lt;<classname>proto::_</classname>, If&gt;(Expr, State, Data)&gt;::type,
typename boost::result_of&lt;<classname>proto::when</classname>&lt;<classname>proto::_</classname>, Then&gt;(Expr, State, Data)&gt;::type,
typename boost::result_of&lt;<classname>proto::when</classname>&lt;<classname>proto::_</classname>, Else&gt;(Expr, State, Data)&gt;::type
&gt;::type</type>
</typedef>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>result_type</type>
<parameter name="expr">
<paramtype>typename impl::expr_param</paramtype>
<description>
<para>An expression </para>
</description>
</parameter>
<parameter name="state">
<paramtype>typename impl::state_param</paramtype>
<description>
<para>The current state </para>
</description>
</parameter>
<parameter name="data">
<paramtype>typename impl::data_param</paramtype>
<description>
<para>A data of arbitrary type </para>
</description>
</parameter>
<returns>
<para>
<computeroutput><classname>proto::when</classname>&lt;<classname>proto::_</classname>, <replaceable>Then-or-Else</replaceable>&gt;()(expr, state, data)</computeroutput>
</para>
</returns>
</method>
</method-group>
</struct>
<typedef name="proto_grammar">
<type>if_</type>
</typedef>
</struct>
<!-- proto::or_ -->
<struct name="or_">
<template>
<template-type-parameter name="G" pack="1"/>
</template>
<inherit><type><classname>proto::transform</classname>&lt;or_&lt;G...&gt; &gt;</type></inherit>
<purpose>For matching one of a set of alternate grammars. Alternates are tried in order to avoid ambiguity.
When used as a transform, <computeroutput>proto::or_&lt;&gt;</computeroutput> applies the transform
associated with the first grammar that matches the expression.</purpose>
<description>
<para>
An expression type <computeroutput>E</computeroutput> matches
<computeroutput>proto::or_&lt;G<subscript>0</subscript>,G<subscript>1</subscript>,...G<subscript>n</subscript>&gt;</computeroutput>
if <computeroutput>E</computeroutput> matches any <computeroutput>G<subscript>x</subscript></computeroutput> for
<computeroutput>x</computeroutput> in <computeroutput>[0,n]</computeroutput>.
</para>
<para>
When applying
<computeroutput>proto::or_&lt;G<subscript>0</subscript>,G<subscript>1</subscript>,...G<subscript>n</subscript>&gt;</computeroutput>
as a transform with an expression <computeroutput>e</computeroutput> of type <computeroutput>E</computeroutput>,
state <computeroutput>s</computeroutput> and data <computeroutput>d</computeroutput>, it is equivalent to
<computeroutput>G<subscript>x</subscript>()(e, s, d)</computeroutput>, where
<computeroutput>x</computeroutput> is the lowest number such that
<computeroutput><classname>proto::matches</classname>&lt;E, G<subscript>x</subscript>&gt;::value</computeroutput>
is <computeroutput>true</computeroutput>.
</para>
<para>
The maximun number of template arguments <computeroutput>proto::or_&lt;&gt;</computeroutput> accepts
is controlled by the <computeroutput><macroname>BOOST_PROTO_MAX_LOGICAL_ARITY</macroname></computeroutput>
macro.
</para>
</description>
<struct name="impl">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="State"/>
<template-type-parameter name="Data"/>
</template>
<inherit><type><classname>proto::transform_impl</classname>&lt; Expr, State, Data &gt;</type></inherit>
<typedef name="result_type">
<type><replaceable>unspecified</replaceable></type>
</typedef>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>result_type</type>
<parameter name="expr">
<paramtype>typename impl::expr_param</paramtype>
<description>
<para>An expression </para>
</description>
</parameter>
<parameter name="state">
<paramtype>typename impl::state_param</paramtype>
<description>
<para>The current state </para>
</description>
</parameter>
<parameter name="data">
<paramtype>typename impl::data_param</paramtype>
<description>
<para>A data of arbitrary type </para>
</description>
</parameter>
<returns>
<para>
<computeroutput>
G<subscript>x</subscript>()(expr, state, data)
</computeroutput>, where
<computeroutput>x</computeroutput> is the lowest number such that
<computeroutput>
<classname>proto::matches</classname>&lt;Expr, G<subscript>x</subscript>&gt;::value
</computeroutput>
is <computeroutput>true</computeroutput>.
</para>
</returns>
</method>
</method-group>
</struct>
<typedef name="proto_grammar">
<type>or_</type>
</typedef>
</struct>
<!-- proto::and_ -->
<struct name="and_">
<template>
<template-type-parameter name="G" pack="1"/>
</template>
<inherit><type><classname>proto::transform</classname>&lt;and_&lt;G...&gt; &gt;</type></inherit>
<purpose>For matching all of a set of grammars. When used as a transform,
<computeroutput>proto::and_&lt;&gt;</computeroutput> applies the transform associated
with each grammar in the set and returns the result of the last.</purpose>
<description>
<para>
An expression type <computeroutput>E</computeroutput> matches
<computeroutput>proto::and_&lt;G<subscript>0</subscript>,G<subscript>1</subscript>,...G<subscript>n</subscript>&gt;</computeroutput>
if <computeroutput>E</computeroutput> matches all <computeroutput>G<subscript>x</subscript></computeroutput>
for <computeroutput>x</computeroutput> in <computeroutput>[0,n]</computeroutput>.
</para>
<para>
When applying
<computeroutput>proto::and_&lt;G<subscript>0</subscript>,G<subscript>1</subscript>,...G<subscript>n</subscript>&gt;</computeroutput>
as a transform with an expression <computeroutput>e</computeroutput>, state
<computeroutput>s</computeroutput> and data <computeroutput>d</computeroutput>, it is equivalent
to <computeroutput>(G<subscript>0</subscript>()(e, s, d),G<subscript>1</subscript>()(e, s, d),...G<subscript>n</subscript>()(e, s, d))</computeroutput>.
</para>
<para>
The maximun number of template arguments <computeroutput>proto::and_&lt;&gt;</computeroutput> accepts
is controlled by the <computeroutput><macroname>BOOST_PROTO_MAX_LOGICAL_ARITY</macroname></computeroutput>
macro.
</para>
</description>
<struct name="impl">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="State"/>
<template-type-parameter name="Data"/>
</template>
<inherit><type><classname>proto::transform_impl</classname>&lt; Expr, State, Data &gt;</type></inherit>
<typedef name="result_type">
<type>typename boost::result_of&lt;G<subscript>n</subscript>(Expr, State, Data)&gt;::type</type>
</typedef>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>result_type</type>
<parameter name="expr">
<paramtype>typename impl::expr_param</paramtype>
<description>
<para>An expression </para>
</description>
</parameter>
<parameter name="state">
<paramtype>typename impl::state_param</paramtype>
<description>
<para>The current state </para>
</description>
</parameter>
<parameter name="data">
<paramtype>typename impl::data_param</paramtype>
<description>
<para>A data of arbitrary type </para>
</description>
</parameter>
<returns>
<para>
<computeroutput>(G<subscript>0</subscript>()(expr, state, data),G<subscript>1</subscript>()(expr, state, data),...G<subscript>n</subscript>()(expr, state, data))</computeroutput>
</para>
</returns>
</method>
</method-group>
</struct>
<typedef name="proto_grammar">
<type>and_</type>
</typedef>
</struct>
<!-- proto::switch_ -->
<struct name="switch_">
<template>
<template-type-parameter name="Cases"/>
<template-type-parameter name="Transform"/>
</template>
<inherit><classname>proto::transform</classname>&lt;switch_&lt;Cases, Transform&gt; &gt;</inherit>
<purpose>For matching one of a set of alternate grammars, which are looked up based on
the result type of the transform passed in second template parameter.
If no transform is passed, the default one is <computeroutput><classname>proto::tag_of</classname>&lt;<classname>proto::_</classname>&gt;()</computeroutput>
so the default matching is based on the expression's tag type. When used as a transform,
<computeroutput>proto::switch_&lt;&gt;</computeroutput> applies the transform associated
with the sub-grammar that matches the expression.</purpose>
<description>
<para>
An expression type <computeroutput>E</computeroutput> matches
<computeroutput>proto::switch_&lt;C,T&gt;</computeroutput> if
<computeroutput>E</computeroutput> matches
<computeroutput>C::case_&lt;boost::result_of&lt;<classname>proto::when</classname>&lt;<classname>proto::_</classname>,T&gt;(E)&gt;::type&gt;</computeroutput>.
</para>
<para>
When applying <computeroutput>proto::switch_&lt;C,T&gt;</computeroutput> as a
transform with an expression <computeroutput>e</computeroutput> of type
<computeroutput>E</computeroutput>, state <computeroutput>s</computeroutput> of
type <computeroutput>S</computeroutput> and data <computeroutput>d</computeroutput>
of type <computeroutput>D</computeroutput>, it is equivalent to
<computeroutput>C::case_&lt;boost::result_of&lt;<classname>proto::when</classname>&lt;<classname>proto::_</classname>,T&gt;(E,S,D)&gt;::type&gt;()(e, s, d)</computeroutput>.
</para>
</description>
<struct name="impl">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="State"/>
<template-type-parameter name="Data"/>
</template>
<inherit><type>
Cases::template case_&lt;
typename <classname>when</classname>&lt;_, Transform&gt;::template impl&lt;Expr, State, Data&gt;::result_type
&gt;::template impl&lt;Expr, State, Data&gt;</type>
</inherit>
</struct>
<typedef name="proto_grammar">
<type>switch_</type>
</typedef>
</struct>
<!-- proto::exact -->
<struct name="exact">
<template>
<template-type-parameter name="T"/>
</template>
<purpose>For forcing exact matches of terminal types.</purpose>
<description>
<para>By default, matching terminals ignores references and cv-qualifiers. For instance,
a terminal expression of type
<computeroutput><classname>proto::terminal</classname>&lt;int const &amp;&gt;::type</computeroutput>
will match the grammar <computeroutput><classname>proto::terminal</classname>&lt;int&gt;</computeroutput>.
If that is not desired, you can force an exact match with
<computeroutput><classname>proto::terminal</classname>&lt;proto::exact&lt;int&gt; &gt;</computeroutput>.
This will only match integer terminals where the terminal is held by value.</para>
</description>
</struct>
<!-- proto::convertible_to -->
<struct name="convertible_to">
<template>
<template-type-parameter name="T"/>
</template>
<purpose>For matching terminals that are convertible to a type.</purpose>
<description>
<para>
Use <computeroutput>proto::convertible_to&lt;&gt;</computeroutput> to match a terminal that is
convertible to some type. For example, the grammar
<computeroutput><classname>proto::terminal</classname>&lt;proto::convertible_to&lt;int&gt; &gt;</computeroutput>
will match any terminal whose argument is convertible to an integer.
</para>
</description>
</struct>
<!-- proto::vararg -->
<struct name="vararg">
<template>
<template-type-parameter name="Grammar"/>
</template>
<purpose>For matching a Grammar to a variable number of sub-expressions.</purpose>
<description>
<para>
An expression type <computeroutput><classname>proto::basic_expr</classname>&lt;AT,
<classname alt="proto::listN">proto::list<replaceable>N</replaceable></classname>&lt;A<subscript>0</subscript>,...A<subscript>n</subscript>,U<subscript>0</subscript>,...U<subscript>m</subscript>&gt; &gt;</computeroutput>
matches a grammar <computeroutput><classname>proto::basic_expr</classname>&lt;BT,
<classname alt="proto::listN">proto::list<replaceable>M</replaceable></classname>&lt;B<subscript>0</subscript>,...B<subscript>n</subscript>,proto::vararg&lt;V&gt; &gt; &gt;</computeroutput>
if <computeroutput>BT</computeroutput> is <computeroutput><classname>proto::_</classname></computeroutput>
or <computeroutput>AT</computeroutput>, and if
<computeroutput>A<subscript>x</subscript></computeroutput> matches
<computeroutput>B<subscript>x</subscript></computeroutput>
for each <computeroutput>x</computeroutput> in <computeroutput>[0,n]</computeroutput>
and if <computeroutput>U<subscript>x</subscript></computeroutput> matches
<computeroutput>V</computeroutput> for each <computeroutput>x</computeroutput> in <computeroutput>[0,m]</computeroutput>.
</para>
<para>For example:</para>
<para>
<programlisting>// Match any function call expression, regardless
// of the number of function arguments:
struct Function :
<classname>proto::function</classname>&lt; proto::vararg&lt;proto::_&gt; &gt;
{};</programlisting>
</para>
<para>
When used as a transform, <computeroutput>proto::vararg&lt;G&gt;</computeroutput>
applies <computeroutput>G</computeroutput>'s transform.
</para>
</description>
</struct>
<!-- proto::matches -->
<struct name="matches">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="Grammar"/>
</template>
<purpose>A Boolean metafunction that evaluates whether a given expression type matches a grammar.</purpose>
<description>
<para>
<computeroutput>proto::matches&lt;Expr, Grammar&gt;</computeroutput> inherits from
<computeroutput>mpl::true_</computeroutput> if
<computeroutput>Expr::proto_grammar</computeroutput> matches
<computeroutput>Grammar::proto_grammar</computeroutput>, and from
<computeroutput>mpl::false_</computeroutput> otherwise.
</para>
<para>
Non-terminal expressions are matched against a grammar according to the following rules:
<itemizedlist>
<listitem>
<para>
The wildcard pattern, <computeroutput>
<classname>proto::_</classname>
</computeroutput>, matches any expression.
</para>
</listitem>
<listitem>
<para>
An expression
<computeroutput>
<classname>proto::basic_expr</classname>&lt;AT,
<classname alt="proto::listN">
proto::list<replaceable>N</replaceable>
</classname>&lt;A<subscript>0</subscript>,...A<subscript>n</subscript>&gt;
&gt;
</computeroutput>
matches a grammar
<computeroutput>
<classname>proto::basic_expr</classname>&lt;BT,
<classname alt="proto::listN">
proto::list<replaceable>N</replaceable>
</classname>&lt;B<subscript>0</subscript>,...B<subscript>n</subscript>&gt;
&gt;
</computeroutput> if
<computeroutput>BT</computeroutput> is <computeroutput>
<classname>proto::_</classname>
</computeroutput> or
<computeroutput>AT</computeroutput>, and if <computeroutput>
A<subscript>x</subscript>
</computeroutput> matches
<computeroutput>
B<subscript>x</subscript>
</computeroutput> for each <computeroutput>x</computeroutput> in <computeroutput>[0,n]</computeroutput>.
</para>
</listitem>
<listitem>
<para>
An expression
<computeroutput>
<classname>proto::basic_expr</classname>&lt;AT,
<classname alt="proto::listN">
proto::list<replaceable>N</replaceable>
</classname>&lt;A<subscript>0</subscript>,...A<subscript>n</subscript>,U<subscript>0</subscript>,...U<subscript>m</subscript>&gt;
&gt;
</computeroutput> matches a grammar
<computeroutput>
<classname>proto::basic_expr</classname>&lt;BT,
<classname alt="proto::listN">
proto::list<replaceable>M</replaceable>
</classname>&lt;B<subscript>0</subscript>,...B<subscript>n</subscript>,<classname>proto::vararg</classname>&lt;V&gt;
&gt; &gt;
</computeroutput> if
<computeroutput>BT</computeroutput> is <computeroutput>
<classname>proto::_</classname>
</computeroutput> or
<computeroutput>AT</computeroutput>, and if
<computeroutput>
A<subscript>x</subscript>
</computeroutput> matches
<computeroutput>
B<subscript>x</subscript>
</computeroutput> for each
<computeroutput>x</computeroutput> in <computeroutput>[0,n]</computeroutput> and if
<computeroutput>
U<subscript>x</subscript>
</computeroutput> matches
<computeroutput>V</computeroutput> for each <computeroutput>x</computeroutput> in
<computeroutput>[0,m]</computeroutput>.
</para>
</listitem>
<listitem>
<para>
An expression <computeroutput>E</computeroutput> matches
<computeroutput>
<classname>proto::or_</classname>&lt;B<subscript>0</subscript>,...B<subscript>n</subscript>&gt;
</computeroutput> if
<computeroutput>E</computeroutput> matches some
<computeroutput>
B<subscript>x</subscript>
</computeroutput> for
<computeroutput>x</computeroutput> in <computeroutput>[0,n]</computeroutput>.
</para>
</listitem>
<listitem>
<para>
An expression <computeroutput>E</computeroutput> matches
<computeroutput>
<classname>proto::and_</classname>&lt;B<subscript>0</subscript>,...B<subscript>n</subscript>&gt;
</computeroutput> if
<computeroutput>E</computeroutput> matches all
<computeroutput>
B<subscript>x</subscript>
</computeroutput> for
<computeroutput>x</computeroutput> in <computeroutput>[0,n]</computeroutput>.
</para>
</listitem>
<listitem>
<para>
An expression <computeroutput>E</computeroutput> matches
<computeroutput>
<classname>proto::if_</classname>&lt;T,U,V&gt;
</computeroutput> if:
<itemizedlist>
<listitem>
<computeroutput>
boost::result_of&lt;<classname>proto::when</classname>&lt;<classname>proto::_</classname>,T&gt;(E)&gt;::type::value
</computeroutput>
is <computeroutput>true</computeroutput> and
<computeroutput>E</computeroutput> matches
<computeroutput>U</computeroutput>, <emphasis>or</emphasis>
</listitem>
<listitem>
<computeroutput>
boost::result_of&lt;<classname>proto::when</classname>&lt;<classname>proto::_</classname>,T&gt;(E)&gt;::type::value
</computeroutput>
is <computeroutput>false</computeroutput> and <computeroutput>E</computeroutput> matches
<computeroutput>V</computeroutput>.
</listitem>
</itemizedlist>
Note: <computeroutput>U</computeroutput> defaults to <computeroutput>
<classname>proto::_</classname>
</computeroutput>
and <computeroutput>V</computeroutput> defaults to
<computeroutput>
<classname>proto::not_</classname>&lt;<classname>proto::_</classname>&gt;
</computeroutput>.
</para>
</listitem>
<listitem>
<para>
An expression <computeroutput>E</computeroutput> matches
<computeroutput>
<classname>proto::not_</classname>&lt;T&gt;
</computeroutput> if
<computeroutput>E</computeroutput> does <emphasis>not</emphasis> match <computeroutput>T</computeroutput>.
</para>
</listitem>
<listitem>
<para>
An expression <computeroutput>E</computeroutput> matches
<computeroutput>
<classname>proto::switch_</classname>&lt;C, T&gt;
</computeroutput> if
<computeroutput>E</computeroutput> matches <computeroutput>C::case_&lt;boost::result_of&lt;<classname>proto::when</classname>&lt;<classname>proto::_</classname>,T&gt;(E)&gt;::type&gt;</computeroutput>.
Note: <computeroutput>T</computeroutput> defaults to <computeroutput><classname>proto::tag_of</classname>&lt;<classname>proto::_</classname>&gt;()</computeroutput>
</para>
</listitem>
</itemizedlist>
</para>
<para>
A terminal expression can trivially match the grammar <classname>proto::_</classname>. In addition,
a terminal expression
<computeroutput>
<classname>proto::basic_expr</classname>&lt;AT,
<classname>proto::term</classname>&lt;A&gt; &gt;
</computeroutput> matches a grammar
<computeroutput>
<classname>proto::basic_expr</classname>&lt;BT, <classname>proto::term</classname>&lt;B&gt; &gt;
</computeroutput>
if <computeroutput>BT</computeroutput> is <computeroutput><classname>proto::_</classname></computeroutput>
or <computeroutput>AT</computeroutput> and one of the following is true:
<itemizedlist>
<listitem>
<para>
<computeroutput>B</computeroutput> is the wildcard pattern,
<computeroutput>
<classname>proto::_</classname>
</computeroutput>
</para>
</listitem>
<listitem>
<para>
<computeroutput>A</computeroutput> is <computeroutput>B</computeroutput>
</para>
</listitem>
<listitem>
<para>
<computeroutput>A</computeroutput> is <computeroutput>B &amp;</computeroutput>
</para>
</listitem>
<listitem>
<para>
<computeroutput>A</computeroutput> is <computeroutput>B const &amp;</computeroutput>
</para>
</listitem>
<listitem>
<para>
<computeroutput>B</computeroutput> is <computeroutput>
<classname>proto::exact</classname>&lt;A&gt;
</computeroutput>
</para>
</listitem>
<listitem>
<para>
<computeroutput>B</computeroutput> is
<computeroutput>
<classname>proto::convertible_to</classname>&lt;X&gt;
</computeroutput>
and <computeroutput>boost::is_convertible&lt;A,X&gt;::value</computeroutput> is
<computeroutput>true</computeroutput>.
</para>
</listitem>
<listitem>
<para>
<computeroutput>A</computeroutput> is <computeroutput>X[M]</computeroutput> or
<computeroutput>X(&amp;)[M]</computeroutput> and
<computeroutput>B</computeroutput> is <computeroutput>
X[<globalname>proto::N</globalname>]
</computeroutput>.
</para>
</listitem>
<listitem>
<para>
<computeroutput>A</computeroutput> is <computeroutput>X(&amp;)[M]</computeroutput>
and <computeroutput>B</computeroutput> is <computeroutput>
X(&amp;)[<globalname>proto::N</globalname>]
</computeroutput>.
</para>
</listitem>
<listitem>
<para>
<computeroutput>A</computeroutput> is <computeroutput>X[M]</computeroutput> or
<computeroutput>X(&amp;)[M]</computeroutput> and <computeroutput>B</computeroutput> is
<computeroutput>X*</computeroutput>.
</para>
</listitem>
<listitem>
<para>
<computeroutput>B</computeroutput> <replaceable>lambda-matches</replaceable>
<computeroutput>A</computeroutput> (see below).
</para>
</listitem>
</itemizedlist>
</para>
<para>
A type <computeroutput>B</computeroutput> <replaceable>lambda-matches</replaceable>
<computeroutput>A</computeroutput> if one of the following is true:
<itemizedlist>
<listitem>
<para>
<computeroutput>B</computeroutput> is <computeroutput>A</computeroutput>
</para>
</listitem>
<listitem>
<para>
<computeroutput>B</computeroutput> is the wildcard pattern, <computeroutput>
<classname>proto::_</classname>
</computeroutput>
</para>
</listitem>
<listitem>
<para>
<computeroutput>B</computeroutput> is <computeroutput>
T&lt;B<subscript>0</subscript>,...B<subscript>n</subscript>&gt;
</computeroutput> and <computeroutput>A</computeroutput> is <computeroutput>
T&lt;A<subscript>0</subscript>,...A<subscript>n</subscript>&gt;
</computeroutput> and for each <computeroutput>x</computeroutput> in <computeroutput>[0,n]</computeroutput>,
<computeroutput>A<subscript>x</subscript></computeroutput> and
<computeroutput>B<subscript>x</subscript></computeroutput> are types such that
<computeroutput>A<subscript>x</subscript></computeroutput> <replaceable>lambda-matches</replaceable>
<computeroutput>B<subscript>x</subscript></computeroutput>
</para>
</listitem>
</itemizedlist>
</para>
</description>
<inherit>
<type>mpl::bool_&lt;<replaceable>true-or-false</replaceable>&gt;</type></inherit>
</struct>
</namespace>
</namespace>
</header>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/proto.hpp">
<para>Includes all of Proto, except the Boost.Typeof registrations.</para>
</header>

View File

@@ -0,0 +1,397 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/proto_fwd.hpp">
<para>Forward declarations of all of proto's public types and functions. </para>
<namespace name="boost">
<namespace name="proto">
<struct name="callable">
<purpose>Base class for callable <conceptname>PolymorphicFunctionObject</conceptname>s</purpose>
<description>
<para>
When defining a callable <conceptname>PolymorphicFunctionObject</conceptname>, inherit
from <computeroutput>proto::callable</computeroutput> so that it can be used to create
a <conceptname>CallableTransform</conceptname>.
</para>
<para>
<computeroutput><classname>proto::is_callable</classname>&lt;T&gt;::value</computeroutput> is
<computeroutput>true</computeroutput> for types that inherit from
<computeroutput>proto::callable</computeroutput>.
</para>
</description>
</struct>
<data-member name="N">
<description>
<para>Array size wildcard for Proto grammars that match array terminals.</para></description>
<type>int const</type>
</data-member>
<namespace name="functional">
<typedef name="make_terminal">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::terminal</classname> &gt;</type>
</typedef>
<typedef name="make_unary_plus">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::unary_plus</classname> &gt;</type>
</typedef>
<typedef name="make_negate">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::negate</classname> &gt;</type>
</typedef>
<typedef name="make_dereference">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::dereference</classname> &gt;</type>
</typedef>
<typedef name="make_complement">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::complement</classname> &gt;</type>
</typedef>
<typedef name="make_address_of">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::address_of</classname> &gt;</type>
</typedef>
<typedef name="make_logical_not">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::logical_not</classname> &gt;</type>
</typedef>
<typedef name="make_pre_inc">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::pre_inc</classname> &gt;</type>
</typedef>
<typedef name="make_pre_dec">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::pre_dec</classname> &gt;</type>
</typedef>
<typedef name="make_post_inc">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::post_inc</classname> &gt;</type>
</typedef>
<typedef name="make_post_dec">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::post_dec</classname> &gt;</type>
</typedef>
<typedef name="make_shift_left">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::shift_left</classname> &gt;</type>
</typedef>
<typedef name="make_shift_right">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::shift_right</classname> &gt;</type>
</typedef>
<typedef name="make_multiplies">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::multiplies</classname> &gt;</type>
</typedef>
<typedef name="make_divides">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::divides</classname> &gt;</type>
</typedef>
<typedef name="make_modulus">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::modulus</classname> &gt;</type>
</typedef>
<typedef name="make_plus">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::plus</classname> &gt;</type>
</typedef>
<typedef name="make_minus">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::minus</classname> &gt;</type>
</typedef>
<typedef name="make_less">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::less</classname> &gt;</type>
</typedef>
<typedef name="make_greater">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::greater</classname> &gt;</type>
</typedef>
<typedef name="make_less_equal">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::less_equal</classname> &gt;</type>
</typedef>
<typedef name="make_greater_equal">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::greater_equal</classname> &gt;</type>
</typedef>
<typedef name="make_equal_to">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::equal_to</classname> &gt;</type>
</typedef>
<typedef name="make_not_equal_to">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::not_equal_to</classname> &gt;</type>
</typedef>
<typedef name="make_logical_or">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::logical_or</classname> &gt;</type>
</typedef>
<typedef name="make_logical_and">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::logical_and</classname> &gt;</type>
</typedef>
<typedef name="make_bitwise_and">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::bitwise_and</classname> &gt;</type>
</typedef>
<typedef name="make_bitwise_or">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::bitwise_or</classname> &gt;</type>
</typedef>
<typedef name="make_bitwise_xor">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::bitwise_xor</classname> &gt;</type>
</typedef>
<typedef name="make_comma">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::comma</classname> &gt;</type>
</typedef>
<typedef name="make_mem_ptr">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::mem_ptr</classname> &gt;</type>
</typedef>
<typedef name="make_assign">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::assign</classname> &gt;</type>
</typedef>
<typedef name="make_shift_left_assign">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::shift_left_assign</classname> &gt;</type>
</typedef>
<typedef name="make_shift_right_assign">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::shift_right_assign</classname> &gt;</type>
</typedef>
<typedef name="make_multiplies_assign">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::multiplies_assign</classname> &gt;</type>
</typedef>
<typedef name="make_divides_assign">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::divides_assign</classname> &gt;</type>
</typedef>
<typedef name="make_modulus_assign">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::modulus_assign</classname> &gt;</type>
</typedef>
<typedef name="make_plus_assign">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::plus_assign</classname> &gt;</type>
</typedef>
<typedef name="make_minus_assign">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::minus_assign</classname> &gt;</type>
</typedef>
<typedef name="make_bitwise_and_assign">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::bitwise_and_assign</classname> &gt;</type>
</typedef>
<typedef name="make_bitwise_or_assign">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::bitwise_or_assign</classname> &gt;</type>
</typedef>
<typedef name="make_bitwise_xor_assign">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::bitwise_xor_assign</classname> &gt;</type>
</typedef>
<typedef name="make_subscript">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::subscript</classname> &gt;</type>
</typedef>
<typedef name="make_if_else">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::if_else_</classname> &gt;</type>
</typedef>
<typedef name="make_function">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::function</classname> &gt;</type>
</typedef>
</namespace>
<typedef name="_flatten">
<type><classname>proto::functional::flatten</classname></type>
</typedef>
<typedef name="_make_pair">
<type><classname>proto::functional::make_pair</classname></type>
</typedef>
<typedef name="_first">
<type><classname>proto::functional::first</classname></type>
</typedef>
<typedef name="_second">
<type><classname>proto::functional::second</classname></type>
</typedef>
<typedef name="_pop_back">
<type><classname>proto::functional::pop_back</classname></type>
</typedef>
<typedef name="_pop_front">
<type><classname>proto::functional::pop_front</classname></type>
</typedef>
<typedef name="_push_back">
<type><classname>proto::functional::push_back</classname></type>
</typedef>
<typedef name="_push_front">
<type><classname>proto::functional::push_front</classname></type>
</typedef>
<typedef name="_reverse">
<type><classname>proto::functional::reverse</classname></type>
</typedef>
<typedef name="_eval">
<type><classname>proto::functional::eval</classname></type>
</typedef>
<typedef name="_deep_copy">
<type><classname>proto::functional::deep_copy</classname></type>
</typedef>
<typedef name="_make_terminal">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::terminal</classname> &gt;</type>
</typedef>
<typedef name="_make_unary_plus">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::unary_plus</classname> &gt;</type>
</typedef>
<typedef name="_make_negate">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::negate</classname> &gt;</type>
</typedef>
<typedef name="_make_dereference">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::dereference</classname> &gt;</type>
</typedef>
<typedef name="_make_complement">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::complement</classname> &gt;</type>
</typedef>
<typedef name="_make_address_of">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::address_of</classname> &gt;</type>
</typedef>
<typedef name="_make_logical_not">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::logical_not</classname> &gt;</type>
</typedef>
<typedef name="_make_pre_inc">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::pre_inc</classname> &gt;</type>
</typedef>
<typedef name="_make_pre_dec">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::pre_dec</classname> &gt;</type>
</typedef>
<typedef name="_make_post_inc">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::post_inc</classname> &gt;</type>
</typedef>
<typedef name="_make_post_dec">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::post_dec</classname> &gt;</type>
</typedef>
<typedef name="_make_shift_left">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::shift_left</classname> &gt;</type>
</typedef>
<typedef name="_make_shift_right">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::shift_right</classname> &gt;</type>
</typedef>
<typedef name="_make_multiplies">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::multiplies</classname> &gt;</type>
</typedef>
<typedef name="_make_divides">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::divides</classname> &gt;</type>
</typedef>
<typedef name="_make_modulus">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::modulus</classname> &gt;</type>
</typedef>
<typedef name="_make_plus">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::plus</classname> &gt;</type>
</typedef>
<typedef name="_make_minus">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::minus</classname> &gt;</type>
</typedef>
<typedef name="_make_less">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::less</classname> &gt;</type>
</typedef>
<typedef name="_make_greater">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::greater</classname> &gt;</type>
</typedef>
<typedef name="_make_less_equal">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::less_equal</classname> &gt;</type>
</typedef>
<typedef name="_make_greater_equal">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::greater_equal</classname> &gt;</type>
</typedef>
<typedef name="_make_equal_to">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::equal_to</classname> &gt;</type>
</typedef>
<typedef name="_make_not_equal_to">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::not_equal_to</classname> &gt;</type>
</typedef>
<typedef name="_make_logical_or">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::logical_or</classname> &gt;</type>
</typedef>
<typedef name="_make_logical_and">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::logical_and</classname> &gt;</type>
</typedef>
<typedef name="_make_bitwise_and">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::bitwise_and</classname> &gt;</type>
</typedef>
<typedef name="_make_bitwise_or">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::bitwise_or</classname> &gt;</type>
</typedef>
<typedef name="_make_bitwise_xor">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::bitwise_xor</classname> &gt;</type>
</typedef>
<typedef name="_make_comma">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::comma</classname> &gt;</type>
</typedef>
<typedef name="_make_mem_ptr">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::mem_ptr</classname> &gt;</type>
</typedef>
<typedef name="_make_assign">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::assign</classname> &gt;</type>
</typedef>
<typedef name="_make_shift_left_assign">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::shift_left_assign</classname> &gt;</type>
</typedef>
<typedef name="_make_shift_right_assign">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::shift_right_assign</classname> &gt;</type>
</typedef>
<typedef name="_make_multiplies_assign">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::multiplies_assign</classname> &gt;</type>
</typedef>
<typedef name="_make_divides_assign">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::divides_assign</classname> &gt;</type>
</typedef>
<typedef name="_make_modulus_assign">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::modulus_assign</classname> &gt;</type>
</typedef>
<typedef name="_make_plus_assign">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::plus_assign</classname> &gt;</type>
</typedef>
<typedef name="_make_minus_assign">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::minus_assign</classname> &gt;</type>
</typedef>
<typedef name="_make_bitwise_and_assign">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::bitwise_and_assign</classname> &gt;</type>
</typedef>
<typedef name="_make_bitwise_or_assign">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::bitwise_or_assign</classname> &gt;</type>
</typedef>
<typedef name="_make_bitwise_xor_assign">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::bitwise_xor_assign</classname> &gt;</type>
</typedef>
<typedef name="_make_subscript">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::subscript</classname> &gt;</type>
</typedef>
<typedef name="_make_if_else">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::if_else_</classname> &gt;</type>
</typedef>
<typedef name="_make_function">
<type><classname>proto::functional::make_expr</classname>&lt; <classname>proto::tag::function</classname> &gt;</type>
</typedef>
<typedef name="_childN">
<purpose>For each <replaceable>N</replaceable> in <computeroutput>[0,BOOST_PROTO_MAX_ARITY)</computeroutput></purpose>
<type><classname>proto::_child_c</classname>&lt; <replaceable>N</replaceable> &gt;</type>
</typedef>
<typedef name="_child">
<type><classname alt="proto::_childN">proto::_child0</classname></type>
</typedef>
<typedef name="_left">
<type><classname alt="proto::_childN">proto::_child0</classname></type>
</typedef>
<typedef name="_right">
<type><classname alt="proto::_childN">proto::_child1</classname></type>
</typedef>
</namespace>
</namespace>
<macro name="BOOST_PROTO_MAX_ARITY">
<purpose>Controls the maximum number of child nodes an expression may have.</purpose>
<description>
<para>
<computeroutput>BOOST_PROTO_MAX_ARITY</computeroutput> defaults to 10. It may be set higher or lower, but not
lower than 3. Setting it higher will have a negative effect on compile times.
</para>
<para>
See also <computeroutput><macroname>BOOST_PROTO_MAX_FUNCTION_CALL_ARITY</macroname></computeroutput>.
</para>
</description>
</macro>
<macro name="BOOST_PROTO_MAX_LOGICAL_ARITY">
<purpose>Controls the maximum number of sub-grammars that
<computeroutput>
<classname alt="boost::proto::or_">proto::or_&lt;&gt;</classname>
</computeroutput> and
<computeroutput>
<classname alt="boost::proto::and_">proto::and_&lt;&gt;</classname>
</computeroutput> accept.</purpose>
<description>
<para>
<computeroutput>BOOST_PROTO_MAX_LOGICAL_ARITY</computeroutput> defaults to 10. It may be set higher or lower. Setting
it higher will have a negative effect on compile times.
</para>
</description>
</macro>
<macro name="BOOST_PROTO_MAX_FUNCTION_CALL_ARITY">
<purpose>Controls the maximum number of arguments that <computeroutput>operator()</computeroutput> overloads
accept.</purpose>
<description>
<para>
When setting
<computeroutput>
<macroname>BOOST_PROTO_MAX_ARITY</macroname>
</computeroutput> higher than the default, compile times
slow down considerably. That is due in large part to the explosion in the number of
<computeroutput>operator()</computeroutput> overloads that must be generated for each
Proto expression type. By setting <computeroutput>BOOST_PROTO_MAX_FUNCTION_CALL_ARITY</computeroutput>
lower than <computeroutput><macroname>BOOST_PROTO_MAX_ARITY</macroname></computeroutput>,
compile times can be sped up considerably.
</para>
</description>
</macro>
</header>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/proto_typeof.hpp">
<para>Boost.Typeof registrations for Proto's types, and definition of the
<computeroutput><macroname>BOOST_PROTO_AUTO</macroname>()</computeroutput> macro.</para>
<macro name="BOOST_PROTO_AUTO" kind="functionlike">
<macro-parameter name="Var"/>
<macro-parameter name="Expr"/>
<purpose>For defining a local variable that stores a Proto expression template,
deep-copying the expression so there are no dangling references.</purpose>
<description>
<para>
To define a local variable <computeroutput>ex</computeroutput> that stores the expression
<computeroutput><functionname alt="boost::proto::lit">proto::lit</functionname>(1) + 2</computeroutput>,
do the following:<programlisting>BOOST_PROTO_AUTO( ex, <functionname alt="boost::proto::lit">proto::lit</functionname>(1) + 2 );</programlisting>.
The above is equivalent to the following:
<programlisting>BOOST_AUTO( ex, <functionname alt="boost::proto::deep_copy">proto::deep_copy</functionname>( <functionname alt="boost::proto::lit">proto::lit</functionname>(1) + 2 ) );</programlisting>
</para>
</description>
</macro>
</header>

View File

@@ -0,0 +1,518 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/repeat.hpp">
<para>
Contains macros to ease the generation of repetitious code constructs.
</para>
<macro name="BOOST_PROTO_REPEAT" kind="functionlike">
<macro-parameter name="MACRO"/>
<purpose>Repeatedly invoke the specified macro.</purpose>
<description>
<para>
<computeroutput>BOOST_PROTO_REPEAT()</computeroutput> is used to generate the kind of repetitive
code that is typical of EDSLs built with Proto.
<computeroutput>BOOST_PROTO_REPEAT(<replaceable>MACRO</replaceable>)</computeroutput>
is equivalent to:
</para>
<para>
<programlisting><replaceable>MACRO</replaceable>(1, <macroname>BOOST_PROTO_typename_A</macroname>, <macroname>BOOST_PROTO_A_const_ref</macroname>, <macroname>BOOST_PROTO_A_const_ref_a</macroname>, <macroname>BOOST_PROTO_ref_a</macroname>)
<replaceable>MACRO</replaceable>(2, <macroname>BOOST_PROTO_typename_A</macroname>, <macroname>BOOST_PROTO_A_const_ref</macroname>, <macroname>BOOST_PROTO_A_const_ref_a</macroname>, <macroname>BOOST_PROTO_ref_a</macroname>)
...
<replaceable>MACRO</replaceable>(<macroname>BOOST_PROTO_MAX_ARITY</macroname>, <macroname>BOOST_PROTO_typename_A</macroname>, <macroname>BOOST_PROTO_A_const_ref</macroname>, <macroname>BOOST_PROTO_A_const_ref_a</macroname>, <macroname>BOOST_PROTO_ref_a</macroname>)</programlisting>
</para>
<para>
<emphasis role="bold">Example:</emphasis>
</para>
<para>
See <computeroutput><macroname>BOOST_PROTO_REPEAT_FROM_TO</macroname>()</computeroutput>.
</para>
</description>
</macro>
<macro name="BOOST_PROTO_REPEAT_FROM_TO" kind="functionlike">
<macro-parameter name="FROM"/>
<macro-parameter name="TO"/>
<macro-parameter name="MACRO"/>
<purpose>Repeatedly invoke the specified macro.</purpose>
<description>
<para>
<computeroutput>BOOST_PROTO_REPEAT_FROM_TO()</computeroutput> is used to generate the kind of repetitive
code that is typical of EDSLs built with Proto.
<computeroutput>BOOST_PROTO_REPEAT_FROM_TO(<replaceable>FROM</replaceable>, <replaceable>TO</replaceable>, <replaceable>MACRO</replaceable>)</computeroutput>
is equivalent to:
</para>
<para>
<programlisting><replaceable>MACRO</replaceable>(<replaceable>FROM</replaceable>, <macroname>BOOST_PROTO_typename_A</macroname>, <macroname>BOOST_PROTO_A_const_ref</macroname>, <macroname>BOOST_PROTO_A_const_ref_a</macroname>, <macroname>BOOST_PROTO_ref_a</macroname>)
<replaceable>MACRO</replaceable>(<replaceable>FROM+1</replaceable>, <macroname>BOOST_PROTO_typename_A</macroname>, <macroname>BOOST_PROTO_A_const_ref</macroname>, <macroname>BOOST_PROTO_A_const_ref_a</macroname>, <macroname>BOOST_PROTO_ref_a</macroname>)
...
<replaceable>MACRO</replaceable>(<replaceable>TO-1</replaceable>, <macroname>BOOST_PROTO_typename_A</macroname>, <macroname>BOOST_PROTO_A_const_ref</macroname>, <macroname>BOOST_PROTO_A_const_ref_a</macroname>, <macroname>BOOST_PROTO_ref_a</macroname>)</programlisting>
</para>
<para>
<emphasis role="bold">Example:</emphasis>
</para>
<para>
<programlisting>// Generate BOOST_PROTO_MAX_ARITY-1 overloads of the
// following construct() function template.
#define M0(N, typename_A, A_const_ref, A_const_ref_a, ref_a) \
template&lt;typename T, typename_A(N)&gt; \
typename <classname alt="boost::proto::result_of::make_expr">proto::result_of::make_expr</classname>&lt; \
<classname alt="boost::proto::tag::function">proto::tag::function</classname> \
, construct_helper&lt;T&gt; \
, A_const_ref(N) \
>::type const \
construct(A_const_ref_a(N)) \
{ \
return <functionname alt="boost::proto::make_expr">proto::make_expr</functionname>&lt; \
<classname alt="boost::proto::tag::function">proto::tag::function</classname> \
&gt;( \
construct_helper&lt;T&gt;() \
, ref_a(N) \
); \
}
BOOST_PROTO_REPEAT_FROM_TO(1, BOOST_PROTO_MAX_ARITY, M0)
#undef M0</programlisting>
</para>
<para>
The above invocation of <computeroutput>BOOST_PROTO_REPEAT_FROM_TO()</computeroutput>
will generate the following code:
</para>
<para>
<programlisting>template&lt;typename T, typename A0&gt;
typename <classname alt="boost::proto::result_of::make_expr">proto::result_of::make_expr</classname>&lt;
<classname alt="boost::proto::tag::function">proto::tag::function</classname>
, construct_helper&lt;T&gt;
, A0 const &amp;
&gt;::type const
construct(A0 const &amp; a0)
{
return <functionname alt="boost::proto::make_expr">proto::make_expr</functionname>&lt;
<classname alt="boost::proto::tag::function">proto::tag::function</classname>
&gt;(
construct_helper&lt;T&gt;()
, boost::ref(a0)
);
}
template&lt;typename T, typename A0, typename A1&gt;
typename <classname alt="boost::proto::result_of::make_expr">proto::result_of::make_expr</classname>&lt;
<classname alt="boost::proto::tag::function">proto::tag::function</classname>
, construct_helper&lt;T&gt;
, A0 const &amp;
, A1 const &amp;
&gt;::type const
construct(A0 const &amp; a0, A1 const &amp; a1)
{
return <functionname alt="boost::proto::make_expr">proto::make_expr</functionname>&lt;
<classname alt="boost::proto::tag::function">proto::tag::function</classname>
&gt;(
construct_helper&lt;T&gt;()
, boost::ref(a0)
, boost::ref(a1)
);
}
// ... and so on, up to BOOST_PROTO_MAX_ARITY-1 arguments ...</programlisting>
</para>
</description>
</macro>
<macro name="BOOST_PROTO_REPEAT_EX" kind="functionlike">
<macro-parameter name="MACRO"/>
<macro-parameter name="typename_A"/>
<macro-parameter name="A"/>
<macro-parameter name="A_a"/>
<macro-parameter name="a"/>
<purpose>Repeatedly invoke the specified macro.</purpose>
<description>
<para>
<computeroutput>BOOST_PROTO_REPEAT_EX()</computeroutput> is used to generate the kind of repetitive
code that is typical of EDSLs built with Proto.
<computeroutput>BOOST_PROTO_REPEAT_EX(<replaceable>MACRO</replaceable>, <replaceable>typename_A</replaceable>, <replaceable>A</replaceable>, <replaceable>A_a</replaceable>, <replaceable>a</replaceable>)</computeroutput>
is equivalent to:
</para>
<para>
<programlisting><replaceable>MACRO</replaceable>(1, typename_A, A, A_a, a)
<replaceable>MACRO</replaceable>(2, typename_A, A, A_a, a)
...
<replaceable>MACRO</replaceable>(<macroname>BOOST_PROTO_MAX_ARITY</macroname>, typename_A, A, A_a, a)</programlisting>
</para>
<para>
<emphasis role="bold">Example:</emphasis>
</para>
<para>
See <computeroutput><macroname>BOOST_PROTO_REPEAT_FROM_TO</macroname>()</computeroutput>.
</para>
</description>
</macro>
<macro name="BOOST_PROTO_REPEAT_FROM_TO_EX" kind="functionlike">
<macro-parameter name="FROM"/>
<macro-parameter name="TO"/>
<macro-parameter name="MACRO"/>
<macro-parameter name="typename_A"/>
<macro-parameter name="A"/>
<macro-parameter name="A_a"/>
<macro-parameter name="a"/>
<purpose>Repeatedly invoke the specified macro.</purpose>
<description>
<para>
<computeroutput>BOOST_PROTO_REPEAT_FROM_TO_EX()</computeroutput> is used to generate the kind of repetitive
code that is typical of EDSLs built with Proto.
<computeroutput>BOOST_PROTO_REPEAT_FROM_TO_EX(<replaceable>FROM</replaceable>, <replaceable>TO</replaceable>, <replaceable>MACRO</replaceable>, <replaceable>typename_A</replaceable>, <replaceable>A</replaceable>, <replaceable>A_a</replaceable>, <replaceable>a</replaceable>)</computeroutput>
is equivalent to:
</para>
<para>
<programlisting><replaceable>MACRO</replaceable>(<replaceable>FROM</replaceable>, typename_A, A, A_a, a)
<replaceable>MACRO</replaceable>(<replaceable>FROM+1</replaceable>, typename_A, A, A_a, a)
...
<replaceable>MACRO</replaceable>(<replaceable>TO-1</replaceable>, typename_A, A, A_a, a)</programlisting>
</para>
<para>
<emphasis role="bold">Example:</emphasis>
</para>
<para>
See <computeroutput><macroname>BOOST_PROTO_REPEAT_FROM_TO</macroname>()</computeroutput>.
</para>
</description>
</macro>
<macro name="BOOST_PROTO_LOCAL_ITERATE" kind="functionlike">
<purpose>Vertical repetition of a user-supplied macro.</purpose>
<description>
<para>
<computeroutput>BOOST_PROTO_LOCAL_ITERATE()</computeroutput> is used generate the kind of repetitive code that is typical
of EDSLs built with Proto. This macro causes the user-defined macro <computeroutput>BOOST_PROTO_LOCAL_MACRO()</computeroutput> to
be expanded with values in the range specified by <computeroutput>BOOST_PROTO_LOCAL_LIMITS</computeroutput>.
</para>
<para>
<emphasis role="bold">Usage:</emphasis>
</para>
<para>
<programlisting>#include BOOST_PROTO_LOCAL_ITERATE()</programlisting>
</para>
<para>
<emphasis role="bold">Example:</emphasis>
</para>
<para>
<programlisting>// Generate BOOST_PROTO_MAX_ARITY-1 overloads of the
// following construct() function template.
#define BOOST_PROTO_LOCAL_MACRO(N, typename_A, A_const_ref, A_const_ref_a, ref_a)\
template&lt;typename T, typename_A(N)&gt; \
typename <classname alt="boost::proto::result_of::make_expr">proto::result_of::make_expr</classname>&lt; \
<classname alt="boost::proto::tag::function">proto::tag::function</classname> \
, construct_helper&lt;T&gt; \
, A_const_ref(N) \
>::type const \
construct(A_const_ref_a(N)) \
{ \
return <functionname alt="boost::proto::make_expr">proto::make_expr</functionname>&lt; \
<classname alt="boost::proto::tag::function">proto::tag::function</classname> \
&gt;( \
construct_helper&lt;T&gt;() \
, ref_a(N) \
); \
}
#define BOOST_PROTO_LOCAL_LIMITS (1, BOOST_PP_DEC(BOOST_PROTO_MAX_ARITY))
#include BOOST_PROTO_LOCAL_ITERATE()</programlisting>
</para>
<para>
The above inclusion of <computeroutput>BOOST_PROTO_LOCAL_ITERATE()</computeroutput>
will generate the following code:
</para>
<para>
<programlisting>template&lt;typename T, typename A0&gt;
typename <classname alt="boost::proto::result_of::make_expr">proto::result_of::make_expr</classname>&lt;
<classname alt="boost::proto::tag::function">proto::tag::function</classname>
, construct_helper&lt;T&gt;
, A0 const &amp;
&gt;::type const
construct(A0 const &amp; a0)
{
return <functionname alt="boost::proto::make_expr">proto::make_expr</functionname>&lt;
<classname alt="boost::proto::tag::function">proto::tag::function</classname>
&gt;(
construct_helper&lt;T&gt;()
, boost::ref(a0)
);
}
template&lt;typename T, typename A0, typename A1&gt;
typename <classname alt="boost::proto::result_of::make_expr">proto::result_of::make_expr</classname>&lt;
<classname alt="boost::proto::tag::function">proto::tag::function</classname>
, construct_helper&lt;T&gt;
, A0 const &amp;
, A1 const &amp;
&gt;::type const
construct(A0 const &amp; a0, A1 const &amp; a1)
{
return <functionname alt="boost::proto::make_expr">proto::make_expr</functionname>&lt;
<classname alt="boost::proto::tag::function">proto::tag::function</classname>
&gt;(
construct_helper&lt;T&gt;()
, boost::ref(a0)
, boost::ref(a1)
);
}
// ... and so on, up to BOOST_PROTO_MAX_ARITY-1 arguments ...</programlisting>
</para>
<para>
If <computeroutput>BOOST_PROTO_LOCAL_LIMITS</computeroutput> is not defined by the user, it defaults
to <computeroutput>(1, BOOST_PROTO_MAX_ARITY)</computeroutput>.
</para>
<para>
At each iteration, <computeroutput>BOOST_PROTO_LOCAL_MACRO()</computeroutput> is invoked with the current
iteration number and the following 4 macro parameters:
<itemizedlist>
<listitem><computeroutput>BOOST_PROTO_LOCAL_typename_A</computeroutput></listitem>
<listitem><computeroutput>BOOST_PROTO_LOCAL_A</computeroutput></listitem>
<listitem><computeroutput>BOOST_PROTO_LOCAL_A_a</computeroutput></listitem>
<listitem><computeroutput>BOOST_PROTO_LOCAL_a</computeroutput></listitem>
</itemizedlist>
If these macros are not defined by the user, they default respectively to:
<itemizedlist>
<listitem><computeroutput><macroname>BOOST_PROTO_typename_A</macroname></computeroutput></listitem>
<listitem><computeroutput><macroname>BOOST_PROTO_A_const_ref</macroname></computeroutput></listitem>
<listitem><computeroutput><macroname>BOOST_PROTO_A_const_ref_a</macroname></computeroutput></listitem>
<listitem><computeroutput><macroname>BOOST_PROTO_ref_a</macroname></computeroutput></listitem>
</itemizedlist>
</para>
<para>
After including <computeroutput>BOOST_PROTO_LOCAL_ITERATE()</computeroutput>, the
following macros are automatically undefined:
<itemizedlist>
<listitem><computeroutput>BOOST_PROTO_LOCAL_MACRO</computeroutput></listitem>
<listitem><computeroutput>BOOST_PROTO_LOCAL_LIMITS</computeroutput></listitem>
<listitem><computeroutput>BOOST_PROTO_LOCAL_typename_A</computeroutput></listitem>
<listitem><computeroutput>BOOST_PROTO_LOCAL_A</computeroutput></listitem>
<listitem><computeroutput>BOOST_PROTO_LOCAL_A_a</computeroutput></listitem>
<listitem><computeroutput>BOOST_PROTO_LOCAL_a</computeroutput></listitem>
</itemizedlist>
</para>
</description>
</macro>
<macro name="BOOST_PROTO_typename_A" kind="functionlike">
<macro-parameter name="N"/>
<purpose>
Generates sequences like
<computeroutput>
typename A<subscript>0</subscript>,
typename A<subscript>1</subscript>, …
typename A<subscript>N-1</subscript>
</computeroutput>.
</purpose>
<description>
<para>
Intended for use with the <computeroutput><macroname>BOOST_PROTO_REPEAT</macroname>()</computeroutput>
and <computeroutput><macroname>BOOST_PROTO_LOCAL_ITERATE</macroname>()</computeroutput> macros.
</para>
<para>
<computeroutput>BOOST_PROTO_typename_A(<replaceable>N</replaceable>)</computeroutput> generates sequences like:
</para>
<para>
<programlisting>typename A<subscript>0</subscript>, typename A<subscript>1</subscript>, … typename A<subscript>N-1</subscript></programlisting>
</para>
</description>
</macro>
<macro name="BOOST_PROTO_A_const_ref" kind="functionlike">
<macro-parameter name="N"/>
<purpose>
Generates sequences like
<computeroutput>
A<subscript>0</subscript> const &amp;,
A<subscript>1</subscript> const &amp;, …
A<subscript>N-1</subscript> const &amp;
</computeroutput>.
</purpose>
<description>
<para>
Intended for use with the <computeroutput><macroname>BOOST_PROTO_REPEAT</macroname>()</computeroutput>
and <computeroutput><macroname>BOOST_PROTO_LOCAL_ITERATE</macroname>()</computeroutput> macros.
</para>
<para>
<computeroutput>BOOST_PROTO_A_const_ref(<replaceable>N</replaceable>)</computeroutput> generates sequences like:
</para>
<para>
<programlisting>A<subscript>0</subscript> const &amp;, A<subscript>1</subscript> const &amp;, … A<subscript>N-1</subscript> const &amp;</programlisting>
</para>
</description>
</macro>
<macro name="BOOST_PROTO_A_ref" kind="functionlike">
<macro-parameter name="N"/>
<purpose>
Generates sequences like
<computeroutput>
A<subscript>0</subscript> &amp;,
A<subscript>1</subscript> &amp;, …
A<subscript>N-1</subscript> &amp;
</computeroutput>.
</purpose>
<description>
<para>
Intended for use with the <computeroutput><macroname>BOOST_PROTO_REPEAT</macroname>()</computeroutput>
and <computeroutput><macroname>BOOST_PROTO_LOCAL_ITERATE</macroname>()</computeroutput> macros.
</para>
<para>
<computeroutput>BOOST_PROTO_A_ref(<replaceable>N</replaceable>)</computeroutput> generates sequences like:
</para>
<para>
<programlisting>A<subscript>0</subscript> &amp;, A<subscript>1</subscript> &amp;, … A<subscript>N-1</subscript> &amp;</programlisting>
</para>
</description>
</macro>
<macro name="BOOST_PROTO_A" kind="functionlike">
<macro-parameter name="N"/>
<purpose>
Generates sequences like
<computeroutput>
A<subscript>0</subscript>,
A<subscript>1</subscript>, …
A<subscript>N-1</subscript>
</computeroutput>.
</purpose>
<description>
<para>
Intended for use with the <computeroutput><macroname>BOOST_PROTO_REPEAT</macroname>()</computeroutput>
and <computeroutput><macroname>BOOST_PROTO_LOCAL_ITERATE</macroname>()</computeroutput> macros.
</para>
<para>
<computeroutput>BOOST_PROTO_A(<replaceable>N</replaceable>)</computeroutput> generates sequences like:
</para>
<para>
<programlisting>A<subscript>0</subscript>, A<subscript>1</subscript>, … A<subscript>N-1</subscript></programlisting>
</para>
</description>
</macro>
<macro name="BOOST_PROTO_A_const" kind="functionlike">
<macro-parameter name="N"/>
<purpose>
Generates sequences like
<computeroutput>
A<subscript>0</subscript> const,
A<subscript>1</subscript> const, …
A<subscript>N-1</subscript> const
</computeroutput>.
</purpose>
<description>
<para>
Intended for use with the <computeroutput><macroname>BOOST_PROTO_REPEAT</macroname>()</computeroutput>
and <computeroutput><macroname>BOOST_PROTO_LOCAL_ITERATE</macroname>()</computeroutput> macros.
</para>
<para>
<computeroutput>BOOST_PROTO_A_const(<replaceable>N</replaceable>)</computeroutput> generates sequences like:
</para>
<para>
<programlisting>A<subscript>0</subscript> const, A<subscript>1</subscript> const, … A<subscript>N-1</subscript> const</programlisting>
</para>
</description>
</macro>
<macro name="BOOST_PROTO_A_const_ref_a" kind="functionlike">
<macro-parameter name="N"/>
<purpose>
Generates sequences like
<computeroutput>
A<subscript>0</subscript> const &amp; a<subscript>0</subscript>,
A<subscript>1</subscript> const &amp; a<subscript>1</subscript>, …
A<subscript>N-1</subscript> const &amp; a<subscript>N-1</subscript>
</computeroutput>.
</purpose>
<description>
<para>
Intended for use with the <computeroutput><macroname>BOOST_PROTO_REPEAT</macroname>()</computeroutput>
and <computeroutput><macroname>BOOST_PROTO_LOCAL_ITERATE</macroname>()</computeroutput> macros.
</para>
<para>
<computeroutput>BOOST_PROTO_A_const_ref_a(<replaceable>N</replaceable>)</computeroutput> generates sequences like:
</para>
<para>
<programlisting>A<subscript>0</subscript> const &amp; a<subscript>0</subscript>, A<subscript>1</subscript> const &amp; a<subscript>1</subscript>, … A<subscript>N-1</subscript> const &amp; a<subscript>N-1</subscript></programlisting>
</para>
</description>
</macro>
<macro name="BOOST_PROTO_A_ref_a" kind="functionlike">
<macro-parameter name="N"/>
<purpose>
Generates sequences like
<computeroutput>
A<subscript>0</subscript> &amp; a<subscript>0</subscript>,
A<subscript>1</subscript> &amp; a<subscript>1</subscript>, …
A<subscript>N-1</subscript> &amp; a<subscript>N-1</subscript>
</computeroutput>.
</purpose>
<description>
<para>
Intended for use with the <computeroutput><macroname>BOOST_PROTO_REPEAT</macroname>()</computeroutput>
and <computeroutput><macroname>BOOST_PROTO_LOCAL_ITERATE</macroname>()</computeroutput> macros.
</para>
<para>
<computeroutput>BOOST_PROTO_A_ref_a(<replaceable>N</replaceable>)</computeroutput> generates sequences like:
</para>
<para>
<programlisting>A<subscript>0</subscript> &amp; a<subscript>0</subscript>, A<subscript>1</subscript> &amp; a<subscript>1</subscript>, … A<subscript>N-1</subscript> &amp; a<subscript>N-1</subscript></programlisting>
</para>
</description>
</macro>
<macro name="BOOST_PROTO_ref_a" kind="functionlike">
<macro-parameter name="N"/>
<purpose>
Generates sequences like
<computeroutput>
boost::ref(a<subscript>0</subscript>),
boost::ref(a<subscript>1</subscript>), …
boost::ref(a<subscript>N-1</subscript>)
</computeroutput>.
</purpose>
<description>
<para>
Intended for use with the <computeroutput><macroname>BOOST_PROTO_REPEAT</macroname>()</computeroutput>
and <computeroutput><macroname>BOOST_PROTO_LOCAL_ITERATE</macroname>()</computeroutput> macros.
</para>
<para>
<computeroutput>BOOST_PROTO_ref_a(<replaceable>N</replaceable>)</computeroutput> generates sequences like:
</para>
<para>
<programlisting>boost::ref(a<subscript>0</subscript>), boost::ref(a<subscript>1</subscript>), … boost::ref(a<subscript>N-1</subscript>)</programlisting>
</para>
</description>
</macro>
<macro name="BOOST_PROTO_a" kind="functionlike">
<macro-parameter name="N"/>
<purpose>
Generates sequences like
<computeroutput>
a<subscript>0</subscript>,
a<subscript>1</subscript>, …
a<subscript>N-1</subscript>
</computeroutput>.
</purpose>
<description>
<para>
Intended for use with the <computeroutput><macroname>BOOST_PROTO_REPEAT</macroname>()</computeroutput>
and <computeroutput><macroname>BOOST_PROTO_LOCAL_ITERATE</macroname>()</computeroutput> macros.
</para>
<para>
<computeroutput>BOOST_PROTO_a(<replaceable>N</replaceable>)</computeroutput> generates sequences like:
</para>
<para>
<programlisting>a<subscript>0</subscript>, a<subscript>1</subscript>, … a<subscript>N-1</subscript></programlisting>
</para>
</description>
</macro>
</header>

View File

@@ -0,0 +1,152 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/tags.hpp">
<para>Contains the tags for all the overloadable operators in C++ </para>
<namespace name="boost">
<namespace name="proto">
<namespace name="tag">
<struct name="terminal">
<purpose>Tag type for terminals; aka, leaves in the expression tree. </purpose>
</struct>
<struct name="unary_plus">
<purpose>Tag type for the unary + operator. </purpose>
</struct>
<struct name="negate">
<purpose>Tag type for the unary - operator. </purpose>
</struct>
<struct name="dereference">
<purpose>Tag type for the unary * operator. </purpose>
</struct>
<struct name="complement">
<purpose>Tag type for the unary ~ operator. </purpose>
</struct>
<struct name="address_of">
<purpose>Tag type for the unary &amp; operator. </purpose>
</struct>
<struct name="logical_not">
<purpose>Tag type for the unary ! operator. </purpose>
</struct>
<struct name="pre_inc">
<purpose>Tag type for the unary prefix ++ operator. </purpose>
</struct>
<struct name="pre_dec">
<purpose>Tag type for the unary prefix -- operator. </purpose>
</struct>
<struct name="post_inc">
<purpose>Tag type for the unary postfix ++ operator. </purpose>
</struct>
<struct name="post_dec">
<purpose>Tag type for the unary postfix -- operator. </purpose>
</struct>
<struct name="shift_left">
<purpose>Tag type for the binary &lt;&lt; operator. </purpose>
</struct>
<struct name="shift_right">
<purpose>Tag type for the binary &gt;&gt; operator. </purpose>
</struct>
<struct name="multiplies">
<purpose>Tag type for the binary * operator. </purpose>
</struct>
<struct name="divides">
<purpose>Tag type for the binary / operator. </purpose>
</struct>
<struct name="modulus">
<purpose>Tag type for the binary % operator. </purpose>
</struct>
<struct name="plus">
<purpose>Tag type for the binary + operator. </purpose>
</struct>
<struct name="minus">
<purpose>Tag type for the binary - operator. </purpose>
</struct>
<struct name="less">
<purpose>Tag type for the binary &lt; operator. </purpose>
</struct>
<struct name="greater">
<purpose>Tag type for the binary &gt; operator. </purpose>
</struct>
<struct name="less_equal">
<purpose>Tag type for the binary &lt;= operator. </purpose>
</struct>
<struct name="greater_equal">
<purpose>Tag type for the binary &gt;= operator. </purpose>
</struct>
<struct name="equal_to">
<purpose>Tag type for the binary == operator. </purpose>
</struct>
<struct name="not_equal_to">
<purpose>Tag type for the binary != operator. </purpose>
</struct>
<struct name="logical_or">
<purpose>Tag type for the binary || operator. </purpose>
</struct>
<struct name="logical_and">
<purpose>Tag type for the binary &amp;&amp; operator. </purpose>
</struct>
<struct name="bitwise_and">
<purpose>Tag type for the binary &amp; operator. </purpose>
</struct>
<struct name="bitwise_or">
<purpose>Tag type for the binary | operator. </purpose>
</struct>
<struct name="bitwise_xor">
<purpose>Tag type for the binary ^ operator. </purpose>
</struct>
<struct name="comma">
<purpose>Tag type for the binary , operator. </purpose>
</struct>
<struct name="mem_ptr">
<purpose>Tag type for the binary -&gt;* operator. </purpose>
</struct>
<struct name="assign">
<purpose>Tag type for the binary = operator. </purpose>
</struct>
<struct name="shift_left_assign">
<purpose>Tag type for the binary &lt;&lt;= operator. </purpose>
</struct>
<struct name="shift_right_assign">
<purpose>Tag type for the binary &gt;&gt;= operator. </purpose>
</struct>
<struct name="multiplies_assign">
<purpose>Tag type for the binary *= operator. </purpose>
</struct>
<struct name="divides_assign">
<purpose>Tag type for the binary /= operator. </purpose>
</struct>
<struct name="modulus_assign">
<purpose>Tag type for the binary = operator. </purpose>
</struct>
<struct name="plus_assign">
<purpose>Tag type for the binary += operator. </purpose>
</struct>
<struct name="minus_assign">
<purpose>Tag type for the binary -= operator. </purpose>
</struct>
<struct name="bitwise_and_assign">
<purpose>Tag type for the binary &amp;= operator. </purpose>
</struct>
<struct name="bitwise_or_assign">
<purpose>Tag type for the binary |= operator. </purpose>
</struct>
<struct name="bitwise_xor_assign">
<purpose>Tag type for the binary ^= operator. </purpose>
</struct>
<struct name="subscript">
<purpose>Tag type for the binary subscript operator. </purpose>
</struct>
<struct name="if_else_">
<purpose>Tag type for the ternary ?: conditional operator. </purpose>
</struct>
<struct name="function">
<purpose>Tag type for the n-ary function call operator. </purpose>
</struct>
</namespace>
</namespace>
</namespace>
</header>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/transform.hpp">
<para>Includes all the built-in transforms of Proto.</para>
</header>

View File

@@ -0,0 +1,485 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/transform/arg.hpp">
<para>Contains definition of the childN transforms and friends.</para>
<namespace name="boost">
<namespace name="proto">
<struct name="_expr">
<inherit><classname>proto::transform</classname>&lt; _expr &gt;</inherit>
<purpose>A <conceptname>PrimitiveTransform</conceptname> that returns the current expression unmodified. </purpose>
<description>
<para>
Example:
<programlisting><classname>proto::terminal</classname>&lt;int&gt;::type i = {42};
<classname>proto::terminal</classname>&lt;int&gt;::type &amp; j = proto::_expr()(i);
assert( boost::addressof(i) == boost::addressof(j) );</programlisting>
</para>
</description>
<struct name="impl">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="State"/>
<template-type-parameter name="Data"/>
</template>
<inherit><classname>proto::transform_impl</classname>&lt; Expr, State, Data &gt;</inherit>
<typedef name="result_type">
<type>Expr</type>
</typedef>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>Expr</type>
<parameter name="expr">
<paramtype>typename impl::expr_param</paramtype>
<description>
<para>The current expression. </para>
</description>
</parameter>
<parameter name="">
<paramtype>typename impl::state_param</paramtype>
</parameter>
<parameter name="">
<paramtype>typename impl::data_param</paramtype>
</parameter>
<description>
<para>
Returns the current expression.
</para>
</description>
<returns>
<para>
<computeroutput>expr</computeroutput>
</para>
</returns>
<throws>
<simpara>Will not throw.</simpara>
</throws>
</method>
</method-group>
</struct>
</struct>
<struct name="_state">
<inherit><classname>proto::transform</classname>&lt; _state &gt;</inherit>
<purpose>A <conceptname>PrimitiveTransform</conceptname> that returns the current state unmodified. </purpose>
<description>
<para>
Example:
<programlisting><classname>proto::terminal</classname>&lt;int&gt;::type i = {42};
char ch = proto::_state()(i, 'a');
assert( ch == 'a' );</programlisting>
</para>
</description>
<struct name="impl">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="State"/>
<template-type-parameter name="Data"/>
</template>
<inherit><classname>proto::transform_impl</classname>&lt; Expr, State, Data &gt;</inherit>
<typedef name="result_type">
<type>State</type>
</typedef>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>State</type>
<parameter name="">
<paramtype>typename impl::expr_param</paramtype>
</parameter>
<parameter name="state">
<paramtype>typename impl::state_param</paramtype>
<description>
<para>The current state. </para>
</description>
</parameter>
<parameter name="">
<paramtype>typename impl::data_param</paramtype>
</parameter>
<description>
<para>
Returns the current state.
</para>
</description>
<returns>
<para>
<computeroutput>state</computeroutput>
</para>
</returns>
<throws>
<simpara>Will not throw.</simpara>
</throws>
</method>
</method-group>
</struct>
</struct>
<struct name="_data">
<inherit><classname>proto::transform</classname>&lt; _data &gt;</inherit>
<purpose>
A <conceptname>PrimitiveTransform</conceptname> that returns the current data unmodified.
If the data (third) parameter is a transform environment, it returns the value associated
with the <code><classname>proto::data_type</classname></code> key. Otherwise, it returns
the data parameter unmodified.
</purpose>
<description>
<para>
If the data (third) parameter is a transform environment, it returns the value associated
with the <code><classname>proto::data_type</classname></code> key. Otherwise, it returns
the data parameter unmodified.
</para>
<para>
<emphasis role="bold">Example:</emphasis>
<programlisting><classname>proto::terminal</classname>&lt;int&gt;::type i = {42};
std::string str("hello");
std::string &amp; d1 = proto::_data()(i, 'a', str);
assert( &amp;str == &amp;d1 );
std::string &amp; d2 = proto::_data()(i, 'a', (<globalname>proto::data</globalname> = boost::ref(str)));
assert( &amp;str == &amp;d2 );</programlisting>
</para>
</description>
<struct name="impl">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="State"/>
<template-type-parameter name="Data"/>
</template>
<inherit><type>
mpl::if_c&lt;
<classname>proto::is_env</classname>&lt;Data&gt;::value,
<classname>proto::_env_var</classname>&lt;<classname>proto::data_type</classname>&gt;,
<classname>proto::_env</classname>
&gt;::type::template impl&lt;Expr, State, Data&gt;</type></inherit>
</struct>
</struct>
<struct name="_child_c">
<template>
<template-nontype-parameter name="N">
<type>int</type>
</template-nontype-parameter>
</template>
<inherit><classname>proto::transform</classname>&lt; _child_c&lt;N&gt; &gt;</inherit>
<purpose>A <conceptname>PrimitiveTransform</conceptname> that returns N-th child of the current expression. </purpose>
<description>
<para>
Example:
<programlisting><classname>proto::terminal</classname>&lt;int&gt;::type i = {42};
<classname>proto::terminal</classname>&lt;int&gt;::type &amp; j = proto::_child_c&lt;0&gt;()(-i);
assert( boost::addressof(i) == boost::addressof(j) );</programlisting>
</para>
</description>
<struct name="impl">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="State"/>
<template-type-parameter name="Data"/>
</template>
<inherit><classname>proto::transform_impl</classname>&lt; Expr, State, Data &gt;</inherit>
<typedef name="result_type">
<type>typename <classname>proto::result_of::child_c</classname>&lt; Expr, N &gt;::type</type>
</typedef>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>typename <classname>proto::result_of::child_c</classname>&lt; Expr, N &gt;::type</type>
<parameter name="expr">
<paramtype>typename impl::expr_param</paramtype>
<description>
<para>The current expression. </para>
</description>
</parameter>
<parameter name="">
<paramtype>typename impl::state_param</paramtype>
</parameter>
<parameter name="">
<paramtype>typename impl::data_param</paramtype>
</parameter>
<description>
<para>
Returns the N-th child of <computeroutput>expr</computeroutput>
</para>
</description>
<requires>
<para>
<computeroutput>Expr::proto_arity::value &gt; N</computeroutput>
</para>
</requires>
<returns>
<para>
<computeroutput><functionname>proto::child_c</functionname>&lt;N&gt;(expr)</computeroutput>
</para>
</returns>
<throws>
<simpara>Will not throw.</simpara>
</throws>
</method>
</method-group>
</struct>
</struct>
<struct name="_value">
<inherit><classname>proto::transform</classname>&lt; _value &gt;</inherit>
<purpose>A <conceptname>PrimitiveTransform</conceptname> that returns the value of the current terminal expression. </purpose>
<description>
<para>
Example:
<programlisting><classname>proto::terminal</classname>&lt;int&gt;::type i = {42};
int j = proto::_value()(i);
assert( 42 == j );</programlisting>
</para>
</description>
<struct name="impl">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="State"/>
<template-type-parameter name="Data"/>
</template>
<inherit><classname>proto::transform_impl</classname>&lt; Expr, State, Data &gt;</inherit>
<typedef name="result_type">
<type>typename <classname>proto::result_of::value</classname>&lt; Expr &gt;::type</type>
</typedef>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>typename <classname>proto::result_of::value</classname>&lt; Expr &gt;::type</type>
<parameter name="expr">
<paramtype>typename impl::expr_param</paramtype>
<description>
<para>The current expression. </para>
</description>
</parameter>
<parameter name="">
<paramtype>typename impl::state_param</paramtype>
</parameter>
<parameter name="">
<paramtype>typename impl::data_param</paramtype>
</parameter>
<description>
<para>
Returns the value of the specified terminal expression.
</para>
</description>
<requires>
<para>
<computeroutput>Expr::proto_arity::value == 0</computeroutput>.
</para>
</requires>
<returns>
<para>
<computeroutput><functionname>proto::value</functionname>(expr)</computeroutput>
</para>
</returns>
<throws>
<simpara>Will not throw.</simpara>
</throws>
</method>
</method-group>
</struct>
</struct>
<struct name="_void">
<inherit><classname>proto::transform</classname>&lt; _void &gt;</inherit>
<purpose>A <conceptname>PrimitiveTransform</conceptname> that does nothing and returns void. </purpose>
<struct name="impl">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="State"/>
<template-type-parameter name="Data"/>
</template>
<inherit><classname>proto::transform_impl</classname>&lt; Expr, State, Data &gt;</inherit>
<typedef name="result_type">
<type>void</type>
</typedef>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>void</type>
<parameter name="">
<paramtype>typename impl::expr_param</paramtype>
</parameter>
<parameter name="">
<paramtype>typename impl::state_param</paramtype>
</parameter>
<parameter name="">
<paramtype>typename impl::data_param</paramtype>
</parameter>
<description>
<para>
Does nothing.
</para>
</description>
<throws>
<simpara>Will not throw.</simpara>
</throws>
</method>
</method-group>
</struct>
</struct>
<struct name="_byref">
<inherit><classname>proto::callable</classname></inherit>
<purpose>A unary callable <conceptname>PolymorphicFunctionObject</conceptname> that wraps its argument
in a <computeroutput>boost::reference_wrapper&lt;&gt;</computeroutput>.</purpose>
<description>
<para>
Example:
<programlisting><classname>proto::terminal</classname>&lt;int&gt;::type i = {42};
boost::reference_wrapper&lt;<classname>proto::terminal</classname>&lt;int&gt;::type&gt; j
= <classname>proto::when</classname>&lt;<classname>proto::_</classname>, proto::_byref(_)&gt;()(i);
assert( boost::addressof(i) == boost::addressof(j.get()) );</programlisting>
</para>
</description>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="T"/>
</template>
<specialization>
<template-arg>This(T &amp;)</template-arg>
</specialization>
<typedef name="type">
<type>boost::reference_wrapper&lt; T &gt; const</type>
</typedef>
</struct-specialization>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="T"/>
</template>
<specialization>
<template-arg>This(T)</template-arg>
</specialization>
<typedef name="type">
<type>boost::reference_wrapper&lt; T const &gt; const</type>
</typedef>
</struct-specialization>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>boost::reference_wrapper&lt; T &gt; const</type>
<template>
<template-type-parameter name="T"/>
</template>
<parameter name="t">
<paramtype>T &amp;</paramtype>
<description>
<para>The object to wrap </para>
</description>
</parameter>
<description>
<para>
Wrap the parameter <computeroutput>t</computeroutput> in a
<computeroutput>boost::reference_wrapper&lt;&gt;</computeroutput>
</para>
</description>
<returns>
<para>
<computeroutput>boost::ref(t)</computeroutput>
</para>
</returns>
<throws>
<simpara>Will not throw.</simpara>
</throws>
</method>
<method name="operator()" cv="const">
<type>boost::reference_wrapper&lt; T const &gt; const</type>
<template>
<template-type-parameter name="T"/>
</template>
<parameter name="t">
<paramtype>T const &amp;</paramtype>
</parameter>
<description>
<para>This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts. </para>
</description>
</method>
</method-group>
</struct>
<struct name="_byval">
<inherit><classname>proto::callable</classname></inherit>
<purpose>
A unary callable <conceptname>PolymorphicFunctionObject</conceptname> that strips references and
<computeroutput>boost::reference_wrapper&lt;&gt;</computeroutput> from its argument.
</purpose>
<description>
<para>
Example:
<programlisting><classname>proto::terminal</classname>&lt;int&gt;::type i = {42};
int j = 67;
int k = <classname>proto::when</classname>&lt;<classname>proto::_</classname>, proto::_byval(<classname>proto::_state</classname>)&gt;()(i, boost::ref(j));
assert( 67 == k );</programlisting>
</para>
</description>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="T"/>
</template>
<specialization>
<template-arg>This(boost::reference_wrapper&lt; T &gt;)</template-arg>
</specialization>
<inherit>result&lt;This(T)&gt;</inherit>
</struct-specialization>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="T"/>
</template>
<specialization>
<template-arg>This(T &amp;)</template-arg>
</specialization>
<inherit>result&lt;This(T)&gt;</inherit>
</struct-specialization>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="T"/>
</template>
<specialization>
<template-arg>This(T)</template-arg>
</specialization>
<typedef name="type">
<type>T</type>
</typedef>
</struct-specialization>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>T</type>
<template>
<template-type-parameter name="T"/>
</template>
<parameter name="t">
<paramtype>T const &amp;</paramtype>
<description>
<para>The object to unref </para>
</description>
</parameter>
<returns>
<para>
<computeroutput>t</computeroutput>
</para>
</returns>
<throws>
<simpara>Will not throw.</simpara>
</throws>
</method>
<method name="operator()" cv="const">
<type>T</type>
<template>
<template-type-parameter name="T"/>
</template>
<parameter name="t">
<paramtype>boost::reference_wrapper&lt; T &gt; const &amp;</paramtype>
</parameter>
<description>
<para>This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts. </para>
</description>
</method>
</method-group>
</struct>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,231 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/transform/call.hpp">
<para>Contains definition of the call&lt;&gt; transform. </para>
<namespace name="boost">
<namespace name="proto">
<struct name="call">
<template>
<template-type-parameter name="T"/>
</template>
<purpose>Make the given <conceptname>CallableTransform</conceptname> into a <conceptname>PrimitiveTransform</conceptname>.</purpose>
<description>
<para>
The purpose of <computeroutput>proto::call&lt;&gt;</computeroutput> is to annotate a transform as callable
so that <computeroutput><classname alt="proto::when">proto::when&lt;&gt;</classname></computeroutput> knows
how to apply it. The template parameter must be either a <conceptname>PrimitiveTransform</conceptname> or a
<conceptname>CallableTransform</conceptname>; that is, a function type for which the return type is a callable
<conceptname>PolymorphicFunctionObject</conceptname>.
</para>
<para>
For the complete description of the behavior of the <computeroutput>proto::call&lt;&gt;</computeroutput>
transform, see the documentation for the nested
<computeroutput>
<classname alt="proto::call::impl">proto::call::impl&lt;&gt;</classname>
</computeroutput>
class template.
</para>
</description>
<inherit><type><classname>proto::transform</classname>&lt; call&lt;T&gt; &gt;</type></inherit>
<struct name="impl">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="State"/>
<template-type-parameter name="Data"/>
</template>
<inherit><type><classname>proto::transform_impl</classname>&lt;Expr, State, Data&gt;</type></inherit>
<typedef name="result_type">
<type><replaceable>see-below</replaceable></type>
<description>
<para>
In the description that follows, a type <computeroutput>T</computeroutput> is determined to model the
<conceptname>PrimitiveTransform</conceptname> concept if
<computeroutput><classname>proto::is_transform</classname>&lt;T&gt;::value</computeroutput> is
<computeroutput>true</computeroutput>.
</para>
<para>
<computeroutput><classname>proto::call</classname>&lt;T&gt;::impl&lt;Expr,State,Data&gt;::result_type</computeroutput>
is computed as follows:
<itemizedlist>
<listitem>
<para>
If <computeroutput>T</computeroutput> if of the form
<computeroutput><conceptname>PrimitiveTransform</conceptname></computeroutput> or
<computeroutput><conceptname>PrimitiveTransform</conceptname>()</computeroutput>, then
<computeroutput>result_type</computeroutput> is:
<programlisting>typename boost::result_of&lt;PrimitiveTransform(Expr, State, Data)&gt;::type</programlisting>
</para>
</listitem>
<listitem>
<para>
If <computeroutput>T</computeroutput> is of the form
<computeroutput><conceptname>PrimitiveTransform</conceptname>(A<subscript>0</subscript>)</computeroutput>, then
<computeroutput>result_type</computeroutput> is:
<programlisting>typename boost::result_of&lt;PrimitiveTransform(
typename boost::result_of&lt;<classname>when</classname>&lt;<classname>_</classname>,A<subscript>0</subscript>&gt;(Expr, State, Data)&gt;::type,
State,
Data
)&gt;::type</programlisting>
</para>
</listitem>
<listitem>
<para>
If <computeroutput>T</computeroutput> is of the form
<computeroutput><conceptname>PrimitiveTransform</conceptname>(A<subscript>0</subscript>, A<subscript>1</subscript>)</computeroutput>, then
<computeroutput>result_type</computeroutput> is:
<programlisting>typename boost::result_of&lt;PrimitiveTransform(
typename boost::result_of&lt;<classname>when</classname>&lt;<classname>_</classname>,A<subscript>0</subscript>&gt;(Expr, State, Data)&gt;::type,
typename boost::result_of&lt;<classname>when</classname>&lt;<classname>_</classname>,A<subscript>1</subscript>&gt;(Expr, State, Data)&gt;::type,
Data
)&gt;::type</programlisting>
</para>
</listitem>
<listitem>
<para>
If <computeroutput>T</computeroutput> is of the form
<computeroutput><conceptname>PrimitiveTransform</conceptname>(A<subscript>0</subscript>, A<subscript>1</subscript>, A<subscript>2</subscript>)</computeroutput>, then
<computeroutput>result_type</computeroutput> is:
<programlisting>typename boost::result_of&lt;PrimitiveTransform(
typename boost::result_of&lt;<classname>when</classname>&lt;<classname>_</classname>,A<subscript>0</subscript>&gt;(Expr, State, Data)&gt;::type,
typename boost::result_of&lt;<classname>when</classname>&lt;<classname>_</classname>,A<subscript>1</subscript>&gt;(Expr, State, Data)&gt;::type,
typename boost::result_of&lt;<classname>when</classname>&lt;<classname>_</classname>,A<subscript>2</subscript>&gt;(Expr, State, Data)&gt;::type
)&gt;::type</programlisting>
</para>
</listitem>
<listitem>
<para>
If <computeroutput>T</computeroutput> is of the form
<computeroutput><conceptname>PolymorphicFunctionObject</conceptname>(A<subscript>0</subscript>,…A<subscript>n</subscript>)</computeroutput>, then
<computeroutput>result_type</computeroutput> is:
<programlisting>typename boost::result_of&lt;PolymorphicFunctionObject(
typename boost::result_of&lt;<classname>when</classname>&lt;<classname>_</classname>,A<subscript>0</subscript>&gt;(Expr, State, Data)&gt;::type,
typename boost::result_of&lt;<classname>when</classname>&lt;<classname>_</classname>,A<subscript>n</subscript>&gt;(Expr, State, Data)&gt;::type
&gt;::type</programlisting>
</para>
</listitem>
<listitem>
<para>
If <computeroutput>T</computeroutput> is of the form
<computeroutput><conceptname>PolymorphicFunctionObject</conceptname>(A<subscript>0</subscript>,…A<subscript>n</subscript> ...)</computeroutput>, then
let <computeroutput>T&apos;</computeroutput> be <computeroutput><conceptname>PolymorphicFunctionObject</conceptname>(A<subscript>0</subscript>,…A<subscript>n-1</subscript>, <replaceable>S</replaceable>)</computeroutput>,
where <replaceable>S</replaceable> is a type sequence computed from the unpacking expression <computeroutput>A<subscript>n</subscript></computeroutput>
as described in the reference for <computeroutput><classname>proto::pack</classname></computeroutput>.
Then, <computeroutput>result_type</computeroutput> is:
<programlisting><computeroutput>typename <classname>proto::call</classname>&lt;T&apos;&gt;::impl&lt;Expr,State,Data&gt;::result_type</computeroutput></programlisting>
</para>
</listitem>
</itemizedlist>
</para>
</description>
</typedef>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>result_type</type>
<parameter name="expr">
<paramtype>typename impl::expr_param</paramtype>
</parameter>
<parameter name="state">
<paramtype>typename impl::state_param</paramtype>
</parameter>
<parameter name="data">
<paramtype>typename impl::data_param</paramtype>
</parameter>
<description>
<para>
In the description that follows, a type <computeroutput>T</computeroutput> is determined to model the
<conceptname>PrimitiveTransform</conceptname> concept if
<computeroutput><classname>proto::is_transform</classname>&lt;T&gt;::value</computeroutput> is
<computeroutput>true</computeroutput>.
</para>
<para>
<computeroutput><classname>proto::call</classname>&lt;T&gt;::impl&lt;Expr,State,Data&gt;::operator()</computeroutput> behaves as follows:
<itemizedlist>
<listitem>
<para>
If <computeroutput>T</computeroutput> if of the form
<computeroutput><conceptname>PrimitiveTransform</conceptname></computeroutput> or
<computeroutput><conceptname>PrimitiveTransform</conceptname>()</computeroutput>, then
return
<programlisting>PrimitiveTransform()(expr, state, data)</programlisting>
</para>
</listitem>
<listitem>
<para>
If <computeroutput>T</computeroutput> is of the form
<computeroutput><conceptname>PrimitiveTransform</conceptname>(A<subscript>0</subscript>)</computeroutput>, then
return
<programlisting>PrimitiveTransform()(
<classname>when</classname>&lt;<classname>_</classname>,A<subscript>0</subscript>&gt;()(expr, state, data),
state,
sata
)</programlisting>
</para>
</listitem>
<listitem>
<para>
If <computeroutput>T</computeroutput> is of the form
<computeroutput><conceptname>PrimitiveTransform</conceptname>(A<subscript>0</subscript>, A<subscript>1</subscript>)</computeroutput>, then
return:
<programlisting>PrimitiveTransform()(
<classname>when</classname>&lt;<classname>_</classname>,A<subscript>0</subscript>&gt;()(expr, state, data),
<classname>when</classname>&lt;<classname>_</classname>,A<subscript>1</subscript>&gt;()(expr, state, data),
Data
)</programlisting>
</para>
</listitem>
<listitem>
<para>
If <computeroutput>T</computeroutput> is of the form
<computeroutput><conceptname>PrimitiveTransform</conceptname>(A<subscript>0</subscript>, A<subscript>1</subscript>, A<subscript>2</subscript>)</computeroutput>, then
return
<programlisting>PrimitiveTransform()(
<classname>when</classname>&lt;<classname>_</classname>,A<subscript>0</subscript>&gt;()(expr, state, data),
<classname>when</classname>&lt;<classname>_</classname>,A<subscript>1</subscript>&gt;()(expr, state, data),
<classname>when</classname>&lt;<classname>_</classname>,A<subscript>2</subscript>&gt;()(expr, state, data)
)</programlisting>
</para>
</listitem>
<listitem>
<para>
If <computeroutput>T</computeroutput> is of the form
<computeroutput><conceptname>PolymorphicFunctionObject</conceptname>(A<subscript>0</subscript>,…A<subscript>n</subscript>)</computeroutput>, then
return:
<programlisting>PolymorphicFunctionObject()(
<classname>when</classname>&lt;<classname>_</classname>,A<subscript>0</subscript>&gt;()(expr, state, data),
...
<classname>when</classname>&lt;<classname>_</classname>,A<subscript>n</subscript>&gt;()(expr, state, data)
)</programlisting>
</para>
</listitem>
<listitem>
<para>
If <computeroutput>T</computeroutput> is of the form
<computeroutput><conceptname>PolymorphicFunctionObject</conceptname>(A<subscript>0</subscript>,…A<subscript>n</subscript> ...)</computeroutput>, then
let <computeroutput>T&apos;</computeroutput> be <computeroutput><conceptname>PolymorphicFunctionObject</conceptname>(A<subscript>0</subscript>,…A<subscript>n-1</subscript>, <replaceable>S</replaceable>)</computeroutput>,
where <replaceable>S</replaceable> is a type sequence computed from the unpacking expression <computeroutput>A<subscript>n</subscript></computeroutput>
as described in the reference for <computeroutput><classname>proto::pack</classname></computeroutput>.
Then, return:
<programlisting><computeroutput><classname>proto::call</classname>&lt;T&apos;&gt;()(expr, state, data)</computeroutput></programlisting>
</para>
</listitem>
</itemizedlist>
</para>
</description>
</method>
</method-group>
</struct>
</struct>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,227 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/transform/default.hpp">
<namespace name="boost">
<namespace name="proto">
<struct name="_default">
<template>
<template-type-parameter name="Grammar">
<default><replaceable>unspecified</replaceable></default>
</template-type-parameter>
</template>
<inherit><classname>proto::transform</classname>&lt; _default&lt;Grammar&gt; &gt;</inherit>
<purpose>A <conceptname>PrimitiveTransform</conceptname> that gives expressions their
usual C++ behavior</purpose>
<description>
<para>
For the complete description of the behavior of the <computeroutput>proto::_default</computeroutput>
transform, see the documentation for the nested <computeroutput>
<classname>proto::_default::impl&lt;&gt;</classname>
</computeroutput> class template.
</para>
<para>
When used without specifying a <computeroutput>Grammar</computeroutput> parameter,
<computeroutput>proto::_default</computeroutput> behaves as if the parameter were
<computeroutput>proto::_default&lt;&gt;</computeroutput>.
</para>
</description>
<struct name="impl">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="State"/>
<template-type-parameter name="Data"/>
</template>
<inherit><type><classname>proto::transform_impl</classname>&lt;Expr, State, Data&gt;</type></inherit>
<typedef name="Tag">
<purpose>For exposition only</purpose>
<type>typename Expr::tag_type</type>
</typedef>
<data-member name="s_expr" specifiers="static">
<purpose>For exposition only</purpose>
<type>Expr</type>
</data-member>
<data-member name="s_state" specifiers="static">
<purpose>For exposition only</purpose>
<type>State</type>
</data-member>
<data-member name="s_data" specifiers="static">
<purpose>For exposition only</purpose>
<type>Data</type>
</data-member>
<typedef name="result_type">
<type><emphasis>see-below</emphasis></type>
<description>
<itemizedlist>
<listitem>
<para>
If <computeroutput>Tag</computeroutput> corresponds to a unary prefix operator,
then the result type is
<programlisting>decltype(
OP Grammar()(<functionname>proto::child</functionname>(s_expr), s_state, s_data)
)</programlisting>
</para>
</listitem>
<listitem>
<para>
If <computeroutput>Tag</computeroutput> corresponds to a unary postfix operator,
then the result type is
<programlisting>decltype(
Grammar()(<functionname>proto::child</functionname>(s_expr), s_state, s_data) OP
)</programlisting>
</para>
</listitem>
<listitem>
<para>
If <computeroutput>Tag</computeroutput> corresponds to a binary infix operator,
then the result type is
<programlisting>decltype(
Grammar()(<functionname>proto::left</functionname>(s_expr), s_state, s_data) OP
Grammar()(<functionname>proto::right</functionname>(s_expr), s_state, s_data)
)</programlisting>
</para>
</listitem>
<listitem>
<para>
If <computeroutput>Tag</computeroutput> is <computeroutput>
<classname>proto::tag::subscript</classname>
</computeroutput>,
then the result type is
<programlisting>decltype(
Grammar()(<functionname>proto::left</functionname>(s_expr), s_state, s_data) [
Grammar()(<functionname>proto::right</functionname>(s_expr), s_state, s_data) ]
)</programlisting>
</para>
</listitem>
<listitem>
<para>
If <computeroutput>Tag</computeroutput> is <computeroutput>
<classname>proto::tag::if_else_</classname>
</computeroutput>,
then the result type is
<programlisting>decltype(
Grammar()(<functionname>proto::child_c</functionname>&lt;0&gt;(s_expr), s_state, s_data) ?
Grammar()(<functionname>proto::child_c</functionname>&lt;1&gt;(s_expr), s_state, s_data) :
Grammar()(<functionname>proto::child_c</functionname>&lt;2&gt;(s_expr), s_state, s_data)
)</programlisting>
</para>
</listitem>
<listitem>
<para>
If <computeroutput>Tag</computeroutput> is <computeroutput>
<classname>proto::tag::function</classname>
</computeroutput>,
then the result type is
<programlisting>decltype(
Grammar()(<functionname>proto::child_c</functionname>&lt;0&gt;(s_expr), s_state, s_data) (
Grammar()(<functionname>proto::child_c</functionname>&lt;1&gt;(s_expr), s_state, s_data),
...
Grammar()(<functionname>proto::child_c</functionname>&lt;N&gt;(s_expr), s_state, s_data) )
)</programlisting>
</para>
</listitem>
</itemizedlist>
</description>
</typedef>
<description>
<para>
Let <computeroutput><computeroutput>OP</computeroutput></computeroutput> be the C++ operator
corresponding to <computeroutput>Expr::proto_tag</computeroutput>. (For example, if
<computeroutput>Tag</computeroutput> is <computeroutput>
<classname>proto::tag::plus</classname></computeroutput>, let <computeroutput>
<computeroutput>OP</computeroutput></computeroutput> be <computeroutput>+</computeroutput>.)
</para>
</description>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>result_type</type>
<parameter name="expr">
<paramtype>typename impl::expr_param</paramtype>
</parameter>
<parameter name="state">
<paramtype>typename impl::state_param</paramtype>
</parameter>
<parameter name="data">
<paramtype>typename impl::data_param</paramtype>
</parameter>
<description>
<computeroutput>
<classname>proto::_default</classname>&lt;Grammar&gt;::impl&lt;Expr, State, Data&gt;::operator()
</computeroutput> returns the following:
<itemizedlist>
<listitem>
<para>
If <computeroutput>Tag</computeroutput> corresponds to a unary prefix operator,
then return
<programlisting>OP Grammar()(<functionname>proto::child</functionname>(expr), state, data)</programlisting>
</para>
</listitem>
<listitem>
<para>
If <computeroutput>Tag</computeroutput> corresponds to a unary postfix operator,
then return
<programlisting>Grammar()(<functionname>proto::child</functionname>(expr), state, data) OP</programlisting>
</para>
</listitem>
<listitem>
<para>
If <computeroutput>Tag</computeroutput> corresponds to a binary infix operator,
then return
<programlisting>Grammar()(<functionname>proto::left</functionname>(expr), state, data) OP
Grammar()(<functionname>proto::right</functionname>(expr), state, data)</programlisting>
</para>
</listitem>
<listitem>
<para>
If <computeroutput>Tag</computeroutput> is <computeroutput>
<classname>proto::tag::subscript</classname>
</computeroutput>,
then return
<programlisting>Grammar()(<functionname>proto::left</functionname>(expr), state, data) [
Grammar()(<functionname>proto::right</functionname>(expr), state, data) ]</programlisting>
</para>
</listitem>
<listitem>
<para>
If <computeroutput>Tag</computeroutput> is <computeroutput>
<classname>proto::tag::if_else_</classname>
</computeroutput>,
then return
<programlisting>Grammar()(<functionname>proto::child_c</functionname>&lt;0&gt;(expr), state, data) ?
Grammar()(<functionname>proto::child_c</functionname>&lt;1&gt;(expr), state, data) :
Grammar()(<functionname>proto::child_c</functionname>&lt;2&gt;(expr), state, data)</programlisting>
</para>
</listitem>
<listitem>
<para>
If <computeroutput>Tag</computeroutput> is <computeroutput>
<classname>proto::tag::function</classname>
</computeroutput>,
then return
<programlisting>Grammar()(<functionname>proto::child_c</functionname>&lt;0&gt;(expr), state, data) (
Grammar()(<functionname>proto::child_c</functionname>&lt;1&gt;(expr), state, data),
...
Grammar()(<functionname>proto::child_c</functionname>&lt;N&gt;(expr), state, data) )</programlisting>
</para>
</listitem>
</itemizedlist>
</description>
</method>
</method-group>
<description>
<para>
The behavior of this class is specified in terms of the C++0x <computeroutput>decltype</computeroutput>
keyword. In systems where this keyword is not available, Proto uses the Boost.Typeof library to
approximate the behavior.
</para>
</description>
</struct>
</struct>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,775 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/transform/env.hpp">
<namespace name="boost">
<namespace name="proto">
<struct name="key_not_found">
<purpose>
The type of objects returned when a key-based lookup fails in a
transform environment.
</purpose>
</struct>
<!-- empty_env -->
<struct name="empty_env">
<purpose>
The type of an object that represents a transform environment
with no key/value pairs in it.
</purpose>
<method-group name="public member functions">
<method name="operator[]" cv="const">
<type><classname>proto::key_not_found</classname></type>
<parameter name="">
<paramtype><replaceable>unspecified</replaceable></paramtype>
</parameter>
<description>
<para>The type of the argument to this function has a
user-defined implicit conversion from any type.</para>
</description>
</method>
</method-group>
</struct>
<!-- env -->
<struct name="env">
<template>
<template-type-parameter name="Key"/>
<template-type-parameter name="Value"/>
<template-type-parameter name="Env">
<default><classname>proto::empty_env</classname></default>
</template-type-parameter>
</template>
<constructor specifiers="explicit">
<parameter name="value">
<paramtype>Value const &amp;</paramtype>
<description>
<para>
The value to be associated with the <code>Key</code>.
</para>
</description>
</parameter>
<parameter name="other">
<paramtype>Env const &amp;</paramtype>
<default>Env()</default>
<description>
<para>
Another key/value store.
</para>
</description>
</parameter>
</constructor>
<method-group name="public member functions">
<method name="operator[]" cv="const">
<type><replaceable>see-below</replaceable></type>
<parameter name="">
<paramtype><replaceable>see-below</replaceable></paramtype>
</parameter>
<description>
<para>
If called with an object that is implicitly convertible to type <code>Key</code>,
this function returns the <code>Value</code> passed to the constructor. Otherwise, it returns
the result of calling <code>operator[]</code> on the <code>Env</code> passed to
the constructor.
</para>
</description>
</method>
</method-group>
</struct>
<!-- is_env -->
<struct name="is_env">
<template>
<template-type-parameter name="T"/>
</template>
<inherit><type>mpl::bool_&lt;<replaceable>true-or-false</replaceable>&gt;</type></inherit>
<purpose>
<para>A Boolean metafuntion for determining whether or not a type is a Proto
transform environment.</para>
</purpose>
<description>
<para><code>is_env&lt;T&gt;</code> inherits from <code>mpl::true_</code> under the following
conditions:
<itemizedlist>
<listitem>If <code>T</code> is <classname>proto::empty_env</classname>.</listitem>
<listitem>If <code>T</code> is a specialization of <classname>proto::env&lt;&gt;</classname>.</listitem>
<listitem>If <code>T</code> is derived from any of the above.</listitem>
<listitem>If <code>T</code> is a cv-qualified variant of any of the above.</listitem>
<listitem>If <code>T</code> is a reference to any of the above.</listitem>
</itemizedlist>
</para>
<para>Otherwise, <code>is_env&lt;T&gt;</code> inherits from <code>mpl::false_</code>.
</para>
</description>
</struct>
<struct name="data_type">
<purpose>
The type of <code><globalname>proto::data</globalname></code>, a key for use when creating
a transform environment that associates a piece of data with this type.
</purpose>
<description>
<para>
The <code>proto::data_type</code> type, along with the <code><globalname>proto::data</globalname></code>
global, are declared using the <code><macroname>BOOST_PROTO_DEFINE_ENV_VAR</macroname>()</code> macro.
</para>
</description>
<method-group name="public member functions">
<overloaded-method name="operator=">
<signature cv="const">
<template>
<template-type-parameter name="Value"/>
</template>
<type><classname>env</classname>&lt;data_type, <replaceable>see-below</replaceable>&gt;</type>
<parameter name="value">
<paramtype>Value &amp;</paramtype>
</parameter>
</signature>
<signature cv="const">
<template>
<template-type-parameter name="Value"/>
</template>
<type><classname>env</classname>&lt;data_type, <replaceable>see-below</replaceable>&gt;</type>
<parameter name="value">
<paramtype>Value const &amp;</paramtype>
</parameter>
</signature>
<description>
<para>
If <code>Value</code> is a specialization <code>boost::reference_wrapper&lt;T&gt;</code>,
this function returns <code><classname>env</classname>&lt;data_type, T &amp;&gt;(value.get())</code>.
</para>
<para>
Else, if the type <code>Value</code> is non-copyable (i.e., a function, an array, abstract, or an ostream),
this function returns <code><classname>env</classname>&lt;data_type, Value <replaceable>cv</replaceable> &amp;&gt;(value)</code>,
where <code><replaceable>cv</replaceable></code> is <code>const</code> for the second overload, and empty
for the first.
</para>
<para>
Otherwise, this function returns <code><classname>env</classname>&lt;data_type, Value&gt;(value)</code>.
</para>
</description>
</overloaded-method>
</method-group>
</struct>
<data-member name="data">
<description>
<para>A key used for creating a transform environment.</para>
</description>
<type><classname>proto::data_type</classname> const</type>
</data-member>
<namespace name="functional">
<!-- functional::as_env -->
<struct name="as_env">
<inherit><classname>proto::callable</classname></inherit>
<purpose>
A unary <conceptname>PolymorphicFunctionObject</conceptname> for ensuring that an object
is a transform environment. If it isn't already, it is turned into one such that the
object is associated with the <classname>proto::data_type</classname> key.
</purpose>
<struct name="result">
<template>
<template-type-parameter name="Sig"/>
</template>
<typedef name="type">
<type><replaceable>see-below</replaceable></type>
<description>
<para>See <code><methodname>proto::functional::as_env::operator()</methodname></code>.</para>
</description>
</typedef>
<description>
<para>
Encodes the return type of <code><methodname>proto::functional::as_env::operator()</methodname></code>.
The presence of this member template makes <code><classname>proto::functional::as_env</classname></code>
a valid TR1-style function object type usable with <code>boost::result_of&lt;&gt;</code>.
</para>
</description>
</struct>
<method-group name="public member functions">
<overloaded-method name="operator()">
<signature cv="const">
<template>
<template-type-parameter name="T"/>
</template>
<type><replaceable>see-below</replaceable></type>
<parameter name="t">
<paramtype>T &amp;</paramtype>
</parameter>
</signature>
<signature cv="const">
<template>
<template-type-parameter name="T"/>
</template>
<type><replaceable>see-below</replaceable></type>
<parameter name="t">
<paramtype>T const &amp;</paramtype>
</parameter>
</signature>
<description>
<para>
If <code><classname>proto::is_env</classname>&lt;T&gt;::value</code> is <code>false</code>,
this function returns the result of <code>(<globalname>proto::data</globalname> = t)</code>.
See <code><methodname>proto::data_type::operator=</methodname></code> for details.
</para>
<para>
Otherwise, this function returns <code>t</code> by reference.
</para>
</description>
</overloaded-method>
</method-group>
</struct>
<!-- functional::has_env_var -->
<struct name="has_env_var">
<inherit><classname>proto::callable</classname></inherit>
<template>
<template-type-parameter name="Key"/>
</template>
<purpose>
A unary boolean <conceptname>PolymorphicFunctionObject</conceptname> used for determining whether a particular
transform environment has a value associated with a particular key.
</purpose>
<struct name="result">
<template>
<template-type-parameter name="Sig"/>
</template>
<typedef name="type">
<type><replaceable>see-below</replaceable></type>
<description>
<para>See <code><methodname>proto::functional::has_env_var::operator()</methodname></code>.</para>
</description>
</typedef>
<description>
<para>
Encodes the return type of <code><methodname>proto::functional::has_env_var::operator()</methodname></code>.
The presence of this member template makes <code><classname>proto::functional::has_env_var</classname></code>
a valid TR1-style function object type usable with <code>boost::result_of&lt;&gt;</code>.
</para>
</description>
</struct>
<method-group name="public member functions">
<method name="operator()" cv="const">
<template>
<template-type-parameter name="Env"/>
</template>
<type><replaceable>see-below</replaceable></type>
<parameter name="e">
<paramtype>Env const &amp;</paramtype>
</parameter>
<description>
<para>
This function behaves as follows:
<itemizedlist>
<listitem>
If <code><classname>proto::is_env</classname>&lt;Env&gt;::value</code> is <code>true</code>:
<itemizedlist>
<listitem>
If <code>e[Key()]</code> returns an instance of
<code><classname>proto::key_not_found</classname></code>, return
<code>mpl::false_</code>. See <code><methodname>proto::env::operator[]</methodname></code>
for more information.
</listitem>
<listitem>
Otherwise, return <code>mpl::true_</code>.
</listitem>
</itemizedlist>
</listitem>
<listitem>
Otherwise:
<itemizedlist>
<listitem>
If <code>Key</code> is <code><classname>proto::data_type</classname></code>,
return <code>mpl::true_</code>.
</listitem>
<listitem>
Otherwise, return <code>mpl::false_</code>.
</listitem>
</itemizedlist>
</listitem>
</itemizedlist>
</para>
</description>
</method>
</method-group>
</struct>
<!-- functional::env_var -->
<struct name="env_var">
<inherit><classname>proto::callable</classname></inherit>
<template>
<template-type-parameter name="Key"/>
</template>
<purpose>
A unary <conceptname>PolymorphicFunctionObject</conceptname> used for fetching the value
associated with a particular key in a transform environment.
</purpose>
<struct name="result">
<template>
<template-type-parameter name="Sig"/>
</template>
<typedef name="type">
<type><replaceable>see-below</replaceable></type>
<description>
<para>See <code><methodname>proto::functional::env_var::operator()</methodname></code>.</para>
</description>
</typedef>
<description>
<para>
Encodes the return type of <code><methodname>proto::functional::env_var::operator()</methodname></code>.
The presence of this member template makes <code><classname>proto::functional::env_var</classname></code>
a valid TR1-style function object type usable with <code>boost::result_of&lt;&gt;</code>.
</para>
</description>
</struct>
<method-group name="public member functions">
<method name="operator()" cv="const">
<template>
<template-type-parameter name="Env"/>
</template>
<type><replaceable>see-below</replaceable></type>
<parameter name="e">
<paramtype>Env const &amp;</paramtype>
</parameter>
<description>
<para>
This function behaves as follows:
<itemizedlist>
<listitem>
If <code>Key</code> is <code><classname>proto::data_type</classname></code>:
<itemizedlist>
<listitem>
If <code><classname>proto::is_env</classname>&lt;Env&gt;::value</code> is <code>true</code>,
return <code>e[<globalname>proto::data</globalname>]</code>.
</listitem>
<listitem>
Otherwise, return <code>e</code>.
</listitem>
</itemizedlist>
</listitem>
<listitem>
Otherwise, return <code>e[Key()]</code>.
</listitem>
</itemizedlist>
</para>
<para>
See <code><methodname>proto::env::operator[]</methodname></code> for additional information.
</para>
</description>
</method>
</method-group>
</struct>
</namespace>
<namespace name="result_of">
<struct name="as_env">
<template>
<template-type-parameter name="T"/>
</template>
<inherit><type>boost::result_of&lt;<classname>proto::functional::as_env</classname>(T)&gt;</type></inherit>
<purpose>
Metafunction for computing the return type of <code><functionname>proto::as_env()</functionname></code>.
</purpose>
</struct>
<struct name="has_env_var">
<template>
<template-type-parameter name="Env"/>
<template-type-parameter name="Key"/>
</template>
<inherit><type>boost::result_of&lt;<classname>proto::functional::has_env_var</classname>&lt;Key&gt;(Env)&gt;::type</type></inherit>
<purpose>
Metafunction for computing the return type of <code><functionname>proto::has_env_var()</functionname></code>.
</purpose>
</struct>
<struct name="env_var">
<template>
<template-type-parameter name="Env"/>
<template-type-parameter name="Key"/>
</template>
<inherit><type>boost::result_of&lt;<classname>proto::functional::env_var</classname>&lt;Key&gt;(Env)&gt;</type></inherit>
<purpose>
Metafunction for computing the return type of <code><functionname>proto::env_var()</functionname></code>.
</purpose>
</struct>
</namespace>
<!-- proto::as_env -->
<overloaded-function name="as_env">
<signature>
<template>
<template-type-parameter name="T"/>
</template>
<type>typename <classname>proto::result_of::as_env</classname>&lt;T &amp;&gt;::type</type>
<parameter name="t">
<paramtype>T &amp;</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="T"/>
</template>
<type>typename <classname>proto::result_of::as_env</classname>&lt;T const &amp;&gt;::type</type>
<parameter name="t">
<paramtype>T const &amp;</paramtype>
</parameter>
</signature>
<purpose>
For ensuring that the given argument is a transform environment. If it is not already,
it is made one as if by <code>(<globalname>proto::data</globalname> = t)</code>.
</purpose>
<description>
<para>
See also:
<itemizedlist>
<listitem>
<code><methodname>proto::data_type::operator=</methodname></code>
</listitem>
<listitem>
<code><methodname>proto::functional::as_env::operator()</methodname></code>
</listitem>
</itemizedlist>
</para>
</description>
<returns><code><classname>proto::functional::as_env</classname>()(t)</code></returns>
</overloaded-function>
<!-- proto::has_env_var -->
<overloaded-function name="has_env_var">
<signature>
<template>
<template-type-parameter name="Key"/>
<template-type-parameter name="Env"/>
</template>
<type>typename <classname>proto::result_of::has_env_var</classname>&lt;Env &amp;, Key&gt;::type</type>
<parameter name="e">
<paramtype>Env &amp;</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="Key"/>
<template-type-parameter name="Env"/>
</template>
<type>typename <classname>proto::result_of::has_env_var</classname>&lt;Env const &amp;, Key&gt;::type</type>
<parameter name="e">
<paramtype>Env const &amp;</paramtype>
</parameter>
</signature>
<purpose>
For testing to see whether a value exists in a transform environment corresponding to the
specified <code>Key</code>.
</purpose>
<description>
<para>
See also:
<itemizedlist>
<listitem>
<code><methodname>proto::functional::has_env_var::operator()</methodname></code>
</listitem>
</itemizedlist>
</para>
</description>
<returns><code><classname>proto::functional::has_env_var&lt;Key&gt;</classname>()(e)</code></returns>
</overloaded-function>
<!-- proto::env_var -->
<overloaded-function name="env_var">
<signature>
<template>
<template-type-parameter name="Key"/>
<template-type-parameter name="Env"/>
</template>
<type>typename <classname>proto::result_of::env_var</classname>&lt;Env &amp;, Key&gt;::type</type>
<parameter name="e">
<paramtype>Env &amp;</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="Key"/>
<template-type-parameter name="Env"/>
</template>
<type>typename <classname>proto::result_of::env_var</classname>&lt;Env const &amp;, Key&gt;::type</type>
<parameter name="e">
<paramtype>Env const &amp;</paramtype>
</parameter>
</signature>
<purpose>
For fetching the value from a transform environment corresponding to the
specified <code>Key</code>.
</purpose>
<description>
<para>
See also:
<itemizedlist>
<listitem>
<code><methodname>proto::functional::env_var::operator()</methodname></code>
</listitem>
</itemizedlist>
</para>
</description>
<returns><code><classname>proto::functional::env_var&lt;Key&gt;</classname>()(e)</code></returns>
</overloaded-function>
<!-- proto::operator, -->
<overloaded-function name="operator,">
<signature>
<template>
<template-type-parameter name="Env"/>
<template-type-parameter name="Key"/>
<template-type-parameter name="Value"/>
</template>
<type><classname>proto::env</classname>&lt;Key, Value, <replaceable>UNCVREF</replaceable>(typename <classname>proto::result_of::as_env</classname>&lt;Env &amp;&gt;::type)&gt;</type>
<parameter name="other">
<paramtype>Env &amp;</paramtype>
</parameter>
<parameter name="head">
<paramtype><classname>proto::env</classname>&lt;Key, Value&gt; const &amp;</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="Env"/>
<template-type-parameter name="Key"/>
<template-type-parameter name="Value"/>
</template>
<type><classname>proto::env</classname>&lt;Key, Value, <replaceable>UNCVREF</replaceable>(typename <classname>proto::result_of::as_env</classname>&lt;Env const &amp;&gt;::type)&gt;</type>
<parameter name="other">
<paramtype>Env const &amp;</paramtype>
</parameter>
<parameter name="head">
<paramtype><classname>proto::env</classname>&lt;Key, Value&gt; const &amp;</paramtype>
</parameter>
</signature>
<purpose>
For composing a larger transform environment from two smaller ones.
</purpose>
<description>
<para>
The effect of this function is to take two transform environments and compose them into
a larger environment that contains the key/values pairs of the two. The first argument
is allowed to not be a transform environment, in which case it is turned into one with
the <functionname>proto::as_env()</functionname> function before composition with the
second argument. The second argument is required to be a transform environment with exactly
one key/value pair.
</para>
<para>
<emphasis role="bold">Example:</emphasis>
</para>
<para>
Given user-defined keys <code>key0</code> and <code>key1</code> of types <code>key0_type</code>
and <code>key1_type</code>, the following code demonstrates how the chained use of <code>operator,</code>
can build a composite transform environment containing a number of key/value pairs:
<programlisting><classname>proto::env</classname>&lt;
key1_type
, int
, <classname>proto::env</classname>&lt;
key0_type
, char const (&amp;)[6]
, <classname>proto::env</classname>&lt;<classname>proto::data_type</classname>, int&gt;
&gt;
&gt; myenv = (<globalname>proto::data</globalname> = 1, key0 = "hello", key1 = 42);
// NOTE: operator, here --^ and here --^
// Check the results:
assert(1 == myenv[proto::data]);
assert(0 == std::strcmp(myenv[key0], "hello"));
assert(42 == myenv[key1]);</programlisting>
</para>
<para>
<emphasis role="bold">Note:</emphasis> In the return type and the "Returns" clause, <code><replaceable>UNCVREF</replaceable>(X)</code> is
the type <code>X</code> stripped of top-level reference and cv-qualifiers.
</para>
<para>
<emphasis role="bold">Note:</emphasis> In the "Returns" clause, <code><replaceable>cv</replaceable></code> is replaced with <code>const</code>
for the second overload, and nothing for the first.
</para>
<para>
<emphasis role="bold">See also:</emphasis>
<itemizedlist>
<listitem>
<code><methodname>proto::env::operator[]</methodname></code>
</listitem>
</itemizedlist>
</para>
</description>
<returns><code><classname>proto::env</classname>&lt;Key, Value, <replaceable>UNCVREF</replaceable>(typename <classname>proto::result_of::as_env</classname>&lt;Env <replaceable>cv</replaceable> &amp;&gt;::type)&gt;(head[Key()], <functionname>proto::as_env</functionname>(other))</code></returns>
</overloaded-function>
<!-- struct _env_var -->
<struct name="_env_var">
<template>
<template-type-parameter name="Key"/>
</template>
<purpose>
A primitive transform that returns the value associated with a particular <code>Key</code>
in the current transform environment.
</purpose>
<inherit>
<type><classname>proto::transform</classname>&lt;_env_var&lt;Key&gt; &gt;</type>
</inherit>
<struct name="impl">
<template>
<template-type-name name="Expr"/>
<template-type-name name="State"/>
<template-type-name name="Data"/>
</template>
<inherit>
<type><classname>proto::transform_impl</classname>&lt;Expr, State, Data&gt; &gt;</type>
</inherit>
<typedef name="result_type">
<type>typename <classname>proto::result_of::env_var</classname>&lt;Data, Key&gt;::type</type>
</typedef>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>result_type</type>
<parameter name="">
<paramtype>typename impl::expr_param</paramtype>
</parameter>
<parameter name="">
<paramtype>typename impl::state_param</paramtype>
</parameter>
<parameter name="data">
<paramtype>typename impl::data_param</paramtype>
<description>
<para>The current transform environment</para>
</description>
</parameter>
<description>
<para>
Fetches the value associated with <code>Key</code> from the transform environment
passed in the data (third) parameter.
</para>
</description>
<requires>
<para>
<code><classname>proto::is_env</classname>&lt;Data&gt;::value</code>
is <code>true</code>.
</para>
</requires>
<returns>
<para>
<code><functionname>proto::env_var</functionname>(data)</code>
</para>
</returns>
</method>
</method-group>
</struct>
<description>
<para>
See <code><classname>proto::_env_var::impl</classname></code> for the full details.
</para>
</description>
</struct>
<!-- struct _env -->
<struct name="_env">
<purpose>
A primitive transform that returns the current transform environment unmodified.
</purpose>
<inherit>
<type><classname>proto::transform</classname>&lt;_env&gt;</type>
</inherit>
<struct name="impl">
<template>
<template-type-name name="Expr"/>
<template-type-name name="State"/>
<template-type-name name="Data"/>
</template>
<inherit>
<type><classname>proto::transform_impl</classname>&lt;Expr, State, Data&gt;</type>
</inherit>
<typedef name="result_type">
<type>Data</type>
</typedef>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>result_type</type>
<parameter name="">
<paramtype>typename impl::expr_param</paramtype>
</parameter>
<parameter name="">
<paramtype>typename impl::state_param</paramtype>
</parameter>
<parameter name="data">
<paramtype>typename impl::data_param</paramtype>
<description>
<para>The current transform environment </para>
</description>
</parameter>
<description>
<para>
Returns the current transform environment
passed in the data (third) parameter.
</para>
</description>
<returns>
<para>
<code>data</code>
</para>
</returns>
</method>
</method-group>
</struct>
<description>
<para>
See <code><classname>proto::_env::impl</classname></code> for the full details.
</para>
</description>
</struct>
</namespace>
</namespace>
<!-- BOOST_PROTO_DEFINE_ENV_VAR() -->
<macro name="BOOST_PROTO_DEFINE_ENV_VAR" kind="functionlike">
<macro-parameter name="Type"/>
<macro-parameter name="Name"/>
<purpose>
Define a type and a global variable of that type that can be used
to initialize a slot in a Proto transform environment.
</purpose>
<description>
<para>
Proto primitive transforms can optionally accept an environment in
their third parameter which is a key/value store of environment
variables. Use the <code>BOOST_PROTO_DEFINE_ENV_VAR()</code> macro
to define the keys.
</para>
<para>
See the description for <code><classname alt="boost::proto::data_type">proto::data_type</classname></code>
for an example of the class interface created by this macro.
</para>
<para>
<emphasis role="bold">Example:</emphasis>
</para>
<para>
<programlisting>BOOST_PROTO_DEFINE_ENV_VAR(mykey_type, mykey);
struct FetchMyKey
: <classname alt="boost::proto::when">proto::when</classname>&lt; <classname alt="boost::proto::_">_</classname>, <classname alt="boost::proto::_env_var">proto::_env_var</classname>&lt;mykey_type&gt; &gt;
{};
int main()
{
<classname alt="boost::proto::terminal">proto::terminal</classname>&lt;int&gt;::type i = {42};
char const * sz = FetchMyKey()(i, 0, (mykey = "hello!"));
assert(0 == std::strcmp(sz, "hello!");
}</programlisting>
</para>
</description>
</macro>
</header>

View File

@@ -0,0 +1,125 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/transform/fold.hpp">
<para>Contains definition of the
<computeroutput>
<classname alt="boost::proto::fold">proto::fold&lt;&gt;</classname>
</computeroutput> and
<computeroutput>
<classname alt="boost::proto::reverse_fold">proto::reverse_fold&lt;&gt;</classname>
</computeroutput>
transforms.</para>
<namespace name="boost">
<namespace name="proto">
<struct name="fold">
<template>
<template-type-parameter name="Sequence"/>
<template-type-parameter name="State0"/>
<template-type-parameter name="Fun"/>
</template>
<inherit>
<classname>proto::transform</classname>&lt; fold&lt;Sequence, State0, Fun&gt; &gt;</inherit>
<purpose>A <conceptname>PrimitiveTransform</conceptname> that invokes the
<computeroutput>fusion::fold&lt;&gt;</computeroutput> algorithm to accumulate a value.</purpose>
<description>
<para>
For the complete description of the behavior of the <computeroutput>proto::fold&lt;&gt;</computeroutput>
transform, see the documentation for the nested <computeroutput>
<classname>proto::fold::impl&lt;&gt;</classname>
</computeroutput> class template.
</para>
</description>
<struct name="impl">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="State"/>
<template-type-parameter name="Data"/>
</template>
<inherit><classname>proto::transform_impl</classname>&lt; Expr, State, Data &gt;</inherit>
<typedef name="X">
<purpose>For exposition only</purpose>
<type><classname>when</classname>&lt;<classname>_</classname>, Sequence&gt;</type>
</typedef>
<typedef name="Y">
<purpose>For exposition only</purpose>
<type><classname>when</classname>&lt;<classname>_</classname>, State0&gt;</type>
</typedef>
<typedef name="seq">
<purpose>A Fusion sequence, for exposition only</purpose>
<type>typename boost::result_of&lt;X(Expr, State, Data)&gt;::type</type>
</typedef>
<typedef name="state0">
<purpose>An initial state for the fold, for exposition only</purpose>
<type>typename boost::result_of&lt;Y(Expr, State, Data)&gt;::type</type>
</typedef>
<typedef name="fun">
<purpose><computeroutput>fun(d)(s,e) == when&lt;_,Fun&gt;()(e,s,d)</computeroutput></purpose>
<type><emphasis>unspecified</emphasis></type>
</typedef>
<typedef name="result_type">
<type>typename fusion::result_of::fold&lt;seq, state0, fun&gt;::type</type>
</typedef>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>result_type</type>
<parameter name="expr">
<paramtype>typename impl::expr_param</paramtype>
<description>
<para>The current expression </para>
</description>
</parameter>
<parameter name="state">
<paramtype>typename impl::state_param</paramtype>
<description>
<para>The current state </para>
</description>
</parameter>
<parameter name="data">
<paramtype>typename impl::data_param</paramtype>
<description>
<para>An arbitrary data </para>
</description>
</parameter>
<description>
<para>
Let <computeroutput>seq</computeroutput> be
<computeroutput><classname>when</classname>&lt;<classname>_</classname>, Sequence&gt;()(expr, state, data)</computeroutput>,
let <computeroutput>state0</computeroutput> be
<computeroutput><classname>when</classname>&lt;<classname>_</classname>, State0&gt;()(expr, state, data)</computeroutput>,
and let <computeroutput>fun(data)</computeroutput> be an object such that
<computeroutput>fun(data)(state, expr)</computeroutput> is equivalent to
<computeroutput><classname>when</classname>&lt;<classname>_</classname>, Fun&gt;()(expr, state, data)</computeroutput>. Then,
this function returns <computeroutput>fusion::fold(seq, state0, fun(data))</computeroutput>.
</para>
</description>
</method>
</method-group>
</struct>
</struct>
<struct name="reverse_fold">
<template>
<template-type-parameter name="Sequence"/>
<template-type-parameter name="State0"/>
<template-type-parameter name="Fun"/>
</template>
<inherit><classname>proto::fold</classname>&lt; <classname>proto::_reverse</classname>(Sequence), State0, Fun &gt;</inherit>
<purpose>
A <conceptname>PrimitiveTransform</conceptname> that is the same as the <computeroutput><classname>proto::fold&lt;&gt;</classname></computeroutput>
transform, except that it folds back-to-front instead of front-to-back. It uses the
<computeroutput>
<classname>proto::_reverse</classname>
</computeroutput> callable <conceptname>PolymorphicFunctionObject</conceptname> to create a
<computeroutput>fusion::reverse_view&lt;&gt;</computeroutput> of the sequence before invoking
<computeroutput>fusion::fold&lt;&gt;</computeroutput>.
</purpose>
</struct>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,141 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/transform/fold_tree.hpp">
<para>
Contains definition of the
<computeroutput>
<classname alt="boost::proto::fold_tree">proto::fold_tree&lt;&gt;</classname>
</computeroutput> and
<computeroutput>
<classname alt="boost::proto::reverse_fold_tree">proto::reverse_fold_tree&lt;&gt;</classname>
</computeroutput>
transforms.
</para>
<namespace name="boost">
<namespace name="proto">
<struct name="fold_tree">
<template>
<template-type-parameter name="Sequence"/>
<template-type-parameter name="State0"/>
<template-type-parameter name="Fun"/>
</template>
<inherit><classname>proto::transform</classname>&lt; fold_tree&lt;Sequence, State0, Fun&gt; &gt;</inherit>
<purpose>A <conceptname>PrimitiveTransform</conceptname> that recursively applies the
<computeroutput><classname>proto::fold</classname>&lt;&gt;</computeroutput> transform to sub-trees
that all share a common tag type.</purpose>
<description>
<para>
<computeroutput>proto::fold_tree&lt;&gt;</computeroutput> is useful for flattening trees into lists;
for example, you might use <computeroutput>proto::fold_tree&lt;&gt;</computeroutput> to flatten an
expression tree like <computeroutput>a | b | c</computeroutput> into a Fusion list like
<computeroutput>cons(c, cons(b, cons(a)))</computeroutput>.
</para>
<para>
<computeroutput>proto::fold_tree&lt;&gt;</computeroutput> is easily understood in terms of a
<computeroutput>recurse_if_&lt;&gt;</computeroutput> helper, defined as follows:
<programlisting> template&lt;typename Tag, typename Fun&gt;
struct recurse_if_ :
<classname>proto::if_</classname>&lt;
// If the current node has type type "Tag" ...
boost::is_same&lt;<classname>proto::tag_of</classname>&lt;<classname>proto::_</classname>&gt;, Tag&gt;(),
// ... recurse, otherwise ...
<classname>proto::fold</classname>&lt;<classname>proto::_</classname>, <classname>proto::_state</classname>, recurse_if_&lt;Tag, Fun&gt; &gt;,
// ... apply the Fun transform.
Fun
&gt;
{};</programlisting>
</para>
<para>
With <computeroutput>recurse_if_&lt;&gt;</computeroutput> as defined above,
<computeroutput>proto::fold_tree&lt;Sequence, State0, Fun&gt;()(expr, state, data)</computeroutput>
is equivalent to:
<programlisting><classname>proto::fold</classname>&lt;
Sequence,
State0,
recurse_if_&lt;typename Expr::proto_tag, Fun&gt;
&gt;()(expr, state, data).</programlisting>
It has the effect of folding a tree front-to-back, recursing into child nodes that share a
tag type with the parent node.
</para>
</description>
<struct name="impl">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="State"/>
<template-type-parameter name="Data"/>
</template>
<inherit>
<type>
<classname>proto::fold</classname>&lt;Sequence, State0, recurse_if_&lt;typename Expr::proto_tag, Fun&gt; &gt;
::template impl&lt;Expr, State, Data&gt;</type>
</inherit>
</struct>
</struct>
<struct name="reverse_fold_tree">
<template>
<template-type-parameter name="Sequence"/>
<template-type-parameter name="State0"/>
<template-type-parameter name="Fun"/>
</template>
<inherit><classname>proto::transform</classname>&lt; reverse_fold_tree&lt;Sequence, State0, Fun&gt; &gt;</inherit>
<purpose>A <conceptname>PrimitiveTransform</conceptname> that recursively applies the
<computeroutput><classname>proto::reverse_fold&lt;&gt;</classname></computeroutput> transform to
sub-trees that all share a common tag type.</purpose>
<description>
<para>
<computeroutput>proto::reverse_fold_tree&lt;&gt;</computeroutput> is useful for flattening trees
into lists; for example, you might use <computeroutput>proto::reverse_fold_tree&lt;&gt;</computeroutput>
to flatten an expression tree like <computeroutput>a | b | c</computeroutput> into a Fusion list like
<computeroutput>cons(a, cons(b, cons(c)))</computeroutput>.
</para>
<para>
<computeroutput>proto::reverse_fold_tree&lt;&gt;</computeroutput> is easily understood in terms of
a <computeroutput>recurse_if_&lt;&gt;</computeroutput> helper, defined as follows:
<programlisting> template&lt;typename Tag, typename Fun&gt;
struct recurse_if_ :
<classname>proto::if_</classname>&lt;
// If the current node has type type "Tag" ...
boost::is_same&lt;<classname>proto::tag_of</classname>&lt;<classname>proto::_</classname>&gt;, Tag&gt;(),
// ... recurse, otherwise ...
<classname>proto::reverse_fold</classname>&lt;<classname>proto::_</classname>, <classname>proto::_state</classname>, recurse_if_&lt;Tag, Fun&gt; &gt;,
// ... apply the Fun transform.
Fun
&gt;
{};</programlisting>
</para>
<para>
With <computeroutput>recurse_if_&lt;&gt;</computeroutput> as defined above,
<computeroutput>proto::reverse_fold_tree&lt;Sequence, State0, Fun&gt;()(expr, state, data)</computeroutput>
is equivalent to:
<programlisting><classname>proto::reverse_fold</classname>&lt;
Sequence,
State0,
recurse_if_&lt;typename Expr::proto_tag, Fun&gt;
&gt;()(expr, state, data).</programlisting>
It has the effect of folding a tree back-to-front, recursing into child nodes that share a
tag type with the parent node.
</para>
</description>
<struct name="impl">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="State"/>
<template-type-parameter name="Data"/>
</template>
<inherit>
<type>
<classname>proto::reverse_fold</classname>&lt;Sequence, State0, recurse_if_&lt;typename Expr::proto_tag, Fun&gt; &gt;
::template impl&lt;Expr, State, Data&gt;</type>
</inherit>
</struct>
</struct>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,306 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/transform/impl.hpp">
<para>Contains definition of transform&lt;&gt; and transform_impl&lt;&gt; helpers. </para>
<namespace name="boost">
<namespace name="proto">
<!-- proto::transform -->
<struct name="transform">
<template>
<template-type-parameter name="PrimitiveTransform"/>
</template>
<purpose>Inherit from this to make your type a <conceptname>PrimitiveTransform</conceptname>.</purpose>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="Expr"/>
</template>
<specialization>
<template-arg>This(Expr)</template-arg>
</specialization>
<typedef name="type">
<type>typename PrimitiveTransform::template impl&lt; Expr, <replaceable>unspecified</replaceable>, <replaceable>unspecified</replaceable> &gt;::result_type</type>
</typedef>
</struct-specialization>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="Expr"/>
<template-type-parameter name="State"/>
</template>
<specialization>
<template-arg>This(Expr, State)</template-arg>
</specialization>
<typedef name="type">
<type>typename PrimitiveTransform::template impl&lt; Expr, State, <replaceable>unspecified</replaceable> &gt;::result_type</type>
</typedef>
</struct-specialization>
<struct-specialization name="result">
<template>
<template-type-parameter name="This"/>
<template-type-parameter name="Expr"/>
<template-type-parameter name="State"/>
<template-type-parameter name="Data"/>
</template>
<specialization>
<template-arg>This(Expr, State, Data)</template-arg>
</specialization>
<typedef name="type">
<type>typename PrimitiveTransform::template impl&lt; Expr, State, Data &gt;::result_type</type>
</typedef>
</struct-specialization>
<typedef name="transform_type">
<type>PrimitiveTransform</type>
</typedef>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>typename PrimitiveTransform::template impl&lt;Expr &amp;, <replaceable>unspecified</replaceable>, <replaceable>unspecified</replaceable>&gt;::result_type</type>
<template>
<template-type-parameter name="Expr"/>
</template>
<parameter name="expr">
<paramtype>Expr &amp;</paramtype>
</parameter>
<returns>
<computeroutput>
typename PrimitiveTransform::template impl&lt;Expr &amp;, <replaceable>unspecified</replaceable>, <replaceable>unspecified</replaceable>&gt;()(expr, <replaceable>unspecified</replaceable>, <replaceable>unspecified</replaceable>)
</computeroutput>
</returns>
</method>
<method name="operator()" cv="const">
<type>typename PrimitiveTransform::template impl&lt;Expr &amp;, State &amp;, <replaceable>unspecified</replaceable>&gt;::result_type</type>
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="State"/>
</template>
<parameter name="expr">
<paramtype>Expr &amp;</paramtype>
</parameter>
<parameter name="state">
<paramtype>State &amp;</paramtype>
</parameter>
<returns>
<computeroutput>
typename PrimitiveTransform::template impl&lt;Expr &amp;, State &amp;, <replaceable>unspecified</replaceable>&gt;()(expr, state, <replaceable>unspecified</replaceable>)
</computeroutput>
</returns>
</method>
<method name="operator()" cv="const">
<type>typename PrimitiveTransform::template impl&lt;Expr &amp;, State const &amp;, <replaceable>unspecified</replaceable>&gt;::result_type</type>
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="State"/>
</template>
<parameter name="expr">
<paramtype>Expr &amp;</paramtype>
</parameter>
<parameter name="state">
<paramtype>State const &amp;</paramtype>
</parameter>
<returns>
<computeroutput>
typename PrimitiveTransform::template impl&lt;Expr &amp;, State const &amp;, <replaceable>unspecified</replaceable>&gt;()(expr, state, <replaceable>unspecified</replaceable>)
</computeroutput>
</returns>
</method>
<method name="operator()" cv="const">
<type>typename PrimitiveTransform::template impl&lt;Expr &amp;, State &amp;, Data &amp;&gt;::result_type</type>
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="State"/>
<template-type-parameter name="Data"/>
</template>
<parameter name="expr">
<paramtype>Expr &amp;</paramtype>
</parameter>
<parameter name="state">
<paramtype>State &amp;</paramtype>
</parameter>
<parameter name="data">
<paramtype>Data &amp;</paramtype>
</parameter>
<returns>
<computeroutput>
typename PrimitiveTransform::template impl&lt;Expr &amp;, State &amp;, Data &amp;&gt;()(expr, state, data)
</computeroutput>
</returns>
</method>
<method name="operator()" cv="const">
<type>typename PrimitiveTransform::template impl&lt;Expr &amp;, State const &amp;, Data &amp;&gt;::result_type</type>
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="State"/>
<template-type-parameter name="Data"/>
</template>
<parameter name="expr">
<paramtype>Expr &amp;</paramtype>
</parameter>
<parameter name="state">
<paramtype>State const &amp;</paramtype>
</parameter>
<parameter name="data">
<paramtype>Data &amp;</paramtype>
</parameter>
<returns>
<computeroutput>
typename PrimitiveTransform::template impl&lt;Expr &amp;, State const &amp;, Data &amp;&gt;()(expr, state, data)
</computeroutput>
</returns>
</method>
</method-group>
</struct>
<!-- proto::transform_impl -->
<struct name="transform_impl">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="State"/>
<template-type-parameter name="Data"/>
</template>
<typedef name="expr">
<type>typename boost::remove_reference&lt;Expr const&gt;::type</type>
</typedef>
<typedef name="expr_param">
<type>typename boost::add_reference&lt;Expr const&gt;::type</type>
</typedef>
<typedef name="state">
<type>typename boost::remove_reference&lt;State const&gt;::type</type>
</typedef>
<typedef name="state_param">
<type>typename boost::add_reference&lt;State const&gt;::type</type>
</typedef>
<typedef name="data">
<type>typename boost::remove_reference&lt;Data const&gt;::type</type>
</typedef>
<typedef name="data_param">
<type>typename boost::add_reference&lt;Data const&gt;::type</type>
</typedef>
</struct>
<!-- proto::pack -->
<struct name="pack">
<purpose>To turn an expression into a pseudo-parameter pack containing the
expression's children, for the purpose of expanding the pack expression within
a <conceptname>CallableTransform</conceptname> or
<conceptname>ObjectTransform</conceptname>.</purpose>
<description>
<para>
<computeroutput>proto::pack</computeroutput> is useful within
<conceptname>CallableTransform</conceptname>s and
<conceptname>ObjectTransform</conceptname>s when one wishes to unpack an expression
into a function call or an object constructor. <computeroutput>proto::pack</computeroutput>
turns a Proto expression into a pseudo-parameter pack, which may appear in an unpacking
pattern to be expanded with the "<computeroutput>...</computeroutput>" syntax.
</para>
<para>
<emphasis role="bold">Example:</emphasis>
</para>
<para>
<programlisting>// The following demonstrates how to use a pseudo-pack expansion
// to unpack an expression into a function call.
struct do_sum : <classname alt="boost::proto::callable">proto::callable</classname>
{
typedef int result_type;
int operator()(int i) const { return i; }
int operator()(int i, int j) const { return i + j; }
int operator()(int i, int j, int k) const { return i + j + k; }
};
// Take any n-ary expression where the children are all int terminals and sum all the ints
struct sum
: <classname alt="boost::proto::when">proto::when</classname>&lt;
// Match any nary expression where the children are all int terminals
<classname alt="boost::proto::nary_expr">proto::nary_expr</classname>&lt;<classname alt="boost::proto::_">_</classname>, <classname alt="boost::proto::vararg">proto::vararg</classname>&lt;<classname alt="boost::proto::terminal">proto::terminal</classname>&lt;int&gt; &gt; &gt;
// Turn the current expression into a pseudo-parameter pack, then expand it,
// extracting the value from each child in turn.
, do_sum(<classname alt="boost::proto::_value">proto::_value</classname>(proto::pack(<classname alt="boost::proto::_">_</classname>))...)
&gt;
{};
int main()
{
<classname alt="boost::proto::terminal">proto::terminal</classname>&lt;int&gt;::type i = {42};
int result = sum()( i(3,5) ); // Creates a ternary functional-call expression
std::cout &lt;&lt; "Sum of 42, 3, and 5 : " &lt;&lt; result &lt;&lt; std::endl;
}</programlisting>
</para>
<para>
The above program displays:
</para>
<para>
<computeroutput>Sum of 42, 3, and 5 : 50</computeroutput>
</para>
<para>
In the above example, the type
<computeroutput>
<classname alt="boost::proto::_value">proto::_value</classname>(proto::pack(<classname alt="boost::proto::_">_</classname>))
</computeroutput>
is a so-called <emphasis>unpacking pattern</emphasis>, described below.
</para>
<para>
<emphasis role="bold">Unpacking Patterns:</emphasis>
</para>
<para>
Composite transforms (either <conceptname>CallableTransform</conceptname>s or
<conceptname>ObjectTransform</conceptname>s) usually have the form
<computeroutput>X(A<subscript>0</subscript>,…A<subscript>n</subscript>)</computeroutput>.
However, when the argument list in a composite transform is terminated with a C-style
vararg ellipsis as in <computeroutput>X(A<subscript>0</subscript>,…A<subscript>n</subscript> ...)</computeroutput>,
the final argument <computeroutput>A<subscript>n</subscript></computeroutput> is treated
as an <emphasis>unpacking pattern</emphasis>.
</para>
<para>
An unpacking pattern must itself be a composite transform; that is, it must be a
function type representing either a <conceptname>CallableTransform</conceptname> or
an <conceptname>ObjectTransform</conceptname>. The type <computeroutput>proto::pack(_)</computeroutput>
must appear exactly once in the unpacking pattern. This type will receive a substitution
when the unpacking pattern is expanded.
</para>
<para>
A composite transform like <computeroutput>X(A<subscript>0</subscript>,…A<subscript>n</subscript> ...)</computeroutput>,
when evaluated against a given expression <replaceable>E</replaceable>, state and data, is evaluated as if it were
<computeroutput>X(A<subscript>0</subscript>,…A<subscript>n-1</subscript>,<replaceable>S</replaceable>)</computeroutput>
where <replaceable>S</replaceable> is a type sequence computed as follows:
</para>
<para>
Let <computeroutput><replaceable>SUB</replaceable>(A,B)</computeroutput> be a type function that replaces every occurence of
<computeroutput>proto::pack(_)</computeroutput> within <computeroutput>A</computeroutput> with <computeroutput>B</computeroutput>.
<itemizedlist>
<listitem>
If the expression <replaceable>E</replaceable> is a terminal (i.e. it has arity 0), <replaceable>S</replaceable>
is the one-element sequence containing <computeroutput><replaceable>SUB</replaceable>(A<subscript>n</subscript>, <classname alt="boost::proto::_value">proto::_value</classname>)</computeroutput>.
</listitem>
<listitem>
If the expression <replaceable>E</replaceable> is a non-terminal, <replaceable>S</replaceable> is the sequence
<computeroutput><replaceable>SUB</replaceable>(A<subscript>n</subscript>, <classname alt="boost::proto::_child_c">proto::_child_c</classname>&lt;0&gt;),…
<replaceable>SUB</replaceable>(A<subscript>n</subscript>, <classname alt="boost::proto::_child_c">proto::_child_c</classname>&lt;<replaceable>M</replaceable>-1&gt;)</computeroutput>, where
<replaceable>M</replaceable> is the arity of the expression <replaceable>E</replaceable>.
</listitem>
</itemizedlist>
</para>
</description>
</struct>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,100 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/transform/integral_c.hpp">
<para>Contains definition of the integral_c transform and friends.</para>
<namespace name="boost">
<namespace name="proto">
<struct name="integral_c">
<template>
<template-type-parameter name="T"/>
<template-nontype-parameter name="I">
<type>T</type>
</template-nontype-parameter>
</template>
<inherit><classname>proto::transform</classname>&lt; integral_c&lt; T, I &gt; &gt;</inherit>
<purpose>A <conceptname>PrimitiveTransform</conceptname> that returns the specified integral constant.</purpose>
<struct name="impl">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="State"/>
<template-type-parameter name="Data"/>
</template>
<inherit><classname>proto::transform_impl</classname>&lt; Expr, State, Data &gt;</inherit>
<typedef name="result_type">
<type>T</type>
</typedef>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>T</type>
<parameter name="">
<paramtype>typename impl::expr_param</paramtype>
</parameter>
<parameter name="">
<paramtype>typename impl::state_param</paramtype>
</parameter>
<parameter name="">
<paramtype>typename impl::data_param</paramtype>
</parameter>
<returns>
<para>
<computeroutput>I</computeroutput>
</para>
</returns>
<throws>
<simpara>Will not throw.</simpara>
</throws>
</method>
</method-group>
</struct>
</struct>
<struct name="char_">
<template>
<template-nontype-parameter name="I">
<type>char</type>
</template-nontype-parameter>
</template>
<inherit><classname>proto::integral_c</classname>&lt; char, I &gt;</inherit>
<purpose>A <conceptname>PrimitiveTransform</conceptname> that returns the specified char.</purpose>
</struct>
<struct name="int_">
<template>
<template-nontype-parameter name="I">
<type>int</type>
</template-nontype-parameter>
</template>
<inherit><classname>proto::integral_c</classname>&lt; int, I &gt;</inherit>
<purpose>A <conceptname>PrimitiveTransform</conceptname> that returns the specified int.</purpose>
</struct>
<struct name="long_">
<template>
<template-nontype-parameter name="I">
<type>long</type>
</template-nontype-parameter>
</template>
<inherit><classname>proto::integral_c</classname>&lt; long, I &gt;</inherit>
<purpose>A <conceptname>PrimitiveTransform</conceptname> that returns the specified long.</purpose>
</struct>
<struct name="size_t">
<template>
<template-nontype-parameter name="I">
<type>std::size_t</type>
</template-nontype-parameter>
</template>
<inherit><classname>proto::integral_c</classname>&lt; std::size_t, I &gt;</inherit>
<purpose>A <conceptname>PrimitiveTransform</conceptname> that returns the specified std::size_t.</purpose>
</struct>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,150 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/transform/lazy.hpp">
<para>
Contains definition of the
<computeroutput>
<classname alt="boost::proto::lazy">proto::lazy&lt;&gt;</classname>
</computeroutput> transform.
</para>
<namespace name="boost">
<namespace name="proto">
<struct name="lazy">
<template>
<template-type-parameter name="T"/>
</template>
<inherit><classname>proto::transform</classname>&lt; lazy&lt;T&gt; &gt;</inherit>
<purpose>A <conceptname>PrimitiveTransform</conceptname> that uses
<computeroutput><classname>proto::make&lt;&gt;</classname></computeroutput> to build a
<conceptname>CallableTransform</conceptname>, and then uses
<computeroutput><classname>proto::call&lt;&gt;</classname></computeroutput> to apply it.
</purpose>
<description>
<para>
<computeroutput>proto::lazy&lt;&gt;</computeroutput> is useful as a higher-order transform,
when the transform to be applied depends on the current state of the transformation. The
invocation of the <computeroutput>
<classname>proto::make&lt;&gt;</classname>
</computeroutput> transform evaluates any nested transforms, and the resulting type is treated
as a <conceptname>CallableTransform</conceptname>, which is evaluated with
<computeroutput><classname>proto::call&lt;&gt;</classname></computeroutput>.
</para>
<para>
For the full description of the behavior of the
<computeroutput>
<classname>proto::lazy&lt;&gt;</classname>
</computeroutput>
transform, see the documentation for the nested
<computeroutput>
<classname>proto::lazy::impl&lt;&gt;</classname>
</computeroutput>
class template.
</para>
</description>
<struct name="impl">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="State"/>
<template-type-parameter name="Data"/>
</template>
<inherit><type><classname>proto::transform_impl</classname>&lt;Expr, State, Data&gt;</type></inherit>
<typedef name="result_type">
<type><replaceable>see-below</replaceable></type>
<description>
<para>
<computeroutput><classname>proto::lazy</classname>&lt;T&gt;::impl&lt;Expr,State,Data&gt;::result_type</computeroutput>
is calculated as follows:
<itemizedlist>
<listitem>
<para>
If <computeroutput>T</computeroutput> if of the form
<computeroutput>O(A<subscript>0</subscript>,…A<subscript>n</subscript>)</computeroutput>, then let <computeroutput>O'</computeroutput>
be <computeroutput>boost::result_of&lt;<classname>proto::make</classname>&lt;O&gt;(Expr, State, Data)&gt;::type</computeroutput>
and let <computeroutput>T'</computeroutput> be <computeroutput>O'(A<subscript>0</subscript>,…A<subscript>n</subscript>)</computeroutput>.
</para>
</listitem>
<listitem>
<para>
If <computeroutput>T</computeroutput> if of the form
<computeroutput>O(A<subscript>0</subscript>,…A<subscript>n</subscript> ...)</computeroutput>, then let <computeroutput>O'</computeroutput>
be <computeroutput>boost::result_of&lt;<classname>proto::make</classname>&lt;O&gt;(Expr, State, Data)&gt;::type</computeroutput>
and let <computeroutput>T'</computeroutput> be <computeroutput>O'(A<subscript>0</subscript>,…A<subscript>n</subscript> ...)</computeroutput>.
</para>
</listitem>
<listitem>
<para>
Otherwise, let <computeroutput>T'</computeroutput>
be <computeroutput>boost::result_of&lt;<classname>proto::make</classname>&lt;T&gt;(Expr, State, Data)&gt;::type</computeroutput>.
</para>
</listitem>
</itemizedlist>
<para>
The result type is
<computeroutput>
boost::result_of&lt;<classname>proto::call</classname>&lt;T'&gt;(Expr, State, Data)&gt;::type
</computeroutput>.
</para>
</para>
</description>
</typedef>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>result_type</type>
<parameter name="expr">
<paramtype>typename impl::expr_param</paramtype>
</parameter>
<parameter name="state">
<paramtype>typename impl::state_param</paramtype>
</parameter>
<parameter name="data">
<paramtype>typename impl::data_param</paramtype>
</parameter>
<description>
<para>
<computeroutput><classname>proto::lazy</classname>&lt;T&gt;::impl&lt;Expr,State,Data&gt;::operator()</computeroutput> behaves as follows:
<itemizedlist>
<listitem>
<para>
If <computeroutput>T</computeroutput> if of the form
<computeroutput>O(A<subscript>0</subscript>,…A<subscript>n</subscript>)</computeroutput>, then let <computeroutput>O'</computeroutput>
be <computeroutput>boost::result_of&lt;<classname>proto::make</classname>&lt;O&gt;(Expr, State, Data)&gt;::type</computeroutput>
and let <computeroutput>T'</computeroutput> be <computeroutput>O'(A<subscript>0</subscript>,…A<subscript>n</subscript>)</computeroutput>.
</para>
</listitem>
<listitem>
<para>
If <computeroutput>T</computeroutput> if of the form
<computeroutput>O(A<subscript>0</subscript>,…A<subscript>n</subscript> ...)</computeroutput>, then let <computeroutput>O'</computeroutput>
be <computeroutput>boost::result_of&lt;<classname>proto::make</classname>&lt;O&gt;(Expr, State, Data)&gt;::type</computeroutput>
and let <computeroutput>T'</computeroutput> be <computeroutput>O'(A<subscript>0</subscript>,…A<subscript>n</subscript> ...)</computeroutput>.
</para>
</listitem>
<listitem>
<para>
Otherwise, let <computeroutput>T'</computeroutput>
be <computeroutput>boost::result_of&lt;<classname>proto::make</classname>&lt;T&gt;(Expr, State, Data)&gt;::type</computeroutput>.
</para>
</listitem>
</itemizedlist>
</para>
</description>
<returns>
<para>
<computeroutput>
<classname>proto::call</classname>&lt;T'&gt;()(expr, state, data)
</computeroutput>
</para>
</returns>
</method>
</method-group>
</struct>
</struct>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,362 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/transform/make.hpp">
<para>
Contains definition of the
<computeroutput>
<classname alt="boost::proto::make">proto::make&lt;&gt;</classname>
</computeroutput>
and
<computeroutput>
<classname alt="boost::proto::protect">proto::protect&lt;&gt;</classname>
</computeroutput>
transforms.
</para>
<namespace name="boost">
<namespace name="proto">
<struct name="noinvoke">
<template>
<template-type-parameter name="T"/>
</template>
<purpose>A type annotation in an <conceptname>ObjectTransform</conceptname> which instructs
Proto not to look for a nested <computeroutput>::type</computeroutput> within
<computeroutput>T</computeroutput> after type substitution.</purpose>
<description>
<para>
<conceptname>ObjectTransform</conceptname>s are evaluated by
<computeroutput><classname alt="proto::make">proto::make&lt;&gt;</classname></computeroutput>,
which finds all nested transforms and replaces them with the result of their applications.
If any substitutions are performed, the result is first assumed to be a metafunction to be applied;
that is, Proto checks to see if the result has a nested <computeroutput>::type</computeroutput>
typedef. If it does, that becomes the result. The purpose of <computeroutput>proto::noinvoke&lt;&gt;</computeroutput>
is to prevent Proto from looking for a nested <computeroutput>::type</computeroutput> typedef
in these situations.
</para>
<para>
Example:
<programlisting>struct Test
: <classname>proto::when</classname>&lt;
<classname>_</classname>
, proto::noinvoke&lt;
// This remove_pointer invocation is bloked by noinvoke
boost::remove_pointer&lt;
// This add_pointer invocation is *not* blocked by noinvoke
boost::add_pointer&lt;<classname>_</classname>&gt;
&gt;
&gt;()
&gt;
{};
void test_noinvoke()
{
typedef <classname>proto::terminal</classname>&lt;int&gt;::type Int;
BOOST_MPL_ASSERT((
boost::is_same&lt;
boost::result_of&lt;Test(Int)&gt;::type
, boost::remove_pointer&lt;Int *&gt;
&gt;
));
Int i = {42};
boost::remove_pointer&lt;Int *&gt; t = Test()(i);
}</programlisting>
</para>
</description>
</struct>
<struct name="protect">
<template>
<template-type-parameter name="PrimitiveTransform"/>
</template>
<inherit><classname>proto::transform</classname>&lt; protect&lt;PrimitiveTransform&gt; &gt;</inherit>
<purpose>A <conceptname>PrimitiveTransform</conceptname> which prevents another
<conceptname>PrimitiveTransform</conceptname> from being applied in an
<conceptname>ObjectTransform</conceptname>.</purpose>
<description>
<para>
When building higher order transforms with
<computeroutput>
<classname alt="proto::make">proto::make&lt;&gt;</classname>
</computeroutput> or
<computeroutput>
<classname alt="proto::lazy">proto::lazy&lt;&gt;</classname>
</computeroutput>,
you sometimes would like to build types that are parameterized with Proto transforms. In such
lambda-style transforms, Proto will unhelpfully find all nested transforms and apply them, even
if you don't want them to be applied. Consider the following transform, which will replace the
<computeroutput>proto::_</computeroutput> in
<computeroutput>Bar&lt;proto::_&gt;()</computeroutput>
with <computeroutput>proto::terminal&lt;int&gt;::type</computeroutput>:
</para>
<para>
<programlisting>template&lt;typename T&gt;
struct Bar
{};
struct Foo :
<classname>proto::when</classname>&lt;<classname>proto::_</classname>, Bar&lt;<classname>proto::_</classname>&gt;() &gt;
{};
<classname>proto::terminal</classname>&lt;int&gt;::type i = {0};
int main() {
Foo()(i);
std::cout &lt;&lt; typeid(Foo()(i)).name() &lt;&lt; std::endl;
}</programlisting>
</para>
<para>
If you actually wanted to default-construct an object of type
<computeroutput>Bar&lt;proto::_&gt;</computeroutput>, you would have to protect the
<computeroutput>_</computeroutput> to prevent it from being applied. You can
use <computeroutput>proto::protect&lt;&gt;</computeroutput> as follows:
</para>
<para>
<programlisting>// OK: replace anything with Bar&lt;_&gt;()
struct Foo :
<classname>proto::when</classname>&lt;<classname>proto::_</classname>, Bar&lt;<classname>proto::protect</classname>&lt;<classname>proto::_</classname>&gt; &gt;() &gt;
{};</programlisting>
</para>
</description>
<struct name="impl">
<template>
<template-type-parameter name=""/>
<template-type-parameter name=""/>
<template-type-parameter name=""/>
</template>
<typedef name="result_type">
<type>PrimitiveTransform</type>
</typedef>
</struct>
</struct>
<struct name="make">
<template>
<template-type-parameter name="T"/>
</template>
<inherit><classname>proto::transform</classname>&lt; make&lt;T&gt; &gt;</inherit>
<purpose>A <conceptname>PrimitiveTransform</conceptname> that computes a type by evaluating
any nested transforms and then constructs an object of that type. </purpose>
<description>
<para>
The purpose of <computeroutput>proto::make&lt;&gt;</computeroutput> is to annotate a transform as
an <conceptname>ObjectTransform</conceptname> so that
<computeroutput><classname alt="proto::when">proto::when&lt;&gt;</classname></computeroutput> knows
how to apply it.
</para>
<para>
For the full description of the behavior of the
<computeroutput><classname alt="proto::make">proto::make&lt;&gt;</classname></computeroutput>
transform, see the documentation for the nested
<computeroutput><classname alt="proto::make::impl">proto::make::impl&lt;&gt;</classname></computeroutput>
class template.
</para>
</description>
<struct name="impl">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="State"/>
<template-type-parameter name="Data"/>
</template>
<inherit><classname>proto::transform_impl</classname>&lt; Expr, State, Data &gt;</inherit>
<typedef name="result_type">
<type><emphasis>see-below</emphasis></type>
<description>
<para>
<computeroutput><classname>proto::make</classname>&lt;T&gt;::impl&lt;Expr, State, Data&gt;::result_type</computeroutput> is
computed as follows:
</para>
<para>
If <computeroutput>T</computeroutput> is an <conceptname>ObjectTransform</conceptname> of the form
<computeroutput>Object(A<subscript>0</subscript>,…A<subscript>n</subscript>)</computeroutput> or
<computeroutput>Object(A<subscript>0</subscript>,…A<subscript>n</subscript> ...)</computeroutput>,
then let <computeroutput>O</computeroutput> be the return type
<computeroutput>Object</computeroutput>. Otherwise, let <computeroutput>O</computeroutput>
be <computeroutput>T</computeroutput>. The <computeroutput>result_type</computeroutput> typedef is
then computed as follows:
</para>
<para>
<itemizedlist>
<listitem>
<para>
If <computeroutput><classname>proto::is_transform</classname>&lt;O&gt;::value</computeroutput> is
<computeroutput>true</computeroutput>, then let the result type be
<computeroutput>
boost::result_of&lt;<classname>proto::when</classname>&lt;<classname>_</classname>, O&gt;(Expr, State, Data)&gt;::type
</computeroutput>.
Note that a substitution took place.
</para>
</listitem>
<listitem>
If <computeroutput>O</computeroutput> is a template like
<computeroutput><classname>proto::noinvoke</classname>&lt;S&lt;X<subscript>0</subscript>,…X<subscript>n</subscript>&gt; &gt;</computeroutput>,
then the result type is calculated as follows:
<itemizedlist>
<listitem>
<para>
For each <computeroutput>i</computeroutput> in
<computeroutput>[0,n]</computeroutput>, let <computeroutput>
X<subscript>i</subscript>'
</computeroutput> be
<computeroutput>
boost::result_of&lt;<classname>proto::make</classname>&lt;X<subscript>i</subscript>&gt;(Expr, State, Data)&gt;::type
</computeroutput>
(which evaluates this procedure recursively). Note that a substitution took place. (In this case,
Proto merely assumes that a substitution took place for the sake of compile-time efficiency. There
would be no reason to use <computeroutput><classname>proto::noinvoke&lt;&gt;</classname></computeroutput>
otherwise.)
</para>
</listitem>
<listitem>
<para>
The result type is
<computeroutput>
S&lt;X<subscript>0</subscript>',…X<subscript>n</subscript>'&gt;
</computeroutput>.
</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
If <computeroutput>O</computeroutput> is a template like
<computeroutput>S&lt;X<subscript>0</subscript>,…X<subscript>n</subscript>&gt;</computeroutput>,
then the result type is calculated as follows:
<itemizedlist>
<listitem>
<para>
For each <computeroutput>i</computeroutput> in
<computeroutput>[0,n]</computeroutput>, let <computeroutput>
X<subscript>i</subscript>'
</computeroutput> be
<computeroutput>
boost::result_of&lt;<classname>proto::make</classname>&lt;X<subscript>i</subscript>&gt;(Expr, State, Data)&gt;::type
</computeroutput>
(which evaluates this procedure recursively). Note whether any substitutions took place during
this operation.
</para>
</listitem>
<listitem>
<para>
If any substitutions took place in the above step and
<computeroutput>
S&lt;X<subscript>0</subscript>',…X<subscript>n</subscript>'&gt;
</computeroutput> has a nested
<computeroutput>type</computeroutput> typedef, the result type is
<computeroutput>
S&lt;X<subscript>0</subscript>',…X<subscript>n</subscript>'&gt;::type
</computeroutput>.
</para>
</listitem>
<listitem>
<para>
Otherwise, the result type is
<computeroutput>
S&lt;X<subscript>0</subscript>',…X<subscript>n</subscript>'&gt;
</computeroutput>.
</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
Otherwise, the result type is <computeroutput>O</computeroutput>, and note that no
substitution took place.
</listitem>
</itemizedlist>
</para>
<para>
Note that <computeroutput><classname alt="proto::when">proto::when&lt;&gt;</classname></computeroutput> is implemented
in terms of <computeroutput><classname alt="proto::call">proto::call&lt;&gt;</classname></computeroutput>
and <computeroutput><classname alt="proto::make">proto::make&lt;&gt;</classname></computeroutput>, so the
above procedure is evaluated recursively.
</para>
</description>
</typedef>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>result_type</type>
<parameter name="expr">
<paramtype>typename impl::expr_param</paramtype>
</parameter>
<parameter name="state">
<paramtype>typename impl::state_param</paramtype>
</parameter>
<parameter name="data">
<paramtype>typename impl::data_param</paramtype>
</parameter>
<description>
<para>
<computeroutput>
<classname>proto::make</classname>&lt;T&gt;::impl&lt;Expr,State,Data&gt;::operator()
</computeroutput>
behaves as follows:
</para>
<para>
<itemizedlist>
<listitem>
<para>
If <computeroutput>T</computeroutput> is of the form
<computeroutput>O(A<subscript>0</subscript>,…A<subscript>n</subscript>)</computeroutput>, then:
</para>
<itemizedlist>
<listitem>
<para>
If <computeroutput>
<classname>proto::is_aggregate</classname>&lt;result_type&gt;::value
</computeroutput> is <computeroutput>true</computeroutput>, then construct
and return an object <computeroutput>that</computeroutput> as follows:
<programlisting>result_type that = {
<classname>proto::when</classname>&lt;<classname>_</classname>, A<subscript>0</subscript>&gt;()(expr, state, data),
<classname>proto::when</classname>&lt;<classname>_</classname>, A<subscript>n</subscript>&gt;()(expr, state, data)
};</programlisting>
</para>
</listitem>
<listitem>
<para>
Otherwise, construct
and return an object <computeroutput>that</computeroutput> as follows:
<programlisting>result_type that(
<classname>proto::when</classname>&lt;<classname>_</classname>, A<subscript>0</subscript>&gt;()(expr, state, data),
<classname>proto::when</classname>&lt;<classname>_</classname>, A<subscript>n</subscript>&gt;()(expr, state, data)
);</programlisting>
</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>
If <computeroutput>T</computeroutput> is of the form
<computeroutput>O(A<subscript>0</subscript>,…A<subscript>n</subscript> ...)</computeroutput>,
then let <computeroutput>T&apos;</computeroutput> be <computeroutput>O(A<subscript>0</subscript>,…A<subscript>n-1</subscript>, <replaceable>S</replaceable>)</computeroutput>,
where <replaceable>S</replaceable> is a type sequence computed from the unpacking expression <computeroutput>A<subscript>n</subscript></computeroutput>
as described in the reference for <computeroutput><classname>proto::pack</classname></computeroutput>. Then, return:
<programlisting>proto::make&lt;T&apos;&gt;()(expr, state, data)</programlisting>
</para>
</listitem>
<listitem>
<para>
Otherwise, construct and return an object <computeroutput>that</computeroutput>
as follows: <programlisting>result_type that = result_type();</programlisting>
</para>
</listitem>
</itemizedlist>
</para>
</description>
</method>
</method-group>
</struct>
</struct>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,189 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/transform/pass_through.hpp">
<para>Definition of the
<computeroutput><classname alt="boost::proto::pass_through">proto::pass_through&lt;&gt;</classname></computeroutput>
transform, which is the default transform of all of the expression generator metafunctions such as
<computeroutput><classname alt="boost::proto::unary_plus">proto::unary_plus&lt;&gt;</classname></computeroutput>,
<computeroutput><classname alt="boost::proto::plus">proto::plus&lt;&gt;</classname></computeroutput> and
<computeroutput><classname alt="boost::proto::nary_expr">proto::nary_expr&lt;&gt;</classname></computeroutput>.</para>
<namespace name="boost">
<namespace name="proto">
<struct name="pass_through">
<template>
<template-type-parameter name="Grammar"/>
<template-type-parameter name="Domain">
<default><classname>proto::deduce_domain</classname></default>
</template-type-parameter>
</template>
<inherit><type><classname>proto::transform</classname>&lt; pass_through&lt;Grammar, Domain&gt; &gt;</type></inherit>
<purpose>A <conceptname>PrimitiveTransform</conceptname> that transforms the child expressions of an expression
node according to the corresponding children of a Grammar. The resulting expression is in the specified domain.</purpose>
<description>
<para>
Given a Grammar such as <computeroutput><classname>proto::plus</classname>&lt;T0, T1&gt;</computeroutput>,
an expression type that matches the grammar such as
<computeroutput><classname>proto::plus</classname>&lt;E0, E1&gt;::type</computeroutput>, a state
<computeroutput>S</computeroutput> and a data <computeroutput>D</computeroutput>, the result of applying
the <computeroutput>proto::pass_through&lt;<classname>proto::plus</classname>&lt;T0, T1&gt; &gt;</computeroutput>
transform is: <programlisting><classname>proto::plus</classname>&lt;
boost::result_of&lt;T0(E0, S, D)&gt;::type,
boost::result_of&lt;T1(E1, S, D)&gt;::type
&gt;::type</programlisting>
</para>
<para>
The above demonstrates how child transforms and child expressions are applied pairwise, and how the
results are reassembled into a new expression node with the same tag type as the original.
</para>
<para>
The <code>Domain</code> template parameter determines which domain the resulting expression should
be in. If it is <code><classname>proto::deduce_domain</classname></code>, which is the default,
the resulting expression is in the same domain as the expression passed in. Otherwise, the resulting
expression is in the specified domain. Practically, that means the specified domain's generator is
used to post-process the resulting expression.
</para>
<para>
The explicit use of <computeroutput>proto::pass_through&lt;&gt;</computeroutput> is not usually
needed, since the expression generator metafunctions such as
<computeroutput><classname>proto::plus</classname>&lt;&gt;</computeroutput> have
<computeroutput>proto::pass_through&lt;&gt;</computeroutput> as their default transform. So,
for instance, these are equivalent:
<itemizedlist>
<listitem>
<computeroutput>
<classname>proto::when</classname>&lt; <classname>proto::plus</classname>&lt;X, Y&gt;, proto::pass_through&lt; <classname>proto::plus</classname>&lt;X, Y&gt; &gt; &gt;
</computeroutput>
</listitem>
<listitem>
<computeroutput>
<classname>proto::when</classname>&lt; <classname>proto::plus</classname>&lt;X, Y&gt;, <classname>proto::plus</classname>&lt;X, Y&gt; &gt;
</computeroutput>
</listitem>
<listitem>
<computeroutput>
<classname>proto::when</classname>&lt; <classname>proto::plus</classname>&lt;X, Y&gt; &gt; // because of proto::when&lt;class X, class Y=X&gt;
</computeroutput>
</listitem>
<listitem>
<computeroutput>
<classname>proto::plus</classname>&lt;X, Y&gt; // because plus&lt;&gt; is both a grammar and a transform
</computeroutput>
</listitem>
</itemizedlist>
</para>
<para>
For example, consider the following transform that promotes all
<computeroutput>float</computeroutput> terminals in an expression to
<computeroutput>double</computeroutput>.
<programlisting>// This transform finds all float terminals in an expression and promotes
// them to doubles.
struct Promote :
<classname>proto::or_</classname>&lt;
<classname>proto::when</classname>&lt;<classname>proto::terminal</classname>&lt;float&gt;, <classname>proto::terminal</classname>&lt;double&gt;::type(<classname>proto::_value</classname>) &gt;,
// terminal&lt;&gt;'s default transform is a no-op:
<classname>proto::terminal</classname>&lt;<classname>proto::_</classname>&gt;,
// nary_expr&lt;&gt; has a pass_through&lt;&gt; transform:
<classname>proto::nary_expr</classname>&lt;<classname>proto::_</classname>, <classname>proto::vararg</classname>&lt;Promote&gt; &gt;
&gt;
{};</programlisting>
</para>
</description>
<struct name="impl">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="State"/>
<template-type-parameter name="Data"/>
</template>
<inherit><type><classname>proto::transform_impl</classname>&lt;Expr, State, Data&gt;</type></inherit>
<typedef name="GN">
<purpose>For each N in [0,Expr arity), for exposition only</purpose>
<type>typename proto::result_of::child_c&lt;Grammar, N&gt;::type</type>
</typedef>
<typedef name="EN">
<purpose>For each N in [0,Expr arity), for exposition only</purpose>
<type>typename proto::result_of::child_c&lt;Expr, N&gt;::type</type>
</typedef>
<typedef name="RN">
<purpose>For each N in [0,Expr arity), for exposition only</purpose>
<type>typename boost::result_of&lt;GN(EN,State,Data)&gt;::type</type>
</typedef>
<typedef name="T">
<purpose>For exposition only</purpose>
<type>typename Expr::proto_tag</type>
</typedef>
<typedef name="Deduce">
<purpose>For exposition only</purpose>
<type>boost::is_same&lt;Domain, <classname>deduce_domain</classname>&gt;</type>
</typedef>
<typedef name="DD">
<purpose>For exposition only</purpose>
<type>typename Expr::proto_domain</type>
</typedef>
<typedef name="D">
<purpose>For exposition only</purpose>
<type>typename mpl::if_&lt;Deduce, DD, Domain&gt;::type</type>
</typedef>
<typedef name="G">
<purpose>For exposition only</purpose>
<type>typename D::proto_generator</type>
</typedef>
<typedef name="A">
<purpose>For exposition only</purpose>
<type><classname>proto::listN</classname>&lt;R0,...RN&gt;</type>
</typedef>
<typedef name="E">
<purpose>For exposition only</purpose>
<type><classname>proto::expr</classname>&lt;T, A&gt;</type>
</typedef>
<typedef name="BE">
<purpose>For exposition only</purpose>
<type><classname>proto::basic_expr</classname>&lt;T, A&gt;</type>
</typedef>
<typedef name="expr_type">
<purpose>For exposition only</purpose>
<type>typename mpl::if_&lt;<classname>proto::wants_basic_expr</classname>&lt;G&gt;, BE, E&gt;::type</type>
</typedef>
<typedef name="result_type">
<type>typename boost::result_of&lt;D(expr_type)&gt;::type</type>
</typedef>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>result_type</type>
<parameter name="expr">
<paramtype>typename impl::expr_param</paramtype>
</parameter>
<parameter name="state">
<paramtype>typename impl::state_param</paramtype>
</parameter>
<parameter name="data">
<paramtype>typename impl::data_param</paramtype>
</parameter>
<requires>
<para>
<computeroutput>
<classname>proto::matches</classname>&lt;Expr, Grammar&gt;::value
</computeroutput> is <computeroutput>true</computeroutput>.
</para>
</requires>
<returns>
<para>
<programlisting>D()(expr_type::make(
G0()(<functionname>proto::child_c</functionname>&lt;0&gt;(expr), state, data),
...
GN()(<functionname>proto::child_c</functionname>&lt;N&gt;(expr), state, data)
))</programlisting>
</para>
</returns>
</method>
</method-group>
</struct>
</struct>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,545 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Eric Niebler
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)
-->
<header name="boost/proto/transform/when.hpp">
<para>
Definition of the
<computeroutput>
<classname alt="boost::proto::when">proto::when&lt;&gt;</classname>
</computeroutput> and
<computeroutput>
<classname alt="boost::proto::otherwise">proto::otherwise&lt;&gt;</classname>
</computeroutput> transforms.
</para>
<namespace name="boost">
<namespace name="proto">
<!-- struct transforms_type -->
<struct name="transforms_type">
<purpose>
The type used to define the global <code><globalname>proto::transforms</globalname></code>,
a key for use when creating and accessing a slot in a transform environment for
a set of external transforms.
</purpose>
<description>
<para>
The <code>proto::transforms_type</code> type, along with the <code><globalname>proto::transforms</globalname></code>
global, are declared using the <code><macroname>BOOST_PROTO_DEFINE_ENV_VAR</macroname>()</code> macro.
</para>
</description>
<method-group name="public member functions">
<overloaded-method name="operator=">
<signature cv="const">
<template>
<template-type-parameter name="Value"/>
</template>
<type><classname>env</classname>&lt;transforms_type, <replaceable>see-below</replaceable>&gt;</type>
<parameter name="value">
<paramtype>Value &amp;</paramtype>
</parameter>
</signature>
<signature cv="const">
<template>
<template-type-parameter name="Value"/>
</template>
<type><classname>env</classname>&lt;transforms_type, <replaceable>see-below</replaceable>&gt;</type>
<parameter name="value">
<paramtype>Value const &amp;</paramtype>
</parameter>
</signature>
<description>
<para>
If <code>Value</code> is a specialization <code>boost::reference_wrapper&lt;T&gt;</code>,
this function returns <code><classname>env</classname>&lt;transforms_type, T &amp;&gt;(value.get())</code>.
</para>
<para>
Else, if the type <code>Value</code> is non-copyable (i.e., a function, an array, abstract, or an ostream),
this function returns <code><classname>env</classname>&lt;transforms_type, Value <replaceable>cv</replaceable> &amp;&gt;(value)</code>,
where <code><replaceable>cv</replaceable></code> is <code>const</code> for the second overload, and empty
for the first.
</para>
<para>
Otherwise, this function returns <code><classname>env</classname>&lt;transforms_type, Value&gt;(value)</code>.
</para>
</description>
</overloaded-method>
</method-group>
</struct>
<data-member name="transforms">
<description>
<para>
A key key for use when creating and accessing a slot in a transform environment for
a set of external transforms.
</para>
</description>
<type><classname>proto::transforms_type</classname> const</type>
</data-member>
<struct name="when">
<template>
<template-type-parameter name="Grammar"/>
<template-type-parameter name="PrimitiveTransform">
<default>Grammar</default>
</template-type-parameter>
</template>
<purpose>A grammar element and a <conceptname>PrimitiveTransform</conceptname> that associates
a transform with the grammar.</purpose>
<description>
<para>
Use <computeroutput>proto::when&lt;&gt;</computeroutput> to override a grammar's default
transform with a custom transform. It is for used when composing larger transforms by
associating smaller transforms with individual rules in your grammar, as in the following
transform which counts the number of terminals in an expression.
<programlisting>// Count the terminals in an expression tree.
// Must be invoked with initial state == mpl::int_&lt;0&gt;().
struct CountLeaves :
<classname>proto::or_</classname>&lt;
proto::when&lt;<classname>proto::terminal</classname>&lt;<classname>proto::_</classname>&gt;, mpl::next&lt;<classname>proto::_state</classname>&gt;()&gt;,
proto::otherwise&lt;<classname>proto::fold</classname>&lt;<classname>proto::_</classname>, <classname>proto::_state</classname>, CountLeaves&gt; &gt;
&gt;
{};</programlisting>
</para>
<para>
In <computeroutput>proto::when&lt;G, T&gt;</computeroutput>, when <computeroutput>T</computeroutput>
is a class type it is a <conceptname>PrimitiveTransform</conceptname> and the following equivalencies hold:
</para>
<itemizedlist>
<listitem>
<para>
<computeroutput>boost::result_of&lt;proto::when&lt;G,T&gt;(E,S,V)&gt;::type</computeroutput> is the same as
<computeroutput>boost::result_of&lt;T(E,S,V)&gt;::type</computeroutput>.
</para>
</listitem>
<listitem>
<para>
<computeroutput>proto::when&lt;G,T&gt;()(e,s,d)</computeroutput> is the same as
<computeroutput>T()(e,s,d)</computeroutput>.
</para>
</listitem>
</itemizedlist>
</description>
<inherit><type>PrimitiveTransform</type></inherit>
<typedef name="proto_grammar">
<type>typename Grammar::proto_grammar</type>
</typedef>
</struct>
<struct-specialization name="when">
<template>
<template-type-parameter name="Grammar"/>
<template-type-parameter name="Fun"/>
</template>
<specialization>
<template-arg>Grammar</template-arg>
<template-arg>Fun *</template-arg>
</specialization>
<inherit><type><classname>proto::when</classname>&lt; Grammar, Fun &gt;</type></inherit>
<purpose>A specialization that treats function pointer <conceptname>Transform</conceptname>s as if they
were function type <conceptname>Transform</conceptname>s.</purpose>
<description>
<para>
This specialization requires that <computeroutput>Fun</computeroutput> is actually a function type.
</para>
<para>
This specialization is required for nested transforms such as
<computeroutput>proto::when&lt;G, T0(T1(_))&gt;</computeroutput>. In C++, functions that are used
as parameters to other functions automatically decay to funtion pointer types. In other words, the
type <computeroutput>T0(T1(_))</computeroutput> is indistinguishable from
<computeroutput>T0(T1(*)(_))</computeroutput>. This specialization is required to handle these
nested function pointer type transforms properly.
</para>
</description>
</struct-specialization>
<struct-specialization name="when">
<template>
<template-type-parameter name="Grammar"/>
<template-type-parameter name="R"/>
<template-type-parameter name="A" pack="1"/>
</template>
<specialization>
<template-arg>Grammar</template-arg>
<template-arg>R(A...)</template-arg>
</specialization>
<inherit><type><classname>proto::transform</classname>&lt; when&lt;Grammar, R(A...)&gt; &gt;</type></inherit>
<purpose>A grammar element and a <conceptname>Transform</conceptname> that associates a
transform with the grammar. </purpose>
<description>
<para>
Use <computeroutput>proto::when&lt;&gt;</computeroutput> to override a grammar's default
transform with a custom transform. It is for use when composing larger transforms by associating
smaller transforms with individual rules in your grammar.
</para>
<para>
The <computeroutput>when&lt;G, R(A...)&gt;</computeroutput> form accepts either a
<conceptname>CallableTransform</conceptname> or an <conceptname>ObjectTransform</conceptname> as its
second parameter. <computeroutput>proto::when&lt;&gt;</computeroutput> uses
<computeroutput><classname>proto::is_callable</classname>&lt;R&gt;::value</computeroutput> to
distinguish between the two, and uses
<computeroutput><classname>proto::call&lt;&gt;</classname></computeroutput> to evaluate
<conceptname>CallableTransform</conceptname>s and
<computeroutput><classname>proto::make&lt;&gt;</classname></computeroutput> to evaluate
<conceptname>ObjectTransform</conceptname>s.
</para>
</description>
<struct name="impl">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="State"/>
<template-type-parameter name="Data"/>
</template>
<inherit><type><classname>proto::transform_impl</classname>&lt; Expr, State, Data &gt;</type></inherit>
<typedef name="call_">
<purpose>For exposition only</purpose>
<type><classname>proto::call</classname>&lt;R(A...)&gt;</type>
</typedef>
<typedef name="make_">
<purpose>For exposition only</purpose>
<type><classname>proto::make</classname>&lt;R(A...)&gt;</type>
</typedef>
<typedef name="which">
<purpose>For exposition only</purpose>
<type>typename mpl::if_&lt;<classname>proto::is_callable</classname>&lt;R&gt;,call_,make_&gt;::type</type>
</typedef>
<typedef name="result_type">
<type>typename boost::result_of&lt;which(Expr, State, Data)&gt;::type</type>
</typedef>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>result_type</type>
<parameter name="expr">
<paramtype>typename impl::expr_param</paramtype>
<description>
<para>The current expression </para>
</description>
</parameter>
<parameter name="state">
<paramtype>typename impl::state_param</paramtype>
<description>
<para>The current state </para>
</description>
</parameter>
<parameter name="data">
<paramtype>typename impl::data_param</paramtype>
<description>
<para>An arbitrary data </para>
</description>
</parameter>
<description>
<para>
Evaluate <computeroutput>R(A...)</computeroutput> as a transform either with
<computeroutput><classname>proto::call&lt;&gt;</classname></computeroutput> or with
<computeroutput><classname>proto::make&lt;&gt;</classname></computeroutput> depending
on whether <computeroutput><classname>proto::is_callable</classname>&lt;R&gt;::value</computeroutput>
is <computeroutput>true</computeroutput> or <computeroutput>false</computeroutput>.
</para>
</description>
<requires>
<para>
<computeroutput><classname>proto::matches</classname>&lt;Expr, Grammar&gt;::value</computeroutput>
is <computeroutput>true</computeroutput>.
</para>
</requires>
<returns>
<para>
<computeroutput>which()(expr, state, data)</computeroutput>
</para>
</returns>
</method>
</method-group>
</struct>
<typedef name="proto_grammar">
<type>typename Grammar::proto_grammar</type>
</typedef>
</struct-specialization>
<struct-specialization name="when">
<template>
<template-type-parameter name="Grammar"/>
<template-type-parameter name="R"/>
<template-type-parameter name="A" pack="1"/>
</template>
<specialization>
<template-arg>Grammar</template-arg>
<template-arg>R(A..., ...)</template-arg>
</specialization>
<inherit><type><classname>proto::transform</classname>&lt; when&lt;Grammar, R(A..., ...)&gt; &gt;</type></inherit>
<purpose>A grammar element and a <conceptname>Transform</conceptname> that associates a
transform with the grammar. </purpose>
<description>
<para>
Use <computeroutput>proto::when&lt;&gt;</computeroutput> to override a grammar's default
transform with a custom transform. It is for use when composing larger transforms by associating
smaller transforms with individual rules in your grammar.
</para>
<para>
The <computeroutput>when&lt;G, R(A..., ...)&gt;</computeroutput> form accepts either a
<conceptname>CallableTransform</conceptname> or an <conceptname>ObjectTransform</conceptname> as its
second parameter. <computeroutput>proto::when&lt;&gt;</computeroutput> uses
<computeroutput><classname>proto::is_callable</classname>&lt;R&gt;::value</computeroutput> to
distinguish between the two, and uses
<computeroutput><classname>proto::call&lt;&gt;</classname></computeroutput> to evaluate
<conceptname>CallableTransform</conceptname>s and
<computeroutput><classname>proto::make&lt;&gt;</classname></computeroutput> to evaluate
<conceptname>ObjectTransform</conceptname>s.
</para>
<para>
<emphasis role="bold">Note:</emphasis> In the specialization
<computeroutput>when&lt;G, R(A..., ...)&gt;</computeroutput>, the first ellipsis denotes a
C++11-style variadic template (which is emulated for C++98 compilers). The second ellipsis
is a C-style vararg.
</para>
</description>
<struct name="impl">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="State"/>
<template-type-parameter name="Data"/>
</template>
<inherit><type><classname>proto::transform_impl</classname>&lt; Expr, State, Data &gt;</type></inherit>
<typedef name="call_">
<purpose>For exposition only</purpose>
<type><classname>proto::call</classname>&lt;R(A..., ...)&gt;</type>
</typedef>
<typedef name="make_">
<purpose>For exposition only</purpose>
<type><classname>proto::make</classname>&lt;R(A..., ...)&gt;</type>
</typedef>
<typedef name="which">
<purpose>For exposition only</purpose>
<type>typename mpl::if_&lt;<classname>proto::is_callable</classname>&lt;R&gt;,call_,make_&gt;::type</type>
</typedef>
<typedef name="result_type">
<type>typename boost::result_of&lt;which(Expr, State, Data)&gt;::type</type>
</typedef>
<method-group name="public member functions">
<method name="operator()" cv="const">
<type>result_type</type>
<parameter name="expr">
<paramtype>typename impl::expr_param</paramtype>
<description>
<para>The current expression </para>
</description>
</parameter>
<parameter name="state">
<paramtype>typename impl::state_param</paramtype>
<description>
<para>The current state </para>
</description>
</parameter>
<parameter name="data">
<paramtype>typename impl::data_param</paramtype>
<description>
<para>An arbitrary data </para>
</description>
</parameter>
<description>
<para>
Evaluate <computeroutput>R(A..., ...)</computeroutput> as a transform either with
<computeroutput><classname>proto::call&lt;&gt;</classname></computeroutput> or with
<computeroutput><classname>proto::make&lt;&gt;</classname></computeroutput> depending
on whether <computeroutput><classname>proto::is_callable</classname>&lt;R&gt;::value</computeroutput>
is <computeroutput>true</computeroutput> or <computeroutput>false</computeroutput>.
</para>
</description>
<requires>
<para>
<computeroutput><classname>proto::matches</classname>&lt;Expr, Grammar&gt;::value</computeroutput>
is <computeroutput>true</computeroutput>.
</para>
</requires>
<returns>
<para>
<computeroutput>which()(expr, state, data)</computeroutput>
</para>
</returns>
</method>
</method-group>
</struct>
<typedef name="proto_grammar">
<type>typename Grammar::proto_grammar</type>
</typedef>
</struct-specialization>
<struct-specialization name="when">
<template>
<template-type-parameter name="Grammar"/>
</template>
<specialization>
<template-arg>Grammar</template-arg>
<template-arg><classname>proto::external_transform</classname></template-arg>
</specialization>
<inherit><type>
<classname>proto::transform</classname>&lt; when&lt;Grammar, <classname>proto::external_transform</classname>&gt; &gt;</type></inherit>
<purpose>A grammar element that associates an externally-specified transform with the grammar.
The transform is looked up in the Data parameter using the Grammar as a key.</purpose>
<description>
<para>
Use <computeroutput>proto::when&lt;&gt;</computeroutput> to override a grammar's default
transform with a custom transform. It is for use when composing larger transforms by associating
smaller transforms with individual rules in your grammar.
</para>
<para>
The <computeroutput>when&lt;G, <classname>proto::external_transform</classname>&gt;</computeroutput>
indicates that the associated transform is not yet known. It should be looked up when the transform
is about to be applied. It is found by looking it up in the passed-in Data parameter, which
behaves like a compile-time map from grammar types to transform types. The map is indexed using
<computeroutput>Grammar</computeroutput> as a key. The associated value type is used as the transform
to apply. In this way, the same grammar can be used to define multiple evaluating strategies that
can be added post-hoc.
</para>
<para>
See <computeroutput><classname>proto::external_transforms</classname></computeroutput> for an example.
</para>
</description>
<struct name="impl">
<template>
<template-type-parameter name="Expr"/>
<template-type-parameter name="State"/>
<template-type-parameter name="Data"/>
</template>
<inherit><type>
boost::remove_reference&lt;
typename mpl::eval_if_c&lt;
<classname>proto::result_of::has_env_var</classname>&lt;Data, <classname>proto::transforms_type</classname>&gt;::value,
<classname>proto::result_of::env_var</classname>&lt;Data, <classname>proto::transforms_type</classname>&gt;,
<classname>proto::result_of::env_var</classname>&lt;Data, <classname>proto::data_type</classname>&gt;
&gt;::type
&gt;::type
::template when&lt; Grammar &gt;
::template impl&lt; Expr, State, Data &gt;</type></inherit>
<description>
<para>
The implementation of the <code>impl</code> struct depends on whether the <code>Data</code>
parameter is a transform environment that contains a value corresponding to the
<classname>proto::transforms_type</classname> key. If so, that value is treated as a
map from rules to transforms. Otherwise, the <code>Data</code> type itself is treated
as such a map.
</para>
</description>
</struct>
<typedef name="proto_grammar">
<type>typename Grammar::proto_grammar</type>
</typedef>
</struct-specialization>
<struct name="otherwise">
<template>
<template-type-parameter name="Fun"/>
</template>
<inherit><type><classname>proto::when</classname>&lt; <classname>proto::_</classname>, Fun &gt;</type></inherit>
<purpose>
Syntactic sugar for <computeroutput><classname>proto::when</classname>&lt; <classname>proto::_</classname>, Fun &gt;</computeroutput>,
for use in grammars to handle all the cases not yet handled.
</purpose>
<description>
<para>
Use <computeroutput>proto::otherwise&lt;T&gt;</computeroutput> in your grammars as a synonym for
<computeroutput><classname>proto::when</classname>&lt; <classname>proto::_</classname>, Fun &gt;</computeroutput>
as in the following transform which counts the number of terminals in an expression.
</para>
<para>
<programlisting>// Count the terminals in an expression tree.
// Must be invoked with initial state == mpl::int_&lt;0&gt;().
struct CountLeaves :
<classname>proto::or_</classname>&lt;
proto::when&lt;<classname>proto::terminal</classname>&lt;<classname>proto::_</classname>&gt;, mpl::next&lt;<classname>proto::_state</classname>&gt;()&gt;,
proto::otherwise&lt;<classname>proto::fold</classname>&lt;<classname>proto::_</classname>, <classname>proto::_state</classname>, CountLeaves&gt; &gt;
&gt;
{};</programlisting>
</para>
</description>
</struct>
<struct name="external_transform">
<purpose>A placeholder for use as the second parameter for <computeroutput><classname>proto::when</classname></computeroutput>
to indicate that the rule's transform is specified externally.</purpose>
<description>
<para>
See <computeroutput><classname>proto::external_transforms</classname></computeroutput> for an example.
</para>
</description>
</struct>
<struct name="external_transforms">
<template>
<template-type-parameter name="When" pack="1"/>
</template>
<purpose>A map from grammars to transforms, used as a way to externally associate transforms.</purpose>
<typedef name="map_type">
<purpose>For exposition only.</purpose>
<type>mpl::map&lt; typename to_mpl_pair&lt; When &gt;::type... &gt;</type>
</typedef>
<struct name="when">
<template>
<template-type-parameter name="Grammar"/>
</template>
<inherit><type><classname>proto::otherwise</classname>&lt; typename mpl::at&lt; map_type, Grammar &gt;::type &gt;</type></inherit>
</struct>
<description>
<para>
It is sometimes desirable to define a grammar that can be customized with different sets of transforms.
To do that, where you would normally specify a transform within a grammar, you can instead put
<computeroutput><classname>proto::external_transform</classname></computeroutput>; for example:
<computeroutput>proto::when&lt; some_grammar, proto::external_transform &gt;</computeroutput>. Then, when
invoking the grammar, you can pass an approriately-defined instance of <computeroutput>proto::external_transforms</computeroutput>
as the Data parameter. When an expression matches <computeroutput>some_grammar</computeroutput>, Proto
will look up the approprite transform in the Data parameter using <computeroutput>some_grammar</computeroutput>
as a key.
</para>
<para>
<programlisting>struct int_terminal
: <classname>proto::terminal</classname>&lt;int&gt;
{};
struct char_terminal
: <classname>proto::terminal</classname>&lt;char&gt;
{};
struct my_grammar
: <classname>proto::or_</classname>&lt;
// The next two grammar rules are customization points.
// The associated transforms are specified externally
// using external_transforms below.
<classname>proto::when</classname>&lt; int_terminal, <classname>proto::external_transform</classname> &gt;
, <classname>proto::when</classname>&lt; char_terminal, <classname>proto::external_transform</classname> &gt;
, <classname>proto::when</classname>&lt;
<classname>proto::plus</classname>&lt; my_grammar, my_grammar &gt;
, <classname>proto::fold</classname>&lt; <classname>proto::_</classname>, int(), my_grammar &gt;
&gt;
&gt;
{};
// Here is where the transforms are associated with the
// grammar rules above.
struct my_transforms
: proto::external_transforms&lt;
<classname>proto::when</classname>&lt;int_terminal, print(<classname>proto::_value</classname>)&gt;
, <classname>proto::when</classname>&lt;char_terminal, print(<classname>proto::_value</classname>)&gt;
&gt;
{};
// ...
<classname>proto::literal</classname>&lt;int&gt; i(1);
<classname>proto::literal</classname>&lt;char&gt; c('a');
my_transforms trx;
// Evaluate "i+c" using my_grammar with the specified transforms:
my_grammar()(i + c, 0, trx);
// If you would also like to pass arbitrary data along with the
// transforms, you can use a transform environment, as so:
my_grammar()(i + c, 0, (proto::data = 42, proto::transforms = trx));</programlisting>
</para>
</description>
</struct>
</namespace>
</namespace>
</header>

View File

@@ -0,0 +1,172 @@
[/
/ Copyright (c) 2008-2012 Eric Niebler
/
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
/]
[section:release_notes Appendix A: Release Notes]
[/=================]
[heading Boost 1.51]
[/=================]
[*Unpacking Expressions]
In Boost 1.51, Proto got simple unpacking patterns. When working with Proto transforms, unpacking expressions are useful for unpacking the children of an expression into a function call or an object constructor, while optionally applying some transformations to each child in turn.
See the [link boost_proto.users_guide.back_end.expression_transformation.unpacking_expressions Unpacking Expressions] section for more information.
[/=================]
[heading Boost 1.44]
[/=================]
[*Behavior Change: proto::and_<>]
In Boost 1.44, the behavior of _and_ as a transform changed. Previously, it only applied the transform associated with the last grammar in the set. Now, it applies all the transforms but only returns the result of the last. That makes it behave like C++'s comma operator. For example, a grammar such as:
proto::and_< G0, G1, G2 >
when evaluated with an expression `e` now behaves like this:
((void)G0()(e), (void)G1()(e), G2()(e))
[note Why the void casts? It's to avoid argument-dependent lookup, which might find an overloaded comma operator.]
[*Behavior Change: proto::as_expr() and proto::as_child()]
The functions _as_expr_ and _as_child_ are used to guarantee that an object is a Proto expression by turning it into one if it is not already, using an optionally specified domain. In previous releases, when these functions were passed a Proto expression in a domain different to the one specified, they would apply the specified domain's generator, resulting in a twice-wrapped expression. This behavior was surprising to some users.
The new behavior of these two functions is to always leave Proto expressions alone, regardless of the expressions' domains.
[*Behavior Change: proto::(pod_)generator<> and proto::basic_expr<>]
Users familiar with Proto's extension mechanism have probably used either _generator_ or _pod_generator_ with a wrapper template when defining their domain. In the past, Proto would instantiate your wrapper template with instances of _expr_. In Boost 1.44, Proto now instantiates your wrapper template with instances of a new type: _basic_expr_.
For instance:
// An expression wrapper
template<class Expr>
struct my_expr_wrapper;
// A domain
struct my_domain
: proto::domain< proto::generator< my_expr_wrapper > >
{};
template<class Expr>
struct my_expr_wrapper
: proto::extends<Expr, my_expr_wrapper<Expr>, my_domain>
{
// Before 1.44, Expr was an instance of proto::expr<>
// In 1.44, Expr is an instance of proto::basic_expr<>
};
The motivation for this change was to improve compile times. _expr_ is an expensive type to instantiate because it defines a host of member functions. When defining your own expression wrapper, the instance of _expr_ sits as a hidden data member function in your wrapper and the members of _expr_ go unused. Therefore, the cost of those member functions is wasted. In contrast, _basic_expr_ is a very lightweight type with no member functions at all.
The vast majority of programs should recompile without any source changes. However, if somewhere you are assuming that you will be given instances specifically of _expr_, your code will break.
[*New Feature: Sub-domains]
In Boost 1.44, Proto introduces an important new feature called "sub-domains". This gives you a way to spcify that one domain is compatible with another such that expressions in one domain can be freely mixed with expressions in another. You can define one domain to be the sub-domain of another by using the third template parameter of _domain_.
For instance:
// Not shown: define some expression
// generators genA and genB
struct A
: proto::domain< genA, proto::_ >
{};
// Define a domain B that is the sub-domain
// of domain A.
struct B
: proto::domain< genB, proto::_, A >
{};
Expressions in domains `A` and `B` can have different wrappers (hence, different interfaces), but they can be combined into larger expressions. Without a sub-domain relationship, this would have been an error. The domain of the resulting expression in this case would be `A`.
The complete description of sub-domains can be found in the reference
sections for _domain_ and _deduce_domain_.
[*New Feature: Domain-specific as_expr() and as_child()]
Proto has always allowed users to customize expressions post-hoc by specifying a Generator when defining their domain. But it has never allowed users to control how Proto assembles sub-expressions in the first place. As of Boost 1.44, users now have this power.
Users defining their own domain can now specify how _as_expr_ and _as_child_ work in their domain. They can do this easily by defining nested class templates named `as_expr` and/or `as_child` within their domain class.
For example:
struct my_domain
: proto::domain< my_generator >
{
typedef
proto::domain< my_generator >
base_domain;
// For my_domain, as_child does the same as
// what as_expr does by default.
template<class T>
struct as_child
: base_domain::as_expr<T>
{};
};
In the above example, `my_domain::as_child<>` simply defers to `proto::domain::as_expr<>`. This has the nice effect of causing all terminals to be captured by value instead of by reference, and to likewise store child expressions by value. The result is that expressions in `my_domain` are safe to store in `auto` variables because they will not have dangling references to intermediate temporary expressions. (Naturally, it also means that expression construction has extra runtime overhead of copying that the compiler may or may not be able to optimize away.)
[/=================]
[heading Boost 1.43]
[/=================]
In Boost 1.43, the recommended usage of _extends_ changed slightly. The new
usage looks like this:
// my_expr is an expression extension of the Expr parameter
template<typename Expr>
struct my_expr
: proto::extends<Expr, my_expr<Expr>, my_domain>
{
my_expr(Expr const &expr = Expr())
: proto::extends<Expr, my_expr, my_domain>(expr)
{}
// NEW: use the following macro to bring
// proto::extends::operator= into scope.
BOOST_PROTO_EXTENDS_USING_ASSIGN(my_expr)
};
The new thing is the use of the [^[macroref BOOST_PROTO_EXTENDS_USING_ASSIGN]()] macro. To allow assignment operators to build expression trees, _extends_ overloads the assignment operator. However, for the `my_expr` template, the compiler generates a default copy assignment operator that hides the ones in _extends_. This is often not desired (although it depends on the syntax you want to allow).
Previously, the recommended usage was to do this:
// my_expr is an expression extension of the Expr parameter
template<typename Expr>
struct my_expr
: proto::extends<Expr, my_expr<Expr>, my_domain>
{
my_expr(Expr const &expr = Expr())
: proto::extends<Expr, my_expr, my_domain>(expr)
{}
// OLD: don't do it like this anymore.
using proto::extends<Expr, my_expr, my_domain>::operator=;
};
While this works in the majority of cases, it still doesn't suppress the implicit generation of the default assignment operator. As a result, expressions of the form `a = b` could either build an expression template or do a copy assignment depending on whether the types of `a` and `b` happen to be the same. That can lead to subtle bugs, so the behavior was changed.
The [^[macroref BOOST_PROTO_EXTENDS_USING_ASSIGN]()] brings into scope the assignment operators defined in _extends_ as well as suppresses the generation of the copy assignment operator.
Also note that the _literal_ class template, which uses _extends_, has been chaged to use [^[macroref BOOST_PROTO_EXTENDS_USING_ASSIGN]()]. The implications are highlighted in the sample code below:
proto::literal<int> a(1), b(2); // two non-const proto literals
proto::literal<int> const c(3); // a const proto literal
a = b; // No-op. Builds an expression tree and discards it.
// Same behavior in 1.42 and 1.43.
a = c; // CHANGE! In 1.42, this performed copy assignment, causing
// a's value to change to 3. In 1.43, the behavior is now
// the same as above: build and discard an expression tree.
[endsect]

View File

@@ -0,0 +1,45 @@
[/
/ Copyright (c) 2008 Eric Niebler
/
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
/]
[/=========================================]
[section:resources Background and Resources]
[/=========================================]
Proto was initially developed as part of _xpressive_ to simplify the job of
transforming an expression template into an executable finite state machine capable
of matching a regular expression. Since then, Proto has found application in the
redesigned and improved Spirit-2 and the related Karma library. As a result of
these efforts, Proto evolved into a generic and abstract grammar and tree
transformation framework applicable in a wide variety of EDSL scenarios.
The grammar and tree transformation framework is modeled on Spirit's grammar and
semantic action framework. The expression tree data structure is similar to Fusion
data structures in many respects, and is interoperable with Fusion's iterators and
algorithms.
The syntax for the grammar-matching features of `proto::matches<>` is inspired by
MPL's lambda expressions.
The idea for using function types for Proto's composite transforms is inspired by Aleksey Gurtovoy's
[@http://lists.boost.org/Archives/boost/2002/11/39718.php "round" lambda] notation.
[/=================]
[heading References]
[/=================]
[:[#boost_proto.users_guide.resources.SYB]Ren, D. and Erwig, M. 2006. A generic recursion toolbox for Haskell or: scrap your boilerplate systematically. In ['Proceedings of the 2006 ACM SIGPLAN Workshop on Haskell] (Portland, Oregon, USA, September 17 - 17, 2006). Haskell '06. ACM, New York, NY, 13-24. DOI=[@http://doi.acm.org/10.1145/1159842.1159845]]
[/======================]
[heading Further Reading]
[/======================]
A technical paper about an earlier version of Proto was accepted into the
[@http://lcsd.cs.tamu.edu/2007/ ACM SIGPLAN Symposium on Library-Centric Software
Design LCSD'07], and can be found at [@http://lcsd.cs.tamu.edu/2007/final/1/1_Paper.pdf].
The tree transforms described in that paper differ from what exists today.
[endsect]

View File

@@ -0,0 +1,87 @@
# (C) Copyright 2004: Eric Niebler
# 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)
exe hello
:
hello.cpp
;
exe calc1
:
calc1.cpp
;
exe calc2
:
calc2.cpp
;
exe calc3
:
calc3.cpp
;
exe lazy_vector
:
lazy_vector.cpp
;
exe tarray
:
tarray.cpp
;
exe rgb
:
rgb.cpp
;
exe vec3
:
vec3.cpp
;
exe vector
:
vector.cpp
;
exe mixed
:
mixed.cpp
;
exe futures
:
futures.cpp
;
exe map_assign
:
map_assign.cpp
;
exe mini_lambda
:
mini_lambda.cpp
;
exe virtual_member
:
virtual_member.cpp
;
exe external_transforms
:
external_transforms.cpp
;
exe lambda
:
lambda.cpp
:
<include>.
<toolset>clang:<cxxflags>-Wno-unused-local-typedef
;

View File

@@ -0,0 +1,68 @@
//[ Calc1
// Copyright 2008 Eric Niebler. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// This is a simple example of how to build an arithmetic expression
// evaluator with placeholders.
#include <iostream>
#include <boost/proto/core.hpp>
#include <boost/proto/context.hpp>
namespace proto = boost::proto;
using proto::_;
template<int I> struct placeholder {};
// Define some placeholders
proto::terminal< placeholder< 1 > >::type const _1 = {{}};
proto::terminal< placeholder< 2 > >::type const _2 = {{}};
// Define a calculator context, for evaluating arithmetic expressions
struct calculator_context
: proto::callable_context< calculator_context const >
{
// The values bound to the placeholders
double d[2];
// The result of evaluating arithmetic expressions
typedef double result_type;
explicit calculator_context(double d1 = 0., double d2 = 0.)
{
d[0] = d1;
d[1] = d2;
}
// Handle the evaluation of the placeholder terminals
template<int I>
double operator ()(proto::tag::terminal, placeholder<I>) const
{
return d[ I - 1 ];
}
};
template<typename Expr>
double evaluate( Expr const &expr, double d1 = 0., double d2 = 0. )
{
// Create a calculator context with d1 and d2 substituted for _1 and _2
calculator_context const ctx(d1, d2);
// Evaluate the calculator expression with the calculator_context
return proto::eval(expr, ctx);
}
int main()
{
// Displays "5"
std::cout << evaluate( _1 + 2.0, 3.0 ) << std::endl;
// Displays "6"
std::cout << evaluate( _1 * _2, 3.0, 2.0 ) << std::endl;
// Displays "0.5"
std::cout << evaluate( (_1 - _2) / _2, 3.0, 2.0 ) << std::endl;
return 0;
}
//]

View File

@@ -0,0 +1,103 @@
//[ Calc2
// Copyright 2008 Eric Niebler. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// This example enhances the simple arithmetic expression evaluator
// in calc1.cpp by using proto::extends to make arithmetic
// expressions immediately evaluable with operator (), a-la a
// function object
#include <iostream>
#include <boost/proto/core.hpp>
#include <boost/proto/context.hpp>
namespace proto = boost::proto;
using proto::_;
template<typename Expr>
struct calculator_expression;
// Tell proto how to generate expressions in the calculator_domain
struct calculator_domain
: proto::domain<proto::generator<calculator_expression> >
{};
// Will be used to define the placeholders _1 and _2
template<int I> struct placeholder {};
// Define a calculator context, for evaluating arithmetic expressions
// (This is as before, in calc1.cpp)
struct calculator_context
: proto::callable_context< calculator_context const >
{
// The values bound to the placeholders
double d[2];
// The result of evaluating arithmetic expressions
typedef double result_type;
explicit calculator_context(double d1 = 0., double d2 = 0.)
{
d[0] = d1;
d[1] = d2;
}
// Handle the evaluation of the placeholder terminals
template<int I>
double operator ()(proto::tag::terminal, placeholder<I>) const
{
return d[ I - 1 ];
}
};
// Wrap all calculator expressions in this type, which defines
// operator () to evaluate the expression.
template<typename Expr>
struct calculator_expression
: proto::extends<Expr, calculator_expression<Expr>, calculator_domain>
{
explicit calculator_expression(Expr const &expr = Expr())
: calculator_expression::proto_extends(expr)
{}
BOOST_PROTO_EXTENDS_USING_ASSIGN(calculator_expression<Expr>)
// Override operator () to evaluate the expression
double operator ()() const
{
calculator_context const ctx;
return proto::eval(*this, ctx);
}
double operator ()(double d1) const
{
calculator_context const ctx(d1);
return proto::eval(*this, ctx);
}
double operator ()(double d1, double d2) const
{
calculator_context const ctx(d1, d2);
return proto::eval(*this, ctx);
}
};
// Define some placeholders (notice they're wrapped in calculator_expression<>)
calculator_expression<proto::terminal< placeholder< 1 > >::type> const _1;
calculator_expression<proto::terminal< placeholder< 2 > >::type> const _2;
// Now, our arithmetic expressions are immediately executable function objects:
int main()
{
// Displays "5"
std::cout << (_1 + 2.0)( 3.0 ) << std::endl;
// Displays "6"
std::cout << ( _1 * _2 )( 3.0, 2.0 ) << std::endl;
// Displays "0.5"
std::cout << ( (_1 - _2) / _2 )( 3.0, 2.0 ) << std::endl;
return 0;
}
//]

View File

@@ -0,0 +1,154 @@
//[ Calc3
// Copyright 2008 Eric Niebler. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// This example enhances the arithmetic expression evaluator
// in calc2.cpp by using a proto transform to calculate the
// number of arguments an expression requires and using a
// compile-time assert to guarantee that the right number of
// arguments are actually specified.
#include <iostream>
#include <boost/mpl/int.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/min_max.hpp>
#include <boost/proto/core.hpp>
#include <boost/proto/context.hpp>
#include <boost/proto/transform.hpp>
namespace mpl = boost::mpl;
namespace proto = boost::proto;
using proto::_;
// Will be used to define the placeholders _1 and _2
template<typename I> struct placeholder : I {};
// This grammar basically says that a calculator expression is one of:
// - A placeholder terminal
// - Some other terminal
// - Some non-terminal whose children are calculator expressions
// In addition, it has transforms that say how to calculate the
// expression arity for each of the three cases.
struct CalculatorGrammar
: proto::or_<
// placeholders have a non-zero arity ...
proto::when< proto::terminal< placeholder<_> >, proto::_value >
// Any other terminals have arity 0 ...
, proto::when< proto::terminal<_>, mpl::int_<0>() >
// For any non-terminals, find the arity of the children and
// take the maximum. This is recursive.
, proto::when< proto::nary_expr<_, proto::vararg<_> >
, proto::fold<_, mpl::int_<0>(), mpl::max<CalculatorGrammar, proto::_state>() > >
>
{};
// Simple wrapper for calculating a calculator expression's arity.
// It specifies mpl::int_<0> as the initial state. The data, which
// is not used, is mpl::void_.
template<typename Expr>
struct calculator_arity
: boost::result_of<CalculatorGrammar(Expr)>
{};
template<typename Expr>
struct calculator_expression;
// Tell proto how to generate expressions in the calculator_domain
struct calculator_domain
: proto::domain<proto::generator<calculator_expression> >
{};
// Define a calculator context, for evaluating arithmetic expressions
// (This is as before, in calc1.cpp and calc2.cpp)
struct calculator_context
: proto::callable_context< calculator_context const >
{
// The values bound to the placeholders
double d[2];
// The result of evaluating arithmetic expressions
typedef double result_type;
explicit calculator_context(double d1 = 0., double d2 = 0.)
{
d[0] = d1;
d[1] = d2;
}
// Handle the evaluation of the placeholder terminals
template<typename I>
double operator ()(proto::tag::terminal, placeholder<I>) const
{
return d[ I() - 1 ];
}
};
// Wrap all calculator expressions in this type, which defines
// operator () to evaluate the expression.
template<typename Expr>
struct calculator_expression
: proto::extends<Expr, calculator_expression<Expr>, calculator_domain>
{
typedef
proto::extends<Expr, calculator_expression<Expr>, calculator_domain>
base_type;
explicit calculator_expression(Expr const &expr = Expr())
: base_type(expr)
{}
BOOST_PROTO_EXTENDS_USING_ASSIGN(calculator_expression<Expr>)
// Override operator () to evaluate the expression
double operator ()() const
{
// Assert that the expression has arity 0
BOOST_MPL_ASSERT_RELATION(0, ==, calculator_arity<Expr>::type::value);
calculator_context const ctx;
return proto::eval(*this, ctx);
}
double operator ()(double d1) const
{
// Assert that the expression has arity 1
BOOST_MPL_ASSERT_RELATION(1, ==, calculator_arity<Expr>::type::value);
calculator_context const ctx(d1);
return proto::eval(*this, ctx);
}
double operator ()(double d1, double d2) const
{
// Assert that the expression has arity 2
BOOST_MPL_ASSERT_RELATION(2, ==, calculator_arity<Expr>::type::value);
calculator_context const ctx(d1, d2);
return proto::eval(*this, ctx);
}
};
// Define some placeholders (notice they're wrapped in calculator_expression<>)
calculator_expression<proto::terminal< placeholder< mpl::int_<1> > >::type> const _1;
calculator_expression<proto::terminal< placeholder< mpl::int_<2> > >::type> const _2;
// Now, our arithmetic expressions are immediately executable function objects:
int main()
{
// Displays "5"
std::cout << (_1 + 2.0)( 3.0 ) << std::endl;
// Displays "6"
std::cout << ( _1 * _2 )( 3.0, 2.0 ) << std::endl;
// Displays "0.5"
std::cout << ( (_1 - _2) / _2 )( 3.0, 2.0 ) << std::endl;
// This won't compile because the arity of the
// expression doesn't match the number of arguments
// ( (_1 - _2) / _2 )( 3.0 );
return 0;
}
//]

View File

@@ -0,0 +1,128 @@
//[ CheckedCalc
// Copyright 2011 Eric Niebler. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// This is an example of how to specify a transform externally so
// that a single grammar can be used to drive multiple differnt
// calculations. In particular, it defines a calculator grammar
// that computes the result of an expression with either checked
// or non-checked division.
#include <iostream>
#include <boost/assert.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/next.hpp>
#include <boost/mpl/min_max.hpp>
#include <boost/fusion/container/vector.hpp>
#include <boost/fusion/container/generation/make_vector.hpp>
#include <boost/proto/proto.hpp>
namespace mpl = boost::mpl;
namespace proto = boost::proto;
namespace fusion = boost::fusion;
// The argument placeholder type
template<typename I> struct placeholder : I {};
// Give each rule in the grammar a "name". This is so that we
// can easily dispatch on it later.
struct calc_grammar;
struct divides_rule : proto::divides<calc_grammar, calc_grammar> {};
// Use external transforms in calc_gramar
struct calc_grammar
: proto::or_<
proto::when<
proto::terminal<placeholder<proto::_> >
, proto::functional::at(proto::_state, proto::_value)
>
, proto::when<
proto::terminal<proto::convertible_to<double> >
, proto::_value
>
, proto::when<
proto::plus<calc_grammar, calc_grammar>
, proto::_default<calc_grammar>
>
, proto::when<
proto::minus<calc_grammar, calc_grammar>
, proto::_default<calc_grammar>
>
, proto::when<
proto::multiplies<calc_grammar, calc_grammar>
, proto::_default<calc_grammar>
>
// Note that we don't specify how division nodes are
// handled here. Proto::external_transform is a placeholder
// for an actual transform.
, proto::when<
divides_rule
, proto::external_transform
>
>
{};
template<typename E> struct calc_expr;
struct calc_domain : proto::domain<proto::generator<calc_expr> > {};
template<typename E>
struct calc_expr
: proto::extends<E, calc_expr<E>, calc_domain>
{
calc_expr(E const &e = E()) : calc_expr::proto_extends(e) {}
};
calc_expr<proto::terminal<placeholder<mpl::int_<0> > >::type> _1;
calc_expr<proto::terminal<placeholder<mpl::int_<1> > >::type> _2;
// Use proto::external_transforms to map from named grammar rules to
// transforms.
struct non_checked_division
: proto::external_transforms<
proto::when< divides_rule, proto::_default<calc_grammar> >
>
{};
struct division_by_zero : std::exception {};
struct do_checked_divide
: proto::callable
{
typedef int result_type;
int operator()(int left, int right) const
{
if (right == 0) throw division_by_zero();
return left / right;
}
};
// Use proto::external_transforms again, this time to map the divides_rule
// to a transforms that performs checked division.
struct checked_division
: proto::external_transforms<
proto::when<
divides_rule
, do_checked_divide(calc_grammar(proto::_left), calc_grammar(proto::_right))
>
>
{};
int main()
{
non_checked_division non_checked;
int result2 = calc_grammar()(_1 / _2, fusion::make_vector(6, 2), non_checked);
BOOST_ASSERT(result2 == 3);
try
{
checked_division checked;
// This should throw
int result3 = calc_grammar()(_1 / _2, fusion::make_vector(6, 0), checked);
BOOST_ASSERT(false); // shouldn't get here!
}
catch(division_by_zero)
{
std::cout << "caught division by zero!\n";
}
}
//]

View File

@@ -0,0 +1,134 @@
//[ FutureGroup
// Copyright 2008 Eric Niebler. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// This is an example of using Proto transforms to implement
// Howard Hinnant's future group proposal.
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/as_vector.hpp>
#include <boost/fusion/include/joint_view.hpp>
#include <boost/fusion/include/single_view.hpp>
#include <boost/proto/core.hpp>
#include <boost/proto/transform.hpp>
namespace mpl = boost::mpl;
namespace proto = boost::proto;
namespace fusion = boost::fusion;
using proto::_;
template<class L,class R>
struct pick_left
{
BOOST_MPL_ASSERT((boost::is_same<L, R>));
typedef L type;
};
// Work-arounds for Microsoft Visual C++ 7.1
#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
#define FutureGroup(x) proto::call<FutureGroup(x)>
#endif
// Define the grammar of future group expression, as well as a
// transform to turn them into a Fusion sequence of the correct
// type.
struct FutureGroup
: proto::or_<
// terminals become a single-element Fusion sequence
proto::when<
proto::terminal<_>
, fusion::single_view<proto::_value>(proto::_value)
>
// (a && b) becomes a concatenation of the sequence
// from 'a' and the one from 'b':
, proto::when<
proto::logical_and<FutureGroup, FutureGroup>
, fusion::joint_view<
boost::add_const<FutureGroup(proto::_left) >
, boost::add_const<FutureGroup(proto::_right) >
>(FutureGroup(proto::_left), FutureGroup(proto::_right))
>
// (a || b) becomes the sequence for 'a', so long
// as it is the same as the sequence for 'b'.
, proto::when<
proto::logical_or<FutureGroup, FutureGroup>
, pick_left<
FutureGroup(proto::_left)
, FutureGroup(proto::_right)
>(FutureGroup(proto::_left))
>
>
{};
#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
#undef FutureGroup
#endif
template<class E>
struct future_expr;
struct future_dom
: proto::domain<proto::generator<future_expr>, FutureGroup>
{};
// Expressions in the future group domain have a .get()
// member function that (ostensibly) blocks for the futures
// to complete and returns the results in an appropriate
// tuple.
template<class E>
struct future_expr
: proto::extends<E, future_expr<E>, future_dom>
{
explicit future_expr(E const &e)
: future_expr::proto_extends(e)
{}
typename fusion::result_of::as_vector<
typename boost::result_of<FutureGroup(E)>::type
>::type
get() const
{
return fusion::as_vector(FutureGroup()(*this));
}
};
// The future<> type has an even simpler .get()
// member function.
template<class T>
struct future
: future_expr<typename proto::terminal<T>::type>
{
future(T const &t = T())
: future::proto_derived_expr(future::proto_base_expr::make(t))
{}
T get() const
{
return proto::value(*this);
}
};
// TEST CASES
struct A {};
struct B {};
struct C {};
int main()
{
using fusion::vector;
future<A> a;
future<B> b;
future<C> c;
future<vector<A,B> > ab;
// Verify that various future groups have the
// correct return types.
A t0 = a.get();
vector<A, B, C> t1 = (a && b && c).get();
vector<A, C> t2 = ((a || a) && c).get();
vector<A, B, C> t3 = ((a && b || a && b) && c).get();
vector<vector<A, B>, C> t4 = ((ab || ab) && c).get();
return 0;
}
//]

View File

@@ -0,0 +1,28 @@
//[ HelloWorld
////////////////////////////////////////////////////////////////////
// Copyright 2008 Eric Niebler. 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 <iostream>
#include <boost/proto/core.hpp>
#include <boost/proto/context.hpp>
// This #include is only needed for compilers that use typeof emulation:
#include <boost/typeof/std/ostream.hpp>
namespace proto = boost::proto;
proto::terminal< std::ostream & >::type cout_ = {std::cout};
template< typename Expr >
void evaluate( Expr const & expr )
{
proto::default_context ctx;
proto::eval(expr, ctx);
}
int main()
{
evaluate( cout_ << "hello" << ',' << " world" );
return 0;
}
//]

View File

@@ -0,0 +1,17 @@
//[ Lambda
///////////////////////////////////////////////////////////////////////////////
// Copyright 2008 Eric Niebler. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// This example builds a simple but functional lambda library using Proto.
#include <iostream>
#include "./lambda.hpp"
int main()
{
using namespace boost::lambda;
int i = (_1 + _1)(42);
std::cout << i << std::endl;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,142 @@
//[ LazyVector
///////////////////////////////////////////////////////////////////////////////
// Copyright 2008 Eric Niebler. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// This example constructs a mini-library for linear algebra, using
// expression templates to eliminate the need for temporaries when
// adding vectors of numbers.
//
// This example uses a domain with a grammar to prune the set
// of overloaded operators. Only those operators that produce
// valid lazy vector expressions are allowed.
#include <vector>
#include <iostream>
#include <boost/mpl/int.hpp>
#include <boost/proto/core.hpp>
#include <boost/proto/context.hpp>
namespace mpl = boost::mpl;
namespace proto = boost::proto;
using proto::_;
template<typename Expr>
struct lazy_vector_expr;
// This grammar describes which lazy vector expressions
// are allowed; namely, vector terminals and addition
// and subtraction of lazy vector expressions.
struct LazyVectorGrammar
: proto::or_<
proto::terminal< std::vector<_> >
, proto::plus< LazyVectorGrammar, LazyVectorGrammar >
, proto::minus< LazyVectorGrammar, LazyVectorGrammar >
>
{};
// Tell proto that in the lazy_vector_domain, all
// expressions should be wrapped in laxy_vector_expr<>
// and must conform to the lazy vector grammar.
struct lazy_vector_domain
: proto::domain<proto::generator<lazy_vector_expr>, LazyVectorGrammar>
{};
// Here is an evaluation context that indexes into a lazy vector
// expression, and combines the result.
template<typename Size = std::size_t>
struct lazy_subscript_context
{
lazy_subscript_context(Size subscript)
: subscript_(subscript)
{}
// Use default_eval for all the operations ...
template<typename Expr, typename Tag = typename Expr::proto_tag>
struct eval
: proto::default_eval<Expr, lazy_subscript_context>
{};
// ... except for terminals, which we index with our subscript
template<typename Expr>
struct eval<Expr, proto::tag::terminal>
{
typedef typename proto::result_of::value<Expr>::type::value_type result_type;
result_type operator ()( Expr const & expr, lazy_subscript_context & ctx ) const
{
return proto::value( expr )[ ctx.subscript_ ];
}
};
Size subscript_;
};
// Here is the domain-specific expression wrapper, which overrides
// operator [] to evaluate the expression using the lazy_subscript_context.
template<typename Expr>
struct lazy_vector_expr
: proto::extends<Expr, lazy_vector_expr<Expr>, lazy_vector_domain>
{
lazy_vector_expr( Expr const & expr = Expr() )
: lazy_vector_expr::proto_extends( expr )
{}
// Use the lazy_subscript_context<> to implement subscripting
// of a lazy vector expression tree.
template< typename Size >
typename proto::result_of::eval< Expr, lazy_subscript_context<Size> >::type
operator []( Size subscript ) const
{
lazy_subscript_context<Size> ctx(subscript);
return proto::eval(*this, ctx);
}
};
// Here is our lazy_vector terminal, implemented in terms of lazy_vector_expr
template< typename T >
struct lazy_vector
: lazy_vector_expr< typename proto::terminal< std::vector<T> >::type >
{
typedef typename proto::terminal< std::vector<T> >::type expr_type;
lazy_vector( std::size_t size = 0, T const & value = T() )
: lazy_vector_expr<expr_type>( expr_type::make( std::vector<T>( size, value ) ) )
{}
// Here we define a += operator for lazy vector terminals that
// takes a lazy vector expression and indexes it. expr[i] here
// uses lazy_subscript_context<> under the covers.
template< typename Expr >
lazy_vector &operator += (Expr const & expr)
{
std::size_t size = proto::value(*this).size();
for(std::size_t i = 0; i < size; ++i)
{
proto::value(*this)[i] += expr[i];
}
return *this;
}
};
int main()
{
// lazy_vectors with 4 elements each.
lazy_vector< double > v1( 4, 1.0 ), v2( 4, 2.0 ), v3( 4, 3.0 );
// Add two vectors lazily and get the 2nd element.
double d1 = ( v2 + v3 )[ 2 ]; // Look ma, no temporaries!
std::cout << d1 << std::endl;
// Subtract two vectors and add the result to a third vector.
v1 += v2 - v3; // Still no temporaries!
std::cout << '{' << v1[0] << ',' << v1[1]
<< ',' << v1[2] << ',' << v1[3] << '}' << std::endl;
// This expression is disallowed because it does not conform
// to the LazyVectorGrammar
//(v2 + v3) += v1;
return 0;
}
//]

View File

@@ -0,0 +1,136 @@
//[ MapAssign
// Copyright 2008 Eric Niebler. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// This is a port of map_list_of() from the Boost.Assign library.
// It has the advantage of being more efficient at runtime by not
// building any temporary container that requires dynamic allocation.
#include <map>
#include <string>
#include <iostream>
#include <boost/proto/core.hpp>
#include <boost/proto/transform.hpp>
#include <boost/type_traits/add_reference.hpp>
namespace proto = boost::proto;
using proto::_;
struct map_list_of_tag
{};
// A simple callable function object that inserts a
// (key,value) pair into a map.
struct insert
: proto::callable
{
template<typename Sig>
struct result;
template<typename This, typename Map, typename Key, typename Value>
struct result<This(Map, Key, Value)>
: boost::add_reference<Map>
{};
template<typename Map, typename Key, typename Value>
Map &operator()(Map &map, Key const &key, Value const &value) const
{
map.insert(typename Map::value_type(key, value));
return map;
}
};
// Work-arounds for Microsoft Visual C++ 7.1
#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
#define MapListOf(x) proto::call<MapListOf(x)>
#define _value(x) call<proto::_value(x)>
#endif
// The grammar for valid map-list expressions, and a
// transform that populates the map.
struct MapListOf
: proto::or_<
proto::when<
// map_list_of(a,b)
proto::function<
proto::terminal<map_list_of_tag>
, proto::terminal<_>
, proto::terminal<_>
>
, insert(
proto::_data
, proto::_value(proto::_child1)
, proto::_value(proto::_child2)
)
>
, proto::when<
// map_list_of(a,b)(c,d)...
proto::function<
MapListOf
, proto::terminal<_>
, proto::terminal<_>
>
, insert(
MapListOf(proto::_child0)
, proto::_value(proto::_child1)
, proto::_value(proto::_child2)
)
>
>
{};
#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
#undef MapListOf
#undef _value
#endif
template<typename Expr>
struct map_list_of_expr;
struct map_list_of_dom
: proto::domain<proto::pod_generator<map_list_of_expr>, MapListOf>
{};
// An expression wrapper that provides a conversion to a
// map that uses the MapListOf
template<typename Expr>
struct map_list_of_expr
{
BOOST_PROTO_BASIC_EXTENDS(Expr, map_list_of_expr, map_list_of_dom)
BOOST_PROTO_EXTENDS_FUNCTION()
template<typename Key, typename Value, typename Cmp, typename Al>
operator std::map<Key, Value, Cmp, Al> () const
{
BOOST_MPL_ASSERT((proto::matches<Expr, MapListOf>));
std::map<Key, Value, Cmp, Al> map;
return MapListOf()(*this, 0, map);
}
};
map_list_of_expr<proto::terminal<map_list_of_tag>::type> const map_list_of = {{{}}};
int main()
{
// Initialize a map:
std::map<std::string, int> op =
map_list_of
("<", 1)
("<=",2)
(">", 3)
(">=",4)
("=", 5)
("<>",6)
;
std::cout << "\"<\" --> " << op["<"] << std::endl;
std::cout << "\"<=\" --> " << op["<="] << std::endl;
std::cout << "\">\" --> " << op[">"] << std::endl;
std::cout << "\">=\" --> " << op[">="] << std::endl;
std::cout << "\"=\" --> " << op["="] << std::endl;
std::cout << "\"<>\" --> " << op["<>"] << std::endl;
return 0;
}
//]

Some files were not shown because too many files have changed in this diff Show More