[proto] another problem w/ terminal matching

Eric, I've found more about the root problem in my code. A pattern for a terminal was not matching and the thus the transform for unary_expr was applied. In the code included, I define a class, K_aux, which inherits from meta_expression<typename proto::terminal<K<mpl::int_<N> >, Normally, objects of type K_aux match a pattern terminal<K<proto::_> >. I'm still fuzzy on why two layers of the type are skipped, but I'm fine with it. Now, if K_aux defines a type named type (e.g. effectively becoming a nullary metafunction) the pattern doesn't match anymore. If this is intentional or unavoidable it should be mentioned in the docs. In boldface. Btw, the entire exercise is to get real compile time constants. I can change the name of the typedef'd type and use code similar to this, but if there was a better way I'd liek to hear. Regards, Maurizio ===File ~/dev/proto_pdl/pe5.cpp============================= #define BOOST_PROTO_MAX_ARITY 10 #define BOOST_MPL_LIMIT_METAFUNCTION_ARITY 10 #include <iostream> #include <boost/xpressive/proto/proto.hpp> #include <boost/xpressive/proto/debug.hpp> #include <boost/type_traits.hpp> namespace proto=boost::proto; namespace mpl=boost::mpl; template<typename> struct meta_expression; struct meta_domain : proto::domain<proto::generator<meta_expression> > {}; template <typename Expr> struct meta_expression : proto::extends<Expr, meta_expression<Expr>, meta_domain> { typedef proto::extends<Expr, meta_expression<Expr>, meta_domain> base_type; meta_expression (Expr const& expr = Expr()) : base_type (expr) {} using base_type::operator =; }; template<typename N> struct K { typedef N type; }; template<int N> struct K_aux : meta_expression<typename proto::terminal< K<mpl::int_<N> > >::type> { // typedef mpl::int_<N> type; }; #define const_(N) (K_aux<N> ()) template<typename N> std::ostream& operator << (std::ostream& os, const K<N> k) { os << "const"; return os; } struct meta_grammar : proto::or_ < proto::terminal<K<proto::_> >, proto::and_< proto::not_<proto::terminal<proto::_> >, proto::unary_expr<proto::_, proto::_> >
{}; template<typename Expr> void is_meta_expression (const Expr& expr) { std::cout << "Expression:\n"; proto::display_expr (expr); if (proto::matches<Expr, meta_grammar>::value) std::cout << "matches meta grammar\n\n"; else std::cout << "doesn't matches meta grammar\n\n"; } int main (int,char**) { is_meta_expression (const_ (1)); } /// Local Variables: /// mode:c++ /// comment-column:60 /// fill-column:150 /// compilation-read-command:nil /// compile-command:"g++ -I. -ope5 pe5.cpp" /// End: ============================================================

Maurizio Vitale wrote:
Eric, I've found more about the root problem in my code. A pattern for a terminal was not matching and the thus the transform for unary_expr was applied.
In the code included, I define a class, K_aux, which inherits from meta_expression<typename proto::terminal<K<mpl::int_<N> >, Normally, objects of type K_aux match a pattern terminal<K<proto::_> >. I'm still fuzzy on why two layers of the type are skipped, but I'm fine with it.
Now, if K_aux defines a type named type (e.g. effectively becoming a nullary metafunction) the pattern doesn't match anymore.
Yep, I've known about this gotcha for a while and have been meaning to fix it before anybody noticed, but you beat me to it. :-P Proto uses the nested type named "type" to mean "the type of this expression", which was fine before proto::extends<> existed, but is dangerous and stupid once people start extending expression types. I'm sorry. Basically, I need to change all the nested types that Proto accesses to be proto-specific. So "type" becomes "proto_type", "tag_type" becomes "proto_tag", and even "arg0_type" becomes "proto_arg0", etc. This is a major breaking change, but it has to be done, and the sooner the better. Darn. -- Eric Niebler Boost Consulting www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com

Eric Niebler wrote:
Maurizio Vitale wrote:
In the code included, I define a class, K_aux, which inherits from meta_expression<typename proto::terminal<K<mpl::int_<N> >, Normally, objects of type K_aux match a pattern terminal<K<proto::_> >. I'm still fuzzy on why two layers of the type are skipped, but I'm fine with it.
Now, if K_aux defines a type named type (e.g. effectively becoming a nullary metafunction) the pattern doesn't match anymore.
Yep, I've known about this gotcha for a while and have been meaning to fix it before anybody noticed, but you beat me to it. :-P Proto uses the nested type named "type" to mean "the type of this expression", which was fine before proto::extends<> existed, but is dangerous and stupid once people start extending expression types. I'm sorry. Basically, I need to change all the nested types that Proto accesses to be proto-specific. So "type" becomes "proto_type", "tag_type" becomes "proto_tag", and even "arg0_type" becomes "proto_arg0", etc. This is a major breaking change, but it has to be done, and the sooner the better. Darn.
This bug should now be fixed. This involved a massive number of breaking renames, so I think this should probably break just about everybody. Sorry. The following Proto expression nested types/members have been renamed: type -> proto_base_expr tag_type -> proto_tag args -> proto_args arity -> proto_arity domain -> proto_domain arg0_type -> proto_arg0 arg1_type -> proto_arg1 ... ... boost_proto_expr_type_ -> proto_derived_expr cast() -> proto_base() In addition, there used to be a "proto::trans" namespace alias for proto::transform, and I've remove that. Bad idea. Gotta say "transform" now, or else create your own alias. -- Eric Niebler Boost Consulting www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com
participants (2)
-
Eric Niebler
-
Maurizio Vitale