[result_of] result template in case of ambiguity

In the case that a function object is written where certain arguments may yield an ambiguous function call, how should the function object's result template be defined? Should using the result template emit an error upon instantiation, or should it merely not define the type typedef? I see different benefits and drawbacks for each approach and I'd rather not arbitrarily pick one if there is already an established convention for this case. -- -Matt Calabrese

Matt Calabrese wrote:
In the case that a function object is written where certain arguments may yield an ambiguous function call, how should the function object's result template be defined?
If the function object advertises a return type via the result_type typedef, or if the function object is a function pointer or another entity with a fixed return type, result_of returns that type. Otherwise, if a particular argument list results in an ill-formed expression, the application of result_of on that argument list is also ill-formed. Do you have a specific scenario in mind?

On 7/10/06, Peter Dimov <pdimov@mmltd.net> wrote:
Do you have a specific scenario in mind?
Yes. For clarity, it is clear that result_of< Type >::type should be ill-formed with ambiguity, however, should result_of< Type > be instantiable at all when the function call would be ill-formed? In short, I don't see any mention of how instantiations of result_of should behave, I only see mention of when accessing the nested typedef of a result_of instantiation is ill-formed. I guess I should follow what a basic typeof implementation would likely do and yield an error upon instantiation of the template, but I figured I'd ask anyway. To me it seems as though simply not defining the type typedef could possibly be a better approach. My exact situation is that I have a macro which I use for creating complex, potentially overloaded function objects, which also add other functionality necessary for models of concepts my library. The return type, signature, and template parameters for all overloads are all passed into the macro, and the macro automatically generates a nested result template in the process of creating the overall function object. This result template does not rely on any explicit typeof functionality, but rather, it uses the overload information passed to the macro to create dummy static functions and templates representing each overload allowable by the current qualification, giving each a different size return type, and using the size of the return type when passed arguments of the given type to determine which overload would be called. The nested type typedef is then set to the return type of the appropriate overload. With this implementation, I would get an error if the call were ambiguous when the person merely instantiates result (not even trying to access the typedef). Another alternative is that I individually check the overloads and if multiple non-template overloads may be called and there are no template overloads which may be called (or any other combination which results in an ambiguous function call), then I inherit from an empty base, otherwise I inherit from a base which yields the result type in a type typedef using the code I described earlier. Note that this form only produces error if you attempt to access ::type with an ambiguous call, not if you merely instantiate the template. I see different advantages to each approach. With error upon instantiation, you'd likely be getting similar functionality to a simple typeof-style implementation, however, this gives you an error if you simply do something such as work with a type which inherits from the instantiation, regardless of whether or not you actually access the result. -- -Matt Calabrese

Matt Calabrese wrote:
On 7/10/06, Peter Dimov <pdimov@mmltd.net> wrote:
Do you have a specific scenario in mind?
Yes. For clarity, it is clear that result_of< Type >::type should be ill-formed with ambiguity, however, should result_of< Type > be instantiable at all when the function call would be ill-formed?
Instantiating the definition of result_of<Type> causes the instantiation of the declarations of its members, so this would imply that when its nested type member is ill-formed, the definition of result_of<> cannot be instantiated.

On 7/10/06, Peter Dimov <pdimov@mmltd.net> wrote:
Instantiating the definition of result_of<Type> causes the instantiation of the declarations of its members, so this would imply that when its nested type member is ill-formed, the definition of result_of<> cannot be instantiated.
Yes, that's not what I'm asking. What I'm asking is should I have a nested type at all in the case of ambiguity? This would make accessing result_of< Type >::type ill-formed, however, it keeps result_of< Type > instantiable. -- -Matt Calabrese

Matt Calabrese wrote:
On 7/10/06, Peter Dimov <pdimov@mmltd.net> wrote:
Instantiating the definition of result_of<Type> causes the instantiation of the declarations of its members, so this would imply that when its nested type member is ill-formed, the definition of result_of<> cannot be instantiated.
Yes, that's not what I'm asking. What I'm asking is should I have a nested type at all in the case of ambiguity? This would make accessing result_of< Type >::type ill-formed, however, it keeps result_of< Type > instantiable.
In principle, a portable program wouldn't be able to depend on the "instantiability" of result_of<Type> (if we're talking about the TR1 result_of) since TR1 doesn't guarantee it. So you may as well pick whatever is more convenient for you, I guess.

"Matt Calabrese" <rivorus@gmail.com> writes:
On 7/10/06, Peter Dimov <pdimov@mmltd.net> wrote:
Instantiating the definition of result_of<Type> causes the instantiation of the declarations of its members, so this would imply that when its nested type member is ill-formed, the definition of result_of<> cannot be instantiated.
Yes, that's not what I'm asking. What I'm asking is should I have a nested type at all in the case of ambiguity? This would make accessing result_of< Type >::type ill-formed, however, it keeps result_of< Type > instantiable.
AFAIK the only way to accomplish that is with a specialization of result_of that has no nested ::type. Am I missing something? -- Dave Abrahams Boost Consulting www.boost-consulting.com

On Jul 10, 2006, at 3:23 AM, Matt Calabrese wrote:
In the case that a function object is written where certain arguments may yield an ambiguous function call, how should the function object's result template be defined? Should using the result template emit an error upon instantiation, or should it merely not define the type typedef? I see different benefits and drawbacks for each approach and I'd rather not arbitrarily pick one if there is already an established convention for this case.
There is no convention for this. In truth, I don't think it matters much what result_of does, because if one tries to actually do the call that result_of is computing a result type for, compilation will be ill-formed. If I had to choose, I'd say do whatever produces the earliest error messages. Doug
participants (4)
-
David Abrahams
-
Doug Gregor
-
Matt Calabrese
-
Peter Dimov