]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/yap/example/lazy_vector.cpp
1 // Copyright (C) 2016-2018 T. Zachary Laine
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)
7 #include <boost/yap/expression.hpp>
15 template <boost::yap::expr_kind Kind
, typename Tuple
>
16 struct lazy_vector_expr
;
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.
24 boost::yap::terminal
<lazy_vector_expr
, double>
25 operator() (boost::yap::terminal
<lazy_vector_expr
, std::vector
<double>> const & expr
);
30 // A custom expression template that defines lazy + and - operators that
31 // produce expressions, and an eager [] operator that returns the nth element
34 template <boost::yap::expr_kind Kind
, typename Tuple
>
35 struct lazy_vector_expr
37 static const boost::yap::expr_kind kind
= Kind
;
41 // Note that this does not return an expression; it is greedily evaluated.
42 auto operator[] (std::size_t n
) const;
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
)
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
})); }
53 boost::yap::terminal
<lazy_vector_expr
, double>
54 take_nth::operator() (boost::yap::terminal
<lazy_vector_expr
, std::vector
<double>> const & expr
)
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
));
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.
72 boost::yap::expr_kind::terminal
,
73 boost::hana::tuple
<std::vector
<double>>
78 explicit lazy_vector (std::vector
<double> && vec
)
79 { elements
= boost::hana::tuple
<std::vector
<double>>(std::move(vec
)); }
81 template <boost::yap::expr_kind Kind
, typename Tuple
>
82 lazy_vector
& operator+= (lazy_vector_expr
<Kind
, Tuple
> const & rhs
)
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
];
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)};
98 double d1
= (v2
+ v3
)[2];
99 std::cout
<< d1
<< "\n";
102 std::cout
<< '{' << v1
[0] << ',' << v1
[1]
103 << ',' << v1
[2] << ',' << v1
[3] << '}' << "\n";
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.