![]() |
Home | Libraries | People | FAQ | More |
By default, Proto defines every possible operator overload for Protofied
expressions. This makes it simple to bang together an EDSL. In some cases,
however, the presence of Proto's promiscuous overloads can lead to confusion
or worse. When that happens, you'll have to disable some of Proto's overloaded
operators. That is done by defining the grammar for your domain and specifying
it as the second parameter of the proto::domain<>
template.
In the Hello Calculator section, we saw an example of a Proto grammar, which is repeated here:
// Define the grammar of calculator expressions struct calculator_grammar : proto::or_< proto::plus< calculator_grammar, calculator_grammar > , proto::minus< calculator_grammar, calculator_grammar > , proto::multiplies< calculator_grammar, calculator_grammar > , proto::divides< calculator_grammar, calculator_grammar > , proto::terminal< proto::_ > > {};
We'll have much more to say about grammars in subsequent sections, but
for now, we'll just say that the calculator_grammar
struct describes a subset of all expression types -- the subset that
comprise valid calculator expressions. We would like to prohibit Proto
from creating a calculator expression that does not conform to this grammar.
We do that by changing the definition of the calculator_domain
struct.
// Define the calculator_domain. Expressions in the calculator // domain are wrapped in the calculator<> wrapper, and they must // conform to the calculator_grammar: struct calculator_domain : proto::domain< proto::generator< calculator >, calculator_grammar > {};
The only new addition is calculator_grammar
as the second template parameter to the proto::domain<>
template. That has the effect of disabling any of Proto's operator overloads
that would create an invalid calculator expression.
Another common use for this feature would be to disable Proto's unary
operator&
overload. It may be surprising for users of your EDSL that they cannot
take the address of their expressions! You can very easily disable Proto's
unary operator&
overload for your domain with a very simple grammar, as below:
// For expressions in my_domain, disable Proto's // unary address-of operator. struct my_domain : proto::domain< proto::generator< my_wrapper > // A simple grammar that matches any expression that // is not a unary address-of expression. , proto::not_< proto::address_of< _ > > > {};
The type proto::not_<
proto::address_of<
_ >
>
is a very simple grammar
that matches all expressions except unary address-of expressions. In
the section describing Proto's intermediate form, we'll have much more
to say about grammars.