Boost Proto - Grammaire et Fonctions
Bonjour à tous,
J'essaie de me mettre à boost.proto mais j'ai un petit problème dès les premiers exemples du users'guide notamment celui où l'on cherche à faire un petit calculateur permettant d'écrire des trucs comme:
Code:
1 2 3
|
auto const& f=_1*_1-_1;
std::cout << f(3) << std::endl; //affiche "6" |
mais surtout des trucs comme:
Code:
1 2 3
|
auto const& g= square(_1)-_1;
std::cout << g(3) << std::endl; //affiche "6" |
Ce que j'arrive pas à faire c'est à valider par une grammaire le deuxième exemple.
Voici l'exemple:
tout d'abord les includes nécessaires:
Code:
1 2 3 4 5 6 7 8 9
|
#include <iostream>
#include <vector>
#include <algorithm>
#include <boost/mpl/int.hpp>
#include <boost/proto/core.hpp>
#include <boost/proto/context.hpp>
namespace proto = boost::proto; |
ensuite la fonction square:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| // Define a square_fun function object
struct square_fun
{
typedef double result_type;
double operator()(double d) const
{
return std::pow(d, 2);
}
};
// Define a lazy square() function for the calculator EDSL.
template< typename Arg >
typename proto::result_of::make_expr<
proto::tag::function // Tag type
, square_fun // First child (by value)
, Arg const & // Second child (by reference)
>::type const
square(Arg const &arg)
{
return proto::make_expr<proto::tag::function>(
square_fun() // First child (by value)
, boost::ref(arg) // Second child (by reference)
);
} |
ensuite la grammaire des expressions possibles:
Code:
1 2 3 4 5 6 7 8 9 10 11 12
|
struct calculator_grammar
: proto::or_<
proto::plus< calculator_grammar, calculator_grammar >
, proto::minus< calculator_grammar, calculator_grammar >
, proto::minus< double, calculator_grammar >
, proto::multiplies< calculator_grammar, calculator_grammar >
, proto::divides< calculator_grammar, calculator_grammar >
, proto::terminal< proto::_ >
//ici je ne sais pas quoi mettre pour valider les expressions à base de square
>
{}; |
et enfin le reste du code avec le contexte, le domaine et le calculateur:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| struct calculator_context : proto::callable_context< calculator_context const >
{
// Values to replace the placeholders
std::vector<double> args;
// Define the result type of the calculator.
// (This makes the calculator_context "callable".)
typedef double result_type;
// Handle the placeholders:
template<int I>
double operator()(proto::tag::terminal, boost::mpl::int_<I>) const
{
return this->args[I];
}
};
// Forward-declare an expression wrapper
template<typename Expr>
struct calculator;
// Define a calculator domain. Expression within
// the calculator domain will be wrapped in the
// calculator<> expression wrapper.
struct calculator_domain
: proto::domain< proto::generator<calculator>/*, calculator_grammar*/ >
{};
// Define a calculator expression wrapper. It behaves just like
// the expression it wraps, but with an extra operator() member
// function that evaluates the expression.
template<typename Expr>
struct calculator
: proto::extends<Expr, calculator<Expr>, calculator_domain>
{
typedef
proto::extends<Expr, calculator<Expr>, calculator_domain>
base_type;
calculator(Expr const &expr = Expr())
: base_type(expr)
{}
typedef double result_type;
// Overload operator() to invoke proto::eval() with
// our calculator_context.
double operator()(double a1) const
{
calculator_context ctx;
ctx.args.push_back(a1);
return proto::eval(*this, ctx);
}
};
// Define the Protofied placeholder terminals
calculator<proto::terminal<boost::mpl::int_<0> >::type> const _1;
int main()
{
auto const& f = _1*_1 - _1;
std::cout << f(3) << std::endl;
auto const& g = square(_1) - _1;
std::cout << g(3) << std::endl;
return 0;
} |
Le truc c'est que si j'active ma grammaire mon exemple avec f compile mais pas celui avec g (normal ça respecte pas ma grammaire). Donc voilà, comment je peux ajouter square(calculator_grammar) à ma grammaire?