Template iz

Iz is a helper template that allows you to inspect a type or an alias.

template iz(Aliases...) ;

It takes a single element as an argument. The reason the template parameters is types as a variable arg sequence is becure if D does not allow (pre version 2.087) to say "I want either a type or alias over here, I don't care, I'll figure it out". But it does allow it when you use a template sequence parameter

method Description
of True if the resolved type is the same as another resolved type
sameAs True if T and U are the same "thing" (type, alias, literal value)
nullType True if the resolved type is typeof(null)
unaryOver True if the resolved type a unary funtion over some other types
binaryOver True if the resolved type a binary funtion over some other types
functionOver True if the resolved type an n-ary funtion over n types
refType True if the resolved type a reference type
valueType True if the resolved type a value type
literalOf True if the resolved type is a literal of a type of T
literal True if the resolved type is a literal
copyConstructable True if resolved type is copy constructable
nonTriviallyCopyConstructable True if resolved type is non-trivially copy constructable
triviallyCopyConstructable True if resolved is trivially copy constructable
equatableTo True if resolved type is equatabel to other
nullTestable True if resolved type can be checked against null
nullSettable True if resolved type can be set to null
refDecl True if resolved type is declred with ref or is a function that returns ref

See also

- https://dlang.org/spec/template.html#variadic-templates


int i = 3;
int j = 4;
int *pi = null;

// Is it resolved to the same type as another?
static assert( iz!i.of!int);
static assert(!iz!i.of!(int*));
static assert( iz!3.of!i);
static assert(!iz!int.of!pi);

// Is it the same as another?
static assert( iz!i.sameAs!i);
static assert(!iz!i.sameAs!j);
static assert( iz!1.sameAs!1);
static assert(!iz!1.sameAs!2);

// Using std.meta algorithm with iz
import std.meta: allSatisfy, AliasSeq;
static assert(allSatisfy!(iz!int.of, 3, 4, int, i));

/// Is it a function over
static assert( iz!(a => a).unaryOver!int);
static assert( iz!((a, b) => a).binaryOver!(int, int));
static assert( iz!((a, b, c, d) => a).functionOver!(int, int, int, int));

// Is this thing a value or reference type?
struct SValueType {}
class CRefType {}
static assert( iz!SValueType.valueType);
static assert(!iz!CRefType.valueType);
static assert(!iz!SValueType.refType);
static assert( iz!CRefType.refType);

static assert( iz!"hello".literalOf!string);
static assert(!iz!3.literalOf!string);

// Is this thing copy constructable?
static struct SDisabledCopyConstructor { @disable this(ref typeof(this)); }
static assert(!iz!SDisabledCopyConstructor.copyConstructable);
static assert( iz!int.copyConstructable);

// Does this thing define a custom copy constructor (i.e. non-trivial copy constructor)
static struct SCopyConstructor { this(ref typeof(this)) {} }
static assert( iz!SCopyConstructor.nonTriviallyCopyConstructable);
static assert(!iz!SCopyConstructor.triviallyCopyConstructable);
static assert(!iz!int.nonTriviallyCopyConstructable);
static assert( iz!int.triviallyCopyConstructable);

// Can we equate these things?
static assert( iz!int.equatableTo!3);
static assert(!iz!3.equatableTo!string);

// What null-semantics does the type have

// Is it settable to null?
static struct SNullSettable { void opAssign(int*) {} }
static assert( iz!pi.nullSettable);
static assert( iz!SNullSettable.nullSettable);
static assert(!iz!i.nullSettable);

// Is it checable with null? (i.e. if (this is null) )
static assert( iz!pi.nullTestable);
static assert(!iz!SNullSettable.nullTestable);
static assert(!iz!i.nullTestable);

// Is it typeof(null)?
static assert(!iz!int.nullType);
static assert( iz!null.nullType);
static assert( iz!(typeof(null)).nullType);