]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/yap/example/lazy_vector.cpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / yap / example / lazy_vector.cpp
1 // Copyright (C) 2016-2018 T. Zachary Laine
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See
4 // accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 //[ lazy_vector
7 #include <boost/yap/expression.hpp>
8
9 #include <algorithm>
10 #include <cassert>
11 #include <iostream>
12 #include <vector>
13
14
15 template <boost::yap::expr_kind Kind, typename Tuple>
16 struct lazy_vector_expr;
17
18
19 // This transform turns a terminal of std::vector<double> into a terminal
20 // containing the nth double in that vector. Think of it as turning our
21 // expression of vectors into an expression of scalars.
22 struct take_nth
23 {
24 boost::yap::terminal<lazy_vector_expr, double>
25 operator() (boost::yap::terminal<lazy_vector_expr, std::vector<double>> const & expr);
26
27 std::size_t n;
28 };
29
30 // A custom expression template that defines lazy + and - operators that
31 // produce expressions, and an eager [] operator that returns the nth element
32 // of the expression.
33 //[ lazy_vector_decl
34 template <boost::yap::expr_kind Kind, typename Tuple>
35 struct lazy_vector_expr
36 {
37 static const boost::yap::expr_kind kind = Kind;
38
39 Tuple elements;
40
41 // Note that this does not return an expression; it is greedily evaluated.
42 auto operator[] (std::size_t n) const;
43 };
44
45 BOOST_YAP_USER_BINARY_OPERATOR(plus, lazy_vector_expr, lazy_vector_expr)
46 BOOST_YAP_USER_BINARY_OPERATOR(minus, lazy_vector_expr, lazy_vector_expr)
47 //]
48
49 template <boost::yap::expr_kind Kind, typename Tuple>
50 auto lazy_vector_expr<Kind, Tuple>::operator[] (std::size_t n) const
51 { return boost::yap::evaluate(boost::yap::transform(*this, take_nth{n})); }
52
53 boost::yap::terminal<lazy_vector_expr, double>
54 take_nth::operator() (boost::yap::terminal<lazy_vector_expr, std::vector<double>> const & expr)
55 {
56 double x = boost::yap::value(expr)[n];
57 // This move is something of a hack; we're forcing Yap to take a copy of x
58 // by using std::move(). The move indicates that the terminal should keep
59 // the value of x (since, being an rvalue, it may be a temporary), rather
60 // than a reference to x. See the "How Expression Operands Are Treated"
61 // section of the tutorial for details.
62 return boost::yap::make_terminal<lazy_vector_expr, double>(std::move(x));
63 }
64
65 // In order to define the += operator with the semantics we want, it's
66 // convenient to derive a terminal type from a terminal instantiation of
67 // lazy_vector_expr. Note that we could have written a template
68 // specialization here instead -- either one would work. That would of course
69 // have required more typing.
70 struct lazy_vector :
71 lazy_vector_expr<
72 boost::yap::expr_kind::terminal,
73 boost::hana::tuple<std::vector<double>>
74 >
75 {
76 lazy_vector () {}
77
78 explicit lazy_vector (std::vector<double> && vec)
79 { elements = boost::hana::tuple<std::vector<double>>(std::move(vec)); }
80
81 template <boost::yap::expr_kind Kind, typename Tuple>
82 lazy_vector & operator+= (lazy_vector_expr<Kind, Tuple> const & rhs)
83 {
84 std::vector<double> & this_vec = boost::yap::value(*this);
85 for (int i = 0, size = (int)this_vec.size(); i < size; ++i) {
86 this_vec[i] += rhs[i];
87 }
88 return *this;
89 }
90 };
91
92 int main ()
93 {
94 lazy_vector v1{std::vector<double>(4, 1.0)};
95 lazy_vector v2{std::vector<double>(4, 2.0)};
96 lazy_vector v3{std::vector<double>(4, 3.0)};
97
98 double d1 = (v2 + v3)[2];
99 std::cout << d1 << "\n";
100
101 v1 += v2 - v3;
102 std::cout << '{' << v1[0] << ',' << v1[1]
103 << ',' << v1[2] << ',' << v1[3] << '}' << "\n";
104
105 // This expression is disallowed because it does not conform to the
106 // implicit grammar. operator+= is only defined on terminals, not
107 // arbitrary expressions.
108 // (v2 + v3) += v1;
109
110 return 0;
111 }
112 //]