To: J3 J3/18-113r1 From: Van Snyder Subject: New types, not type aliases, from existing types Date: 2018-February-13 Reference: 13-220, 04-146r1; 2004 hate-dislike-like-love score 0-1-9-1 Number ====== TBD Submitted by ============ J3 Status ====== For consideration. Basic Functionality =================== Provide a facility to define new types, not type aliases, from existing types. Rationale ========= New types can be used for every purpose for which type aliases are desired, but there are many things a new type can do that a type alias cannot. Type aliases (not new types) were in several drafts for the purpose of | C interoperability. All of the functionality specified to justify | that project is available by using new types instead of type aliases. | Type aliases are not useful for generic resolution, and do not provide | strong type checking in expressions, assignment, or procedure | references. | | One of the examples from C interoperability was | | typedef time_t long; | time_t TimeNow; | | interoperates with | | use ISO_C_Binding, only: C_Long | integer(c_long) :: TimeNow | | but there was a desire for | | typealias :: Time_t => integer(c_long) | type(time_t) :: TimeNow | | In this proposal it would be | | type, new :: Time_t => integer(c_long) | type(time_t) :: TimeNow | | The difference is that now TimeNow can be used for generic resolution. | Here's one example where a new type solves a problem and a type alias doesn't. Suppose you have the requirement to evaluate something using, say, rational approximations, and in some cases you need six digits of precision while in other cases you need twelve. Assume the twelve-digit case is sufficiently more expensive that you want to use the six-digit version where possible. With two routines, you use SELECTED_REAL_KIND to declare their characteristics, and glue them together with a generic name. You develop and certify them on a 32-bit machine. Then you send your whole program off to production and they can't even compile it because they use a 64-bit machine where SELECTED_REAL_KIND(6) and SELECTED_REAL_KIND(12) have the same value. Estimated Impact on Standard ============================ Minor. Detailed Specification ====================== Provide syntax to define a new type in terms of an existing one. Objects of the type from which new types are created are compatible with objects of those new types, provided corresponding type parameters have the same values. New types inherit operations and type-bound procedures from the type from which they are created. Compatibility and inheritance are already well-described concepts that can be exploited to simplify description of new type definitions. Type parameter values for the original type may be specified during the definition of a new type. Objects of the new type have those type parameter values, which cannot be specified during declaration of objects of the new type. If values are not specified for type parameters of the original type, values for those parameters shall be specified during declarations of objects of the new types. An already-existing almost-similar example is the type DOUBLE | PRECISION. Objects of that type have the same kind type parameter value as objects of type REAL(kind(0.0d0)), and a kind type parameter value cannot be specified during declaration of objects of type DOUBLE PRECISION. It is different from this proposal in that DOUBLE | PRECISION is the same as type REAL(kind(0.0d0)) | Concrete syntax can be decided in due course. Example: type, new :: Real6 => Real(selected_real_kind(6)) type, new :: Real12 => Real(selected_real_kind(12)) or new type :: Real6 => Real(selected_real_kind(6)) new type :: Real12 => Real(selected_real_kind(12)) wherein the blank in "new type" is optional. Types Real6 and Real12 are distinct types, even if their type parameter values are the same. Therefore generic interfaces continue to work, even if SELECTED_REAL_KIND(6) and SELECTED_REAL_KIND(12) have the same value. Generic programming using, e.g. parameterized modules, is not helpful | for this problem because the procedures would be almost completely | different, although the argument and result types could be | parameterized. This is only marginally helpful. |