std.experimental.typecons
This module implements experimental additions/modifications to std.typecons
.
Use this module to test out new functionality for std.typecons.wrap
which allows for a struct to be wrapped against an interface; the implementation in std.typecons
only allows for classes to use the wrap functionality.
- Source
- std/experimental/typecons.d
- License:
- Boost License 1.0.
- Authors:
- Andrei Alexandrescu, Bartosz Milewski, Don Clugston, Shin Fujishiro, Kenji Hara
- template wrap(Targets...) if (Targets.length >= 1 && allSatisfy!(isInterface, Targets))
-
- auto wrap(Source)(inout Source src)
Constraints: if (implementsInterface!(Source, Targets)); -
Wrap src in an anonymous class implementing Targets.
wrap creates an internal wrapper class which implements the interfaces in
Targets
using the methods ofsrc
, then returns a GC-allocated instance of it.
Source can be either aclass
or astruct
, but it must structurally conform with all the Targets interfaces; i.e. it must provide concrete methods with compatible signatures of those in Targets.
If Source is astruct
then wrapping/unwrapping will create a copy; it is not possible to affect the originalstruct
through the wrapper.
The returned object additionally supportsunwrap
.- Note
- If Targets has only one entry and Source is a class which explicitly implements it, wrap simply returns src upcasted to
Targets[0]
.
- Bugs:
- wrap does not support interfaces which take their own type as either a parameter type or return type in any of its methods.
- See Also:
-
unwrap
for examples
- auto wrap(Source)(inout Source src)
- inout(Target) unwrap(Target, Source)(inout Source src);
-
Extract object previously wrapped by
wrap
.- Parameters:
Target type of wrapped object Source src
wrapper object returned by wrap
- Returns:
- the wrapped object, or null if src is not a wrapper created by
wrap
and Target is a class
- Throws:
-
std.conv.ConvException
when attempting to extract a struct which is not the wrapped type
- See Also:
wrap
- Examples:
-
interface Quack { int quack(); @property int height(); } interface Flyer { @property int height(); } class Duck : Quack { int quack() { return 1; } @property int height() { return 10; } } class Human { int quack() { return 2; } @property int height() { return 20; } } struct HumanStructure { int quack() { return 3; } @property int height() { return 30; } } Duck d1 = new Duck(); Human h1 = new Human(); HumanStructure hs1; interface Refreshable { int refresh(); } // does not have structural conformance static assert(!__traits(compiles, d1.wrap!Refreshable)); static assert(!__traits(compiles, h1.wrap!Refreshable)); static assert(!__traits(compiles, hs1.wrap!Refreshable)); // strict upcast Quack qd = d1.wrap!Quack; assert(qd is d1); assert(qd.quack() == 1); // calls Duck.quack // strict downcast Duck d2 = qd.unwrap!Duck; assert(d2 is d1); // structural upcast Quack qh = h1.wrap!Quack; Quack qhs = hs1.wrap!Quack; assert(qh.quack() == 2); // calls Human.quack assert(qhs.quack() == 3); // calls HumanStructure.quack // structural downcast Human h2 = qh.unwrap!Human; HumanStructure hs2 = qhs.unwrap!HumanStructure; assert(h2 is h1); assert(hs2 is hs1); // structural upcast (two steps) Quack qx = h1.wrap!Quack; // Human -> Quack Quack qxs = hs1.wrap!Quack; // HumanStructure -> Quack Flyer fx = qx.wrap!Flyer; // Quack -> Flyer Flyer fxs = qxs.wrap!Flyer; // Quack -> Flyer assert(fx.height == 20); // calls Human.height assert(fxs.height == 30); // calls HumanStructure.height // strucural downcast (two steps) Quack qy = fx.unwrap!Quack; // Flyer -> Quack Quack qys = fxs.unwrap!Quack; // Flyer -> Quack Human hy = qy.unwrap!Human; // Quack -> Human HumanStructure hys = qys.unwrap!HumanStructure; // Quack -> HumanStructure assert(hy is h1); assert(hys is hs1); // strucural downcast (one step) Human hz = fx.unwrap!Human; // Flyer -> Human HumanStructure hzs = fxs.unwrap!HumanStructure; // Flyer -> HumanStructure assert(hz is h1); assert(hzs is hs1);
- Examples:
-
import std.traits : functionAttributes, FunctionAttribute; interface A { int run(); } interface B { int stop(); @property int status(); } class X { int run() { return 1; } int stop() { return 2; } @property int status() { return 3; } } auto x = new X(); auto ab = x.wrap!(A, B); A a = ab; B b = ab; writeln(a.run()); // 1 writeln(b.stop()); // 2 writeln(b.status); // 3 static assert(functionAttributes!(typeof(ab).status) & FunctionAttribute.property);
- template Final(T)
Final!T makeFinal(T)(T t); -
Type constructor for final (aka head-const) variables.
Final variables cannot be directly mutated or rebound, but references reached through the variable are typed with their original mutability. It is equivalent to
final
variables in D1 and Java, as well asreadonly
variables in C#.
WhenT
is aconst
orimmutable
type,Final
aliases toT
.- Examples:
-
Final
can be used to create class references which cannot be rebound:static class A { int i; this(int i) pure nothrow @nogc @safe { this.i = i; } } auto a = makeFinal(new A(42)); writeln(a.i); // 42 //a = new A(24); // Reassignment is illegal, a.i = 24; // But fields are still mutable. writeln(a.i); // 24
- Examples:
-
Final
can also be used to create read-only data fields without using transitive immutability:static class A { int i; this(int i) pure nothrow @nogc @safe { this.i = i; } } static class B { Final!A a; this(A a) pure nothrow @nogc @safe { this.a = a; // Construction, thus allowed. } } auto b = new B(new A(42)); writeln(b.a.i); // 42 // b.a = new A(24); // Reassignment is illegal, b.a.i = 24; // but `a` is still mutable. writeln(b.a.i); // 24
© 1999–2021 The D Language Foundation
Licensed under the Boost License 1.0.
https://dlang.org/phobos/std_experimental_typecons.html