summaryrefslogtreecommitdiff
path: root/libs/proto
diff options
context:
space:
mode:
authorChanho Park <chanho61.park@samsung.com>2014-12-11 18:55:56 +0900
committerChanho Park <chanho61.park@samsung.com>2014-12-11 18:55:56 +0900
commit08c1e93fa36a49f49325a07fe91ff92c964c2b6c (patch)
tree7a7053ceb8874b28ec4b868d4c49b500008a102e /libs/proto
parentbb4dd8289b351fae6b55e303f189127a394a1edd (diff)
downloadboost-08c1e93fa36a49f49325a07fe91ff92c964c2b6c.tar.gz
boost-08c1e93fa36a49f49325a07fe91ff92c964c2b6c.tar.bz2
boost-08c1e93fa36a49f49325a07fe91ff92c964c2b6c.zip
Imported Upstream version 1.57.0upstream/1.57.0
Diffstat (limited to 'libs/proto')
-rw-r--r--libs/proto/doc/back_end.qbk224
-rw-r--r--libs/proto/doc/history.qbk2
-rw-r--r--libs/proto/doc/preface.qbk2
-rw-r--r--libs/proto/doc/reference.xml143
-rw-r--r--libs/proto/doc/reference/functional/range.xml11
-rw-r--r--libs/proto/doc/reference/functional/range/begin.xml73
-rw-r--r--libs/proto/doc/reference/functional/range/empty.xml50
-rw-r--r--libs/proto/doc/reference/functional/range/end.xml73
-rw-r--r--libs/proto/doc/reference/functional/range/rbegin.xml73
-rw-r--r--libs/proto/doc/reference/functional/range/rend.xml73
-rw-r--r--libs/proto/doc/reference/functional/range/size.xml61
-rw-r--r--libs/proto/doc/reference/functional/std/iterator.xml247
-rw-r--r--libs/proto/doc/reference/transform/arg.xml61
-rw-r--r--libs/proto/doc/reference/transform/env.xml775
-rw-r--r--libs/proto/doc/reference/transform/pass_through.xml24
-rw-r--r--libs/proto/doc/reference/transform/when.xml86
-rw-r--r--libs/proto/example/external_transforms.cpp2
-rw-r--r--libs/proto/example/lambda.hpp4
-rw-r--r--libs/proto/example/vec3.cpp10
-rw-r--r--libs/proto/example/virtual_member.cpp42
-rw-r--r--libs/proto/preprocess/Jamfile.v26
-rw-r--r--libs/proto/preprocess/preprocess_proto.cpp23
-rw-r--r--libs/proto/preprocess/wave.cfg10
-rw-r--r--libs/proto/test/Jamfile.v27
-rw-r--r--libs/proto/test/cpp-next_bug.cpp80
-rw-r--r--libs/proto/test/env_var.cpp297
-rw-r--r--libs/proto/test/external_transforms.cpp185
-rw-r--r--libs/proto/test/make_expr.cpp10
-rw-r--r--libs/proto/test/mem_ptr.cpp4
-rw-r--r--libs/proto/test/mpl.cpp67
-rw-r--r--libs/proto/test/pack_expansion.cpp4
-rw-r--r--libs/proto/test/protect.cpp106
-rw-r--r--libs/proto/test/toy_spirit2.cpp9
33 files changed, 2629 insertions, 215 deletions
diff --git a/libs/proto/doc/back_end.qbk b/libs/proto/doc/back_end.qbk
index 858f19b396..4175fe15fe 100644
--- a/libs/proto/doc/back_end.qbk
+++ b/libs/proto/doc/back_end.qbk
@@ -986,154 +986,144 @@ When writing transforms, "fold" is such a basic operation that Proto provides a
[section:data Passing Auxiliary Data to Transforms]
[/================================================]
-In the last section, we saw that we can pass a second parameter to grammars with transforms: an accumulation variable or /state/ that gets updated as your transform executes. There are times when your transforms will need to access auxiliary data that does /not/ accumulate, so bundling it with the state parameter is impractical. Instead, you can pass auxiliary data as a third parameter, known as the /data/ parameter. Below we show an example involving string processing where the data parameter is essential.
+In the last section, we saw that we can pass a second parameter to grammars with transforms: an accumulation variable or /state/ that gets updated as your transform executes. There are times when your transforms will need to access auxiliary data that does /not/ accumulate, so bundling it with the state parameter is impractical. Instead, you can pass auxiliary data as a third parameter, known as the /data/ parameter.
-[note All Proto grammars are function objects that take one, two or three arguments: the expression, the state, and the data. There are no additional arguments to know about, we promise. In Haskell, there is set of tree traversal technologies known collectively as _SYB_. In that framework, there are also three parameters: the term, the accumulator, and the context. These are Proto's expression, state and data parameters under different names.]
+Let's modify our previous example so that it writes each terminal to `std::cout` before it puts it into a list. This could be handy for debugging your transforms, for instance. We can make it general by passing a `std::ostream` into the transform in the data parameter. Within the transform itself, we can retrieve the `ostream` with the _data_pt_ transform. The strategy is as follows: use the _and_ transform to chain two actions. The second action will create the `fusion::cons<>` node as before. The first action, however, will display the current expression. For that, we first construct an instance of [classref boost::proto::functional::display_expr `proto::functional::display_expr`] and then call it.
-Expression templates are often used as an optimization to eliminate temporary objects. Consider the problem of string concatenation: a series of concatenations would result in the needless creation of temporary strings. We can use Proto to make string concatenation very efficient. To make the problem more interesting, we can apply a locale-sensitive transformation to each character during the concatenation. The locale information will be passed as the data parameter.
-
-Consider the following expression template:
-
- proto::lit("hello") + " " + "world";
-
-We would like to concatenate this string into a statically allocated wide character buffer, widening each character in turn using the specified locale. The first step is to write a grammar that describes this expression, with transforms that calculate the total string length. Here it is:
-
- // A grammar that matches string concatenation expressions, and
- // a transform that calculates the total string length.
- struct StringLength
+ // Fold the terminals in output statements like
+ // "cout_ << 42 << '\n'" into a Fusion cons-list.
+ struct FoldToList
: proto::or_<
+ // Don't add the ostream terminal to the list
proto::when<
- // When you find a character array ...
- proto::terminal<char[proto::N]>
- // ... the length is the size of the array minus 1.
- , mpl::prior<mpl::sizeof_<proto::_value> >()
+ proto::terminal< std::ostream & >
+ , proto::_state
>
+ // Put all other terminals at the head of the
+ // list that we're building in the "state" parameter
, proto::when<
- // The length of a concatenated string is ...
- proto::plus<StringLength, StringLength>
- // ... the sum of the lengths of each sub-string.
- , proto::fold<
- _
- , mpl::size_t<0>()
- , mpl::plus<StringLength, proto::_state>()
+ proto::terminal<_>
+ , proto::and_<
+ // First, write the terminal to an ostream passed
+ // in the data parameter
+ proto::lazy<
+ proto::make<proto::functional::display_expr(proto::_data)>(_)
+ >
+ // Then, constuct the new cons list.
+ , fusion::cons<proto::_value, proto::_state>(
+ proto::_value, proto::_state
+ )
>
>
+ // For left-shift operations, first fold the right
+ // child to a list using the current state. Use
+ // the result as the state parameter when folding
+ // the left child to a list.
+ , proto::when<
+ proto::shift_left<FoldToList, FoldToList>
+ , FoldToList(
+ proto::_left
+ , FoldToList(proto::_right, proto::_state, proto::_data)
+ , proto::_data
+ )
+ >
>
{};
-Notice the use of _fold_pt_. It is a primitive transform that takes a sequence, a state, and function, just like `std::accumulate()`. The three template parameters are transforms. The first yields the sequence of expressions over which to fold, the second yields the initial state of the fold, and the third is the function to apply at each iteration. The use of `proto::_` as the first parameter might have you confused. In addition to being Proto's wildcard, `proto::_` is also a primitive transform that returns the current expression, which (if it is a non-terminal) is a sequence of its child expressions.
+This is a lot to take in, no doubt. But focus on the second `when` clause above. It says: when you find a terminal, first display the terminal using the `ostream` you find in the data parameter, then take the value of the terminal and the current state to build a new `cons` list. The function object `display_expr` does the job of printing the terminal, and `proto::and_<>` chains the actions together and executes them in sequence, returning the result of the last one.
-Next, we need a function object that accepts a narrow string, a wide character buffer, and a `std::ctype<>` facet for doing the locale-specific stuff. It's fairly straightforward.
+[def __the_expr__ ['the-expr]]
- // A function object that writes a narrow string
- // into a wide buffer.
- struct WidenCopy : proto::callable
- {
- typedef wchar_t *result_type;
+[note Also new is _lazy_pt_. Sometimes you don't have a ready-made callable object to execute. Instead, you want to first make one and /then/ execute it. Above, we need to create a `display_expr`, initializing it with our `ostream`. After that, we want to invoke it by passing it the current expression. It's as if we were doing `display_expr(std::cout)(__the_expr__)`. We achieve this two-phase evaluation using `proto::lazy<>`. If this doesn't make sense yet, don't worry about it.]
- wchar_t *
- operator()(char const *str, wchar_t *buf, std::ctype<char> const &ct) const
- {
- for(; *str; ++str, ++buf)
- *buf = ct.widen(*str);
- return buf;
- }
- };
+We can use the above transform as before, but now we can pass an `ostream` as the third parameter and get to watch the transform in action. Here's a sample usage:
-Finally, we need some transforms that actually walk the concatenated string expression, widens the characters and writes them to a buffer. We will pass a `wchar_t*` as the state parameter and update it as we go. We'll also pass the `std::ctype<>` facet as the data parameter. It looks like this:
+ proto::terminal<std::ostream &>::type const cout_ = {std::cout};
- // Write concatenated strings into a buffer, widening
- // them as we go.
- struct StringCopy
- : proto::or_<
- proto::when<
- proto::terminal<char[proto::N]>
- , WidenCopy(proto::_value, proto::_state, proto::_data)
- >
- , proto::when<
- proto::plus<StringCopy, StringCopy>
- , StringCopy(
- proto::_right
- , StringCopy(proto::_left, proto::_state, proto::_data)
- , proto::_data
- )
+ // This is the type of the list we build below
+ typedef
+ fusion::cons<
+ int
+ , fusion::cons<
+ double
+ , fusion::cons<
+ char
+ , fusion::nil
+ >
>
>
- {};
+ result_type;
-Let's look more closely at the transform associated with non-terminals:
+ // Fold an output expression into a Fusion list, using
+ // fusion::nil as the initial state of the transformation.
+ // Pass std::cout as the data parameter so that we can track
+ // the progress of the transform on the console.
+ FoldToList to_list;
+ result_type args = to_list(cout_ << 1 << 3.14 << '\n', fusion::nil(), std::cout);
- StringCopy(
- proto::_right
- , StringCopy(proto::_left, proto::_state, proto::_data)
- , proto::_data
- )
+ // Now "args" is the list: {1, 3.14, '\n'}
-This bears a resemblance to the transform in the previous section that folded an expression tree into a list. First we recurse on the left child, writing its strings into the `wchar_t*` passed in as the state parameter. That returns the new value of the `wchar_t*`, which is passed as state while transforming the right child. Both invocations receive the same `std::ctype<>`, which is passed in as the data parameter.
+This code displays the following:
-With these pieces in our pocket, we can implement our concatenate-and-widen function as follows:
+[pre terminal(
+)
+terminal(3.14)
+terminal(1)]
- template<typename Expr>
- void widen( Expr const &expr )
- {
- // Make sure the expression conforms to our grammar
- BOOST_MPL_ASSERT(( proto::matches<Expr, StringLength> ));
+This is a rather round-about way of demonstrating that you can pass extra data to a transform as a third parameter. There are no restrictions on what this parameter can be, and, unlike the state parameter, Proto will never mess with it.
- // Calculate the length of the string and allocate a buffer statically
- static std::size_t const length =
- boost::result_of<StringLength(Expr)>::type::value;
- wchar_t buffer[ length + 1 ] = {L'\0'};
+[heading Transform Environment Variables]
- // Get the current ctype facet
- std::locale loc;
- std::ctype<char> const &ct(std::use_facet<std::ctype<char> >(loc));
+[note ['This is an advanced topic. Feel free to skip if you are new to Proto.]]
- // Concatenate and widen the string expression
- StringCopy()(expr, &buffer[0], ct);
+The example above uses the data parameter as a transport mechanism for an unstructured blob of data; in this case, a reference to an `ostream`. As your Proto algorithms become more sophisticated, you may find that an unstructured blob of data isn't terribly convenient to work with. Different parts of your algorithm may be interested in different bits of data. What you want, instead, is a way to pass in a collection of /environment variables/ to a transform, like a collection of key\/value pairs. Then, you can easily get at the piece of data you want by asking the data parameter for the value associated with a particular key. Proto's /transform environments/ give you just that.
- // Write out the buffer.
- std::wcout << buffer << std::endl;
- }
+Let's start by defining a key.
- int main()
- {
- widen( proto::lit("hello") + " " + "world" );
- }
+ BOOST_PROTO_DEFINE_ENV_VAR(mykey_type, mykey);
-The above code displays:
+This defines a global constant `mykey` with the type `mykey_type`. We can use `mykey` to store a piece of assiciated data in a transform environment, as so:
-[pre
-hello world
-]
+ // Call the MyEval algorithm with a transform environment containing
+ // two key/value pairs: one for proto::data and one for mykey
+ MyEval()( expr, state, (proto::data = 42, mykey = "hello world") );
+
+The above means to invoke the `MyEval` algorithm with three parameters: an expression, an initial state, and a transform environment containing two key\/value pairs.
-This is a rather round-about way of demonstrating that you can pass extra data to a transform as a third parameter. There are no restrictions on what this parameter can be, and (unlike the state parameter) Proto will never mess with it.
+From within a Proto algorithm, you can access the values associated with different keys using the [classref boost::proto::_env_var `proto::_env_var<>`] transform. For instance, `proto::_env_var<mykey_type>` would fetch the value `"hello world"` from the transform environment created above.
-[heading Implicit Parameters to Primitive Transforms]
+The `proto::_data` transform has some additional smarts. Rather than always returning the third parameter regarless of whether it is a blob or a transform environment, it checks first to see if it's a blob or not. If so, that's what gets returned. If not, it returns the value associated with the `proto::data` key. In the above example, that would be the value `42`.
-Let's use the above example to illustrate some other niceties of Proto transforms. We've seen that grammars, when used as function objects, can accept up to 3 parameters, and that when using these grammars in callable transforms, you can also specify up to 3 parameters. Let's take another look at the transform associated with non-terminals above:
+There's a small host of functions, metafunction, and classes that you can use to create and manipulate transform environments, some for testing whether an object is a transform environment, some for coercing an object to be a transform environment, and some for querying a transform environment whether or not is has a value for a particular key. For an exhaustive treatment of the topic, check out the reference for the [headerref boost/proto/transform/env.hpp] header.
- StringCopy(
- proto::_right
- , StringCopy(proto::_left, proto::_state, proto::_data)
+[endsect]
+
+[section:implicit_params Implicit Parameters to Primitive Transforms]
+
+Let's use `FoldToList` example from the previous two sections to illustrate some other niceties of Proto transforms. We've seen that grammars, when used as function objects, can accept up to 3 parameters, and that when using these grammars in callable transforms, you can also specify up to 3 parameters. Let's take another look at the transform associated with non-terminals from the last section:
+
+ FoldToList(
+ proto::_left
+ , FoldToList(proto::_right, proto::_state, proto::_data)
, proto::_data
)
-Here we specify all three parameters to both invocations of the `StringCopy` grammar. But we don't have to specify all three. If we don't specify a third parameter, `proto::_data` is assumed. Likewise for the second parameter and `proto::_state`. So the above transform could have been written more simply as:
+Here we specify all three parameters to both invocations of the `FoldToList` grammar. But we don't have to specify all three. If we don't specify a third parameter, `proto::_data` is assumed. Likewise for the second parameter and `proto::_state`. So the above transform could have been written more simply as:
- StringCopy(
- proto::_right
- , StringCopy(proto::_left)
+ FoldToList(
+ proto::_left
+ , StringCopy(proto::_right)
)
The same is true for any primitive transform. The following are all equivalent:
[table Implicit Parameters to Primitive Transforms
[[Equivalent Transforms]]
- [[`proto::when<_, StringCopy>`]]
- [[`proto::when<_, StringCopy()>`]]
- [[`proto::when<_, StringCopy(_)>`]]
- [[`proto::when<_, StringCopy(_, proto::_state)>`]]
- [[`proto::when<_, StringCopy(_, proto::_state, proto::_data)>`]]
+ [[`proto::when<_, FoldToList>`]]
+ [[`proto::when<_, FoldToList()>`]]
+ [[`proto::when<_, FoldToList(_)>`]]
+ [[`proto::when<_, FoldToList(_, proto::_state)>`]]
+ [[`proto::when<_, FoldToList(_, proto::_state, proto::_data)>`]]
]
[note *Grammars Are Primitive Transforms Are Function Objects*
@@ -1142,18 +1132,18 @@ So far, we've said that all Proto grammars are function objects. But it's more a
[note *Not All Function Objects Are Primitive Transforms*
-You might be tempted now to drop the `_state` and `_data` parameters to `WidenCopy(proto::_value, proto::_state, proto::_data)`. That would be an error. `WidenCopy` is just a plain function object, not a primitive transform, so you must specify all its arguments. We'll see later how to write your own primitive transforms.]
+You might be tempted now to drop the `_state` and `_data` parameters for all your callable transforms. That would be an error. You can only do that for primitive transforms, and not all callables are primitive transforms. Later on, we'll see what distinguishes ordinary callables from their more powerful primitive transfor cousins, but the short version is this: primitive transforms inherit from [classref boost::proto::transform `proto::transform<>`].]
Once you know that primitive transforms will always receive all three parameters -- expression, state, and data -- it makes things possible that wouldn't be otherwise. For instance, consider that for binary expressions, these two transforms are equivalent. Can you see why?
[table Two Equivalent Transforms
- [[Without [^proto::fold<>]][With [^proto::fold<>]]]
- [[``StringCopy(
- proto::_right
- , StringCopy(proto::_left, proto::_state, proto::_data)
+ [[Without [^proto::reverse_fold<>]][With [^proto::reverse_fold<>]]]
+ [[``FoldToList(
+ proto::_left
+ , FoldToList(proto::_right, proto::_state, proto::_data)
, proto::_data
)``
-][``proto::fold<_, proto::_state, StringCopy>``]]
+][``proto::reverse_fold<_, proto::_state, FoldToList>``]]
]
[endsect]
@@ -1417,6 +1407,20 @@ Now, let's implement checked division. The rest should be unsurprising.
The above code demonstrates how a single grammar can be used with different transforms specified externally. This makes it possible to reuse a grammar to drive several different computations.
+[heading Separating Data From External Transforms]
+
+As described above, the external transforms feature usurps the data parameter, which is intended to be a place where you can pass arbitrary data, and gives it a specific meaning. But what if you are already using the data parameter for something else? The answer is to use a transform environment. By associating your external transforms with the `proto::transforms` key, you are free to pass arbitrary data in other slots.
+
+To continue the above example, what if we also needed to pass a piece of data into our transform along with the external transforms? It would look like this:
+
+ int result3 = calc_grammar_extern()(
+ _1 / _2
+ , fusion::make_vector(6, 0)
+ , (proto::data = 42, proto::transforms = checked)
+ );
+
+In the above invocation of the `calc_grammar_extern` algorithm, the map of external transforms is associated with the `proto::transforms` key and passed to the algorithm in a transform environment. Also in the transform environment is a key\/value pair that associates the value `42` with the `proto::data` key.
+
[endsect]
[/====================================================]
diff --git a/libs/proto/doc/history.qbk b/libs/proto/doc/history.qbk
index 1ef42230de..488cdd2ada 100644
--- a/libs/proto/doc/history.qbk
+++ b/libs/proto/doc/history.qbk
@@ -9,7 +9,7 @@
[variablelist
[
- [August ??, 2010]
+ [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.]
]
diff --git a/libs/proto/doc/preface.qbk b/libs/proto/doc/preface.qbk
index 6c31bd8a34..8da2f04754 100644
--- a/libs/proto/doc/preface.qbk
+++ b/libs/proto/doc/preface.qbk
@@ -13,7 +13,7 @@
[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://www.osl.iu.edu/~tveldhui/papers/Expression-Templates/exprtmpl.html Expression Templates]].
+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.
diff --git a/libs/proto/doc/reference.xml b/libs/proto/doc/reference.xml
index 778437a771..e60dedab3b 100644
--- a/libs/proto/doc/reference.xml
+++ b/libs/proto/doc/reference.xml
@@ -44,6 +44,16 @@
</listitem>
<listitem>
<computeroutput>
+ <classname alt="boost::proto::_env">proto::_env</classname>
+ </computeroutput>
+ </listitem>
+ <listitem>
+ <computeroutput>
+ <classname alt="boost::proto::_env_var">proto::_env_var</classname>
+ </computeroutput>
+ </listitem>
+ <listitem>
+ <computeroutput>
<classname alt="boost::proto::_expr">proto::_expr</classname>
</computeroutput>
</listitem>
@@ -204,6 +214,11 @@
</listitem>
<listitem>
<computeroutput>
+ <classname alt="boost::proto::data_type">proto::data_type</classname>
+ </computeroutput>
+ </listitem>
+ <listitem>
+ <computeroutput>
<classname alt="boost::proto::deduce_domain">proto::deduce_domain</classname>
</computeroutput>
</listitem>
@@ -254,6 +269,16 @@
</listitem>
<listitem>
<computeroutput>
+ <classname alt="boost::proto::empty_env">proto::empty_env</classname>
+ </computeroutput>
+ </listitem>
+ <listitem>
+ <computeroutput>
+ <classname alt="boost::proto::env">proto::env</classname>
+ </computeroutput>
+ </listitem>
+ <listitem>
+ <computeroutput>
<classname alt="boost::proto::equal_to">proto::equal_to</classname>
</computeroutput>
</listitem>
@@ -299,11 +324,21 @@
</listitem>
<listitem>
<computeroutput>
+ <classname alt="boost::proto::functional::advance">proto::functional::advance</classname>
+ </computeroutput>
+ </listitem>
+ <listitem>
+ <computeroutput>
<classname alt="boost::proto::functional::as_child">proto::functional::as_child</classname>
</computeroutput>
</listitem>
<listitem>
<computeroutput>
+ <classname alt="boost::proto::functional::as_env">proto::functional::as_env</classname>
+ </computeroutput>
+ </listitem>
+ <listitem>
+ <computeroutput>
<classname alt="boost::proto::functional::as_expr">proto::functional::as_expr</classname>
</computeroutput>
</listitem>
@@ -314,6 +349,11 @@
</listitem>
<listitem>
<computeroutput>
+ <classname alt="boost::proto::functional::begin">proto::functional::begin</classname>
+ </computeroutput>
+ </listitem>
+ <listitem>
+ <computeroutput>
<classname alt="boost::proto::functional::child">proto::functional::child</classname>
</computeroutput>
</listitem>
@@ -334,6 +374,26 @@
</listitem>
<listitem>
<computeroutput>
+ <classname alt="boost::proto::functional::distance">proto::functional::distance</classname>
+ </computeroutput>
+ </listitem>
+ <listitem>
+ <computeroutput>
+ <classname alt="boost::proto::functional::empty">proto::functional::empty</classname>
+ </computeroutput>
+ </listitem>
+ <listitem>
+ <computeroutput>
+ <classname alt="boost::proto::functional::end">proto::functional::end</classname>
+ </computeroutput>
+ </listitem>
+ <listitem>
+ <computeroutput>
+ <classname alt="boost::proto::functional::env_var">proto::functional::env_var</classname>
+ </computeroutput>
+ </listitem>
+ <listitem>
+ <computeroutput>
<classname alt="boost::proto::functional::eval">proto::functional::eval</classname>
</computeroutput>
</listitem>
@@ -349,6 +409,11 @@
</listitem>
<listitem>
<computeroutput>
+ <classname alt="boost::proto::functional::has_env_var">proto::functional::has_env_var</classname>
+ </computeroutput>
+ </listitem>
+ <listitem>
+ <computeroutput>
<classname alt="boost::proto::functional::left">proto::functional::left</classname>
</computeroutput>
</listitem>
@@ -364,6 +429,11 @@
</listitem>
<listitem>
<computeroutput>
+ <classname alt="boost::proto::functional::next">proto::functional::next</classname>
+ </computeroutput>
+ </listitem>
+ <listitem>
+ <computeroutput>
<classname alt="boost::proto::functional::pop_back">proto::functional::pop_back</classname>
</computeroutput>
</listitem>
@@ -374,6 +444,11 @@
</listitem>
<listitem>
<computeroutput>
+ <classname alt="boost::proto::functional::prior">proto::functional::prior</classname>
+ </computeroutput>
+ </listitem>
+ <listitem>
+ <computeroutput>
<classname alt="boost::proto::functional::push_back">proto::functional::push_back</classname>
</computeroutput>
</listitem>
@@ -384,6 +459,16 @@
</listitem>
<listitem>
<computeroutput>
+ <classname alt="boost::proto::functional::rbegin">proto::functional::rbegin</classname>
+ </computeroutput>
+ </listitem>
+ <listitem>
+ <computeroutput>
+ <classname alt="boost::proto::functional::rend">proto::functional::rend</classname>
+ </computeroutput>
+ </listitem>
+ <listitem>
+ <computeroutput>
<classname alt="boost::proto::functional::reverse">proto::functional::reverse</classname>
</computeroutput>
</listitem>
@@ -399,6 +484,11 @@
</listitem>
<listitem>
<computeroutput>
+ <classname alt="boost::proto::functional::size">proto::functional::size</classname>
+ </computeroutput>
+ </listitem>
+ <listitem>
+ <computeroutput>
<classname alt="boost::proto::functional::unpack_expr">proto::functional::unpack_expr</classname>
</computeroutput>
</listitem>
@@ -459,6 +549,11 @@
</listitem>
<listitem>
<computeroutput>
+ <classname alt="boost::proto::is_env">proto::is_env</classname>
+ </computeroutput>
+ </listitem>
+ <listitem>
+ <computeroutput>
<classname alt="boost::proto::is_expr">proto::is_expr</classname>
</computeroutput>
</listitem>
@@ -479,6 +574,11 @@
</listitem>
<listitem>
<computeroutput>
+ <classname alt="boost::proto::key_not_found">proto::key_not_found</classname>
+ </computeroutput>
+ </listitem>
+ <listitem>
+ <computeroutput>
<classname alt="boost::proto::lazy">proto::lazy</classname>
</computeroutput>
</listitem>
@@ -664,6 +764,11 @@
</listitem>
<listitem>
<computeroutput>
+ <classname alt="boost::proto::result_of::as_env">proto::result_of::as_env</classname>
+ </computeroutput>
+ </listitem>
+ <listitem>
+ <computeroutput>
<classname alt="boost::proto::result_of::as_expr">proto::result_of::as_expr</classname>
</computeroutput>
</listitem>
@@ -684,6 +789,11 @@
</listitem>
<listitem>
<computeroutput>
+ <classname alt="boost::proto::result_of::env_var">proto::result_of::env_var</classname>
+ </computeroutput>
+ </listitem>
+ <listitem>
+ <computeroutput>
<classname alt="boost::proto::result_of::eval">proto::result_of::eval</classname>
</computeroutput>
</listitem>
@@ -694,6 +804,11 @@
</listitem>
<listitem>
<computeroutput>
+ <classname alt="boost::proto::result_of::has_env_var">proto::result_of::has_env_var</classname>
+ </computeroutput>
+ </listitem>
+ <listitem>
+ <computeroutput>
<classname alt="boost::proto::result_of::left">proto::result_of::left</classname>
</computeroutput>
</listitem>
@@ -1009,6 +1124,11 @@
</listitem>
<listitem>
<computeroutput>
+ <classname alt="boost::proto::transforms_type">proto::transforms_type</classname>
+ </computeroutput>
+ </listitem>
+ <listitem>
+ <computeroutput>
<classname alt="boost::proto::transform_impl">proto::transform_impl</classname>
</computeroutput>
</listitem>
@@ -1060,6 +1180,11 @@
</listitem>
<listitem>
<computeroutput>
+ <functionname alt="boost::proto::as_env">proto::as_env()</functionname>
+ </computeroutput>
+ </listitem>
+ <listitem>
+ <computeroutput>
<functionname alt="boost::proto::as_expr">proto::as_expr()</functionname>
</computeroutput>
</listitem>
@@ -1095,6 +1220,11 @@
</listitem>
<listitem>
<computeroutput>
+ <functionname alt="boost::proto::env_var">proto::env_var()</functionname>
+ </computeroutput>
+ </listitem>
+ <listitem>
+ <computeroutput>
<functionname alt="boost::proto::eval">proto::eval()</functionname>
</computeroutput>
</listitem>
@@ -1105,6 +1235,11 @@
</listitem>
<listitem>
<computeroutput>
+ <functionname alt="boost::proto::has_env_var">proto::has_env_var()</functionname>
+ </computeroutput>
+ </listitem>
+ <listitem>
+ <computeroutput>
<functionname alt="boost::proto::if_else">proto::if_else()</functionname>
</computeroutput>
</listitem>
@@ -1158,7 +1293,14 @@
<xi:include href="reference/functional/fusion/push_back.xml"/>
<xi:include href="reference/functional/fusion/push_front.xml"/>
<xi:include href="reference/functional/fusion/reverse.xml"/>
+ <xi:include href="reference/functional/range/begin.xml"/>
+ <xi:include href="reference/functional/range/empty.xml"/>
+ <xi:include href="reference/functional/range/end.xml"/>
+ <xi:include href="reference/functional/range/rbegin.xml"/>
+ <xi:include href="reference/functional/range/rend.xml"/>
+ <xi:include href="reference/functional/range/size.xml"/>
<xi:include href="reference/functional/std.xml"/>
+ <xi:include href="reference/functional/std/iterator.xml"/>
<xi:include href="reference/functional/std/utility.xml"/>
<xi:include href="reference/fusion.xml"/>
<xi:include href="reference/generate.xml"/>
@@ -1176,6 +1318,7 @@
<xi:include href="reference/transform/arg.xml"/>
<xi:include href="reference/transform/call.xml"/>
<xi:include href="reference/transform/default.xml"/>
+ <xi:include href="reference/transform/env.xml"/>
<xi:include href="reference/transform/fold.xml"/>
<xi:include href="reference/transform/fold_tree.xml"/>
<xi:include href="reference/transform/impl.xml"/>
diff --git a/libs/proto/doc/reference/functional/range.xml b/libs/proto/doc/reference/functional/range.xml
new file mode 100644
index 0000000000..266634361f
--- /dev/null
+++ b/libs/proto/doc/reference/functional/range.xml
@@ -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>
diff --git a/libs/proto/doc/reference/functional/range/begin.xml b/libs/proto/doc/reference/functional/range/begin.xml
new file mode 100644
index 0000000000..735c9d519a
--- /dev/null
+++ b/libs/proto/doc/reference/functional/range/begin.xml
@@ -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>
diff --git a/libs/proto/doc/reference/functional/range/empty.xml b/libs/proto/doc/reference/functional/range/empty.xml
new file mode 100644
index 0000000000..bfaf844cfe
--- /dev/null
+++ b/libs/proto/doc/reference/functional/range/empty.xml
@@ -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>
diff --git a/libs/proto/doc/reference/functional/range/end.xml b/libs/proto/doc/reference/functional/range/end.xml
new file mode 100644
index 0000000000..196f81e9dd
--- /dev/null
+++ b/libs/proto/doc/reference/functional/range/end.xml
@@ -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>
diff --git a/libs/proto/doc/reference/functional/range/rbegin.xml b/libs/proto/doc/reference/functional/range/rbegin.xml
new file mode 100644
index 0000000000..ac634d29b7
--- /dev/null
+++ b/libs/proto/doc/reference/functional/range/rbegin.xml
@@ -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>
diff --git a/libs/proto/doc/reference/functional/range/rend.xml b/libs/proto/doc/reference/functional/range/rend.xml
new file mode 100644
index 0000000000..8385c2ffdd
--- /dev/null
+++ b/libs/proto/doc/reference/functional/range/rend.xml
@@ -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>
diff --git a/libs/proto/doc/reference/functional/range/size.xml b/libs/proto/doc/reference/functional/range/size.xml
new file mode 100644
index 0000000000..edb88b65f4
--- /dev/null
+++ b/libs/proto/doc/reference/functional/range/size.xml
@@ -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>
diff --git a/libs/proto/doc/reference/functional/std/iterator.xml b/libs/proto/doc/reference/functional/std/iterator.xml
new file mode 100644
index 0000000000..7ea293833b
--- /dev/null
+++ b/libs/proto/doc/reference/functional/std/iterator.xml
@@ -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>
diff --git a/libs/proto/doc/reference/transform/arg.xml b/libs/proto/doc/reference/transform/arg.xml
index 6256970f9d..ad25ac0a83 100644
--- a/libs/proto/doc/reference/transform/arg.xml
+++ b/libs/proto/doc/reference/transform/arg.xml
@@ -120,14 +120,27 @@ assert( ch == 'a' );</programlisting>
<struct name="_data">
<inherit><classname>proto::transform</classname>&lt; _data &gt;</inherit>
- <purpose>A <conceptname>PrimitiveTransform</conceptname> that returns the current data unmodified. </purpose>
+ <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>
- Example:
+ 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; data = proto::_data()(i, 'a', str);
-assert( &amp;str == &amp;data );</programlisting>
+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">
@@ -136,40 +149,12 @@ assert( &amp;str == &amp;data );</programlisting>
<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>Data</type>
- </typedef>
- <method-group name="public member functions">
- <method name="operator()" cv="const">
- <type>Data</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 data. </para>
- </description>
- </parameter>
- <description>
- <para>
- Returns the current data.
- </para>
- </description>
- <returns>
- <para>
- <computeroutput>data</computeroutput>
- </para>
- </returns>
- <throws>
- <simpara>Will not throw.</simpara>
- </throws>
- </method>
- </method-group>
+ <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>
diff --git a/libs/proto/doc/reference/transform/env.xml b/libs/proto/doc/reference/transform/env.xml
new file mode 100644
index 0000000000..95858ca8b0
--- /dev/null
+++ b/libs/proto/doc/reference/transform/env.xml
@@ -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>
diff --git a/libs/proto/doc/reference/transform/pass_through.xml b/libs/proto/doc/reference/transform/pass_through.xml
index 0308f995b4..7252cedc34 100644
--- a/libs/proto/doc/reference/transform/pass_through.xml
+++ b/libs/proto/doc/reference/transform/pass_through.xml
@@ -18,10 +18,13 @@
<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&gt; &gt;</type></inherit>
+ <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.</purpose>
+ 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>,
@@ -39,6 +42,13 @@
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
@@ -107,10 +117,18 @@ struct Promote :
<purpose>For exposition only</purpose>
<type>typename Expr::proto_tag</type>
</typedef>
- <typedef name="D">
+ <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>
diff --git a/libs/proto/doc/reference/transform/when.xml b/libs/proto/doc/reference/transform/when.xml
index 38098c8ca0..c70c57d7ca 100644
--- a/libs/proto/doc/reference/transform/when.xml
+++ b/libs/proto/doc/reference/transform/when.xml
@@ -18,6 +18,69 @@
</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"/>
@@ -342,9 +405,24 @@ struct CountLeaves :
<template-type-parameter name="Data"/>
</template>
<inherit><type>
- boost::remove_reference&lt; Data &gt;::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>
@@ -454,7 +532,11 @@ struct my_transforms
my_transforms trx;
// Evaluate "i+c" using my_grammar with the specified transforms:
-my_grammar()(i + c, 0, trx);</programlisting>
+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>
diff --git a/libs/proto/example/external_transforms.cpp b/libs/proto/example/external_transforms.cpp
index e9b06a3d5d..3667ebbd69 100644
--- a/libs/proto/example/external_transforms.cpp
+++ b/libs/proto/example/external_transforms.cpp
@@ -86,7 +86,7 @@ struct non_checked_division
struct division_by_zero : std::exception {};
struct do_checked_divide
- : proto::callable
+ : proto::callable
{
typedef int result_type;
int operator()(int left, int right) const
diff --git a/libs/proto/example/lambda.hpp b/libs/proto/example/lambda.hpp
index 554669095e..c93ceed5f6 100644
--- a/libs/proto/example/lambda.hpp
+++ b/libs/proto/example/lambda.hpp
@@ -503,7 +503,7 @@
struct llresult<This()>
: mpl::if_c<
result_of<IsNullary(This &)>::type::value
- , result_of<Eval(This &, no_exception_type const &, fusion::vector0 &)>
+ , result_of<Eval(This &, no_exception_type const &, fusion::vector0<> &)>
, mpl::identity<void>
>::type
{};
@@ -538,7 +538,7 @@
typename result<llexpr const()>::type
operator()() const
{
- fusion::vector0 args;
+ fusion::vector0<> args;
return Eval()(*this, no_exception, args);
}
diff --git a/libs/proto/example/vec3.cpp b/libs/proto/example/vec3.cpp
index 3591357b4f..2da948725f 100644
--- a/libs/proto/example/vec3.cpp
+++ b/libs/proto/example/vec3.cpp
@@ -113,6 +113,16 @@ struct Vec3
return *this;
}
+ // This copy-assign is needed because a template is never
+ // considered for copy assignment.
+ Vec3 &operator=(Vec3 const &that)
+ {
+ (*this)[0] = that[0];
+ (*this)[1] = that[1];
+ (*this)[2] = that[2];
+ return *this;
+ }
+
void print() const
{
std::cout << '{' << (*this)[0]
diff --git a/libs/proto/example/virtual_member.cpp b/libs/proto/example/virtual_member.cpp
index b9984612cc..46183baeb4 100644
--- a/libs/proto/example/virtual_member.cpp
+++ b/libs/proto/example/virtual_member.cpp
@@ -87,27 +87,7 @@ namespace mini_lambda
}
// Forward declaration for the mini-lambda grammar
- struct grammar;
-
- // A callable PolymorphicFunctionObject that evaluates
- // if/then/else expressions.
- struct eval_if_else : proto::callable
- {
- typedef void result_type;
-
- template<typename If, typename Then, typename Else, typename Args>
- void operator()(If const &if_, Then const &then_, Else const &else_, Args const &args) const
- {
- if(grammar()(if_, 0, args))
- {
- grammar()(then_, 0, args);
- }
- else
- {
- grammar()(else_, 0, args);
- }
- }
- };
+ struct eval_if_else;
// Forward declaration for the mini-lambda expression wrapper
template<class E>
@@ -156,6 +136,26 @@ namespace mini_lambda
>
{};
+ // A callable PolymorphicFunctionObject that evaluates
+ // if/then/else expressions.
+ struct eval_if_else : proto::callable
+ {
+ typedef void result_type;
+
+ template<typename If, typename Then, typename Else, typename Args>
+ void operator()(If const &if_, Then const &then_, Else const &else_, Args const &args) const
+ {
+ if(grammar()(if_, 0, args))
+ {
+ grammar()(then_, 0, args);
+ }
+ else
+ {
+ grammar()(else_, 0, args);
+ }
+ }
+ };
+
// Define the mini-lambda domain, in which all expressions are
// wrapped in mini_lambda::expression.
struct domain
diff --git a/libs/proto/preprocess/Jamfile.v2 b/libs/proto/preprocess/Jamfile.v2
index ae1e35d0d2..04b7cce03e 100644
--- a/libs/proto/preprocess/Jamfile.v2
+++ b/libs/proto/preprocess/Jamfile.v2
@@ -4,13 +4,15 @@
# Generates preprocessed files with wave.
+project : requirements <link>static <variant>release ;
+
actions wave
{
$(>[2]) -o- -DBOOST_PROTO_MAX_ARITY=10 --config-file wave.cfg $(>[1])
}
-W = ../../../tools/wave/build//wave ;
+W = /boost/libs/wave/tool//wave ;
make preprocess_proto
- : preprocess_proto.cpp $(W) : wave
+ : preprocess_proto.cpp $(W) : wave : <dependency>wave.cfg
;
diff --git a/libs/proto/preprocess/preprocess_proto.cpp b/libs/proto/preprocess/preprocess_proto.cpp
index eada9de19b..b1023f0dcf 100644
--- a/libs/proto/preprocess/preprocess_proto.cpp
+++ b/libs/proto/preprocess/preprocess_proto.cpp
@@ -3,21 +3,8 @@
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-//#include <boost/proto/core.hpp>
-//#include <boost/proto/debug.hpp>
-//#include <boost/proto/context.hpp>
-//#include <boost/proto/transform.hpp>
-//#include <boost/proto/functional.hpp>
-
-#include <boost/proto/args.hpp>
-#include <boost/proto/expr.hpp>
-#include <boost/proto/extends.hpp>
-#include <boost/proto/deep_copy.hpp>
-#include <boost/proto/generate.hpp>
-#include <boost/proto/make_expr.hpp>
-#include <boost/proto/matches.hpp>
-#include <boost/proto/transform/call.hpp>
-#include <boost/proto/transform/default.hpp>
-#include <boost/proto/transform/fold.hpp>
-#include <boost/proto/transform/lazy.hpp>
-#include <boost/proto/transform/make.hpp>
+#include "../include/boost/proto/core.hpp"
+#include "../include/boost/proto/debug.hpp"
+#include "../include/boost/proto/context.hpp"
+#include "../include/boost/proto/transform.hpp"
+#include "../include/boost/proto/functional.hpp"
diff --git a/libs/proto/preprocess/wave.cfg b/libs/proto/preprocess/wave.cfg
index a488b20a46..b0059003b7 100644
--- a/libs/proto/preprocess/wave.cfg
+++ b/libs/proto/preprocess/wave.cfg
@@ -7,10 +7,20 @@
-DBOOST_PROTO_DONT_USE_PREPROCESSED_FILES
-DBOOST_PROTO_CREATE_PREPROCESSED_FILES
-D_WIN32
+-NBOOST_STATIC_ASSERT
+-NBOOST_PROTO_TEMPLATE_ARITY_PARAM
+-NBOOST_PROTO_RESULT_OF
+-NBOOST_PROTO_DISABLE_IF_IS_CONST
+-NBOOST_PROTO_DISABLE_IF_IS_FUNCTION
+-NBOOST_PROTO_USE_GET_POINTER
+-NBOOST_PROTO_GET_POINTER
+-NBOOST_PROTO_ASSERT_VALID_DOMAIN
+-NBOOST_PROTO_RETURN_TYPE_STRICT_LOOSE
-NBOOST_FORCEINLINE
-NBOOST_MPL_ASSERT
-NBOOST_MPL_ASSERT_MSG
-NBOOST_MPL_ASSERT_RELATION
+-S../include
-S../../..
-S"C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include"
-S.
diff --git a/libs/proto/test/Jamfile.v2 b/libs/proto/test/Jamfile.v2
index 7e502644ad..d765eae990 100644
--- a/libs/proto/test/Jamfile.v2
+++ b/libs/proto/test/Jamfile.v2
@@ -13,6 +13,8 @@ project
<toolset>msvc-8.0:<define>_CRT_SECURE_NO_DEPRECATE
<toolset>msvc-9.0:<define>_SCL_SECURE_NO_DEPRECATE
<toolset>msvc-10.0:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>msvc-11.0:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>msvc-11.0:<define>_SCL_SECURE_NO_WARNINGS
<toolset>gcc:<cxxflags>-ftemplate-depth-1024
<library>/boost/test//boost_unit_test_framework
<link>static
@@ -23,10 +25,13 @@ test-suite "proto"
:
[ run calculator.cpp ]
[ run constrained_ops.cpp ]
+ [ run cpp-next_bug.cpp ]
[ run deep_copy.cpp ]
[ run display_expr.cpp ]
[ run deduce_domain.cpp ]
+ [ run env_var.cpp ]
[ run examples.cpp ]
+ [ run external_transforms.cpp ]
[ run lambda.cpp ]
[ run make_expr.cpp ]
[ run matches.cpp ]
@@ -36,8 +41,10 @@ test-suite "proto"
[ run toy_spirit2.cpp ]
[ run make.cpp ]
[ run mem_ptr.cpp : : : <toolset>msvc:<cxxflags>/wd4355 ]
+ [ run mpl.cpp ]
[ run noinvoke.cpp ]
[ run pack_expansion.cpp ]
+ [ run protect.cpp ]
[ compile bug2407.cpp ]
;
diff --git a/libs/proto/test/cpp-next_bug.cpp b/libs/proto/test/cpp-next_bug.cpp
new file mode 100644
index 0000000000..2f4b8b4745
--- /dev/null
+++ b/libs/proto/test/cpp-next_bug.cpp
@@ -0,0 +1,80 @@
+///////////////////////////////////////////////////////////////////////////////
+// cpp-next_bug.hpp
+//
+// 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)
+
+#include <vector>
+#include <boost/proto/proto.hpp>
+#include <boost/test/unit_test.hpp>
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+using proto::_;
+
+namespace linear_algebra
+{
+ // A trait that returns true only for std::vector
+ template<typename T>
+ struct is_std_vector
+ : mpl::false_
+ {};
+
+ template<typename T, typename A>
+ struct is_std_vector<std::vector<T, A> >
+ : mpl::true_
+ {};
+
+ // A type used as a domain for linear algebra expressions
+ struct linear_algebra_domain
+ : proto::domain<>
+ {};
+
+ // Define all the operator overloads for combining std::vectors
+ BOOST_PROTO_DEFINE_OPERATORS(is_std_vector, linear_algebra_domain)
+
+ // Take any expression and turn each node
+ // into a subscript expression, using the
+ // state as the RHS.
+ struct Distribute
+ : proto::or_<
+ proto::when<proto::terminal<_>, proto::_make_subscript(_, proto::_state)>
+ , proto::plus<Distribute, Distribute>
+ >
+ {};
+
+ struct Optimize
+ : proto::or_<
+ proto::when<
+ proto::subscript<Distribute, proto::terminal<_> >,
+ Distribute(proto::_left, proto::_right)
+ >
+ , proto::plus<Optimize, Optimize>
+ , proto::terminal<_>
+ >
+ {};
+}
+
+static const int celems = 4;
+static int const value[celems] = {1,2,3,4};
+std::vector<int> A(value, value+celems), B(A);
+
+void test1()
+{
+ using namespace linear_algebra;
+ proto::_default<> eval;
+ BOOST_CHECK_EQUAL(8, eval(Optimize()((A + B)[3])));
+}
+
+using namespace boost::unit_test;
+///////////////////////////////////////////////////////////////////////////////
+// init_unit_test_suite
+//
+test_suite* init_unit_test_suite( int argc, char* argv[] )
+{
+ test_suite *test = BOOST_TEST_SUITE("test for a problem reported on the cpp-next.com blog");
+
+ test->add(BOOST_TEST_CASE(&test1));
+
+ return test;
+}
diff --git a/libs/proto/test/env_var.cpp b/libs/proto/test/env_var.cpp
new file mode 100644
index 0000000000..14ce8be9b1
--- /dev/null
+++ b/libs/proto/test/env_var.cpp
@@ -0,0 +1,297 @@
+///////////////////////////////////////////////////////////////////////////////
+// env_var.cpp
+//
+// 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)
+
+#include <cstring>
+#include <sstream>
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/proto/proto.hpp>
+#include <boost/test/unit_test.hpp>
+
+namespace proto = boost::proto;
+
+BOOST_PROTO_DEFINE_ENV_VAR(tag0_type, tag0);
+
+struct abstract
+{
+ virtual ~abstract() = 0;
+};
+
+abstract::~abstract() {}
+
+struct concrete : abstract
+{
+ ~concrete() {}
+};
+
+template<typename Tag, typename Env>
+void assert_has_env_var(Env const &)
+{
+ BOOST_MPL_ASSERT((proto::result_of::has_env_var<Env, Tag>));
+}
+
+template<typename Tag, typename Env>
+void assert_has_env_var_not(Env const &)
+{
+ BOOST_MPL_ASSERT_NOT((proto::result_of::has_env_var<Env, Tag>));
+}
+
+void test_is_env()
+{
+ BOOST_MPL_ASSERT_NOT((proto::is_env<int>));
+ BOOST_MPL_ASSERT_NOT((proto::is_env<int &>));
+ BOOST_MPL_ASSERT_NOT((proto::is_env<int const &>));
+
+ BOOST_MPL_ASSERT_NOT((proto::is_env<abstract>));
+ BOOST_MPL_ASSERT_NOT((proto::is_env<abstract &>));
+ BOOST_MPL_ASSERT_NOT((proto::is_env<abstract const &>));
+
+ BOOST_MPL_ASSERT((proto::is_env<proto::empty_env>));
+ BOOST_MPL_ASSERT((proto::is_env<proto::empty_env &>));
+ BOOST_MPL_ASSERT((proto::is_env<proto::empty_env const &>));
+
+ BOOST_MPL_ASSERT((proto::is_env<proto::env<tag0_type, int> >));
+ BOOST_MPL_ASSERT((proto::is_env<proto::env<tag0_type, int> &>));
+ BOOST_MPL_ASSERT((proto::is_env<proto::env<tag0_type, int> const &>));
+}
+
+void test_as_env()
+{
+ proto::env<proto::data_type, int> e0 = proto::as_env(2);
+ BOOST_CHECK_EQUAL(e0[proto::data], 2);
+ assert_has_env_var<proto::data_type>(e0);
+ assert_has_env_var_not<tag0_type>(e0);
+
+ int i = 39;
+ proto::env<proto::data_type, int &> e1 = proto::as_env(boost::ref(i));
+ assert_has_env_var<proto::data_type>(i);
+ assert_has_env_var_not<tag0_type>(i);
+ BOOST_CHECK_EQUAL(e1[proto::data], 39);
+ BOOST_CHECK_EQUAL(&e1[proto::data], &i);
+
+ proto::empty_env e2 = proto::as_env(proto::empty_env());
+ proto::env<proto::data_type, int &> e3 = proto::as_env(e1);
+ proto::env<proto::data_type, int &> & e4 = proto::as_env(boost::ref(e1));
+ BOOST_CHECK_EQUAL(&e4, &e1);
+
+ concrete c;
+ abstract &a = c;
+ std::stringstream sout;
+ int rgi[2] = {};
+ proto::env<proto::data_type, abstract &> e5 = proto::as_env(a);
+ proto::env<proto::data_type, std::stringstream &> e6 = proto::as_env(sout);
+ BOOST_CHECK_EQUAL(&e6[proto::data], &sout);
+ proto::env<proto::data_type, int(&)[2]> e7 = proto::as_env(rgi);
+ BOOST_CHECK_EQUAL(&e7[proto::data][0], &rgi[0]);
+ proto::env<proto::data_type, void(&)()> e8 = proto::as_env(test_as_env);
+ BOOST_CHECK_EQUAL(&e8[proto::data], &test_as_env);
+}
+
+void test_comma()
+{
+ proto::env<proto::data_type, int> e0 = (proto::data = 1);
+ BOOST_CHECK_EQUAL(e0[proto::data], 1);
+
+ int i = 39;
+ proto::env<proto::data_type, int &> e1 = (proto::data = boost::ref(i));
+ BOOST_CHECK_EQUAL(e1[proto::data], 39);
+ BOOST_CHECK_EQUAL(&e1[proto::data], &i);
+
+ concrete c;
+ abstract &a = c;
+ std::stringstream sout;
+ int rgi[2] = {};
+ proto::env<proto::data_type, abstract &> e5 = (proto::data = a);
+ proto::env<proto::data_type, std::stringstream &> e6 = (proto::data = sout);
+ BOOST_CHECK_EQUAL(&e6[proto::data], &sout);
+ proto::env<proto::data_type, int(&)[2]> e7 = (proto::data = rgi);
+ BOOST_CHECK_EQUAL(&e7[proto::data][0], &rgi[0]);
+ // The test below fails on msvc due to a compiler bug
+ // note: <https://connect.microsoft.com/VisualStudio/feedback/details/754684/premature-decay-of-function-types-in-overloaded-assignment-operator>
+#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
+ proto::env<proto::data_type, void(&)()> e8 = (proto::data = boost::ref(test_as_env));
+ BOOST_CHECK_EQUAL(&e8[proto::data], &test_as_env);
+#else
+ proto::env<proto::data_type, void(&)()> e8 = (proto::data = test_as_env);
+ BOOST_CHECK_EQUAL(&e8[proto::data], &test_as_env);
+#endif
+
+ proto::env<
+ tag0_type
+ , char const (&)[6]
+ , proto::env<proto::data_type, int>
+ > e9 = (proto::data = 1, tag0 = "hello");
+ BOOST_CHECK_EQUAL(e9[proto::data], 1);
+ BOOST_CHECK_EQUAL(0, std::strcmp(e9[tag0], "hello"));
+
+ proto::env<
+ tag0_type
+ , int
+ , proto::env<
+ tag0_type
+ , char const (&)[6]
+ , proto::env<proto::data_type, int>
+ >
+ > e10 = (proto::data = 1, tag0 = "hello", tag0 = 42);
+ BOOST_CHECK_EQUAL(e10[proto::data], 1);
+ BOOST_CHECK_EQUAL(e10[tag0], 42);
+
+ proto::env<
+ tag0_type
+ , char const (&)[6]
+ , proto::env<proto::data_type, abstract &>
+ > e11 = (a, tag0 = "hello");
+ BOOST_CHECK_EQUAL(&e11[proto::data], &a);
+ BOOST_CHECK_EQUAL(0, std::strcmp(e11[tag0], "hello"));
+
+ proto::env<
+ tag0_type
+ , int
+ , proto::env<
+ tag0_type
+ , char const (&)[6]
+ , proto::env<proto::data_type, abstract &>
+ >
+ > e12 = (a, tag0 = "hello", tag0 = 42);
+ BOOST_CHECK_EQUAL(&e12[proto::data], &a);
+ BOOST_CHECK_EQUAL(e12[tag0], 42);
+
+ proto::env<tag0_type, int> e13 = (proto::empty_env(), tag0 = 42);
+ BOOST_CHECK_EQUAL(e13[tag0], 42);
+ assert_has_env_var<tag0_type>(e13);
+ assert_has_env_var_not<proto::data_type>(e13);
+
+ proto::empty_env empty;
+ proto::env<tag0_type, int> e14 = (boost::ref(empty), tag0 = 42);
+ BOOST_CHECK_EQUAL(e14[tag0], 42);
+
+ proto::env<
+ proto::data_type
+ , char const (&)[6]
+ , proto::env<tag0_type, int>
+ > e15 = (boost::ref(e14), proto::data = "hello");
+ BOOST_CHECK_EQUAL(e15[tag0], 42);
+ BOOST_CHECK_EQUAL(0, std::strcmp(e15[proto::data], "hello"));
+
+ proto::env<
+ proto::data_type
+ , char const (&)[6]
+ , proto::env<tag0_type, int>
+ > e16 = (proto::as_env(boost::ref(e14)), proto::data = "hello");
+ BOOST_CHECK_EQUAL(e16[tag0], 42);
+ BOOST_CHECK_EQUAL(0, std::strcmp(e16[proto::data], "hello"));
+}
+
+void test_result_of_env_var()
+{
+ typedef proto::empty_env env0_type;
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env0_type, proto::data_type>::type, proto::key_not_found>));
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env0_type &, proto::data_type>::type, proto::key_not_found>));
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env0_type const &, proto::data_type>::type, proto::key_not_found>));
+
+ typedef proto::env<proto::data_type, int> env1_type;
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env1_type, proto::data_type>::type, int>));
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env1_type &, proto::data_type>::type, int>));
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env1_type const &, proto::data_type>::type, int>));
+
+ typedef proto::env<proto::data_type, int &> env2_type;
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env2_type, proto::data_type>::type, int &>));
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env2_type &, proto::data_type>::type, int &>));
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env2_type const &, proto::data_type>::type, int &>));
+
+ typedef proto::env<proto::data_type, double, proto::env<tag0_type, abstract &> > env3_type;
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env3_type, proto::data_type>::type, double>));
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env3_type, tag0_type>::type, abstract &>));
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env3_type &, proto::data_type>::type, double>));
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env3_type &, tag0_type>::type, abstract &>));
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env3_type const &, proto::data_type>::type, double>));
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env3_type const &, tag0_type>::type, abstract &>));
+
+ typedef proto::env<tag0_type, double, proto::env<tag0_type, abstract &> > env4_type;
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env4_type, tag0_type>::type, double>));
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env4_type &, tag0_type>::type, double>));
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env4_type const &, tag0_type>::type, double>));
+}
+
+void test_env_var()
+{
+ proto::key_not_found x0 = proto::env_var<proto::data_type>(proto::empty_env());
+ proto::key_not_found x1 = proto::env_var<proto::data_type>(tag0 = 42);
+ int x2 = proto::env_var<tag0_type>(tag0 = 42);
+ BOOST_CHECK_EQUAL(x2, 42);
+ int x3 = proto::functional::env_var<tag0_type>()(tag0 = 42);
+ BOOST_CHECK_EQUAL(x3, 42);
+
+ int i = 43;
+ int & x4 = proto::env_var<tag0_type>(tag0 = boost::ref(i));
+ BOOST_CHECK_EQUAL(&x4, &i);
+ int & x5 = proto::functional::env_var<tag0_type>()(tag0 = boost::ref(i));
+ BOOST_CHECK_EQUAL(&x5, &i);
+
+ concrete c;
+ abstract &a = c;
+ abstract &x6 = proto::env_var<tag0_type>(tag0 = a);
+ BOOST_CHECK_EQUAL(&x6, &a);
+ abstract &x7 = proto::functional::env_var<tag0_type>()(tag0 = a);
+ BOOST_CHECK_EQUAL(&x7, &a);
+
+ abstract &x8 = proto::env_var<tag0_type>((42, tag0 = a));
+ BOOST_CHECK_EQUAL(&x8, &a);
+ abstract &x9 = proto::functional::env_var<tag0_type>()((42, tag0 = a));
+ BOOST_CHECK_EQUAL(&x9, &a);
+}
+
+void test_env_var_tfx()
+{
+ typedef proto::terminal<int>::type int_;
+ int_ i = {42};
+
+ // tests for _env
+ BOOST_MPL_ASSERT((boost::is_same<boost::result_of<proto::_env(int_ &)>::type, proto::empty_env>));
+ BOOST_MPL_ASSERT((boost::is_same<boost::result_of<proto::_env(int_ &, int)>::type, proto::empty_env>));
+ BOOST_MPL_ASSERT((boost::is_same<boost::result_of<proto::_env(int_ &, int &, float &)>::type, float &>));
+
+ // Bummer, is there any way around this?
+#ifdef BOOST_RESULT_OF_USE_DECLTYPE
+ BOOST_MPL_ASSERT((boost::is_same<boost::result_of<proto::_env(int_ &, int &, float)>::type, float const &>));
+ BOOST_MPL_ASSERT((boost::is_same<boost::tr1_result_of<proto::_env(int_ &, int &, float)>::type, float>));
+#else
+ BOOST_MPL_ASSERT((boost::is_same<boost::result_of<proto::_env(int_ &, int &, float)>::type, float>));
+ BOOST_MPL_ASSERT((boost::is_same<boost::tr1_result_of<proto::_env(int_ &, int &, float)>::type, float>));
+#endif
+
+ double d = 3.14;
+ double & rd = proto::_env()(i, 0, d);
+ BOOST_CHECK_EQUAL(&d, &rd);
+
+ proto::env<proto::data_type, int> e0 = proto::_env()(i, 0, proto::as_env(42));
+ BOOST_CHECK_EQUAL(e0[proto::data], 42);
+
+ proto::env<proto::data_type, int> e1 = proto::_env()(i, 0, proto::functional::as_env()(42));
+ BOOST_CHECK_EQUAL(e1[proto::data], 42);
+
+ proto::env<proto::data_type, int> e2 = proto::_env()(i, 0, (proto::data = 42));
+ BOOST_CHECK_EQUAL(e2[proto::data], 42);
+
+ proto::env<proto::data_type, int, proto::env<proto::data_type, int> > e3 = proto::_env()(i, 0, (42, proto::data = 43));
+ BOOST_CHECK_EQUAL(e3[proto::data], 43);
+}
+
+using namespace boost::unit_test;
+///////////////////////////////////////////////////////////////////////////////
+// init_unit_test_suite
+//
+test_suite* init_unit_test_suite( int argc, char* argv[] )
+{
+ test_suite *test = BOOST_TEST_SUITE("test for environment variables");
+ test->add(BOOST_TEST_CASE(&test_as_env));
+ test->add(BOOST_TEST_CASE(&test_comma));
+ test->add(BOOST_TEST_CASE(&test_result_of_env_var));
+ test->add(BOOST_TEST_CASE(&test_env_var));
+ test->add(BOOST_TEST_CASE(&test_env_var_tfx));
+ return test;
+}
diff --git a/libs/proto/test/external_transforms.cpp b/libs/proto/test/external_transforms.cpp
new file mode 100644
index 0000000000..f72e945872
--- /dev/null
+++ b/libs/proto/test/external_transforms.cpp
@@ -0,0 +1,185 @@
+// 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/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>
+#include <boost/test/unit_test.hpp>
+
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+namespace fusion = boost::fusion;
+using proto::_;
+
+// 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::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))
+ >
+ >
+{};
+
+BOOST_PROTO_DEFINE_ENV_VAR(mydata_tag, mydata);
+
+void test_external_transforms()
+{
+ non_checked_division non_checked;
+ int result1 = calc_grammar()(_1 / _2, fusion::make_vector(6, 2), non_checked);
+ BOOST_CHECK_EQUAL(result1, 3);
+
+ // check that additional data slots are ignored
+ int result2 = calc_grammar()(_1 / _2, fusion::make_vector(8, 2), (non_checked, mydata = "foo"));
+ BOOST_CHECK_EQUAL(result2, 4);
+
+ // check that we can use the dedicated slot for this purpose
+ int result3 = calc_grammar()(_1 / _2, fusion::make_vector(8, 2), (42, proto::transforms = non_checked, mydata = "foo"));
+ BOOST_CHECK_EQUAL(result2, 4);
+
+ checked_division checked;
+ try
+ {
+ // This should throw
+ int result3 = calc_grammar()(_1 / _2, fusion::make_vector(6, 0), checked);
+ BOOST_CHECK(!"Didn't throw an exception"); // shouldn't get here!
+ }
+ catch(division_by_zero)
+ {
+ ; // OK
+ }
+ catch(...)
+ {
+ BOOST_CHECK(!"Unexpected exception"); // shouldn't get here!
+ }
+
+ try
+ {
+ // This should throw
+ int result4 = calc_grammar()(_1 / _2, fusion::make_vector(6, 0), (checked, mydata = test_external_transforms));
+ BOOST_CHECK(!"Didn't throw an exception"); // shouldn't get here!
+ }
+ catch(division_by_zero)
+ {
+ ; // OK
+ }
+ catch(...)
+ {
+ BOOST_CHECK(!"Unexpected exception"); // shouldn't get here!
+ }
+
+ try
+ {
+ // This should throw
+ int result5 = calc_grammar()(_1 / _2, fusion::make_vector(6, 0), (42, proto::transforms = checked, mydata = test_external_transforms));
+ BOOST_CHECK(!"Didn't throw an exception"); // shouldn't get here!
+ }
+ catch(division_by_zero)
+ {
+ ; // OK
+ }
+ catch(...)
+ {
+ BOOST_CHECK(!"Unexpected exception"); // shouldn't get here!
+ }
+}
+
+using namespace boost::unit_test;
+///////////////////////////////////////////////////////////////////////////////
+// init_unit_test_suite
+//
+test_suite* init_unit_test_suite( int argc, char* argv[] )
+{
+ test_suite *test = BOOST_TEST_SUITE("test for external transforms");
+
+ test->add(BOOST_TEST_CASE(&test_external_transforms));
+
+ return test;
+}
diff --git a/libs/proto/test/make_expr.cpp b/libs/proto/test/make_expr.cpp
index ee491a900b..d59f757485 100644
--- a/libs/proto/test/make_expr.cpp
+++ b/libs/proto/test/make_expr.cpp
@@ -69,10 +69,11 @@ void test_make_expr()
void test_make_expr_ref()
{
int i = 42;
- proto::terminal<int const &>::type t1 = proto::make_expr<proto::tag::terminal>(boost::cref(1)); // DANGEROUS
+ int const ci = 84;
+ proto::terminal<int const &>::type t1 = proto::make_expr<proto::tag::terminal>(boost::cref(ci));
proto::terminal<int &>::type t2 = proto::make_expr<proto::tag::terminal>(boost::ref(i));
BOOST_CHECK_EQUAL(&i, &proto::value(t2));
- proto::unary_plus<proto::terminal<int const &>::type>::type p1 = proto::make_expr<proto::tag::unary_plus>(boost::cref(1)); // DANGEROUS
+ proto::unary_plus<proto::terminal<int const &>::type>::type p1 = proto::make_expr<proto::tag::unary_plus>(boost::cref(ci));
proto::unary_plus<proto::terminal<int &>::type>::type p2 = proto::make_expr<proto::tag::unary_plus>(boost::ref(i));
BOOST_CHECK_EQUAL(proto::value(proto::child(p2)), 42);
@@ -143,10 +144,11 @@ void test_make_expr_functional()
void test_make_expr_functional_ref()
{
int i = 42;
- proto::terminal<int const &>::type t1 = proto::functional::make_expr<proto::tag::terminal>()(boost::cref(1)); // DANGEROUS
+ int const ci = 84;
+ proto::terminal<int const &>::type t1 = proto::functional::make_expr<proto::tag::terminal>()(boost::cref(ci));
proto::terminal<int &>::type t2 = proto::functional::make_expr<proto::tag::terminal>()(boost::ref(i));
BOOST_CHECK_EQUAL(&i, &proto::value(t2));
- proto::unary_plus<proto::terminal<int const &>::type>::type p1 = proto::functional::make_expr<proto::tag::unary_plus>()(boost::cref(1)); // DANGEROUS
+ proto::unary_plus<proto::terminal<int const &>::type>::type p1 = proto::functional::make_expr<proto::tag::unary_plus>()(boost::cref(ci));
proto::unary_plus<proto::terminal<int &>::type>::type p2 = proto::functional::make_expr<proto::tag::unary_plus>()(boost::ref(i));
BOOST_CHECK_EQUAL(proto::value(proto::child(p2)), 42);
diff --git a/libs/proto/test/mem_ptr.cpp b/libs/proto/test/mem_ptr.cpp
index 9e6c64b4dd..5326c665bf 100644
--- a/libs/proto/test/mem_ptr.cpp
+++ b/libs/proto/test/mem_ptr.cpp
@@ -62,14 +62,14 @@ struct my_terminal
typename proto::result_of::make_expr<proto::tag::function, my_terminal const &, A0 &>::type const
operator()(A0 &a0) const
{
- return proto::make_expr<proto::tag::function>(boost::cref(*this), boost::ref(a0));
+ return proto::make_expr<proto::tag::function>(boost::ref(*this), boost::ref(a0));
}
template<typename A0>
typename proto::result_of::make_expr<proto::tag::function, my_terminal const &, A0 const &>::type const
operator()(A0 const &a0) const
{
- return proto::make_expr<proto::tag::function>(boost::cref(*this), boost::cref(a0));
+ return proto::make_expr<proto::tag::function>(boost::ref(*this), boost::ref(a0));
}
};
diff --git a/libs/proto/test/mpl.cpp b/libs/proto/test/mpl.cpp
new file mode 100644
index 0000000000..292e582bdb
--- /dev/null
+++ b/libs/proto/test/mpl.cpp
@@ -0,0 +1,67 @@
+///////////////////////////////////////////////////////////////////////////////
+// mpl.hpp
+//
+// 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)
+
+#include <boost/proto/proto.hpp>
+#include <boost/fusion/mpl.hpp>
+#include <boost/mpl/pop_back.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/test/unit_test.hpp>
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+namespace fusion = boost::fusion;
+using proto::_;
+
+template<class E>
+struct my_expr;
+
+struct my_domain
+ : proto::domain<proto::generator<my_expr> >
+{};
+
+template<class E>
+struct my_expr
+ : proto::extends<E, my_expr<E>, my_domain>
+{
+ my_expr(E const &e = E())
+ : proto::extends<E, my_expr<E>, my_domain>(e)
+ {}
+
+ typedef fusion::fusion_sequence_tag tag;
+};
+
+template<typename T>
+void test_impl(T const &)
+{
+ typedef typename mpl::pop_back<T>::type result_type;
+ BOOST_STATIC_ASSERT(
+ (boost::is_same<
+ result_type
+ , my_expr<proto::basic_expr<proto::tag::plus, proto::list1<my_expr<proto::terminal<int>::type>&> > >
+ >::value)
+ );
+}
+
+// Test that we can call mpl algorithms on proto expression types, and get proto expression types back
+void test_mpl()
+{
+ my_expr<proto::terminal<int>::type> i;
+ test_impl(i + i);
+}
+
+using namespace boost::unit_test;
+///////////////////////////////////////////////////////////////////////////////
+// init_unit_test_suite
+//
+test_suite* init_unit_test_suite( int argc, char* argv[] )
+{
+ test_suite *test = BOOST_TEST_SUITE("test proto mpl integration via fusion");
+
+ test->add(BOOST_TEST_CASE(&test_mpl));
+
+ return test;
+}
diff --git a/libs/proto/test/pack_expansion.cpp b/libs/proto/test/pack_expansion.cpp
index 20c46ac81a..7aacb32f4d 100644
--- a/libs/proto/test/pack_expansion.cpp
+++ b/libs/proto/test/pack_expansion.cpp
@@ -77,7 +77,9 @@ struct eval2
void test_call_pack()
{
proto::terminal<int>::type i = {42};
- int res = eval1()(i + 2);
+ int res = eval1()(i);
+ BOOST_CHECK_EQUAL(res, 42);
+ res = eval1()(i + 2);
BOOST_CHECK_EQUAL(res, 44);
res = eval1()(i * 2);
BOOST_CHECK_EQUAL(res, 84);
diff --git a/libs/proto/test/protect.cpp b/libs/proto/test/protect.cpp
new file mode 100644
index 0000000000..33b055198c
--- /dev/null
+++ b/libs/proto/test/protect.cpp
@@ -0,0 +1,106 @@
+///////////////////////////////////////////////////////////////////////////////
+// protect.hpp
+//
+// 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)
+
+#include <boost/proto/core.hpp>
+#include <boost/proto/transform/make.hpp>
+#include <boost/type_traits/add_pointer.hpp>
+#include <boost/type_traits/remove_pointer.hpp>
+#include <boost/test/unit_test.hpp>
+namespace proto=boost::proto;
+using proto::_;
+
+template<typename T>
+struct identity
+{
+ typedef T type;
+};
+
+struct TestWithMake
+ : proto::make< proto::protect<_> >
+{};
+
+struct TestWithMake1
+ : proto::make< identity<proto::protect<_> > >
+{};
+
+struct TestWithMake2
+ : proto::make< identity<proto::protect<int> > >
+{};
+
+struct TestWithMake3
+ : proto::make< identity<proto::protect<identity<_> > > >
+{};
+
+struct TestWithMake4
+ : proto::make< identity<proto::protect<identity<int> > > >
+{};
+
+struct TestWithMake5
+ : proto::make< identity<proto::protect<identity<identity<int> > > > >
+{};
+
+void test_protect_with_make()
+{
+ proto::terminal<int>::type i = {42};
+
+ _ t = TestWithMake()(i);
+ _ t1 = TestWithMake1()(i);
+ int t2 = TestWithMake2()(i);
+ identity<_> t3 = TestWithMake3()(i);
+ identity<int> t4 = TestWithMake4()(i);
+ identity<identity<int> > t5 = TestWithMake5()(i);
+}
+
+//struct TestWithWhen
+// : proto::when<_, proto::protect<_>() >
+//{};
+
+struct TestWithWhen1
+ : proto::when<_, identity<proto::protect<_> >() >
+{};
+
+struct TestWithWhen2
+ : proto::when<_, identity<proto::protect<int> >() >
+{};
+
+struct TestWithWhen3
+ : proto::when<_, identity<proto::protect<identity<_> > >() >
+{};
+
+struct TestWithWhen4
+ : proto::when<_, identity<proto::protect<identity<int> > >() >
+{};
+
+struct TestWithWhen5
+ : proto::when<_, identity<proto::protect<identity<identity<int> > > >() >
+{};
+
+void test_protect_with_when()
+{
+ proto::terminal<int>::type i = {42};
+
+ //_ t = TestWithWhen()(i);
+ _ t1 = TestWithWhen1()(i);
+ int t2 = TestWithWhen2()(i);
+ identity<_> t3 = TestWithWhen3()(i);
+ identity<int> t4 = TestWithWhen4()(i);
+ identity<identity<int> > t5 = TestWithWhen5()(i);
+}
+
+using namespace boost::unit_test;
+///////////////////////////////////////////////////////////////////////////////
+// init_unit_test_suite
+//
+test_suite* init_unit_test_suite( int argc, char* argv[] )
+{
+ test_suite *test = BOOST_TEST_SUITE("test proto::protect");
+
+ test->add(BOOST_TEST_CASE(&test_protect_with_make));
+ test->add(BOOST_TEST_CASE(&test_protect_with_when));
+
+ return test;
+}
diff --git a/libs/proto/test/toy_spirit2.cpp b/libs/proto/test/toy_spirit2.cpp
index de646cd444..a0f246f3f1 100644
--- a/libs/proto/test/toy_spirit2.cpp
+++ b/libs/proto/test/toy_spirit2.cpp
@@ -10,7 +10,6 @@
#include <cstring>
#include <iomanip>
#include <iostream>
-#include <boost/version.hpp>
#include <boost/assert.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/utility/result_of.hpp>
@@ -286,19 +285,11 @@ namespace boost { namespace spirit2
typedef bool result_type;
- #if BOOST_VERSION >= 104200
template<typename T>
bool operator ()(bool success, T const &t) const
{
return success && this->parse(t);
}
- #else
- template<typename T>
- bool operator ()(T const &t, bool success) const
- {
- return success && this->parse(t);
- }
- #endif
};
template<typename Iterator>