Skip to content

Instantly share code, notes, and snippets.

@rikkimax
Last active February 19, 2020 17:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rikkimax/046fb4451e8cbac354ecb292f9a76798 to your computer and use it in GitHub Desktop.
Save rikkimax/046fb4451e8cbac354ecb292f9a76798 to your computer and use it in GitHub Desktop.
template parameters as properties of a type + first class type support DIP idea's

First class types

Abstract

First class types is a way to represent types during runtime and compile time without using template parameters. When used at compile time in functions these functions become type functions.

Semantics

For each class bottom-most TypeInfo a new child will be created in the form of TypeInfo_Name_Typed. This new child will be defined as:

class TypeInfo_Name_Typed(T) : TypeInfo_Name {
    alias Type = T;
}

Where Name is substituted for the indevidual TypeInfo_<Name>.

At runtime TypeInfo_Name_Typed will be implicitly cast to its parent type. At compile time a TypeInfo_Name_Typed will behave as a type and must be typeid'd to get access to the TypeInfo like you would normally do.

The syntax at compile time is typeid.

An example of this is:

typeid maxSize(typeid A, typeid B) {
    return A.sizeof > B.sizeof ? A : B;
}

Under the hood it was rewritten to:

auto maxSize(TypeInfo_RealA_Typed A, TypeInfo_RealB_Typed B) {
    return A.Type.sizeof > B.Type.sizeof ? A : B;
}

This works because the restriction of the return type is amended to allow it to be resolved to be a TypeInfo_Name_Tagged when a typeid is used as part of a return statement.

An example of this in action using maxSize as the base:

void someFunc(C, D)(C something, D somethingElse) {
    typeid largestOf = maxSize(C, D);
    
    pragma(msg, largestOf.sizeof); // ok largestOf is accessible as a type at CT
    writeln(largestOf.sizeof); // ok the expression is ran at CT
    writeln(largestOf.name); // ok, largestOf is a TypeInfo_Name here as this is RT
}

Template parameters as properties of a type

Description

In D some template parameters are used to assign a value to which needs to be accessible outside of the type. Instead of extracting the property out of the template parameter list or using a different name instead of the name in the template parameter list, this DIP gives a single syntax which treats a member of a type as if it was a template parameter.

This DIP depends on Walter's named arguments DIP to provide the syntax and semantics of assigning the value/type to the property.

Semantics

This DIP adds the ability for auto to be used as a field type in a struct/class/union.

A field can either be an auto or typeof(auto).

If it is an typeof(auto) this represents a template parameter that is a type. If it is an auto this represents a template parameter this is a value.

auto was chosen as keyword of preference due to enum T and alias T being already used and is not currently valid as a type for a type member field.

Both must be assigned via a template argument syntax and the declaration must be within an @property {} block.

The property may not need to be assigned to if it has a default value.

An example of this syntax is:

struct StructWithProperties {
    @property {
        typeof(auto) SomeType;
        auto Threshold;
    }
    
    static assert(is(typeof(Threshold) == int) && Threshold >= 0 && Threshold < 10, "Threshold must be equal or above 0 and less than 10");
}

static assert(StructWithProperties!(SomeType: Object, Threshold: 2).Threshold == 2);

is equivalent to:

struct StructWithProperties(SomeTypeParam, int ThresholdParam) {
    alias SomeType = SomeTypeParam;
    enum Threshold = ThresholdParam;

    static assert(Threshold >= 0 && Threshold < 10, "Threshold must be equal or above 0 and less than 10");
}

static assert(StructWithProperties!(SomeTypeParam: Object, ThresholdParam: 2).Threshold == 2);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment