$include_dir="/home/hyper-archives/boost-users/include"; include("$include_dir/msg-header.inc") ?>
Subject: Re: [Boost-users] proto: analytical-only math functions
From: Eric Niebler (eric_at_[hidden])
Date: 2009-03-05 12:53:34
Hicham Mouline wrote:
> Eric Niebler wrote:
>> You really need to reread the section on domains again. The parameter to 
>> proto::generator must be an expression extension class template.
>> That's all I have for now. Good luck. And be sure to check the docs, 
>> because you could have found many of these answers there.
> 
> The complication comes in my case from the fact that the grammar is not
> stand alone type but an inner-type.
Why does that make a difference?
> I have a new question. I am trying to make my basic functions (the cmath
> ones)
> lazy functions as in the user guide.
> 
> // to represent the c++03 math functions
> // c++0x math functions are commented out.
> template < double (*basic_function_ptr)(double) >
> struct basic_function_tag {
>   typedef double result_type;
>   result_type operator()(double d) const { return basic_function_ptr(d); } 
> };
> 
> proto::terminal< basic_function_tag<std::sin> >::type const sinfct = {{}};
> 
> // Define a lazy sin
> // 
> template<typename Arg>
> typename proto::result_of::make_expr<
>   proto::tag::function,                            // Tag type
>   basic_function_tag<std::sin>,          // First child (by value)
>   Arg const &                                      // Second child (by
> reference)
>> ::type
> sin(Arg const &arg)
> {
>     return proto::make_expr<proto::tag::function>(
>       basic_function_tag< std::sin >(),   // First child (by value)
>       boost::ref(arg)                             // Second child (by
> reference)
>     );
> }
> 
> This should work for sin( literals and c++ vars ) and for sin( proto
> expressions ).
> 
> As in my grammar I used to accept basic functions as proto terminals ,
> How can I change the grammar to take this new sin() instead?
Well, what you really want is to say is something like this:
proto::function<
     proto::terminal<basic_function_tag<_> > // Whoops! :-(
   , proto::_
 >
But proto::_ only matches types, not non-type template parameters. What 
you can do instead is something like this:
template<typename T>
struct is_basic_function_tag : mpl::false_ {};
template<double (*F)(double)>
struct is_basic_function_tag<basic_function_tag<F> > : mpl::true_ {};
proto::function<
     proto::and_<
         proto::terminal<_>
       , proto::if_< is_basic_function_tag<proto::_value>() >
     >
   , proto::_
 >
HTH,
-- Eric Niebler BoostPro Computing http://www.boostpro.com