!standard 12.06(00) 03-12-05 AC95-00086/01 !standard 03.09.02(16) !standard 03.04.01(05) !class amendment 03-12-05 !status received no action 03-12-05 !status received 03-10-30 !subject Can't pass limited constants into a generic !summary !appendix !topic "=" on class-wide types as generic actual subprogram !reference 12.6, 3.9.2(16), 3.4.1(5) !from Adam Beneschan 10-30-03 !discussion I've noticed two separate examples lately where publicly available source code expects a generic formal subprogram named "=" to default to a subprogram whose parameters are of a class-wide type. The first example was briefly discussed here in August, and was posted by the author, Martin Krischik. A simplified example: generic type Item (<>) is abstract tagged private; with function "=" (L, R : Item'Class) return Boolean is <>; package Pkg is ... This normally cannot be instantiated with any type unless the actual for "=" is explicitly specified, because if you instantiate it like this: package New_Pkg is new Pkg (Type_1); 12.6(6) and 8.6(26) say that the actual for "=" must be type-conformant with the formal subprogram declaration, and since there is no predefined subprogram with this profile: function "=" (L, R : Type_1'Class) return Boolean; the instantiation will fail unless such a function is explicitly declared. A similar example comes from a Doubly_Linked_List package by R. A. Matthews and is part of the Gapse project. The generic declaration is: generic type Data_Type (<>) is private; with function "=" (Left, Right : Data_Type) return Boolean is <>; package Doubly_Linked_List is ... and one of the examples he provides, contains this code: type Variant_Type is abstract tagged null record; package Variant_Lists is new Doubly_Linked_List (Variant_Type'Class); This instantiation is illegal for the same reason. I haven't tried to look at Martin's code closely, but it's pretty clear how this construct could be useful in the Doubly_Linked_List case. One of the functions defined by Doubly_Linked_List is "=" on a list type, which tests whether all elements of the list are the same. To do this if the actual for Data_Type is a tagged type, you would want to use a user-defined "=" function defined for the type; furthermore, you would want the ability to instantiate with a class-wide type so you could create a heterogeneous list, and have "=" inside the generic work the same way it would for parameters of a class-wide type, as described by 3.9.2(16) (returns FALSE if the tags are different, otherwise dispatches to the correct "=" function). But the above won't get the job done. Note that while 3.9.2(16) defines how "=" works on classwide parameters, it doesn't cause a predefined "=" function to be created that could be used as a generic actual parameter. Since there are two pieces of public code that try to use this capability, should the language be modified so that they will work legally? I'm thinking that 12.6(10) could be extended to read: "If a generic unit has a subprogram_default specified by a box, and the corresponding actual parameter is omitted, then it is equivalent to an explicit actual parameter that is a usage name identical to the defining name of the formal. If there is no visible subprogram that is type-conformant with the profile of the formal subprogram, and if the formal subprogram is a function whose name is the equality operator, and if the parameters to this function are of a class-wide type, then the actual is an implicit subprogram whose profile matches the profile of the formal subprogram and which returns the result of a function_call on the equality operator as defined by 3.9.2(16)." I'm sure I didn't get the wording quite right, but it could be something like that. Comments? *************************************************************** From: Tucker Taft Sent: Thursday, October 30, 2003 9:48 PM Although class-wide types are generally permitted as actual types if the formal has unknown discriminants, the rules are not spelled out clearly in the manual. The "=" operator is just the tip of the iceberg. If the formal type is a formal extension, things are even weirder, since the formal has a full set of primitives, even though the actual does not. I think there is an AI which talks about all this, but in general we have swept this whole area under the rug, and just hoped that implementors "do the right thing." After a little bit of looking, it appears that AI-158 is the one that talks about this. The current version of AI-158 is pretty yucky in my view, but the ARG has not discussed it recently, and I suspect we won't unless someone forces the issue. Perhaps Pascal is listening? How about one more round on AI-158 at the next ARG meeting? **************************************************************** From: Randy Brukardt Sent: Thursday, October 30, 2003 10:19 PM It was on the agenda for Sydney (it was recently rewritten by Gary Dismukes). But we didn't look at any regular AIs (well, except 2 really easy ones in the last 10 minutes of Saturday night). Until we catch up with amendments, it probably will stay that way. I'm going to review the regular AIs so that we can use our limited time on them on the ones that are more likely to matter to users and/or implementors. But of course those are the hardest. *************************************************************** From: Tucker Taft Sent: Thursday, October 30, 2003 10:48 PM I think this one is worth some of our time, though maybe not until the February meeting. Even ignoring renaming, I can't find where we describe the semantics of a call on a primitive in an instantiation using a class-wide actual. I hope the semantics are of a wrapper that takes class-wide parameters, and then does a dispatching call. I would hope that renaming is essentially identical to that. Renaming as body provides a good model. I think Adam is essentially asking that when a class-wide type is an actual, these same kind of wrappers be provided as default when a formal subprogram matching a primitive of the formal type has a default of <>, and the (dispatching) primitive of the specific type associated with the actual class-wide type is directly visible. **************************************************************** From: Adam Beneschan Sent: Friday, October 31, 2003 10:57 AM Essentially, yes; but one of the examples I provided was a case where the actual was not a class-wide type: generic type Item (<>) is abstract tagged private; with function "=" (L, R : Item'Class) return Boolean is <>; package Pkg is ... Here there's a problem even if the actual for Item is not a class-wide type. I'm not sure whether the same principles apply. **************************************************************** From: Tucker Taft Sent: Friday, October 31, 2003 11:38 AM I was ignoring that one, because that seems like a clear bug to me. The user should have written: with function "="(L, R : Item) return Boolean is <>; instead. **************************************************************** From: Adam Beneschan Sent: Friday, October 31, 2003 12:55 PM Yes, I forgot that in a previous discussion, we agreed that if the generic formal function is declared with class-wide type parameters, then any call to "=" in the generic body with parameters of type Item or Item'Class is ambiguous. **************************************************************** From: Martin Krischik Sent: Sunday, November 2, 2003 5:40 AM > The user should have written: > > with function "="(L, R : Item) return Boolean is <>; > > instead. I like to point out that I have indeed corrected the statement. ****************************************************************