]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/proto/example/vec3.cpp
2 ///////////////////////////////////////////////////////////////////////////////
3 // Copyright 2008 Eric Niebler. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 // This is a simple example using proto::extends to extend a terminal type with
8 // additional behaviors, and using custom contexts and proto::eval for
9 // evaluating expressions. It is a port of the Vec3 example
10 // from PETE (http://www.codesourcery.com/pooma/download.html).
14 #include <boost/assert.hpp>
15 #include <boost/mpl/int.hpp>
16 #include <boost/proto/core.hpp>
17 #include <boost/proto/context.hpp>
18 #include <boost/proto/proto_typeof.hpp>
19 #include <boost/proto/transform.hpp>
20 namespace mpl
= boost::mpl
;
21 namespace proto
= boost::proto
;
24 // Here is an evaluation context that indexes into a Vec3
25 // expression, and combines the result.
26 struct Vec3SubscriptCtx
27 : proto::callable_context
< Vec3SubscriptCtx
const >
29 typedef int result_type
;
31 Vec3SubscriptCtx(int i
)
35 // Index array terminals with our subscript. Everything
36 // else will be handled by the default evaluation context.
37 int operator ()(proto::tag::terminal
, int const (&arr
)[3]) const
45 // Here is an evaluation context that counts the number
46 // of Vec3 terminals in an expression.
48 : proto::callable_context
< CountLeavesCtx
, proto::null_context
>
54 typedef void result_type
;
56 void operator ()(proto::tag::terminal
, int const(&)[3])
64 struct iplus
: std::plus
<int>, proto::callable
{};
66 // Here is a transform that does the same thing as the above context.
67 // It demonstrates the use of the std::plus<> function object
68 // with the fold transform. With minor modifications, this
69 // transform could be used to calculate the leaf count at compile
70 // time, rather than at runtime.
73 // match a Vec3 terminal, return 1
74 proto::when
<proto::terminal
<int[3]>, mpl::int_
<1>() >
75 // match a terminal, return int() (which is 0)
76 , proto::when
<proto::terminal
<_
>, int() >
77 // fold everything else, using std::plus<> to add
78 // the leaf count of each child to the accumulated state.
79 , proto::otherwise
< proto::fold
<_
, int(), iplus(CountLeaves
, proto::_state
) > >
83 // Here is the Vec3 struct, which is a vector of 3 integers.
85 : proto::extends
<proto::terminal
<int[3]>::type
, Vec3
>
87 explicit Vec3(int i
=0, int j
=0, int k
=0)
94 int &operator [](int i
)
96 return proto::value(*this)[i
];
99 int const &operator [](int i
) const
101 return proto::value(*this)[i
];
104 // Here we define a operator = for Vec3 terminals that
105 // takes a Vec3 expression.
106 template< typename Expr
>
107 Vec3
&operator =(Expr
const & expr
)
109 typedef Vec3SubscriptCtx
const CVec3SubscriptCtx
;
110 (*this)[0] = proto::eval(proto::as_expr(expr
), CVec3SubscriptCtx(0));
111 (*this)[1] = proto::eval(proto::as_expr(expr
), CVec3SubscriptCtx(1));
112 (*this)[2] = proto::eval(proto::as_expr(expr
), CVec3SubscriptCtx(2));
116 // This copy-assign is needed because a template is never
117 // considered for copy assignment.
118 Vec3
&operator=(Vec3
const &that
)
120 (*this)[0] = that
[0];
121 (*this)[1] = that
[1];
122 (*this)[2] = that
[2];
128 std::cout
<< '{' << (*this)[0]
129 << ", " << (*this)[1]
130 << ", " << (*this)[2]
135 // The count_leaves() function uses the CountLeaves transform and
136 // to count the number of leaves in an expression.
137 template<typename Expr
>
138 int count_leaves(Expr
const &expr
)
140 // Count the number of Vec3 terminals using the
141 // CountLeavesCtx evaluation context.
143 proto::eval(expr
, ctx
);
145 // This is another way to count the leaves using a transform.
147 BOOST_ASSERT( CountLeaves()(expr
, i
, i
) == ctx
.count
);
167 BOOST_PROTO_AUTO(expr1
, b
+ c
);
171 int num
= count_leaves(expr1
);
172 std::cout
<< num
<< std::endl
;
174 BOOST_PROTO_AUTO(expr2
, b
+ 3 * c
);
175 num
= count_leaves(expr2
);
176 std::cout
<< num
<< std::endl
;
178 BOOST_PROTO_AUTO(expr3
, b
+ c
* d
);
179 num
= count_leaves(expr3
);
180 std::cout
<< num
<< std::endl
;