あなたの定義によると、has_deref
文法は次のいずれかの式に一致します。
- ANY 式に適用される逆参照演算子
- 引数が文法に再帰的に一致する任意のn項(単項:
complement
、negate
またはunary_plus
subscript
plus
if_else_
function
has_deref
あなたの例では、のplus<terminal<int>,dereference<terminal<int> > >
ようなものがありbinary_expr<tag::plus,terminal<int>,unary_expr<tag::dereference,terminal<int> > >
ます。表現を一致させようとすると (私が思うに)、Proto は最初に文法の最初の要素 ( dereference<_>
) を試み、明らかに失敗します。次に、2 番目のものを試してbinary_expr<tag::plus,...>
一致nary_expr<_,...>
させるため、文法を の両方の引数式に再帰的に一致させようとしplus
ます。2 番目のものは直接一致しますが、最初のもの ( terminal<int>
) はいずれの可能性とも一致しないため、式全体が一致しません。
あなたが望むことをするための可能な(そして悲しいことに不格好な)アプローチの1つは、次のようなものです。
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>
>
{};
次のいずれかの式に一致します。
- ANY 式に適用される間接参照演算子。
- 再帰的に一致する式に適用される単項演算子
has_deref
。
has_deref
第 1 オペランドが一致する式で、第2 オペランドが ANY 式 (一致する式を含む)である二項演算子has_deref
。
- 最初のオペランドが一致しない式で
has_deref
、2 番目のオペランドが一致する式である二項演算子。
以下は、複数の式がこの新しい文法に一致することを確認する例です (最大 2 つの引数を持つ関数も確認するように拡張されています)。
#include <iostream>
#include <boost/proto/proto.hpp>
namespace proto = boost::proto;
using proto::_;
template <typename Grammar>
struct function_contains_at_least_one : proto::or_<//this is awful, there should be a better way
proto::function<Grammar>,
proto::function<Grammar,_>,
proto::function<_,Grammar>,
proto::function<Grammar,_,_>,
proto::function<_,Grammar,_>,
proto::function<_,_,Grammar>
>
{};
struct has_deref : proto::or_< //ignoring if_else_
proto::dereference<_>,
proto::unary_expr<_,has_deref>,
proto::binary_expr<_, _,has_deref>,
proto::binary_expr<_,has_deref,_>,
function_contains_at_least_one<has_deref>
>
{};
template<class Expr>
void test_expr(const std::string& repr, const Expr &e)
{
std::cout << repr << " matches 'has_deref'? " << std::boolalpha << proto::matches<Expr,
has_deref>::value << std::endl;
//display_expr(e);
}
#define TEST_EXPR( EXPR ) test_expr(#EXPR,EXPR)
int main()
{
using proto::lit;
TEST_EXPR(lit(1) + lit(2));
TEST_EXPR(lit(1) + *lit(2));
TEST_EXPR(*lit(1) + *lit(2));
TEST_EXPR(*(lit(1) * (lit("foo")+lit(2))));
TEST_EXPR(+-*lit(1)[~*lit(2)++]);
//testing functions
TEST_EXPR( lit(1)() );
TEST_EXPR( (*lit(1))() );
TEST_EXPR( lit(1)(lit(2)) );
TEST_EXPR( (*lit(1))(lit(2)) );
TEST_EXPR( lit(1)(*lit(2)) );
TEST_EXPR( lit(1)(lit(2),lit(3)) );
TEST_EXPR( (*lit(1))(*lit(2),*lit(3)) );
}