// test_boost_proto // - Small test program to illustrate wrapper removal issue #include namespace clifford { namespace proto = boost::proto; // expression tags namespace tag { struct reverse_ {}; } //////////////////////////////////////////////////////////////////// // Grammar struct ga_grammar; struct ga_grammar_cases { template struct case_ : proto::not_ {}; }; // terminals - usually multivectors or doubles template<> struct ga_grammar_cases::case_ : proto::_ {}; // reverse operator template<> struct ga_grammar_cases::case_ : proto::unary_expr {}; struct ga_grammar : proto::switch_ {}; struct ga_domain; template struct ga_expr : proto::extends, ga_domain> { typedef proto::extends, ga_domain> base_type; typedef void clifford_is_expr_; ga_expr(const Expr& expr = Expr() ) : base_type( expr ) {} }; struct ga_domain : proto::domain, ga_grammar> {}; ////////////////////////////////////////////////////////////////// // Capture the expression // control overloads namespace detail_ { template struct make_unary_expr_if {}; template struct make_unary_expr_if : proto::result_of::make_expr {}; template struct make_unary_expr_if : proto::result_of::make_expr {}; } // namespace detail_ #define CLIFFORD_DEFINE_UNARY_OPERATOR(OP, TAG) \ template \ const typename detail_::make_unary_expr_if::type \ OP(A const &a) { \ return proto::make_expr(boost::ref(a)); \ } CLIFFORD_DEFINE_UNARY_OPERATOR(operator~, tag::reverse_) //////////////////////////////////////////////////////////////////// /// Transform the expression //struct transform_expression : proto::_ {}; // <= this is fine struct transform_expression : proto::nary_expr > {}; ////////////////////////////////////////////////////////////////// // Evaluate the expression template void evaluate_expr(Res& res, const ga_expr& expr) { // do something ... } template void evaluate(Res& res, const ga_expr& expr) { BOOST_MPL_ASSERT((proto::matches< ga_expr, ga_grammar>)); evaluate_expr(res, transform_expression()(expr) ); } // "stub" structs for multivector terminals template struct multivector_base { typedef void clifford_is_multivector_; /// \brief cast to the actual mulivector type T& operator()() { return static_cast(*this); } /// \overload const T& operator()() const { return static_cast(*this); } }; // general geometric algebra multivector template template class multivector : public multivector_base< multivector > { public: multivector () {}; // generalised assign template multivector& operator=(const ga_expr& expr) { evaluate(*this, expr); return *this; } // implementation ... }; // class multivector ///////////////////////////////////////////////////////////////////// // make some multivector types - stubs // (p,q) signature of space, p positive and q negative basis elements template struct algebra {}; // implementation ... typedef algebra<4,1> ga41; namespace cga3 { struct cga3 : ga41{}; // 3D conformal geometric algebra, cga // some bases ( implemented using mpl integral sequences wrappers) struct ebivector_basis{}; // {e12, e13, e23 } struct rotator_basis{}; // {1, e12, e23, e31} // ... // some useful general multivector types typedef multivector ebivector; typedef multivector rotator; // Rotation about origin, aka Quaternion // ... } // namespace cga3 } // namespace clifford int main() { clifford::cga3::rotator R; clifford::cga3::ebivector B; R = ~B; }