!standard 13.01 (10) 99-07-28 AI95-00137/02 !class binding interpretation 96-05-07 !status Corrigendum 2000 99-07-28 !status WG9 approved 96-12-07 !status ARG approved 6-0-2 96-06-17 !status work item 96-05-08 !status received 96-05-07 !priority High !difficulty Medium !subject Attribute definition clause for Stream Attributes !summary 13.1(10) says: 10 For an untagged derived type, no type-related representation items are allowed if the parent type is a by-reference type, or has any user-defined primitive subprograms. This rule does not apply to an attribute_definition_clause for one of the stream-oriented attributes Read, Write, Input, and Output. !question 13.1(10) seems to forbid the following example: with Ada.Streams; use Ada.Streams; generic type T is private; package Attr_Rep is type NT is new T; procedure Attribute_Write( Stream : access Root_Stream_Type'Class; Item : in NT); for NT'Write use Attribute_Write; -- Illegal? (No.) end Attr_Rep; !recommendation (See summary.) !wording (See corrigendum.) !discussion The intent of 13.1(10) is to forbid two types from having different representation in certain cases. However, the stream-oriented attributes, although they are formally defined to be "representation attributes", do not actually affect the representation of the type. Therefore, there is no need for 13.1(10) to apply to these attributes. Furthermore, as the example illustrates, applying the rule to these attributes would seriously hinder their usefulness. !corrigendum 13.01(10) @drepl For an untagged derived type, no type-related representation items are allowed if the parent type is a by-reference type, or has any user-defined primitive subprograms. @dby For an untagged derived type, no type-related representation items, other than the stream-oriented attributes Read, Write, Input, and Output, are allowed if the parent type is a by-reference type, or has any user-defined primitive subprograms. !corrigendum 13.01(11) @drepl Representation aspects of a generic formal parameter are the same as those of the actual. A type-related representation item is not allowed for a descendant of a generic formal untagged type. @dby Representation aspects of a generic formal parameter are the same as those of the actual. A type-related representation item, other than the stream-oriented attributes Read, Write, Input, and Output, is not allowed for a descendant of a generic formal untagged type. !ACATS test Create a C-Test to verify that Read/Write attributes can be defined on derived non-tagged types. !appendix !section 13.1(10) !subject Attribute definition clause for Stream Attributes !reference RM95-13.1(10) !reference RM95-13.1(11) !reference RM95-13.13.2(36) !from Anthony Gargaro 96-04-28 !keywords !reference 96-5519.a Anthony Gargaro 96-4-28>> !discussion stream attributes, representation items A consequence of specifying attribute definition clauses for the stream attributes is that the restrictions associated with representation items hamper the use of stream attributes. For example, the following idiom is illegal by 13.1(11). with Ada.Streams; use Ada.Streams; generic type T is private; package Attr_Rep is type NT is new T; procedure Attribute_Write( Stream : access Root_Stream_Type'Class; Item : in NT); -- Illegal use of attribute definition clause for NT'Write use Attribute_Write; end Attr_Rep; package body Attr_Rep is procedure Attribute_Write( Stream : access Root_Stream_Type'Class; Item : in NT) is begin -- Save type information for dispatching Write and then call T'Write(Stream, T(Item)); end Attribute_Write; end Attr_Rep; Since allowing such idioms facilitates reading/writing streams that are architecture neutral, consideration should be given to relaxing the application of 13.1(10,11) to representation-independent attributes. **************************************************************** !section 13.1(10) !subject Attribute definition clause for Stream Attributes !reference RM95-13.1(10) !reference RM95-13.1(11) !reference RM95-13.13.2(36) !keywords stream attributes, representation items !reference 96-5519.a Anthony Gargaro 96-4-28 !keywords stream attributes, representation items !from Norman Cohen 96-04-29 !reference 96-5521.a Norman H. Cohen 96-4-29>> !discussion Interestingly, 13.1(11) does not prohibit the following workaround: with Ada.Streams; use Ada.Streams; generic type T is private; package Attr_Rep is type NT is record Only_Component: T; end record; procedure Attribute_Write( Stream : access Root_Stream_Type'Class; Item : in NT); for NT'Write use Attribute_Write; end Attr_Rep; package body Attr_Rep is procedure Attribute_Write( Stream : access Root_Stream_Type'Class; Item : in NT) is begin -- Save type information for dispatching Write and then call T'Write(Stream, Item.Only_Component); end Attribute_Write; end Attr_Rep; Of course this is a nuisance: NT doesn't inherit T's operations, so one always has to invoke Op(X.Only_Component) instead of Op(X). One can define corresponding operations for type NT manually, but there is no way to allow direct conversions between descendents of NT and types that are truly in the derivation class for T. (One wishes to use NT rather than T in constructing new types, so that the 'Write for the new type invokes NT'Write.) On the one hand, the existence of such a loophole indicates that there is no fundamental problem with the relaxation Anthony suggests. On the other hand, the existence of the loophole may make resolution of the problem a little less of an emergency. **************************************************************** !section 13.1(10) !subject Attribute definition clause for Stream Attributes !reference RM95-13.1(10) !reference RM95-13.1(11) !reference RM95-13.13.2(36) !keywords stream attributes, representation items !reference 96-5519.a Anthony Gargaro 96-4-28 !keywords stream attributes, representation items !reference 96-5521.a Norman H. Cohen 96-4-29 !from Bob Duff !reference 96-5542.a Robert A Duff 96-5-8>> !discussion Norm says: > Interestingly, 13.1(11) does not prohibit the following workaround: > [workaround involving wrapping the type in a record] Right. Another workaround is to simply make the thing a tagged type, since 13.1(11) applies only to untagged types. - Bob **************************************************************** !section 13.1(10) !subject Attribute definition clause for Stream Attributes !reference RM95-13.1(10) !reference RM95-13.1(11) !reference RM95-13.13.2(36) !reference 96-5519.a Anthony Gargaro 96-4-28 !reference 96-5521.a Norman H. Cohen 96-4-29 !reference 96-5542.a Robert A Duff 96-5-8 !from Anthony Gargaro 96-05-10 !reference 96-5546.a Anthony 96-5-10>> !discussion >>Norm says: >> Interestingly, 13.1(11) does not prohibit the following workaround: >> [workaround involving wrapping the type in a record] to which Bob replied: >Right. Another workaround is to simply make the thing a tagged type, >since 13.1(11) applies only to untagged types. In the context of the application where this issue was raised both of these options were considered. Unfortunately, neither seems satisfactory since the useability of the abstraction which is presented to the programmer is compromised. This is because the idiom requires the incremental composition of types to allow arbitrary user-defined types to be associated with "architecture neutral" stream attributes. In the case of wrapping the type (which is used at the moment), there is a useability penalty. The programmer must be aware of the wrapper name when referencing subcomponents of the type and this may become onerous if the composite type contains other composite types. ****************************************************************