4779 lines
576 KiB
HTML
4779 lines
576 KiB
HTML
<!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"><</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"><</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">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"><</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">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"><</span><span class="keyword">double</span> <span class="special">(*)(</span><span class="keyword">double</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">expression</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"><</span><span class="keyword">double</span><span class="special">></span>
|
||
<span class="special">></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">expression</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"><</span><span class="keyword">float</span><span class="special">></span>
|
||
<span class="special">></span>
|
||
<span class="special">></span>
|
||
<span class="special">></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"><</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"><</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">></span>
|
||
<span class="special">></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"><></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"><</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"><</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">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"><</span><span class="keyword">double</span> <span class="special">(*)(</span><span class="keyword">double</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">expression</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"><</span><span class="keyword">double</span><span class="special">></span>
|
||
<span class="special">></span>
|
||
<span class="special">></span>
|
||
<span class="special">>,</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"><</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"><</span><span class="keyword">float</span><span class="special">></span>
|
||
<span class="special">></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"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></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"><</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">>;</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"><</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"><</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">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"><</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">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"><</span><span class="keyword">double</span> <span class="special">(*)(</span><span class="keyword">double</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">expression</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"><</span><span class="keyword">double</span><span class="special">></span>
|
||
<span class="special">></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">expression</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"><</span><span class="keyword">float</span><span class="special">></span>
|
||
<span class="special">></span>
|
||
<span class="special">></span>
|
||
<span class="special">></span>
|
||
<span class="identifier">yap_expr</span> <span class="special">=</span> <span class="identifier">term</span><span class="special"><</span><span class="keyword">double</span> <span class="special">(*)(</span><span class="keyword">double</span><span class="special">)>{{</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<></a></code>.
|
||
<code class="computeroutput"><a class="link" href="../boost/yap/expression.html" title="Struct template expression">expression<></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<></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<></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<></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<></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"><+></span>
|
||
<span class="identifier">expr</span><span class="special"><()></span>
|
||
<span class="identifier">term</span><span class="special"><</span><span class="keyword">double</span> <span class="special">(*)(</span><span class="keyword">double</span><span class="special">)>[=</span><span class="number">1</span><span class="special">]</span>
|
||
<span class="identifier">term</span><span class="special"><</span><span class="keyword">double</span><span class="special">>[=</span><span class="number">3</span><span class="special">]</span>
|
||
<span class="identifier">term</span><span class="special"><</span><span class="keyword">float</span><span class="special">>[=</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">&</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"><</span><span class="keyword">int</span><span class="special">></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"><</span><span class="keyword">int</span><span class="special">></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"><</span><span class="keyword">long</span> <span class="keyword">long</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</span><span class="special"><</span><span class="identifier">I</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"><</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">yap</span><span class="special">::</span><span class="identifier">placeholder</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">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">llong_c</span><span class="special"><</span><span class="identifier">I</span><span class="special">>;</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"><</span><span class="keyword">typename</span> <span class="identifier">T</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">expr_tag</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">T</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="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"><</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">></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"><</span><span class="identifier">Kind</span><span class="special">>,</span> <span class="identifier">Arg</span> <span class="special">&&...</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"><</span><span class="identifier">Arg</span><span class="special">>(</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"><></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"><></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"><</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">></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"><</span><span class="identifier">minimal_expr</span><span class="special">>(</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"><</span><span class="identifier">minimal_expr</span><span class="special">>(</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"><</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">>(</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"><<</span> <span class="identifier">result</span> <span class="special"><<</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"><...></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"><...></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"><></span></code>,
|
||
<code class="computeroutput"><span class="identifier">expr</span><span class="special"><></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"><<=()</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<></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"><</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">></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"><</span><span class="keyword">long</span> <span class="keyword">long</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</span><span class="special"><</span><span class="identifier">I</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"><</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">yap</span><span class="special">::</span><span class="identifier">placeholder</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">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">llong_c</span><span class="special"><</span><span class="identifier">I</span><span class="special">>;</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"><</span><span class="keyword">typename</span> <span class="identifier">T</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">expr_tag</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">T</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="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"><</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">></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"><</span><span class="identifier">Kind</span><span class="special">>,</span> <span class="identifier">Arg</span> <span class="special">&&...</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"><</span><span class="identifier">Arg</span><span class="special">>(</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"><</span><span class="keyword">typename</span> <span class="identifier">T</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">expr_tag</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">vector</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">const</span> <span class="special">&</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 -> transform(left).</span>
|
||
<span class="keyword">template</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">U</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">future_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">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"><</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">U</span><span class="special">></span>
|
||
<span class="special">></span> <span class="keyword">const</span> <span class="special">&</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"><</span><span class="keyword">typename</span> <span class="identifier">Range</span><span class="special">></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"><</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">algorithm_t</span> <span class="identifier">a</span><span class="special">,</span>
|
||
<span class="identifier">Range</span> <span class="special">&</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">&</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">&</span></code>,
|
||
<code class="computeroutput"><span class="keyword">int</span> <span class="keyword">const</span>
|
||
<span class="special">&</span></code>, <code class="computeroutput"><span class="keyword">float</span>
|
||
<span class="special">&&</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"><</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">></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"><</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">comma</span><span class="special">>,</span> <span class="identifier">T</span> <span class="special">&&</span> <span class="identifier">t</span><span class="special">,</span> <span class="identifier">U</span> <span class="special">&&</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"><</span><span class="identifier">minimal_expr</span><span class="special">>(</span><span class="keyword">static_cast</span><span class="special"><</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="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"><</span><span class="identifier">minimal_expr</span><span class="special">>(</span><span class="keyword">static_cast</span><span class="special"><</span><span class="identifier">U</span> <span class="special">&&>(</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"><</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">></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"><</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">call</span><span class="special">>,</span> <span class="identifier">Callable</span> <span class="special">&&</span> <span class="identifier">callable</span><span class="special">,</span> <span class="identifier">Args</span> <span class="special">&&...</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"><</span><span class="identifier">minimal_expr</span><span class="special">>(</span><span class="keyword">static_cast</span><span class="special"><</span><span class="identifier">Callable</span> <span class="special">&&>(</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"><</span><span class="identifier">minimal_expr</span><span class="special">>(</span><span class="keyword">static_cast</span><span class="special"><</span><span class="identifier">Args</span> <span class="special">&&>(</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"><></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"><></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"><></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"><></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<></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">&</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"><<</span> <span class="identifier">i</span> <span class="special"><<</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">&</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">expr_tmpl</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"><</span><span class="identifier">PARTIAL_DECAY</span><span class="special">(</span><span class="identifier">T</span><span class="special">)>></span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">T</span> <span class="special">&</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">expr_tmpl</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"><</span><span class="identifier">PARTIAL_DECAY</span><span class="special">(</span><span class="identifier">T</span><span class="special">)>></span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">T</span> <span class="special">&&</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">expr_tmpl</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"><</span><span class="identifier">PARTIAL_DECAY</span><span class="special">(</span><span class="identifier">T</span><span class="special">)>></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">&</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">expr_tmpl</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">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special"><</span><span class="identifier">E</span> <span class="keyword">const</span>
|
||
<span class="special">&>></span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">E</span> <span class="special">&</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">expr_tmpl</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">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">tuple</span><span class="special"><</span><span class="identifier">E</span> <span class="special">&>></span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">E</span> <span class="special">&&</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"><</span><span class="identifier">expr_kind</span><span class="special">::</span><span class="identifier">expr_ref</span><span class="special">,</span>
|
||
<span class="special">...></span> <span class="keyword">const</span>
|
||
<span class="special">&</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">expr_tmpl</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="special">...></span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">expr_tmpl</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="special">...></span> <span class="special">&</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">expr_tmpl</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="special">...></span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">expr_tmpl</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="special">...></span> <span class="special">&&</span></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">expr_tmpl</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="special">...></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"><</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">></span>
|
||
</pre>
|
||
<p>
|
||
You must include <code class="computeroutput"><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">print</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></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<->
|
||
expr<+>
|
||
term<boost::yap::placeholder<4ll>>[=4]
|
||
expr<*>
|
||
term<double &>[=1]
|
||
term<thing>[=<<unprintable-value>>] &
|
||
term<char const*>[=lvalue terminal] const &
|
||
</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"><</span><span class="identifier">op</span><span class="special">></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"><</span><span class="identifier">T</span><span class="special">></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">&</span></code> or <code class="computeroutput"><span class="keyword">const</span>
|
||
<span class="special">&</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"><<(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span> <span class="special">&,</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"><<</span><span class="identifier">unprintable</span><span class="special">-</span><span class="identifier">value</span><span class="special">>></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"><</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">></span>
|
||
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">iostream</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">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"><<</span> <span class="string">"Hello"</span> <span class="special"><<</span> <span class="char">','</span> <span class="special"><<</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"><</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">></span>
|
||
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">iostream</span><span class="special">></span>
|
||
|
||
|
||
<span class="keyword">template</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="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">></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"><</span><span class="keyword">typename</span> <span class="identifier">T</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="keyword">operator</span><span class="special"><<</span> <span class="special">(</span><span class="identifier">T</span> <span class="special">&&</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"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span><span class="identifier">T</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">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"><</span><span class="identifier">stream_expr</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">cout</span> <span class="special"><<</span> <span class="string">"Hello"</span> <span class="special"><<</span> <span class="char">','</span> <span class="special"><<</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"><</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">></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"><</span><span class="identifier">minimal_expr</span><span class="special">>(</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"><</span><span class="identifier">minimal_expr</span><span class="special">>(</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"><</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">>(</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"><<</span> <span class="identifier">result</span> <span class="special"><<</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"><</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">></span>
|
||
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">iostream</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">// Displays "5"</span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</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"><<</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"><<</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"><<</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"><<</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"><<</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"><</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">></span>
|
||
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">iostream</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="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">&&...</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">&&...</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">&&...</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"><<</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"><<</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"><<</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"><<</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"><<</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"><<</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"><</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">></span>
|
||
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">iostream</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">// Displays "5"</span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</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"><<</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"><<</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"><<</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"><<</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"><<</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"><</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">></span>
|
||
|
||
<span class="preprocessor">#include</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">maximum</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">iostream</span><span class="special">></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"><</span><span class="keyword">long</span> <span class="keyword">long</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</span><span class="special"><</span><span class="identifier">I</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"><</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">yap</span><span class="special">::</span><span class="identifier">placeholder</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">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">llong_c</span><span class="special"><</span><span class="identifier">I</span><span class="special">>;</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"><</span><span class="keyword">typename</span> <span class="identifier">T</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">expr_tag</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">T</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="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"><</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">></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"><</span><span class="identifier">Kind</span><span class="special">>,</span> <span class="identifier">Arg</span> <span class="special">&&...</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"><</span><span class="identifier">Arg</span><span class="special">>(</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">&&...</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">&&...</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">&&...</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"><<</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"><<</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"><<</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"><<</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"><<</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"><<</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 << expr_3_fn(3.0) << std::endl;</span>
|
||
|
||
<span class="comment">// Static-asserts with "Called with wrong number of args."</span>
|
||
<span class="comment">//std::cout << expr_3_fn(3.0, 2.0, 1.0) << 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"><</span><span class="keyword">double</span><span class="special">></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"><</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">></span>
|
||
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">algorithm</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">cassert</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">iostream</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">vector</span><span class="special">></span>
|
||
|
||
|
||
<span class="keyword">template</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="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">></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<double> 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"><</span><span class="identifier">lazy_vector_expr</span><span class="special">,</span> <span class="keyword">double</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"><</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"><</span><span class="keyword">double</span><span class="special">>></span> <span class="keyword">const</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">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"><</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">></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"><</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">></span>
|
||
<span class="keyword">auto</span> <span class="identifier">lazy_vector_expr</span><span class="special"><</span><span class="identifier">Kind</span><span class="special">,</span> <span class="identifier">Tuple</span><span class="special">>::</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"><</span><span class="identifier">lazy_vector_expr</span><span class="special">,</span> <span class="keyword">double</span><span class="special">></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"><</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"><</span><span class="keyword">double</span><span class="special">>></span> <span class="keyword">const</span> <span class="special">&</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"><</span><span class="identifier">lazy_vector_expr</span><span class="special">,</span> <span class="keyword">double</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="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"><</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"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="keyword">double</span><span class="special">>></span>
|
||
<span class="special">></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"><</span><span class="keyword">double</span><span class="special">></span> <span class="special">&&</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"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="keyword">double</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">vec</span><span class="special">));</span> <span class="special">}</span>
|
||
|
||
<span class="keyword">template</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="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">></span>
|
||
<span class="identifier">lazy_vector</span> <span class="special">&</span> <span class="keyword">operator</span><span class="special">+=</span> <span class="special">(</span><span class="identifier">lazy_vector_expr</span><span class="special"><</span><span class="identifier">Kind</span><span class="special">,</span> <span class="identifier">Tuple</span><span class="special">></span> <span class="keyword">const</span> <span class="special">&</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"><</span><span class="keyword">double</span><span class="special">></span> <span class="special">&</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"><</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"><</span><span class="keyword">double</span><span class="special">>(</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"><</span><span class="keyword">double</span><span class="special">>(</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"><</span><span class="keyword">double</span><span class="special">>(</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"><<</span> <span class="identifier">d1</span> <span class="special"><<</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"><<</span> <span class="char">'{'</span> <span class="special"><<</span> <span class="identifier">v1</span><span class="special">[</span><span class="number">0</span><span class="special">]</span> <span class="special"><<</span> <span class="char">','</span> <span class="special"><<</span> <span class="identifier">v1</span><span class="special">[</span><span class="number">1</span><span class="special">]</span>
|
||
<span class="special"><<</span> <span class="char">','</span> <span class="special"><<</span> <span class="identifier">v1</span><span class="special">[</span><span class="number">2</span><span class="special">]</span> <span class="special"><<</span> <span class="char">','</span> <span class="special"><<</span> <span class="identifier">v1</span><span class="special">[</span><span class="number">3</span><span class="special">]</span> <span class="special"><<</span> <span class="char">'}'</span> <span class="special"><<</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"><</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">></span>
|
||
|
||
<span class="preprocessor">#include</span> <span class="special"><</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">></span>
|
||
<span class="preprocessor">#include</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">fold</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
<span class="preprocessor">#include</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">maximum</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">algorithm</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">cassert</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">iostream</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">vector</span><span class="special">></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"><</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"><</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">&</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"><</span><span class="keyword">double</span><span class="special">></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">&</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"><</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"><</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">&</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">&</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">matrix</span> <span class="keyword">const</span> <span class="special">&</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"><</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"><</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">&</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">&</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">matrix</span> <span class="special">&</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"><</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"><</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"><</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">></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"><</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">></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"><</span><span class="identifier">Kind</span><span class="special">,</span> <span class="identifier">Tuple</span><span class="special">></span> <span class="keyword">const</span> <span class="special">&</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"><</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">></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"><</span><span class="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">></span>
|
||
<span class="keyword">struct</span> <span class="identifier">self_evaluating_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">assign</span><span class="special">,</span> <span class="identifier">Tuple</span><span class="special">></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"><</span><span class="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">></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"><</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">self_evaluating_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">multiplies</span><span class="special">,</span> <span class="identifier">Tuple</span><span class="special">></span> <span class="keyword">const</span> <span class="special">&</span> <span class="identifier">expr</span><span class="special">,</span>
|
||
<span class="identifier">matrix</span> <span class="special">&</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"><</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">double</span> <span class="identifier">d</span><span class="special">,</span>
|
||
<span class="identifier">matrix</span> <span class="keyword">const</span> <span class="special">&</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"><</span><span class="keyword">double</span><span class="special">,</span> <span class="identifier">matrix</span> <span class="keyword">const</span> <span class="special">&>(</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"><</span><span class="keyword">decltype</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="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"><</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">></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"><</span><span class="identifier">Kind</span><span class="special">,</span> <span class="identifier">Tuple</span><span class="special">></span> <span class="keyword">const</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="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"><</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">></span>
|
||
<span class="identifier">self_evaluating_expr</span><span class="special"><</span><span class="identifier">Kind</span><span class="special">,</span> <span class="identifier">Tuple</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">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"><</span><span class="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">></span>
|
||
<span class="identifier">self_evaluating_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">assign</span><span class="special">,</span> <span class="identifier">Tuple</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="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"><</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"><</span><span class="identifier">matrix</span><span class="special">></span>
|
||
<span class="special">></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"><</span><span class="identifier">matrix</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">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"><</span><span class="identifier">T</span><span class="special">,</span> <span class="number">3</span><span class="special">></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"><</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">></span>
|
||
<span class="preprocessor">#include</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">print</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">array</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">iostream</span><span class="special">></span>
|
||
|
||
|
||
<span class="keyword">template</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="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">></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"><</span><span class="identifier">tarray_expr</span><span class="special">,</span> <span class="keyword">int</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"><</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"><</span><span class="keyword">int</span><span class="special">,</span> <span class="number">3</span><span class="special">>></span> <span class="keyword">const</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">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"><</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">></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 & and</span>
|
||
<span class="comment">// int & 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"><</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"><</span><span class="keyword">int</span> <span class="keyword">const</span> <span class="special">&>>{}</span> <span class="special">||</span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">is_same</span><span class="special"><</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"><</span><span class="keyword">int</span> <span class="special">&>>{}</span> <span class="special">||</span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">is_same</span><span class="special"><</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"><</span><span class="keyword">int</span><span class="special">>>{}</span> <span class="special">||</span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">is_same</span><span class="special"><</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"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">array</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="number">3</span><span class="special">>>>{},</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"><</span><span class="identifier">tarray_expr</span><span class="special">,</span> <span class="keyword">int</span><span class="special">></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"><</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"><</span><span class="keyword">int</span><span class="special">,</span> <span class="number">3</span><span class="special">>></span> <span class="keyword">const</span> <span class="special">&</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"><</span><span class="identifier">tarray_expr</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="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">&</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">ostream</span> <span class="special">&</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"><</span><span class="identifier">tarray_expr</span><span class="special">,</span> <span class="keyword">int</span><span class="special">></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"><<</span> <span class="char">'{'</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="special"><<</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">&</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">ostream</span> <span class="special">&</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"><</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"><</span><span class="keyword">int</span><span class="special">,</span> <span class="number">3</span><span class="special">>></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"><</span><span class="keyword">int</span><span class="special">,</span> <span class="number">3</span><span class="special">></span> <span class="keyword">const</span> <span class="special">&</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"><<</span> <span class="char">'{'</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="string">", "</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="string">", "</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="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"><</span><span class="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">></span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span> <span class="special">&</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">ostream</span> <span class="special">&</span> <span class="identifier">os</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">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">></span> <span class="keyword">const</span> <span class="special">&</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"><<</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"><</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">></span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span> <span class="special">&</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">ostream</span> <span class="special">&</span> <span class="identifier">os</span><span class="special">,</span> <span class="identifier">tarray_expr</span><span class="special"><</span><span class="identifier">Kind</span><span class="special">,</span> <span class="identifier">Tuple</span><span class="special">></span> <span class="keyword">const</span> <span class="special">&</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"><<</span> <span class="char">'('</span><span class="special">;</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">left</span><span class="special">(</span><span class="identifier">expr</span><span class="special">)</span> <span class="special"><<</span> <span class="string">" "</span> <span class="special"><<</span> <span class="identifier">op_string</span><span class="special">(</span><span class="identifier">Kind</span><span class="special">)</span> <span class="special"><<</span> <span class="string">" "</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">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"><<</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"><</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"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">array</span><span class="special"><</span><span class="keyword">int</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">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"><</span><span class="keyword">int</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="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">&</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">&</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"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span>
|
||
<span class="identifier">tarray</span> <span class="special">&</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">&</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"><</span> <span class="special">::</span><span class="identifier">tarray_expr</span><span class="special">>(</span><span class="identifier">t</span><span class="special">));</span>
|
||
<span class="special">}</span>
|
||
|
||
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Expr</span><span class="special">></span>
|
||
<span class="identifier">tarray</span> <span class="special">&</span> <span class="identifier">printAssign</span> <span class="special">(</span><span class="identifier">Expr</span> <span class="keyword">const</span> <span class="special">&</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"><<</span> <span class="special">*</span><span class="keyword">this</span> <span class="special"><<</span> <span class="string">" = "</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">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"><</span><span class="keyword">typename</span> <span class="identifier">Expr</span><span class="special">></span>
|
||
<span class="identifier">tarray</span> <span class="special">&</span> <span class="identifier">assign</span> <span class="special">(</span><span class="identifier">Expr</span> <span class="keyword">const</span> <span class="special">&</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"><<</span> <span class="identifier">a</span> <span class="special"><<</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"><<</span> <span class="identifier">b</span> <span class="special"><<</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"><<</span> <span class="identifier">c</span> <span class="special"><<</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"><<</span> <span class="identifier">a</span> <span class="special"><<</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"><<</span> <span class="identifier">b</span> <span class="special"><<</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"><<</span> <span class="identifier">c</span> <span class="special"><<</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"><<</span> <span class="identifier">a</span> <span class="special"><<</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"><</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">></span>
|
||
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">array</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">iostream</span><span class="special">></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"><</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"><</span><span class="keyword">int</span><span class="special">,</span> <span class="number">3</span><span class="special">>></span> <span class="keyword">const</span> <span class="special">&</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<> 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"><</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"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">array</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="number">3</span><span class="special">>></span>
|
||
<span class="special">>;</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"><</span><span class="keyword">int</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="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">&</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">&</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"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span>
|
||
<span class="identifier">vec3</span> <span class="special">&</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">&</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"><<</span> <span class="char">'{'</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="string">", "</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="string">", "</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="char">'}'</span> <span class="special"><<</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">&</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"><</span><span class="keyword">typename</span> <span class="identifier">Expr</span><span class="special">></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">&</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"><<</span> <span class="identifier">num</span> <span class="special"><<</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"><<</span> <span class="identifier">num</span> <span class="special"><<</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"><<</span> <span class="identifier">num</span> <span class="special"><<</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"><></span></code>s:
|
||
</p>
|
||
<p>
|
||
</p>
|
||
<pre class="programlisting"><span class="preprocessor">#include</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">yap</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">vector</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">iostream</span><span class="special">></span>
|
||
|
||
|
||
<span class="keyword">struct</span> <span class="identifier">take_nth</span>
|
||
<span class="special">{</span>
|
||
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</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">expr_tag</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">vector</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">const</span> <span class="special">&</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<> 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"><</span><span class="keyword">typename</span> <span class="identifier">T</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">expr_tag</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">vector</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">const</span> <span class="special">&</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"><</span><span class="keyword">typename</span> <span class="identifier">Expr</span><span class="special">></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">&</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"><</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">></span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="special">&</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"><</span><span class="identifier">T</span><span class="special">></span> <span class="special">&</span> <span class="identifier">vec</span><span class="special">,</span> <span class="identifier">Expr</span> <span class="keyword">const</span> <span class="special">&</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"><</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"><</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">></span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="special">&</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"><</span><span class="identifier">T</span><span class="special">></span> <span class="special">&</span> <span class="identifier">vec</span><span class="special">,</span> <span class="identifier">Expr</span> <span class="keyword">const</span> <span class="special">&</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"><</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"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></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"><</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">struct</span> <span class="identifier">is_vector</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">A</span><span class="special">>></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<> 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">// <</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">// ></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">// <=</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">// >=</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">// &&</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">// &</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"><</span><span class="keyword">int</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">d</span><span class="special">;</span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="keyword">double</span><span class="special">></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"><</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"><</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"><</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"><<</span> <span class="string">" a("</span> <span class="special"><<</span> <span class="identifier">i</span> <span class="special"><<</span> <span class="string">") = "</span> <span class="special"><<</span> <span class="identifier">a</span><span class="special">[</span><span class="identifier">i</span><span class="special">]</span>
|
||
<span class="special"><<</span> <span class="string">" b("</span> <span class="special"><<</span> <span class="identifier">i</span> <span class="special"><<</span> <span class="string">") = "</span> <span class="special"><<</span> <span class="identifier">b</span><span class="special">[</span><span class="identifier">i</span><span class="special">]</span>
|
||
<span class="special"><<</span> <span class="string">" c("</span> <span class="special"><<</span> <span class="identifier">i</span> <span class="special"><<</span> <span class="string">") = "</span> <span class="special"><<</span> <span class="identifier">c</span><span class="special">[</span><span class="identifier">i</span><span class="special">]</span>
|
||
<span class="special"><<</span> <span class="string">" d("</span> <span class="special"><<</span> <span class="identifier">i</span> <span class="special"><<</span> <span class="string">") = "</span> <span class="special"><<</span> <span class="identifier">d</span><span class="special">[</span><span class="identifier">i</span><span class="special">]</span>
|
||
<span class="special"><<</span> <span class="string">" e("</span> <span class="special"><<</span> <span class="identifier">i</span> <span class="special"><<</span> <span class="string">") = "</span> <span class="special"><<</span> <span class="identifier">e</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">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"><></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<></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<></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"><></span></code>s
|
||
and <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special"><></span></code>s
|
||
in the same expression.
|
||
</p>
|
||
<p>
|
||
</p>
|
||
<pre class="programlisting"><span class="preprocessor">#include</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">yap</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">complex</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">list</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">vector</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">iostream</span><span class="special">></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"><</span><span class="keyword">typename</span> <span class="identifier">Iter</span><span class="special">></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"><</span><span class="keyword">typename</span> <span class="identifier">Iter</span><span class="special">></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"><</span><span class="identifier">Iter</span><span class="special">>{</span><span class="identifier">it</span><span class="special">};</span> <span class="special">}</span>
|
||
|
||
|
||
<span class="comment">// A container -> 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"><</span><span class="keyword">typename</span> <span class="identifier">Cont</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">expr_tag</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">Cont</span> <span class="keyword">const</span> <span class="special">&</span> <span class="identifier">cont</span><span class="special">)</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">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 -> 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"><</span><span class="keyword">typename</span> <span class="identifier">Iter</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">expr_tag</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">iter_wrapper</span><span class="special"><</span><span class="identifier">Iter</span><span class="special">></span> <span class="identifier">wrapper</span><span class="special">)</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">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"><</span><span class="keyword">typename</span> <span class="identifier">Iter</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">expr_tag</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">iter_wrapper</span><span class="special"><</span><span class="identifier">Iter</span><span class="special">></span> <span class="special">&</span> <span class="identifier">wrapper</span><span class="special">)</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">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"><</span>
|
||
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">class</span><span class="special">,</span> <span class="keyword">class</span><span class="special">></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">></span>
|
||
<span class="identifier">Cont</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">A</span><span class="special">></span> <span class="special">&</span> <span class="identifier">op_assign</span> <span class="special">(</span><span class="identifier">Cont</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">A</span><span class="special">></span> <span class="special">&</span> <span class="identifier">cont</span><span class="special">,</span> <span class="identifier">Expr</span> <span class="keyword">const</span> <span class="special">&</span> <span class="identifier">e</span><span class="special">,</span> <span class="identifier">Op</span> <span class="special">&&</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">&&</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"><</span>
|
||
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">class</span><span class="special">,</span> <span class="keyword">class</span><span class="special">></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="identifier">Cont</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">A</span><span class="special">></span> <span class="special">&</span> <span class="identifier">assign</span> <span class="special">(</span><span class="identifier">Cont</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">A</span><span class="special">></span> <span class="special">&</span> <span class="identifier">cont</span><span class="special">,</span> <span class="identifier">Expr</span> <span class="keyword">const</span> <span class="special">&</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">&</span> <span class="identifier">cont_value</span><span class="special">,</span> <span class="keyword">auto</span> <span class="special">&&</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"><</span><span class="keyword">decltype</span><span class="special">(</span><span class="identifier">expr_value</span><span class="special">)>(</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"><</span>
|
||
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">class</span><span class="special">,</span> <span class="keyword">class</span><span class="special">></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="identifier">Cont</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">A</span><span class="special">></span> <span class="special">&</span> <span class="keyword">operator</span><span class="special">+=</span> <span class="special">(</span><span class="identifier">Cont</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">A</span><span class="special">></span> <span class="special">&</span> <span class="identifier">cont</span><span class="special">,</span> <span class="identifier">Expr</span> <span class="keyword">const</span> <span class="special">&</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">&</span> <span class="identifier">cont_value</span><span class="special">,</span> <span class="keyword">auto</span> <span class="special">&&</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"><</span><span class="keyword">decltype</span><span class="special">(</span><span class="identifier">expr_value</span><span class="special">)>(</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"><</span>
|
||
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">class</span><span class="special">,</span> <span class="keyword">class</span><span class="special">></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="identifier">Cont</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">A</span><span class="special">></span> <span class="special">&</span> <span class="keyword">operator</span><span class="special">-=</span> <span class="special">(</span><span class="identifier">Cont</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">A</span><span class="special">></span> <span class="special">&</span> <span class="identifier">cont</span><span class="special">,</span> <span class="identifier">Expr</span> <span class="keyword">const</span> <span class="special">&</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">&</span> <span class="identifier">cont_value</span><span class="special">,</span> <span class="keyword">auto</span> <span class="special">&&</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"><</span><span class="keyword">decltype</span><span class="special">(</span><span class="identifier">expr_value</span><span class="special">)>(</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"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></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"><</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">struct</span> <span class="identifier">is_mixed</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">A</span><span class="special">>></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"><</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">struct</span> <span class="identifier">is_mixed</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">A</span><span class="special">>></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">// <</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">// ></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">// <=</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">// >=</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">// &&</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">// &</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"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></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"><</span><span class="keyword">int</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">d</span><span class="special">;</span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special"><</span><span class="keyword">double</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">list</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">complex</span><span class="special"><</span><span class="keyword">double</span><span class="special">>></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"><</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"><</span><span class="keyword">double</span><span class="special">>(</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"><</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"><</span><span class="keyword">double</span><span class="special">>(</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"><</span><span class="keyword">double</span><span class="special">>::</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"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">complex</span><span class="special"><</span><span class="keyword">double</span><span class="special">>>::</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"><</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"><<</span> <span class="string">"a("</span> <span class="special"><<</span> <span class="identifier">i</span> <span class="special"><<</span> <span class="string">") = "</span> <span class="special"><<</span> <span class="identifier">a</span><span class="special">[</span><span class="identifier">i</span><span class="special">]</span>
|
||
<span class="special"><<</span> <span class="string">" b("</span> <span class="special"><<</span> <span class="identifier">i</span> <span class="special"><<</span> <span class="string">") = "</span> <span class="special"><<</span> <span class="identifier">b</span><span class="special">[</span><span class="identifier">i</span><span class="special">]</span>
|
||
<span class="special"><<</span> <span class="string">" c("</span> <span class="special"><<</span> <span class="identifier">i</span> <span class="special"><<</span> <span class="string">") = "</span> <span class="special"><<</span> <span class="identifier">c</span><span class="special">[</span><span class="identifier">i</span><span class="special">]</span>
|
||
<span class="special"><<</span> <span class="string">" d("</span> <span class="special"><<</span> <span class="identifier">i</span> <span class="special"><<</span> <span class="string">") = "</span> <span class="special"><<</span> <span class="identifier">d</span><span class="special">[</span><span class="identifier">i</span><span class="special">]</span>
|
||
<span class="special"><<</span> <span class="string">" e("</span> <span class="special"><<</span> <span class="identifier">i</span> <span class="special"><<</span> <span class="string">") = "</span> <span class="special"><<</span> <span class="special">*</span><span class="identifier">ei</span><span class="special">++</span>
|
||
<span class="special"><<</span> <span class="string">" f("</span> <span class="special"><<</span> <span class="identifier">i</span> <span class="special"><<</span> <span class="string">") = "</span> <span class="special"><<</span> <span class="special">*</span><span class="identifier">fi</span><span class="special">++</span>
|
||
<span class="special"><<</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"><</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">></span>
|
||
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">map</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">iostream</span><span class="special">></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"><</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">></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"><</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">></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"><</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">Fn</span> <span class="keyword">const</span> <span class="special">&</span> <span class="identifier">fn</span><span class="special">,</span> <span class="identifier">Key2</span> <span class="special">&&</span> <span class="identifier">key</span><span class="special">,</span> <span class="identifier">Value2</span> <span class="special">&&</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"><</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">>(</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"><</span><span class="identifier">Key2</span> <span class="special">&&>(</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"><</span><span class="identifier">Value2</span> <span class="special">&&>(</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"><</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">></span> <span class="special">&</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"><</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">></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"><</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">></span>
|
||
<span class="keyword">operator</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special"><</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">></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"><</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">></span> <span class="identifier">retval</span><span class="special">;</span>
|
||
<span class="identifier">map_list_of_transform</span><span class="special"><</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">></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"><</span><span class="identifier">map_list_of_expr</span><span class="special">>(</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"><</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">></span> <span class="identifier">op</span> <span class="special">=</span>
|
||
<span class="identifier">map_list_of</span>
|
||
<span class="special">(</span><span class="string">"<"</span><span class="special">,</span> <span class="number">1</span><span class="special">)</span>
|
||
<span class="special">(</span><span class="string">"<="</span><span class="special">,</span><span class="number">2</span><span class="special">)</span>
|
||
<span class="special">(</span><span class="string">">"</span><span class="special">,</span> <span class="number">3</span><span class="special">)</span>
|
||
<span class="special">(</span><span class="string">">="</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">"<>"</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"><<</span> <span class="string">"\"<\" --> "</span> <span class="special"><<</span> <span class="identifier">op</span><span class="special">[</span><span class="string">"<"</span><span class="special">]</span> <span class="special"><<</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"><<</span> <span class="string">"\"<=\" --> "</span> <span class="special"><<</span> <span class="identifier">op</span><span class="special">[</span><span class="string">"<="</span><span class="special">]</span> <span class="special"><<</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"><<</span> <span class="string">"\">\" --> "</span> <span class="special"><<</span> <span class="identifier">op</span><span class="special">[</span><span class="string">">"</span><span class="special">]</span> <span class="special"><<</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"><<</span> <span class="string">"\">=\" --> "</span> <span class="special"><<</span> <span class="identifier">op</span><span class="special">[</span><span class="string">">="</span><span class="special">]</span> <span class="special"><<</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"><<</span> <span class="string">"\"=\" --> "</span> <span class="special"><<</span> <span class="identifier">op</span><span class="special">[</span><span class="string">"="</span><span class="special">]</span> <span class="special"><<</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"><<</span> <span class="string">"\"<>\" --> "</span> <span class="special"><<</span> <span class="identifier">op</span><span class="special">[</span><span class="string">"<>"</span><span class="special">]</span> <span class="special"><<</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"><</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">></span>
|
||
|
||
<span class="preprocessor">#include</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">concat</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
|
||
|
||
<span class="comment">// A custom expression template for future groups. It supports operators ||</span>
|
||
<span class="comment">// and &&.</span>
|
||
<span class="keyword">template</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="keyword">typename</span> <span class="identifier">Tuple</span><span class="special">></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">&&</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"><</span><span class="identifier">Tuple</span> <span class="special">&&>(</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"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span>
|
||
<span class="keyword">struct</span> <span class="identifier">future</span> <span class="special">:</span>
|
||
<span class="identifier">future_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">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"><</span><span class="identifier">T</span><span class="special">>></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">&</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"><</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"><</span><span class="identifier">T</span><span class="special">>></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"><</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">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"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></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"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">remove_reference_t</span><span class="special"><</span><span class="identifier">T</span><span class="special">>>;</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"><</span><span class="keyword">typename</span> <span class="identifier">T</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">future_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">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"><</span><span class="identifier">T</span><span class="special">></span>
|
||
<span class="special">></span> <span class="keyword">const</span> <span class="special">&</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 -> transform(left).</span>
|
||
<span class="keyword">template</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">U</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">future_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">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"><</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">U</span><span class="special">></span>
|
||
<span class="special">></span> <span class="keyword">const</span> <span class="special">&</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 && right -> concat(transform(left), transform(right)).</span>
|
||
<span class="keyword">template</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">U</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">future_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">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"><</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">U</span><span class="special">></span>
|
||
<span class="special">></span> <span class="keyword">const</span> <span class="special">&</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"><</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">></span>
|
||
<span class="keyword">auto</span> <span class="identifier">future_expr</span><span class="special"><</span><span class="identifier">Kind</span><span class="special">,</span> <span class="identifier">Tuple</span><span class="special">>::</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"><</span><span class="keyword">typename</span> <span class="special">...</span><span class="identifier">T</span><span class="special">></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"><</span><span class="identifier">T</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">future</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="identifier">future</span><span class="special"><</span><span class="identifier">B</span><span class="special">></span> <span class="identifier">b</span><span class="special">;</span>
|
||
<span class="identifier">future</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="identifier">future</span><span class="special"><</span><span class="identifier">vector</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="special">></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"><</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">t1</span> <span class="special">=</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">get</span><span class="special">();</span>
|
||
<span class="identifier">vector</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span> <span class="identifier">C</span><span class="special">></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">&&</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"><</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">t3</span> <span class="special">=</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">a</span> <span class="special">&&</span> <span class="identifier">b</span><span class="special">)</span> <span class="special">&&</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"><</span><span class="identifier">vector</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">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">&&</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"><</span><span class="identifier">Node</span><span class="special">*>&</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">-></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">-></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">-></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"><</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">></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<>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"><</span><span class="identifier">OPCODE</span> <span class="identifier">Opcode</span><span class="special">></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"><</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"><</span><span class="identifier">OPCODE</span><span class="special">>></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"><</span><span class="identifier">OPCODE</span><span class="special">>{</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 <math.h>, so we have to add trailing underscores.</span>
|
||
<span class="identifier">autodiff_fn_expr</span><span class="special"><</span><span class="identifier">OP_SIN</span><span class="special">></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"><</span><span class="identifier">OP_COS</span><span class="special">></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"><</span><span class="identifier">OP_SQRT</span><span class="special">></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"><</span><span class="keyword">long</span> <span class="keyword">long</span> <span class="identifier">I</span><span class="special">></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"><</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">yap</span><span class="special">::</span><span class="identifier">placeholder</span><span class="special"><</span><span class="identifier">I</span><span class="special">>)</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"><</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">&</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"><</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="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"><</span><span class="keyword">typename</span> <span class="identifier">Expr</span><span class="special">></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"><</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">OPCODE</span> <span class="identifier">opcode</span><span class="special">,</span> <span class="identifier">Expr</span> <span class="keyword">const</span> <span class="special">&</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"><</span><span class="identifier">autodiff_expr</span><span class="special">>(</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"><</span><span class="keyword">typename</span> <span class="identifier">Expr</span><span class="special">></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"><</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">>,</span>
|
||
<span class="identifier">Expr</span> <span class="keyword">const</span> <span class="special">&</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"><</span><span class="identifier">autodiff_expr</span><span class="special">>(</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"><</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">></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"><</span><span class="identifier">Kind</span><span class="special">>,</span> <span class="identifier">Expr1</span> <span class="keyword">const</span> <span class="special">&</span> <span class="identifier">expr1</span><span class="special">,</span> <span class="identifier">Expr2</span> <span class="keyword">const</span> <span class="special">&</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"><</span><span class="identifier">autodiff_expr</span><span class="special">>(</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"><</span><span class="identifier">autodiff_expr</span><span class="special">>(</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"><</span><span class="identifier">Node</span> <span class="special">*></span> <span class="special">&</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"><</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">></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">&</span> <span class="identifier">expr</span><span class="special">,</span> <span class="identifier">vector</span><span class="special"><</span><span class="identifier">Node</span> <span class="special">*></span> <span class="special">&</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">[&</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"><</span><span class="identifier">VNode</span> <span class="special">*>(</span><span class="identifier">n</span><span class="special">);</span>
|
||
<span class="identifier">v</span><span class="special">-></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"><</span><span class="identifier">Node</span><span class="special">*>&</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"><</span><span class="keyword">double</span><span class="special">></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"><</span><span class="keyword">double</span><span class="special">></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"><</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">></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"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></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"><</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">T</span> <span class="special">&&</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"><</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">></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"><</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">CallableExpr</span> <span class="identifier">callable</span><span class="special">,</span> <span class="identifier">Arg</span> <span class="special">&&...</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"><</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">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"><</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">></span>
|
||
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">algorithm</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">vector</span><span class="special">></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"><</span><span class="keyword">typename</span> <span class="identifier">Iter</span><span class="special">></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"><</span><span class="keyword">typename</span> <span class="identifier">Range</span><span class="special">></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">&</span> <span class="identifier">r</span><span class="special">)</span>
|
||
<span class="special">{</span>
|
||
<span class="identifier">simple_range</span><span class="special"><</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">())></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<>, 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"><</span><span class="keyword">typename</span> <span class="identifier">LExpr</span><span class="special">></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"><</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">>,</span>
|
||
<span class="identifier">LExpr</span> <span class="special">&&</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"><</span><span class="identifier">LExpr</span><span class="special">>(</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"><</span><span class="keyword">typename</span> <span class="identifier">Range</span><span class="special">></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"><</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">algorithm_t</span> <span class="identifier">a</span><span class="special">,</span>
|
||
<span class="identifier">Range</span> <span class="special">&</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"><</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">></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"><</span><span class="keyword">typename</span> <span class="identifier">Assignee</span><span class="special">></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"><</span><span class="identifier">algorithm_t</span><span class="special">></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"><</span><span class="keyword">int</span><span class="special">></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"><</span><span class="keyword">int</span><span class="special">></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"><</span><span class="keyword">int</span><span class="special">>({</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"><</span><span class="keyword">int</span><span class="special">></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"><</span><span class="keyword">int</span><span class="special">></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"><</span><span class="keyword">int</span><span class="special">>({</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"><</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">></span>
|
||
|
||
<span class="preprocessor">#include</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">map</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
<span class="preprocessor">#include</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">at_key</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
<span class="preprocessor">#include</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="identifier">hpp</span><span class="special">></span>
|
||
<span class="preprocessor">#include</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">hpp</span><span class="special">></span>
|
||
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">vector</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">iostream</span><span class="special">></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"><</span><span class="keyword">long</span> <span class="keyword">long</span> <span class="identifier">I</span><span class="special">></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"><</span><span class="identifier">I</span><span class="special">></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"><</span><span class="keyword">typename</span> <span class="identifier">ExprMap</span><span class="special">></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"><</span><span class="keyword">long</span> <span class="keyword">long</span> <span class="identifier">I</span><span class="special">></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"><</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">let_placeholder</span><span class="special"><</span><span class="identifier">I</span><span class="special">></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"><</span><span class="identifier">I</span><span class="special">>))</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"><</span><span class="identifier">I</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">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"><</span><span class="keyword">typename</span> <span class="identifier">ExprMap</span><span class="special">></span>
|
||
<span class="keyword">struct</span> <span class="identifier">let_result</span>
|
||
<span class="special">{</span>
|
||
<span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Expr</span><span class="special">></span>
|
||
<span class="keyword">auto</span> <span class="keyword">operator</span><span class="special">[](</span><span class="identifier">Expr</span> <span class="special">&&</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"><</span><span class="identifier">Expr</span><span class="special">>(</span><span class="identifier">expr</span><span class="special">),</span> <span class="identifier">let_terminal_transform</span><span class="special"><</span><span class="identifier">ExprMap</span><span class="special">>{</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<>s to YAP expressions.</span>
|
||
<span class="keyword">template</span><span class="special"><</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">></span>
|
||
<span class="keyword">auto</span> <span class="identifier">let_impl</span><span class="special">(</span><span class="identifier">Map</span> <span class="special">&&</span> <span class="identifier">map</span><span class="special">,</span> <span class="identifier">Expr</span> <span class="special">&&</span> <span class="identifier">expr</span><span class="special">,</span> <span class="identifier">Exprs</span> <span class="special">&&...</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"><</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">)))>::</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"><</span><span class="identifier">I</span><span class="special">::</span><span class="identifier">value</span><span class="special">>;</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"><</span><span class="identifier">map_t</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="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"><</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">)))>::</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"><</span><span class="identifier">I</span><span class="special">::</span><span class="identifier">value</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">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"><</span><span class="identifier">Exprs</span><span class="special">>(</span><span class="identifier">exprs</span><span class="special">)...);</span>
|
||
<span class="special">}</span>
|
||
<span class="special">}</span>
|
||
|
||
<span class="comment">// Takes N > 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"><</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">></span>
|
||
<span class="keyword">auto</span> <span class="identifier">let</span><span class="special">(</span><span class="identifier">Expr</span> <span class="special">&&</span> <span class="identifier">expr</span><span class="special">,</span> <span class="identifier">Exprs</span> <span class="special">&&...</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"><</span><span class="identifier">Expr</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"><</span><span class="identifier">Exprs</span><span class="special">>(</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"><</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"><</span><span class="identifier">let_placeholder</span><span class="special"><</span><span class="number">0</span><span class="special">>>></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"><</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"><</span><span class="identifier">let_placeholder</span><span class="special"><</span><span class="number">1</span><span class="special">>>></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"><<</span> <span class="special">--</span><span class="identifier">_a</span> <span class="special"><<</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"><<</span> <span class="identifier">i</span> <span class="special"><<</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"><<</span> <span class="identifier">_a</span> <span class="special"><<</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"><<</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">// << 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"><<</span> <span class="number">3</span><span class="special">)</span>
|
||
<span class="special">[</span>
|
||
<span class="identifier">_a</span> <span class="special"><<</span> <span class="string">"1"</span><span class="special">,</span> <span class="identifier">_a</span> <span class="special"><<</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"><<</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"><</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">></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<></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<></a></code>
|
||
reference expression template (great for prototyping, but not recommended
|
||
for production work), include the <code class="computeroutput"><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">hpp</span><span class="special">></span></code>
|
||
header.
|
||
</p>
|
||
<p>
|
||
If you want to include all of the above, use the <code class="computeroutput"><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">yap</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></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"><</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">></span></code>
|
||
header; this header is not included in the <code class="computeroutput"><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">yap</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></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"><</span><span class="identifier">user</span><span class="special">::</span><span class="identifier">number</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="identifier">term</span><span class="special"><</span><span class="identifier">user</span><span class="special">::</span><span class="identifier">number</span><span class="special">></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"><</span><span class="identifier">user</span><span class="special">::</span><span class="identifier">number</span><span class="special">></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"><+</span><span class="number">0</span><span class="special">>:</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"><+</span><span class="number">1</span><span class="special">>:</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"><+</span><span class="number">4</span><span class="special">>:</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"><+</span><span class="number">8</span><span class="special">>:</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"><+</span><span class="number">12</span><span class="special">>:</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"><+</span><span class="number">16</span><span class="special">>:</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"><+</span><span class="number">20</span><span class="special">>:</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"><+</span><span class="number">24</span><span class="special">>:</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"><+</span><span class="number">28</span><span class="special">>:</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"><+</span><span class="number">29</span><span class="special">>:</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"><+</span><span class="number">0</span><span class="special">>:</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"><+</span><span class="number">1</span><span class="special">>:</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"><+</span><span class="number">4</span><span class="special">>:</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"><+</span><span class="number">8</span><span class="special">>:</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"><+</span><span class="number">12</span><span class="special">>:</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"><+</span><span class="number">16</span><span class="special">>:</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"><+</span><span class="number">20</span><span class="special">>:</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"><+</span><span class="number">24</span><span class="special">>:</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"><+</span><span class="number">28</span><span class="special">>:</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"><+</span><span class="number">29</span><span class="special">>:</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"><</span><span class="identifier">user</span><span class="special">::</span><span class="identifier">number</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="identifier">term</span><span class="special"><</span><span class="identifier">user</span><span class="special">::</span><span class="identifier">number</span><span class="special">></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"><</span><span class="identifier">user</span><span class="special">::</span><span class="identifier">number</span><span class="special">></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"><</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">></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">"<"</span><span class="special">,</span> <span class="number">1</span><span class="special">)</span>
|
||
<span class="special">(</span><span class="string">"<="</span><span class="special">,</span><span class="number">2</span><span class="special">)</span>
|
||
<span class="special">(</span><span class="string">">"</span><span class="special">,</span> <span class="number">3</span><span class="special">)</span>
|
||
<span class="special">(</span><span class="string">">="</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">"<>"</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"><</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">></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">"<"</span><span class="special">,</span> <span class="number">1</span><span class="special">)</span>
|
||
<span class="special">(</span><span class="string">"<="</span><span class="special">,</span><span class="number">2</span><span class="special">)</span>
|
||
<span class="special">(</span><span class="string">">"</span><span class="special">,</span> <span class="number">3</span><span class="special">)</span>
|
||
<span class="special">(</span><span class="string">">="</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">"<>"</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"><</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">></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"><</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">></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">"<"</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">"<="</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">">"</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">">="</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">"<>"</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"><</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">></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"><</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">></span> <span class="identifier">retval</span> <span class="special">=</span> <span class="special">{</span>
|
||
<span class="special">{</span><span class="string">"<"</span><span class="special">,</span> <span class="number">1</span><span class="special">},</span>
|
||
<span class="special">{</span><span class="string">"<="</span><span class="special">,</span><span class="number">2</span><span class="special">},</span>
|
||
<span class="special">{</span><span class="string">">"</span><span class="special">,</span> <span class="number">3</span><span class="special">},</span>
|
||
<span class="special">{</span><span class="string">">="</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">"<>"</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>
|