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 : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
 
auto const& f=_1*_1-_1;
std::cout << f(3) << std::endl; //affiche "6"
mais surtout des trucs comme:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 : Sélectionner tout - Visualiser dans une fenêtre à part
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 : Sélectionner tout - Visualiser dans une fenêtre à part
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 : Sélectionner tout - Visualiser dans une fenêtre à part
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 : Sélectionner tout - Visualiser dans une fenêtre à part
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?