Overview of Type Queries¶
Type queries let compile-time code inspect an expression's type, compare types, and ask about physical layout or integer properties. Deduction patterns let a generic function bind a type from its arguments.
Type inspection¶
::type_queries STATIC_TEST
{
VAR value I32 := 12;
ASSERT(SAME_TYPES(DECLTYPE(value), I32));
ASSERT(SAME_TYPES(TYPEOF(value), MUT& I32));
ASSERT(SIZEOF(I32) == 4);
ASSERT(BITS(I32) == 32);
ASSERT(IS_SIGNED(I32));
}
DECLTYPE reports the declared value type. TYPEOF preserves the expression's
reference qualification. SIZEOF, ALIGNOF, and BITS report layout and
integer facts where the target provides them.
An empty Quxlang structure has size zero and alignment one on a physical-layout target:
::empty STRUCT
{
}
::empty_layout STATIC_TEST
{
STATIC_IF(ARCH_IS_LAYOUTLESS == FALSE)
{
ASSERT(SIZEOF(empty) == 0);
ASSERT(ALIGNOF(empty) == 1);
}
}
An ARCH_IS_LAYOUTLESS == FALSE condition restricts layout queries to targets
that define object layout.
Polymorphism queries¶
TYPE_IS_POLYMORPHIC(T) returns a compile-time BOOL. Both polymorphic struct
categories return TRUE; other concrete types return FALSE:
::message STRUCT POLYMORPHIC {}
::shared_message STRUCT VIRTUAL_POLYMORPHIC {}
::plain_message STRUCT {}
::polymorphism_queries STATIC_TEST
{
ASSERT(TYPE_IS_POLYMORPHIC(message));
ASSERT(TYPE_IS_POLYMORPHIC(shared_message));
ASSERT(TYPE_IS_POLYMORPHIC(plain_message) == FALSE);
ASSERT(TYPE_IS_POLYMORPHIC(I32) == FALSE);
ASSERT(TYPE_IS_POLYMORPHIC(CONST->message) == FALSE);
}
The query tests its type operand directly; the query does not follow a pointer
to the pointee type. TYPE_IS_POLYMORPHIC does not construct an object and is
available on layoutless targets.
Runtime type identification¶
TYPE_INDEX_OF(T) identifies a statically named type. DYNAMIC_TYPE_OF(ptr)
identifies the complete polymorphic object through a base pointer:
::timed_message STRUCT POLYMORPHIC
{
.base_part BASE message;
.timestamp VAR I64;
}
::dynamic_identity STATIC_TEST
{
VAR object timed_message;
VAR pointer CONST->message := object<-;
ASSERT(DYNAMIC_TYPE_OF(pointer) == TYPE_INDEX_OF(timed_message));
}
This example requires a native target. DYNAMIC_TYPE_OF requires a readable
pointer to a polymorphic struct; using a nonpolymorphic struct pointer does not
compile. A null pointer causes undefined behavior. During construction and
destruction, the result follows the active constructor or destructor type.
Argument type deduction¶
AUTO(t) binds the non-reference value type. TT(t) retains the presented
type, including a reference. DECAY(t) is useful for forwarding: it preserves
lvalue references but turns an expiring TEMP& into an owned value type.
Reusing a deduction name requires every occurrence to agree on the same bound type.
Public struct fields¶
Public Field Reflection inspects the fields of
named structs. PUBLIC_FIELD_COUNT, PUBLIC_FIELD_NAME, and
PUBLIC_FIELD_CONTAINS inspect the public field list; PUBLIC_FIELD_TYPE
reports a declared field type, and PUBLIC_FIELD_GET projects a field from
an object. Public field indices follow declaration order.
Composite reflection¶
Composites expose field counts,
names, declared types, and field projections through COMPOSITE_* operations.
DECLTYPE(record) supplies the type operand for metadata queries.
COMPOSITE_FIELD_GET accesses a field selected at compile time.
Reference¶
See the Type Queries and Deduction Reference for every query, layoutless behavior, exact deduction transformations, and overload-ranking relationships.