License
Source: std/typecons.d
This module implements a variety of type constructors, i.e., templates that allow construction of new, useful general-purpose types.
Source: std/typecons.d
Encapsulates unique ownership of a resource.
When a Unique!T goes out of scope it will call destroy on the resource T that it manages, unless it is transferred. One important consequence of destroy is that it will call the destructor of the resource T. GC-managed references are not guaranteed to be valid during a destructor call, but other members of T, such as file handles or pointers to malloc memory, will still be valid during the destructor call. This allows the resource T to deallocate or clean up any non-GC resources.
If it is desirable to persist a Unique!T outside of its original scope, then it can be transferred. The transfer can be explicit, by calling release, or implicit, when returning Unique from a function. The resource T can be a polymorphic class object or instance of an interface, in which case Unique behaves polymorphically too.
If T is a value type, then Unique!T will be implemented as a reference to a T.
RefT _pPostblit operator is undefined to prevent the cloning of `Unique` objects.this(RefT p)Constructor that takes an rvalue. It will ensure uniqueness, as long as the rvalue isn't just a view on an lvalue (e.g., a cast). Typical usage: ---- Unique!Foo f = new Foo; ----this(ref RefT p)Constructor that takes an lvalue. It nulls its source. The nulling will ensure uniqueness as long as there are no previous aliases to the source.this(T value)Constructs a `Rebindable2` from a given value.Defines a value paired with a distinctive "null" state that denotes the absence of a value. If default constructed, a Nullable!T object starts in the null state. Assigning it renders it non-null. Calling nullify can nullify it again.
Practically Nullable!T stores a T and a bool.
See also:
apply, an alternative way to use the payload.private DontCallDestructorT _valueprivate bool _isNullbool opEquals(this This, Rhs)(auto ref Rhs rhs) if (!is(CommonType!(This, Rhs) == void))If they are both null, then they are equal. If one is null and the other is not, then they are not equal. If they are both non-null, then they are equal if their values are equal.bool opEquals(this This, Rhs)(auto ref Rhs rhs) if (is(CommonType!(This, Rhs) == void) && is(typeof(this.get == rhs)))Dittostring toString()()Gives the string `"Nullable.null"` if `isNull` is `true`. Otherwise, the result is equivalent to calling formattedWrite on the underlying value.void toString(W)(ref W writer, scope const ref FormatSpec!char fmt) if (isOutputRange!(W, char))dittovoid toString(W)(ref W writer, scope const ref FormatSpec!char fmt) if (isOutputRange!(W, char)) constdittoT opCast(T, this This)() if (is(This : T) || This.sizeof == T.sizeof) refPrevents `opCast` from disabling built-in conversions.void nullify()()Forces `this` to the null state.Nullable opAssign()(T value) ref returnAssigns `value` to the internally-held state. If the assignment succeeds, `this` becomes non-null.inout(T) get() @property ref inout @safe pure nothrowGets the value if not null. If `this` is in the null state, and the optional parameter `fallback` was provided, it will be returned. Without `fallback`, calling `get` with a null state is invalid.Just like Nullable!T, except that the null state is defined as a particular value. For example, Nullable!(uint, uint.max) is an uint that sets aside the value uint.max to denote a null state. Nullable!(T, nullValue) is more storage-efficient than Nullable!T because it does not need to store an extra bool.
T | The wrapped type for which Nullable provides a null value. |
nullValue | The null value which denotes the null state of this Nullable. Must be of type T. |
private T _valuevoid nullify()()Forces `this` to the null state.void opAssign()(T value)Assigns `value` to the internally-held state. If the assignment succeeds, `this` becomes non-null. No null checks are made. Note that the assignment may leave `this` in the null state.inout(T) get() @property ref inoutGets the value. `this` must not be in the null state. This function is also called for the implicit conversion to `T`.this(T value)Constructor initializing `this` with `value`.toString()Just like Nullable!T, except that the object refers to a value sitting elsewhere in memory. This makes assignments overwrite the initially assigned value. Internally NullableRef!T only stores a pointer to T (i.e., Nullable!T.sizeof == (T*).sizeof).
private T * _valuebool isNull() @property const @safe pure nothrowReturns `true` if and only if `this` is in the null state.void opAssign()(T value) if (isAssignable!T)Assigns `value` to the internally-held state.inout(T) get() @property ref inout @safe pure nothrowGets the value. `this` must not be in the null state. This function is also called for the implicit conversion to `T`.this(T * value)Constructor binding `this` to `value`.toString()BlackHole!Base is a subclass of Base which automatically implements all abstract member functions in Base as do-nothing functions. Each auto-implemented function just returns the default value of the return type without doing anything.
The name came from
Class::_BlackHolePerl module by Sean M. Burke.
Base | A non-final class for BlackHole to inherit from. |
WhiteHole!Base is a subclass of Base which automatically implements all abstract member functions as functions that always fail. These functions simply throw an Error and never return. Whitehole is useful for trapping the use of class member functions that haven't been implemented.
The name came from
Class::_WhiteHolePerl module by Michael G Schwern.
Base | A non-final class for WhiteHole to inherit from. |
ditto
this(string method)AutoImplement automatically implements (by default) all abstract member functions in the class or interface Base in specified way.
The second version of AutoImplement automatically implements Interface, while deriving from BaseClass.
how | template which specifies _how functions will be implemented/overridden. Two arguments are passed to how: the type Base and an alias to an implemented function. Then how must return an implemented function body as a string. The generated function body can use these keywords:
Importer.writeln("Log: ~ qname ~ (", args, ")");; static if (!__traits(isAbstractFunction, fun)) { static if (is(ReturnType!fun == void)) stmt ~= q{ parent(args); }; else stmt ~= q{ auto r = parent(args); Importer.writeln("--> ", r); return r; }; } return stmt; } -------------------- |
what | template which determines _what functions should be implemented/overridden. An argument is passed to what: an alias to a non-final member function in Base. Then what must return a boolean value. Return true to indicate that the passed function should be implemented/overridden. -------------------- // Sees if fun returns something. enum bool hasValue(alias fun) = !is(ReturnType!(fun) == void); -------------------- |
std.typecons module. Thus,
any useful functions outside std.typecons cannot be used in the generated code. To workaround this problem, you may import necessary things in a local struct, as done in the generateLogger() template in the above example.
BUGS:
"Error: function std.typecons._AutoImplement!(Foo)._AutoImplement.bar does not override any function". [Bugzilla 2525]
parent keyword is actually a delegate to the super class'
corresponding member function. [Bugzilla 2540]
how and/or what may cause
strange compile error. Use template tuple parameter instead to workaround this problem. [Bugzilla 4217]
ditto
Options regarding auto-initialization of a SafeRefCounted object (see the definition of SafeRefCounted below).
Defines a reference-counted object containing a T value as payload.
An instance of SafeRefCounted is a reference to a structure, which is referred to as the store, or storage implementation struct in this documentation. The store contains a reference count and the T payload. SafeRefCounted uses malloc to allocate the store. As instances of SafeRefCounted are copied or go out of scope, they will automatically increment or decrement the reference count. When the reference count goes down to zero, SafeRefCounted will call destroy against the payload and call free to deallocate the store. If the T payload contains any references to GC-allocated memory, then SafeRefCounted will add it to the GC memory that is scanned for pointers, and remove it from GC scanning before free is called on the store.
One important consequence of destroy is that it will call the destructor of the T payload. GC-managed references are not guaranteed to be valid during a destructor call, but other members of T, such as file handles or pointers to malloc memory, will still be valid during the destructor call. This allows the T to deallocate or clean up any non-GC resources immediately after the reference count has reached zero.
Without -preview=dip1000, SafeRefCounted is unsafe and should be used with care. No references to the payload should be escaped outside the SafeRefCounted object.
With -preview=dip1000, SafeRefCounted is safe if it's payload is accessed only with the borrow function. Scope semantics can also prevent accidental escaping of refCountedPayload, but it's still up to the user to not destroy the last counted reference while the payload is in use. Due to that, refCountedPayload remains accessible only in @system code.
The autoInit option makes the object ensure the store is automatically initialized. Leaving autoInit == RefCountedAutoInitialize.yes (the default option) is convenient but has the cost of a test whenever the payload is accessed. If autoInit == RefCountedAutoInitialize.no, user code must call either refCountedStore.isInitialized or refCountedStore.ensureInitialized before attempting to access the payload. Not doing so results in null pointer dereference.
If T.this() is annotated with @disable then autoInit must be RefCountedAutoInitialize.no in order to compile.
RefCountedStore _refCountedvoid pureFree( void * ptr )void checkInit()() if (autoInit == RefCountedAutoInitialize.yes)inout(RefCountedStore) refCountedStore() @property nothrow @safe ref inoutReturns storage implementation struct.void opAssign(typeof(this) rhs)Assignment operators.void opAssign(T rhs)Dittothis(auto ref A args)Constructor that initializes the payload.this(return scope T val)Ditto~thisDestructor that tracks the reference count appropriately. If !refCountedStore.isInitialized, does nothing. When the reference count goes down to zero, calls `destroy` agaist the payload and calls `...RefCountedStore`SafeRefCounted` storage implementation.based on an existing type. Unlike the alias feature,
init | Optional initial value for the new type. |
cookie | Optional, used to create multiple unique types which are based on the same origin type T |
you can use the TypedefType template to extract the type which the Typedef wraps.
private T Typedef_payloadauto ref opCast(T2, this X)()string toString(this T)()Convert wrapped value to a human readable stringvoid toString(this T, W)(ref W writer, scope const ref FormatSpec!char fmt) if (isOutputRange!(W, char))dittoConvenience names that allow using e.g. Yes.encryption instead of Flag!"encryption".yes and No.encryption instead of Flag!"encryption".no.
opDispatch(string name)Ditto
opDispatch(string name)A typesafe structure for storing combinations of enum values.
This template defines a simple struct to represent bitwise OR combinations of enum values. It can be used if all the enum values are integral constants with a bit count of at most 1, or if the unsafe parameter is explicitly set to Yes. This is much safer than using the enum itself to store the OR combination, which can produce surprising effects like this: ---- enum E { A = 1 << 0, B = 1 << 1 } E e = E.A | E.B; // will throw SwitchError final switch (e) { case E.A: return; case E.B: return; } ----
Base mValuebool opCast(B: bool)() constBase opCast(B)() if (is(Base : B)) constauto opUnary(string op)() if (op == "~") constauto ref opAssign(T...)(T flags) if (allSatisfy!(isBaseEnumType, T))auto ref opAssign(E flag)auto ref opOpAssign(string op: "|")(BitFlags flags)auto ref opOpAssign(string op: "&")(BitFlags flags)auto ref opOpAssign(string op: "|")(E flag)auto ref opOpAssign(string op: "&")(E flag)auto opBinary(string op)(E flag) if (op == "|" || op == "&") constauto opBinaryRight(string op)(E flag) if (op == "|" || op == "&") constbool opDispatch(string name)() if (__traits(hasMember, E, name)) constvoid opDispatch(string name)(bool set) if (__traits(hasMember, E, name))Replaces all occurrences of From into To, in one or more types T. For example, ReplaceType!(int, uint, Tuple!(int, float)[string]) yields Tuple!(uint, float)[string]. The types in which replacement is performed may be arbitrarily complex, including qualifiers, built-in type constructors (pointers, arrays, associative arrays, functions, and delegates), and template instantiations; replacement proceeds transitively through the type definition. However, member types in structs or classes are not replaced because there are no ways to express the types resulting after replacement.
This is an advanced type manipulation necessary e.g. for replacing the placeholder type This in Algebraic.
ReplaceType aliases itself to the type(s) that result after
replacement.
Ternary type with three truth values:
Ternary.yes for trueTernary.no for falseTernary.unknown as an unknown stateAlso known as trinary, trivalent, or trilean.
private ubyte valuemake(0) noThe possible states of the `Ternary`make(2) yesdittomake(6) unknowndittovoid opAssign(bool b)dittoThe old version of SafeRefCounted, before borrow existed. Old code may be relying on @safety of some of the member functions which cannot be safe in the new scheme, and can avoid breakage by continuing to use this. SafeRefCounted should be preferred, as this type is outdated and unrecommended for new code.
RefCountedStore _refCountedRefCountedStoreRebindable!T rebindable(T)(T obj) if (is(T == class) || is(T == interface) || isDynamicArray!T || isAssociativeArray!T)Convenience function for creating a `Rebindable` using automatic type inference.Rebindable!T rebindable(T)(T value) if (!is(T == class) && !is(T == interface) && !isDynamicArray!T && !isAssociativeArray!T
&& !is(T : Rebindable!U, U))dittoRebindable!T rebindable(T)(Rebindable!T obj)This function simply returns the `Rebindable` object passed in. It's useful in generic programming cases when a given object may be either a regular `class` or a `Rebindable`.Rebindable2!T rebindable2(T)(T value)string alignForSize(E...)(const char[][] names...)Order the provided members to minimize size while preserving alignment. Alignment is not always optimal for 80-bit reals, nor for structs declared as align(1).SafeRefCounted!(T, RefCountedAutoInitialize.no) safeRefCounted(T)(T val)Initializes a `SafeRefCounted` with `val`. The template parameter `T` of `SafeRefCounted` is inferred from `val`. This function can be used to move non-copyable values to the heap. It also disables...size_t _alignUp(size_t alignment)(size_t n) if (alignment > 0 && !((alignment - 1) & alignment))RefCounted!(T, RefCountedAutoInitialize.no) refCounted(T)(T val)Like safeRefCounted but used to initialize RefCounted instead. Intended for backwards compatibility, otherwise it is preferable to use `safeRefCounted`.distinctFieldNames = __traits(compiles,
{
static foreach (__name; names)
static if (is(typeof(__name) : string))
mixin("enum int " ~ __name ~ " = 0;");
})isDIP1000 = __traits(compiles, () @safe {
int x;
int * p;
p = & x;
})if (distinctFieldNames!(Specs))_Tuple of values, for example Tuple!(int, string) is a record that stores an int and a string. Tuple can be used to bundle values together, notably when returning multiple values from a function. If obj is a Tuple, the individual members are accessible with the syntax obj[0] for the first field, obj[1] for the second, and so on.
Specs | A list of types (and optionally, member names) that the Tuple contains. |
if (isTuple!T)Constructs a Tuple object instantiated and initialized according to the given arguments.
Names | An optional list of strings naming each successive field of the Tuple or a list of types that the elements are being casted to. For a list of names, each name matches up with the corresponding field given by Args. A name does not have to be provided for every field, but as the names must proceed in order, it is not possible to skip one field and name the next after it. For a list of types, there must be exactly as many types as parameters. |
args | Values to initialize the Tuple with. The Tuple's type will be inferred from the types of the values given. |
Tuple with its type inferred from the arguments given.if (is(T == class) || is(T == interface) || isDynamicArray!T || isAssociativeArray!T)Rebindable!(T) is a simple, efficient wrapper that behaves just like an object of type T, except that you can reassign it to refer to another object. For completeness, Rebindable!(T) aliases itself away to T if T is a non-const object type.
You may want to use Rebindable when you want to have mutable storage referring to const objects, for example an array of references that must be sorted in place. Rebindable does not break the soundness of D's type system and does not incur any of the risks usually associated with cast.
T | Any type. |
if (is(T == class) || is(T == interface))Similar to Rebindable!(T) but strips all qualifiers from the reference as opposed to just constness / immutability. Primary intended use case is with shared (having thread-local reference to shared class data)
T | A class or interface type. |
Unpacks the content of a Nullable, performs an operation and packs it again. Does nothing if isNull.
When called on a Nullable, apply will unpack the value contained in the Nullable, pass it to the function you provide and wrap the result in another Nullable (if necessary). If the Nullable is null, apply will return null itself.
t | a Nullable |
fun | a function operating on the content of the nullable |
if (is(typeof(& func)))Predefined how-policies for AutoImplement. These templates are also used by BlackHole and WhiteHole, respectively.
ditto
if (is(T == class) || is(T == interface))if (Targets.length >= 1 && allSatisfy!(isMutable, Targets))Supports structural based typesafe conversion.
If Source has structural conformance with the interface Targets, wrap creates an internal wrapper class which inherits Targets and wraps the src object, then returns it.
unwrap can be used to extract objects which have been wrapped by wrap.
if (Targets.length >= 1 && !allSatisfy!(isMutable, Targets))ditto
if (isMutable!Target)ditto
if (!isMutable!Target)ditto
Borrows the payload of SafeRefCounted for use in fun. Inferred as @safe if fun is @safe and does not escape a reference to the payload. The reference count will be incremented for the duration of the operation, so destroying the last reference will not leave dangling references in fun.
fun | A callable accepting the payload either by value or by reference. |
refCount | The counted reference to the payload. |
fun, if any. ref in the return value will be
forwarded. Issues: For yet unknown reason, code that uses this function with UFCS syntax will not be inferred as @safe. It will still compile if the code is explicitly marked @safe and nothing in fun prevents that.
Get the underlying type which a Typedef wraps. If T is not a Typedef it will alias itself to T.
if (is(T == class))Allocates a class object right inside the current scope, therefore avoiding the overhead of new. This facility is unsafe; it is the responsibility of the user to not escape a reference to the object outside the scope.
The class destructor will be called when the result of scoped() is itself destroyed.
Scoped class instances can be embedded in a parent class or struct, just like a child struct instance. Scoped member variables must have type typeof(scoped!Class(args)), and be initialized with a call to scoped. See below for an example.
are no pointers to it. As such, it is illegal to move a scoped object.
Returns the _scoped object.
args | Arguments to pass to T's constructor. |
Defines a simple, self-documenting yes/no flag. This makes it easy for APIs to define functions accepting flags without resorting to bool, which is opaque in calls, and without needing to define an enumerated type separately. Using Flag!"Name" instead of bool makes the flag's meaning visible in calls. Each yes/no flag has its own type, which makes confusions and mix-ups impossible.
Example:
Code calling getLine (usually far away from its definition) can't be understood without looking at the documentation, even by users familiar with the API: ---- string getLine(bool keepTerminator) { ... if (keepTerminator) ... ... } ... auto line = getLine(false); ----
Assuming the reverse meaning (i.e. "ignoreTerminator") and inserting the wrong code compiles and runs with erroneous results.
After replacing the boolean parameter with an instantiation of Flag, code calling getLine can be easily read and understood even by people not fluent with the API:
---- string getLine(Flag!"keepTerminator" keepTerminator) { ... if (keepTerminator) ... ... } ... auto line = getLine(Yes.keepTerminator); ----
The structs Yes and No are provided as shorthand for Flag!"Name".yes and Flag!"Name".no and are preferred for brevity and readability. These convenience structs mean it is usually unnecessary and counterproductive to create an alias of a Flag as a way of avoiding typing out the full type while specifying the affirmative or negative options.
Passing categorical data by means of unstructured bool parameters is classified under "simple-data coupling" by Steve McConnell in the Code Complete book, along with three other kinds of coupling. The author argues citing several studies that coupling has a negative effect on code quality. Flag offers a simple structuring method for passing yes/no flags to APIs.
Detect whether an enum is of integral type and has only "flag" values (i.e. values with a bit count of exactly 1). Additionally, a zero value is allowed for compatibility with enums including a "None" value.
Like ReplaceType, but does not perform replacement in types for which pred evaluates to true.