在Proto表达式的某处匹配运算符

时间:2016-05-16 17:54:09

标签: boost-proto

为什么以下Boost.Proto语法匹配取消引用运算符,以及它是什么? 正确的方法吗?

#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));
}

1 个答案:

答案 0 :(得分:1)

根据您的定义,您的has_deref语法匹配以下表达式:

  • 应用于ANY表达式的解除引用运算符
  • 任何n-ary(可以是一元的:complementnegateunary_plus;二进制,如:subscriptplus; ternary like { {1}},或直接类似if_else_}表达式,其参数递归地匹配function语法。

在您的示例中,您有has_deref,类似于plus<terminal<int>,dereference<terminal<int> > >。在尝试匹配你的表达式时(我认为)Proto首先尝试你的语法的第一个元素(binary_expr<tag::plus,terminal<int>,unary_expr<tag::dereference,terminal<int> > >)并且显然失败了。然后尝试第二个和dereference<_>匹配binary_expr<tag::plus,...>,因此它递归地尝试将语法与nary_expr<_,...>的两个参数表达式匹配。第二个直接匹配,但第一个(plus)与两种可能性都不匹配,因此整个表达式无法匹配。

一种可能(并且可悲的笨重)方法来做你想做的事情可能是这样的:

terminal<int>

匹配以下表达式:

  • 应用于任何表达式的解除引用运算符。
  • 一元运算符应用于递归匹配struct has_deref : proto::or_< //ignoring if_then_else and function proto::dereference<_>, proto::unary_expr<_, has_deref>, proto::binary_expr<_, has_deref, _>, proto::binary_expr<_, _, has_deref> > {}; 的表达式。
  • 一个二元运算符,其第一个操作数是与has_deref匹配的表达式,第二个是ANY表达式(包括与has_deref匹配的表达式)。
  • 一个二元运算符,其第一个操作数是一个与has_deref不匹配的表达式,第二个操作数是一个表达式。

Here是一个示例,它检查多个表达式是否与这个新语法匹配(扩展为检查最多2个参数的函数):

has_deref