boost/doc/html/boost_yap/manual.html
2021-10-05 21:37:46 +02:00

4779 lines
576 KiB
HTML
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Manual</title>
<link rel="stylesheet" href="../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="The Boost C++ Libraries BoostBook Documentation Subset">
<link rel="up" href="../yap.html" title="Chapter 48. Boost.YAP">
<link rel="prev" href="../yap.html" title="Chapter 48. Boost.YAP">
<link rel="next" href="concepts.html" title="Concepts">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../boost.png"></td>
<td align="center"><a href="../../../index.html">Home</a></td>
<td align="center"><a href="../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../yap.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../yap.html"><img src="../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="concepts.html"><img src="../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="boost_yap.manual"></a><a class="link" href="manual.html" title="Manual">Manual</a>
</h2></div></div></div>
<div class="toc"><dl class="toc">
<dt><span class="section"><a href="manual.html#boost_yap.manual.an_expression_template_primer">An Expression
Template Primer</a></span></dt>
<dt><span class="section"><a href="manual.html#boost_yap.manual.the_yap_way">The YAP Way</a></span></dt>
<dt><span class="section"><a href="manual.html#boost_yap.manual.expressions">Expressions</a></span></dt>
<dt><span class="section"><a href="manual.html#boost_yap.manual.mix_and_match_expression_templates">Mix-and-Match
Expression Templates</a></span></dt>
<dt><span class="section"><a href="manual.html#boost_yap.manual.kinds_of_expressions">Kinds of Expressions</a></span></dt>
<dt><span class="section"><a href="manual.html#boost_yap.manual.operators">Operators</a></span></dt>
<dt><span class="section"><a href="manual.html#boost_yap.manual.transforming_expressions">Transforming
Expressions</a></span></dt>
<dt><span class="section"><a href="manual.html#boost_yap.manual.evaluating_expressions">Evaluating Expressions</a></span></dt>
<dt><span class="section"><a href="manual.html#boost_yap.manual.operator_macros">Operator Macros</a></span></dt>
<dt><span class="section"><a href="manual.html#boost_yap.manual.how_expression_operands_are_treated">How
Expression Operands Are Treated</a></span></dt>
<dt><span class="section"><a href="manual.html#boost_yap.manual.printing">Printing</a></span></dt>
<dt><span class="section"><a href="manual.html#boost_yap.manual.examples">Examples</a></span></dt>
<dt><span class="section"><a href="manual.html#boost_yap.manual.header_organization">Header Organization</a></span></dt>
<dt><span class="section"><a href="manual.html#boost_yap.manual.configuration">Configuration</a></span></dt>
<dt><span class="section"><a href="manual.html#boost_yap.manual.object_code">Object Code</a></span></dt>
</dl></div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_yap.manual.an_expression_template_primer"></a><a class="link" href="manual.html#boost_yap.manual.an_expression_template_primer" title="An Expression Template Primer">An Expression
Template Primer</a>
</h3></div></div></div>
<p>
What are expression templates anyway? In short, expression templates are
templates that you write to capture expressions so that they can be transformed
and/or evaluated lazily.
</p>
<p>
An example of normal C++ expression is:
</p>
<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">sqrt</span><span class="special">(</span><span class="number">3.0</span><span class="special">)</span> <span class="special">+</span> <span class="number">8.0f</span>
</pre>
<p>
The compiler sees this and creates some representation of that expression
inside the compiler. This is typically an <a href="https://en.wikipedia.org/wiki/Abstract_syntax_tree" target="_top">abstract
syntax tree</a> (AST). The AST for the expression above might be:
</p>
<p>
<span class="inlinemediaobject"><img src="../yap/img/ast.png" alt="ast"></span>
</p>
<p>
This tree structure captures all the elements of the original C++ code. The
expression is a plus operation whose left side is a call to <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">sqrt</span><span class="special">(</span><span class="number">3.0</span><span class="special">)</span></code>
and whose right side is <code class="computeroutput"><span class="number">8.0f</span></code>.
The call to <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">sqrt</span><span class="special">(</span><span class="number">3.0</span><span class="special">)</span></code> is its own expression subtree consisting
of a call node and its argument node.
</p>
<p>
A Boost.YAP version of this same tree is:
</p>
<p>
<span class="inlinemediaobject"><img src="../yap/img/expr.png" alt="expr"></span>
</p>
<p>
The <code class="computeroutput"><span class="keyword">operator</span><span class="special">+()</span></code>
is represented by a Boost.YAP expression whose kind is <code class="computeroutput"><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">plus</span></code>
and the call is represented by a Boost.YAP expression whose kind is <code class="computeroutput"><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">call</span></code>.
Notice that the call expression has two terminals, one for the callable,
and one for its single argument.
</p>
<p>
The type that holds this expression is:
</p>
<p>
</p>
<pre class="programlisting"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">&lt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">plus</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">&lt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">call</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">&lt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="keyword">double</span> <span class="special">(*)(</span><span class="keyword">double</span><span class="special">)&gt;</span>
<span class="special">&gt;,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">&lt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;</span>
<span class="special">&gt;</span>
<span class="special">&gt;</span>
<span class="special">&gt;,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">&lt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="keyword">float</span><span class="special">&gt;</span>
<span class="special">&gt;</span>
<span class="special">&gt;</span>
<span class="special">&gt;</span>
</pre>
<p>
</p>
<p>
That looks like a big mess; let's unpack it. You might notice that the overall
shape is the same as the expression tree diagram above. We have tree-like
nesting of <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span></code>
template instantiations.
</p>
<p>
Here's the top-level <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span></code> again with its noisy guts removed:
</p>
<p>
</p>
<pre class="programlisting"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">&lt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">plus</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span>
</pre>
<p>
</p>
<pre class="programlisting"><span class="comment">// Left and right operand expressions ...</span>
</pre>
<p>
</p>
<pre class="programlisting"> <span class="special">&gt;</span>
<span class="special">&gt;</span>
</pre>
<p>
</p>
<p>
It has an <code class="computeroutput"><a class="link" href="../boost/yap/expr_kind.html" title="Type expr_kind">expr_kind</a></code>
of <code class="computeroutput"><span class="identifier">plus</span></code> as its first template
parameter (it's a non-type parameter); this indicates what kind of "node"
it is. In this case, the top level expression is analogous to our <code class="computeroutput"><span class="keyword">operator</span><span class="special">+()</span></code>
AST node. Its operands are the elements of its <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;&gt;</span></code> data member.
</p>
<p>
The left operand to the top-level plus operation is itself a Boost.YAP expression
representing <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">sqrt</span><span class="special">(</span><span class="number">3.0</span><span class="special">)</span></code>:
</p>
<p>
</p>
<pre class="programlisting"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">&lt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">call</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">&lt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="keyword">double</span> <span class="special">(*)(</span><span class="keyword">double</span><span class="special">)&gt;</span>
<span class="special">&gt;,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">&lt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;</span>
<span class="special">&gt;</span>
<span class="special">&gt;</span>
<span class="special">&gt;,</span>
</pre>
<p>
</p>
<p>
This expression is a call expression. The first operand to the call expression
is the callable entity, in this case a pointer to <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">sqrt</span></code>.
The remaining operands are the arguments to pass to the callable; in this
case, there's only one operand after the callable, <code class="computeroutput"><span class="number">3.0</span></code>.
</p>
<p>
The children of the <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">sqrt</span><span class="special">(</span><span class="number">3.0</span><span class="special">)</span></code> subexpression are terminals. This means
that they are leaf nodes in our notional AST.
</p>
<p>
The right operand to the top-level plus operation is of course also a Boost.YAP
expression. It is also a terminal:
</p>
<p>
</p>
<pre class="programlisting"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">&lt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="keyword">float</span><span class="special">&gt;</span>
<span class="special">&gt;</span>
</pre>
<p>
</p>
<p>
Notice a couple of things here: 1) non-terminals (the top-level plus operation
and the call opertion in our example) have tuple elements that are <span class="bold"><strong>all</strong></span> Boost.YAP expressions, and 2) terminals have tuple
elements, <span class="bold"><strong>none of which</strong></span> are Boost.YAP expressions
(they're just normal types like <code class="computeroutput"><span class="keyword">float</span></code>
and <code class="computeroutput"><span class="keyword">double</span> <span class="special">(*)(</span><span class="keyword">double</span><span class="special">)</span></code>).
</p>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../doc/src/images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td align="left" valign="top"><p>
From here on, I'll use the terms "expression" and "node"
interchangably, and I'll also use the terms "subexpression" and
"child" interchangably. Even though expression templates are
not identical to tree-based ASTs, they're close enough that the terminology
is interchangable without loss of meaning.
</p></td></tr>
</table></div>
<h5>
<a name="boost_yap.manual.an_expression_template_primer.h0"></a>
<span class="phrase"><a name="boost_yap.manual.an_expression_template_primer.capturing_an_expression"></a></span><a class="link" href="manual.html#boost_yap.manual.an_expression_template_primer.capturing_an_expression">Capturing
an Expression</a>
</h5>
<p>
If we want to capture an expression using Boost.YAP we have to do something
to let the compiler know not just to eagerly evaulate our expression, as
it does when it sees <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">sqrt</span><span class="special">(</span><span class="number">3.0</span><span class="special">)</span>
<span class="special">+</span> <span class="number">8.0f</span></code>.
</p>
<p>
To do this, we create <a class="link" href="../boost/yap/expr_kind.html#boost.yap.expr_kind.terminal"><code class="computeroutput"><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span></code></a> expressions out of one
or more of the terminals in the expression we want to capture and evaluate
lazily. Here, I've declared a template alias to make that easier to type:
</p>
<p>
</p>
<pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">using</span> <span class="identifier">term</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">T</span><span class="special">&gt;;</span>
</pre>
<p>
</p>
<p>
And here is how I might use that alias to create the terminal containing
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">sqrt</span></code>:
</p>
<p>
</p>
<pre class="programlisting"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">&lt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">plus</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">&lt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">call</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">&lt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="keyword">double</span> <span class="special">(*)(</span><span class="keyword">double</span><span class="special">)&gt;</span>
<span class="special">&gt;,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">&lt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;</span>
<span class="special">&gt;</span>
<span class="special">&gt;</span>
<span class="special">&gt;,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">&lt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="keyword">float</span><span class="special">&gt;</span>
<span class="special">&gt;</span>
<span class="special">&gt;</span>
<span class="special">&gt;</span>
<span class="identifier">yap_expr</span> <span class="special">=</span> <span class="identifier">term</span><span class="special">&lt;</span><span class="keyword">double</span> <span class="special">(*)(</span><span class="keyword">double</span><span class="special">)&gt;{{</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">sqrt</span><span class="special">}}(</span><span class="number">3.0</span><span class="special">)</span> <span class="special">+</span> <span class="number">8.0f</span><span class="special">;</span>
</pre>
<p>
</p>
<p>
The reason I can then just call the terminal with a <code class="computeroutput"><span class="number">3.0</span></code>
argument and add <code class="computeroutput"><span class="number">8.0f</span></code> to the
result is that I'm taking a great big shortcut in this example by using Boost.YAP's
built-in example expression template, <code class="computeroutput"><a class="link" href="../boost/yap/expression.html" title="Struct template expression">expression&lt;&gt;</a></code>.
<code class="computeroutput"><a class="link" href="../boost/yap/expression.html" title="Struct template expression">expression&lt;&gt;</a></code> is a template with all
the operator overloads defined, including the call operator. Each operator
overload returns an <code class="computeroutput"><a class="link" href="../boost/yap/expression.html" title="Struct template expression">expression&lt;&gt;</a></code>,
which is why the <code class="computeroutput"><span class="special">+</span></code> in <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">sqrt</span><span class="special">(</span><span class="number">3.0</span><span class="special">)</span>
<span class="special">+</span> <span class="number">8.0f</span></code>
also works.
</p>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../doc/src/images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td align="left" valign="top">
<p>
<code class="computeroutput"><a class="link" href="../boost/yap/expression.html" title="Struct template expression">expression&lt;&gt;</a></code> is great for example
code like what you see here, and it's great for small expression template
use cases that are essentially implementation details. You should write
your own expression templates for anything that is to be used in any other
context. The reason for this is that most of the time your expression template
system will not want to support all combinations of all possible operators
and function calls. For instance, code like this:
</p>
<p>
(a + b) = c;
</p>
<p>
is at least unusual, if not outright wrong. Where does <code class="computeroutput"><span class="identifier">c</span></code>
go? Into <code class="computeroutput"><span class="identifier">a</span></code>, <code class="computeroutput"><span class="identifier">b</span></code>, or into an expiring <code class="computeroutput"><span class="identifier">a</span> <span class="special">+</span> <span class="identifier">b</span></code> temporary? What if <code class="computeroutput"><span class="identifier">a</span></code>
is a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code> and <code class="computeroutput"><span class="identifier">b</span></code>
is a <code class="computeroutput"><span class="identifier">FILE</span> <span class="special">*</span></code>?
<code class="computeroutput"><a class="link" href="../boost/yap/expression.html" title="Struct template expression">expression&lt;&gt;</a></code> doesn't care. You probably
want to design interfaces that are more carefully considered than the "everything
goes" style implied by using <code class="computeroutput"><a class="link" href="../boost/yap/expression.html" title="Struct template expression">expression&lt;&gt;</a></code>.
</p>
</td></tr>
</table></div>
<p>
Boost.YAP comes with a handy <code class="computeroutput"><a class="link" href="../boost/yap/print.html" title="Function template print">print()</a></code>
function. Calling it like this:
</p>
<p>
</p>
<pre class="programlisting"><span class="identifier">print</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">,</span> <span class="identifier">yap_expr</span><span class="special">);</span>
</pre>
<p>
</p>
<p>
Gives this output:
</p>
<pre class="programlisting"><span class="identifier">expr</span><span class="special">&lt;+&gt;</span>
<span class="identifier">expr</span><span class="special">&lt;()&gt;</span>
<span class="identifier">term</span><span class="special">&lt;</span><span class="keyword">double</span> <span class="special">(*)(</span><span class="keyword">double</span><span class="special">)&gt;[=</span><span class="number">1</span><span class="special">]</span>
<span class="identifier">term</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;[=</span><span class="number">3</span><span class="special">]</span>
<span class="identifier">term</span><span class="special">&lt;</span><span class="keyword">float</span><span class="special">&gt;[=</span><span class="number">8</span><span class="special">]</span>
</pre>
<p>
This is a lot more readable. I show this to you here to give you a more concise
view of the AST-like structure.
</p>
<p>
(In case you're wondering why <code class="computeroutput"><span class="special">&amp;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">sqrt</span></code>
is printed as the value <code class="computeroutput"><span class="number">1</span></code>, so
was I. Apparently, that's just what GCC prints for that. Weird.)
</p>
<h5>
<a name="boost_yap.manual.an_expression_template_primer.h1"></a>
<span class="phrase"><a name="boost_yap.manual.an_expression_template_primer.doing_something_useful_with_it"></a></span><a class="link" href="manual.html#boost_yap.manual.an_expression_template_primer.doing_something_useful_with_it">Doing
Something Useful With It</a>
</h5>
<p>
Now we've seen a simple expression both described as a C++ AST and captured
as a Boost.YAP expression. This just introduces the expression template mechanism;
what do we do with it once we have an expression template? Consider one of
the examples from the intro:
</p>
<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">v1</span> <span class="special">=</span> <span class="special">{/*</span> <span class="special">...</span> <span class="special">*/};</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">v2</span> <span class="special">=</span> <span class="identifier">sort</span><span class="special">(</span><span class="identifier">v</span><span class="special">)</span> <span class="special">|</span> <span class="identifier">unique</span><span class="special">;</span>
</pre>
<p>
The rest of the tutorial will explain in greater detail how Boost.YAP can
be used in situations like this, but the brief version is this:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
Use Boost.YAP to capture an expression. In this case, something like
<code class="computeroutput"><span class="keyword">auto</span> <span class="identifier">expr</span>
<span class="special">=</span> <span class="identifier">sort</span><span class="special">(</span><span class="identifier">v</span><span class="special">)</span> <span class="special">|</span> <span class="identifier">unique</span><span class="special">;</span></code>.
</li>
<li class="listitem">
Use the Boost.YAP <code class="computeroutput"><a class="link" href="../boost/yap/transform.html" title="Function template transform">transform()</a></code>
algorithm to transform the expression into what you want. In this case,
something like <code class="computeroutput"><span class="keyword">auto</span> <span class="identifier">desired_expr</span>
<span class="special">=</span> <span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">expr</span><span class="special">,</span> <span class="identifier">my_transform</span><span class="special">);</span></code>, which turns the concise form <code class="computeroutput"><span class="identifier">sort</span><span class="special">(</span><span class="identifier">v</span><span class="special">)</span> <span class="special">|</span> <span class="identifier">unique</span></code>
into the more verbose calls required by the standard algorithm APIs.
Note that the resulting expression can be transformed repeatedly if this
is desirable.
</li>
<li class="listitem">
Evauate the final expression, either using <code class="computeroutput"><a class="link" href="../boost/yap/evaluate.html" title="Function template evaluate">evaluate()</a></code>
or a call to <code class="computeroutput"><a class="link" href="../boost/yap/transform.html" title="Function template transform">transform()</a></code>
that transforms the final expression into an evaluated result.
</li>
</ul></div>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_yap.manual.the_yap_way"></a><a class="link" href="manual.html#boost_yap.manual.the_yap_way" title="The YAP Way">The YAP Way</a>
</h3></div></div></div>
<p>
There are certain idioms that Boost.YAP is written to support. Before getting
into the nuts and bolts of how Boost.YAP operates, let's define these idioms.
</p>
<h5>
<a name="boost_yap.manual.the_yap_way.h0"></a>
<span class="phrase"><a name="boost_yap.manual.the_yap_way._code__phrase_role__identifier__evaluate__phrase__phrase_role__special_____phrase__phrase_role__identifier__transform__phrase__phrase_role__special_______phrase___code_"></a></span><a class="link" href="manual.html#boost_yap.manual.the_yap_way._code__phrase_role__identifier__evaluate__phrase__phrase_role__special_____phrase__phrase_role__identifier__transform__phrase__phrase_role__special_______phrase___code_"><code class="computeroutput"><span class="identifier">evaluate</span><span class="special">(</span><span class="identifier">transform</span><span class="special">())</span></code></a>
</h5>
<p>
This is the main idiom you'll see reinforced in the examples. The idea is
that you capture an expression:
</p>
<pre class="programlisting"><span class="keyword">auto</span> <span class="identifier">expr_0</span> <span class="special">=</span> <span class="comment">/* ... */</span> <span class="special">;</span>
</pre>
<p>
then transform it one or more times:
</p>
<pre class="programlisting"><span class="keyword">auto</span> <span class="identifier">expr_1</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">expr_0</span><span class="special">,</span> <span class="identifier">my_transform_1</span><span class="special">);</span>
<span class="keyword">auto</span> <span class="identifier">expr_2</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">expr_1</span><span class="special">,</span> <span class="identifier">my_transform_2</span><span class="special">);</span>
<span class="comment">// ...</span>
<span class="keyword">auto</span> <span class="identifier">expr_n</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">expr_n_minus_1</span><span class="special">,</span> <span class="identifier">my_transform_n</span><span class="special">);</span>
</pre>
<p>
and then finally you evaluate it:
</p>
<pre class="programlisting"><span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">evaluate</span><span class="special">(</span><span class="identifier">expr_n</span><span class="special">);</span>
</pre>
<p>
Each call to <code class="computeroutput"><a class="link" href="../boost/yap/transform.html" title="Function template transform">transform()</a></code> here produces a new <a class="link" href="concepts.html#boost_yap.concepts.expression">Expression</a> that can subsequently
be transformed. This is conceptually similar to what happens inside many
compilers. Capturing the expression is analogous to the compiler's parse;
the transformations are analogous to optimization passes; and the evaluation
is analogous to code generation.
</p>
<p>
This keeps the meaning of your code quite clear and easy to follow. For this
reason, I think you should try to use Boost.YAP in this way when you can.
</p>
<h5>
<a name="boost_yap.manual.the_yap_way.h1"></a>
<span class="phrase"><a name="boost_yap.manual.the_yap_way._code__phrase_role__identifier__transform__phrase__phrase_role__special______phrase___code__as_evaluate"></a></span><a class="link" href="manual.html#boost_yap.manual.the_yap_way._code__phrase_role__identifier__transform__phrase__phrase_role__special______phrase___code__as_evaluate"><code class="computeroutput"><span class="identifier">transform</span><span class="special">()</span></code>-as-evaluate</a>
</h5>
<p>
This is a variant of <code class="computeroutput"><span class="identifier">evaluate</span><span class="special">(</span><span class="identifier">transform</span><span class="special">())</span></code>, where the <code class="computeroutput"><a class="link" href="../boost/yap/evaluate.html" title="Function template evaluate">evaluate()</a></code>
call at the end is unnecessary, because the final (or perhaps only) transform
does all the evaluation we need.
</p>
<p>
For instance, here is the <code class="computeroutput"><span class="identifier">get_arity</span></code>
transform object used in the <a class="link" href="manual.html#boost_yap.manual.examples.calc3" title="Calc3">Calc3</a>
example (don't worry too much about the implementation — we'll return
to this later in the docs in much greater detail):
</p>
<p>
</p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">get_arity</span>
<span class="special">{</span>
<span class="comment">// Base case 1: Match a placeholder terminal, and return its arity as the</span>
<span class="comment">// result.</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">long</span> <span class="keyword">long</span> <span class="identifier">I</span><span class="special">&gt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">llong</span><span class="special">&lt;</span><span class="identifier">I</span><span class="special">&gt;</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_tag</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">&gt;,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">placeholder</span><span class="special">&lt;</span><span class="identifier">I</span><span class="special">&gt;)</span>
<span class="special">{</span> <span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">llong_c</span><span class="special">&lt;</span><span class="identifier">I</span><span class="special">&gt;;</span> <span class="special">}</span>
<span class="comment">// Base case 2: Match any other terminal. Return 0; non-placeholders do</span>
<span class="comment">// not contribute to arity.</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_tag</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">&gt;,</span> <span class="identifier">T</span> <span class="special">&amp;&amp;)</span>
<span class="special">{</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">literals</span><span class="special">;</span>
<span class="keyword">return</span> <span class="number">0</span><span class="identifier">_c</span><span class="special">;</span>
<span class="special">}</span>
<span class="comment">// Recursive case: Match any expression not covered above, and return the</span>
<span class="comment">// maximum of its children's arities.</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">Kind</span><span class="special">,</span> <span class="keyword">typename</span><span class="special">...</span> <span class="identifier">Arg</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_tag</span><span class="special">&lt;</span><span class="identifier">Kind</span><span class="special">&gt;,</span> <span class="identifier">Arg</span> <span class="special">&amp;&amp;...</span> <span class="identifier">arg</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">maximum</span><span class="special">(</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">make_tuple</span><span class="special">(</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">as_expr</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special">&lt;</span><span class="identifier">Arg</span><span class="special">&gt;(</span><span class="identifier">arg</span><span class="special">)),</span>
<span class="identifier">get_arity</span><span class="special">{}</span>
<span class="special">)...</span>
<span class="special">)</span>
<span class="special">);</span>
<span class="special">}</span>
<span class="special">};</span>
</pre>
<p>
</p>
<p>
Here is how this might be used:
</p>
<pre class="programlisting"><span class="keyword">auto</span> <span class="identifier">expr</span> <span class="special">=</span> <span class="number">1</span><span class="identifier">_p</span> <span class="special">*</span> <span class="number">2</span><span class="identifier">_p</span><span class="special">;</span>
<span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">arity</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">expr</span><span class="special">,</span> <span class="identifier">get_arity</span><span class="special">{});</span>
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">arity</span><span class="special">.</span><span class="identifier">value</span> <span class="special">==</span> <span class="number">2</span><span class="special">,</span> <span class="string">"Called with wrong number of args."</span><span class="special">);</span>
</pre>
<p>
In this case, <code class="computeroutput"><a class="link" href="../boost/yap/transform.html" title="Function template transform">transform()</a></code> produces a non-<a class="link" href="concepts.html#boost_yap.concepts.expression">Expression</a>
value, all by itself. We got our result without ever needing to call <code class="computeroutput"><a class="link" href="../boost/yap/evaluate.html" title="Function template evaluate">evaluate()</a></code>.
</p>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../doc/src/images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td align="left" valign="top"><p>
Whether <code class="computeroutput"><a class="link" href="../boost/yap/transform.html" title="Function template transform">transform()</a></code> returns an <a class="link" href="concepts.html#boost_yap.concepts.expression">Expression</a>
or non-<a class="link" href="concepts.html#boost_yap.concepts.expression">Expression</a>
is entirely up to the caller. The transform object passed as the second
argument to <code class="computeroutput"><a class="link" href="../boost/yap/transform.html" title="Function template transform">transform()</a></code> defines what <code class="computeroutput"><a class="link" href="../boost/yap/transform.html" title="Function template transform">transform()</a></code>'s return type will be.
</p></td></tr>
</table></div>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_yap.manual.expressions"></a><a class="link" href="manual.html#boost_yap.manual.expressions" title="Expressions">Expressions</a>
</h3></div></div></div>
<p>
Boost.YAP consists of expressions and functions that operate on them. A function
that takes an expression will accept any type that models the <a class="link" href="concepts.html#boost_yap.concepts.expression">Expression</a>
concept.
</p>
<p>
For a type <code class="computeroutput"><span class="identifier">T</span></code> to model the
<a class="link" href="concepts.html#boost_yap.concepts.expression">Expression</a> concept,
<code class="computeroutput"><span class="identifier">T</span></code> must contain at least an
<code class="computeroutput"><a class="link" href="../boost/yap/expr_kind.html" title="Type expr_kind">expr_kind</a></code>
(terminal, plus-operation, etc.) and a <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;&gt;</span></code> of values. That's it.
</p>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../doc/src/images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td align="left" valign="top"><p>
The <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;&gt;</span></code>
of values is constrained, based on the kind of the expression; see the
full <a class="link" href="concepts.html#boost_yap.concepts.expression">Expression</a> documentation
for details.
</p></td></tr>
</table></div>
<p>
Here's an example of an expression:
</p>
<p>
</p>
<pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">Kind</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">minimal_expr</span>
<span class="special">{</span>
<span class="keyword">static</span> <span class="keyword">const</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">kind</span> <span class="special">=</span> <span class="identifier">Kind</span><span class="special">;</span>
<span class="identifier">Tuple</span> <span class="identifier">elements</span><span class="special">;</span>
<span class="special">};</span>
</pre>
<p>
</p>
<p>
That's a template that models <a class="link" href="concepts.html#boost_yap.concepts.expressiontemplate">ExpressionTemplate</a>.
Instantiated with the proper template parameters, it produces <a class="link" href="concepts.html#boost_yap.concepts.expression">Expressions</a>.
</p>
<p>
Ok, so it's not that interesting by itself — <code class="computeroutput"><span class="identifier">minimal_expr</span></code>
has no operations defined for it. But we can still use it with the Boost.YAP
functions that take an <a class="link" href="concepts.html#boost_yap.concepts.expression">Expression</a>.
Let's make a Boost.YAP plus-expression manually:
</p>
<p>
</p>
<pre class="programlisting"><span class="keyword">auto</span> <span class="identifier">left</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_terminal</span><span class="special">&lt;</span><span class="identifier">minimal_expr</span><span class="special">&gt;(</span><span class="number">1</span><span class="special">);</span>
<span class="keyword">auto</span> <span class="identifier">right</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_terminal</span><span class="special">&lt;</span><span class="identifier">minimal_expr</span><span class="special">&gt;(</span><span class="number">41</span><span class="special">);</span>
<span class="keyword">auto</span> <span class="identifier">expr</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_expression</span><span class="special">&lt;</span>
<span class="identifier">minimal_expr</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">plus</span>
<span class="special">&gt;(</span><span class="identifier">left</span><span class="special">,</span> <span class="identifier">right</span><span class="special">);</span>
</pre>
<p>
</p>
<p>
If we evaluate it using <code class="computeroutput"><a class="link" href="../boost/yap/evaluate.html" title="Function template evaluate">evaluate()</a></code>,
it does what you would expect:
</p>
<p>
</p>
<pre class="programlisting"><span class="keyword">auto</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">evaluate</span><span class="special">(</span><span class="identifier">expr</span><span class="special">);</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">result</span> <span class="special">&lt;&lt;</span> <span class="string">"\n"</span><span class="special">;</span> <span class="comment">// prints "42"</span>
</pre>
<p>
</p>
<p>
One more thing. It is important to remember that Boost.YAP expressions are
all-lazy, all the time. There is no auto-evaluation of a Boost.YAP expression
like there is with normal C++ expressions. If you want your expressions to
be evaluated, you must call <code class="computeroutput"><a class="link" href="../boost/yap/evaluate.html" title="Function template evaluate">evaluate()</a></code>,
or define non-lazy operations that force evaluation where and when you want
it. This last approach is usually the right one, and there are lots of examples
of how to do this in the <a class="link" href="manual.html#boost_yap.manual.examples" title="Examples">Examples</a>
section. In particular, checkout the <a class="link" href="manual.html#boost_yap.manual.examples.lazy_vector" title="Lazy Vector">Lazy
Vector</a> and <a class="link" href="manual.html#boost_yap.manual.examples.tarray" title="TArray">TArray</a>
examples.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_yap.manual.mix_and_match_expression_templates"></a><a class="link" href="manual.html#boost_yap.manual.mix_and_match_expression_templates" title="Mix-and-Match Expression Templates">Mix-and-Match
Expression Templates</a>
</h3></div></div></div>
<p>
Because Boost.YAP operates on <a class="link" href="concepts.html#boost_yap.concepts.expression">Expressions</a>,
it is possible to mix and match <a class="link" href="concepts.html#boost_yap.concepts.expression">Expressions</a>
that are instantiations of different templates.
</p>
<p>
Here's why that's important. Say we have two types in a library. <code class="computeroutput"><span class="identifier">S</span></code> is a string type, and <code class="computeroutput"><span class="identifier">M</span></code>
is a matrix type. In the code here, <code class="computeroutput"><span class="identifier">s</span></code>
and <code class="computeroutput"><span class="identifier">m</span></code> are objects of types
<code class="computeroutput"><span class="identifier">S</span></code> and <code class="computeroutput"><span class="identifier">M</span></code>
respectively. Say we also have typical operator overloads for these types,
so <code class="computeroutput"><span class="identifier">m</span> <span class="special">*</span>
<span class="identifier">m</span></code> and <code class="computeroutput"><span class="identifier">s</span><span class="special">[</span><span class="number">0</span><span class="special">]</span></code>
are well-formed expressions, but <code class="computeroutput"><span class="identifier">m</span><span class="special">[</span><span class="number">0</span><span class="special">]</span></code>
and <code class="computeroutput"><span class="identifier">s</span> <span class="special">*</span>
<span class="identifier">s</span></code> are not.
</p>
<p>
To use these with Boost.YAP I might write an expression template for each:
</p>
<pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;...&gt;</span>
<span class="keyword">struct</span> <span class="identifier">m_expr</span>
<span class="special">{</span>
<span class="comment">// ...</span>
<span class="special">};</span>
<span class="identifier">BOOST_YAP_USER_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">times</span><span class="special">,</span> <span class="identifier">m_expr</span><span class="special">,</span> <span class="identifier">m_expr</span><span class="special">)</span>
<span class="keyword">template</span> <span class="special">&lt;...&gt;</span>
<span class="keyword">struct</span> <span class="identifier">s_expr</span>
<span class="special">{</span>
<span class="comment">// ...</span>
<span class="identifier">BOOST_YAP_USER_SUBSCRIPT_OPERATOR</span><span class="special">(::</span><span class="identifier">s_expr</span><span class="special">)</span>
<span class="special">};</span>
</pre>
<p>
With this, I might write a Boost.YAP expression like:
</p>
<pre class="programlisting"><span class="identifier">some_expr_producing_func</span><span class="special">(</span><span class="identifier">S</span><span class="special">(</span><span class="string">"my_matrix"</span><span class="special">))</span> <span class="special">*</span> <span class="identifier">some_matrix</span>
</pre>
<p>
I can transform this expression however I like, and do not have to worry
about the fact that it contains expressions instantiated from different templates.
</p>
<p>
If Boost.YAP required an expression to be instantiated from a single expression
template <code class="computeroutput"><span class="identifier">expr</span><span class="special">&lt;&gt;</span></code>,
<code class="computeroutput"><span class="identifier">expr</span><span class="special">&lt;&gt;</span></code>
would have to have both operators. This means that all of a sudden <code class="computeroutput"><span class="identifier">s</span> <span class="special">*</span> <span class="identifier">s</span></code>
and <code class="computeroutput"><span class="identifier">m</span><span class="special">[</span><span class="number">0</span><span class="special">]</span></code> would be
well-formed expressions within a Boost.YAP expression, but <span class="bold"><strong>not</strong></span>
for the real types <code class="computeroutput"><span class="identifier">S</span></code> and
<code class="computeroutput"><span class="identifier">M</span></code> respectively. That would
be super weird.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_yap.manual.kinds_of_expressions"></a><a class="link" href="manual.html#boost_yap.manual.kinds_of_expressions" title="Kinds of Expressions">Kinds of Expressions</a>
</h3></div></div></div>
<p>
Most of the expression kinds are the overloadable operators (<code class="computeroutput"><span class="keyword">operator</span><span class="special">!()</span></code>,
<code class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;&lt;=()</span></code>,
etc.), See <code class="computeroutput"><a class="link" href="../boost/yap/expr_kind.html" title="Type expr_kind">expr_kind</a></code>
for the full list.
</p>
<p>
There are three special kinds of expressions:
</p>
<div class="variablelist">
<p class="title"><b></b></p>
<dl class="variablelist">
<dt><span class="term"><a class="link" href="../boost/yap/expr_kind.html#boost.yap.expr_kind.terminal"><code class="computeroutput"><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span></code></a></span></dt>
<dd><p>
A terminal contains a non-Expression value, and represents a leaf-node
in an expression tree. A terminal may have a <code class="computeroutput"><a class="link" href="../boost/yap/placeholder.html" title="Struct template placeholder">placeholder&lt;&gt;</a></code>
value, in which case it acts as a placeholder.
</p></dd>
<dt><span class="term"><a class="link" href="../boost/yap/expr_kind.html#boost.yap.expr_kind.if_else"><code class="computeroutput"><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">if_else</span></code></a></span></dt>
<dd><p>
An <code class="computeroutput"><span class="identifier">if_else</span></code> expression
is analogous to the C++ ternary operator (<code class="computeroutput"><span class="special">?:</span></code>).
It's up to you to make sure that the conditional expression given to
<code class="computeroutput"><span class="identifier">if_else</span></code> can be converted
to <code class="computeroutput"><span class="keyword">bool</span></code>; Boost.YAP does
not check this.
</p></dd>
<dt><span class="term"><a class="link" href="../boost/yap/expr_kind.html#boost.yap.expr_kind.expr_ref"><code class="computeroutput"><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">expr_ref</span></code></a></span></dt>
<dd><p>
An <code class="computeroutput"><span class="identifier">expr_ref</span></code> expression
is one that acts as a (possibly <code class="computeroutput"><span class="keyword">const</span></code>)
lvalue reference to another expression. It exists to prevent unnecessary
copies of expressions.
</p></dd>
</dl>
</div>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_yap.manual.operators"></a><a class="link" href="manual.html#boost_yap.manual.operators" title="Operators">Operators</a>
</h3></div></div></div>
<p>
Let's see an expression template type with some operators:
</p>
<p>
</p>
<pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">Kind</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">lazy_vector_expr</span>
<span class="special">{</span>
<span class="keyword">static</span> <span class="keyword">const</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">kind</span> <span class="special">=</span> <span class="identifier">Kind</span><span class="special">;</span>
<span class="identifier">Tuple</span> <span class="identifier">elements</span><span class="special">;</span>
<span class="comment">// Note that this does not return an expression; it is greedily evaluated.</span>
<span class="keyword">auto</span> <span class="keyword">operator</span><span class="special">[]</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">n</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span>
<span class="special">};</span>
<span class="identifier">BOOST_YAP_USER_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">plus</span><span class="special">,</span> <span class="identifier">lazy_vector_expr</span><span class="special">,</span> <span class="identifier">lazy_vector_expr</span><span class="special">)</span>
<span class="identifier">BOOST_YAP_USER_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">minus</span><span class="special">,</span> <span class="identifier">lazy_vector_expr</span><span class="special">,</span> <span class="identifier">lazy_vector_expr</span><span class="special">)</span>
</pre>
<p>
</p>
<p>
Those macros are used to define operator overloads that return <a class="link" href="concepts.html#boost_yap.concepts.expression">Expressions</a>.
As shown here, that sort of operator can be mixed with normal, non-lazy ones
— the <code class="computeroutput"><span class="keyword">operator</span><span class="special">[]</span></code>
is a normal eager function.
</p>
<p>
Use of the macros is not necessary (you can write your own operators that
return <a class="link" href="concepts.html#boost_yap.concepts.expression">Expressions</a> if
you like), but it is suitable 99% of the time.
</p>
<p>
Making the operators easy to define like this allows you to define custom
expression templates that have only the operators defined that are appropriate
for your use case.
</p>
<p>
Detailed documentation on all the available macros can be found later in
the <a class="link" href="manual.html#boost_yap.manual.operator_macros" title="Operator Macros">Operator Macros</a>
section.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_yap.manual.transforming_expressions"></a><a class="link" href="manual.html#boost_yap.manual.transforming_expressions" title="Transforming Expressions">Transforming
Expressions</a>
</h3></div></div></div>
<p>
Transformations in Boost.YAP are done using the <code class="computeroutput"><a class="link" href="../boost/yap/transform.html" title="Function template transform">transform()</a></code>
function.
</p>
<p>
Let's take another look at the example expression from the intro:
</p>
<p>
<span class="inlinemediaobject"><img src="../yap/img/expr.png" alt="expr"></span>
</p>
<p>
Consider a call to <code class="computeroutput"><a class="link" href="../boost/yap/transform.html" title="Function template transform">transform()</a></code>,
operating on that expression:
</p>
<pre class="programlisting"><span class="keyword">auto</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">expr</span><span class="special">,</span> <span class="identifier">xform</span><span class="special">);</span>
</pre>
<p>
Boost.YAP's <code class="computeroutput"><a class="link" href="../boost/yap/transform.html" title="Function template transform">transform()</a></code> first looks at the top level
expression, which in this case is a <code class="computeroutput"><span class="special">+</span></code>
expression. If the transform object <code class="computeroutput"><span class="identifier">xform</span></code>
matches the <code class="computeroutput"><span class="special">+</span></code> expression, <code class="computeroutput"><a class="link" href="../boost/yap/transform.html" title="Function template transform">transform()</a></code> is done; it just returns
<code class="computeroutput"><span class="identifier">xform</span><span class="special">(</span><span class="identifier">expr</span><span class="special">)</span></code>.
If <code class="computeroutput"><span class="identifier">xform</span></code> does not match the
<code class="computeroutput"><span class="special">+</span></code> expression, <code class="computeroutput"><a class="link" href="../boost/yap/transform.html" title="Function template transform">transform()</a></code> transforms all its operands
(which for <code class="computeroutput"><span class="keyword">operator</span><span class="special">+()</span></code>
is just the left and right operands), and returns a new <code class="computeroutput"><span class="special">+</span></code>
expression with those transformed operands. What I mean by "match"
is covered in detail below.
</p>
<p>
The overall effect of this is that <code class="computeroutput"><a class="link" href="../boost/yap/transform.html" title="Function template transform">transform()</a></code>
effectively copies an <code class="computeroutput"><span class="identifier">expr</span></code>
node that <span class="bold"><strong>does not</strong></span> match <code class="computeroutput"><span class="identifier">xform</span></code>,
and returns a transformed node for an <code class="computeroutput"><span class="identifier">expr</span></code>
node that <span class="bold"><strong>does</strong></span> match <code class="computeroutput"><span class="identifier">xform</span></code>.
</p>
<p>
<code class="computeroutput"><a class="link" href="../boost/yap/transform.html" title="Function template transform">transform()</a></code> can also take multiple transform
objects. If you call it with N transform objects, it will attempt to match
each of the N transforms to a given expression, one at a time and in their
given order. Only if no transform matches an expression does the copy-and-recurse
behavior kick in.
</p>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../doc/src/images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td align="left" valign="top"><p>
There's another form of <code class="computeroutput"><a class="link" href="../boost/yap/transform.html" title="Function template transform">transform()</a></code>,
<code class="computeroutput"><a class="link" href="../boost/yap/transform_strict.html" title="Function template transform_strict">transform_strict()</a></code>. <code class="computeroutput"><a class="link" href="../boost/yap/transform_strict.html" title="Function template transform_strict">transform_strict()</a></code>
is identical to <code class="computeroutput"><a class="link" href="../boost/yap/transform.html" title="Function template transform">transform()</a></code>
except that it does not copy or recurse into an unmatched expression. Instead,
a failed match is a hard error. This is useful when you have written a
transform that you expect to completely transform an expression, and you
want the compiler to tell you if you've made a mistake.
</p></td></tr>
</table></div>
<p>
One common result of calling <code class="computeroutput"><a class="link" href="../boost/yap/transform.html" title="Function template transform">transform()</a></code>
is that you create a copy of <code class="computeroutput"><span class="identifier">expr</span></code>,
with a few matching nodes transformed. But this does not have to be the result
of calling <code class="computeroutput"><a class="link" href="../boost/yap/transform.html" title="Function template transform">transform()</a></code>, because a Boost.YAP transformation
is free-form; it must return a value, but may do just about anything else.
It can transform an expression into anything — a new expression of
any kind, or even a non-expression value (effectively evaluating the expression).
As before, here is the <code class="computeroutput"><span class="identifier">get_arity</span></code>
transform from the <a class="link" href="manual.html#boost_yap.manual.examples.calc3" title="Calc3">Calc3</a>
example. It returns a value, not an <a class="link" href="concepts.html#boost_yap.concepts.expression">Expression</a>:
</p>
<p>
</p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">get_arity</span>
<span class="special">{</span>
<span class="comment">// Base case 1: Match a placeholder terminal, and return its arity as the</span>
<span class="comment">// result.</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">long</span> <span class="keyword">long</span> <span class="identifier">I</span><span class="special">&gt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">llong</span><span class="special">&lt;</span><span class="identifier">I</span><span class="special">&gt;</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_tag</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">&gt;,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">placeholder</span><span class="special">&lt;</span><span class="identifier">I</span><span class="special">&gt;)</span>
<span class="special">{</span> <span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">llong_c</span><span class="special">&lt;</span><span class="identifier">I</span><span class="special">&gt;;</span> <span class="special">}</span>
<span class="comment">// Base case 2: Match any other terminal. Return 0; non-placeholders do</span>
<span class="comment">// not contribute to arity.</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_tag</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">&gt;,</span> <span class="identifier">T</span> <span class="special">&amp;&amp;)</span>
<span class="special">{</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">literals</span><span class="special">;</span>
<span class="keyword">return</span> <span class="number">0</span><span class="identifier">_c</span><span class="special">;</span>
<span class="special">}</span>
<span class="comment">// Recursive case: Match any expression not covered above, and return the</span>
<span class="comment">// maximum of its children's arities.</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">Kind</span><span class="special">,</span> <span class="keyword">typename</span><span class="special">...</span> <span class="identifier">Arg</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_tag</span><span class="special">&lt;</span><span class="identifier">Kind</span><span class="special">&gt;,</span> <span class="identifier">Arg</span> <span class="special">&amp;&amp;...</span> <span class="identifier">arg</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">maximum</span><span class="special">(</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">make_tuple</span><span class="special">(</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">as_expr</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special">&lt;</span><span class="identifier">Arg</span><span class="special">&gt;(</span><span class="identifier">arg</span><span class="special">)),</span>
<span class="identifier">get_arity</span><span class="special">{}</span>
<span class="special">)...</span>
<span class="special">)</span>
<span class="special">);</span>
<span class="special">}</span>
<span class="special">};</span>
</pre>
<p>
</p>
<p>
Also, note that in this case the transform is stateless, but you could also
give your transform objects data members containing contextual state:
</p>
<p>
</p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">take_nth</span>
<span class="special">{</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_tag</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">&gt;,</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">vec</span><span class="special">)</span>
<span class="special">{</span> <span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_terminal</span><span class="special">(</span><span class="identifier">vec</span><span class="special">[</span><span class="identifier">n</span><span class="special">]);</span> <span class="special">}</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">n</span><span class="special">;</span>
<span class="special">};</span>
</pre>
<p>
</p>
<div class="tip"><table border="0" summary="Tip">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="../../../doc/src/images/tip.png"></td>
<th align="left">Tip</th>
</tr>
<tr><td align="left" valign="top"><p>
Often when you create an expression, you will want to evaluate it in different
contexts, changing its evaluation — or even entire meaning —
in each context. <code class="computeroutput"><a class="link" href="../boost/yap/evaluate.html" title="Function template evaluate">evaluate()</a></code>
is wrong for this task, since it only takes values for substitution into
placeholders. In these situations, you should instead use multiple transforms
that evaluate your expression in different ways.
</p></td></tr>
</table></div>
<h5>
<a name="boost_yap.manual.transforming_expressions.h0"></a>
<span class="phrase"><a name="boost_yap.manual.transforming_expressions.when__functionname_alt__boost__yap__transform___code__phrase_role__identifier__transform__phrase__phrase_role__special______phrase___code___functionname__recurses"></a></span><a class="link" href="manual.html#boost_yap.manual.transforming_expressions.when__functionname_alt__boost__yap__transform___code__phrase_role__identifier__transform__phrase__phrase_role__special______phrase___code___functionname__recurses">When
transform() Recurses</a>
</h5>
<p>
As described above, <code class="computeroutput"><a class="link" href="../boost/yap/transform.html" title="Function template transform">transform()</a></code>
only recurses when it <span class="bold"><strong>does not</strong></span> find a match.
This means that if you want to transform a nonterminal, say an <code class="computeroutput"><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">call</span></code> expression we'll call <code class="computeroutput"><span class="identifier">C</span></code>, and <span class="bold"><strong>also</strong></span>
<code class="computeroutput"><span class="identifier">C</span></code>'s subexpressions, you must
explicitly call <code class="computeroutput"><a class="link" href="../boost/yap/transform.html" title="Function template transform">transform()</a></code> yourself in your transform
that matches <code class="computeroutput"><span class="identifier">C</span></code>. You can see
this kind of explicit <code class="computeroutput"><a class="link" href="../boost/yap/transform.html" title="Function template transform">transform()</a></code>
call in the recursive case of <code class="computeroutput"><span class="identifier">get_arity</span></code>
in the example code above.
</p>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../doc/src/images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td align="left" valign="top"><p>
The code you write with Boost.YAP is likely going to be very generic, especially
when you're writing a transform. <code class="computeroutput"><a class="link" href="../boost/yap/transform.html" title="Function template transform">transform()</a></code>
requires an <a class="link" href="concepts.html#boost_yap.concepts.expression">Expression</a>
as its first parameter. In situations when you want to make sure that the
first parameter you pass to <code class="computeroutput"><a class="link" href="../boost/yap/transform.html" title="Function template transform">transform()</a></code>
is always a Boost.YAP expression, use the <code class="computeroutput"><a class="link" href="../boost/yap/as_exp_1_3_49_8_2_2_1_1_15.html" title="Function template as_expr">as_expr()</a></code>
function. This is commonly needed when writing a transform in which you
manually recurse by calling <code class="computeroutput"><a class="link" href="../boost/yap/transform.html" title="Function template transform">transform()</a></code>
inside one of your transform overloads.
</p></td></tr>
</table></div>
<h5>
<a name="boost_yap.manual.transforming_expressions.h1"></a>
<span class="phrase"><a name="boost_yap.manual.transforming_expressions.transform_matching"></a></span><a class="link" href="manual.html#boost_yap.manual.transforming_expressions.transform_matching">Transform
Matching</a>
</h5>
<p>
In Boost.YAP a <a class="link" href="concepts.html#boost_yap.concepts.transform">Transform</a>
is a <a href="http://en.cppreference.com/w/cpp/concept/Callable" target="_top">Callable</a>
that has <span class="bold"><strong>zero or more</strong></span> overloads that model
the <a class="link" href="concepts.html#boost_yap.concepts.expressiontransform">ExpressionTransform</a>
or <a class="link" href="concepts.html#boost_yap.concepts.tagtransform">TagTransform</a> concepts.
</p>
<p>
An <a class="link" href="concepts.html#boost_yap.concepts.expressiontransform">ExpressionTransform</a>
overload takes a single parameter whose type is the expression to be transformed.
Here's one from a transform object in the <a class="link" href="manual.html#boost_yap.manual.examples.future_group" title="Future Group">Future
Group</a> example:
</p>
<p>
</p>
<pre class="programlisting"><span class="comment">// Transform left || right -&gt; transform(left).</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">U</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span>
<span class="identifier">future_expr</span><span class="special">&lt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">logical_or</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">U</span><span class="special">&gt;</span>
<span class="special">&gt;</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">or_expr</span>
<span class="special">)</span> <span class="special">{</span>
<span class="comment">// Recursively transform the left side, and return the result.</span>
<span class="comment">// Without the recursion, we might return a terminal expression here</span>
<span class="comment">// insead of a tuple.</span>
<span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">left</span><span class="special">(</span><span class="identifier">or_expr</span><span class="special">),</span> <span class="special">*</span><span class="keyword">this</span><span class="special">);</span>
<span class="special">}</span>
</pre>
<p>
</p>
<p>
<a class="link" href="concepts.html#boost_yap.concepts.expressiontransform">ExpressionTransforms</a>
are most useful when you want to transform a narrow set of expression types
(perhaps only one). In particular, you can distinguish between <code class="computeroutput"><span class="keyword">const</span></code> and non-<code class="computeroutput"><span class="keyword">const</span></code>,
reference and non-reference, etc., in the expression and its operands in
a way that you have less control over with the other kind of transform.
</p>
<p>
A <a class="link" href="concepts.html#boost_yap.concepts.tagtransform">TagTransform</a> overload
takes a tag that indicates the <code class="computeroutput"><a class="link" href="../boost/yap/expr_kind.html" title="Type expr_kind">expr_kind</a></code> of the expression
to be transformed, and then (loosely) the value of each operand of the expression
to be transformed. This looseness prevents you from needing to write out
the full type of the matched expression. Here's one from the <a class="link" href="manual.html#boost_yap.manual.examples.pipable_algorithms" title="Pipable Algorithms">Pipable
Algorithms</a> example:
</p>
<p>
</p>
<pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Range</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="keyword">operator</span><span class="special">()(</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_tag</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">call</span><span class="special">&gt;,</span>
<span class="identifier">algorithm_t</span> <span class="identifier">a</span><span class="special">,</span>
<span class="identifier">Range</span> <span class="special">&amp;</span> <span class="identifier">r</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">call_algorithm</span><span class="special">(</span><span class="identifier">a</span><span class="special">,</span> <span class="identifier">r</span><span class="special">);</span>
<span class="special">}</span>
</pre>
<p>
</p>
<p>
<a class="link" href="concepts.html#boost_yap.concepts.tagtransform">TagTransforms</a> are
most useful when the transform needs to match an expression without regard
to whether its operands are <a class="link" href="../boost/yap/expr_kind.html#boost.yap.expr_kind.expr_ref"><code class="computeroutput"><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">expr_ref</span></code></a> expressions, or —
if they are terminals — whether they contain or refer to their values.
<a class="link" href="concepts.html#boost_yap.concepts.tagtransform">TagTransforms</a> tend
to be far more concise.
</p>
<h5>
<a name="boost_yap.manual.transforming_expressions.h2"></a>
<span class="phrase"><a name="boost_yap.manual.transforming_expressions.a_more_rigorous_description_of_tagtransform_parameters"></a></span><a class="link" href="manual.html#boost_yap.manual.transforming_expressions.a_more_rigorous_description_of_tagtransform_parameters">A
More Rigorous Description of TagTransform Parameters</a>
</h5>
<p>
That "(loosely)" before probably bothered you, right? Me too. Each
non-tag parameter is passed to a <a class="link" href="concepts.html#boost_yap.concepts.tagtransform">TagTransform</a>
by calling an operand accessor appropriate to <code class="computeroutput"><span class="identifier">expr</span></code>'s
kind, and then calling a terminal-specific version of <code class="computeroutput"><a class="link" href="../boost/yap/value.html" title="Function template value">value()</a></code>
(<code class="computeroutput"><span class="identifier">terminal_value</span><span class="special">()</span></code>)
on the result. For example, consider a plus expression <code class="computeroutput"><span class="identifier">expr</span></code>.
The <a class="link" href="concepts.html#boost_yap.concepts.tagtransform">TagTransform</a> on
a transform object <code class="computeroutput"><span class="identifier">xform</span></code>
would be called like this:
</p>
<pre class="programlisting"><span class="identifier">xform</span><span class="special">(</span><span class="identifier">plus_tag</span><span class="special">,</span> <span class="identifier">terminal_value</span><span class="special">(</span><span class="identifier">left</span><span class="special">(</span><span class="identifier">expr</span><span class="special">)),</span> <span class="identifier">terminal_value</span><span class="special">(</span><span class="identifier">right</span><span class="special">(</span><span class="identifier">expr</span><span class="special">)))</span>
</pre>
<p>
The operand accessors (<code class="computeroutput"><a class="link" href="../boost/yap/left.html" title="Function template left">left()</a></code>
and <code class="computeroutput"><a class="link" href="../boost/yap/right.html" title="Function template right">right()</a></code> in this example) all dereference
<a class="link" href="../boost/yap/expr_kind.html#boost.yap.expr_kind.expr_ref"><code class="computeroutput"><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">expr_ref</span></code></a>
expressions before operating on them, and <code class="computeroutput"><span class="identifier">terminal_value</span><span class="special">()</span></code> does the same.
</p>
<p>
<code class="computeroutput"><span class="identifier">terminal_value</span><span class="special">()</span></code>
works much like <code class="computeroutput"><a class="link" href="../boost/yap/value.html" title="Function template value">value()</a></code>, except that it does not
take the value of a <span class="bold"><strong>nonterminal</strong></span> unary expression;
it just forwards a nonterminal through. It still takes values out of terminals
and unwraps <a class="link" href="../boost/yap/expr_kind.html#boost.yap.expr_kind.expr_ref"><code class="computeroutput"><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">expr_ref</span></code></a>
expressions, though.
</p>
<p>
The auto-unwrapping of terminals means that you can effectively ignore the
presence of <a class="link" href="../boost/yap/expr_kind.html#boost.yap.expr_kind.expr_ref"><code class="computeroutput"><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">expr_ref</span></code></a>
expressions when writing a <a class="link" href="concepts.html#boost_yap.concepts.tagtransform">TagTransform</a>.
You can also just deal with the values inside terminals, and not the terminals
themselves. Also, you can match all terminal value qualifiers (<code class="computeroutput"><span class="keyword">const</span></code> or not, lvalue or rvalue) uniformly
with a <code class="computeroutput"><span class="identifier">T</span> <span class="keyword">const</span>
<span class="special">&amp;</span></code> parameter. Finally, you can
write <a class="link" href="concepts.html#boost_yap.concepts.tagtransform">TagTransform</a>
parameter types that can catch conversions; for instance, you can match any
negation expression containing a terminal, <span class="bold"><strong>or a reference
to one</strong></span>, containing a value convertible to <code class="computeroutput"><span class="keyword">double</span></code>
like this:
</p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">xform</span>
<span class="special">{</span>
<span class="keyword">auto</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">negate_tag</span><span class="special">,</span> <span class="keyword">double</span> <span class="identifier">x</span><span class="special">)</span>
<span class="special">{</span> <span class="keyword">return</span> <span class="comment">/* ... */</span><span class="special">;</span> <span class="special">}</span>
<span class="special">}</span>
</pre>
<p>
That will match a negation of a terminal containing an <code class="computeroutput"><span class="keyword">unsigned</span>
<span class="keyword">int</span></code>, <code class="computeroutput"><span class="keyword">unsigned</span>
<span class="keyword">int</span> <span class="special">&amp;</span></code>,
<code class="computeroutput"><span class="keyword">int</span> <span class="keyword">const</span>
<span class="special">&amp;</span></code>, <code class="computeroutput"><span class="keyword">float</span>
<span class="special">&amp;&amp;</span></code>, etc. It will also match
a negation of a reference to such a terminal.
</p>
<h5>
<a name="boost_yap.manual.transforming_expressions.h3"></a>
<span class="phrase"><a name="boost_yap.manual.transforming_expressions.mixing_the_two_kinds_of_transforms"></a></span><a class="link" href="manual.html#boost_yap.manual.transforming_expressions.mixing_the_two_kinds_of_transforms">Mixing
the Two Kinds of Transforms</a>
</h5>
<p>
You can have two overloads in your transform that match an expression, one
an <a class="link" href="concepts.html#boost_yap.concepts.expressiontransform">ExpressionTransform</a>
and one a <a class="link" href="concepts.html#boost_yap.concepts.tagtransform">TagTransform</a>,
and there will not be any ambiguity. The <a class="link" href="concepts.html#boost_yap.concepts.tagtransform">TagTransform</a>
is matched first, and the <a class="link" href="concepts.html#boost_yap.concepts.expressiontransform">ExpressionTransform</a>
is matched only if the <a class="link" href="concepts.html#boost_yap.concepts.tagtransform">TagTransform</a>
did not. You don't have to worry about ambiguity, but save yourself some
confusion and mix the two kinds of overloads as little as possible.
</p>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../doc/src/images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td align="left" valign="top"><p>
The above only applies when you have an <a class="link" href="concepts.html#boost_yap.concepts.expressiontransform">ExpressionTransform</a>
and a <a class="link" href="concepts.html#boost_yap.concepts.tagtransform">TagTransform</a>
that match <span class="bold"><strong>the same kind of expression</strong></span>.
Having unrelated <a class="link" href="concepts.html#boost_yap.concepts.expressiontransform">ExpressionTransforms</a>
and <a class="link" href="concepts.html#boost_yap.concepts.tagtransform">TagTransforms</a>
within the same transform object is often quite useful.
</p></td></tr>
</table></div>
<h5>
<a name="boost_yap.manual.transforming_expressions.h4"></a>
<span class="phrase"><a name="boost_yap.manual.transforming_expressions.multiple_transform_objects"></a></span><a class="link" href="manual.html#boost_yap.manual.transforming_expressions.multiple_transform_objects">Multiple
Transform Objects</a>
</h5>
<p>
In the case that multiple transform objects are being used in <code class="computeroutput"><a class="link" href="../boost/yap/transform.html" title="Function template transform">transform()</a></code>, the above logic applies
to each one independently before the next one is used. In other words, in
the call <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">expr</span><span class="special">,</span>
<span class="identifier">a</span><span class="special">,</span> <span class="identifier">b</span><span class="special">)</span></code>, <code class="computeroutput"><a class="link" href="../boost/yap/transform.html" title="Function template transform">transform()</a></code> tries to match any <a class="link" href="concepts.html#boost_yap.concepts.tagtransform">TagTransform</a> from <code class="computeroutput"><span class="identifier">a</span></code> to an expression first, then any <a class="link" href="concepts.html#boost_yap.concepts.expressiontransform">ExpressionTransform</a>
from <code class="computeroutput"><span class="identifier">a</span></code>, then any <a class="link" href="concepts.html#boost_yap.concepts.tagtransform">TagTransform</a>
from <code class="computeroutput"><span class="identifier">b</span></code>, and finally any
<a class="link" href="concepts.html#boost_yap.concepts.expressiontransform">ExpressionTransform</a>
from <code class="computeroutput"><span class="identifier">b</span></code>. Only the first matching
overload in this sequence is used; all overloads later in the sequence or
in later transforms, whether they match or not, are simply ignored.
</p>
<h5>
<a name="boost_yap.manual.transforming_expressions.h5"></a>
<span class="phrase"><a name="boost_yap.manual.transforming_expressions.yap_supplied_transforms"></a></span><a class="link" href="manual.html#boost_yap.manual.transforming_expressions.yap_supplied_transforms">YAP-Supplied
Transforms</a>
</h5>
<p>
Boost.YAP comes with a couple of functions that return ready-made transforms,
<code class="computeroutput"><a class="link" href="../boost/yap/replacements.html" title="Function template replacements">replacements()</a></code> and <code class="computeroutput"><a class="link" href="../boost/yap/evaluation.html" title="Function template evaluation">evaluation()</a></code>.
</p>
<p>
The transforms returned by <code class="computeroutput"><a class="link" href="../boost/yap/replacements.html" title="Function template replacements">replacements()</a></code>
replace only placeholder terminals. Placeholder <code class="computeroutput"><span class="identifier">I</span></code>
is replaced by the <code class="computeroutput"><span class="identifier">I</span><span class="special">-</span><span class="number">1</span></code>-th argument passed to <code class="computeroutput"><a class="link" href="../boost/yap/replacements.html" title="Function template replacements">replacements()</a></code>.
Placeholders are <code class="computeroutput"><span class="number">1</span></code>-based for
consistency with other Boost and <code class="computeroutput"><span class="identifier">std</span></code>
placeholders.
</p>
<p>
There are also a couple of specialty transform functions, <code class="computeroutput"><a class="link" href="../boost/yap/replace_placeholders.html" title="Function template replace_placeholders">replace_placeholders()</a></code>
and <code class="computeroutput"><a class="link" href="../boost/yap/evaluate.html" title="Function template evaluate">evaluate()</a></code>. These are convenience functions
that just call <code class="computeroutput"><a class="link" href="../boost/yap/transform.html" title="Function template transform">transform()</a></code> on an expression using
<code class="computeroutput"><a class="link" href="../boost/yap/replacements.html" title="Function template replacements">replacements()</a></code> or <code class="computeroutput"><a class="link" href="../boost/yap/evaluation.html" title="Function template evaluation">evaluation()</a></code>
as the transform, respectively.
</p>
<p>
The behavior of <code class="computeroutput"><a class="link" href="../boost/yap/evaluation.html" title="Function template evaluation">evaluation()</a></code>
is covered in the next section, <a class="link" href="manual.html#boost_yap.manual.evaluating_expressions" title="Evaluating Expressions">Evaluating
Expressions</a>.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_yap.manual.evaluating_expressions"></a><a class="link" href="manual.html#boost_yap.manual.evaluating_expressions" title="Evaluating Expressions">Evaluating Expressions</a>
</h3></div></div></div>
<p>
Boost.YAP expressions are evaluated explicitly, by calling the <code class="computeroutput"><a class="link" href="../boost/yap/evaluate.html" title="Function template evaluate">evaluate()</a></code> function or calling <code class="computeroutput"><a class="link" href="../boost/yap/transform.html" title="Function template transform">transform()</a></code> using a transform object
returned from <code class="computeroutput"><a class="link" href="../boost/yap/evaluation.html" title="Function template evaluation">evaluation()</a></code>. The former is a convenince
function that does the latter.
</p>
<p>
<code class="computeroutput"><a class="link" href="../boost/yap/evaluate.html" title="Function template evaluate">evaluate()</a></code> simply removes all the Boost.YAP
machinery from an expression and evaluates it exactly as it would have been
if Boost.YAP were not used. This means that functions are called, operators
evaluated, etc. all as normal. To illustrate this, take a look at the implementation
of <code class="computeroutput"><span class="keyword">operator</span><span class="special">,()</span></code>
used in <code class="computeroutput"><a class="link" href="../boost/yap/evaluate.html" title="Function template evaluate">evaluate()</a></code>:
</p>
<p>
</p>
<pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">U</span><span class="special">&gt;</span>
<span class="keyword">constexpr</span> <span class="keyword">decltype</span><span class="special">(</span><span class="keyword">auto</span><span class="special">)</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">expr_tag</span><span class="special">&lt;</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">comma</span><span class="special">&gt;,</span> <span class="identifier">T</span> <span class="special">&amp;&amp;</span> <span class="identifier">t</span><span class="special">,</span> <span class="identifier">U</span> <span class="special">&amp;&amp;</span> <span class="identifier">u</span><span class="special">)</span> <span class="keyword">const</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">transform</span><span class="special">(</span>
<span class="identifier">as_expr</span><span class="special">&lt;</span><span class="identifier">minimal_expr</span><span class="special">&gt;(</span><span class="keyword">static_cast</span><span class="special">&lt;</span><span class="identifier">T</span> <span class="special">&amp;&amp;&gt;(</span><span class="identifier">t</span><span class="special">)),</span> <span class="special">*</span><span class="keyword">this</span><span class="special">),</span>
<span class="identifier">transform</span><span class="special">(</span>
<span class="identifier">as_expr</span><span class="special">&lt;</span><span class="identifier">minimal_expr</span><span class="special">&gt;(</span><span class="keyword">static_cast</span><span class="special">&lt;</span><span class="identifier">U</span> <span class="special">&amp;&amp;&gt;(</span><span class="identifier">u</span><span class="special">)),</span> <span class="special">*</span><span class="keyword">this</span><span class="special">);</span>
<span class="special">}</span>
</pre>
<p>
</p>
<p>
What this transformation does is transform the left and right expressions,
and then use the built-in <code class="computeroutput"><span class="keyword">operator</span><span class="special">,()</span></code> on the result. The evaluation transformations
for the other operators do the same thing — evaluate the operands,
then return the result of applying the built-in operator to the operands.
</p>
<p>
Function calls are done in a similar way, except that the callable is also
a subexpression that needs to be evaluated before being called:
</p>
<p>
</p>
<pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Callable</span><span class="special">,</span> <span class="keyword">typename</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span>
<span class="keyword">constexpr</span> <span class="keyword">decltype</span><span class="special">(</span><span class="keyword">auto</span><span class="special">)</span> <span class="keyword">operator</span><span class="special">()(</span>
<span class="identifier">expr_tag</span><span class="special">&lt;</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">call</span><span class="special">&gt;,</span> <span class="identifier">Callable</span> <span class="special">&amp;&amp;</span> <span class="identifier">callable</span><span class="special">,</span> <span class="identifier">Args</span> <span class="special">&amp;&amp;...</span> <span class="identifier">args</span><span class="special">)</span> <span class="keyword">const</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">transform</span><span class="special">(</span><span class="identifier">as_expr</span><span class="special">&lt;</span><span class="identifier">minimal_expr</span><span class="special">&gt;(</span><span class="keyword">static_cast</span><span class="special">&lt;</span><span class="identifier">Callable</span> <span class="special">&amp;&amp;&gt;(</span><span class="identifier">callable</span><span class="special">)),</span> <span class="special">*</span><span class="keyword">this</span><span class="special">)(</span>
<span class="identifier">transform</span><span class="special">(</span><span class="identifier">as_expr</span><span class="special">&lt;</span><span class="identifier">minimal_expr</span><span class="special">&gt;(</span><span class="keyword">static_cast</span><span class="special">&lt;</span><span class="identifier">Args</span> <span class="special">&amp;&amp;&gt;(</span><span class="identifier">args</span><span class="special">)),</span> <span class="special">*</span><span class="keyword">this</span><span class="special">)...</span>
<span class="special">);</span>
<span class="special">}</span>
</pre>
<p>
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_yap.manual.operator_macros"></a><a class="link" href="manual.html#boost_yap.manual.operator_macros" title="Operator Macros">Operator Macros</a>
</h3></div></div></div>
<p>
If you got here without reading the <a class="link" href="manual.html#boost_yap.manual.operators" title="Operators">Operators</a>
section, go read that first. Here are the operator macros and their uses:
</p>
<div class="table">
<a name="boost_yap.manual.operator_macros.unary_and_binary_operator_defining_macros"></a><p class="title"><b>Table 48.1. Unary and Binary Operator-Defining Macros</b></p>
<div class="table-contents"><table class="table" summary="Unary and Binary Operator-Defining Macros">
<colgroup>
<col>
<col>
<col>
<col>
<col>
</colgroup>
<thead><tr>
<th>
<p>
Macro
</p>
</th>
<th>
<p>
Use
</p>
</th>
<th>
<p>
First/Left Operand Type
</p>
</th>
<th>
<p>
Right Operand Type
</p>
</th>
<th>
<p>
Notes
</p>
</th>
</tr></thead>
<tbody>
<tr>
<td>
<p>
<code class="computeroutput"><a class="link" href="../BOOST_YAP_U_1_3_49_8_2_7_1.html" title="Macro BOOST_YAP_USER_UNARY_OPERATOR">BOOST_YAP_USER_UNARY_OPERATOR</a></code>
</p>
</td>
<td>
<p>
Unary operators.
</p>
</td>
<td>
<p>
An <a class="link" href="concepts.html#boost_yap.concepts.expression">Expression</a>
instantiated from <a class="link" href="concepts.html#boost_yap.concepts.expressiontemplate">ExpressionTemplate</a>
macro parameter <code class="computeroutput"><span class="identifier">expr_template</span></code>.
</p>
</td>
<td>
<p>
--
</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>
<code class="computeroutput"><a class="link" href="../BOOST_YAP_U_1_3_49_8_2_7_2.html" title="Macro BOOST_YAP_USER_BINARY_OPERATOR">BOOST_YAP_USER_BINARY_OPERATOR</a></code>
</p>
</td>
<td>
<p>
Binary operators.
</p>
</td>
<td>
<p>
Any type.
</p>
</td>
<td>
<p>
Any type.
</p>
</td>
<td>
<p>
At least one parameter must be an <a class="link" href="concepts.html#boost_yap.concepts.expression">Expression</a>
instantiated from <a class="link" href="concepts.html#boost_yap.concepts.expressiontemplate">ExpressionTemplate</a>
macro parameter <code class="computeroutput"><span class="identifier">expr_template</span></code>.
</p>
</td>
</tr>
<tr>
<td>
<p>
<code class="computeroutput"><a class="link" href="../BOOST_YAP_U_1_3_49_8_2_7_9.html" title="Macro BOOST_YAP_USER_UDT_UNARY_OPERATOR">BOOST_YAP_USER_UDT_UNARY_OPERATOR</a></code>
</p>
</td>
<td>
<p>
Free operators defined over non-<a class="link" href="concepts.html#boost_yap.concepts.expression">Expression</a>
types constrained by a type trait (e.g. all <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special">&lt;&gt;</span></code>s).
</p>
</td>
<td>
<p>
Any non-<a class="link" href="concepts.html#boost_yap.concepts.expression">Expression</a>
that satisfies the given type trait.
</p>
</td>
<td>
<p>
--
</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>
<code class="computeroutput"><a class="link" href="../BOOST_YAP__1_3_49_8_2_7_10.html" title="Macro BOOST_YAP_USER_UDT_UDT_BINARY_OPERATOR">BOOST_YAP_USER_UDT_UDT_BINARY_OPERATOR</a></code>
</p>
</td>
<td>
<p>
Free operators defined over non-<a class="link" href="concepts.html#boost_yap.concepts.expression">Expression</a>
types constrained by a pair of type traits (e.g. a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special">&lt;&gt;</span></code>
on the left, and a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;&gt;</span></code> on the right). Useful for
type-asymmetric operators.
</p>
</td>
<td>
<p>
Any non-<a class="link" href="concepts.html#boost_yap.concepts.expression">Expression</a>
that satisfies the left-hand type trait.
</p>
</td>
<td>
<p>
Any non-<a class="link" href="concepts.html#boost_yap.concepts.expression">Expression</a>
that satisfies the right-hand type trait.
</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>
<code class="computeroutput"><a class="link" href="../BOOST_YAP__1_3_49_8_2_7_11.html" title="Macro BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR">BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR</a></code>
</p>
</td>
<td>
<p>
Free operators defined over pairs of non-<a class="link" href="concepts.html#boost_yap.concepts.expression">Expression</a>
types, one constrained by a type trait and one not (e.g. a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special">&lt;&gt;</span></code>
on either side, and anything on the other).
</p>
</td>
<td>
<p>
Any non-<a class="link" href="concepts.html#boost_yap.concepts.expression">Expression</a>.
</p>
</td>
<td>
<p>
--
</p>
</td>
<td>
<p>
At least one parameter must satisfy the given type trait.
</p>
</td>
</tr>
</tbody>
</table></div>
</div>
<br class="table-break"><p>
Some operators may only be defined as member functions, and so are not covered
by general-purpose the unary and binary operator macros above:
</p>
<div class="table">
<a name="boost_yap.manual.operator_macros.the_member_only_operator_macros"></a><p class="title"><b>Table 48.2. The Member-Only Operator Macros</b></p>
<div class="table-contents"><table class="table" summary="The Member-Only Operator Macros">
<colgroup>
<col>
<col>
<col>
<col>
</colgroup>
<thead><tr>
<th>
<p>
Macro
</p>
</th>
<th>
<p>
Use
</p>
</th>
<th>
<p>
Operands
</p>
</th>
<th>
<p>
Notes
</p>
</th>
</tr></thead>
<tbody>
<tr>
<td>
<p>
<code class="computeroutput"><a class="link" href="../BOOST_YAP_U_1_3_49_8_2_7_3.html" title="Macro BOOST_YAP_USER_ASSIGN_OPERATOR">BOOST_YAP_USER_ASSIGN_OPERATOR</a></code>
</p>
</td>
<td>
<p>
Assignment operator.
</p>
</td>
<td>
<p>
Any type except <code class="computeroutput"><span class="keyword">decltype</span><span class="special">(*</span><span class="keyword">this</span><span class="special">)</span></code>.
</p>
</td>
<td>
<p>
Does not conflict with the assignment or move assignment operators.
</p>
</td>
</tr>
<tr>
<td>
<p>
<code class="computeroutput"><a class="link" href="../BOOST_YAP_U_1_3_49_8_2_7_4.html" title="Macro BOOST_YAP_USER_SUBSCRIPT_OPERATOR">BOOST_YAP_USER_SUBSCRIPT_OPERATOR</a></code>
</p>
</td>
<td>
<p>
Subscript operator.
</p>
</td>
<td>
<p>
Any type.
</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>
<code class="computeroutput"><a class="link" href="../BOOST_YAP_U_1_3_49_8_2_7_5.html" title="Macro BOOST_YAP_USER_CALL_OPERATOR">BOOST_YAP_USER_CALL_OPERATOR</a></code>
</p>
</td>
<td>
<p>
Call operator taking any number of parameters.
</p>
</td>
<td>
<p>
Any type.
</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>
<code class="computeroutput"><a class="link" href="../BOOST_YAP_U_1_3_49_8_2_7_6.html" title="Macro BOOST_YAP_USER_CALL_OPERATOR_N">BOOST_YAP_USER_CALL_OPERATOR_N</a></code>
</p>
</td>
<td>
<p>
Call operator taking exactly N parameters.
</p>
</td>
<td>
<p>
Any type.
</p>
</td>
<td>
</td>
</tr>
</tbody>
</table></div>
</div>
<br class="table-break"><div class="table">
<a name="boost_yap.manual.operator_macros.if_else_psuedo_operator_macros"></a><p class="title"><b>Table 48.3. if_else Psuedo-Operator Macros</b></p>
<div class="table-contents"><table class="table" summary="if_else Psuedo-Operator Macros">
<colgroup>
<col>
<col>
<col>
<col>
</colgroup>
<thead><tr>
<th>
<p>
Macro
</p>
</th>
<th>
<p>
Use
</p>
</th>
<th>
<p>
Operands
</p>
</th>
<th>
<p>
Notes
</p>
</th>
</tr></thead>
<tbody>
<tr>
<td>
<p>
<code class="computeroutput"><a class="link" href="../BOOST_YAP_U_1_3_49_8_2_7_7.html" title="Macro BOOST_YAP_USER_EXPR_IF_ELSE">BOOST_YAP_USER_EXPR_IF_ELSE</a></code>
</p>
</td>
<td>
<p>
Free <code class="computeroutput"><span class="identifier">if_else</span><span class="special">()</span></code>
function that requires at least one parameter to be an expression.
</p>
</td>
<td>
<p>
Any type.
</p>
</td>
<td>
<p>
At least one parameter must be an <a class="link" href="concepts.html#boost_yap.concepts.expression">Expression</a>.
</p>
</td>
</tr>
<tr>
<td>
<p>
<code class="computeroutput"><a class="link" href="../BOOST_YAP_U_1_3_49_8_2_7_8.html" title="Macro BOOST_YAP_USER_UDT_ANY_IF_ELSE">BOOST_YAP_USER_UDT_ANY_IF_ELSE</a></code>
</p>
</td>
<td>
<p>
Free <code class="computeroutput"><span class="identifier">if_else</span><span class="special">()</span></code>
function for non-<a class="link" href="concepts.html#boost_yap.concepts.expression">Expression</a>
types that requires at least one parameter to satisfy the given
type trait.
</p>
</td>
<td>
<p>
Any non-<a class="link" href="concepts.html#boost_yap.concepts.expression">Expression</a>.
</p>
</td>
<td>
<p>
At least one parameter must satisfy the given type trait.
</p>
</td>
</tr>
</tbody>
</table></div>
</div>
<br class="table-break"><div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../doc/src/images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td align="left" valign="top"><p>
Operands are handled in a uniform way across all functions defined by all
the macros listed here. See <a class="link" href="manual.html#boost_yap.manual.how_expression_operands_are_treated" title="How Expression Operands Are Treated">How
Expression Operands Are Treated</a> for details.
</p></td></tr>
</table></div>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_yap.manual.how_expression_operands_are_treated"></a><a class="link" href="manual.html#boost_yap.manual.how_expression_operands_are_treated" title="How Expression Operands Are Treated">How
Expression Operands Are Treated</a>
</h3></div></div></div>
<p>
For any <code class="computeroutput"><a class="link" href="../boost/yap/expression.html" title="Struct template expression">expression&lt;&gt;</a></code> operator overload, or
any function defined using one of the function definition macros, operands
are treated in a uniform way.
</p>
<p>
The guiding design principle here is that an expression built using Boost.YAP
should match the semantics of a builtin C++ expression as closely as possible.
This implies that an rvalue be treated as if it were a temporary (as it may
in fact have initially been) throughout the building and transformation of
an expression, and that an lvalue should retain its connection to the underlying
named entity to which it refers.
</p>
<p>
For example, if you see
</p>
<pre class="programlisting"><span class="keyword">auto</span> <span class="identifier">expr</span> <span class="special">=</span> <span class="identifier">a</span> <span class="special">+</span> <span class="number">1</span><span class="special">;</span>
</pre>
<p>
you should expect that <code class="computeroutput"><span class="identifier">a</span></code>
will be an lvalue reference to some object of type <code class="computeroutput"><span class="keyword">decltype</span><span class="special">(</span><span class="identifier">a</span><span class="special">)</span></code>,
regardless of whether <code class="computeroutput"><span class="identifier">a</span></code> is
a Boost.YAP <a class="link" href="concepts.html#boost_yap.concepts.expression">Expression</a>
or a builtin type. Similarly, you should expect the <code class="computeroutput"><span class="number">1</span></code>
to be an rvalue, whether wrapped in a terminal or not.
</p>
<p>
Let's take a quick look at <code class="computeroutput"><a class="link" href="../boost/yap/make_t_1_3_49_8_2_2_1_1_14.html" title="Function template make_terminal">make_terminal()</a></code>.
If you call it with a <code class="computeroutput"><span class="identifier">T</span></code> rvalue,
the terminal's value type is a <code class="computeroutput"><span class="identifier">T</span></code>,
and the rvalue gets moved into it. If you call it with a <code class="computeroutput"><span class="identifier">T</span>
<span class="special">[</span><span class="keyword">const</span><span class="special">]</span></code> lvalue, the value type is <code class="computeroutput"><span class="identifier">T</span> <span class="special">[</span><span class="keyword">const</span><span class="special">]</span> <span class="special">&amp;</span></code>, and
the reference refers to the lvalue (read <code class="computeroutput"><span class="special">[</span><span class="keyword">const</span><span class="special">]</span></code> as
"possibly <code class="computeroutput"><span class="keyword">const</span></code>-qualified").
This is important because you might write through the terminal later in an
assignment operation. You don't want to lose the ability to do this, or be
forced to write some Baroque pile of code to do so — it should be
natural and easy.
</p>
<p>
And it is:
</p>
<p>
</p>
<pre class="programlisting"><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span>
<span class="keyword">auto</span> <span class="identifier">expr</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_terminal</span><span class="special">(</span><span class="identifier">i</span><span class="special">)</span> <span class="special">=</span> <span class="number">42</span><span class="special">;</span>
<span class="identifier">evaluate</span><span class="special">(</span><span class="identifier">expr</span><span class="special">);</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">i</span> <span class="special">&lt;&lt;</span> <span class="string">"\n"</span><span class="special">;</span> <span class="comment">// Prints 42.</span>
</pre>
<p>
</p>
<p>
Now, there is a wrinkle. Boost.YAP's lazy expressions can be built piecemeal:
</p>
<pre class="programlisting"><span class="keyword">auto</span> <span class="identifier">subexpr</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_terminal</span><span class="special">(</span><span class="number">1</span><span class="special">)</span> <span class="special">+</span> <span class="number">2</span><span class="special">;</span>
<span class="comment">// This is fine, and acts more-or-less as if you wrote "1 / (1 + 2)".</span>
<span class="keyword">auto</span> <span class="identifier">expr</span> <span class="special">=</span> <span class="number">1</span> <span class="special">/</span> <span class="identifier">subexpr</span><span class="special">;</span>
</pre>
<p>
whereas C++'s eager builtin expressions cannot:
</p>
<pre class="programlisting"><span class="keyword">auto</span> <span class="identifier">subexpr</span> <span class="special">=</span> <span class="number">1</span> <span class="special">+</span> <span class="number">2</span><span class="special">;</span> <span class="comment">// Same as "int subexpr = 3;". Hm.</span>
<span class="keyword">auto</span> <span class="identifier">expr</span> <span class="special">=</span> <span class="number">1</span> <span class="special">/</span> <span class="identifier">subexpr</span><span class="special">;</span> <span class="comment">// Same as "int expr = 0;" Arg.</span>
</pre>
<p>
Ok, so since you can build these lazy Boost.YAP expressions up from subexpressions,
how do we treat the subexpressions? We treat them in exactly the same way
as <code class="computeroutput"><a class="link" href="../boost/yap/make_t_1_3_49_8_2_2_1_1_14.html" title="Function template make_terminal">make_terminal()</a></code> treats its parameter. Rvalues
are moved in, and lvalues are captured by (possibly <code class="computeroutput"><span class="keyword">const</span></code>)
reference.
</p>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../doc/src/images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td align="left" valign="top"><p>
If you want to subvert the capture-by-reference semantics of using subexpressions,
just <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">()</span></code>
them. That will force a move — or copy of values for which move
is not defined.
</p></td></tr>
</table></div>
<p>
The capture-by-reference behavior is implemented via a special <code class="computeroutput"><a class="link" href="../boost/yap/expr_kind.html" title="Type expr_kind">expr_kind</a></code>,
<a class="link" href="../boost/yap/expr_kind.html#boost.yap.expr_kind.expr_ref"><code class="computeroutput"><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">expr_ref</span></code></a>.
An <code class="computeroutput"><span class="identifier">expr_ref</span></code> expression has
a single data element: a (possibly <code class="computeroutput"><span class="keyword">const</span></code>
(Can I stop saying that every time? You get it, right? Ok, good.)) reference
to an expression. This additional level of indirection causes some complications
at times, as you can see in the examples. Fortunately, the complications
are not overly cumbersome.
</p>
<p>
So, given the rules above, here is a comprehensive breakdown of what happens
when an operand is passed to a Boost.YAP operator. In this table, <code class="computeroutput"><span class="identifier">expr_tmpl</span></code> is an <a class="link" href="concepts.html#boost_yap.concepts.expressiontemplate">ExpressionTemplate</a>,
and <code class="computeroutput"><span class="identifier">T</span></code> is a non-<a class="link" href="concepts.html#boost_yap.concepts.expression">Expression</a>
type. <code class="computeroutput"><span class="identifier">E</span></code> refers to any non-<code class="computeroutput"><span class="identifier">expr_ref</span></code> <a class="link" href="concepts.html#boost_yap.concepts.expression">Expression</a>.
Boost.YAP does a partial decay on non-<a class="link" href="concepts.html#boost_yap.concepts.expression">Expression</a>
operands, in which <code class="computeroutput"><span class="identifier">cv</span></code> and
reference qualifiers are left unchanged, but arrays are decayed to pointers
and functions are decayed to function pointers. <code class="computeroutput"><span class="identifier">PARTIAL_DECAY</span><span class="special">(</span><span class="identifier">T</span><span class="special">)</span></code>
indicates such a partial decay of <code class="computeroutput"><span class="identifier">T</span></code>.
</p>
<div class="table">
<a name="boost_yap.manual.how_expression_operands_are_treated.operand_handling"></a><p class="title"><b>Table 48.4. Operand Handling</b></p>
<div class="table-contents"><table class="table" summary="Operand Handling">
<colgroup>
<col>
<col>
<col>
</colgroup>
<thead><tr>
<th>
<p>
Operand
</p>
</th>
<th>
<p>
Captured As
</p>
</th>
<th>
<p>
Notes
</p>
</th>
</tr></thead>
<tbody>
<tr>
<td>
<p>
<code class="computeroutput"><span class="identifier">T</span> <span class="keyword">const</span>
<span class="special">&amp;</span></code>
</p>
</td>
<td>
<p>
<code class="computeroutput"><span class="identifier">expr_tmpl</span><span class="special">&lt;</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="identifier">PARTIAL_DECAY</span><span class="special">(</span><span class="identifier">T</span><span class="special">)&gt;&gt;</span></code>
</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>
<code class="computeroutput"><span class="identifier">T</span> <span class="special">&amp;</span></code>
</p>
</td>
<td>
<p>
<code class="computeroutput"><span class="identifier">expr_tmpl</span><span class="special">&lt;</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="identifier">PARTIAL_DECAY</span><span class="special">(</span><span class="identifier">T</span><span class="special">)&gt;&gt;</span></code>
</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>
<code class="computeroutput"><span class="identifier">T</span> <span class="special">&amp;&amp;</span></code>
</p>
</td>
<td>
<p>
<code class="computeroutput"><span class="identifier">expr_tmpl</span><span class="special">&lt;</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="identifier">PARTIAL_DECAY</span><span class="special">(</span><span class="identifier">T</span><span class="special">)&gt;&gt;</span></code>
</p>
</td>
<td>
<p>
Operand moved.
</p>
</td>
</tr>
<tr>
<td>
<p>
<code class="computeroutput"><span class="identifier">E</span> <span class="keyword">const</span>
<span class="special">&amp;</span></code>
</p>
</td>
<td>
<p>
<code class="computeroutput"><span class="identifier">expr_tmpl</span><span class="special">&lt;</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">expr_ref</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="identifier">E</span> <span class="keyword">const</span>
<span class="special">&amp;&gt;&gt;</span></code>
</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>
<code class="computeroutput"><span class="identifier">E</span> <span class="special">&amp;</span></code>
</p>
</td>
<td>
<p>
<code class="computeroutput"><span class="identifier">expr_tmpl</span><span class="special">&lt;</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">expr_ref</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="identifier">E</span> <span class="special">&amp;&gt;&gt;</span></code>
</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>
<code class="computeroutput"><span class="identifier">E</span> <span class="special">&amp;&amp;</span></code>
</p>
</td>
<td>
<p>
<code class="computeroutput"><span class="identifier">E</span></code>
</p>
</td>
<td>
<p>
Operand moved.
</p>
</td>
</tr>
<tr>
<td>
<p>
<code class="computeroutput"><span class="identifier">expr_tmpl</span><span class="special">&lt;</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">expr_ref</span><span class="special">,</span>
<span class="special">...&gt;</span> <span class="keyword">const</span>
<span class="special">&amp;</span></code>
</p>
</td>
<td>
<p>
<code class="computeroutput"><span class="identifier">expr_tmpl</span><span class="special">&lt;</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">expr_ref</span><span class="special">,</span>
<span class="special">...&gt;</span></code>
</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>
<code class="computeroutput"><span class="identifier">expr_tmpl</span><span class="special">&lt;</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">expr_ref</span><span class="special">,</span>
<span class="special">...&gt;</span> <span class="special">&amp;</span></code>
</p>
</td>
<td>
<p>
<code class="computeroutput"><span class="identifier">expr_tmpl</span><span class="special">&lt;</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">expr_ref</span><span class="special">,</span>
<span class="special">...&gt;</span></code>
</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>
<code class="computeroutput"><span class="identifier">expr_tmpl</span><span class="special">&lt;</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">expr_ref</span><span class="special">,</span>
<span class="special">...&gt;</span> <span class="special">&amp;&amp;</span></code>
</p>
</td>
<td>
<p>
<code class="computeroutput"><span class="identifier">expr_tmpl</span><span class="special">&lt;</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">expr_ref</span><span class="special">,</span>
<span class="special">...&gt;</span></code>
</p>
</td>
<td>
<p>
Operand moved.
</p>
</td>
</tr>
</tbody>
</table></div>
</div>
<br class="table-break"><p>
The partial decay of non-<a class="link" href="concepts.html#boost_yap.concepts.expression">Expression</a>
operands is another example of how Boost.YAP attempts to create expression
trees that are as semantically close to builtin expressions as possible.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_yap.manual.printing"></a><a class="link" href="manual.html#boost_yap.manual.printing" title="Printing">Printing</a>
</h3></div></div></div>
<p>
Boost.YAP has a convenient <code class="computeroutput"><a class="link" href="../boost/yap/print.html" title="Function template print">print()</a></code>
function, that prints an expression tree to a stream. It is not intended
for production work (for instance, it has no formatting options), but it
is excellent for debugging and instrumentation.
</p>
<p>
Since it is only a debugging aid, <code class="computeroutput"><a class="link" href="../boost/yap/print.html" title="Function template print">print()</a></code>
is found in a separate header not included when you include Boost.YAP with
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">yap</span><span class="special">/</span><span class="identifier">yap</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
<p>
You must include <code class="computeroutput"><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">yap</span><span class="special">/</span><span class="identifier">print</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span></code>
explicitly.
</p>
<p>
<code class="computeroutput"><a class="link" href="../boost/yap/print.html" title="Function template print">print()</a></code> handles several patterns
of expression specially, to allow a concise representation of a given expression
tree. For example, given this definition:
</p>
<p>
</p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">thing</span> <span class="special">{};</span>
</pre>
<p>
</p>
<p>
and this expression:
</p>
<p>
</p>
<pre class="programlisting"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">literals</span><span class="special">;</span>
<span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">const_lvalue_terminal_containing_rvalue</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_terminal</span><span class="special">(</span><span class="string">"lvalue terminal"</span><span class="special">);</span>
<span class="keyword">double</span> <span class="keyword">const</span> <span class="identifier">d</span> <span class="special">=</span> <span class="number">1.0</span><span class="special">;</span>
<span class="keyword">auto</span> <span class="identifier">rvalue_terminal_containing_lvalue</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_terminal</span><span class="special">(</span><span class="identifier">d</span><span class="special">);</span>
<span class="keyword">auto</span> <span class="identifier">thing_terminal</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_terminal</span><span class="special">(</span><span class="identifier">thing</span><span class="special">{});</span>
<span class="keyword">auto</span> <span class="identifier">expr</span> <span class="special">=</span>
<span class="number">4</span><span class="identifier">_p</span> <span class="special">+</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">rvalue_terminal_containing_lvalue</span><span class="special">)</span> <span class="special">*</span> <span class="identifier">thing_terminal</span> <span class="special">-</span>
<span class="identifier">const_lvalue_terminal_containing_rvalue</span><span class="special">;</span>
</pre>
<p>
</p>
<p>
<code class="computeroutput"><a class="link" href="../boost/yap/print.html" title="Function template print">print()</a></code> produces this output:
</p>
<pre class="programlisting">expr&lt;-&gt;
expr&lt;+&gt;
term&lt;boost::yap::placeholder&lt;4ll&gt;&gt;[=4]
expr&lt;*&gt;
term&lt;double &amp;&gt;[=1]
term&lt;thing&gt;[=&lt;&lt;unprintable-value&gt;&gt;] &amp;
term&lt;char const*&gt;[=lvalue terminal] const &amp;
</pre>
<p>
As you can see, <code class="computeroutput"><a class="link" href="../boost/yap/print.html" title="Function template print">print()</a></code> shows one node per line,
and represents the tree structure with indentation. It abbreviates non-terminal
nodes in the tree <code class="computeroutput"><span class="identifier">expr</span><span class="special">&lt;</span><span class="identifier">op</span><span class="special">&gt;</span></code>,
where <code class="computeroutput"><span class="identifier">op</span></code> is an operator symbol.
Terminal nodes are abbreviated <code class="computeroutput"><span class="identifier">term</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span></code>,
where <code class="computeroutput"><span class="identifier">T</span></code> is the type of value
contained in the terminal; this may be a reference type or a value.
</p>
<p>
A <code class="computeroutput"><span class="identifier">term</span></code> node may not be a
terminal node at all, but an <a class="link" href="../boost/yap/expr_kind.html#boost.yap.expr_kind.expr_ref"><code class="computeroutput"><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">expr_ref</span></code></a> expression containing a
terminal. Such a <a class="link" href="../boost/yap/expr_kind.html#boost.yap.expr_kind.expr_ref"><code class="computeroutput"><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">expr_ref</span></code></a> node has a <code class="computeroutput"><span class="special">&amp;</span></code> or <code class="computeroutput"><span class="keyword">const</span>
<span class="special">&amp;</span></code> suffix, to indicate that it
is a mutable or <code class="computeroutput"><span class="keyword">const</span></code> reference,
respectively.
</p>
<p>
Each <code class="computeroutput"><span class="identifier">term</span></code> node has a bracketed
value near the end. The format is <code class="computeroutput"><span class="special">[=</span><span class="identifier">X</span><span class="special">]</span></code> where
<code class="computeroutput"><span class="identifier">X</span></code> is the value the terminal
contains. If the terminal contains a value for which no <code class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;&lt;(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span> <span class="special">&amp;,</span> <span class="special">...)</span></code>
overload exists (such as the <code class="computeroutput"><span class="identifier">thing</span></code>
type above), <code class="computeroutput"><span class="identifier">X</span></code> will be <code class="computeroutput"><span class="special">&lt;&lt;</span><span class="identifier">unprintable</span><span class="special">-</span><span class="identifier">value</span><span class="special">&gt;&gt;</span></code>.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_yap.manual.examples"></a><a class="link" href="manual.html#boost_yap.manual.examples" title="Examples">Examples</a>
</h3></div></div></div>
<div class="toc"><dl class="toc">
<dt><span class="section"><a href="manual.html#boost_yap.manual.examples.hello_world">Hello World</a></span></dt>
<dt><span class="section"><a href="manual.html#boost_yap.manual.examples.hello_world_redux">Hello
World Redux</a></span></dt>
<dt><span class="section"><a href="manual.html#boost_yap.manual.examples.minimal">Minimal</a></span></dt>
<dt><span class="section"><a href="manual.html#boost_yap.manual.examples.calc1">Calc1</a></span></dt>
<dt><span class="section"><a href="manual.html#boost_yap.manual.examples.calc2">Calc2</a></span></dt>
<dt><span class="section"><a href="manual.html#boost_yap.manual.examples.calc3">Calc3</a></span></dt>
<dt><span class="section"><a href="manual.html#boost_yap.manual.examples.lazy_vector">Lazy Vector</a></span></dt>
<dt><span class="section"><a href="manual.html#boost_yap.manual.examples.self_evaluating_expressions">Self-Evaluating
Expressions</a></span></dt>
<dt><span class="section"><a href="manual.html#boost_yap.manual.examples.tarray">TArray</a></span></dt>
<dt><span class="section"><a href="manual.html#boost_yap.manual.examples.vec3">Vec3</a></span></dt>
<dt><span class="section"><a href="manual.html#boost_yap.manual.examples.vector">Vector</a></span></dt>
<dt><span class="section"><a href="manual.html#boost_yap.manual.examples.mixed">Mixed</a></span></dt>
<dt><span class="section"><a href="manual.html#boost_yap.manual.examples.map_assign">Map Assign</a></span></dt>
<dt><span class="section"><a href="manual.html#boost_yap.manual.examples.future_group">Future Group</a></span></dt>
<dt><span class="section"><a href="manual.html#boost_yap.manual.examples.autodiff">Autodiff</a></span></dt>
<dt><span class="section"><a href="manual.html#boost_yap.manual.examples.transforming_terminals_only">Transforming
Terminals Only</a></span></dt>
<dt><span class="section"><a href="manual.html#boost_yap.manual.examples.pipable_algorithms">Pipable
Algorithms</a></span></dt>
<dt><span class="section"><a href="manual.html#boost_yap.manual.examples.boost_phoenix_style__let___">Boost.Phoenix-style
<code class="computeroutput"><span class="identifier">let</span><span class="special">()</span></code></a></span></dt>
</dl></div>
<p>
Most of these examples are patterned after the examples from Boost.Proto.
In part, this was done to underscore where Boost.YAP can do what Proto can,
and where it cannot.
</p>
<p>
Where possible, a Proto-derived example uses syntax in <code class="computeroutput"><span class="identifier">main</span><span class="special">()</span></code> identical to that in the original Proto
example.
</p>
<p>
If you don't know anything about Proto, don't worry. The examples are useful
on their own.
</p>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="boost_yap.manual.examples.hello_world"></a><a class="link" href="manual.html#boost_yap.manual.examples.hello_world" title="Hello World">Hello World</a>
</h4></div></div></div>
<p>
Remember how I mentioned earlier that Boost.YAP does things in a completely
lazy way? Boost.YAP doesn't ever evaluate your expression eagerly. Eager
evaluation can be done, but it's a bit of code.
</p>
<p>
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">yap</span><span class="special">/</span><span class="identifier">expression</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">int</span> <span class="identifier">main</span> <span class="special">()</span>
<span class="special">{</span>
<span class="identifier">evaluate</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_terminal</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="string">"Hello"</span> <span class="special">&lt;&lt;</span> <span class="char">','</span> <span class="special">&lt;&lt;</span> <span class="string">" world!\n"</span><span class="special">);</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="boost_yap.manual.examples.hello_world_redux"></a><a class="link" href="manual.html#boost_yap.manual.examples.hello_world_redux" title="Hello World Redux">Hello
World Redux</a>
</h4></div></div></div>
<p>
That's better! Sort of.... We created a custom expression template with
an eager stream operator. This gives us eager evaluation, but gives away
all the lazy AST building-then-evaluating that we're using expression templates
for in the first place. In this simple example, we don't really need it.
</p>
<p>
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">yap</span><span class="special">/</span><span class="identifier">algorithm</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">Kind</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">stream_expr</span>
<span class="special">{</span>
<span class="keyword">static</span> <span class="keyword">const</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">kind</span> <span class="special">=</span> <span class="identifier">Kind</span><span class="special">;</span>
<span class="identifier">Tuple</span> <span class="identifier">elements</span><span class="special">;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">decltype</span><span class="special">(</span><span class="keyword">auto</span><span class="special">)</span> <span class="keyword">operator</span><span class="special">&lt;&lt;</span> <span class="special">(</span><span class="identifier">T</span> <span class="special">&amp;&amp;</span> <span class="identifier">x</span><span class="special">)</span>
<span class="special">{</span> <span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">value</span><span class="special">(*</span><span class="keyword">this</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special">&lt;</span><span class="identifier">T</span> <span class="special">&amp;&amp;&gt;(</span><span class="identifier">x</span><span class="special">);</span> <span class="special">}</span>
<span class="special">};</span>
<span class="keyword">int</span> <span class="identifier">main</span> <span class="special">()</span>
<span class="special">{</span>
<span class="keyword">auto</span> <span class="identifier">cout</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_terminal</span><span class="special">&lt;</span><span class="identifier">stream_expr</span><span class="special">&gt;(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">);</span>
<span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"Hello"</span> <span class="special">&lt;&lt;</span> <span class="char">','</span> <span class="special">&lt;&lt;</span> <span class="string">" world!\n"</span><span class="special">;</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="boost_yap.manual.examples.minimal"></a><a class="link" href="manual.html#boost_yap.manual.examples.minimal" title="Minimal">Minimal</a>
</h4></div></div></div>
<p>
<code class="computeroutput"><span class="identifier">minimal_expr</span></code> below models
<a class="link" href="concepts.html#boost_yap.concepts.expressiontemplate">ExpressionTemplate</a>;
since it has no operators, an expression must be built manually.
</p>
<p>
First, the template itself:
</p>
<p>
</p>
<pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">Kind</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">minimal_expr</span>
<span class="special">{</span>
<span class="keyword">static</span> <span class="keyword">const</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">kind</span> <span class="special">=</span> <span class="identifier">Kind</span><span class="special">;</span>
<span class="identifier">Tuple</span> <span class="identifier">elements</span><span class="special">;</span>
<span class="special">};</span>
</pre>
<p>
</p>
<p>
This can be used to make a <code class="computeroutput"><span class="identifier">minimal_expr</span></code>
plus expression:
</p>
<p>
</p>
<pre class="programlisting"><span class="keyword">auto</span> <span class="identifier">left</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_terminal</span><span class="special">&lt;</span><span class="identifier">minimal_expr</span><span class="special">&gt;(</span><span class="number">1</span><span class="special">);</span>
<span class="keyword">auto</span> <span class="identifier">right</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_terminal</span><span class="special">&lt;</span><span class="identifier">minimal_expr</span><span class="special">&gt;(</span><span class="number">41</span><span class="special">);</span>
<span class="keyword">auto</span> <span class="identifier">expr</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_expression</span><span class="special">&lt;</span>
<span class="identifier">minimal_expr</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">plus</span>
<span class="special">&gt;(</span><span class="identifier">left</span><span class="special">,</span> <span class="identifier">right</span><span class="special">);</span>
</pre>
<p>
</p>
<p>
You can evaluate, transform, or otherwise operate on <code class="computeroutput"><span class="identifier">minimal_expr</span></code>
expressions using the functions in Boost.YAP that accept an <a class="link" href="concepts.html#boost_yap.concepts.expression">Expression</a>:
</p>
<p>
</p>
<pre class="programlisting"><span class="keyword">auto</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">evaluate</span><span class="special">(</span><span class="identifier">expr</span><span class="special">);</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">result</span> <span class="special">&lt;&lt;</span> <span class="string">"\n"</span><span class="special">;</span> <span class="comment">// prints "42"</span>
</pre>
<p>
</p>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../doc/src/images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td align="left" valign="top"><p>
Don't use Boost.YAP this way. Use the operator macros instead. This is
an example contrived only to show you the minimum requirements on a Boost.YAP-compatible
template.
</p></td></tr>
</table></div>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="boost_yap.manual.examples.calc1"></a><a class="link" href="manual.html#boost_yap.manual.examples.calc1" title="Calc1">Calc1</a>
</h4></div></div></div>
<p>
This is the first of several calculator-building examples derived from
Proto. This first one just builds lazy expressions with placeholders, and
evaluates them. Here we can first see how much C++14-and-later language
features help the end user — the Proto version is much, much longer.
</p>
<p>
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">yap</span><span class="special">/</span><span class="identifier">expression</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">int</span> <span class="identifier">main</span> <span class="special">()</span>
<span class="special">{</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">literals</span><span class="special">;</span>
<span class="comment">// Displays "5"</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">evaluate</span><span class="special">(</span> <span class="number">1</span><span class="identifier">_p</span> <span class="special">+</span> <span class="number">2.0</span><span class="special">,</span> <span class="number">3.0</span> <span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="comment">// Displays "6"</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">evaluate</span><span class="special">(</span> <span class="number">1</span><span class="identifier">_p</span> <span class="special">*</span> <span class="number">2</span><span class="identifier">_p</span><span class="special">,</span> <span class="number">3.0</span><span class="special">,</span> <span class="number">2.0</span> <span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="comment">// Displays "0.5"</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">evaluate</span><span class="special">(</span> <span class="special">(</span><span class="number">1</span><span class="identifier">_p</span> <span class="special">-</span> <span class="number">2</span><span class="identifier">_p</span><span class="special">)</span> <span class="special">/</span> <span class="number">2</span><span class="identifier">_p</span><span class="special">,</span> <span class="number">3.0</span><span class="special">,</span> <span class="number">2.0</span> <span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="boost_yap.manual.examples.calc2"></a><a class="link" href="manual.html#boost_yap.manual.examples.calc2" title="Calc2">Calc2</a>
</h4></div></div></div>
<p>
The Proto Calc2 example turns the expressions from Calc1 into callable
objects. Using Boost.YAP you can do this in two ways.
</p>
<p>
You can just use lambdas to wrap the expressions:
</p>
<p>
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">yap</span><span class="special">/</span><span class="identifier">expression</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">int</span> <span class="identifier">main</span> <span class="special">()</span>
<span class="special">{</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">literals</span><span class="special">;</span>
<span class="keyword">auto</span> <span class="identifier">expr_1</span> <span class="special">=</span> <span class="number">1</span><span class="identifier">_p</span> <span class="special">+</span> <span class="number">2.0</span><span class="special">;</span>
<span class="keyword">auto</span> <span class="identifier">expr_1_fn</span> <span class="special">=</span> <span class="special">[</span><span class="identifier">expr_1</span><span class="special">](</span><span class="keyword">auto</span> <span class="special">&amp;&amp;...</span> <span class="identifier">args</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">evaluate</span><span class="special">(</span><span class="identifier">expr_1</span><span class="special">,</span> <span class="identifier">args</span><span class="special">...);</span>
<span class="special">};</span>
<span class="keyword">auto</span> <span class="identifier">expr_2</span> <span class="special">=</span> <span class="number">1</span><span class="identifier">_p</span> <span class="special">*</span> <span class="number">2</span><span class="identifier">_p</span><span class="special">;</span>
<span class="keyword">auto</span> <span class="identifier">expr_2_fn</span> <span class="special">=</span> <span class="special">[</span><span class="identifier">expr_2</span><span class="special">](</span><span class="keyword">auto</span> <span class="special">&amp;&amp;...</span> <span class="identifier">args</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">evaluate</span><span class="special">(</span><span class="identifier">expr_2</span><span class="special">,</span> <span class="identifier">args</span><span class="special">...);</span>
<span class="special">};</span>
<span class="keyword">auto</span> <span class="identifier">expr_3</span> <span class="special">=</span> <span class="special">(</span><span class="number">1</span><span class="identifier">_p</span> <span class="special">-</span> <span class="number">2</span><span class="identifier">_p</span><span class="special">)</span> <span class="special">/</span> <span class="number">2</span><span class="identifier">_p</span><span class="special">;</span>
<span class="keyword">auto</span> <span class="identifier">expr_3_fn</span> <span class="special">=</span> <span class="special">[</span><span class="identifier">expr_3</span><span class="special">](</span><span class="keyword">auto</span> <span class="special">&amp;&amp;...</span> <span class="identifier">args</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">evaluate</span><span class="special">(</span><span class="identifier">expr_3</span><span class="special">,</span> <span class="identifier">args</span><span class="special">...);</span>
<span class="special">};</span>
<span class="comment">// Displays "5"</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">expr_1_fn</span><span class="special">(</span><span class="number">3.0</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="comment">// Displays "6"</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">expr_2_fn</span><span class="special">(</span><span class="number">3.0</span><span class="special">,</span> <span class="number">2.0</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="comment">// Displays "0.5"</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">expr_3_fn</span><span class="special">(</span><span class="number">3.0</span><span class="special">,</span> <span class="number">2.0</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
</p>
<p>
Or you can use <code class="computeroutput"><a class="link" href="../boost/yap/make_expression_function.html" title="Function template make_expression_function">make_expression_function()</a></code>
to make a callable object from your expression:
</p>
<p>
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">yap</span><span class="special">/</span><span class="identifier">expression</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">int</span> <span class="identifier">main</span> <span class="special">()</span>
<span class="special">{</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">literals</span><span class="special">;</span>
<span class="comment">// Displays "5"</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">make_expression_function</span><span class="special">(</span><span class="number">1</span><span class="identifier">_p</span> <span class="special">+</span> <span class="number">2.0</span><span class="special">)(</span><span class="number">3.0</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="comment">// Displays "6"</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">make_expression_function</span><span class="special">(</span><span class="number">1</span><span class="identifier">_p</span> <span class="special">*</span> <span class="number">2</span><span class="identifier">_p</span><span class="special">)(</span><span class="number">3.0</span><span class="special">,</span> <span class="number">2.0</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="comment">// Displays "0.5"</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">make_expression_function</span><span class="special">((</span><span class="number">1</span><span class="identifier">_p</span> <span class="special">-</span> <span class="number">2</span><span class="identifier">_p</span><span class="special">)</span> <span class="special">/</span> <span class="number">2</span><span class="identifier">_p</span><span class="special">)(</span><span class="number">3.0</span><span class="special">,</span> <span class="number">2.0</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="boost_yap.manual.examples.calc3"></a><a class="link" href="manual.html#boost_yap.manual.examples.calc3" title="Calc3">Calc3</a>
</h4></div></div></div>
<p>
Here, we introduce a <a class="link" href="concepts.html#boost_yap.concepts.transform">Transform</a>
used to calculate expression arity, and <code class="computeroutput"><span class="keyword">static_assert</span><span class="special">()</span></code> that the number of parameters passed
by the caller matches the arity.
</p>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../doc/src/images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td align="left" valign="top"><p>
The <code class="computeroutput"><span class="identifier">get_arity</span></code> <a class="link" href="concepts.html#boost_yap.concepts.transform">Transform</a>
doesn't produce an <a class="link" href="concepts.html#boost_yap.concepts.expression">Expression</a>,
and it does not have to. <a class="link" href="concepts.html#boost_yap.concepts.transform">Transforms</a>
may produce <a class="link" href="concepts.html#boost_yap.concepts.expression">Expressions</a>
or arbitrary values. They may also have arbitrary side effects, and may
be stateful.
</p></td></tr>
</table></div>
<p>
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">yap</span><span class="special">/</span><span class="identifier">expression</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">hana</span><span class="special">/</span><span class="identifier">maximum</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="comment">// Look! A transform! This one transforms the expression tree into the arity</span>
<span class="comment">// of the expression, based on its placeholders.</span>
<span class="keyword">struct</span> <span class="identifier">get_arity</span>
<span class="special">{</span>
<span class="comment">// Base case 1: Match a placeholder terminal, and return its arity as the</span>
<span class="comment">// result.</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">long</span> <span class="keyword">long</span> <span class="identifier">I</span><span class="special">&gt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">llong</span><span class="special">&lt;</span><span class="identifier">I</span><span class="special">&gt;</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_tag</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">&gt;,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">placeholder</span><span class="special">&lt;</span><span class="identifier">I</span><span class="special">&gt;)</span>
<span class="special">{</span> <span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">llong_c</span><span class="special">&lt;</span><span class="identifier">I</span><span class="special">&gt;;</span> <span class="special">}</span>
<span class="comment">// Base case 2: Match any other terminal. Return 0; non-placeholders do</span>
<span class="comment">// not contribute to arity.</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_tag</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">&gt;,</span> <span class="identifier">T</span> <span class="special">&amp;&amp;)</span>
<span class="special">{</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">literals</span><span class="special">;</span>
<span class="keyword">return</span> <span class="number">0</span><span class="identifier">_c</span><span class="special">;</span>
<span class="special">}</span>
<span class="comment">// Recursive case: Match any expression not covered above, and return the</span>
<span class="comment">// maximum of its children's arities.</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">Kind</span><span class="special">,</span> <span class="keyword">typename</span><span class="special">...</span> <span class="identifier">Arg</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_tag</span><span class="special">&lt;</span><span class="identifier">Kind</span><span class="special">&gt;,</span> <span class="identifier">Arg</span> <span class="special">&amp;&amp;...</span> <span class="identifier">arg</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">maximum</span><span class="special">(</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">make_tuple</span><span class="special">(</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">as_expr</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special">&lt;</span><span class="identifier">Arg</span><span class="special">&gt;(</span><span class="identifier">arg</span><span class="special">)),</span>
<span class="identifier">get_arity</span><span class="special">{}</span>
<span class="special">)...</span>
<span class="special">)</span>
<span class="special">);</span>
<span class="special">}</span>
<span class="special">};</span>
<span class="keyword">int</span> <span class="identifier">main</span> <span class="special">()</span>
<span class="special">{</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">literals</span><span class="special">;</span>
<span class="comment">// These lambdas wrap our expressions as callables, and allow us to check</span>
<span class="comment">// the arity of each as we call it.</span>
<span class="keyword">auto</span> <span class="identifier">expr_1</span> <span class="special">=</span> <span class="number">1</span><span class="identifier">_p</span> <span class="special">+</span> <span class="number">2.0</span><span class="special">;</span>
<span class="keyword">auto</span> <span class="identifier">expr_1_fn</span> <span class="special">=</span> <span class="special">[</span><span class="identifier">expr_1</span><span class="special">](</span><span class="keyword">auto</span> <span class="special">&amp;&amp;...</span> <span class="identifier">args</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">arity</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">expr_1</span><span class="special">,</span> <span class="identifier">get_arity</span><span class="special">{});</span>
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">arity</span><span class="special">.</span><span class="identifier">value</span> <span class="special">==</span> <span class="keyword">sizeof</span><span class="special">...(</span><span class="identifier">args</span><span class="special">),</span> <span class="string">"Called with wrong number of args."</span><span class="special">);</span>
<span class="keyword">return</span> <span class="identifier">evaluate</span><span class="special">(</span><span class="identifier">expr_1</span><span class="special">,</span> <span class="identifier">args</span><span class="special">...);</span>
<span class="special">};</span>
<span class="keyword">auto</span> <span class="identifier">expr_2</span> <span class="special">=</span> <span class="number">1</span><span class="identifier">_p</span> <span class="special">*</span> <span class="number">2</span><span class="identifier">_p</span><span class="special">;</span>
<span class="keyword">auto</span> <span class="identifier">expr_2_fn</span> <span class="special">=</span> <span class="special">[</span><span class="identifier">expr_2</span><span class="special">](</span><span class="keyword">auto</span> <span class="special">&amp;&amp;...</span> <span class="identifier">args</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">arity</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">expr_2</span><span class="special">,</span> <span class="identifier">get_arity</span><span class="special">{});</span>
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">arity</span><span class="special">.</span><span class="identifier">value</span> <span class="special">==</span> <span class="keyword">sizeof</span><span class="special">...(</span><span class="identifier">args</span><span class="special">),</span> <span class="string">"Called with wrong number of args."</span><span class="special">);</span>
<span class="keyword">return</span> <span class="identifier">evaluate</span><span class="special">(</span><span class="identifier">expr_2</span><span class="special">,</span> <span class="identifier">args</span><span class="special">...);</span>
<span class="special">};</span>
<span class="keyword">auto</span> <span class="identifier">expr_3</span> <span class="special">=</span> <span class="special">(</span><span class="number">1</span><span class="identifier">_p</span> <span class="special">-</span> <span class="number">2</span><span class="identifier">_p</span><span class="special">)</span> <span class="special">/</span> <span class="number">2</span><span class="identifier">_p</span><span class="special">;</span>
<span class="keyword">auto</span> <span class="identifier">expr_3_fn</span> <span class="special">=</span> <span class="special">[</span><span class="identifier">expr_3</span><span class="special">](</span><span class="keyword">auto</span> <span class="special">&amp;&amp;...</span> <span class="identifier">args</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">arity</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">expr_3</span><span class="special">,</span> <span class="identifier">get_arity</span><span class="special">{});</span>
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">arity</span><span class="special">.</span><span class="identifier">value</span> <span class="special">==</span> <span class="keyword">sizeof</span><span class="special">...(</span><span class="identifier">args</span><span class="special">),</span> <span class="string">"Called with wrong number of args."</span><span class="special">);</span>
<span class="keyword">return</span> <span class="identifier">evaluate</span><span class="special">(</span><span class="identifier">expr_3</span><span class="special">,</span> <span class="identifier">args</span><span class="special">...);</span>
<span class="special">};</span>
<span class="comment">// Displays "5"</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">expr_1_fn</span><span class="special">(</span><span class="number">3.0</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="comment">// Displays "6"</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">expr_2_fn</span><span class="special">(</span><span class="number">3.0</span><span class="special">,</span> <span class="number">2.0</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="comment">// Displays "0.5"</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">expr_3_fn</span><span class="special">(</span><span class="number">3.0</span><span class="special">,</span> <span class="number">2.0</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="comment">// Static-asserts with "Called with wrong number of args."</span>
<span class="comment">//std::cout &lt;&lt; expr_3_fn(3.0) &lt;&lt; std::endl;</span>
<span class="comment">// Static-asserts with "Called with wrong number of args."</span>
<span class="comment">//std::cout &lt;&lt; expr_3_fn(3.0, 2.0, 1.0) &lt;&lt; std::endl;</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="boost_yap.manual.examples.lazy_vector"></a><a class="link" href="manual.html#boost_yap.manual.examples.lazy_vector" title="Lazy Vector">Lazy Vector</a>
</h4></div></div></div>
<p>
Finally, it starts to get interesting! This example shows how you can add
plus and other operations to sequences of data without creating temporaries
and allocating memory.
</p>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../doc/src/images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td align="left" valign="top"><p>
In this example, we see a terminal type that owns the storage of its
value, a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;</span></code>.
See the Vector example later on to see a terminal type that does not.
</p></td></tr>
</table></div>
<p>
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">yap</span><span class="special">/</span><span class="identifier">expression</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">algorithm</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">cassert</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">vector</span><span class="special">&gt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">Kind</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">lazy_vector_expr</span><span class="special">;</span>
<span class="comment">// This transform turns a terminal of std::vector&lt;double&gt; into a terminal</span>
<span class="comment">// containing the nth double in that vector. Think of it as turning our</span>
<span class="comment">// expression of vectors into an expression of scalars.</span>
<span class="keyword">struct</span> <span class="identifier">take_nth</span>
<span class="special">{</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">&lt;</span><span class="identifier">lazy_vector_expr</span><span class="special">,</span> <span class="keyword">double</span><span class="special">&gt;</span>
<span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">&lt;</span><span class="identifier">lazy_vector_expr</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;&gt;</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">expr</span><span class="special">);</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">n</span><span class="special">;</span>
<span class="special">};</span>
<span class="comment">// A custom expression template that defines lazy + and - operators that</span>
<span class="comment">// produce expressions, and an eager [] operator that returns the nth element</span>
<span class="comment">// of the expression.</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">Kind</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">lazy_vector_expr</span>
<span class="special">{</span>
<span class="keyword">static</span> <span class="keyword">const</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">kind</span> <span class="special">=</span> <span class="identifier">Kind</span><span class="special">;</span>
<span class="identifier">Tuple</span> <span class="identifier">elements</span><span class="special">;</span>
<span class="comment">// Note that this does not return an expression; it is greedily evaluated.</span>
<span class="keyword">auto</span> <span class="keyword">operator</span><span class="special">[]</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">n</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span>
<span class="special">};</span>
<span class="identifier">BOOST_YAP_USER_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">plus</span><span class="special">,</span> <span class="identifier">lazy_vector_expr</span><span class="special">,</span> <span class="identifier">lazy_vector_expr</span><span class="special">)</span>
<span class="identifier">BOOST_YAP_USER_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">minus</span><span class="special">,</span> <span class="identifier">lazy_vector_expr</span><span class="special">,</span> <span class="identifier">lazy_vector_expr</span><span class="special">)</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">Kind</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="identifier">lazy_vector_expr</span><span class="special">&lt;</span><span class="identifier">Kind</span><span class="special">,</span> <span class="identifier">Tuple</span><span class="special">&gt;::</span><span class="keyword">operator</span><span class="special">[]</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">n</span><span class="special">)</span> <span class="keyword">const</span>
<span class="special">{</span> <span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">evaluate</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(*</span><span class="keyword">this</span><span class="special">,</span> <span class="identifier">take_nth</span><span class="special">{</span><span class="identifier">n</span><span class="special">}));</span> <span class="special">}</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">&lt;</span><span class="identifier">lazy_vector_expr</span><span class="special">,</span> <span class="keyword">double</span><span class="special">&gt;</span>
<span class="identifier">take_nth</span><span class="special">::</span><span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">&lt;</span><span class="identifier">lazy_vector_expr</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;&gt;</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">expr</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">double</span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">value</span><span class="special">(</span><span class="identifier">expr</span><span class="special">)[</span><span class="identifier">n</span><span class="special">];</span>
<span class="comment">// This move is something of a hack; we're forcing Yap to take a copy of x</span>
<span class="comment">// by using std::move(). The move indicates that the terminal should keep</span>
<span class="comment">// the value of x (since, being an rvalue, it may be a temporary), rather</span>
<span class="comment">// than a reference to x. See the "How Expression Operands Are Treated"</span>
<span class="comment">// section of the tutorial for details.</span>
<span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_terminal</span><span class="special">&lt;</span><span class="identifier">lazy_vector_expr</span><span class="special">,</span> <span class="keyword">double</span><span class="special">&gt;(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">x</span><span class="special">));</span>
<span class="special">}</span>
<span class="comment">// In order to define the += operator with the semantics we want, it's</span>
<span class="comment">// convenient to derive a terminal type from a terminal instantiation of</span>
<span class="comment">// lazy_vector_expr. Note that we could have written a template</span>
<span class="comment">// specialization here instead -- either one would work. That would of course</span>
<span class="comment">// have required more typing.</span>
<span class="keyword">struct</span> <span class="identifier">lazy_vector</span> <span class="special">:</span>
<span class="identifier">lazy_vector_expr</span><span class="special">&lt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;&gt;</span>
<span class="special">&gt;</span>
<span class="special">{</span>
<span class="identifier">lazy_vector</span> <span class="special">()</span> <span class="special">{}</span>
<span class="keyword">explicit</span> <span class="identifier">lazy_vector</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;</span> <span class="special">&amp;&amp;</span> <span class="identifier">vec</span><span class="special">)</span>
<span class="special">{</span> <span class="identifier">elements</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;&gt;(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">vec</span><span class="special">));</span> <span class="special">}</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">Kind</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">&gt;</span>
<span class="identifier">lazy_vector</span> <span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">+=</span> <span class="special">(</span><span class="identifier">lazy_vector_expr</span><span class="special">&lt;</span><span class="identifier">Kind</span><span class="special">,</span> <span class="identifier">Tuple</span><span class="special">&gt;</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">rhs</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;</span> <span class="special">&amp;</span> <span class="identifier">this_vec</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">value</span><span class="special">(*</span><span class="keyword">this</span><span class="special">);</span>
<span class="keyword">for</span> <span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">,</span> <span class="identifier">size</span> <span class="special">=</span> <span class="special">(</span><span class="keyword">int</span><span class="special">)</span><span class="identifier">this_vec</span><span class="special">.</span><span class="identifier">size</span><span class="special">();</span> <span class="identifier">i</span> <span class="special">&lt;</span> <span class="identifier">size</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">)</span> <span class="special">{</span>
<span class="identifier">this_vec</span><span class="special">[</span><span class="identifier">i</span><span class="special">]</span> <span class="special">+=</span> <span class="identifier">rhs</span><span class="special">[</span><span class="identifier">i</span><span class="special">];</span>
<span class="special">}</span>
<span class="keyword">return</span> <span class="special">*</span><span class="keyword">this</span><span class="special">;</span>
<span class="special">}</span>
<span class="special">};</span>
<span class="keyword">int</span> <span class="identifier">main</span> <span class="special">()</span>
<span class="special">{</span>
<span class="identifier">lazy_vector</span> <span class="identifier">v1</span><span class="special">{</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;(</span><span class="number">4</span><span class="special">,</span> <span class="number">1.0</span><span class="special">)};</span>
<span class="identifier">lazy_vector</span> <span class="identifier">v2</span><span class="special">{</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;(</span><span class="number">4</span><span class="special">,</span> <span class="number">2.0</span><span class="special">)};</span>
<span class="identifier">lazy_vector</span> <span class="identifier">v3</span><span class="special">{</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;(</span><span class="number">4</span><span class="special">,</span> <span class="number">3.0</span><span class="special">)};</span>
<span class="keyword">double</span> <span class="identifier">d1</span> <span class="special">=</span> <span class="special">(</span><span class="identifier">v2</span> <span class="special">+</span> <span class="identifier">v3</span><span class="special">)[</span><span class="number">2</span><span class="special">];</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">d1</span> <span class="special">&lt;&lt;</span> <span class="string">"\n"</span><span class="special">;</span>
<span class="identifier">v1</span> <span class="special">+=</span> <span class="identifier">v2</span> <span class="special">-</span> <span class="identifier">v3</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="char">'{'</span> <span class="special">&lt;&lt;</span> <span class="identifier">v1</span><span class="special">[</span><span class="number">0</span><span class="special">]</span> <span class="special">&lt;&lt;</span> <span class="char">','</span> <span class="special">&lt;&lt;</span> <span class="identifier">v1</span><span class="special">[</span><span class="number">1</span><span class="special">]</span>
<span class="special">&lt;&lt;</span> <span class="char">','</span> <span class="special">&lt;&lt;</span> <span class="identifier">v1</span><span class="special">[</span><span class="number">2</span><span class="special">]</span> <span class="special">&lt;&lt;</span> <span class="char">','</span> <span class="special">&lt;&lt;</span> <span class="identifier">v1</span><span class="special">[</span><span class="number">3</span><span class="special">]</span> <span class="special">&lt;&lt;</span> <span class="char">'}'</span> <span class="special">&lt;&lt;</span> <span class="string">"\n"</span><span class="special">;</span>
<span class="comment">// This expression is disallowed because it does not conform to the</span>
<span class="comment">// implicit grammar. operator+= is only defined on terminals, not</span>
<span class="comment">// arbitrary expressions.</span>
<span class="comment">// (v2 + v3) += v1;</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="boost_yap.manual.examples.self_evaluating_expressions"></a><a class="link" href="manual.html#boost_yap.manual.examples.self_evaluating_expressions" title="Self-Evaluating Expressions">Self-Evaluating
Expressions</a>
</h4></div></div></div>
<p>
In most of the examples, we've seen Boost.YAP expressions captured, transformed,
and/or evaluated either manually, or within certain operations that always
do certain transformations (as in the <code class="computeroutput"><span class="keyword">operator</span><span class="special">[]</span></code> in the <a class="link" href="manual.html#boost_yap.manual.examples.lazy_vector" title="Lazy Vector">Lazy
Vector</a> example).
</p>
<p>
Sometimes, you want the transfrmations to happen just before a Boost.YAP
expression is used by non-Boost.YAP-aware code. At other times, you might
want an entire Boost.YAP expression to be evaluated if it appears by itself
in a statement (i.e. as an expression statement).
</p>
<p>
This example uses C++17's <code class="computeroutput"><span class="keyword">if</span> <span class="keyword">constexpr</span> <span class="special">()</span></code>,
simply because it makes the example shorter and easier to digest. The
<code class="computeroutput"><span class="keyword">if</span> <span class="keyword">constexpr</span>
<span class="special">()</span></code> bits are not strictly necessary.
</p>
<p>
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">yap</span><span class="special">/</span><span class="identifier">expression</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">optional</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">hana</span><span class="special">/</span><span class="identifier">fold</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">hana</span><span class="special">/</span><span class="identifier">maximum</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">algorithm</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">cassert</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">vector</span><span class="special">&gt;</span>
<span class="comment">// A super-basic matrix type, and a few associated operations.</span>
<span class="keyword">struct</span> <span class="identifier">matrix</span>
<span class="special">{</span>
<span class="identifier">matrix</span><span class="special">()</span> <span class="special">:</span> <span class="identifier">values_</span><span class="special">(),</span> <span class="identifier">rows_</span><span class="special">(</span><span class="number">0</span><span class="special">),</span> <span class="identifier">cols_</span><span class="special">(</span><span class="number">0</span><span class="special">)</span> <span class="special">{}</span>
<span class="identifier">matrix</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">rows</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">cols</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">values_</span><span class="special">(</span><span class="identifier">rows</span> <span class="special">*</span> <span class="identifier">cols</span><span class="special">),</span> <span class="identifier">rows_</span><span class="special">(</span><span class="identifier">rows</span><span class="special">),</span> <span class="identifier">cols_</span><span class="special">(</span><span class="identifier">cols</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">assert</span><span class="special">(</span><span class="number">0</span> <span class="special">&lt;</span> <span class="identifier">rows</span><span class="special">);</span>
<span class="identifier">assert</span><span class="special">(</span><span class="number">0</span> <span class="special">&lt;</span> <span class="identifier">cols</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">rows</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">rows_</span><span class="special">;</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">cols</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">cols_</span><span class="special">;</span> <span class="special">}</span>
<span class="keyword">double</span> <span class="keyword">operator</span><span class="special">()(</span><span class="keyword">int</span> <span class="identifier">r</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">c</span><span class="special">)</span> <span class="keyword">const</span>
<span class="special">{</span> <span class="keyword">return</span> <span class="identifier">values_</span><span class="special">[</span><span class="identifier">r</span> <span class="special">*</span> <span class="identifier">cols_</span> <span class="special">+</span> <span class="identifier">c</span><span class="special">];</span> <span class="special">}</span>
<span class="keyword">double</span> <span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">()(</span><span class="keyword">int</span> <span class="identifier">r</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">c</span><span class="special">)</span>
<span class="special">{</span> <span class="keyword">return</span> <span class="identifier">values_</span><span class="special">[</span><span class="identifier">r</span> <span class="special">*</span> <span class="identifier">cols_</span> <span class="special">+</span> <span class="identifier">c</span><span class="special">];</span> <span class="special">}</span>
<span class="keyword">private</span><span class="special">:</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;</span> <span class="identifier">values_</span><span class="special">;</span>
<span class="keyword">int</span> <span class="identifier">rows_</span><span class="special">;</span>
<span class="keyword">int</span> <span class="identifier">cols_</span><span class="special">;</span>
<span class="special">};</span>
<span class="identifier">matrix</span> <span class="keyword">operator</span><span class="special">*(</span><span class="identifier">matrix</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">double</span> <span class="identifier">x</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">matrix</span> <span class="identifier">retval</span> <span class="special">=</span> <span class="identifier">lhs</span><span class="special">;</span>
<span class="keyword">for</span> <span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special">&lt;</span> <span class="identifier">retval</span><span class="special">.</span><span class="identifier">rows</span><span class="special">();</span> <span class="special">++</span><span class="identifier">i</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">for</span> <span class="special">(</span><span class="keyword">int</span> <span class="identifier">j</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">j</span> <span class="special">&lt;</span> <span class="identifier">retval</span><span class="special">.</span><span class="identifier">cols</span><span class="special">();</span> <span class="special">++</span><span class="identifier">j</span><span class="special">)</span> <span class="special">{</span>
<span class="identifier">retval</span><span class="special">(</span><span class="identifier">i</span><span class="special">,</span> <span class="identifier">j</span><span class="special">)</span> <span class="special">*=</span> <span class="identifier">x</span><span class="special">;</span>
<span class="special">}</span>
<span class="special">}</span>
<span class="keyword">return</span> <span class="identifier">retval</span><span class="special">;</span>
<span class="special">}</span>
<span class="identifier">matrix</span> <span class="keyword">operator</span><span class="special">*(</span><span class="keyword">double</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">matrix</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">lhs</span><span class="special">)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">lhs</span> <span class="special">*</span> <span class="identifier">x</span><span class="special">;</span> <span class="special">}</span>
<span class="identifier">matrix</span> <span class="keyword">operator</span><span class="special">+(</span><span class="identifier">matrix</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">matrix</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">rhs</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">rows</span><span class="special">()</span> <span class="special">==</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">rows</span><span class="special">());</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">cols</span><span class="special">()</span> <span class="special">==</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">cols</span><span class="special">());</span>
<span class="identifier">matrix</span> <span class="identifier">retval</span> <span class="special">=</span> <span class="identifier">lhs</span><span class="special">;</span>
<span class="keyword">for</span> <span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special">&lt;</span> <span class="identifier">retval</span><span class="special">.</span><span class="identifier">rows</span><span class="special">();</span> <span class="special">++</span><span class="identifier">i</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">for</span> <span class="special">(</span><span class="keyword">int</span> <span class="identifier">j</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">j</span> <span class="special">&lt;</span> <span class="identifier">retval</span><span class="special">.</span><span class="identifier">cols</span><span class="special">();</span> <span class="special">++</span><span class="identifier">j</span><span class="special">)</span> <span class="special">{</span>
<span class="identifier">retval</span><span class="special">(</span><span class="identifier">i</span><span class="special">,</span> <span class="identifier">j</span><span class="special">)</span> <span class="special">+=</span> <span class="identifier">rhs</span><span class="special">(</span><span class="identifier">i</span><span class="special">,</span> <span class="identifier">j</span><span class="special">);</span>
<span class="special">}</span>
<span class="special">}</span>
<span class="keyword">return</span> <span class="identifier">retval</span><span class="special">;</span>
<span class="special">}</span>
<span class="comment">// daxpy() means Double-precision AX Plus Y. This crazy name comes from BLAS.</span>
<span class="comment">// It is more efficient than a naive implementation, because it does not</span>
<span class="comment">// create temporaries. The covnention of using Y as an out-parameter comes</span>
<span class="comment">// from FORTRAN BLAS.</span>
<span class="identifier">matrix</span> <span class="special">&amp;</span> <span class="identifier">daxpy</span><span class="special">(</span><span class="keyword">double</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">matrix</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">matrix</span> <span class="special">&amp;</span> <span class="identifier">y</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">rows</span><span class="special">()</span> <span class="special">==</span> <span class="identifier">y</span><span class="special">.</span><span class="identifier">rows</span><span class="special">());</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">cols</span><span class="special">()</span> <span class="special">==</span> <span class="identifier">y</span><span class="special">.</span><span class="identifier">cols</span><span class="special">());</span>
<span class="keyword">for</span> <span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special">&lt;</span> <span class="identifier">y</span><span class="special">.</span><span class="identifier">rows</span><span class="special">();</span> <span class="special">++</span><span class="identifier">i</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">for</span> <span class="special">(</span><span class="keyword">int</span> <span class="identifier">j</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">j</span> <span class="special">&lt;</span> <span class="identifier">y</span><span class="special">.</span><span class="identifier">cols</span><span class="special">();</span> <span class="special">++</span><span class="identifier">j</span><span class="special">)</span> <span class="special">{</span>
<span class="identifier">y</span><span class="special">(</span><span class="identifier">i</span><span class="special">,</span> <span class="identifier">j</span><span class="special">)</span> <span class="special">+=</span> <span class="identifier">a</span> <span class="special">*</span> <span class="identifier">x</span><span class="special">(</span><span class="identifier">i</span><span class="special">,</span> <span class="identifier">j</span><span class="special">);</span>
<span class="special">}</span>
<span class="special">}</span>
<span class="keyword">return</span> <span class="identifier">y</span><span class="special">;</span>
<span class="special">}</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">Kind</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">self_evaluating_expr</span><span class="special">;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">Kind</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="identifier">evaluate_matrix_expr</span><span class="special">(</span><span class="identifier">self_evaluating_expr</span><span class="special">&lt;</span><span class="identifier">Kind</span><span class="special">,</span> <span class="identifier">Tuple</span><span class="special">&gt;</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">expr</span><span class="special">);</span>
<span class="comment">// This is the primary template for our expression template. If you assign a</span>
<span class="comment">// self_evaluating_expr to a matrix, its conversion operator transforms and</span>
<span class="comment">// evaluates the expression with a call to evaluate_matrix_expr().</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">Kind</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">self_evaluating_expr</span>
<span class="special">{</span>
<span class="keyword">operator</span> <span class="keyword">auto</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
<span class="keyword">static</span> <span class="keyword">const</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">kind</span> <span class="special">=</span> <span class="identifier">Kind</span><span class="special">;</span>
<span class="identifier">Tuple</span> <span class="identifier">elements</span><span class="special">;</span>
<span class="special">};</span>
<span class="comment">// This is a specialization of our expression template for assignment</span>
<span class="comment">// expressions. The destructor transforms and evaluates via a call to</span>
<span class="comment">// evaluate_matrix_expr(), and then assigns the result to the variable on the</span>
<span class="comment">// left side of the assignment.</span>
<span class="comment">//</span>
<span class="comment">// In a production implementation, you'd need to have specializations for</span>
<span class="comment">// plus_assign, minus_assign, etc.</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">self_evaluating_expr</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">assign</span><span class="special">,</span> <span class="identifier">Tuple</span><span class="special">&gt;</span>
<span class="special">{</span>
<span class="special">~</span><span class="identifier">self_evaluating_expr</span><span class="special">();</span>
<span class="keyword">static</span> <span class="keyword">const</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">kind</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">assign</span><span class="special">;</span>
<span class="identifier">Tuple</span> <span class="identifier">elements</span><span class="special">;</span>
<span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">use_daxpy</span>
<span class="special">{</span>
<span class="comment">// A plus-expression, which may be of the form double * matrix + matrix,</span>
<span class="comment">// or may be something else. Since our daxpy() above requires a mutable</span>
<span class="comment">// "y", we only need to match a mutable lvalue matrix reference here.</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="keyword">operator</span><span class="special">()(</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_tag</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">plus</span><span class="special">&gt;,</span>
<span class="identifier">self_evaluating_expr</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">multiplies</span><span class="special">,</span> <span class="identifier">Tuple</span><span class="special">&gt;</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">expr</span><span class="special">,</span>
<span class="identifier">matrix</span> <span class="special">&amp;</span> <span class="identifier">m</span><span class="special">)</span>
<span class="special">{</span>
<span class="comment">// Here, we transform the left-hand side into a pair if it's the</span>
<span class="comment">// double * matrix operation we're looking for. Otherwise, we just</span>
<span class="comment">// get a copy of the left side expression.</span>
<span class="comment">//</span>
<span class="comment">// Note that this is a bit of a cheat, done for clarity. If we pass a</span>
<span class="comment">// larger expression that happens to contain a double * matrix</span>
<span class="comment">// subexpression, that subexpression will be transformed into a tuple!</span>
<span class="comment">// In production code, this transform should probably only be</span>
<span class="comment">// performed on an expression with all terminal members.</span>
<span class="keyword">auto</span> <span class="identifier">lhs</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span>
<span class="identifier">expr</span><span class="special">,</span>
<span class="special">[](</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_tag</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">multiplies</span><span class="special">&gt;,</span>
<span class="keyword">double</span> <span class="identifier">d</span><span class="special">,</span>
<span class="identifier">matrix</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">m</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">,</span> <span class="identifier">matrix</span> <span class="keyword">const</span> <span class="special">&amp;&gt;(</span><span class="identifier">d</span><span class="special">,</span> <span class="identifier">m</span><span class="special">);</span>
<span class="special">});</span>
<span class="comment">// If we got back a copy of expr above, just re-construct the</span>
<span class="comment">// expression this function mathes; in other words, do not effectively</span>
<span class="comment">// transform anything. Otherwise, replace the expression matched by</span>
<span class="comment">// this function with a call to daxpy().</span>
<span class="keyword">if</span> <span class="keyword">constexpr</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">is_expr</span><span class="special">&lt;</span><span class="keyword">decltype</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">)&gt;::</span><span class="identifier">value</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">expr</span> <span class="special">+</span> <span class="identifier">m</span><span class="special">;</span>
<span class="special">}</span> <span class="keyword">else</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_terminal</span><span class="special">(</span><span class="identifier">daxpy</span><span class="special">)(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">first</span><span class="special">,</span> <span class="identifier">lhs</span><span class="special">.</span><span class="identifier">second</span><span class="special">,</span> <span class="identifier">m</span><span class="special">);</span>
<span class="special">}</span>
<span class="special">}</span>
<span class="special">};</span>
<span class="comment">// This is the heart of what self_evaluating_expr does. If we had other</span>
<span class="comment">// optimizations/transformations we wanted to do, we'd put them in this</span>
<span class="comment">// function, either before or after the use_daxpy transformation.</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">Kind</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="identifier">evaluate_matrix_expr</span><span class="special">(</span><span class="identifier">self_evaluating_expr</span><span class="special">&lt;</span><span class="identifier">Kind</span><span class="special">,</span> <span class="identifier">Tuple</span><span class="special">&gt;</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">expr</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">auto</span> <span class="identifier">daxpy_form</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">expr</span><span class="special">,</span> <span class="identifier">use_daxpy</span><span class="special">{});</span>
<span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">evaluate</span><span class="special">(</span><span class="identifier">daxpy_form</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">Kind</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">&gt;</span>
<span class="identifier">self_evaluating_expr</span><span class="special">&lt;</span><span class="identifier">Kind</span><span class="special">,</span> <span class="identifier">Tuple</span><span class="special">&gt;::</span><span class="keyword">operator</span> <span class="keyword">auto</span><span class="special">()</span> <span class="keyword">const</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">evaluate_matrix_expr</span><span class="special">(*</span><span class="keyword">this</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">&gt;</span>
<span class="identifier">self_evaluating_expr</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">assign</span><span class="special">,</span> <span class="identifier">Tuple</span><span class="special">&gt;::</span>
<span class="special">~</span><span class="identifier">self_evaluating_expr</span><span class="special">()</span>
<span class="special">{</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">literals</span><span class="special">;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">evaluate</span><span class="special">(</span><span class="identifier">elements</span><span class="special">[</span><span class="number">0</span><span class="identifier">_c</span><span class="special">])</span> <span class="special">=</span> <span class="identifier">evaluate_matrix_expr</span><span class="special">(</span><span class="identifier">elements</span><span class="special">[</span><span class="number">1</span><span class="identifier">_c</span><span class="special">]);</span>
<span class="special">}</span>
<span class="comment">// In order to define the = operator with the semantics we want, it's</span>
<span class="comment">// convenient to derive a terminal type from a terminal instantiation of</span>
<span class="comment">// self_evaluating_expr. Note that we could have written a template</span>
<span class="comment">// specialization here instead -- either one would work. That would of course</span>
<span class="comment">// have required more typing.</span>
<span class="keyword">struct</span> <span class="identifier">self_evaluating</span> <span class="special">:</span>
<span class="identifier">self_evaluating_expr</span><span class="special">&lt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="identifier">matrix</span><span class="special">&gt;</span>
<span class="special">&gt;</span>
<span class="special">{</span>
<span class="identifier">self_evaluating</span><span class="special">()</span> <span class="special">{}</span>
<span class="keyword">explicit</span> <span class="identifier">self_evaluating</span><span class="special">(</span><span class="identifier">matrix</span> <span class="identifier">m</span><span class="special">)</span>
<span class="special">{</span> <span class="identifier">elements</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="identifier">matrix</span><span class="special">&gt;(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">m</span><span class="special">));</span> <span class="special">}</span>
<span class="identifier">BOOST_YAP_USER_ASSIGN_OPERATOR</span><span class="special">(</span><span class="identifier">self_evaluating_expr</span><span class="special">,</span> <span class="special">::</span><span class="identifier">self_evaluating_expr</span><span class="special">);</span>
<span class="special">};</span>
<span class="identifier">BOOST_YAP_USER_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">plus</span><span class="special">,</span> <span class="identifier">self_evaluating_expr</span><span class="special">,</span> <span class="identifier">self_evaluating_expr</span><span class="special">)</span>
<span class="identifier">BOOST_YAP_USER_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">minus</span><span class="special">,</span> <span class="identifier">self_evaluating_expr</span><span class="special">,</span> <span class="identifier">self_evaluating_expr</span><span class="special">)</span>
<span class="identifier">BOOST_YAP_USER_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">multiplies</span><span class="special">,</span> <span class="identifier">self_evaluating_expr</span><span class="special">,</span> <span class="identifier">self_evaluating_expr</span><span class="special">)</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span>
<span class="special">{</span>
<span class="identifier">matrix</span> <span class="identifier">identity</span><span class="special">(</span><span class="number">2</span><span class="special">,</span> <span class="number">2</span><span class="special">);</span>
<span class="identifier">identity</span><span class="special">(</span><span class="number">0</span><span class="special">,</span> <span class="number">0</span><span class="special">)</span> <span class="special">=</span> <span class="number">1.0</span><span class="special">;</span>
<span class="identifier">identity</span><span class="special">(</span><span class="number">1</span><span class="special">,</span> <span class="number">1</span><span class="special">)</span> <span class="special">=</span> <span class="number">1.0</span><span class="special">;</span>
<span class="comment">// These are YAP-ified terminal expressions.</span>
<span class="identifier">self_evaluating</span> <span class="identifier">m1</span><span class="special">(</span><span class="identifier">identity</span><span class="special">);</span>
<span class="identifier">self_evaluating</span> <span class="identifier">m2</span><span class="special">(</span><span class="identifier">identity</span><span class="special">);</span>
<span class="identifier">self_evaluating</span> <span class="identifier">m3</span><span class="special">(</span><span class="identifier">identity</span><span class="special">);</span>
<span class="comment">// This transforms the YAP expression to use daxpy(), so it creates no</span>
<span class="comment">// temporaries. The transform happens in the destructor of the</span>
<span class="comment">// assignment-expression specialization of self_evaluating_expr.</span>
<span class="identifier">m1</span> <span class="special">=</span> <span class="number">3.0</span> <span class="special">*</span> <span class="identifier">m2</span> <span class="special">+</span> <span class="identifier">m3</span><span class="special">;</span>
<span class="comment">// Same as above, except that it uses the matrix conversion operator on</span>
<span class="comment">// the self_evaluating_expr primary template, because here we're assigning</span>
<span class="comment">// a YAP expression to a non-YAP-ified matrix.</span>
<span class="identifier">matrix</span> <span class="identifier">m_result_1</span> <span class="special">=</span> <span class="number">3.0</span> <span class="special">*</span> <span class="identifier">m2</span> <span class="special">+</span> <span class="identifier">m3</span><span class="special">;</span>
<span class="comment">// Creates temporaries and does not use daxpy(), because the A * X + Y</span>
<span class="comment">// pattern does not occur within the expression.</span>
<span class="identifier">matrix</span> <span class="identifier">m_result_2</span> <span class="special">=</span> <span class="number">3.0</span> <span class="special">*</span> <span class="identifier">m2</span><span class="special">;</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="boost_yap.manual.examples.tarray"></a><a class="link" href="manual.html#boost_yap.manual.examples.tarray" title="TArray">TArray</a>
</h4></div></div></div>
<p>
Proto refers to this as the "mini-library for linear algebra"
example. It shows how quite complicated expressions involving sequences
can be evaluated elementwise, requiring no temporaries.
</p>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../doc/src/images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td align="left" valign="top"><p>
The original Proto example used a terminal that contained an array of
three <code class="computeroutput"><span class="keyword">int</span></code>s; Boost.YAP cannot
represent this, and so this example uses a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">array</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span> <span class="number">3</span><span class="special">&gt;</span></code>
instead. Boost.YAP decays <code class="computeroutput"><span class="keyword">int</span><span class="special">[</span><span class="number">3</span><span class="special">]</span></code>
to <code class="computeroutput"><span class="keyword">int</span> <span class="special">*</span></code>,
since that is what is done in a C++ expression. See <a class="link" href="manual.html#boost_yap.manual.how_expression_operands_are_treated" title="How Expression Operands Are Treated">How
Expression Operands Are Treated</a> for details.
</p></td></tr>
</table></div>
<p>
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">yap</span><span class="special">/</span><span class="identifier">algorithm</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">yap</span><span class="special">/</span><span class="identifier">print</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">array</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">Kind</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">tarray_expr</span><span class="special">;</span>
<span class="keyword">struct</span> <span class="identifier">take_nth</span>
<span class="special">{</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">&lt;</span><span class="identifier">tarray_expr</span><span class="special">,</span> <span class="keyword">int</span><span class="special">&gt;</span>
<span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">&lt;</span><span class="identifier">tarray_expr</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">array</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="number">3</span><span class="special">&gt;&gt;</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">expr</span><span class="special">);</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">n</span><span class="special">;</span>
<span class="special">};</span>
<span class="comment">// Another custom expression template. In this case, we static_assert() that</span>
<span class="comment">// it only gets instantiated with terminals with pre-approved value types.</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">Kind</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">tarray_expr</span>
<span class="special">{</span>
<span class="comment">// Make sure that, if this expression is a terminal, its value is one we</span>
<span class="comment">// want to support. Note that the presence of expr_kind::expr_ref makes</span>
<span class="comment">// life slightly more difficult; we have to account for int const &amp; and</span>
<span class="comment">// int &amp; as well as int.</span>
<span class="keyword">static_assert</span><span class="special">(</span>
<span class="identifier">Kind</span> <span class="special">!=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span> <span class="special">||</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">is_same</span><span class="special">&lt;</span><span class="identifier">Tuple</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="keyword">int</span> <span class="keyword">const</span> <span class="special">&amp;&gt;&gt;{}</span> <span class="special">||</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">is_same</span><span class="special">&lt;</span><span class="identifier">Tuple</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="keyword">int</span> <span class="special">&amp;&gt;&gt;{}</span> <span class="special">||</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">is_same</span><span class="special">&lt;</span><span class="identifier">Tuple</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;&gt;{}</span> <span class="special">||</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">is_same</span><span class="special">&lt;</span><span class="identifier">Tuple</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">array</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="number">3</span><span class="special">&gt;&gt;&gt;{},</span>
<span class="string">"tarray_expr instantiated with an unsupported terminal type."</span>
<span class="special">);</span>
<span class="keyword">static</span> <span class="keyword">const</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">kind</span> <span class="special">=</span> <span class="identifier">Kind</span><span class="special">;</span>
<span class="identifier">Tuple</span> <span class="identifier">elements</span><span class="special">;</span>
<span class="keyword">int</span> <span class="keyword">operator</span><span class="special">[]</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">n</span><span class="special">)</span> <span class="keyword">const</span>
<span class="special">{</span> <span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">evaluate</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(*</span><span class="keyword">this</span><span class="special">,</span> <span class="identifier">take_nth</span><span class="special">{</span><span class="identifier">n</span><span class="special">}));</span> <span class="special">}</span>
<span class="special">};</span>
<span class="comment">// Define operators +, -, *, and /.</span>
<span class="identifier">BOOST_YAP_USER_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">plus</span><span class="special">,</span> <span class="identifier">tarray_expr</span><span class="special">,</span> <span class="identifier">tarray_expr</span><span class="special">)</span>
<span class="identifier">BOOST_YAP_USER_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">minus</span><span class="special">,</span> <span class="identifier">tarray_expr</span><span class="special">,</span> <span class="identifier">tarray_expr</span><span class="special">)</span>
<span class="identifier">BOOST_YAP_USER_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">multiplies</span><span class="special">,</span> <span class="identifier">tarray_expr</span><span class="special">,</span> <span class="identifier">tarray_expr</span><span class="special">)</span>
<span class="identifier">BOOST_YAP_USER_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">divides</span><span class="special">,</span> <span class="identifier">tarray_expr</span><span class="special">,</span> <span class="identifier">tarray_expr</span><span class="special">)</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">&lt;</span><span class="identifier">tarray_expr</span><span class="special">,</span> <span class="keyword">int</span><span class="special">&gt;</span>
<span class="identifier">take_nth</span><span class="special">::</span><span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">&lt;</span><span class="identifier">tarray_expr</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">array</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="number">3</span><span class="special">&gt;&gt;</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">expr</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">int</span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">value</span><span class="special">(</span><span class="identifier">expr</span><span class="special">)[</span><span class="identifier">n</span><span class="special">];</span>
<span class="comment">// Again, this is the move hack to get x into the resulting terminal as a</span>
<span class="comment">// value instead of a reference.</span>
<span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_terminal</span><span class="special">&lt;</span><span class="identifier">tarray_expr</span><span class="special">&gt;(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">x</span><span class="special">));</span>
<span class="special">}</span>
<span class="comment">// Stream-out operators for the two kinds of terminals we support.</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span> <span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">&lt;&lt;</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span> <span class="special">&amp;</span> <span class="identifier">os</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">&lt;</span><span class="identifier">tarray_expr</span><span class="special">,</span> <span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">expr</span><span class="special">)</span>
<span class="special">{</span> <span class="keyword">return</span> <span class="identifier">os</span> <span class="special">&lt;&lt;</span> <span class="char">'{'</span> <span class="special">&lt;&lt;</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">value</span><span class="special">(</span><span class="identifier">expr</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="char">'}'</span><span class="special">;</span> <span class="special">}</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span> <span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">&lt;&lt;</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span> <span class="special">&amp;</span> <span class="identifier">os</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">&lt;</span><span class="identifier">tarray_expr</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">array</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="number">3</span><span class="special">&gt;&gt;</span> <span class="identifier">expr</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">array</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="number">3</span><span class="special">&gt;</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">a</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">value</span><span class="special">(</span><span class="identifier">expr</span><span class="special">);</span>
<span class="keyword">return</span> <span class="identifier">os</span> <span class="special">&lt;&lt;</span> <span class="char">'{'</span> <span class="special">&lt;&lt;</span> <span class="identifier">a</span><span class="special">[</span><span class="number">0</span><span class="special">]</span> <span class="special">&lt;&lt;</span> <span class="string">", "</span> <span class="special">&lt;&lt;</span> <span class="identifier">a</span><span class="special">[</span><span class="number">1</span><span class="special">]</span> <span class="special">&lt;&lt;</span> <span class="string">", "</span> <span class="special">&lt;&lt;</span> <span class="identifier">a</span><span class="special">[</span><span class="number">2</span><span class="special">]</span> <span class="special">&lt;&lt;</span> <span class="char">'}'</span><span class="special">;</span>
<span class="special">}</span>
<span class="comment">// Stream-out operators for general expressions. Note that we have to treat</span>
<span class="comment">// the reference case separately; this also could have been done using</span>
<span class="comment">// constexpr if in a single function template.</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span> <span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">&lt;&lt;</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span> <span class="special">&amp;</span> <span class="identifier">os</span><span class="special">,</span> <span class="identifier">tarray_expr</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">expr_ref</span><span class="special">,</span> <span class="identifier">Tuple</span><span class="special">&gt;</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">expr</span><span class="special">)</span>
<span class="special">{</span> <span class="keyword">return</span> <span class="identifier">os</span> <span class="special">&lt;&lt;</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">deref</span><span class="special">(</span><span class="identifier">expr</span><span class="special">);</span> <span class="special">}</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">Kind</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span> <span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">&lt;&lt;</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span> <span class="special">&amp;</span> <span class="identifier">os</span><span class="special">,</span> <span class="identifier">tarray_expr</span><span class="special">&lt;</span><span class="identifier">Kind</span><span class="special">,</span> <span class="identifier">Tuple</span><span class="special">&gt;</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">expr</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">Kind</span> <span class="special">==</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">plus</span> <span class="special">||</span> <span class="identifier">Kind</span> <span class="special">==</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">minus</span><span class="special">)</span>
<span class="identifier">os</span> <span class="special">&lt;&lt;</span> <span class="char">'('</span><span class="special">;</span>
<span class="identifier">os</span> <span class="special">&lt;&lt;</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">left</span><span class="special">(</span><span class="identifier">expr</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="string">" "</span> <span class="special">&lt;&lt;</span> <span class="identifier">op_string</span><span class="special">(</span><span class="identifier">Kind</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="string">" "</span> <span class="special">&lt;&lt;</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">right</span><span class="special">(</span><span class="identifier">expr</span><span class="special">);</span>
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">Kind</span> <span class="special">==</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">plus</span> <span class="special">||</span> <span class="identifier">Kind</span> <span class="special">==</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">minus</span><span class="special">)</span>
<span class="identifier">os</span> <span class="special">&lt;&lt;</span> <span class="char">')'</span><span class="special">;</span>
<span class="keyword">return</span> <span class="identifier">os</span><span class="special">;</span>
<span class="special">}</span>
<span class="comment">// Since we want different behavior on terminals than on other kinds of</span>
<span class="comment">// expressions, we create a custom type that does so.</span>
<span class="keyword">struct</span> <span class="identifier">tarray</span> <span class="special">:</span>
<span class="identifier">tarray_expr</span><span class="special">&lt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">array</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="number">3</span><span class="special">&gt;&gt;</span>
<span class="special">&gt;</span>
<span class="special">{</span>
<span class="keyword">explicit</span> <span class="identifier">tarray</span> <span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">j</span> <span class="special">=</span> <span class="number">0</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">k</span> <span class="special">=</span> <span class="number">0</span><span class="special">)</span>
<span class="special">{</span>
<span class="special">(*</span><span class="keyword">this</span><span class="special">)[</span><span class="number">0</span><span class="special">]</span> <span class="special">=</span> <span class="identifier">i</span><span class="special">;</span>
<span class="special">(*</span><span class="keyword">this</span><span class="special">)[</span><span class="number">1</span><span class="special">]</span> <span class="special">=</span> <span class="identifier">j</span><span class="special">;</span>
<span class="special">(*</span><span class="keyword">this</span><span class="special">)[</span><span class="number">2</span><span class="special">]</span> <span class="special">=</span> <span class="identifier">k</span><span class="special">;</span>
<span class="special">}</span>
<span class="keyword">explicit</span> <span class="identifier">tarray</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">array</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="number">3</span><span class="special">&gt;</span> <span class="identifier">a</span><span class="special">)</span>
<span class="special">{</span>
<span class="special">(*</span><span class="keyword">this</span><span class="special">)[</span><span class="number">0</span><span class="special">]</span> <span class="special">=</span> <span class="identifier">a</span><span class="special">[</span><span class="number">0</span><span class="special">];</span>
<span class="special">(*</span><span class="keyword">this</span><span class="special">)[</span><span class="number">1</span><span class="special">]</span> <span class="special">=</span> <span class="identifier">a</span><span class="special">[</span><span class="number">1</span><span class="special">];</span>
<span class="special">(*</span><span class="keyword">this</span><span class="special">)[</span><span class="number">2</span><span class="special">]</span> <span class="special">=</span> <span class="identifier">a</span><span class="special">[</span><span class="number">2</span><span class="special">];</span>
<span class="special">}</span>
<span class="keyword">int</span> <span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">[]</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">ptrdiff_t</span> <span class="identifier">i</span><span class="special">)</span>
<span class="special">{</span> <span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">value</span><span class="special">(*</span><span class="keyword">this</span><span class="special">)[</span><span class="identifier">i</span><span class="special">];</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">[]</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">ptrdiff_t</span> <span class="identifier">i</span><span class="special">)</span> <span class="keyword">const</span>
<span class="special">{</span> <span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">value</span><span class="special">(*</span><span class="keyword">this</span><span class="special">)[</span><span class="identifier">i</span><span class="special">];</span> <span class="special">}</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="identifier">tarray</span> <span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">=</span> <span class="special">(</span><span class="identifier">T</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">t</span><span class="special">)</span>
<span class="special">{</span>
<span class="comment">// We use as_expr() here to make sure that the value passed to</span>
<span class="comment">// assign() is an expression. as_expr() simply forwards expressions</span>
<span class="comment">// through, and wraps non-expressions as terminals.</span>
<span class="keyword">return</span> <span class="identifier">assign</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">as_expr</span><span class="special">&lt;</span> <span class="special">::</span><span class="identifier">tarray_expr</span><span class="special">&gt;(</span><span class="identifier">t</span><span class="special">));</span>
<span class="special">}</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Expr</span><span class="special">&gt;</span>
<span class="identifier">tarray</span> <span class="special">&amp;</span> <span class="identifier">printAssign</span> <span class="special">(</span><span class="identifier">Expr</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">expr</span><span class="special">)</span>
<span class="special">{</span>
<span class="special">*</span><span class="keyword">this</span> <span class="special">=</span> <span class="identifier">expr</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="special">*</span><span class="keyword">this</span> <span class="special">&lt;&lt;</span> <span class="string">" = "</span> <span class="special">&lt;&lt;</span> <span class="identifier">expr</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="keyword">return</span> <span class="special">*</span><span class="keyword">this</span><span class="special">;</span>
<span class="special">}</span>
<span class="keyword">private</span><span class="special">:</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Expr</span><span class="special">&gt;</span>
<span class="identifier">tarray</span> <span class="special">&amp;</span> <span class="identifier">assign</span> <span class="special">(</span><span class="identifier">Expr</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">expr</span><span class="special">)</span>
<span class="special">{</span>
<span class="special">(*</span><span class="keyword">this</span><span class="special">)[</span><span class="number">0</span><span class="special">]</span> <span class="special">=</span> <span class="identifier">expr</span><span class="special">[</span><span class="number">0</span><span class="special">];</span>
<span class="special">(*</span><span class="keyword">this</span><span class="special">)[</span><span class="number">1</span><span class="special">]</span> <span class="special">=</span> <span class="identifier">expr</span><span class="special">[</span><span class="number">1</span><span class="special">];</span>
<span class="special">(*</span><span class="keyword">this</span><span class="special">)[</span><span class="number">2</span><span class="special">]</span> <span class="special">=</span> <span class="identifier">expr</span><span class="special">[</span><span class="number">2</span><span class="special">];</span>
<span class="keyword">return</span> <span class="special">*</span><span class="keyword">this</span><span class="special">;</span>
<span class="special">}</span>
<span class="special">};</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span>
<span class="special">{</span>
<span class="identifier">tarray</span> <span class="identifier">a</span><span class="special">(</span><span class="number">3</span><span class="special">,</span><span class="number">1</span><span class="special">,</span><span class="number">2</span><span class="special">);</span>
<span class="identifier">tarray</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">a</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">b</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">[</span><span class="number">0</span><span class="special">]</span> <span class="special">=</span> <span class="number">7</span><span class="special">;</span> <span class="identifier">b</span><span class="special">[</span><span class="number">1</span><span class="special">]</span> <span class="special">=</span> <span class="number">33</span><span class="special">;</span> <span class="identifier">b</span><span class="special">[</span><span class="number">2</span><span class="special">]</span> <span class="special">=</span> <span class="special">-</span><span class="number">99</span><span class="special">;</span>
<span class="identifier">tarray</span> <span class="identifier">c</span><span class="special">(</span><span class="identifier">a</span><span class="special">);</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">c</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="identifier">a</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">a</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">b</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">c</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="identifier">a</span> <span class="special">=</span> <span class="identifier">b</span> <span class="special">+</span> <span class="identifier">c</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">a</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="identifier">a</span><span class="special">.</span><span class="identifier">printAssign</span><span class="special">(</span><span class="identifier">b</span><span class="special">+</span><span class="identifier">c</span><span class="special">*(</span><span class="identifier">b</span> <span class="special">+</span> <span class="number">3</span><span class="special">*</span><span class="identifier">c</span><span class="special">));</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="boost_yap.manual.examples.vec3"></a><a class="link" href="manual.html#boost_yap.manual.examples.vec3" title="Vec3">Vec3</a>
</h4></div></div></div>
<p>
An example using 3-space vectors, a bit like the tarray example.
</p>
<p>
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">yap</span><span class="special">/</span><span class="identifier">yap</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">array</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">take_nth</span>
<span class="special">{</span>
<span class="keyword">auto</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">array</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="number">3</span><span class="special">&gt;&gt;</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">expr</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">int</span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">value</span><span class="special">(</span><span class="identifier">expr</span><span class="special">)[</span><span class="identifier">n</span><span class="special">];</span>
<span class="comment">// The move forces the terminal to store the value of x, not a</span>
<span class="comment">// reference.</span>
<span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_terminal</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">x</span><span class="special">));</span>
<span class="special">}</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">n</span><span class="special">;</span>
<span class="special">};</span>
<span class="comment">// Since this example doesn't constrain the operators defined on its</span>
<span class="comment">// expressions, we can just use boost::yap::expression&lt;&gt; as the expression</span>
<span class="comment">// template.</span>
<span class="keyword">using</span> <span class="identifier">vec3_terminal</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">&lt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">array</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="number">3</span><span class="special">&gt;&gt;</span>
<span class="special">&gt;;</span>
<span class="comment">// Customize the terminal type we use by adding index and assignment</span>
<span class="comment">// operations.</span>
<span class="keyword">struct</span> <span class="identifier">vec3</span> <span class="special">:</span> <span class="identifier">vec3_terminal</span>
<span class="special">{</span>
<span class="keyword">explicit</span> <span class="identifier">vec3</span> <span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">j</span> <span class="special">=</span> <span class="number">0</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">k</span> <span class="special">=</span> <span class="number">0</span><span class="special">)</span>
<span class="special">{</span>
<span class="special">(*</span><span class="keyword">this</span><span class="special">)[</span><span class="number">0</span><span class="special">]</span> <span class="special">=</span> <span class="identifier">i</span><span class="special">;</span>
<span class="special">(*</span><span class="keyword">this</span><span class="special">)[</span><span class="number">1</span><span class="special">]</span> <span class="special">=</span> <span class="identifier">j</span><span class="special">;</span>
<span class="special">(*</span><span class="keyword">this</span><span class="special">)[</span><span class="number">2</span><span class="special">]</span> <span class="special">=</span> <span class="identifier">k</span><span class="special">;</span>
<span class="special">}</span>
<span class="keyword">explicit</span> <span class="identifier">vec3</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">array</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="number">3</span><span class="special">&gt;</span> <span class="identifier">a</span><span class="special">)</span>
<span class="special">{</span>
<span class="special">(*</span><span class="keyword">this</span><span class="special">)[</span><span class="number">0</span><span class="special">]</span> <span class="special">=</span> <span class="identifier">a</span><span class="special">[</span><span class="number">0</span><span class="special">];</span>
<span class="special">(*</span><span class="keyword">this</span><span class="special">)[</span><span class="number">1</span><span class="special">]</span> <span class="special">=</span> <span class="identifier">a</span><span class="special">[</span><span class="number">1</span><span class="special">];</span>
<span class="special">(*</span><span class="keyword">this</span><span class="special">)[</span><span class="number">2</span><span class="special">]</span> <span class="special">=</span> <span class="identifier">a</span><span class="special">[</span><span class="number">2</span><span class="special">];</span>
<span class="special">}</span>
<span class="keyword">int</span> <span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">[]</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">ptrdiff_t</span> <span class="identifier">i</span><span class="special">)</span>
<span class="special">{</span> <span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">value</span><span class="special">(*</span><span class="keyword">this</span><span class="special">)[</span><span class="identifier">i</span><span class="special">];</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">[]</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">ptrdiff_t</span> <span class="identifier">i</span><span class="special">)</span> <span class="keyword">const</span>
<span class="special">{</span> <span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">value</span><span class="special">(*</span><span class="keyword">this</span><span class="special">)[</span><span class="identifier">i</span><span class="special">];</span> <span class="special">}</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="identifier">vec3</span> <span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">=</span> <span class="special">(</span><span class="identifier">T</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">t</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">decltype</span><span class="special">(</span><span class="keyword">auto</span><span class="special">)</span> <span class="identifier">expr</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">as_expr</span><span class="special">(</span><span class="identifier">t</span><span class="special">);</span>
<span class="special">(*</span><span class="keyword">this</span><span class="special">)[</span><span class="number">0</span><span class="special">]</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">evaluate</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">expr</span><span class="special">,</span> <span class="identifier">take_nth</span><span class="special">{</span><span class="number">0</span><span class="special">}));</span>
<span class="special">(*</span><span class="keyword">this</span><span class="special">)[</span><span class="number">1</span><span class="special">]</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">evaluate</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">expr</span><span class="special">,</span> <span class="identifier">take_nth</span><span class="special">{</span><span class="number">1</span><span class="special">}));</span>
<span class="special">(*</span><span class="keyword">this</span><span class="special">)[</span><span class="number">2</span><span class="special">]</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">evaluate</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">expr</span><span class="special">,</span> <span class="identifier">take_nth</span><span class="special">{</span><span class="number">2</span><span class="special">}));</span>
<span class="keyword">return</span> <span class="special">*</span><span class="keyword">this</span><span class="special">;</span>
<span class="special">}</span>
<span class="keyword">void</span> <span class="identifier">print</span><span class="special">()</span> <span class="keyword">const</span>
<span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="char">'{'</span> <span class="special">&lt;&lt;</span> <span class="special">(*</span><span class="keyword">this</span><span class="special">)[</span><span class="number">0</span><span class="special">]</span>
<span class="special">&lt;&lt;</span> <span class="string">", "</span> <span class="special">&lt;&lt;</span> <span class="special">(*</span><span class="keyword">this</span><span class="special">)[</span><span class="number">1</span><span class="special">]</span>
<span class="special">&lt;&lt;</span> <span class="string">", "</span> <span class="special">&lt;&lt;</span> <span class="special">(*</span><span class="keyword">this</span><span class="special">)[</span><span class="number">2</span><span class="special">]</span>
<span class="special">&lt;&lt;</span> <span class="char">'}'</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="special">}</span>
<span class="special">};</span>
<span class="comment">// This is a stateful transform that keeps a running count of the terminals it</span>
<span class="comment">// has seen.</span>
<span class="keyword">struct</span> <span class="identifier">count_leaves_impl</span>
<span class="special">{</span>
<span class="keyword">auto</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span><span class="identifier">vec3_terminal</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">expr</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">value</span> <span class="special">+=</span> <span class="number">1</span><span class="special">;</span>
<span class="keyword">return</span> <span class="identifier">expr</span><span class="special">;</span>
<span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">value</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Expr</span><span class="special">&gt;</span>
<span class="keyword">int</span> <span class="identifier">count_leaves</span> <span class="special">(</span><span class="identifier">Expr</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">expr</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">count_leaves_impl</span> <span class="identifier">impl</span><span class="special">;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">as_expr</span><span class="special">(</span><span class="identifier">expr</span><span class="special">),</span> <span class="identifier">impl</span><span class="special">);</span>
<span class="keyword">return</span> <span class="identifier">impl</span><span class="special">.</span><span class="identifier">value</span><span class="special">;</span>
<span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span>
<span class="special">{</span>
<span class="identifier">vec3</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">b</span><span class="special">,</span> <span class="identifier">c</span><span class="special">;</span>
<span class="identifier">c</span> <span class="special">=</span> <span class="number">4</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">[</span><span class="number">0</span><span class="special">]</span> <span class="special">=</span> <span class="special">-</span><span class="number">1</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">[</span><span class="number">1</span><span class="special">]</span> <span class="special">=</span> <span class="special">-</span><span class="number">2</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">[</span><span class="number">2</span><span class="special">]</span> <span class="special">=</span> <span class="special">-</span><span class="number">3</span><span class="special">;</span>
<span class="identifier">a</span> <span class="special">=</span> <span class="identifier">b</span> <span class="special">+</span> <span class="identifier">c</span><span class="special">;</span>
<span class="identifier">a</span><span class="special">.</span><span class="identifier">print</span><span class="special">();</span>
<span class="identifier">vec3</span> <span class="identifier">d</span><span class="special">;</span>
<span class="keyword">auto</span> <span class="identifier">expr1</span> <span class="special">=</span> <span class="identifier">b</span> <span class="special">+</span> <span class="identifier">c</span><span class="special">;</span>
<span class="identifier">d</span> <span class="special">=</span> <span class="identifier">expr1</span><span class="special">;</span>
<span class="identifier">d</span><span class="special">.</span><span class="identifier">print</span><span class="special">();</span>
<span class="keyword">int</span> <span class="identifier">num</span> <span class="special">=</span> <span class="identifier">count_leaves</span><span class="special">(</span><span class="identifier">expr1</span><span class="special">);</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">num</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="identifier">num</span> <span class="special">=</span> <span class="identifier">count_leaves</span><span class="special">(</span><span class="identifier">b</span> <span class="special">+</span> <span class="number">3</span> <span class="special">*</span> <span class="identifier">c</span><span class="special">);</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">num</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="identifier">num</span> <span class="special">=</span> <span class="identifier">count_leaves</span><span class="special">(</span><span class="identifier">b</span> <span class="special">+</span> <span class="identifier">c</span> <span class="special">*</span> <span class="identifier">d</span><span class="special">);</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">num</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="boost_yap.manual.examples.vector"></a><a class="link" href="manual.html#boost_yap.manual.examples.vector" title="Vector">Vector</a>
</h4></div></div></div>
<p>
So far we've only seen examples with custom terminals that own the values
in the expressions we operate on. What happens when you've got types that
you want to operate on, non-intrusively? Here's how you might do it with
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;&gt;</span></code>s:
</p>
<p>
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">yap</span><span class="special">/</span><span class="identifier">yap</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">vector</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">take_nth</span>
<span class="special">{</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_tag</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">&gt;,</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">vec</span><span class="special">)</span>
<span class="special">{</span> <span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_terminal</span><span class="special">(</span><span class="identifier">vec</span><span class="special">[</span><span class="identifier">n</span><span class="special">]);</span> <span class="special">}</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">n</span><span class="special">;</span>
<span class="special">};</span>
<span class="comment">// A stateful transform that records whether all the std::vector&lt;&gt; terminals</span>
<span class="comment">// it has seen are equal to the given size.</span>
<span class="keyword">struct</span> <span class="identifier">equal_sizes_impl</span>
<span class="special">{</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_tag</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">&gt;,</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">vec</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">expr_size</span> <span class="special">=</span> <span class="identifier">vec</span><span class="special">.</span><span class="identifier">size</span><span class="special">();</span>
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">expr_size</span> <span class="special">!=</span> <span class="identifier">size</span><span class="special">)</span>
<span class="identifier">value</span> <span class="special">=</span> <span class="keyword">false</span><span class="special">;</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="keyword">const</span> <span class="identifier">size</span><span class="special">;</span>
<span class="keyword">bool</span> <span class="identifier">value</span><span class="special">;</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Expr</span><span class="special">&gt;</span>
<span class="keyword">bool</span> <span class="identifier">equal_sizes</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">size</span><span class="special">,</span> <span class="identifier">Expr</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">expr</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">equal_sizes_impl</span> <span class="identifier">impl</span><span class="special">{</span><span class="identifier">size</span><span class="special">,</span> <span class="keyword">true</span><span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">as_expr</span><span class="special">(</span><span class="identifier">expr</span><span class="special">),</span> <span class="identifier">impl</span><span class="special">);</span>
<span class="keyword">return</span> <span class="identifier">impl</span><span class="special">.</span><span class="identifier">value</span><span class="special">;</span>
<span class="special">}</span>
<span class="comment">// Assigns some expression e to the given vector by evaluating e elementwise,</span>
<span class="comment">// to avoid temporaries and allocations.</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Expr</span><span class="special">&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span> <span class="identifier">assign</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span> <span class="identifier">vec</span><span class="special">,</span> <span class="identifier">Expr</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">e</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">decltype</span><span class="special">(</span><span class="keyword">auto</span><span class="special">)</span> <span class="identifier">expr</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">as_expr</span><span class="special">(</span><span class="identifier">e</span><span class="special">);</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">equal_sizes</span><span class="special">(</span><span class="identifier">vec</span><span class="special">.</span><span class="identifier">size</span><span class="special">(),</span> <span class="identifier">expr</span><span class="special">));</span>
<span class="keyword">for</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">,</span> <span class="identifier">size</span> <span class="special">=</span> <span class="identifier">vec</span><span class="special">.</span><span class="identifier">size</span><span class="special">();</span> <span class="identifier">i</span> <span class="special">&lt;</span> <span class="identifier">size</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">)</span> <span class="special">{</span>
<span class="identifier">vec</span><span class="special">[</span><span class="identifier">i</span><span class="special">]</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">evaluate</span><span class="special">(</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">as_expr</span><span class="special">(</span><span class="identifier">expr</span><span class="special">),</span> <span class="identifier">take_nth</span><span class="special">{</span><span class="identifier">i</span><span class="special">}));</span>
<span class="special">}</span>
<span class="keyword">return</span> <span class="identifier">vec</span><span class="special">;</span>
<span class="special">}</span>
<span class="comment">// As assign() above, just using +=.</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Expr</span><span class="special">&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">+=</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span> <span class="identifier">vec</span><span class="special">,</span> <span class="identifier">Expr</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">e</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">decltype</span><span class="special">(</span><span class="keyword">auto</span><span class="special">)</span> <span class="identifier">expr</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">as_expr</span><span class="special">(</span><span class="identifier">e</span><span class="special">);</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">equal_sizes</span><span class="special">(</span><span class="identifier">vec</span><span class="special">.</span><span class="identifier">size</span><span class="special">(),</span> <span class="identifier">expr</span><span class="special">));</span>
<span class="keyword">for</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">,</span> <span class="identifier">size</span> <span class="special">=</span> <span class="identifier">vec</span><span class="special">.</span><span class="identifier">size</span><span class="special">();</span> <span class="identifier">i</span> <span class="special">&lt;</span> <span class="identifier">size</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">)</span> <span class="special">{</span>
<span class="identifier">vec</span><span class="special">[</span><span class="identifier">i</span><span class="special">]</span> <span class="special">+=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">evaluate</span><span class="special">(</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">as_expr</span><span class="special">(</span><span class="identifier">expr</span><span class="special">),</span> <span class="identifier">take_nth</span><span class="special">{</span><span class="identifier">i</span><span class="special">}));</span>
<span class="special">}</span>
<span class="keyword">return</span> <span class="identifier">vec</span><span class="special">;</span>
<span class="special">}</span>
<span class="comment">// Define a type trait that identifies std::vectors.</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">is_vector</span> <span class="special">:</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">false_type</span> <span class="special">{};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">A</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">is_vector</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">A</span><span class="special">&gt;&gt;</span> <span class="special">:</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">true_type</span> <span class="special">{};</span>
<span class="comment">// Define all the expression-returning numeric operators we need. Each will</span>
<span class="comment">// accept any std::vector&lt;&gt; as any of its arguments, and then any value in the</span>
<span class="comment">// remaining argument, if any -- some of the operators below are unary.</span>
<span class="identifier">BOOST_YAP_USER_UDT_UNARY_OPERATOR</span><span class="special">(</span><span class="identifier">negate</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_vector</span><span class="special">);</span> <span class="comment">// -</span>
<span class="identifier">BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">multiplies</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_vector</span><span class="special">);</span> <span class="comment">// *</span>
<span class="identifier">BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">divides</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_vector</span><span class="special">);</span> <span class="comment">// /</span>
<span class="identifier">BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">modulus</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_vector</span><span class="special">);</span> <span class="comment">// %</span>
<span class="identifier">BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">plus</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_vector</span><span class="special">);</span> <span class="comment">// +</span>
<span class="identifier">BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">minus</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_vector</span><span class="special">);</span> <span class="comment">// -</span>
<span class="identifier">BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">less</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_vector</span><span class="special">);</span> <span class="comment">// &lt;</span>
<span class="identifier">BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">greater</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_vector</span><span class="special">);</span> <span class="comment">// &gt;</span>
<span class="identifier">BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">less_equal</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_vector</span><span class="special">);</span> <span class="comment">// &lt;=</span>
<span class="identifier">BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">greater_equal</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_vector</span><span class="special">);</span> <span class="comment">// &gt;=</span>
<span class="identifier">BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">equal_to</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_vector</span><span class="special">);</span> <span class="comment">// ==</span>
<span class="identifier">BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">not_equal_to</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_vector</span><span class="special">);</span> <span class="comment">// !=</span>
<span class="identifier">BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">logical_or</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_vector</span><span class="special">);</span> <span class="comment">// ||</span>
<span class="identifier">BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">logical_and</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_vector</span><span class="special">);</span> <span class="comment">// &amp;&amp;</span>
<span class="identifier">BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">bitwise_and</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_vector</span><span class="special">);</span> <span class="comment">// &amp;</span>
<span class="identifier">BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">bitwise_or</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_vector</span><span class="special">);</span> <span class="comment">// |</span>
<span class="identifier">BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">bitwise_xor</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_vector</span><span class="special">);</span> <span class="comment">// ^</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span>
<span class="special">{</span>
<span class="keyword">int</span> <span class="identifier">i</span><span class="special">;</span>
<span class="keyword">int</span> <span class="keyword">const</span> <span class="identifier">n</span> <span class="special">=</span> <span class="number">10</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">a</span><span class="special">,</span><span class="identifier">b</span><span class="special">,</span><span class="identifier">c</span><span class="special">,</span><span class="identifier">d</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;</span> <span class="identifier">e</span><span class="special">(</span><span class="identifier">n</span><span class="special">);</span>
<span class="keyword">for</span> <span class="special">(</span><span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special">&lt;</span> <span class="identifier">n</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">a</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">i</span><span class="special">);</span>
<span class="identifier">b</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="number">2</span><span class="special">*</span><span class="identifier">i</span><span class="special">);</span>
<span class="identifier">c</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="number">3</span><span class="special">*</span><span class="identifier">i</span><span class="special">);</span>
<span class="identifier">d</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">i</span><span class="special">);</span>
<span class="special">}</span>
<span class="comment">// After this point, no allocations occur.</span>
<span class="identifier">assign</span><span class="special">(</span><span class="identifier">b</span><span class="special">,</span> <span class="number">2</span><span class="special">);</span>
<span class="identifier">assign</span><span class="special">(</span><span class="identifier">d</span><span class="special">,</span> <span class="identifier">a</span> <span class="special">+</span> <span class="identifier">b</span> <span class="special">*</span> <span class="identifier">c</span><span class="special">);</span>
<span class="identifier">a</span> <span class="special">+=</span> <span class="identifier">if_else</span><span class="special">(</span><span class="identifier">d</span> <span class="special">&lt;</span> <span class="number">30</span><span class="special">,</span> <span class="identifier">b</span><span class="special">,</span> <span class="identifier">c</span><span class="special">);</span>
<span class="identifier">assign</span><span class="special">(</span><span class="identifier">e</span><span class="special">,</span> <span class="identifier">c</span><span class="special">);</span>
<span class="identifier">e</span> <span class="special">+=</span> <span class="identifier">e</span> <span class="special">-</span> <span class="number">4</span> <span class="special">/</span> <span class="special">(</span><span class="identifier">c</span> <span class="special">+</span> <span class="number">1</span><span class="special">);</span>
<span class="keyword">for</span> <span class="special">(</span><span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special">&lt;</span> <span class="identifier">n</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span>
<span class="special">&lt;&lt;</span> <span class="string">" a("</span> <span class="special">&lt;&lt;</span> <span class="identifier">i</span> <span class="special">&lt;&lt;</span> <span class="string">") = "</span> <span class="special">&lt;&lt;</span> <span class="identifier">a</span><span class="special">[</span><span class="identifier">i</span><span class="special">]</span>
<span class="special">&lt;&lt;</span> <span class="string">" b("</span> <span class="special">&lt;&lt;</span> <span class="identifier">i</span> <span class="special">&lt;&lt;</span> <span class="string">") = "</span> <span class="special">&lt;&lt;</span> <span class="identifier">b</span><span class="special">[</span><span class="identifier">i</span><span class="special">]</span>
<span class="special">&lt;&lt;</span> <span class="string">" c("</span> <span class="special">&lt;&lt;</span> <span class="identifier">i</span> <span class="special">&lt;&lt;</span> <span class="string">") = "</span> <span class="special">&lt;&lt;</span> <span class="identifier">c</span><span class="special">[</span><span class="identifier">i</span><span class="special">]</span>
<span class="special">&lt;&lt;</span> <span class="string">" d("</span> <span class="special">&lt;&lt;</span> <span class="identifier">i</span> <span class="special">&lt;&lt;</span> <span class="string">") = "</span> <span class="special">&lt;&lt;</span> <span class="identifier">d</span><span class="special">[</span><span class="identifier">i</span><span class="special">]</span>
<span class="special">&lt;&lt;</span> <span class="string">" e("</span> <span class="special">&lt;&lt;</span> <span class="identifier">i</span> <span class="special">&lt;&lt;</span> <span class="string">") = "</span> <span class="special">&lt;&lt;</span> <span class="identifier">e</span><span class="special">[</span><span class="identifier">i</span><span class="special">]</span>
<span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="special">}</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
</p>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../doc/src/images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td align="left" valign="top"><p>
Though this example only provides overloads for the operations we want
to define over <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;&gt;</span></code>s,
the result of each of those operations is an <code class="computeroutput"><a class="link" href="../boost/yap/expression.html" title="Struct template expression">expression&lt;&gt;</a></code>,
which uses <span class="bold"><strong>all</strong></span> the operator overloads.
If we wanted to restrict the operations on the results too, we could
have defined a custom expression template with the desired operations,
and used that instead of <code class="computeroutput"><a class="link" href="../boost/yap/expression.html" title="Struct template expression">expression&lt;&gt;</a></code>
in the operator macros.
</p></td></tr>
</table></div>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="boost_yap.manual.examples.mixed"></a><a class="link" href="manual.html#boost_yap.manual.examples.mixed" title="Mixed">Mixed</a>
</h4></div></div></div>
<p>
This is a lot like the previous Vector example, except that it operates
on <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;&gt;</span></code>s
and <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special">&lt;&gt;</span></code>s
in the same expression.
</p>
<p>
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">yap</span><span class="special">/</span><span class="identifier">yap</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">complex</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">list</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">vector</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="comment">// This wrapper makes the pattern matching in transforms below (like deref and</span>
<span class="comment">// incr) a lot easier to write.</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Iter</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">iter_wrapper</span>
<span class="special">{</span>
<span class="identifier">Iter</span> <span class="identifier">it</span><span class="special">;</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Iter</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="identifier">make_iter_wrapper</span> <span class="special">(</span><span class="identifier">Iter</span> <span class="identifier">it</span><span class="special">)</span>
<span class="special">{</span> <span class="keyword">return</span> <span class="identifier">iter_wrapper</span><span class="special">&lt;</span><span class="identifier">Iter</span><span class="special">&gt;{</span><span class="identifier">it</span><span class="special">};</span> <span class="special">}</span>
<span class="comment">// A container -&gt; wrapped-begin transform.</span>
<span class="keyword">struct</span> <span class="identifier">begin</span>
<span class="special">{</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Cont</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_tag</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">&gt;,</span>
<span class="identifier">Cont</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">cont</span><span class="special">)</span>
<span class="special">-&gt;</span> <span class="keyword">decltype</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_terminal</span><span class="special">(</span><span class="identifier">make_iter_wrapper</span><span class="special">(</span><span class="identifier">cont</span><span class="special">.</span><span class="identifier">begin</span><span class="special">())))</span>
<span class="special">{</span> <span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_terminal</span><span class="special">(</span><span class="identifier">make_iter_wrapper</span><span class="special">(</span><span class="identifier">cont</span><span class="special">.</span><span class="identifier">begin</span><span class="special">()));</span> <span class="special">}</span>
<span class="special">};</span>
<span class="comment">// A wrapped-iterator -&gt; dereferenced value transform.</span>
<span class="keyword">struct</span> <span class="identifier">deref</span>
<span class="special">{</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Iter</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_tag</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">&gt;,</span>
<span class="identifier">iter_wrapper</span><span class="special">&lt;</span><span class="identifier">Iter</span><span class="special">&gt;</span> <span class="identifier">wrapper</span><span class="special">)</span>
<span class="special">-&gt;</span> <span class="keyword">decltype</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_terminal</span><span class="special">(*</span><span class="identifier">wrapper</span><span class="special">.</span><span class="identifier">it</span><span class="special">))</span>
<span class="special">{</span> <span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_terminal</span><span class="special">(*</span><span class="identifier">wrapper</span><span class="special">.</span><span class="identifier">it</span><span class="special">);</span> <span class="special">}</span>
<span class="special">};</span>
<span class="comment">// A wrapped-iterator increment transform, using side effects.</span>
<span class="keyword">struct</span> <span class="identifier">incr</span>
<span class="special">{</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Iter</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_tag</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">&gt;,</span>
<span class="identifier">iter_wrapper</span><span class="special">&lt;</span><span class="identifier">Iter</span><span class="special">&gt;</span> <span class="special">&amp;</span> <span class="identifier">wrapper</span><span class="special">)</span>
<span class="special">-&gt;</span> <span class="keyword">decltype</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_terminal</span><span class="special">(</span><span class="identifier">wrapper</span><span class="special">.</span><span class="identifier">it</span><span class="special">))</span>
<span class="special">{</span>
<span class="special">++</span><span class="identifier">wrapper</span><span class="special">.</span><span class="identifier">it</span><span class="special">;</span>
<span class="comment">// Since this transform is valuable for its side effects, and thus the</span>
<span class="comment">// result of the transform is ignored, we could return anything here.</span>
<span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_terminal</span><span class="special">(</span><span class="identifier">wrapper</span><span class="special">.</span><span class="identifier">it</span><span class="special">);</span>
<span class="special">}</span>
<span class="special">};</span>
<span class="comment">// The implementation of elementwise evaluation of expressions of sequences;</span>
<span class="comment">// all the later operations use this one.</span>
<span class="keyword">template</span> <span class="special">&lt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span><span class="special">,</span> <span class="keyword">class</span><span class="special">&gt;</span> <span class="keyword">class</span> <span class="identifier">Cont</span><span class="special">,</span>
<span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span>
<span class="keyword">typename</span> <span class="identifier">A</span><span class="special">,</span>
<span class="keyword">typename</span> <span class="identifier">Expr</span><span class="special">,</span>
<span class="keyword">typename</span> <span class="identifier">Op</span>
<span class="special">&gt;</span>
<span class="identifier">Cont</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">A</span><span class="special">&gt;</span> <span class="special">&amp;</span> <span class="identifier">op_assign</span> <span class="special">(</span><span class="identifier">Cont</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">A</span><span class="special">&gt;</span> <span class="special">&amp;</span> <span class="identifier">cont</span><span class="special">,</span> <span class="identifier">Expr</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">e</span><span class="special">,</span> <span class="identifier">Op</span> <span class="special">&amp;&amp;</span> <span class="identifier">op</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">decltype</span><span class="special">(</span><span class="keyword">auto</span><span class="special">)</span> <span class="identifier">expr</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">as_expr</span><span class="special">(</span><span class="identifier">e</span><span class="special">);</span>
<span class="comment">// Transform the expression of sequences into an expression of</span>
<span class="comment">// begin-iterators.</span>
<span class="keyword">auto</span> <span class="identifier">expr2</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">as_expr</span><span class="special">(</span><span class="identifier">expr</span><span class="special">),</span> <span class="identifier">begin</span><span class="special">{});</span>
<span class="keyword">for</span> <span class="special">(</span><span class="keyword">auto</span> <span class="special">&amp;&amp;</span> <span class="identifier">x</span> <span class="special">:</span> <span class="identifier">cont</span><span class="special">)</span> <span class="special">{</span>
<span class="comment">// Transform the expression of iterators into an expression of</span>
<span class="comment">// pointed-to-values, evaluate the resulting expression, and call op()</span>
<span class="comment">// with the result of the evaluation.</span>
<span class="identifier">op</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">evaluate</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">expr2</span><span class="special">,</span> <span class="identifier">deref</span><span class="special">{})));</span>
<span class="comment">// Transform the expression of iterators into an ignored value; as a</span>
<span class="comment">// side effect, increment the iterators in the expression.</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">expr2</span><span class="special">,</span> <span class="identifier">incr</span><span class="special">{});</span>
<span class="special">}</span>
<span class="keyword">return</span> <span class="identifier">cont</span><span class="special">;</span>
<span class="special">}</span>
<span class="keyword">template</span> <span class="special">&lt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span><span class="special">,</span> <span class="keyword">class</span><span class="special">&gt;</span> <span class="keyword">class</span> <span class="identifier">Cont</span><span class="special">,</span>
<span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span>
<span class="keyword">typename</span> <span class="identifier">A</span><span class="special">,</span>
<span class="keyword">typename</span> <span class="identifier">Expr</span>
<span class="special">&gt;</span>
<span class="identifier">Cont</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">A</span><span class="special">&gt;</span> <span class="special">&amp;</span> <span class="identifier">assign</span> <span class="special">(</span><span class="identifier">Cont</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">A</span><span class="special">&gt;</span> <span class="special">&amp;</span> <span class="identifier">cont</span><span class="special">,</span> <span class="identifier">Expr</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">expr</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">op_assign</span><span class="special">(</span><span class="identifier">cont</span><span class="special">,</span> <span class="identifier">expr</span><span class="special">,</span> <span class="special">[](</span><span class="keyword">auto</span> <span class="special">&amp;</span> <span class="identifier">cont_value</span><span class="special">,</span> <span class="keyword">auto</span> <span class="special">&amp;&amp;</span> <span class="identifier">expr_value</span><span class="special">)</span> <span class="special">{</span>
<span class="identifier">cont_value</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special">&lt;</span><span class="keyword">decltype</span><span class="special">(</span><span class="identifier">expr_value</span><span class="special">)&gt;(</span><span class="identifier">expr_value</span><span class="special">);</span>
<span class="special">});</span>
<span class="special">}</span>
<span class="keyword">template</span> <span class="special">&lt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span><span class="special">,</span> <span class="keyword">class</span><span class="special">&gt;</span> <span class="keyword">class</span> <span class="identifier">Cont</span><span class="special">,</span>
<span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span>
<span class="keyword">typename</span> <span class="identifier">A</span><span class="special">,</span>
<span class="keyword">typename</span> <span class="identifier">Expr</span>
<span class="special">&gt;</span>
<span class="identifier">Cont</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">A</span><span class="special">&gt;</span> <span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">+=</span> <span class="special">(</span><span class="identifier">Cont</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">A</span><span class="special">&gt;</span> <span class="special">&amp;</span> <span class="identifier">cont</span><span class="special">,</span> <span class="identifier">Expr</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">expr</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">op_assign</span><span class="special">(</span><span class="identifier">cont</span><span class="special">,</span> <span class="identifier">expr</span><span class="special">,</span> <span class="special">[](</span><span class="keyword">auto</span> <span class="special">&amp;</span> <span class="identifier">cont_value</span><span class="special">,</span> <span class="keyword">auto</span> <span class="special">&amp;&amp;</span> <span class="identifier">expr_value</span><span class="special">)</span> <span class="special">{</span>
<span class="identifier">cont_value</span> <span class="special">+=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special">&lt;</span><span class="keyword">decltype</span><span class="special">(</span><span class="identifier">expr_value</span><span class="special">)&gt;(</span><span class="identifier">expr_value</span><span class="special">);</span>
<span class="special">});</span>
<span class="special">}</span>
<span class="keyword">template</span> <span class="special">&lt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span><span class="special">,</span> <span class="keyword">class</span><span class="special">&gt;</span> <span class="keyword">class</span> <span class="identifier">Cont</span><span class="special">,</span>
<span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span>
<span class="keyword">typename</span> <span class="identifier">A</span><span class="special">,</span>
<span class="keyword">typename</span> <span class="identifier">Expr</span>
<span class="special">&gt;</span>
<span class="identifier">Cont</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">A</span><span class="special">&gt;</span> <span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">-=</span> <span class="special">(</span><span class="identifier">Cont</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">A</span><span class="special">&gt;</span> <span class="special">&amp;</span> <span class="identifier">cont</span><span class="special">,</span> <span class="identifier">Expr</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">expr</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">op_assign</span><span class="special">(</span><span class="identifier">cont</span><span class="special">,</span> <span class="identifier">expr</span><span class="special">,</span> <span class="special">[](</span><span class="keyword">auto</span> <span class="special">&amp;</span> <span class="identifier">cont_value</span><span class="special">,</span> <span class="keyword">auto</span> <span class="special">&amp;&amp;</span> <span class="identifier">expr_value</span><span class="special">)</span> <span class="special">{</span>
<span class="identifier">cont_value</span> <span class="special">-=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special">&lt;</span><span class="keyword">decltype</span><span class="special">(</span><span class="identifier">expr_value</span><span class="special">)&gt;(</span><span class="identifier">expr_value</span><span class="special">);</span>
<span class="special">});</span>
<span class="special">}</span>
<span class="comment">// A type trait that identifies std::vectors and std::lists.</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">is_mixed</span> <span class="special">:</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">false_type</span> <span class="special">{};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">A</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">is_mixed</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">A</span><span class="special">&gt;&gt;</span> <span class="special">:</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">true_type</span> <span class="special">{};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">A</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">is_mixed</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">A</span><span class="special">&gt;&gt;</span> <span class="special">:</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">true_type</span> <span class="special">{};</span>
<span class="comment">// Define expression-producing operators over std::vectors and std::lists.</span>
<span class="identifier">BOOST_YAP_USER_UDT_UNARY_OPERATOR</span><span class="special">(</span><span class="identifier">negate</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_mixed</span><span class="special">);</span> <span class="comment">// -</span>
<span class="identifier">BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">multiplies</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_mixed</span><span class="special">);</span> <span class="comment">// *</span>
<span class="identifier">BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">divides</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_mixed</span><span class="special">);</span> <span class="comment">// /</span>
<span class="identifier">BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">modulus</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_mixed</span><span class="special">);</span> <span class="comment">// %</span>
<span class="identifier">BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">plus</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_mixed</span><span class="special">);</span> <span class="comment">// +</span>
<span class="identifier">BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">minus</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_mixed</span><span class="special">);</span> <span class="comment">// -</span>
<span class="identifier">BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">less</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_mixed</span><span class="special">);</span> <span class="comment">// &lt;</span>
<span class="identifier">BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">greater</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_mixed</span><span class="special">);</span> <span class="comment">// &gt;</span>
<span class="identifier">BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">less_equal</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_mixed</span><span class="special">);</span> <span class="comment">// &lt;=</span>
<span class="identifier">BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">greater_equal</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_mixed</span><span class="special">);</span> <span class="comment">// &gt;=</span>
<span class="identifier">BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">equal_to</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_mixed</span><span class="special">);</span> <span class="comment">// ==</span>
<span class="identifier">BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">not_equal_to</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_mixed</span><span class="special">);</span> <span class="comment">// !=</span>
<span class="identifier">BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">logical_or</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_mixed</span><span class="special">);</span> <span class="comment">// ||</span>
<span class="identifier">BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">logical_and</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_mixed</span><span class="special">);</span> <span class="comment">// &amp;&amp;</span>
<span class="identifier">BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">bitwise_and</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_mixed</span><span class="special">);</span> <span class="comment">// &amp;</span>
<span class="identifier">BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">bitwise_or</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_mixed</span><span class="special">);</span> <span class="comment">// |</span>
<span class="identifier">BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">bitwise_xor</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">,</span> <span class="identifier">is_mixed</span><span class="special">);</span> <span class="comment">// ^</span>
<span class="comment">// Define a type that can resolve to any overload of std::sin().</span>
<span class="keyword">struct</span> <span class="identifier">sin_t</span>
<span class="special">{</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="identifier">T</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">T</span> <span class="identifier">x</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">sin</span><span class="special">(</span><span class="identifier">x</span><span class="special">);</span>
<span class="special">}</span>
<span class="special">};</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span>
<span class="special">{</span>
<span class="keyword">int</span> <span class="identifier">n</span> <span class="special">=</span> <span class="number">10</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">a</span><span class="special">,</span><span class="identifier">b</span><span class="special">,</span><span class="identifier">c</span><span class="special">,</span><span class="identifier">d</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;</span> <span class="identifier">e</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">complex</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;&gt;</span> <span class="identifier">f</span><span class="special">;</span>
<span class="keyword">int</span> <span class="identifier">i</span><span class="special">;</span>
<span class="keyword">for</span><span class="special">(</span><span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span><span class="identifier">i</span> <span class="special">&lt;</span> <span class="identifier">n</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">a</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">i</span><span class="special">);</span>
<span class="identifier">b</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="number">2</span><span class="special">*</span><span class="identifier">i</span><span class="special">);</span>
<span class="identifier">c</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="number">3</span><span class="special">*</span><span class="identifier">i</span><span class="special">);</span>
<span class="identifier">d</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">i</span><span class="special">);</span>
<span class="identifier">e</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="number">0.0</span><span class="special">);</span>
<span class="identifier">f</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">complex</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;(</span><span class="number">1.0</span><span class="special">,</span> <span class="number">1.0</span><span class="special">));</span>
<span class="special">}</span>
<span class="identifier">assign</span><span class="special">(</span><span class="identifier">b</span><span class="special">,</span> <span class="number">2</span><span class="special">);</span>
<span class="identifier">assign</span><span class="special">(</span><span class="identifier">d</span><span class="special">,</span> <span class="identifier">a</span> <span class="special">+</span> <span class="identifier">b</span> <span class="special">*</span> <span class="identifier">c</span><span class="special">);</span>
<span class="identifier">a</span> <span class="special">+=</span> <span class="identifier">if_else</span><span class="special">(</span><span class="identifier">d</span> <span class="special">&lt;</span> <span class="number">30</span><span class="special">,</span> <span class="identifier">b</span><span class="special">,</span> <span class="identifier">c</span><span class="special">);</span>
<span class="identifier">assign</span><span class="special">(</span><span class="identifier">e</span><span class="special">,</span> <span class="identifier">c</span><span class="special">);</span>
<span class="identifier">e</span> <span class="special">+=</span> <span class="identifier">e</span> <span class="special">-</span> <span class="number">4</span> <span class="special">/</span> <span class="special">(</span><span class="identifier">c</span> <span class="special">+</span> <span class="number">1</span><span class="special">);</span>
<span class="keyword">auto</span> <span class="identifier">sin</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_terminal</span><span class="special">(</span><span class="identifier">sin_t</span><span class="special">{});</span>
<span class="identifier">f</span> <span class="special">-=</span> <span class="identifier">sin</span><span class="special">(</span><span class="number">0.1</span> <span class="special">*</span> <span class="identifier">e</span> <span class="special">*</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">complex</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;(</span><span class="number">0.2</span><span class="special">,</span> <span class="number">1.2</span><span class="special">));</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;::</span><span class="identifier">const_iterator</span> <span class="identifier">ei</span> <span class="special">=</span> <span class="identifier">e</span><span class="special">.</span><span class="identifier">begin</span><span class="special">();</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">complex</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;&gt;::</span><span class="identifier">const_iterator</span> <span class="identifier">fi</span> <span class="special">=</span> <span class="identifier">f</span><span class="special">.</span><span class="identifier">begin</span><span class="special">();</span>
<span class="keyword">for</span> <span class="special">(</span><span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special">&lt;</span> <span class="identifier">n</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span>
<span class="special">&lt;&lt;</span> <span class="string">"a("</span> <span class="special">&lt;&lt;</span> <span class="identifier">i</span> <span class="special">&lt;&lt;</span> <span class="string">") = "</span> <span class="special">&lt;&lt;</span> <span class="identifier">a</span><span class="special">[</span><span class="identifier">i</span><span class="special">]</span>
<span class="special">&lt;&lt;</span> <span class="string">" b("</span> <span class="special">&lt;&lt;</span> <span class="identifier">i</span> <span class="special">&lt;&lt;</span> <span class="string">") = "</span> <span class="special">&lt;&lt;</span> <span class="identifier">b</span><span class="special">[</span><span class="identifier">i</span><span class="special">]</span>
<span class="special">&lt;&lt;</span> <span class="string">" c("</span> <span class="special">&lt;&lt;</span> <span class="identifier">i</span> <span class="special">&lt;&lt;</span> <span class="string">") = "</span> <span class="special">&lt;&lt;</span> <span class="identifier">c</span><span class="special">[</span><span class="identifier">i</span><span class="special">]</span>
<span class="special">&lt;&lt;</span> <span class="string">" d("</span> <span class="special">&lt;&lt;</span> <span class="identifier">i</span> <span class="special">&lt;&lt;</span> <span class="string">") = "</span> <span class="special">&lt;&lt;</span> <span class="identifier">d</span><span class="special">[</span><span class="identifier">i</span><span class="special">]</span>
<span class="special">&lt;&lt;</span> <span class="string">" e("</span> <span class="special">&lt;&lt;</span> <span class="identifier">i</span> <span class="special">&lt;&lt;</span> <span class="string">") = "</span> <span class="special">&lt;&lt;</span> <span class="special">*</span><span class="identifier">ei</span><span class="special">++</span>
<span class="special">&lt;&lt;</span> <span class="string">" f("</span> <span class="special">&lt;&lt;</span> <span class="identifier">i</span> <span class="special">&lt;&lt;</span> <span class="string">") = "</span> <span class="special">&lt;&lt;</span> <span class="special">*</span><span class="identifier">fi</span><span class="special">++</span>
<span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="special">}</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="boost_yap.manual.examples.map_assign"></a><a class="link" href="manual.html#boost_yap.manual.examples.map_assign" title="Map Assign">Map Assign</a>
</h4></div></div></div>
<p>
An implementation of <code class="computeroutput"><span class="identifier">map_list_of</span><span class="special">()</span></code> from Boost.Assign using Boost.YAP.
</p>
<p>
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">yap</span><span class="special">/</span><span class="identifier">algorithm</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">map</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="comment">// This transform applies all the call-subexpressions in a map_list_of</span>
<span class="comment">// expression (a nested chain of call operations) as a side effect; the</span>
<span class="comment">// expression returned by the transform is ignored.</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Key</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Value</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Allocator</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">map_list_of_transform</span>
<span class="special">{</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Fn</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Key2</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Value2</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_tag</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">call</span><span class="special">&gt;,</span>
<span class="identifier">Fn</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">fn</span><span class="special">,</span> <span class="identifier">Key2</span> <span class="special">&amp;&amp;</span> <span class="identifier">key</span><span class="special">,</span> <span class="identifier">Value2</span> <span class="special">&amp;&amp;</span> <span class="identifier">value</span><span class="special">)</span>
<span class="special">{</span>
<span class="comment">// Recurse into the function subexpression. Remember, transform()</span>
<span class="comment">// walks the nodes in an expression tree looking for matches. Once it</span>
<span class="comment">// finds a match, it is finished with that matching subtree. So</span>
<span class="comment">// without this recursive call, only the top-level call expression is</span>
<span class="comment">// matched by transform().</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">as_expr</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">minimal_expr</span><span class="special">&gt;(</span><span class="identifier">fn</span><span class="special">),</span> <span class="special">*</span><span class="keyword">this</span><span class="special">);</span>
<span class="identifier">map</span><span class="special">.</span><span class="identifier">emplace</span><span class="special">(</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special">&lt;</span><span class="identifier">Key2</span> <span class="special">&amp;&amp;&gt;(</span><span class="identifier">key</span><span class="special">),</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special">&lt;</span><span class="identifier">Value2</span> <span class="special">&amp;&amp;&gt;(</span><span class="identifier">value</span><span class="special">)</span>
<span class="special">);</span>
<span class="comment">// All we care about are the side effects of this transform, so we can</span>
<span class="comment">// return any old thing here.</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special">&lt;</span><span class="identifier">Key</span><span class="special">,</span> <span class="identifier">Value</span><span class="special">,</span> <span class="identifier">Allocator</span><span class="special">&gt;</span> <span class="special">&amp;</span> <span class="identifier">map</span><span class="special">;</span>
<span class="special">};</span>
<span class="comment">// A custom expression template type for map_list_of expressions. We only</span>
<span class="comment">// need support for the call operator and an implicit conversion to a</span>
<span class="comment">// std::map.</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">Kind</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">map_list_of_expr</span>
<span class="special">{</span>
<span class="keyword">static</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="keyword">const</span> <span class="identifier">kind</span> <span class="special">=</span> <span class="identifier">Kind</span><span class="special">;</span>
<span class="identifier">Tuple</span> <span class="identifier">elements</span><span class="special">;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Key</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Value</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Allocator</span><span class="special">&gt;</span>
<span class="keyword">operator</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special">&lt;</span><span class="identifier">Key</span><span class="special">,</span> <span class="identifier">Value</span><span class="special">,</span> <span class="identifier">Allocator</span><span class="special">&gt;</span> <span class="special">()</span> <span class="keyword">const</span>
<span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special">&lt;</span><span class="identifier">Key</span><span class="special">,</span> <span class="identifier">Value</span><span class="special">,</span> <span class="identifier">Allocator</span><span class="special">&gt;</span> <span class="identifier">retval</span><span class="special">;</span>
<span class="identifier">map_list_of_transform</span><span class="special">&lt;</span><span class="identifier">Key</span><span class="special">,</span> <span class="identifier">Value</span><span class="special">,</span> <span class="identifier">Allocator</span><span class="special">&gt;</span> <span class="identifier">transform</span><span class="special">{</span><span class="identifier">retval</span><span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(*</span><span class="keyword">this</span><span class="special">,</span> <span class="identifier">transform</span><span class="special">);</span>
<span class="keyword">return</span> <span class="identifier">retval</span><span class="special">;</span>
<span class="special">}</span>
<span class="identifier">BOOST_YAP_USER_CALL_OPERATOR_N</span><span class="special">(::</span><span class="identifier">map_list_of_expr</span><span class="special">,</span> <span class="number">2</span><span class="special">)</span>
<span class="special">};</span>
<span class="comment">// A tag type for creating the map_list_of function terminal.</span>
<span class="keyword">struct</span> <span class="identifier">map_list_of_tag</span> <span class="special">{};</span>
<span class="keyword">auto</span> <span class="identifier">map_list_of</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_terminal</span><span class="special">&lt;</span><span class="identifier">map_list_of_expr</span><span class="special">&gt;(</span><span class="identifier">map_list_of_tag</span><span class="special">{});</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span>
<span class="special">{</span>
<span class="comment">// Initialize a map:</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span> <span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">op</span> <span class="special">=</span>
<span class="identifier">map_list_of</span>
<span class="special">(</span><span class="string">"&lt;"</span><span class="special">,</span> <span class="number">1</span><span class="special">)</span>
<span class="special">(</span><span class="string">"&lt;="</span><span class="special">,</span><span class="number">2</span><span class="special">)</span>
<span class="special">(</span><span class="string">"&gt;"</span><span class="special">,</span> <span class="number">3</span><span class="special">)</span>
<span class="special">(</span><span class="string">"&gt;="</span><span class="special">,</span><span class="number">4</span><span class="special">)</span>
<span class="special">(</span><span class="string">"="</span><span class="special">,</span> <span class="number">5</span><span class="special">)</span>
<span class="special">(</span><span class="string">"&lt;&gt;"</span><span class="special">,</span><span class="number">6</span><span class="special">)</span>
<span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"\"&lt;\" --&gt; "</span> <span class="special">&lt;&lt;</span> <span class="identifier">op</span><span class="special">[</span><span class="string">"&lt;"</span><span class="special">]</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"\"&lt;=\" --&gt; "</span> <span class="special">&lt;&lt;</span> <span class="identifier">op</span><span class="special">[</span><span class="string">"&lt;="</span><span class="special">]</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"\"&gt;\" --&gt; "</span> <span class="special">&lt;&lt;</span> <span class="identifier">op</span><span class="special">[</span><span class="string">"&gt;"</span><span class="special">]</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"\"&gt;=\" --&gt; "</span> <span class="special">&lt;&lt;</span> <span class="identifier">op</span><span class="special">[</span><span class="string">"&gt;="</span><span class="special">]</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"\"=\" --&gt; "</span> <span class="special">&lt;&lt;</span> <span class="identifier">op</span><span class="special">[</span><span class="string">"="</span><span class="special">]</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"\"&lt;&gt;\" --&gt; "</span> <span class="special">&lt;&lt;</span> <span class="identifier">op</span><span class="special">[</span><span class="string">"&lt;&gt;"</span><span class="special">]</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
</p>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../doc/src/images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td align="left" valign="top"><p>
<code class="computeroutput"><span class="identifier">map_list_of_expr</span></code> defines
a generic call operator that matches any call, including one with the
wrong number of arguments. This could be fixed by adding a <code class="computeroutput"><span class="keyword">static_assert</span><span class="special">()</span></code>
to the <code class="computeroutput"><span class="identifier">map_list_of_expr</span></code>
template, or by hand-writing the call operator with SFNIAE or concept
constraints.
</p></td></tr>
</table></div>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="boost_yap.manual.examples.future_group"></a><a class="link" href="manual.html#boost_yap.manual.examples.future_group" title="Future Group">Future Group</a>
</h4></div></div></div>
<p>
An implementation of Howard Hinnant's design for <span class="emphasis"><em>future groups</em></span>.
</p>
<p>
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">yap</span><span class="special">/</span><span class="identifier">algorithm</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">hana</span><span class="special">/</span><span class="identifier">concat</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="comment">// A custom expression template for future groups. It supports operators ||</span>
<span class="comment">// and &amp;&amp;.</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">Kind</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">future_expr</span>
<span class="special">{</span>
<span class="keyword">static</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="keyword">const</span> <span class="identifier">kind</span> <span class="special">=</span> <span class="identifier">Kind</span><span class="special">;</span>
<span class="identifier">future_expr</span> <span class="special">(</span><span class="identifier">Tuple</span> <span class="special">&amp;&amp;</span> <span class="identifier">tuple</span><span class="special">)</span> <span class="special">:</span>
<span class="identifier">elements</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special">&lt;</span><span class="identifier">Tuple</span> <span class="special">&amp;&amp;&gt;(</span><span class="identifier">tuple</span><span class="special">))</span>
<span class="special">{}</span>
<span class="identifier">Tuple</span> <span class="identifier">elements</span><span class="special">;</span>
<span class="comment">// Returns the transformed/flattened expression.</span>
<span class="keyword">auto</span> <span class="identifier">get</span> <span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
<span class="special">};</span>
<span class="identifier">BOOST_YAP_USER_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">logical_or</span><span class="special">,</span> <span class="identifier">future_expr</span><span class="special">,</span> <span class="identifier">future_expr</span><span class="special">)</span>
<span class="identifier">BOOST_YAP_USER_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">logical_and</span><span class="special">,</span> <span class="identifier">future_expr</span><span class="special">,</span> <span class="identifier">future_expr</span><span class="special">)</span>
<span class="comment">// A special-cased future terminal that matches the semantics from the</span>
<span class="comment">// original Proto example.</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">future</span> <span class="special">:</span>
<span class="identifier">future_expr</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;&gt;</span>
<span class="special">{</span>
<span class="identifier">future</span> <span class="special">(</span><span class="identifier">T</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">t</span> <span class="special">=</span> <span class="identifier">T</span><span class="special">())</span> <span class="special">:</span>
<span class="identifier">future_expr</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;&gt;</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;{</span><span class="identifier">t</span><span class="special">})</span>
<span class="special">{}</span>
<span class="identifier">T</span> <span class="identifier">get</span> <span class="special">()</span> <span class="keyword">const</span>
<span class="special">{</span> <span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">value</span><span class="special">(*</span><span class="keyword">this</span><span class="special">);</span> <span class="special">}</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">using</span> <span class="identifier">remove_cv_ref_t</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">remove_cv_t</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">remove_reference_t</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;&gt;;</span>
<span class="comment">// A transform that flattens future expressions into a tuple.</span>
<span class="keyword">struct</span> <span class="identifier">future_transform</span>
<span class="special">{</span>
<span class="comment">// Transform a terminal into its contained tuple.</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span>
<span class="identifier">future_expr</span><span class="special">&lt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span>
<span class="special">&gt;</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">term</span>
<span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">term</span><span class="special">.</span><span class="identifier">elements</span><span class="special">;</span>
<span class="special">}</span>
<span class="comment">// Transform left || right -&gt; transform(left).</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">U</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span>
<span class="identifier">future_expr</span><span class="special">&lt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">logical_or</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">U</span><span class="special">&gt;</span>
<span class="special">&gt;</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">or_expr</span>
<span class="special">)</span> <span class="special">{</span>
<span class="comment">// Recursively transform the left side, and return the result.</span>
<span class="comment">// Without the recursion, we might return a terminal expression here</span>
<span class="comment">// insead of a tuple.</span>
<span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">left</span><span class="special">(</span><span class="identifier">or_expr</span><span class="special">),</span> <span class="special">*</span><span class="keyword">this</span><span class="special">);</span>
<span class="special">}</span>
<span class="comment">// Transform left &amp;&amp; right -&gt; concat(transform(left), transform(right)).</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">U</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span>
<span class="identifier">future_expr</span><span class="special">&lt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">logical_and</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">U</span><span class="special">&gt;</span>
<span class="special">&gt;</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">and_expr</span>
<span class="special">)</span> <span class="special">{</span>
<span class="comment">// Recursively transform each side, then combine the resulting tuples</span>
<span class="comment">// into a single tuple result.</span>
<span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">concat</span><span class="special">(</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">left</span><span class="special">(</span><span class="identifier">and_expr</span><span class="special">),</span> <span class="special">*</span><span class="keyword">this</span><span class="special">),</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">right</span><span class="special">(</span><span class="identifier">and_expr</span><span class="special">),</span> <span class="special">*</span><span class="keyword">this</span><span class="special">)</span>
<span class="special">);</span>
<span class="special">}</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">Kind</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="identifier">future_expr</span><span class="special">&lt;</span><span class="identifier">Kind</span><span class="special">,</span> <span class="identifier">Tuple</span><span class="special">&gt;::</span><span class="identifier">get</span> <span class="special">()</span> <span class="keyword">const</span>
<span class="special">{</span> <span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(*</span><span class="keyword">this</span><span class="special">,</span> <span class="identifier">future_transform</span><span class="special">{});</span> <span class="special">}</span>
<span class="comment">// TEST CASES</span>
<span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{};</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{};</span>
<span class="keyword">struct</span> <span class="identifier">C</span> <span class="special">{};</span>
<span class="comment">// Called "vector" just so the code in main() will match the original Proto</span>
<span class="comment">// example.</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="special">...</span><span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">using</span> <span class="identifier">vector</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">...&gt;;</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span>
<span class="special">{</span>
<span class="identifier">future</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;</span> <span class="identifier">a</span><span class="special">;</span>
<span class="identifier">future</span><span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">future</span><span class="special">&lt;</span><span class="identifier">C</span><span class="special">&gt;</span> <span class="identifier">c</span><span class="special">;</span>
<span class="identifier">future</span><span class="special">&lt;</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">B</span><span class="special">&gt;</span> <span class="special">&gt;</span> <span class="identifier">ab</span><span class="special">;</span>
<span class="comment">// Verify that various future groups have the</span>
<span class="comment">// correct return types.</span>
<span class="identifier">A</span> <span class="identifier">t0</span> <span class="special">=</span> <span class="identifier">a</span><span class="special">.</span><span class="identifier">get</span><span class="special">();</span>
<span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">,</span> <span class="identifier">B</span><span class="special">,</span> <span class="identifier">C</span><span class="special">&gt;</span> <span class="identifier">t1</span> <span class="special">=</span> <span class="special">(</span><span class="identifier">a</span> <span class="special">&amp;&amp;</span> <span class="identifier">b</span> <span class="special">&amp;&amp;</span> <span class="identifier">c</span><span class="special">).</span><span class="identifier">get</span><span class="special">();</span>
<span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">,</span> <span class="identifier">C</span><span class="special">&gt;</span> <span class="identifier">t2</span> <span class="special">=</span> <span class="special">((</span><span class="identifier">a</span> <span class="special">||</span> <span class="identifier">a</span><span class="special">)</span> <span class="special">&amp;&amp;</span> <span class="identifier">c</span><span class="special">).</span><span class="identifier">get</span><span class="special">();</span>
<span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">,</span> <span class="identifier">B</span><span class="special">,</span> <span class="identifier">C</span><span class="special">&gt;</span> <span class="identifier">t3</span> <span class="special">=</span> <span class="special">((</span><span class="identifier">a</span> <span class="special">&amp;&amp;</span> <span class="identifier">b</span> <span class="special">||</span> <span class="identifier">a</span> <span class="special">&amp;&amp;</span> <span class="identifier">b</span><span class="special">)</span> <span class="special">&amp;&amp;</span> <span class="identifier">c</span><span class="special">).</span><span class="identifier">get</span><span class="special">();</span>
<span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">,</span> <span class="identifier">B</span><span class="special">&gt;,</span> <span class="identifier">C</span><span class="special">&gt;</span> <span class="identifier">t4</span> <span class="special">=</span> <span class="special">((</span><span class="identifier">ab</span> <span class="special">||</span> <span class="identifier">ab</span><span class="special">)</span> <span class="special">&amp;&amp;</span> <span class="identifier">c</span><span class="special">).</span><span class="identifier">get</span><span class="special">();</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="boost_yap.manual.examples.autodiff"></a><a class="link" href="manual.html#boost_yap.manual.examples.autodiff" title="Autodiff">Autodiff</a>
</h4></div></div></div>
<p>
Here we adapt an <a href="https://en.wikipedia.org/wiki/Automatic_differentiation" target="_top">automatic
differentiation</a> library to use Boost.YAP for specifying the equations
it operates on.
</p>
<p>
Autodiff is a pretty small library, and doesn't cover every possible input
expression. What it covers is simple arithmetic, and the well-known functions
<code class="computeroutput"><span class="identifier">sin</span></code>, <code class="computeroutput"><span class="identifier">cos</span></code>,
<code class="computeroutput"><span class="identifier">sqrt</span></code>, and <code class="computeroutput"><span class="identifier">pow</span></code>.
</p>
<p>
Here is how you would form an input to the library using its API. This
is taken from the test program that comes with the library.
</p>
<p>
</p>
<pre class="programlisting"><span class="identifier">Node</span><span class="special">*</span> <span class="identifier">build_linear_fun1_manually</span><span class="special">(</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">Node</span><span class="special">*&gt;&amp;</span> <span class="identifier">list</span><span class="special">)</span>
<span class="special">{</span>
<span class="comment">//f(x1,x2,x3) = -5*x1+sin(10)*x1+10*x2-x3/6</span>
<span class="identifier">PNode</span><span class="special">*</span> <span class="identifier">v5</span> <span class="special">=</span> <span class="identifier">create_param_node</span><span class="special">(-</span><span class="number">5</span><span class="special">);</span>
<span class="identifier">PNode</span><span class="special">*</span> <span class="identifier">v10</span> <span class="special">=</span> <span class="identifier">create_param_node</span><span class="special">(</span><span class="number">10</span><span class="special">);</span>
<span class="identifier">PNode</span><span class="special">*</span> <span class="identifier">v6</span> <span class="special">=</span> <span class="identifier">create_param_node</span><span class="special">(</span><span class="number">6</span><span class="special">);</span>
<span class="identifier">VNode</span><span class="special">*</span> <span class="identifier">x1</span> <span class="special">=</span> <span class="identifier">create_var_node</span><span class="special">();</span>
<span class="identifier">VNode</span><span class="special">*</span> <span class="identifier">x2</span> <span class="special">=</span> <span class="identifier">create_var_node</span><span class="special">();</span>
<span class="identifier">VNode</span><span class="special">*</span> <span class="identifier">x3</span> <span class="special">=</span> <span class="identifier">create_var_node</span><span class="special">();</span>
<span class="identifier">OPNode</span><span class="special">*</span> <span class="identifier">op1</span> <span class="special">=</span> <span class="identifier">create_binary_op_node</span><span class="special">(</span><span class="identifier">OP_TIMES</span><span class="special">,</span><span class="identifier">v5</span><span class="special">,</span><span class="identifier">x1</span><span class="special">);</span> <span class="comment">//op1 = v5*x1</span>
<span class="identifier">OPNode</span><span class="special">*</span> <span class="identifier">op2</span> <span class="special">=</span> <span class="identifier">create_uary_op_node</span><span class="special">(</span><span class="identifier">OP_SIN</span><span class="special">,</span><span class="identifier">v10</span><span class="special">);</span> <span class="comment">//op2 = sin(v10)</span>
<span class="identifier">OPNode</span><span class="special">*</span> <span class="identifier">op3</span> <span class="special">=</span> <span class="identifier">create_binary_op_node</span><span class="special">(</span><span class="identifier">OP_TIMES</span><span class="special">,</span><span class="identifier">op2</span><span class="special">,</span><span class="identifier">x1</span><span class="special">);</span> <span class="comment">//op3 = op2*x1</span>
<span class="identifier">OPNode</span><span class="special">*</span> <span class="identifier">op4</span> <span class="special">=</span> <span class="identifier">create_binary_op_node</span><span class="special">(</span><span class="identifier">OP_PLUS</span><span class="special">,</span><span class="identifier">op1</span><span class="special">,</span><span class="identifier">op3</span><span class="special">);</span> <span class="comment">//op4 = op1 + op3</span>
<span class="identifier">OPNode</span><span class="special">*</span> <span class="identifier">op5</span> <span class="special">=</span> <span class="identifier">create_binary_op_node</span><span class="special">(</span><span class="identifier">OP_TIMES</span><span class="special">,</span><span class="identifier">v10</span><span class="special">,</span><span class="identifier">x2</span><span class="special">);</span> <span class="comment">//op5 = v10*x2</span>
<span class="identifier">OPNode</span><span class="special">*</span> <span class="identifier">op6</span> <span class="special">=</span> <span class="identifier">create_binary_op_node</span><span class="special">(</span><span class="identifier">OP_PLUS</span><span class="special">,</span><span class="identifier">op4</span><span class="special">,</span><span class="identifier">op5</span><span class="special">);</span> <span class="comment">//op6 = op4+op5</span>
<span class="identifier">OPNode</span><span class="special">*</span> <span class="identifier">op7</span> <span class="special">=</span> <span class="identifier">create_binary_op_node</span><span class="special">(</span><span class="identifier">OP_DIVID</span><span class="special">,</span><span class="identifier">x3</span><span class="special">,</span><span class="identifier">v6</span><span class="special">);</span> <span class="comment">//op7 = x3/v6</span>
<span class="identifier">OPNode</span><span class="special">*</span> <span class="identifier">op8</span> <span class="special">=</span> <span class="identifier">create_binary_op_node</span><span class="special">(</span><span class="identifier">OP_MINUS</span><span class="special">,</span><span class="identifier">op6</span><span class="special">,</span><span class="identifier">op7</span><span class="special">);</span> <span class="comment">//op8 = op6 - op7</span>
<span class="identifier">x1</span><span class="special">-&gt;</span><span class="identifier">val</span> <span class="special">=</span> <span class="special">-</span><span class="number">1.9</span><span class="special">;</span>
<span class="identifier">x2</span><span class="special">-&gt;</span><span class="identifier">val</span> <span class="special">=</span> <span class="number">2</span><span class="special">;</span>
<span class="identifier">x3</span><span class="special">-&gt;</span><span class="identifier">val</span> <span class="special">=</span> <span class="number">5.</span><span class="special">/</span><span class="number">6.</span><span class="special">;</span>
<span class="identifier">list</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">x1</span><span class="special">);</span>
<span class="identifier">list</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">x2</span><span class="special">);</span>
<span class="identifier">list</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">x3</span><span class="special">);</span>
<span class="keyword">return</span> <span class="identifier">op8</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
</p>
<p>
I have a <span class="bold"><strong>lot</strong></span> of trouble understanding
what's going on here, and even more verifying that the expression written
in the comment is actually what the code produces. Let's see if we can
do better.
</p>
<p>
First, we start with a custom expression template, <code class="computeroutput"><span class="identifier">autodiff_expr</span></code>.
It supports simple arithmetic, but notice it has no call operator —
we don't want <code class="computeroutput"><span class="special">(</span><span class="identifier">a</span>
<span class="special">+</span> <span class="identifier">b</span><span class="special">)()</span></code> to be a valid expression.
</p>
<p>
</p>
<pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">Kind</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">autodiff_expr</span>
<span class="special">{</span>
<span class="keyword">static</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="keyword">const</span> <span class="identifier">kind</span> <span class="special">=</span> <span class="identifier">Kind</span><span class="special">;</span>
<span class="identifier">Tuple</span> <span class="identifier">elements</span><span class="special">;</span>
<span class="special">};</span>
<span class="identifier">BOOST_YAP_USER_UNARY_OPERATOR</span><span class="special">(</span><span class="identifier">negate</span><span class="special">,</span> <span class="identifier">autodiff_expr</span><span class="special">,</span> <span class="identifier">autodiff_expr</span><span class="special">)</span>
<span class="identifier">BOOST_YAP_USER_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">plus</span><span class="special">,</span> <span class="identifier">autodiff_expr</span><span class="special">,</span> <span class="identifier">autodiff_expr</span><span class="special">)</span>
<span class="identifier">BOOST_YAP_USER_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">minus</span><span class="special">,</span> <span class="identifier">autodiff_expr</span><span class="special">,</span> <span class="identifier">autodiff_expr</span><span class="special">)</span>
<span class="identifier">BOOST_YAP_USER_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">multiplies</span><span class="special">,</span> <span class="identifier">autodiff_expr</span><span class="special">,</span> <span class="identifier">autodiff_expr</span><span class="special">)</span>
<span class="identifier">BOOST_YAP_USER_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">divides</span><span class="special">,</span> <span class="identifier">autodiff_expr</span><span class="special">,</span> <span class="identifier">autodiff_expr</span><span class="special">)</span>
</pre>
<p>
</p>
<p>
We're going to be using a lot of placeholders in our Autodiff expressions,
and it sure would be nice if they were <code class="computeroutput"><span class="identifier">autodiff_expr</span></code>s
and not <code class="computeroutput"><a class="link" href="../boost/yap/expression.html" title="Struct template expression">expression&lt;&gt;s</a></code>, so that only our
desired operators are in play. To do this, we define an operator that produces
placeholder literals, using the <code class="computeroutput"><a class="link" href="../BOOST_YAP__1_3_49_8_2_7_12.html" title="Macro BOOST_YAP_USER_LITERAL_PLACEHOLDER_OPERATOR">BOOST_YAP_USER_LITERAL_PLACEHOLDER_OPERATOR</a></code>
macro:
</p>
<p>
</p>
<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">autodiff_placeholders</span> <span class="special">{</span>
<span class="comment">// This defines a placeholder literal operator that creates autodiff_expr</span>
<span class="comment">// placeholders.</span>
<span class="identifier">BOOST_YAP_USER_LITERAL_PLACEHOLDER_OPERATOR</span><span class="special">(</span><span class="identifier">autodiff_expr</span><span class="special">)</span>
<span class="special">}</span>
</pre>
<p>
</p>
<p>
Now, how about the functions we need to support, and where do we put the
call operator? In other examples we created terminal subclasses or templates
to get special behavior on terminals. In this case, we want to create a
function-terminal template:
</p>
<p>
</p>
<pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="identifier">OPCODE</span> <span class="identifier">Opcode</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">autodiff_fn_expr</span> <span class="special">:</span>
<span class="identifier">autodiff_expr</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="identifier">OPCODE</span><span class="special">&gt;&gt;</span>
<span class="special">{</span>
<span class="identifier">autodiff_fn_expr</span> <span class="special">()</span> <span class="special">:</span>
<span class="identifier">autodiff_expr</span> <span class="special">{</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="identifier">OPCODE</span><span class="special">&gt;{</span><span class="identifier">Opcode</span><span class="special">}}</span>
<span class="special">{}</span>
<span class="identifier">BOOST_YAP_USER_CALL_OPERATOR_N</span><span class="special">(::</span><span class="identifier">autodiff_expr</span><span class="special">,</span> <span class="number">1</span><span class="special">);</span>
<span class="special">};</span>
<span class="comment">// Someone included &lt;math.h&gt;, so we have to add trailing underscores.</span>
<span class="identifier">autodiff_fn_expr</span><span class="special">&lt;</span><span class="identifier">OP_SIN</span><span class="special">&gt;</span> <span class="keyword">const</span> <span class="identifier">sin_</span><span class="special">;</span>
<span class="identifier">autodiff_fn_expr</span><span class="special">&lt;</span><span class="identifier">OP_COS</span><span class="special">&gt;</span> <span class="keyword">const</span> <span class="identifier">cos_</span><span class="special">;</span>
<span class="identifier">autodiff_fn_expr</span><span class="special">&lt;</span><span class="identifier">OP_SQRT</span><span class="special">&gt;</span> <span class="keyword">const</span> <span class="identifier">sqrt_</span><span class="special">;</span>
</pre>
<p>
</p>
<p>
<code class="computeroutput"><span class="identifier">OPCODE</span></code> is an enumeration
in Autodiff. We use it as a non-type template parameter for convenience
when declaring <code class="computeroutput"><span class="identifier">sin_</span></code> and
friends. All we really need is for the <code class="computeroutput"><span class="identifier">OPCODE</span></code>
to be the value of the terminals we produce, and for these function-terminals
to have the call operator.
</p>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../doc/src/images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td align="left" valign="top"><p>
Using <code class="computeroutput"><a class="link" href="../BOOST_YAP_U_1_3_49_8_2_7_5.html" title="Macro BOOST_YAP_USER_CALL_OPERATOR">BOOST_YAP_USER_CALL_OPERATOR</a></code>
is a bit loose here, because it defines a variadic template. We could
have written unary call operators to ensure that the user can't write
call expressions with the wrong number of arguments.
</p></td></tr>
</table></div>
<p>
Now, some tranforms:
</p>
<p>
</p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">xform</span>
<span class="special">{</span>
<span class="comment">// Create a var-node for each placeholder when we see it for the first</span>
<span class="comment">// time.</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">long</span> <span class="keyword">long</span> <span class="identifier">I</span><span class="special">&gt;</span>
<span class="identifier">Node</span> <span class="special">*</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_tag</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">&gt;,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">placeholder</span><span class="special">&lt;</span><span class="identifier">I</span><span class="special">&gt;)</span>
<span class="special">{</span>
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">list_</span><span class="special">.</span><span class="identifier">size</span><span class="special">()</span> <span class="special">&lt;</span> <span class="identifier">I</span><span class="special">)</span>
<span class="identifier">list_</span><span class="special">.</span><span class="identifier">resize</span><span class="special">(</span><span class="identifier">I</span><span class="special">);</span>
<span class="keyword">auto</span> <span class="special">&amp;</span> <span class="identifier">retval</span> <span class="special">=</span> <span class="identifier">list_</span><span class="special">[</span><span class="identifier">I</span> <span class="special">-</span> <span class="number">1</span><span class="special">];</span>
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">retval</span> <span class="special">==</span> <span class="keyword">nullptr</span><span class="special">)</span>
<span class="identifier">retval</span> <span class="special">=</span> <span class="identifier">create_var_node</span><span class="special">();</span>
<span class="keyword">return</span> <span class="identifier">retval</span><span class="special">;</span>
<span class="special">}</span>
<span class="comment">// Create a param-node for every numeric terminal in the expression.</span>
<span class="identifier">Node</span> <span class="special">*</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_tag</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">&gt;,</span> <span class="keyword">double</span> <span class="identifier">x</span><span class="special">)</span>
<span class="special">{</span> <span class="keyword">return</span> <span class="identifier">create_param_node</span><span class="special">(</span><span class="identifier">x</span><span class="special">);</span> <span class="special">}</span>
<span class="comment">// Create a "uary" node for each call expression, using its OPCODE.</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Expr</span><span class="special">&gt;</span>
<span class="identifier">Node</span> <span class="special">*</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_tag</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">call</span><span class="special">&gt;,</span>
<span class="identifier">OPCODE</span> <span class="identifier">opcode</span><span class="special">,</span> <span class="identifier">Expr</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">expr</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">create_uary_op_node</span><span class="special">(</span>
<span class="identifier">opcode</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">as_expr</span><span class="special">&lt;</span><span class="identifier">autodiff_expr</span><span class="special">&gt;(</span><span class="identifier">expr</span><span class="special">),</span> <span class="special">*</span><span class="keyword">this</span><span class="special">)</span>
<span class="special">);</span>
<span class="special">}</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Expr</span><span class="special">&gt;</span>
<span class="identifier">Node</span> <span class="special">*</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_tag</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">negate</span><span class="special">&gt;,</span>
<span class="identifier">Expr</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">expr</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">create_uary_op_node</span><span class="special">(</span>
<span class="identifier">OP_NEG</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">as_expr</span><span class="special">&lt;</span><span class="identifier">autodiff_expr</span><span class="special">&gt;(</span><span class="identifier">expr</span><span class="special">),</span> <span class="special">*</span><span class="keyword">this</span><span class="special">)</span>
<span class="special">);</span>
<span class="special">}</span>
<span class="comment">// Define a mapping from binary arithmetic expr_kind to OPCODE...</span>
<span class="keyword">static</span> <span class="identifier">OPCODE</span> <span class="identifier">op_for_kind</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">kind</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">switch</span> <span class="special">(</span><span class="identifier">kind</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">case</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">plus</span><span class="special">:</span> <span class="keyword">return</span> <span class="identifier">OP_PLUS</span><span class="special">;</span>
<span class="keyword">case</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">minus</span><span class="special">:</span> <span class="keyword">return</span> <span class="identifier">OP_MINUS</span><span class="special">;</span>
<span class="keyword">case</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">multiplies</span><span class="special">:</span> <span class="keyword">return</span> <span class="identifier">OP_TIMES</span><span class="special">;</span>
<span class="keyword">case</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">divides</span><span class="special">:</span> <span class="keyword">return</span> <span class="identifier">OP_DIVID</span><span class="special">;</span>
<span class="keyword">default</span><span class="special">:</span> <span class="identifier">assert</span><span class="special">(!</span><span class="string">"This should never execute"</span><span class="special">);</span> <span class="keyword">return</span> <span class="identifier">OPCODE</span><span class="special">{};</span>
<span class="special">}</span>
<span class="identifier">assert</span><span class="special">(!</span><span class="string">"This should never execute"</span><span class="special">);</span>
<span class="keyword">return</span> <span class="identifier">OPCODE</span><span class="special">{};</span>
<span class="special">}</span>
<span class="comment">// ... and use it to handle all the binary arithmetic operators.</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">Kind</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Expr1</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Expr2</span><span class="special">&gt;</span>
<span class="identifier">Node</span> <span class="special">*</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_tag</span><span class="special">&lt;</span><span class="identifier">Kind</span><span class="special">&gt;,</span> <span class="identifier">Expr1</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">expr1</span><span class="special">,</span> <span class="identifier">Expr2</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">expr2</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">create_binary_op_node</span><span class="special">(</span>
<span class="identifier">op_for_kind</span><span class="special">(</span><span class="identifier">Kind</span><span class="special">),</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">as_expr</span><span class="special">&lt;</span><span class="identifier">autodiff_expr</span><span class="special">&gt;(</span><span class="identifier">expr1</span><span class="special">),</span> <span class="special">*</span><span class="keyword">this</span><span class="special">),</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">as_expr</span><span class="special">&lt;</span><span class="identifier">autodiff_expr</span><span class="special">&gt;(</span><span class="identifier">expr2</span><span class="special">),</span> <span class="special">*</span><span class="keyword">this</span><span class="special">)</span>
<span class="special">);</span>
<span class="special">}</span>
<span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">Node</span> <span class="special">*&gt;</span> <span class="special">&amp;</span> <span class="identifier">list_</span><span class="special">;</span>
<span class="special">};</span>
</pre>
<p>
</p>
<p>
We need a function to tie everything together, since the transforms cannot
fill in the values for the placeholders.
</p>
<p>
</p>
<pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Expr</span><span class="special">,</span> <span class="keyword">typename</span> <span class="special">...</span><span class="identifier">T</span><span class="special">&gt;</span>
<span class="identifier">Node</span> <span class="special">*</span> <span class="identifier">to_auto_diff_node</span> <span class="special">(</span><span class="identifier">Expr</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">expr</span><span class="special">,</span> <span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">Node</span> <span class="special">*&gt;</span> <span class="special">&amp;</span> <span class="identifier">list</span><span class="special">,</span> <span class="identifier">T</span> <span class="special">...</span> <span class="identifier">args</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">Node</span> <span class="special">*</span> <span class="identifier">retval</span> <span class="special">=</span> <span class="keyword">nullptr</span><span class="special">;</span>
<span class="comment">// This fills in list as a side effect.</span>
<span class="identifier">retval</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">expr</span><span class="special">,</span> <span class="identifier">xform</span><span class="special">{</span><span class="identifier">list</span><span class="special">});</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">list</span><span class="special">.</span><span class="identifier">size</span><span class="special">()</span> <span class="special">==</span> <span class="keyword">sizeof</span><span class="special">...(</span><span class="identifier">args</span><span class="special">));</span>
<span class="comment">// Fill in the values of the value-nodes in list with the "args"</span>
<span class="comment">// parameter pack.</span>
<span class="keyword">auto</span> <span class="identifier">it</span> <span class="special">=</span> <span class="identifier">list</span><span class="special">.</span><span class="identifier">begin</span><span class="special">();</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">for_each</span><span class="special">(</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">make_tuple</span><span class="special">(</span><span class="identifier">args</span> <span class="special">...),</span>
<span class="special">[&amp;</span><span class="identifier">it</span><span class="special">](</span><span class="keyword">auto</span> <span class="identifier">x</span><span class="special">)</span> <span class="special">{</span>
<span class="identifier">Node</span> <span class="special">*</span> <span class="identifier">n</span> <span class="special">=</span> <span class="special">*</span><span class="identifier">it</span><span class="special">;</span>
<span class="identifier">VNode</span> <span class="special">*</span> <span class="identifier">v</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">polymorphic_downcast</span><span class="special">&lt;</span><span class="identifier">VNode</span> <span class="special">*&gt;(</span><span class="identifier">n</span><span class="special">);</span>
<span class="identifier">v</span><span class="special">-&gt;</span><span class="identifier">val</span> <span class="special">=</span> <span class="identifier">x</span><span class="special">;</span>
<span class="special">++</span><span class="identifier">it</span><span class="special">;</span>
<span class="special">}</span>
<span class="special">);</span>
<span class="keyword">return</span> <span class="identifier">retval</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
</p>
<p>
Finally, here is the Boost.YAP version of the function we started with:
</p>
<p>
</p>
<pre class="programlisting"><span class="identifier">Node</span><span class="special">*</span> <span class="identifier">build_linear_fun1</span><span class="special">(</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">Node</span><span class="special">*&gt;&amp;</span> <span class="identifier">list</span><span class="special">)</span>
<span class="special">{</span>
<span class="comment">//f(x1,x2,x3) = -5*x1+sin(10)*x1+10*x2-x3/6</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">autodiff_placeholders</span><span class="special">;</span>
<span class="keyword">return</span> <span class="identifier">to_auto_diff_node</span><span class="special">(</span>
<span class="special">-</span><span class="number">5</span> <span class="special">*</span> <span class="number">1</span><span class="identifier">_p</span> <span class="special">+</span> <span class="identifier">sin_</span><span class="special">(</span><span class="number">10</span><span class="special">)</span> <span class="special">*</span> <span class="number">1</span><span class="identifier">_p</span> <span class="special">+</span> <span class="number">10</span> <span class="special">*</span> <span class="number">2</span><span class="identifier">_p</span> <span class="special">-</span> <span class="number">3</span><span class="identifier">_p</span> <span class="special">/</span> <span class="number">6</span><span class="special">,</span>
<span class="identifier">list</span><span class="special">,</span>
<span class="special">-</span><span class="number">1.9</span><span class="special">,</span>
<span class="number">2</span><span class="special">,</span>
<span class="number">5.</span><span class="special">/</span><span class="number">6.</span>
<span class="special">);</span>
<span class="special">}</span>
</pre>
<p>
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="boost_yap.manual.examples.transforming_terminals_only"></a><a class="link" href="manual.html#boost_yap.manual.examples.transforming_terminals_only" title="Transforming Terminals Only">Transforming
Terminals Only</a>
</h4></div></div></div>
<p>
Sometimes it can be useful only to transform the terminals in an expression.
For instance, if you have some type you use for SIMD operations called
<code class="computeroutput"><span class="identifier">simd</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;</span></code>,
you may want to replace all the <code class="computeroutput"><span class="keyword">double</span></code>
terminals with <code class="computeroutput"><span class="identifier">simd</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;</span></code>.
Perhaps you just want to change out <code class="computeroutput"><span class="keyword">double</span></code>
for <code class="computeroutput"><span class="keyword">float</span></code>, or <code class="computeroutput"><span class="keyword">int</span></code> for <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span></code>.
You get the idea.
</p>
<p>
In this example, we're replacing all the terminals with something essentially
arbitrary, the sequence of integer terminals <code class="computeroutput"><span class="identifier">N</span><span class="special">,</span> <span class="identifier">N</span> <span class="special">+</span> <span class="number">1</span><span class="special">,</span>
<span class="identifier">N</span> <span class="special">+</span>
<span class="number">2</span><span class="special">,</span> <span class="special">...</span></code>. This makes it easier to observe the
result of the replacement in a simple example.
</p>
<p>
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">yap</span><span class="special">/</span><span class="identifier">yap</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">iota_terminal_transform</span>
<span class="special">{</span>
<span class="comment">// Base case. Note that we're not treating placeholders specially for this</span>
<span class="comment">// example (they're easy to special-case if necessary).</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_tag</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">&gt;,</span> <span class="identifier">T</span> <span class="special">&amp;&amp;</span> <span class="identifier">t</span><span class="special">)</span>
<span class="special">{</span>
<span class="comment">// Like the std::iota() algorithm, we create replacement int terminals</span>
<span class="comment">// with the values index_, index_ + 1, index_ + 2, etc.</span>
<span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_terminal</span><span class="special">(</span><span class="identifier">index_</span><span class="special">++);</span>
<span class="special">}</span>
<span class="comment">// Recursive case: Match any call expression.</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">CallableExpr</span><span class="special">,</span> <span class="keyword">typename</span><span class="special">...</span> <span class="identifier">Arg</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_tag</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">call</span><span class="special">&gt;,</span>
<span class="identifier">CallableExpr</span> <span class="identifier">callable</span><span class="special">,</span> <span class="identifier">Arg</span> <span class="special">&amp;&amp;...</span> <span class="identifier">arg</span><span class="special">)</span>
<span class="special">{</span>
<span class="comment">// Even though the callable in a call expression is technically a</span>
<span class="comment">// terminal, it doesn't make a lot of sense to replace it with an int,</span>
<span class="comment">// so we'll only transform the argument subexpressions.</span>
<span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_expression</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">call</span><span class="special">&gt;(</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">as_expr</span><span class="special">(</span><span class="identifier">callable</span><span class="special">),</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">as_expr</span><span class="special">(</span><span class="identifier">arg</span><span class="special">),</span> <span class="special">*</span><span class="keyword">this</span><span class="special">)...);</span>
<span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">index_</span><span class="special">;</span>
<span class="special">};</span>
<span class="keyword">int</span> <span class="identifier">sum</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">b</span><span class="special">)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">a</span> <span class="special">+</span> <span class="identifier">b</span><span class="special">;</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span>
<span class="special">{</span>
<span class="special">{</span>
<span class="comment">// This simple sum(8, 8) expression requires both overloads of</span>
<span class="comment">// iota_terminal_transform.</span>
<span class="keyword">auto</span> <span class="identifier">expr</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_terminal</span><span class="special">(</span><span class="identifier">sum</span><span class="special">)(</span><span class="number">8</span><span class="special">,</span> <span class="number">8</span><span class="special">);</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">evaluate</span><span class="special">(</span><span class="identifier">expr</span><span class="special">)</span> <span class="special">==</span> <span class="number">16</span><span class="special">);</span>
<span class="keyword">auto</span> <span class="identifier">iota_expr</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">expr</span><span class="special">,</span> <span class="identifier">iota_terminal_transform</span><span class="special">{</span><span class="number">1</span><span class="special">});</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">evaluate</span><span class="special">(</span><span class="identifier">iota_expr</span><span class="special">)</span> <span class="special">==</span> <span class="number">3</span><span class="special">);</span>
<span class="special">}</span>
<span class="special">{</span>
<span class="comment">// This expression requires only the terminal case of</span>
<span class="comment">// iota_terminal_transform.</span>
<span class="keyword">auto</span> <span class="identifier">expr</span> <span class="special">=</span> <span class="special">-(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_terminal</span><span class="special">(</span><span class="number">8</span><span class="special">)</span> <span class="special">+</span> <span class="number">8</span><span class="special">);</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">evaluate</span><span class="special">(</span><span class="identifier">expr</span><span class="special">)</span> <span class="special">==</span> <span class="special">-</span><span class="number">16</span><span class="special">);</span>
<span class="keyword">auto</span> <span class="identifier">iota_expr</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">expr</span><span class="special">,</span> <span class="identifier">iota_terminal_transform</span><span class="special">{</span><span class="number">0</span><span class="special">});</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">evaluate</span><span class="special">(</span><span class="identifier">iota_expr</span><span class="special">)</span> <span class="special">==</span> <span class="special">-</span><span class="number">1</span><span class="special">);</span>
<span class="special">}</span>
<span class="special">{</span>
<span class="comment">// Like the first expression above, this expression requires both</span>
<span class="comment">// overloads of iota_terminal_transform.</span>
<span class="keyword">auto</span> <span class="identifier">expr</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_terminal</span><span class="special">(</span><span class="identifier">sum</span><span class="special">)(-(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_terminal</span><span class="special">(</span><span class="number">8</span><span class="special">)</span> <span class="special">+</span> <span class="number">8</span><span class="special">),</span> <span class="number">0</span><span class="special">);</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">evaluate</span><span class="special">(</span><span class="identifier">expr</span><span class="special">)</span> <span class="special">==</span> <span class="special">-</span><span class="number">16</span><span class="special">);</span>
<span class="keyword">auto</span> <span class="identifier">iota_expr</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">expr</span><span class="special">,</span> <span class="identifier">iota_terminal_transform</span><span class="special">{</span><span class="number">0</span><span class="special">});</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">evaluate</span><span class="special">(</span><span class="identifier">iota_expr</span><span class="special">)</span> <span class="special">==</span> <span class="special">-</span><span class="number">3</span><span class="special">);</span>
<span class="special">}</span>
<span class="special">}</span>
</pre>
<p>
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="boost_yap.manual.examples.pipable_algorithms"></a><a class="link" href="manual.html#boost_yap.manual.examples.pipable_algorithms" title="Pipable Algorithms">Pipable
Algorithms</a>
</h4></div></div></div>
<p>
Let's revisit the pipable standard algorithm example from the intro. Here's
how you might implement it.
</p>
<p>
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">yap</span><span class="special">/</span><span class="identifier">algorithm</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">algorithm</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">vector</span><span class="special">&gt;</span>
<span class="comment">// An enum to represent all the standard algorithms we want to adapt. In this</span>
<span class="comment">// example, we only care about std::sort() and std::unique().</span>
<span class="keyword">enum</span> <span class="keyword">class</span> <span class="identifier">algorithm_t</span> <span class="special">{</span> <span class="identifier">sort</span><span class="special">,</span> <span class="identifier">unique</span> <span class="special">};</span>
<span class="comment">// Just about the simplest range template you could construct. Nothing fancy.</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Iter</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">simple_range</span>
<span class="special">{</span>
<span class="identifier">Iter</span> <span class="identifier">begin</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">first_</span><span class="special">;</span> <span class="special">}</span>
<span class="identifier">Iter</span> <span class="identifier">end</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">last_</span><span class="special">;</span> <span class="special">}</span>
<span class="identifier">Iter</span> <span class="identifier">first_</span><span class="special">;</span>
<span class="identifier">Iter</span> <span class="identifier">last_</span><span class="special">;</span>
<span class="special">};</span>
<span class="comment">// This simply calls the standard algorithm that corresponds to "a". This</span>
<span class="comment">// certainly won't work for all the algorithms, but it works for many of them</span>
<span class="comment">// that just take a begin/end pair.</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Range</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="identifier">call_algorithm</span><span class="special">(</span><span class="identifier">algorithm_t</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">Range</span> <span class="special">&amp;</span> <span class="identifier">r</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">simple_range</span><span class="special">&lt;</span><span class="keyword">decltype</span><span class="special">(</span><span class="identifier">r</span><span class="special">.</span><span class="identifier">begin</span><span class="special">())&gt;</span> <span class="identifier">retval</span><span class="special">{</span><span class="identifier">r</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(),</span> <span class="identifier">r</span><span class="special">.</span><span class="identifier">end</span><span class="special">()};</span>
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">a</span> <span class="special">==</span> <span class="identifier">algorithm_t</span><span class="special">::</span><span class="identifier">sort</span><span class="special">)</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">sort</span><span class="special">(</span><span class="identifier">r</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(),</span> <span class="identifier">r</span><span class="special">.</span><span class="identifier">end</span><span class="special">());</span>
<span class="special">}</span> <span class="keyword">else</span> <span class="keyword">if</span> <span class="special">(</span><span class="identifier">a</span> <span class="special">==</span> <span class="identifier">algorithm_t</span><span class="special">::</span><span class="identifier">unique</span><span class="special">)</span> <span class="special">{</span>
<span class="identifier">retval</span><span class="special">.</span><span class="identifier">last_</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">unique</span><span class="special">(</span><span class="identifier">r</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(),</span> <span class="identifier">r</span><span class="special">.</span><span class="identifier">end</span><span class="special">());</span>
<span class="special">}</span>
<span class="keyword">return</span> <span class="identifier">retval</span><span class="special">;</span>
<span class="special">}</span>
<span class="comment">// This is the transform that evaluates our piped expressions. It returns a</span>
<span class="comment">// simple_range&lt;&gt;, not a Yap expression.</span>
<span class="keyword">struct</span> <span class="identifier">algorithm_eval</span>
<span class="special">{</span>
<span class="comment">// A pipe should always have a Yap expression on the left and an</span>
<span class="comment">// algorithm_t terminal on the right.</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">LExpr</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="keyword">operator</span><span class="special">()(</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_tag</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">bitwise_or</span><span class="special">&gt;,</span>
<span class="identifier">LExpr</span> <span class="special">&amp;&amp;</span> <span class="identifier">left</span><span class="special">,</span>
<span class="identifier">algorithm_t</span> <span class="identifier">right</span><span class="special">)</span>
<span class="special">{</span>
<span class="comment">// Recursively evaluate the left ...</span>
<span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">left_result</span> <span class="special">=</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special">&lt;</span><span class="identifier">LExpr</span><span class="special">&gt;(</span><span class="identifier">left</span><span class="special">),</span> <span class="special">*</span><span class="keyword">this</span><span class="special">);</span>
<span class="comment">// ... and use the result to call the function on the right.</span>
<span class="keyword">return</span> <span class="identifier">call_algorithm</span><span class="special">(</span><span class="identifier">right</span><span class="special">,</span> <span class="identifier">left_result</span><span class="special">);</span>
<span class="special">}</span>
<span class="comment">// A call operation is evaluated directly. Note that the range parameter</span>
<span class="comment">// is taken as an lvalue reference, to prevent binding to a temporary and</span>
<span class="comment">// taking dangling references to its begin and end. We let the compiler</span>
<span class="comment">// deduce whether the lvalue reference is const.</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Range</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="keyword">operator</span><span class="special">()(</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_tag</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">call</span><span class="special">&gt;,</span>
<span class="identifier">algorithm_t</span> <span class="identifier">a</span><span class="special">,</span>
<span class="identifier">Range</span> <span class="special">&amp;</span> <span class="identifier">r</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">call_algorithm</span><span class="special">(</span><span class="identifier">a</span><span class="special">,</span> <span class="identifier">r</span><span class="special">);</span>
<span class="special">}</span>
<span class="special">};</span>
<span class="comment">// This is the expression template we use for the general case of a pipable</span>
<span class="comment">// algorithm expression. Terminals are handled separately.</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="identifier">Kind</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">algorithm_expr</span>
<span class="special">{</span>
<span class="keyword">static</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="keyword">const</span> <span class="identifier">kind</span> <span class="special">=</span> <span class="identifier">Kind</span><span class="special">;</span>
<span class="identifier">Tuple</span> <span class="identifier">elements</span><span class="special">;</span>
<span class="comment">// This is how we get the nice initializer semantics we see in the example</span>
<span class="comment">// usage below. This is a bit limited though, because we always create a</span>
<span class="comment">// temporary. It might therefore be better just to create algorithm_expr</span>
<span class="comment">// expressions, call yap::evaluate(), and then use the sequence containers</span>
<span class="comment">// assign() member function to do the actual assignment.</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Assignee</span><span class="special">&gt;</span>
<span class="keyword">operator</span> <span class="identifier">Assignee</span><span class="special">()</span> <span class="keyword">const</span>
<span class="special">{</span>
<span class="comment">// Exercise left for the reader: static_assert() that Assignee is some</span>
<span class="comment">// sort of container type.</span>
<span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">range</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(*</span><span class="keyword">this</span><span class="special">,</span> <span class="identifier">algorithm_eval</span><span class="special">{});</span>
<span class="keyword">return</span> <span class="identifier">Assignee</span><span class="special">(</span><span class="identifier">range</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(),</span> <span class="identifier">range</span><span class="special">.</span><span class="identifier">end</span><span class="special">());</span>
<span class="special">}</span>
<span class="special">};</span>
<span class="comment">// This is a bit loose, because it allows us to write "sort(v) | unique(u)" or</span>
<span class="comment">// similar. It works fine for this example, but in production code you may</span>
<span class="comment">// want to write out the functions generated by this macro, and add SFINAE or</span>
<span class="comment">// concepts constraints on the right template parameter.</span>
<span class="identifier">BOOST_YAP_USER_BINARY_OPERATOR</span><span class="special">(</span><span class="identifier">bitwise_or</span><span class="special">,</span> <span class="identifier">algorithm_expr</span><span class="special">,</span> <span class="identifier">algorithm_expr</span><span class="special">)</span>
<span class="comment">// It's useful to specially handle terminals, because we want a different set</span>
<span class="comment">// of operations to apply to them. We don't want "sort(x)(y)" to be</span>
<span class="comment">// well-formed, for instance, or "sort | unique" either.</span>
<span class="keyword">struct</span> <span class="identifier">algorithm</span>
<span class="special">{</span>
<span class="keyword">static</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span> <span class="keyword">const</span> <span class="identifier">kind</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="identifier">algorithm_t</span><span class="special">&gt;</span> <span class="identifier">elements</span><span class="special">;</span>
<span class="identifier">BOOST_YAP_USER_CALL_OPERATOR_N</span><span class="special">(::</span><span class="identifier">algorithm_expr</span><span class="special">,</span> <span class="number">1</span><span class="special">)</span>
<span class="special">};</span>
<span class="comment">// Here are ready-made Yap terminals, one for each algorithm enumerated in</span>
<span class="comment">// algorithm_t.</span>
<span class="keyword">constexpr</span> <span class="identifier">algorithm</span> <span class="identifier">sort</span><span class="special">{{</span><span class="identifier">algorithm_t</span><span class="special">::</span><span class="identifier">sort</span><span class="special">}};</span>
<span class="keyword">constexpr</span> <span class="identifier">algorithm</span> <span class="identifier">unique</span><span class="special">{{</span><span class="identifier">algorithm_t</span><span class="special">::</span><span class="identifier">unique</span><span class="special">}};</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span>
<span class="special">{</span>
<span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">v1</span> <span class="special">=</span> <span class="special">{</span><span class="number">0</span><span class="special">,</span> <span class="number">2</span><span class="special">,</span> <span class="number">2</span><span class="special">,</span> <span class="number">7</span><span class="special">,</span> <span class="number">1</span><span class="special">,</span> <span class="number">3</span><span class="special">,</span> <span class="number">8</span><span class="special">};</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">sort</span><span class="special">(</span><span class="identifier">v1</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(),</span> <span class="identifier">v1</span><span class="special">.</span><span class="identifier">end</span><span class="special">());</span>
<span class="keyword">auto</span> <span class="identifier">it</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">unique</span><span class="special">(</span><span class="identifier">v1</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(),</span> <span class="identifier">v1</span><span class="special">.</span><span class="identifier">end</span><span class="special">());</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="keyword">const</span> <span class="identifier">v2</span><span class="special">(</span><span class="identifier">v1</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(),</span> <span class="identifier">it</span><span class="special">);</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">v2</span> <span class="special">==</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;({</span><span class="number">0</span><span class="special">,</span> <span class="number">1</span><span class="special">,</span> <span class="number">2</span><span class="special">,</span> <span class="number">3</span><span class="special">,</span> <span class="number">7</span><span class="special">,</span> <span class="number">8</span><span class="special">}));</span>
<span class="special">}</span>
<span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">v1</span> <span class="special">=</span> <span class="special">{</span><span class="number">0</span><span class="special">,</span> <span class="number">2</span><span class="special">,</span> <span class="number">2</span><span class="special">,</span> <span class="number">7</span><span class="special">,</span> <span class="number">1</span><span class="special">,</span> <span class="number">3</span><span class="special">,</span> <span class="number">8</span><span class="special">};</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="keyword">const</span> <span class="identifier">v2</span> <span class="special">=</span> <span class="identifier">sort</span><span class="special">(</span><span class="identifier">v1</span><span class="special">)</span> <span class="special">|</span> <span class="identifier">unique</span><span class="special">;</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">v2</span> <span class="special">==</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;({</span><span class="number">0</span><span class="special">,</span> <span class="number">1</span><span class="special">,</span> <span class="number">2</span><span class="special">,</span> <span class="number">3</span><span class="special">,</span> <span class="number">7</span><span class="special">,</span> <span class="number">8</span><span class="special">}));</span>
<span class="special">}</span>
<span class="special">}</span>
</pre>
<p>
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="boost_yap.manual.examples.boost_phoenix_style__let___"></a><a class="link" href="manual.html#boost_yap.manual.examples.boost_phoenix_style__let___" title="Boost.Phoenix-style let()">Boost.Phoenix-style
<code class="computeroutput"><span class="identifier">let</span><span class="special">()</span></code></a>
</h4></div></div></div>
<p>
Boost.Phoenix has a thing called <a href="http://www.boost.org/doc/libs/1_66_0/libs/phoenix/doc/html/phoenix/modules/scope/let.html" target="_top"><code class="computeroutput"><span class="identifier">let</span><span class="special">()</span></code></a>.
It introduces named reusable values that are usable in subsequent expressions.
This example is something simliar, though not exactly like Phoenix's version.
In Phoenix, a let placeholder is only evaluated once, whereas the example
below does something more like macro substitution; each let-placeholder
is replaced with its initializing expression everywhere it is used.
</p>
<p>
This example uses C++17's <code class="computeroutput"><span class="keyword">if</span> <span class="keyword">constexpr</span> <span class="special">()</span></code>,
simply because it makes the example shorter and easier to digest. The
<code class="computeroutput"><span class="keyword">if</span> <span class="keyword">constexpr</span>
<span class="special">()</span></code> bits are not strictly necessary.
</p>
<p>
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">yap</span><span class="special">/</span><span class="identifier">yap</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">hana</span><span class="special">/</span><span class="identifier">map</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">hana</span><span class="special">/</span><span class="identifier">at_key</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">hana</span><span class="special">/</span><span class="identifier">contains</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">hana</span><span class="special">/</span><span class="identifier">keys</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">vector</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="comment">// Here, we introduce special let-placeholders, so we can use them along side</span>
<span class="comment">// the normal YAP placeholders without getting them confused.</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">long</span> <span class="keyword">long</span> <span class="identifier">I</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">let_placeholder</span> <span class="special">:</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">llong</span><span class="special">&lt;</span><span class="identifier">I</span><span class="special">&gt;</span>
<span class="special">{</span>
<span class="special">};</span>
<span class="comment">// Replaces each let-terminal with the expression with which it was</span>
<span class="comment">// initialized in let(). So in 'let(_a = foo)[ _a + 1 ]', this transform will</span>
<span class="comment">// be used on '_a + 1' to replace '_a' with 'foo'. The map_ member holds the</span>
<span class="comment">// mapping of let-placeholders to their initializers.</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">ExprMap</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">let_terminal_transform</span>
<span class="special">{</span>
<span class="comment">// This matches only let-placeholders. For each one matched, we look up</span>
<span class="comment">// its initializer in map_ and return it.</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">long</span> <span class="keyword">long</span> <span class="identifier">I</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="keyword">operator</span><span class="special">()(</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_tag</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">&gt;,</span>
<span class="identifier">let_placeholder</span><span class="special">&lt;</span><span class="identifier">I</span><span class="special">&gt;</span> <span class="identifier">i</span><span class="special">)</span>
<span class="special">{</span>
<span class="comment">// If we have an entry in map_ for this placeholder, return the value</span>
<span class="comment">// of the entry. Otherwise, pass i through as a terminal.</span>
<span class="keyword">if</span> <span class="keyword">constexpr</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">contains</span><span class="special">(</span>
<span class="keyword">decltype</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">keys</span><span class="special">(</span><span class="identifier">map_</span><span class="special">))(),</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">llong_c</span><span class="special">&lt;</span><span class="identifier">I</span><span class="special">&gt;))</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">map_</span><span class="special">[</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">llong_c</span><span class="special">&lt;</span><span class="identifier">I</span><span class="special">&gt;];</span>
<span class="special">}</span> <span class="keyword">else</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_terminal</span><span class="special">(</span><span class="identifier">i</span><span class="special">);</span>
<span class="special">}</span>
<span class="special">}</span>
<span class="identifier">ExprMap</span> <span class="identifier">map_</span><span class="special">;</span>
<span class="special">};</span>
<span class="comment">// As you can see below, let() is an eager function; this template is used for</span>
<span class="comment">// its return values. It contains the mapping from let-placeholders to</span>
<span class="comment">// initializer expressions used to transform the expression inside '[]' after</span>
<span class="comment">// a let()'. It also has an operator[]() member function that takes the</span>
<span class="comment">// expression inside '[]' and returns a version of it with the</span>
<span class="comment">// let-placeholders replaced.</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">ExprMap</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">let_result</span>
<span class="special">{</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Expr</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="keyword">operator</span><span class="special">[](</span><span class="identifier">Expr</span> <span class="special">&amp;&amp;</span> <span class="identifier">expr</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">transform</span><span class="special">(</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special">&lt;</span><span class="identifier">Expr</span><span class="special">&gt;(</span><span class="identifier">expr</span><span class="special">),</span> <span class="identifier">let_terminal_transform</span><span class="special">&lt;</span><span class="identifier">ExprMap</span><span class="special">&gt;{</span><span class="identifier">map_</span><span class="special">});</span>
<span class="special">}</span>
<span class="identifier">ExprMap</span> <span class="identifier">map_</span><span class="special">;</span>
<span class="special">};</span>
<span class="comment">// Processes the expressions passed to let() one at a time, adding each one to</span>
<span class="comment">// a Hana map of hana::llong&lt;&gt;s to YAP expressions.</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Map</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Expr</span><span class="special">,</span> <span class="keyword">typename</span><span class="special">...</span> <span class="identifier">Exprs</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="identifier">let_impl</span><span class="special">(</span><span class="identifier">Map</span> <span class="special">&amp;&amp;</span> <span class="identifier">map</span><span class="special">,</span> <span class="identifier">Expr</span> <span class="special">&amp;&amp;</span> <span class="identifier">expr</span><span class="special">,</span> <span class="identifier">Exprs</span> <span class="special">&amp;&amp;...</span> <span class="identifier">exprs</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">static_assert</span><span class="special">(</span>
<span class="identifier">Expr</span><span class="special">::</span><span class="identifier">kind</span> <span class="special">==</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">assign</span><span class="special">,</span>
<span class="string">"Expressions passed to let() must be of the form placeholder = Expression"</span><span class="special">);</span>
<span class="keyword">if</span> <span class="keyword">constexpr</span> <span class="special">(</span><span class="keyword">sizeof</span><span class="special">...(</span><span class="identifier">Exprs</span><span class="special">)</span> <span class="special">==</span> <span class="number">0</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">using</span> <span class="identifier">I</span> <span class="special">=</span> <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">remove_reference</span><span class="special">&lt;</span><span class="keyword">decltype</span><span class="special">(</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">value</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">left</span><span class="special">(</span><span class="identifier">expr</span><span class="special">)))&gt;::</span><span class="identifier">type</span><span class="special">;</span>
<span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">i</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">llong_c</span><span class="special">&lt;</span><span class="identifier">I</span><span class="special">::</span><span class="identifier">value</span><span class="special">&gt;;</span>
<span class="keyword">using</span> <span class="identifier">map_t</span> <span class="special">=</span> <span class="keyword">decltype</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">insert</span><span class="special">(</span>
<span class="identifier">map</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">make_pair</span><span class="special">(</span><span class="identifier">i</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">right</span><span class="special">(</span><span class="identifier">expr</span><span class="special">))));</span>
<span class="keyword">return</span> <span class="identifier">let_result</span><span class="special">&lt;</span><span class="identifier">map_t</span><span class="special">&gt;{</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">insert</span><span class="special">(</span>
<span class="identifier">map</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">make_pair</span><span class="special">(</span><span class="identifier">i</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">right</span><span class="special">(</span><span class="identifier">expr</span><span class="special">)))};</span>
<span class="special">}</span> <span class="keyword">else</span> <span class="special">{</span>
<span class="keyword">using</span> <span class="identifier">I</span> <span class="special">=</span> <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">remove_reference</span><span class="special">&lt;</span><span class="keyword">decltype</span><span class="special">(</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">value</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">left</span><span class="special">(</span><span class="identifier">expr</span><span class="special">)))&gt;::</span><span class="identifier">type</span><span class="special">;</span>
<span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">i</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">llong_c</span><span class="special">&lt;</span><span class="identifier">I</span><span class="special">::</span><span class="identifier">value</span><span class="special">&gt;;</span>
<span class="keyword">return</span> <span class="identifier">let_impl</span><span class="special">(</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">insert</span><span class="special">(</span>
<span class="identifier">map</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">make_pair</span><span class="special">(</span><span class="identifier">i</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">right</span><span class="special">(</span><span class="identifier">expr</span><span class="special">))),</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special">&lt;</span><span class="identifier">Exprs</span><span class="special">&gt;(</span><span class="identifier">exprs</span><span class="special">)...);</span>
<span class="special">}</span>
<span class="special">}</span>
<span class="comment">// Takes N &gt; 0 expressions of the form 'placeholder = expr', and returns an</span>
<span class="comment">// object with an overloaded operator[]().</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Expr</span><span class="special">,</span> <span class="keyword">typename</span><span class="special">...</span> <span class="identifier">Exprs</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="identifier">let</span><span class="special">(</span><span class="identifier">Expr</span> <span class="special">&amp;&amp;</span> <span class="identifier">expr</span><span class="special">,</span> <span class="identifier">Exprs</span> <span class="special">&amp;&amp;...</span> <span class="identifier">exprs</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">let_impl</span><span class="special">(</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">make_map</span><span class="special">(),</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special">&lt;</span><span class="identifier">Expr</span><span class="special">&gt;(</span><span class="identifier">expr</span><span class="special">),</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special">&lt;</span><span class="identifier">Exprs</span><span class="special">&gt;(</span><span class="identifier">exprs</span><span class="special">)...);</span>
<span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span>
<span class="special">{</span>
<span class="comment">// Some handy terminals -- the _a and _b let-placeholders and std::cout as</span>
<span class="comment">// a YAP terminal.</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">&lt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="identifier">let_placeholder</span><span class="special">&lt;</span><span class="number">0</span><span class="special">&gt;&gt;&gt;</span> <span class="keyword">const</span> <span class="identifier">_a</span><span class="special">;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expression</span><span class="special">&lt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">terminal</span><span class="special">,</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="identifier">let_placeholder</span><span class="special">&lt;</span><span class="number">1</span><span class="special">&gt;&gt;&gt;</span> <span class="keyword">const</span> <span class="identifier">_b</span><span class="special">;</span>
<span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">cout</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">make_terminal</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">);</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">literals</span><span class="special">;</span>
<span class="special">{</span>
<span class="keyword">auto</span> <span class="identifier">expr</span> <span class="special">=</span> <span class="identifier">let</span><span class="special">(</span><span class="identifier">_a</span> <span class="special">=</span> <span class="number">2</span><span class="special">)[</span><span class="identifier">_a</span> <span class="special">+</span> <span class="number">1</span><span class="special">];</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">evaluate</span><span class="special">(</span><span class="identifier">expr</span><span class="special">)</span> <span class="special">==</span> <span class="number">3</span><span class="special">);</span>
<span class="special">}</span>
<span class="special">{</span>
<span class="keyword">auto</span> <span class="identifier">expr</span> <span class="special">=</span> <span class="identifier">let</span><span class="special">(</span><span class="identifier">_a</span> <span class="special">=</span> <span class="number">123</span><span class="special">,</span> <span class="identifier">_b</span> <span class="special">=</span> <span class="number">456</span><span class="special">)[</span><span class="identifier">_a</span> <span class="special">+</span> <span class="identifier">_b</span><span class="special">];</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">evaluate</span><span class="special">(</span><span class="identifier">expr</span><span class="special">)</span> <span class="special">==</span> <span class="number">123</span> <span class="special">+</span> <span class="number">456</span><span class="special">);</span>
<span class="special">}</span>
<span class="comment">// This prints out "0 0", because 'i' is passed as an lvalue, so its</span>
<span class="comment">// decrement is visible outside the let expression.</span>
<span class="special">{</span>
<span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">1</span><span class="special">;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">evaluate</span><span class="special">(</span><span class="identifier">let</span><span class="special">(</span><span class="identifier">_a</span> <span class="special">=</span> <span class="number">1</span><span class="identifier">_p</span><span class="special">)[</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="special">--</span><span class="identifier">_a</span> <span class="special">&lt;&lt;</span> <span class="char">' '</span><span class="special">],</span> <span class="identifier">i</span><span class="special">);</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">i</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="special">}</span>
<span class="comment">// Prints "Hello, World" due to let()'s scoping rules.</span>
<span class="special">{</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">evaluate</span><span class="special">(</span>
<span class="identifier">let</span><span class="special">(</span><span class="identifier">_a</span> <span class="special">=</span> <span class="number">1</span><span class="identifier">_p</span><span class="special">,</span> <span class="identifier">_b</span> <span class="special">=</span> <span class="number">2</span><span class="identifier">_p</span><span class="special">)</span>
<span class="special">[</span>
<span class="comment">// _a here is an int: 1</span>
<span class="identifier">let</span><span class="special">(</span><span class="identifier">_a</span> <span class="special">=</span> <span class="number">3</span><span class="identifier">_p</span><span class="special">)</span> <span class="comment">// hides the outer _a</span>
<span class="special">[</span>
<span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">_a</span> <span class="special">&lt;&lt;</span> <span class="identifier">_b</span> <span class="comment">// prints "Hello, World"</span>
<span class="special">]</span>
<span class="special">],</span>
<span class="number">1</span><span class="special">,</span> <span class="string">" World"</span><span class="special">,</span> <span class="string">"Hello,"</span>
<span class="special">);</span>
<span class="special">}</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"\n"</span><span class="special">;</span>
<span class="comment">// Due to the macro-substitution style that this example uses, this prints</span>
<span class="comment">// "3132". Phoenix's let() prints "312", because it only evaluates '1_p</span>
<span class="comment">// &lt;&lt; 3' once.</span>
<span class="special">{</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">yap</span><span class="special">::</span><span class="identifier">evaluate</span><span class="special">(</span>
<span class="identifier">let</span><span class="special">(</span><span class="identifier">_a</span> <span class="special">=</span> <span class="number">1</span><span class="identifier">_p</span> <span class="special">&lt;&lt;</span> <span class="number">3</span><span class="special">)</span>
<span class="special">[</span>
<span class="identifier">_a</span> <span class="special">&lt;&lt;</span> <span class="string">"1"</span><span class="special">,</span> <span class="identifier">_a</span> <span class="special">&lt;&lt;</span> <span class="string">"2"</span>
<span class="special">],</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span>
<span class="special">);</span>
<span class="special">}</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"\n"</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
</p>
</div>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_yap.manual.header_organization"></a><a class="link" href="manual.html#boost_yap.manual.header_organization" title="Header Organization">Header Organization</a>
</h3></div></div></div>
<p>
The main header you will always need to use Boost.YAP is the <code class="computeroutput"><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">yap</span><span class="special">/</span><span class="identifier">algorithm</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span></code>
header. If you want to ensure that you don't accidentally use <code class="computeroutput"><a class="link" href="../boost/yap/expression.html" title="Struct template expression">expression&lt;&gt;</a></code> (which I recommend),
just include this header and nothing else.
</p>
<p>
If you want to use the <code class="computeroutput"><a class="link" href="../boost/yap/expression.html" title="Struct template expression">expression&lt;&gt;</a></code>
reference expression template (great for prototyping, but not recommended
for production work), include the <code class="computeroutput"><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">yap</span><span class="special">/</span><span class="identifier">expression</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span></code>
header.
</p>
<p>
If you want to include all of the above, use the <code class="computeroutput"><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">yap</span><span class="special">/</span><span class="identifier">yap</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span></code>
header.
</p>
<p>
If you want to use <code class="computeroutput"><a class="link" href="../boost/yap/print.html" title="Function template print">print()</a></code>, include the <code class="computeroutput"><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">yap</span><span class="special">/</span><span class="identifier">print</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span></code>
header; this header is not included in the <code class="computeroutput"><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">yap</span><span class="special">/</span><span class="identifier">yap</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span></code>
header.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_yap.manual.configuration"></a><a class="link" href="manual.html#boost_yap.manual.configuration" title="Configuration">Configuration</a>
</h3></div></div></div>
<p>
<code class="computeroutput"><a class="link" href="../BOOST_NO_CONSTEXPR_IF.html" title="Macro BOOST_NO_CONSTEXPR_IF">BOOST_NO_CONSTEXPR_IF</a></code>
is a macro that indicates whether the compiler has support for constexpr
if. It defaults to no. Define it to be a nonzero value if your compiler has
constexpr if support. Note that this is a temporary hack; this should eventually
be a Boost-wide macro.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_yap.manual.object_code"></a><a class="link" href="manual.html#boost_yap.manual.object_code" title="Object Code">Object Code</a>
</h3></div></div></div>
<p>
Let's look at some assembly. All assembly here was produced with Clang 4.0
with <code class="computeroutput"><span class="special">-</span><span class="identifier">O3</span></code>.
Given these definitions:
</p>
<p>
</p>
<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">user</span> <span class="special">{</span>
<span class="keyword">struct</span> <span class="identifier">number</span>
<span class="special">{</span>
<span class="keyword">double</span> <span class="identifier">value</span><span class="special">;</span>
<span class="keyword">friend</span> <span class="identifier">number</span> <span class="keyword">operator</span><span class="special">+(</span><span class="identifier">number</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">number</span> <span class="identifier">rhs</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">number</span><span class="special">{</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">value</span> <span class="special">+</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">value</span><span class="special">};</span>
<span class="special">}</span>
<span class="keyword">friend</span> <span class="identifier">number</span> <span class="keyword">operator</span><span class="special">*(</span><span class="identifier">number</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">number</span> <span class="identifier">rhs</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">number</span><span class="special">{</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">value</span> <span class="special">*</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">value</span><span class="special">};</span>
<span class="special">}</span>
<span class="special">};</span>
<span class="special">}</span>
</pre>
<p>
</p>
<p>
Here is a Boost.YAP-based arithmetic function:
</p>
<p>
</p>
<pre class="programlisting"><span class="identifier">user</span><span class="special">::</span><span class="identifier">number</span> <span class="identifier">eval_as_yap_expr</span><span class="special">(</span><span class="identifier">user</span><span class="special">::</span><span class="identifier">number</span> <span class="identifier">a_</span><span class="special">,</span> <span class="identifier">user</span><span class="special">::</span><span class="identifier">number</span> <span class="identifier">x_</span><span class="special">,</span> <span class="identifier">user</span><span class="special">::</span><span class="identifier">number</span> <span class="identifier">y_</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">term</span><span class="special">&lt;</span><span class="identifier">user</span><span class="special">::</span><span class="identifier">number</span><span class="special">&gt;</span> <span class="identifier">a</span><span class="special">{{</span><span class="identifier">a_</span><span class="special">}};</span>
<span class="identifier">term</span><span class="special">&lt;</span><span class="identifier">user</span><span class="special">::</span><span class="identifier">number</span><span class="special">&gt;</span> <span class="identifier">x</span><span class="special">{{</span><span class="identifier">x_</span><span class="special">}};</span>
<span class="identifier">term</span><span class="special">&lt;</span><span class="identifier">user</span><span class="special">::</span><span class="identifier">number</span><span class="special">&gt;</span> <span class="identifier">y</span><span class="special">{{</span><span class="identifier">y_</span><span class="special">}};</span>
<span class="keyword">auto</span> <span class="identifier">expr</span> <span class="special">=</span> <span class="special">(</span><span class="identifier">a</span> <span class="special">*</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">y</span><span class="special">)</span> <span class="special">*</span> <span class="special">(</span><span class="identifier">a</span> <span class="special">*</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">y</span><span class="special">)</span> <span class="special">+</span> <span class="special">(</span><span class="identifier">a</span> <span class="special">*</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">y</span><span class="special">);</span>
<span class="keyword">return</span> <span class="identifier">yap</span><span class="special">::</span><span class="identifier">evaluate</span><span class="special">(</span><span class="identifier">expr</span><span class="special">);</span>
<span class="special">}</span>
</pre>
<p>
</p>
<p>
and the assembly it produces:
</p>
<pre class="programlisting"><span class="identifier">arithmetic_perf</span><span class="special">[</span><span class="number">0</span><span class="identifier">x100001c00</span><span class="special">]</span> <span class="special">&lt;+</span><span class="number">0</span><span class="special">&gt;:</span> <span class="identifier">pushq</span> <span class="special">%</span><span class="identifier">rbp</span>
<span class="identifier">arithmetic_perf</span><span class="special">[</span><span class="number">0</span><span class="identifier">x100001c01</span><span class="special">]</span> <span class="special">&lt;+</span><span class="number">1</span><span class="special">&gt;:</span> <span class="identifier">movq</span> <span class="special">%</span><span class="identifier">rsp</span><span class="special">,</span> <span class="special">%</span><span class="identifier">rbp</span>
<span class="identifier">arithmetic_perf</span><span class="special">[</span><span class="number">0</span><span class="identifier">x100001c04</span><span class="special">]</span> <span class="special">&lt;+</span><span class="number">4</span><span class="special">&gt;:</span> <span class="identifier">mulsd</span> <span class="special">%</span><span class="identifier">xmm1</span><span class="special">,</span> <span class="special">%</span><span class="identifier">xmm0</span>
<span class="identifier">arithmetic_perf</span><span class="special">[</span><span class="number">0</span><span class="identifier">x100001c08</span><span class="special">]</span> <span class="special">&lt;+</span><span class="number">8</span><span class="special">&gt;:</span> <span class="identifier">addsd</span> <span class="special">%</span><span class="identifier">xmm2</span><span class="special">,</span> <span class="special">%</span><span class="identifier">xmm0</span>
<span class="identifier">arithmetic_perf</span><span class="special">[</span><span class="number">0</span><span class="identifier">x100001c0c</span><span class="special">]</span> <span class="special">&lt;+</span><span class="number">12</span><span class="special">&gt;:</span> <span class="identifier">movapd</span> <span class="special">%</span><span class="identifier">xmm0</span><span class="special">,</span> <span class="special">%</span><span class="identifier">xmm1</span>
<span class="identifier">arithmetic_perf</span><span class="special">[</span><span class="number">0</span><span class="identifier">x100001c10</span><span class="special">]</span> <span class="special">&lt;+</span><span class="number">16</span><span class="special">&gt;:</span> <span class="identifier">mulsd</span> <span class="special">%</span><span class="identifier">xmm1</span><span class="special">,</span> <span class="special">%</span><span class="identifier">xmm1</span>
<span class="identifier">arithmetic_perf</span><span class="special">[</span><span class="number">0</span><span class="identifier">x100001c14</span><span class="special">]</span> <span class="special">&lt;+</span><span class="number">20</span><span class="special">&gt;:</span> <span class="identifier">addsd</span> <span class="special">%</span><span class="identifier">xmm0</span><span class="special">,</span> <span class="special">%</span><span class="identifier">xmm1</span>
<span class="identifier">arithmetic_perf</span><span class="special">[</span><span class="number">0</span><span class="identifier">x100001c18</span><span class="special">]</span> <span class="special">&lt;+</span><span class="number">24</span><span class="special">&gt;:</span> <span class="identifier">movapd</span> <span class="special">%</span><span class="identifier">xmm1</span><span class="special">,</span> <span class="special">%</span><span class="identifier">xmm0</span>
<span class="identifier">arithmetic_perf</span><span class="special">[</span><span class="number">0</span><span class="identifier">x100001c1c</span><span class="special">]</span> <span class="special">&lt;+</span><span class="number">28</span><span class="special">&gt;:</span> <span class="identifier">popq</span> <span class="special">%</span><span class="identifier">rbp</span>
<span class="identifier">arithmetic_perf</span><span class="special">[</span><span class="number">0</span><span class="identifier">x100001c1d</span><span class="special">]</span> <span class="special">&lt;+</span><span class="number">29</span><span class="special">&gt;:</span> <span class="identifier">retq</span>
</pre>
<p>
And for the equivalent function using builtin expressions:
</p>
<p>
</p>
<pre class="programlisting"><span class="identifier">user</span><span class="special">::</span><span class="identifier">number</span> <span class="identifier">eval_as_cpp_expr</span><span class="special">(</span><span class="identifier">user</span><span class="special">::</span><span class="identifier">number</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">user</span><span class="special">::</span><span class="identifier">number</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">user</span><span class="special">::</span><span class="identifier">number</span> <span class="identifier">y</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="special">(</span><span class="identifier">a</span> <span class="special">*</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">y</span><span class="special">)</span> <span class="special">*</span> <span class="special">(</span><span class="identifier">a</span> <span class="special">*</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">y</span><span class="special">)</span> <span class="special">+</span> <span class="special">(</span><span class="identifier">a</span> <span class="special">*</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">y</span><span class="special">);</span>
<span class="special">}</span>
</pre>
<p>
</p>
<p>
the assembly is:
</p>
<pre class="programlisting"><span class="identifier">arithmetic_perf</span><span class="special">[</span><span class="number">0</span><span class="identifier">x100001e10</span><span class="special">]</span> <span class="special">&lt;+</span><span class="number">0</span><span class="special">&gt;:</span> <span class="identifier">pushq</span> <span class="special">%</span><span class="identifier">rbp</span>
<span class="identifier">arithmetic_perf</span><span class="special">[</span><span class="number">0</span><span class="identifier">x100001e11</span><span class="special">]</span> <span class="special">&lt;+</span><span class="number">1</span><span class="special">&gt;:</span> <span class="identifier">movq</span> <span class="special">%</span><span class="identifier">rsp</span><span class="special">,</span> <span class="special">%</span><span class="identifier">rbp</span>
<span class="identifier">arithmetic_perf</span><span class="special">[</span><span class="number">0</span><span class="identifier">x100001e14</span><span class="special">]</span> <span class="special">&lt;+</span><span class="number">4</span><span class="special">&gt;:</span> <span class="identifier">mulsd</span> <span class="special">%</span><span class="identifier">xmm1</span><span class="special">,</span> <span class="special">%</span><span class="identifier">xmm0</span>
<span class="identifier">arithmetic_perf</span><span class="special">[</span><span class="number">0</span><span class="identifier">x100001e18</span><span class="special">]</span> <span class="special">&lt;+</span><span class="number">8</span><span class="special">&gt;:</span> <span class="identifier">addsd</span> <span class="special">%</span><span class="identifier">xmm2</span><span class="special">,</span> <span class="special">%</span><span class="identifier">xmm0</span>
<span class="identifier">arithmetic_perf</span><span class="special">[</span><span class="number">0</span><span class="identifier">x100001e1c</span><span class="special">]</span> <span class="special">&lt;+</span><span class="number">12</span><span class="special">&gt;:</span> <span class="identifier">movapd</span> <span class="special">%</span><span class="identifier">xmm0</span><span class="special">,</span> <span class="special">%</span><span class="identifier">xmm1</span>
<span class="identifier">arithmetic_perf</span><span class="special">[</span><span class="number">0</span><span class="identifier">x100001e20</span><span class="special">]</span> <span class="special">&lt;+</span><span class="number">16</span><span class="special">&gt;:</span> <span class="identifier">mulsd</span> <span class="special">%</span><span class="identifier">xmm1</span><span class="special">,</span> <span class="special">%</span><span class="identifier">xmm1</span>
<span class="identifier">arithmetic_perf</span><span class="special">[</span><span class="number">0</span><span class="identifier">x100001e24</span><span class="special">]</span> <span class="special">&lt;+</span><span class="number">20</span><span class="special">&gt;:</span> <span class="identifier">addsd</span> <span class="special">%</span><span class="identifier">xmm0</span><span class="special">,</span> <span class="special">%</span><span class="identifier">xmm1</span>
<span class="identifier">arithmetic_perf</span><span class="special">[</span><span class="number">0</span><span class="identifier">x100001e28</span><span class="special">]</span> <span class="special">&lt;+</span><span class="number">24</span><span class="special">&gt;:</span> <span class="identifier">movapd</span> <span class="special">%</span><span class="identifier">xmm1</span><span class="special">,</span> <span class="special">%</span><span class="identifier">xmm0</span>
<span class="identifier">arithmetic_perf</span><span class="special">[</span><span class="number">0</span><span class="identifier">x100001e2c</span><span class="special">]</span> <span class="special">&lt;+</span><span class="number">28</span><span class="special">&gt;:</span> <span class="identifier">popq</span> <span class="special">%</span><span class="identifier">rbp</span>
<span class="identifier">arithmetic_perf</span><span class="special">[</span><span class="number">0</span><span class="identifier">x100001e2d</span><span class="special">]</span> <span class="special">&lt;+</span><span class="number">29</span><span class="special">&gt;:</span> <span class="identifier">retq</span>
</pre>
<p>
If we increase the number of terminals by a factor of four:
</p>
<p>
</p>
<pre class="programlisting"><span class="identifier">user</span><span class="special">::</span><span class="identifier">number</span>
<span class="identifier">eval_as_yap_expr_4x</span><span class="special">(</span><span class="identifier">user</span><span class="special">::</span><span class="identifier">number</span> <span class="identifier">a_</span><span class="special">,</span> <span class="identifier">user</span><span class="special">::</span><span class="identifier">number</span> <span class="identifier">x_</span><span class="special">,</span> <span class="identifier">user</span><span class="special">::</span><span class="identifier">number</span> <span class="identifier">y_</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">term</span><span class="special">&lt;</span><span class="identifier">user</span><span class="special">::</span><span class="identifier">number</span><span class="special">&gt;</span> <span class="identifier">a</span><span class="special">{{</span><span class="identifier">a_</span><span class="special">}};</span>
<span class="identifier">term</span><span class="special">&lt;</span><span class="identifier">user</span><span class="special">::</span><span class="identifier">number</span><span class="special">&gt;</span> <span class="identifier">x</span><span class="special">{{</span><span class="identifier">x_</span><span class="special">}};</span>
<span class="identifier">term</span><span class="special">&lt;</span><span class="identifier">user</span><span class="special">::</span><span class="identifier">number</span><span class="special">&gt;</span> <span class="identifier">y</span><span class="special">{{</span><span class="identifier">y_</span><span class="special">}};</span>
<span class="keyword">auto</span> <span class="identifier">expr</span> <span class="special">=</span> <span class="special">(</span><span class="identifier">a</span> <span class="special">*</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">y</span><span class="special">)</span> <span class="special">*</span> <span class="special">(</span><span class="identifier">a</span> <span class="special">*</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">y</span><span class="special">)</span> <span class="special">+</span> <span class="special">(</span><span class="identifier">a</span> <span class="special">*</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">y</span><span class="special">)</span> <span class="special">+</span>
<span class="special">(</span><span class="identifier">a</span> <span class="special">*</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">y</span><span class="special">)</span> <span class="special">*</span> <span class="special">(</span><span class="identifier">a</span> <span class="special">*</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">y</span><span class="special">)</span> <span class="special">+</span> <span class="special">(</span><span class="identifier">a</span> <span class="special">*</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">y</span><span class="special">)</span> <span class="special">+</span>
<span class="special">(</span><span class="identifier">a</span> <span class="special">*</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">y</span><span class="special">)</span> <span class="special">*</span> <span class="special">(</span><span class="identifier">a</span> <span class="special">*</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">y</span><span class="special">)</span> <span class="special">+</span> <span class="special">(</span><span class="identifier">a</span> <span class="special">*</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">y</span><span class="special">)</span> <span class="special">+</span>
<span class="special">(</span><span class="identifier">a</span> <span class="special">*</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">y</span><span class="special">)</span> <span class="special">*</span> <span class="special">(</span><span class="identifier">a</span> <span class="special">*</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">y</span><span class="special">)</span> <span class="special">+</span> <span class="special">(</span><span class="identifier">a</span> <span class="special">*</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">y</span><span class="special">);</span>
<span class="keyword">return</span> <span class="identifier">yap</span><span class="special">::</span><span class="identifier">evaluate</span><span class="special">(</span><span class="identifier">expr</span><span class="special">);</span>
<span class="special">}</span>
</pre>
<p>
</p>
<p>
the results are the same: in this simple case, the Boost.YAP and builtin
expressions result in the same object code.
</p>
<p>
However, increasing the number of terminals by an additional factor of 2.5
(for a total of 90 terminals), the inliner can no longer do as well for Boost.YAP
expressions as for builtin ones.
</p>
<p>
More complex nonarithmetic code produces more mixed results. For example,
here is a function using code from the Map Assign example:
</p>
<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span> <span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">make_map_with_boost_yap</span> <span class="special">()</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">map_list_of</span>
<span class="special">(</span><span class="string">"&lt;"</span><span class="special">,</span> <span class="number">1</span><span class="special">)</span>
<span class="special">(</span><span class="string">"&lt;="</span><span class="special">,</span><span class="number">2</span><span class="special">)</span>
<span class="special">(</span><span class="string">"&gt;"</span><span class="special">,</span> <span class="number">3</span><span class="special">)</span>
<span class="special">(</span><span class="string">"&gt;="</span><span class="special">,</span><span class="number">4</span><span class="special">)</span>
<span class="special">(</span><span class="string">"="</span><span class="special">,</span> <span class="number">5</span><span class="special">)</span>
<span class="special">(</span><span class="string">"&lt;&gt;"</span><span class="special">,</span><span class="number">6</span><span class="special">)</span>
<span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
By contrast, here is the Boost.Assign version of the same function:
</p>
<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span> <span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">make_map_with_boost_assign</span> <span class="special">()</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">assign</span><span class="special">::</span><span class="identifier">map_list_of</span>
<span class="special">(</span><span class="string">"&lt;"</span><span class="special">,</span> <span class="number">1</span><span class="special">)</span>
<span class="special">(</span><span class="string">"&lt;="</span><span class="special">,</span><span class="number">2</span><span class="special">)</span>
<span class="special">(</span><span class="string">"&gt;"</span><span class="special">,</span> <span class="number">3</span><span class="special">)</span>
<span class="special">(</span><span class="string">"&gt;="</span><span class="special">,</span><span class="number">4</span><span class="special">)</span>
<span class="special">(</span><span class="string">"="</span><span class="special">,</span> <span class="number">5</span><span class="special">)</span>
<span class="special">(</span><span class="string">"&lt;&gt;"</span><span class="special">,</span><span class="number">6</span><span class="special">)</span>
<span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
Here is how you might do it "manually":
</p>
<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span> <span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">make_map_manually</span> <span class="special">()</span>
<span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span> <span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">retval</span><span class="special">;</span>
<span class="identifier">retval</span><span class="special">.</span><span class="identifier">emplace</span><span class="special">(</span><span class="string">"&lt;"</span><span class="special">,</span> <span class="number">1</span><span class="special">);</span>
<span class="identifier">retval</span><span class="special">.</span><span class="identifier">emplace</span><span class="special">(</span><span class="string">"&lt;="</span><span class="special">,</span><span class="number">2</span><span class="special">);</span>
<span class="identifier">retval</span><span class="special">.</span><span class="identifier">emplace</span><span class="special">(</span><span class="string">"&gt;"</span><span class="special">,</span> <span class="number">3</span><span class="special">);</span>
<span class="identifier">retval</span><span class="special">.</span><span class="identifier">emplace</span><span class="special">(</span><span class="string">"&gt;="</span><span class="special">,</span><span class="number">4</span><span class="special">);</span>
<span class="identifier">retval</span><span class="special">.</span><span class="identifier">emplace</span><span class="special">(</span><span class="string">"="</span><span class="special">,</span> <span class="number">5</span><span class="special">);</span>
<span class="identifier">retval</span><span class="special">.</span><span class="identifier">emplace</span><span class="special">(</span><span class="string">"&lt;&gt;"</span><span class="special">,</span><span class="number">6</span><span class="special">);</span>
<span class="keyword">return</span> <span class="identifier">retval</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
Finally, here is the same map created from an initializer list:
</p>
<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span> <span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">make_map_inializer_list</span> <span class="special">()</span>
<span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span> <span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">retval</span> <span class="special">=</span> <span class="special">{</span>
<span class="special">{</span><span class="string">"&lt;"</span><span class="special">,</span> <span class="number">1</span><span class="special">},</span>
<span class="special">{</span><span class="string">"&lt;="</span><span class="special">,</span><span class="number">2</span><span class="special">},</span>
<span class="special">{</span><span class="string">"&gt;"</span><span class="special">,</span> <span class="number">3</span><span class="special">},</span>
<span class="special">{</span><span class="string">"&gt;="</span><span class="special">,</span><span class="number">4</span><span class="special">},</span>
<span class="special">{</span><span class="string">"="</span><span class="special">,</span> <span class="number">5</span><span class="special">},</span>
<span class="special">{</span><span class="string">"&lt;&gt;"</span><span class="special">,</span><span class="number">6</span><span class="special">}</span>
<span class="special">};</span>
<span class="keyword">return</span> <span class="identifier">retval</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
All of these produce roughly the same amount of assembly instructions. Benchmarking
these four functions with Google Benchmark yields these results:
</p>
<div class="table">
<a name="boost_yap.manual.object_code.runtimes_of_different_map_constructions"></a><p class="title"><b>Table 48.5. Runtimes of Different Map Constructions</b></p>
<div class="table-contents"><table class="table" summary="Runtimes of Different Map Constructions">
<colgroup>
<col>
<col>
</colgroup>
<thead><tr>
<th>
<p>
Function
</p>
</th>
<th>
<p>
Time (ns)
</p>
</th>
</tr></thead>
<tbody>
<tr>
<td>
<p>
make_map_with_boost_yap()
</p>
</td>
<td>
<p>
1285
</p>
</td>
</tr>
<tr>
<td>
<p>
make_map_with_boost_assign()
</p>
</td>
<td>
<p>
1459
</p>
</td>
</tr>
<tr>
<td>
<p>
make_map_manually()
</p>
</td>
<td>
<p>
985
</p>
</td>
</tr>
<tr>
<td>
<p>
make_map_inializer_list()
</p>
</td>
<td>
<p>
954
</p>
</td>
</tr>
</tbody>
</table></div>
</div>
<br class="table-break"><p>
The Boost.YAP-based implementation finishes in the middle of the pack.
</p>
<p>
In general, the expression trees produced by Boost.YAP get evaluated down
to something close to the hand-written equivalent. There is an abstraction
penalty, but it is small for reasonably-sized expressions.
</p>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright © 2018 T. Zachary Laine<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../yap.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../yap.html"><img src="../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="concepts.html"><img src="../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>