[proto] declaring result type for callable contexts
Eric,
It seems like result types must be defined inside a struct eval, but
examples in the documentation show the form commented out below.
Is this a recent change?
Also, in absence of a result_type declaration inside struct eval {...}
the type defaults to int. Would it be possible to make it void or
some_ugly_looking_type_that_tell_me_i_is_all_wrong?
int might happen to be what the user wants, until he decide to change
it and hides the problem.
template<typename Expr>
struct my_context : proto::callable_context
Maurizio Vitale wrote:
Eric,
It seems like result types must be defined inside a struct eval, but examples in the documentation show the form commented out below.
Is this a recent change?
Also, in absence of a result_type declaration inside struct eval {...} the type defaults to int. Would it be possible to make it void or some_ugly_looking_type_that_tell_me_i_is_all_wrong? int might happen to be what the user wants, until he decide to change it and hides the problem.
template<typename Expr> struct my_context : proto::callable_context
{ struct eval {typedef double result_type;}; // doesn't work (anymore?) //typedef double result_type; };
There have been no recent changes in this area, though I have been reorganizing some code. The Context concept (ugh, not defined in the reference section, sorry) requires a nested eval struct template with a nested result_type typedef. Users can define a context that satisfies that requirement by inheriting from callable_context, which defines the nested eval<> struct for you, and is implemented in terms of member function overloads within the derived context type. That turns out to be a lot easier in most situations. In short, if you're using callable_context, don't define nested eval<> structs. If you have some code that recently stopped working, you should post it so I can see that the problem is. -- Eric Niebler BoostPro Computing http://www.boostpro.com
"Eric" == Eric Niebler
writes:
Eric> Maurizio Vitale wrote:
>> Eric, It seems like result types must be defined inside a struct
>> eval, but examples in the documentation show the form commented
>> out below.
>>
>> Is this a recent change?
>>
>> Also, in absence of a result_type declaration inside struct eval
>> {...} the type defaults to int. Would it be possible to make it
>> void or some_ugly_looking_type_that_tell_me_i_is_all_wrong? int
>> might happen to be what the user wants, until he decide to change
>> it and hides the problem.
>>
>> template<typename Expr> struct my_context :
>> proto::callable_context
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
AMDG Maurizio Vitale wrote:
Also, in absence of a result_type declaration inside struct eval {...} the type defaults to int.
Are you by any chance using Sun CC? If so this is a compiler bug. In Christ, Steven Watanabe
"Steven" == Steven Watanabe
writes:
Steven> AMDG Steven> Maurizio Vitale wrote: >> Also, in absence of a result_type declaration inside struct eval >> {...} the type defaults to int. Steven> Are you by any chance using Sun CC? If so this is a Steven> compiler bug. No, but I read another post of yours about SunCC defaulting to int on instantiation failures and since that was what I was getting I started investigating some more. I'm distilling some code that show the problem before replying to Eric, but both gcc 4.3.1 and Intel 11.0 agree on int. Thanks, Maurizio
participants (3)
-
Eric Niebler
-
Maurizio Vitale
-
Steven Watanabe