Why doesn't the following Boost.Proto grammar match dereference operator, and what's the
correct way to do this?
#include <iostream>
#include <boost/proto/proto.hpp>
namespace proto = boost::proto;
using proto::_;
struct has_deref : proto::or_<
proto::dereference<_>,
proto::nary_expr<_, proto::vararg<has_deref>>
>
{};
template<class Expr>
void test_expr(const Expr &e)
{
proto::display_expr(e);
std::cout << "matches? " << std::boolalpha << proto::matches<Expr,
has_deref>::value << std::endl;
}
int main()
{
test_expr(proto::lit(1) + *proto::lit(2));
}
According to your definition your
has_derefgrammar matches expressions that are either:complement,negateorunary_plus; binary like:subscriptorplus; ternary likeif_else_, or directly n-ary likefunction) expression whose arguments recursively match thehas_derefgrammar.In your example you have a
plus<terminal<int>,dereference<terminal<int> > >which is something likebinary_expr<tag::plus,terminal<int>,unary_expr<tag::dereference,terminal<int> > >. When trying to match your expression (I think) Proto tries first the first element of your grammar (dereference<_>) and obviously fails. Then tries the second one andbinary_expr<tag::plus,...>matchesnary_expr<_,...>and so it recursively tries to match the grammar to both argument expressions of theplus. The second one matches directly, but the first one (terminal<int>) does not match either of the possibilities and so the whole expression fails to match.One possible (and sadly clunky) approach to do what you want could be something like:
that matches expressions that are either:
has_deref.has_derefand its second is ANY expression (including expressions that matchhas_deref) .has_derefand its second is one that does.Here is an example that checks that several expressions match this new grammar (extended to also check for functions with at most 2 arguments):