Ticket #4175: test_boost_proto.cpp

File test_boost_proto.cpp, 4.5 KB (added by Robert Valkenburg <rj.valkenburg@…>, 12 years ago)

self contained program which shows expression unwrapping

Line 
1// test_boost_proto
2// - Small test program to illustrate wrapper removal issue
3
4#include <boost/proto/proto.hpp>
5
6namespace clifford {
7
8 namespace proto = boost::proto;
9
10 // expression tags
11 namespace tag {
12 struct reverse_ {};
13 }
14
15
16 ////////////////////////////////////////////////////////////////////
17 // Grammar
18 struct ga_grammar;
19
20 struct ga_grammar_cases {
21 template <class Tag>
22 struct case_ : proto::not_<proto::_> {};
23 };
24
25 // terminals - usually multivectors or doubles
26 template<> struct ga_grammar_cases::case_<proto::tag::terminal>
27 : proto::_ {};
28
29 // reverse operator
30 template<> struct ga_grammar_cases::case_<tag::reverse_>
31 : proto::unary_expr<tag::reverse_, ga_grammar> {};
32
33 struct ga_grammar : proto::switch_<ga_grammar_cases> {};
34
35
36 struct ga_domain;
37
38 template<typename Expr>
39 struct ga_expr
40 : proto::extends<Expr, ga_expr<Expr>, ga_domain>
41 {
42 typedef proto::extends<Expr, ga_expr<Expr>, ga_domain> base_type;
43
44 typedef void clifford_is_expr_;
45
46 ga_expr(const Expr& expr = Expr() )
47 : base_type( expr )
48 {}
49 };
50
51 struct ga_domain : proto::domain<proto::generator<ga_expr>, ga_grammar> {};
52
53
54 //////////////////////////////////////////////////////////////////
55 // Capture the expression
56
57 // control overloads
58 namespace detail_
59 {
60 template <class Tag, class Arg, class Enable = void>
61 struct make_unary_expr_if {};
62
63 template <class T, class Arg>
64 struct make_unary_expr_if<T, Arg, typename Arg::clifford_is_multivector_>
65 : proto::result_of::make_expr<T, ga_domain, const Arg&> {};
66
67 template <class T, class Arg>
68 struct make_unary_expr_if<T, Arg, typename Arg::clifford_is_expr_>
69 : proto::result_of::make_expr<T, ga_domain, const Arg&> {};
70
71 } // namespace detail_
72
73#define CLIFFORD_DEFINE_UNARY_OPERATOR(OP, TAG) \
74 template<typename A> \
75 const typename detail_::make_unary_expr_if<TAG, A>::type \
76 OP(A const &a) { \
77 return proto::make_expr<TAG, ga_domain >(boost::ref(a)); \
78 }
79
80 CLIFFORD_DEFINE_UNARY_OPERATOR(operator~, tag::reverse_)
81
82
83 ////////////////////////////////////////////////////////////////////
84 /// Transform the expression
85
86 //struct transform_expression : proto::_ {}; // <= this is fine
87
88 struct transform_expression
89 : proto::nary_expr<proto::_, proto::vararg<transform_expression> > {};
90
91
92 //////////////////////////////////////////////////////////////////
93 // Evaluate the expression
94
95 template <class Res, class Expr>
96 void evaluate_expr(Res& res, const ga_expr<Expr>& expr) {
97 // do something ...
98 }
99
100 template <class Res, class Expr>
101 void evaluate(Res& res, const ga_expr<Expr>& expr) {
102 BOOST_MPL_ASSERT((proto::matches< ga_expr<Expr>, ga_grammar>));
103 evaluate_expr(res, transform_expression()(expr) );
104 }
105
106 // "stub" structs for multivector terminals
107
108 template <class T> struct multivector_base {
109 typedef void clifford_is_multivector_;
110 /// \brief cast to the actual mulivector type
111 T& operator()() { return static_cast<T&>(*this); }
112 /// \overload
113 const T& operator()() const { return static_cast<const T&>(*this); }
114 };
115
116 // general geometric algebra multivector template
117 template <class B, class A>
118 class multivector : public multivector_base< multivector<B, A> >
119 {
120 public:
121 multivector () {};
122
123 // generalised assign
124 template <class T>
125 multivector& operator=(const ga_expr<T>& expr) {
126 evaluate(*this, expr);
127 return *this;
128 }
129
130 // implementation ...
131 }; // class multivector
132
133 /////////////////////////////////////////////////////////////////////
134 // make some multivector types - stubs
135
136 // (p,q) signature of space, p positive and q negative basis elements
137 template <size_t p, size_t q>
138 struct algebra {}; // implementation ...
139
140 typedef algebra<4,1> ga41;
141
142 namespace cga3 {
143 struct cga3 : ga41{}; // 3D conformal geometric algebra, cga
144
145 // some bases ( implemented using mpl integral sequences wrappers)
146 struct ebivector_basis{}; // {e12, e13, e23 }
147 struct rotator_basis{}; // {1, e12, e23, e31}
148 // ...
149
150 // some useful general multivector types
151 typedef multivector<ebivector_basis, cga3> ebivector;
152 typedef multivector<rotator_basis, cga3> rotator; // Rotation about origin, aka Quaternion
153 // ...
154
155 } // namespace cga3
156} // namespace clifford
157
158
159int main()
160{
161 clifford::cga3::rotator R;
162 clifford::cga3::ebivector B;
163
164 R = ~B;
165}