Boost logo

Boost Users :

Subject: Re: [Boost-users] [proto] declaring result type for callable contexts
From: Eric Niebler (eric_at_[hidden])
Date: 2009-06-05 18:41:33


Maurizio Vitale wrote:
>
> Ok, while reducing the code to something small enough for posting I
> think I've got what was wrong. Let's see if it makes sense to you:
>
> [if my prose is too long and makes little sense, you can find my code
> attached to this message]
>
> - my context inherits from callable_context and defines a
> result_type. But it doesn't define (yet) any overload for the
> arithmetic operations.
>
> - I then have a data structure that I use for terminals.
> This also has no arithmetic operators defined. BUT it
> has conversion operators to some basic types (was int, it is now
> double to see where the type was coming from)
>
> What I think happens is that the default_context is asked to
> evaluate expression, knows jack about my data type but happily see
> a conversion operator to a builtin type, use it and then does
> arithmetic over it using the builtin arithmetic operator.
>
> So proto reports the right type for the evaluation of the
> expression, it is just that it is not what I declared with
> result_type.

Correct.

> Maybe it would be good to add an assertion for this
> case, as forgetting even one overload under the appropriate
> circumstances (e.g. conversion operator to a builtin type) can
> cause a not immediately diagnosable problem.

The way callable_context is currently defined is by-design, but rather
poorly documented at the moment. The "result_type" typedef essentially
says, "of the expression types I (the callable context) handle with
explicit overloads (in your case, none), the return type is X.
Everything else I leave to the fallback context. Ask it what the
resulting type is." In this way that you can easily chain and layer
contexts.

In your case, the fallback context is the proto::default_context, which
does "the C++ thing" with your expression. Consider:

struct data { operator double() const { return 0.; } };
data a,b;
double r = a*b; // OK, a and b are implicitly converted
                 // to doubles and multiplied

This is essentially what your code is doing.

> In the small example I cannot reproduce one aspect of what I was seeing,
> namely that putting result_type inside a struct eval made proto return
> what I was expecting (it would have been wrong, but I had enough
> conversion operators/constructor to make it work on the surface).
> My guess is that in that case proto believes in my eval and doesn't use
> the callable_context one which in turns would use my context and then
> falling back on default context.

Adding your own eval struct template would hide the one defined in
callable_context. You might get the right return type, but now any
operator overloads you define in your systemc_context will be ignored.

HTH,

-- 
Eric Niebler
BoostPro Computing
http://www.boostpro.com

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net