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.
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
}