1 // Written in the D programming language.
4 This module implements a variety of type constructors, i.e., templates
5 that allow construction of new, useful general-purpose types.
7 $(SCRIPT inhibitQuickIndex = 1;)
9 $(TR $(TH Category) $(TH Functions))
23 $(TR $(TD Memory allocation) $(TD
26 $(LREF RefCountedAutoInitialize)
30 $(TR $(TD Code generation) $(TD
33 $(LREF generateAssertTrap)
34 $(LREF generateEmptyFunction)
37 $(TR $(TD Nullable) $(TD
43 $(TR $(TD Proxies) $(TD
60 Copyright: Copyright the respective authors, 2008-
61 License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0).
62 Source: $(PHOBOSSRC std/_typecons.d)
63 Authors: $(HTTP erdani.org, Andrei Alexandrescu),
64 $(HTTP bartoszmilewski.wordpress.com, Bartosz Milewski),
71 import core.stdc.stdint : uintptr_t;
72 import std.meta; // : AliasSeq, allSatisfy;
79 alias Coord = Tuple!(int, "x", int, "y", int, "z");
81 c[1] = 1; // access by index
82 c.z = 1; // access by given name
83 assert(c == Coord(0, 1, 1));
85 // names can be omitted
86 alias DicEntry = Tuple!(string, string);
88 // tuples can also be constructed on instantiation
89 assert(tuple(2, 3, 4)[1] == 3);
90 // construction on instantiation works with names too
91 assert(tuple!("x", "y", "z")(2, 3, 4).y == 3);
93 // Rebindable references to const and immutable objects
95 class Widget { void foo() const @safe {} }
96 const w1 = new Widget, w2 = new Widget;
98 // w1 = w2 would not work; can't rebind const object
99 auto r = Rebindable!(const Widget)(w1);
100 // invoke method as if r were a Widget object
102 // rebind r to refer to another object
107 debug(Unique) import std.stdio;
110 Encapsulates unique ownership of a resource.
112 When a $(D Unique!T) goes out of scope it will call $(D destroy)
113 on the resource $(D T) that it manages, unless it is transferred.
114 One important consequence of $(D destroy) is that it will call the
115 destructor of the resource $(D T). GC-managed references are not
116 guaranteed to be valid during a destructor call, but other members of
117 $(D T), such as file handles or pointers to $(D malloc) memory, will
118 still be valid during the destructor call. This allows the resource
119 $(D T) to deallocate or clean up any non-GC resources.
121 If it is desirable to persist a $(D Unique!T) outside of its original
122 scope, then it can be transferred. The transfer can be explicit, by
123 calling $(D release), or implicit, when returning Unique from a
124 function. The resource $(D T) can be a polymorphic class object or
125 instance of an interface, in which case Unique behaves polymorphically
128 If $(D T) is a value type, then $(D Unique!T) will be implemented
129 as a reference to a $(D T).
133 /** Represents a reference to $(D T). Resolves to $(D T*) if $(D T) is a value type. */
134 static if (is(T == class) || is(T == interface))
140 // Deferred in case we get some language support for checking uniqueness.
143 Allows safe construction of $(D Unique). It creates the resource and
144 guarantees unique ownership of it (unless $(D T) publishes aliases of
146 Note: Nested structs/classes cannot be created.
148 args = Arguments to pass to $(D T)'s constructor.
151 auto u = Unique!(C).create();
154 static Unique!T create(A...)(auto ref A args)
155 if (__traits(compiles, new T(args)))
157 debug(Unique) writeln("Unique.create for ", T.stringof);
164 Constructor that takes an rvalue.
165 It will ensure uniqueness, as long as the rvalue
166 isn't just a view on an lvalue (e.g., a cast).
169 Unique!Foo f = new Foo;
174 debug(Unique) writeln("Unique constructor with rvalue");
178 Constructor that takes an lvalue. It nulls its source.
179 The nulling will ensure uniqueness as long as there
180 are no previous aliases to the source.
185 debug(Unique) writeln("Unique constructor nulling source");
190 Constructor that takes a $(D Unique) of a type that is convertible to our type.
192 Typically used to transfer a $(D Unique) rvalue of derived type to
193 a $(D Unique) of base type.
199 Unique!Object uo = uc.release;
205 debug(Unique) writeln("Unique constructor converting from ", U.stringof);
210 /// Transfer ownership from a $(D Unique) of a type that is convertible to our type.
211 void opAssign(U)(Unique!U u)
214 debug(Unique) writeln("Unique opAssign converting from ", U.stringof);
215 // first delete any resource we own
223 debug(Unique) writeln("Unique destructor of ", (_p is null)? null: _p);
231 /** Returns whether the resource exists. */
232 @property bool isEmpty() const
236 /** Transfer ownership to a $(D Unique) rvalue. Nullifies the current contents.
237 Same as calling std.algorithm.move on it.
241 debug(Unique) writeln("Unique Release");
242 import std.algorithm.mutation : move;
246 /** Forwards member access to contents. */
250 Postblit operator is undefined to prevent the cloning of $(D Unique) objects.
264 this(int i){this.i = i;}
268 // Construct a unique instance of S on the heap
269 Unique!S ut = new S(5);
270 // Implicit transfer of ownership
273 // Borrow a unique resource by ref
274 void increment(ref Unique!S ur)
278 void consume(Unique!S u2)
281 // Resource automatically deleted here
288 //consume(u1); // Error: u1 is not copyable
289 // Transfer ownership of the resource
296 // test conversion to base ref
302 // constructor conversion
303 Unique!Object u = Unique!C(new C);
304 static assert(!__traits(compiles, {u = new C;}));
307 assert(deleted == 1);
310 static assert(!__traits(compiles, {Unique!Object uo = uc;}));
311 Unique!Object uo = new C;
312 // opAssign conversion, deleting uo resource first
316 assert(deleted == 2);
321 debug(Unique) writeln("Unique class");
324 ~this() { debug(Unique) writeln(" Bar destructor"); }
325 int val() const { return 4; }
327 alias UBar = Unique!(Bar);
330 debug(Unique) writeln("inside g");
333 auto ub = UBar(new Bar);
336 static assert(!__traits(compiles, {auto ub3 = g(ub);}));
337 debug(Unique) writeln("Calling g");
338 auto ub2 = g(ub.release);
339 debug(Unique) writeln("Returned from g");
341 assert(!ub2.isEmpty);
346 debug(Unique) writeln("Unique interface");
362 int val() const { return 4; }
364 alias UBar = Unique!Bar;
367 debug(Unique) writeln("inside g");
372 assert(u.val() == 4);
373 // Resource automatically deleted here
375 auto ub = UBar(new BarImpl);
376 assert(BarImpl.count == 1);
379 static assert(!__traits(compiles, {auto ub3 = g(ub);}));
380 debug(Unique) writeln("Calling g");
381 auto ub2 = g(ub.release);
382 debug(Unique) writeln("Returned from g");
384 assert(!ub2.isEmpty);
385 consume(ub2.release);
386 assert(BarImpl.count == 0);
391 debug(Unique) writeln("Unique struct");
394 ~this() { debug(Unique) writeln(" Foo destructor"); }
395 int val() const { return 3; }
398 alias UFoo = Unique!(Foo);
402 debug(Unique) writeln("inside f");
406 auto uf = UFoo(new Foo);
409 static assert(!__traits(compiles, {auto uf3 = f(uf);}));
410 debug(Unique) writeln("Unique struct: calling f");
411 auto uf2 = f(uf.release);
412 debug(Unique) writeln("Unique struct: returned from f");
414 assert(!uf2.isEmpty);
417 // ensure Unique behaves correctly through const access paths
420 struct Bar {int val;}
423 Unique!Bar bar = new Bar;
428 const Foo* ptr = &foo;
429 static assert(is(typeof(ptr) == const(Foo*)));
430 static assert(is(typeof(ptr.bar) == const(Unique!Bar)));
431 static assert(is(typeof(ptr.bar.val) == const(int)));
432 assert(ptr.bar.val == 6);
434 assert(ptr.bar.val == 7);
437 // Used in Tuple.toString
438 private template sharedToString(alias field)
439 if (is(typeof(field) == shared))
441 static immutable sharedToString = typeof(field).stringof;
444 private template sharedToString(alias field)
445 if (!is(typeof(field) == shared))
447 alias sharedToString = field;
451 _Tuple of values, for example $(D Tuple!(int, string)) is a record that
452 stores an $(D int) and a $(D string). $(D Tuple) can be used to bundle
453 values together, notably when returning multiple values from a
454 function. If $(D obj) is a `Tuple`, the individual members are
455 accessible with the syntax $(D obj[0]) for the first field, $(D obj[1])
456 for the second, and so on.
458 The choice of zero-based indexing instead of one-base indexing was
459 motivated by the ability to use value tuples with various compile-time
460 loop constructs (e.g. $(REF AliasSeq, std,meta) iteration), all of which use
463 See_Also: $(LREF tuple).
466 Specs = A list of types (and optionally, member names) that the `Tuple` contains.
468 template Tuple(Specs...)
470 import std.meta : staticMap;
472 // Parse (type,name) pairs (FieldSpecs) out of the specified
473 // arguments. Some fields would have name, others not.
474 template parseSpecs(Specs...)
476 static if (Specs.length == 0)
478 alias parseSpecs = AliasSeq!();
480 else static if (is(Specs[0]))
482 static if (is(typeof(Specs[1]) : string))
485 AliasSeq!(FieldSpec!(Specs[0 .. 2]),
486 parseSpecs!(Specs[2 .. $]));
491 AliasSeq!(FieldSpec!(Specs[0]),
492 parseSpecs!(Specs[1 .. $]));
497 static assert(0, "Attempted to instantiate Tuple with an "
498 ~"invalid argument: "~ Specs[0].stringof);
502 template FieldSpec(T, string s = "")
508 alias fieldSpecs = parseSpecs!Specs;
510 // Used with staticMap.
511 alias extractType(alias spec) = spec.Type;
512 alias extractName(alias spec) = spec.name;
514 // Generates named fields as follows:
515 // alias name_0 = Identity!(field[0]);
516 // alias name_1 = Identity!(field[1]);
518 // NOTE: field[k] is an expression (which yields a symbol of a
519 // variable) and can't be aliased directly.
520 string injectNamedFields()
523 foreach (i, name; staticMap!(extractName, fieldSpecs))
525 import std.format : format;
527 decl ~= format("alias _%s = Identity!(field[%s]);", i, i);
528 if (name.length != 0)
530 decl ~= format("alias %s = _%s;", name, i);
536 // Returns Specs for a subtuple this[from .. to] preserving field
538 alias sliceSpecs(size_t from, size_t to) =
539 staticMap!(expandSpec, fieldSpecs[from .. to]);
541 template expandSpec(alias spec)
543 static if (spec.name.length == 0)
545 alias expandSpec = AliasSeq!(spec.Type);
549 alias expandSpec = AliasSeq!(spec.Type, spec.name);
553 enum areCompatibleTuples(Tup1, Tup2, string op) = isTuple!Tup2 && is(typeof(
554 (ref Tup1 tup1, ref Tup2 tup2)
556 static assert(tup1.field.length == tup2.field.length);
557 foreach (i, _; Tup1.Types)
559 auto lhs = typeof(tup1.field[i]).init;
560 auto rhs = typeof(tup2.field[i]).init;
561 static if (op == "=")
564 auto result = mixin("lhs "~op~" rhs");
568 enum areBuildCompatibleTuples(Tup1, Tup2) = isTuple!Tup2 && is(typeof(
570 static assert(Tup1.Types.length == Tup2.Types.length);
571 foreach (i, _; Tup1.Types)
572 static assert(isBuildable!(Tup1.Types[i], Tup2.Types[i]));
575 /+ Returns $(D true) iff a $(D T) can be initialized from a $(D U). +/
576 enum isBuildable(T, U) = is(typeof(
581 /+ Helper for partial instanciation +/
582 template isBuildableFrom(U)
584 enum isBuildableFrom(T) = isBuildable!(T, U);
590 * The types of the `Tuple`'s components.
592 alias Types = staticMap!(extractType, fieldSpecs);
595 static if (Specs.length == 0) @safe unittest
597 alias Fields = Tuple!(int, "id", string, float);
598 static assert(is(Fields.Types == AliasSeq!(int, string, float)));
602 * The names of the `Tuple`'s components. Unnamed fields have empty names.
604 alias fieldNames = staticMap!(extractName, fieldSpecs);
607 static if (Specs.length == 0) @safe unittest
609 alias Fields = Tuple!(int, "id", string, float);
610 static assert(Fields.fieldNames == AliasSeq!("id", "", ""));
614 * Use $(D t.expand) for a `Tuple` $(D t) to expand it into its
615 * components. The result of $(D expand) acts as if the `Tuple`'s components
616 * were listed as a list of values. (Ordinarily, a $(D Tuple) acts as a
620 mixin(injectNamedFields());
623 static if (Specs.length == 0) @safe unittest
625 auto t1 = tuple(1, " hello ", 2.3);
626 assert(t1.toString() == `Tuple!(int, string, double)(1, " hello ", 2.3)`);
628 void takeSeveralTypes(int n, string s, bool b)
630 assert(n == 4 && s == "test" && b == false);
633 auto t2 = tuple(4, "test", false);
634 //t.expand acting as a list of values
635 takeSeveralTypes(t2.expand);
638 static if (is(Specs))
640 // This is mostly to make t[n] work.
646 ref inout(Tuple!Types) _Tuple_super() inout @trusted
648 foreach (i, _; Types) // Rely on the field layout
650 static assert(typeof(return).init.tupleof[i].offsetof ==
653 return *cast(typeof(return)*) &(field[0]);
655 // This is mostly to make t[n] work.
656 alias _Tuple_super this;
659 // backwards compatibility
660 alias field = expand;
663 * Constructor taking one value for each field.
666 * values = A list of values that are either the same
667 * types as those given by the `Types` field
668 * of this `Tuple`, or can implicitly convert
669 * to those types. They must be in the same
670 * order as they appear in `Types`.
672 static if (Types.length > 0)
681 static if (Specs.length == 0) @safe unittest
683 alias ISD = Tuple!(int, string, double);
684 auto tup = ISD(1, "test", 3.2);
685 assert(tup.toString() == `Tuple!(int, string, double)(1, "test", 3.2)`);
689 * Constructor taking a compatible array.
692 * values = A compatible static array to build the `Tuple` from.
693 * Array slices are not supported.
695 this(U, size_t n)(U[n] values)
696 if (n == Types.length && allSatisfy!(isBuildableFrom!U, Types))
698 foreach (i, _; Types)
700 field[i] = values[i];
705 static if (Specs.length == 0) @safe unittest
708 Tuple!(int, int) t = ints;
712 * Constructor taking a compatible `Tuple`. Two `Tuple`s are compatible
713 * $(B iff) they are both of the same length, and, for each type `T` on the
714 * left-hand side, the corresponding type `U` on the right-hand side can
715 * implicitly convert to `T`.
718 * another = A compatible `Tuple` to build from. Its type must be
719 * compatible with the target `Tuple`'s type.
722 if (areBuildCompatibleTuples!(typeof(this), U))
724 field[] = another.field[];
728 static if (Specs.length == 0) @safe unittest
730 alias IntVec = Tuple!(int, int, int);
731 alias DubVec = Tuple!(double, double, double);
733 IntVec iv = tuple(1, 1, 1);
735 //Ok, int can implicitly convert to double
737 //Error: double cannot implicitly convert to int
742 * Comparison for equality. Two `Tuple`s are considered equal
743 * $(B iff) they fulfill the following criteria:
746 * $(LI Each `Tuple` is the same length.)
747 * $(LI For each type `T` on the left-hand side and each type
748 * `U` on the right-hand side, values of type `T` can be
749 * compared with values of type `U`.)
750 * $(LI For each value `v1` on the left-hand side and each value
751 * `v2` on the right-hand side, the expression `v1 == v2` is
755 * rhs = The `Tuple` to compare against. It must meeting the criteria
756 * for comparison between `Tuple`s.
759 * true if both `Tuple`s are equal, otherwise false.
761 bool opEquals(R)(R rhs)
762 if (areCompatibleTuples!(typeof(this), R, "=="))
764 return field[] == rhs.field[];
768 bool opEquals(R)(R rhs) const
769 if (areCompatibleTuples!(typeof(this), R, "=="))
771 return field[] == rhs.field[];
775 static if (Specs.length == 0) @safe unittest
777 Tuple!(int, string) t1 = tuple(1, "test");
778 Tuple!(double, string) t2 = tuple(1.0, "test");
779 //Ok, int can be compared with double and
780 //both have a value of 1
785 * Comparison for ordering.
788 * rhs = The `Tuple` to compare against. It must meet the criteria
789 * for comparison between `Tuple`s.
792 * For any values `v1` on the right-hand side and `v2` on the
796 * $(LI A negative integer if the expression `v1 < v2` is true.)
797 * $(LI A positive integer if the expression `v1 > v2` is true.)
798 * $(LI 0 if the expression `v1 == v2` is true.))
801 if (areCompatibleTuples!(typeof(this), R, "<"))
803 foreach (i, Unused; Types)
805 if (field[i] != rhs.field[i])
807 return field[i] < rhs.field[i] ? -1 : 1;
814 int opCmp(R)(R rhs) const
815 if (areCompatibleTuples!(typeof(this), R, "<"))
817 foreach (i, Unused; Types)
819 if (field[i] != rhs.field[i])
821 return field[i] < rhs.field[i] ? -1 : 1;
828 The first `v1` for which `v1 > v2` is true determines
829 the result. This could lead to unexpected behaviour.
831 static if (Specs.length == 0) @safe unittest
833 auto tup1 = tuple(1, 1, 1);
834 auto tup2 = tuple(1, 100, 100);
837 //Only the first result matters for comparison
843 * Assignment from another `Tuple`.
846 * rhs = The source `Tuple` to assign from. Each element of the
847 * source `Tuple` must be implicitly assignable to each
848 * respective element of the target `Tuple`.
850 void opAssign(R)(auto ref R rhs)
851 if (areCompatibleTuples!(typeof(this), R, "="))
853 import std.algorithm.mutation : swap;
855 static if (is(R : Tuple!Types) && !__traits(isRef, rhs))
859 // Cannot use swap at compile time
860 field[] = rhs.field[];
864 // Use swap-and-destroy to optimize rvalue assignment
865 swap!(Tuple!Types)(this, rhs);
870 // Do not swap; opAssign should be called on the fields.
871 field[] = rhs.field[];
876 * Renames the elements of a $(LREF Tuple).
878 * `rename` uses the passed `names` and returns a new
879 * $(LREF Tuple) using these names, with the content
881 * If fewer names are passed than there are members
882 * of the $(LREF Tuple) then those trailing members are unchanged.
883 * An empty string will remove the name for that member.
884 * It is an compile-time error to pass more names than
885 * there are members of the $(LREF Tuple).
887 ref rename(names...)() return
888 if (names.length == 0 || allSatisfy!(isSomeString, typeof(names)))
890 import std.algorithm.comparison : equal;
891 // to circumvent bug 16418
892 static if (names.length == 0 || equal([names], [fieldNames]))
896 enum nT = Types.length;
897 enum nN = names.length;
898 static assert(nN <= nT, "Cannot have more names than tuple members");
899 alias allNames = AliasSeq!(names, fieldNames[nN .. $]);
901 template GetItem(size_t idx)
903 import std.array : empty;
905 alias GetItem = Alias!(Types[idx]);
906 else static if (allNames[idx - nT].empty)
907 alias GetItem = AliasSeq!();
909 alias GetItem = Alias!(allNames[idx - nT]);
912 import std.range : roundRobin, iota;
913 alias NewTupleT = Tuple!(staticMap!(GetItem, aliasSeqOf!(
914 roundRobin(iota(nT), iota(nT, 2*nT)))));
915 return *(() @trusted => cast(NewTupleT*)&this)();
920 static if (Specs.length == 0) @safe unittest
922 auto t0 = tuple(4, "hello");
924 auto t0Named = t0.rename!("val", "tag");
925 assert(t0Named.val == 4);
926 assert(t0Named.tag == "hello");
928 Tuple!(float, "dat", size_t[2], "pos") t1;
930 auto t1Named = t1.rename!"height";
931 t1Named.height = 3.4f;
932 assert(t1Named.height == 3.4f);
933 assert(t1Named.pos == [2, 1]);
934 t1Named.rename!"altitude".altitude = 5;
935 assert(t1Named.height == 5);
937 Tuple!(int, "a", int, int, "c") t2;
939 auto t2Named = t2.rename!("", "b");
940 // "a" no longer has a name
941 static assert(!hasMember!(typeof(t2Named), "a"));
942 assert(t2Named[0] == 3);
943 assert(t2Named.b == 4);
944 assert(t2Named.c == 5);
946 // not allowed to specify more names than the tuple has members
947 static assert(!__traits(compiles, t2.rename!("a","b","c","d")));
949 // use it in a range pipeline
950 import std.range : iota, zip;
951 import std.algorithm.iteration : map, sum;
952 auto res = zip(iota(1, 4), iota(10, 13))
953 .map!(t => t.rename!("a", "b"))
954 .map!(t => t.a * t.b)
960 * Overload of $(LREF _rename) that takes an associative array
961 * `translate` as a template parameter, where the keys are
962 * either the names or indices of the members to be changed
963 * and the new names are the corresponding values.
964 * Every key in `translate` must be the name of a member of the
966 * The same rules for empty strings apply as for the variadic
967 * template overload of $(LREF _rename).
969 ref rename(alias translate)()
970 if (is(typeof(translate) : V[K], V, K) && isSomeString!V &&
971 (isSomeString!K || is(K : size_t)))
973 import std.range : ElementType;
974 static if (isSomeString!(ElementType!(typeof(translate.keys))))
977 import std.conv : to;
978 import std.algorithm.iteration : filter;
979 import std.algorithm.searching : canFind;
980 enum notFound = translate.keys
981 .filter!(k => fieldNames.canFind(k) == -1);
982 static assert(notFound.empty, "Cannot find members "
983 ~ notFound.to!string ~ " in type "
984 ~ typeof(this).stringof);
986 return this.rename!(aliasSeqOf!(
988 import std.array : empty;
989 auto names = [fieldNames];
990 foreach (ref n; names)
992 if (auto p = n in translate)
1000 import std.algorithm.iteration : filter;
1001 import std.conv : to;
1002 enum invalid = translate.keys.
1003 filter!(k => k < 0 || k >= this.length);
1004 static assert(invalid.empty, "Indices " ~ invalid.to!string
1005 ~ " are out of bounds for tuple with length "
1006 ~ this.length.to!string);
1008 return this.rename!(aliasSeqOf!(
1010 auto names = [fieldNames];
1011 foreach (k, v; translate)
1019 static if (Specs.length == 0) @safe unittest
1021 //replacing names by their current name
1023 Tuple!(float, "dat", size_t[2], "pos") t1;
1025 auto t1Named = t1.rename!(["dat": "height"]);
1026 t1Named.height = 3.4;
1027 assert(t1Named.pos == [2, 1]);
1028 t1Named.rename!(["height": "altitude"]).altitude = 5;
1029 assert(t1Named.height == 5);
1031 Tuple!(int, "a", int, "b") t2;
1033 auto t2Named = t2.rename!(["a": "b", "b": "c"]);
1034 assert(t2Named.b == 3);
1035 assert(t2Named.c == 4);
1039 static if (Specs.length == 0) @safe unittest
1041 //replace names by their position
1043 Tuple!(float, "dat", size_t[2], "pos") t1;
1045 auto t1Named = t1.rename!([0: "height"]);
1046 t1Named.height = 3.4;
1047 assert(t1Named.pos == [2, 1]);
1048 t1Named.rename!([0: "altitude"]).altitude = 5;
1049 assert(t1Named.height == 5);
1051 Tuple!(int, "a", int, "b", int, "c") t2;
1052 t2 = tuple(3, 4, 5);
1053 auto t2Named = t2.rename!([0: "c", 2: "a"]);
1054 assert(t2Named.a == 5);
1055 assert(t2Named.b == 4);
1056 assert(t2Named.c == 3);
1059 static if (Specs.length == 0) @safe unittest
1061 //check that empty translations work fine
1062 enum string[string] a0 = null;
1063 enum string[int] a1 = null;
1064 Tuple!(float, "a", float, "b") t0;
1066 auto t1 = t0.rename!a0;
1070 auto t2 = t0.rename!a1;
1073 auto t3 = t0.rename;
1079 * Takes a slice by-reference of this `Tuple`.
1082 * from = A `size_t` designating the starting position of the slice.
1083 * to = A `size_t` designating the ending position (exclusive) of the slice.
1086 * A new `Tuple` that is a slice from `[from, to$(RPAREN)` of the original.
1087 * It has the same types and values as the range `[from, to$(RPAREN)` in
1091 ref inout(Tuple!(sliceSpecs!(from, to))) slice(size_t from, size_t to)() inout @trusted
1092 if (from <= to && to <= Types.length)
1095 (typeof(this).alignof % typeof(return).alignof == 0) &&
1096 (expand[from].offsetof % typeof(return).alignof == 0),
1097 "Slicing by reference is impossible because of an alignment mistmatch. (See Phobos issue #15645.)");
1099 return *cast(typeof(return)*) &(field[from]);
1103 static if (Specs.length == 0) @safe unittest
1105 Tuple!(int, string, float, double) a;
1108 auto s = a.slice!(1, 3);
1109 static assert(is(typeof(s) == Tuple!(string, float)));
1110 assert(s[0] == "abc" && s[1] == 4.5);
1112 // Phobos issue #15645
1113 Tuple!(int, short, bool, double) b;
1114 static assert(!__traits(compiles, b.slice!(2, 4)));
1118 Creates a hash of this `Tuple`.
1121 A `size_t` representing the hash of this `Tuple`.
1123 size_t toHash() const nothrow @trusted
1126 foreach (i, T; Types)
1127 h += typeid(T).getHash(cast(const void*)&field[i]);
1135 * Converts to string.
1138 * The string representation of this `Tuple`.
1140 string toString()() const
1142 import std.array : appender;
1143 auto app = appender!string();
1144 this.toString((const(char)[] chunk) => app ~= chunk);
1148 import std.format : FormatSpec;
1151 * Formats `Tuple` with either `%s`, `%(inner%)` or `%(inner%|sep%)`.
1153 * $(TABLE2 Formats supported by Tuple,
1154 * $(THEAD Format, Description)
1155 * $(TROW $(P `%s`), $(P Format like `Tuple!(types)(elements formatted with %s each)`.))
1156 * $(TROW $(P `%(inner%)`), $(P The format `inner` is applied the expanded `Tuple`, so
1157 * it may contain as many formats as the `Tuple` has fields.))
1158 * $(TROW $(P `%(inner%|sep%)`), $(P The format `inner` is one format, that is applied
1159 * on all fields of the `Tuple`. The inner format must be compatible to all
1162 * Tuple!(int, double)[3] tupList = [ tuple(1, 1.0), tuple(2, 4.0), tuple(3, 9.0) ];
1165 * assert(format("%s", tuple("a", 1)) == `Tuple!(string, int)("a", 1)`);
1167 * // One Format for each individual component
1168 * assert(format("%(%#x v %.4f w %#x%)", tuple(1, 1.0, 10)) == `0x1 v 1.0000 w 0xa`);
1169 * assert(format( "%#x v %.4f w %#x" , tuple(1, 1.0, 10).expand) == `0x1 v 1.0000 w 0xa`);
1171 * // One Format for all components
1172 * assert(format("%(>%s<%| & %)", tuple("abc", 1, 2.3, [4, 5])) == `>abc< & >1< & >2.3< & >[4, 5]<`);
1174 * // Array of Tuples
1175 * assert(format("%(%(f(%d) = %.1f%); %)", tupList) == `f(1) = 1.0; f(2) = 4.0; f(3) = 9.0`);
1178 * // Error: %( %) missing.
1179 * assertThrown!FormatException(
1180 * format("%d, %f", tuple(1, 2.0)) == `1, 2.0`
1183 * // Error: %( %| %) missing.
1184 * assertThrown!FormatException(
1185 * format("%d", tuple(1, 2)) == `1, 2`
1188 * // Error: %d inadequate for double.
1189 * assertThrown!FormatException(
1190 * format("%(%d%|, %)", tuple(1, 2.0)) == `1, 2.0`
1194 void toString(DG)(scope DG sink) const
1196 toString(sink, FormatSpec!char());
1200 void toString(DG, Char)(scope DG sink, FormatSpec!Char fmt) const
1202 import std.format : formatElement, formattedWrite, FormatException;
1207 foreach (i, Type; Types)
1213 // TODO: Change this once formattedWrite() works for shared objects.
1214 static if (is(Type == class) && is(Type == shared))
1216 sink(Type.stringof);
1220 formattedWrite(sink, fmt.nested, this.field[i]);
1226 formattedWrite(sink, fmt.nested, staticMap!(sharedToString, this.expand));
1229 else if (fmt.spec == 's')
1231 enum header = Unqual!(typeof(this)).stringof ~ "(",
1235 foreach (i, Type; Types)
1241 // TODO: Change this once formatElement() works for shared objects.
1242 static if (is(Type == class) && is(Type == shared))
1244 sink(Type.stringof);
1249 formatElement(sink, field[i], f);
1256 throw new FormatException(
1257 "Expected '%s' or '%(...%)' or '%(...%|...%)' format specifier for type '" ~
1258 Unqual!(typeof(this)).stringof ~ "', not '%" ~ fmt.spec ~ "'.");
1268 Tuple!(int, int) point;
1269 // assign coordinates
1278 `Tuple` members can be named. It is legal to mix named and unnamed
1279 members. The method above is still applicable to all fields.
1283 alias Entry = Tuple!(int, "index", string, "value");
1287 assert(e[1] == "Hello");
1292 A `Tuple` with named fields is a distinct type from a `Tuple` with unnamed
1293 fields, i.e. each naming imparts a separate type for the `Tuple`. Two
1294 `Tuple`s differing in naming only are still distinct, even though they
1295 might have the same structure.
1299 Tuple!(int, "x", int, "y") point1;
1300 Tuple!(int, int) point2;
1301 assert(!is(typeof(point1) == typeof(point2)));
1305 Creates a copy of a $(LREF Tuple) with its fields in _reverse order.
1308 t = The `Tuple` to copy.
1313 auto reverse(T)(T t)
1316 import std.meta : Reverse;
1317 // @@@BUG@@@ Cannot be an internal function due to forward reference issues.
1319 // @@@BUG@@@ 9929 Need 'this' when calling template with expanded tuple
1320 // return tuple(Reverse!(t.expand));
1322 ReverseTupleType!T result;
1323 auto tup = t.expand;
1324 result.expand = Reverse!tup;
1331 auto tup = tuple(1, "2");
1332 assert(tup.reverse == tuple("2", 1));
1335 /* Get a Tuple type with the reverse specification of Tuple T. */
1336 private template ReverseTupleType(T)
1339 static if (is(T : Tuple!A, A...))
1340 alias ReverseTupleType = Tuple!(ReverseTupleSpecs!A);
1343 /* Reverse the Specs of a Tuple. */
1344 private template ReverseTupleSpecs(T...)
1346 static if (T.length > 1)
1348 static if (is(typeof(T[$-1]) : string))
1350 alias ReverseTupleSpecs = AliasSeq!(T[$-2], T[$-1], ReverseTupleSpecs!(T[0 .. $-2]));
1354 alias ReverseTupleSpecs = AliasSeq!(T[$-1], ReverseTupleSpecs!(T[0 .. $-1]));
1359 alias ReverseTupleSpecs = T;
1363 // ensure that internal Tuple unittests are compiled
1373 Tuple!(int, "a", int, "b") nosh;
1374 static assert(nosh.length == 2);
1377 assert(nosh.a == 5);
1378 assert(nosh.b == 6);
1381 Tuple!(short, double) b;
1382 static assert(b.length == 2);
1384 auto a = Tuple!(int, real)(b);
1385 assert(a[0] == 0 && a[1] == 5);
1386 a = Tuple!(int, real)(1, 2);
1387 assert(a[0] == 1 && a[1] == 2);
1388 auto c = Tuple!(int, "a", double, "b")(a);
1389 assert(c[0] == 1 && c[1] == 2);
1392 Tuple!(int, real) nosh;
1395 assert(nosh[0] == 5 && nosh[1] == 0);
1396 assert(nosh.to!string == "Tuple!(int, real)(5, 0)", nosh.to!string);
1397 Tuple!(int, int) yessh;
1402 Tuple!(int, shared A) nosh;
1404 assert(nosh[0] == 5 && nosh[1] is null);
1405 assert(nosh.to!string == "Tuple!(int, shared(A))(5, shared(A))");
1408 Tuple!(int, string) t;
1411 assert(t[0] == 10 && t[1] == "str");
1412 assert(t.to!string == `Tuple!(int, string)(10, "str")`, t.to!string);
1415 Tuple!(int, "a", double, "b") x;
1416 static assert(x.a.offsetof == x[0].offsetof);
1417 static assert(x.b.offsetof == x[1].offsetof);
1420 assert(x[0] == 5 && x[1] == 4.5);
1421 assert(x.a == 5 && x.b == 4.5);
1425 Tuple!(int, real) t;
1426 static assert(is(typeof(t[0]) == int));
1427 static assert(is(typeof(t[1]) == real));
1432 assert(*p0 == t[0]);
1433 assert(*p1 == t[1]);
1437 Tuple!(int, "x", real, "y", double, "z", string) t;
1442 auto a = t.slice!(0, 3);
1443 assert(a.length == 3);
1447 auto b = t.slice!(2, 4);
1448 assert(b.length == 2);
1450 assert(b[1] == t[3]);
1454 Tuple!(Tuple!(int, real), Tuple!(string, "s")) t;
1455 static assert(is(typeof(t[0]) == Tuple!(int, real)));
1456 static assert(is(typeof(t[1]) == Tuple!(string, "s")));
1457 static assert(is(typeof(t[0][0]) == int));
1458 static assert(is(typeof(t[0][1]) == real));
1459 static assert(is(typeof(t[1].s) == string));
1460 t[0] = tuple(10, 20.0L);
1462 assert(t[0][0] == 10);
1463 assert(t[0][1] == 20.0L);
1464 assert(t[1].s == "abc");
1471 this(this) { ++count; }
1472 ~this() { --count; }
1473 void opAssign(S rhs) { count = rhs.count; }
1476 Tuple!(S, S) ssCopy = ss;
1477 assert(ssCopy[0].count == 1);
1478 assert(ssCopy[1].count == 1);
1479 ssCopy[1] = ssCopy[0];
1480 assert(ssCopy[1].count == 2);
1486 Tuple!(int, int) _front;
1487 @property ref Tuple!(int, int) front() return { return _front; }
1488 @property bool empty() { return _front[0] >= 10; }
1489 void popFront() { ++_front[0]; }
1493 static assert(is(typeof(a) == Tuple!(int, int)));
1494 assert(0 <= a[0] && a[0] < 10);
1498 // Construction with compatible elements
1500 auto t1 = Tuple!(int, double)(1, 1);
1503 auto t8702a = tuple(tuple(1));
1504 auto t8702b = Tuple!(Tuple!(int))(Tuple!(int)(1));
1506 // Construction with compatible tuple
1511 Tuple!(int, "a", double, "b") y = x;
1515 static assert(!__traits(compiles, Tuple!(int, int)(y)));
1521 alias T = Tuple!(const(int));
1526 alias T = Tuple!(int[1][]);
1531 auto tup = tuple(1, "2");
1532 assert(tup.reverse == tuple("2", 1));
1535 Tuple!(int, "x", string, "y") tup = tuple(1, "2");
1536 auto rev = tup.reverse;
1537 assert(rev == tuple("2", 1));
1538 assert(rev.x == 1 && rev.y == "2");
1541 Tuple!(wchar, dchar, int, "x", string, "y", char, byte, float) tup;
1542 tup = tuple('a', 'b', 3, "4", 'c', cast(byte) 0x0D, 0.00);
1543 auto rev = tup.reverse;
1544 assert(rev == tuple(0.00, cast(byte) 0x0D, 'c', "4", 3, 'b', 'a'));
1545 assert(rev.x == 3 && rev.y == "4");
1552 struct Equ1 { bool opEquals(Equ1) { return true; } }
1553 auto tm1 = tuple(Equ1.init);
1554 const tc1 = tuple(Equ1.init);
1555 static assert( is(typeof(tm1 == tm1)));
1556 static assert(!is(typeof(tm1 == tc1)));
1557 static assert(!is(typeof(tc1 == tm1)));
1558 static assert(!is(typeof(tc1 == tc1)));
1560 struct Equ2 { bool opEquals(const Equ2) const { return true; } }
1561 auto tm2 = tuple(Equ2.init);
1562 const tc2 = tuple(Equ2.init);
1563 static assert( is(typeof(tm2 == tm2)));
1564 static assert( is(typeof(tm2 == tc2)));
1565 static assert( is(typeof(tc2 == tm2)));
1566 static assert( is(typeof(tc2 == tc2)));
1568 struct Equ3 { bool opEquals(T)(T) { return true; } }
1569 auto tm3 = tuple(Equ3.init); // bugzilla 8686
1570 const tc3 = tuple(Equ3.init);
1571 static assert( is(typeof(tm3 == tm3)));
1572 static assert( is(typeof(tm3 == tc3)));
1573 static assert(!is(typeof(tc3 == tm3)));
1574 static assert(!is(typeof(tc3 == tc3)));
1576 struct Equ4 { bool opEquals(T)(T) const { return true; } }
1577 auto tm4 = tuple(Equ4.init);
1578 const tc4 = tuple(Equ4.init);
1579 static assert( is(typeof(tm4 == tm4)));
1580 static assert( is(typeof(tm4 == tc4)));
1581 static assert( is(typeof(tc4 == tm4)));
1582 static assert( is(typeof(tc4 == tc4)));
1586 struct Cmp1 { int opCmp(Cmp1) { return 0; } }
1587 auto tm1 = tuple(Cmp1.init);
1588 const tc1 = tuple(Cmp1.init);
1589 static assert( is(typeof(tm1 < tm1)));
1590 static assert(!is(typeof(tm1 < tc1)));
1591 static assert(!is(typeof(tc1 < tm1)));
1592 static assert(!is(typeof(tc1 < tc1)));
1594 struct Cmp2 { int opCmp(const Cmp2) const { return 0; } }
1595 auto tm2 = tuple(Cmp2.init);
1596 const tc2 = tuple(Cmp2.init);
1597 static assert( is(typeof(tm2 < tm2)));
1598 static assert( is(typeof(tm2 < tc2)));
1599 static assert( is(typeof(tc2 < tm2)));
1600 static assert( is(typeof(tc2 < tc2)));
1602 struct Cmp3 { int opCmp(T)(T) { return 0; } }
1603 auto tm3 = tuple(Cmp3.init);
1604 const tc3 = tuple(Cmp3.init);
1605 static assert( is(typeof(tm3 < tm3)));
1606 static assert( is(typeof(tm3 < tc3)));
1607 static assert(!is(typeof(tc3 < tm3)));
1608 static assert(!is(typeof(tc3 < tc3)));
1610 struct Cmp4 { int opCmp(T)(T) const { return 0; } }
1611 auto tm4 = tuple(Cmp4.init);
1612 const tc4 = tuple(Cmp4.init);
1613 static assert( is(typeof(tm4 < tm4)));
1614 static assert( is(typeof(tm4 < tc4)));
1615 static assert( is(typeof(tc4 < tm4)));
1616 static assert( is(typeof(tc4 < tc4)));
1619 static void test14890(inout int[] dummy)
1621 alias V = Tuple!(int, int);
1626 inout V wv; // OK <- NG
1627 inout const V wcv; // OK <- NG
1629 foreach (v1; AliasSeq!(mv, cv, iv, wv, wcv))
1630 foreach (v2; AliasSeq!(mv, cv, iv, wv, wcv))
1636 int[2] ints = [ 1, 2 ];
1637 Tuple!(int, int) t = ints;
1638 assert(t[0] == 1 && t[1] == 2);
1639 Tuple!(long, uint) t2 = ints;
1640 assert(t2[0] == 1 && t2[1] == 2);
1645 auto t1 = Tuple!(int, "x", string, "y")(1, "a");
1647 assert(t1.y == "a");
1648 void foo(Tuple!(int, string) t2) {}
1651 Tuple!(int, int)[] arr;
1652 arr ~= tuple(10, 20); // OK
1653 arr ~= Tuple!(int, "x", int, "y")(10, 20); // NG -> OK
1655 static assert(is(typeof(Tuple!(int, "x", string, "y").tupleof) ==
1656 typeof(Tuple!(int, string ).tupleof)));
1661 immutable Tuple!(int) t1;
1662 auto r1 = t1[0]; // OK
1663 immutable Tuple!(int, "x") t2;
1664 auto r2 = t2[0]; // error
1668 import std.exception : assertCTFEable;
1674 t = tuple(2); // assignment
1680 Tuple!(immutable(Foo)[]) a;
1685 //Test non-assignable
1690 alias IS = immutable S;
1691 static assert(!isAssignable!IS);
1695 alias TIS = Tuple!IS;
1699 alias TISIS = Tuple!(IS, IS);
1700 TISIS d = tuple(s, s);
1702 TISIS e = TISIS(ss);
1708 alias T = Tuple!(int, "x", double, "foo");
1709 static assert(T.fieldNames[0] == "x");
1710 static assert(T.fieldNames[1] == "foo");
1712 alias Fields = Tuple!(int, "id", string, float);
1713 static assert(Fields.fieldNames == AliasSeq!("id", "", ""));
1719 // New behaviour, named arguments.
1721 typeof(tuple!("x")(1)) == Tuple!(int, "x")));
1723 typeof(tuple!("x")(1.0)) == Tuple!(double, "x")));
1725 typeof(tuple!("x")("foo")) == Tuple!(string, "x")));
1727 typeof(tuple!("x", "y")(1, 2.0)) == Tuple!(int, "x", double, "y")));
1729 auto a = tuple!("a", "b", "c")("1", 2, 3.0f);
1730 static assert(is(typeof(a.a) == string));
1731 static assert(is(typeof(a.b) == int));
1732 static assert(is(typeof(a.c) == float));
1734 // Old behaviour, but with explicit type parameters.
1736 typeof(tuple!(int, double)(1, 2.0)) == Tuple!(int, double)));
1738 typeof(tuple!(const int)(1)) == Tuple!(const int)));
1740 typeof(tuple()) == Tuple!()));
1742 // Nonsensical behaviour
1743 static assert(!__traits(compiles, tuple!(1)(2)));
1744 static assert(!__traits(compiles, tuple!("x")(1, 2)));
1745 static assert(!__traits(compiles, tuple!("x", "y")(1)));
1746 static assert(!__traits(compiles, tuple!("x")()));
1747 static assert(!__traits(compiles, tuple!("x", int)(2)));
1753 Tuple!(Rebindable!(const C)) a;
1758 @nogc @safe unittest
1760 alias T = Tuple!(string, "s");
1767 import std.format : format, FormatException;
1768 import std.exception : assertThrown;
1770 // enum tupStr = tuple(1, 1.0).toString; // toString is *impure*.
1771 //static assert(tupStr == `Tuple!(int, double)(1, 1)`);
1773 Tuple!(int, double)[3] tupList = [ tuple(1, 1.0), tuple(2, 4.0), tuple(3, 9.0) ];
1776 assert(format("%s", tuple("a", 1)) == `Tuple!(string, int)("a", 1)`);
1778 // One Format for each individual component
1779 assert(format("%(%#x v %.4f w %#x%)", tuple(1, 1.0, 10)) == `0x1 v 1.0000 w 0xa`);
1780 assert(format( "%#x v %.4f w %#x" , tuple(1, 1.0, 10).expand) == `0x1 v 1.0000 w 0xa`);
1782 // One Format for all components
1783 assert(format("%(>%s<%| & %)", tuple("abc", 1, 2.3, [4, 5])) == `>abc< & >1< & >2.3< & >[4, 5]<`);
1786 assert(format("%(%(f(%d) = %.1f%); %)", tupList) == `f(1) = 1.0; f(2) = 4.0; f(3) = 9.0`);
1789 // Error: %( %) missing.
1790 assertThrown!FormatException(
1791 format("%d, %f", tuple(1, 2.0)) == `1, 2.0`
1794 // Error: %( %| %) missing.
1795 assertThrown!FormatException(
1796 format("%d", tuple(1, 2)) == `1, 2`
1799 // Error: %d inadequate for double
1800 assertThrown!FormatException(
1801 format("%(%d%|, %)", tuple(1, 2.0)) == `1, 2.0`
1806 Constructs a $(LREF Tuple) object instantiated and initialized according to
1807 the given arguments.
1810 Names = An optional list of strings naming each successive field of the `Tuple`.
1811 Each name matches up with the corresponding field given by `Args`.
1812 A name does not have to be provided for every field, but as
1813 the names must proceed in order, it is not possible to skip
1814 one field and name the next after it.
1816 template tuple(Names...)
1820 args = Values to initialize the `Tuple` with. The `Tuple`'s type will
1821 be inferred from the types of the values given.
1824 A new `Tuple` with its type inferred from the arguments given.
1826 auto tuple(Args...)(Args args)
1828 static if (Names.length == 0)
1830 // No specified names, just infer types from Args...
1831 return Tuple!Args(args);
1833 else static if (!is(typeof(Names[0]) : string))
1835 // Names[0] isn't a string, must be explicit types.
1836 return Tuple!Names(args);
1840 // Names[0] is a string, so must be specifying names.
1841 static assert(Names.length == Args.length,
1842 "Insufficient number of names given.");
1844 // Interleave(a, b).and(c, d) == (a, c, b, d)
1845 // This is to get the interleaving of types and names for Tuple
1846 // e.g. Tuple!(int, "x", string, "y")
1847 template Interleave(A...)
1849 template and(B...) if (B.length == 1)
1851 alias and = AliasSeq!(A[0], B[0]);
1854 template and(B...) if (B.length != 1)
1856 alias and = AliasSeq!(A[0], B[0],
1857 Interleave!(A[1..$]).and!(B[1..$]));
1860 return Tuple!(Interleave!(Args).and!(Names))(args);
1868 auto value = tuple(5, 6.7, "hello");
1869 assert(value[0] == 5);
1870 assert(value[1] == 6.7);
1871 assert(value[2] == "hello");
1873 // Field names can be provided.
1874 auto entry = tuple!("index", "value")(4, "Hello");
1875 assert(entry.index == 4);
1876 assert(entry.value == "Hello");
1880 Returns $(D true) if and only if $(D T) is an instance of $(D std.typecons.Tuple).
1883 T = The type to check.
1886 true if `T` is a `Tuple` type, false otherwise.
1888 enum isTuple(T) = __traits(compiles,
1890 void f(Specs...)(Tuple!Specs tup) {}
1897 static assert(isTuple!(Tuple!()));
1898 static assert(isTuple!(Tuple!(int)));
1899 static assert(isTuple!(Tuple!(int, real, string)));
1900 static assert(isTuple!(Tuple!(int, "x", real, "y")));
1901 static assert(isTuple!(Tuple!(int, Tuple!(real), string)));
1906 static assert(isTuple!(const Tuple!(int)));
1907 static assert(isTuple!(immutable Tuple!(int)));
1909 static assert(!isTuple!(int));
1910 static assert(!isTuple!(const int));
1913 static assert(!isTuple!(S));
1916 // used by both Rebindable and UnqualRef
1917 private mixin template RebindableCommon(T, U, alias This)
1918 if (is(T == class) || is(T == interface) || isAssociativeArray!T)
1926 @trusted pure nothrow @nogc
1928 void opAssign(T another)
1930 stripped = cast(U) another;
1933 void opAssign(typeof(this) another)
1935 stripped = another.stripped;
1938 static if (is(T == const U) && is(T == const shared U))
1940 // safely assign immutable to const / const shared
1941 void opAssign(This!(immutable U) another)
1943 stripped = another.stripped;
1949 opAssign(initializer);
1952 @property inout(T) get() inout
1962 $(D Rebindable!(T)) is a simple, efficient wrapper that behaves just
1963 like an object of type $(D T), except that you can reassign it to
1964 refer to another object. For completeness, $(D Rebindable!(T)) aliases
1965 itself away to $(D T) if $(D T) is a non-const object type.
1967 You may want to use $(D Rebindable) when you want to have mutable
1968 storage referring to $(D const) objects, for example an array of
1969 references that must be sorted in place. $(D Rebindable) does not
1970 break the soundness of D's type system and does not incur any of the
1971 risks usually associated with $(D cast).
1974 T = An object, interface, array slice type, or associative array type.
1976 template Rebindable(T)
1977 if (is(T == class) || is(T == interface) || isDynamicArray!T || isAssociativeArray!T)
1979 static if (is(T == const U, U) || is(T == immutable U, U))
1981 static if (isDynamicArray!T)
1983 import std.range.primitives : ElementEncodingType;
1984 alias Rebindable = const(ElementEncodingType!T)[];
1990 mixin RebindableCommon!(T, U, Rebindable);
1996 alias Rebindable = T;
2000 ///Regular $(D const) object references cannot be reassigned.
2003 class Widget { int x; int y() const { return x; } }
2004 const a = new Widget;
2007 // error! can't modify const a
2009 // error! can't modify const a
2014 However, $(D Rebindable!(Widget)) does allow reassignment,
2015 while otherwise behaving exactly like a $(D const Widget).
2019 class Widget { int x; int y() const { return x; } }
2020 auto a = Rebindable!(const Widget)(new Widget);
2023 // error! can't modify const a
2029 @safe unittest // issue 16054
2031 Rebindable!(immutable Object) r;
2032 static assert(__traits(compiles, r.get()));
2033 static assert(!__traits(compiles, &r.get()));
2037 Convenience function for creating a $(D Rebindable) using automatic type
2041 obj = A reference to an object, interface, associative array, or an array slice
2042 to initialize the `Rebindable` with.
2045 A newly constructed `Rebindable` initialized with the given reference.
2047 Rebindable!T rebindable(T)(T obj)
2048 if (is(T == class) || is(T == interface) || isDynamicArray!T || isAssociativeArray!T)
2056 This function simply returns the $(D Rebindable) object passed in. It's useful
2057 in generic programming cases when a given object may be either a regular
2058 $(D class) or a $(D Rebindable).
2061 obj = An instance of Rebindable!T.
2064 `obj` without any modification.
2066 Rebindable!T rebindable(T)(Rebindable!T obj)
2073 interface CI { int foo() const; }
2075 int foo() const { return 42; }
2076 @property int bar() const { return 23; }
2078 Rebindable!(C) obj0;
2079 static assert(is(typeof(obj0) == C));
2081 Rebindable!(const(C)) obj1;
2082 static assert(is(typeof(obj1.get) == const(C)), typeof(obj1.get).stringof);
2083 static assert(is(typeof(obj1.stripped) == C));
2085 assert(obj1.get !is null);
2086 obj1 = new const(C);
2087 assert(obj1.get !is null);
2089 Rebindable!(immutable(C)) obj2;
2090 static assert(is(typeof(obj2.get) == immutable(C)));
2091 static assert(is(typeof(obj2.stripped) == C));
2092 obj2 = new immutable(C);
2093 assert(obj1.get !is null);
2096 assert(obj2.foo() == 42);
2097 assert(obj2.bar == 23);
2099 interface I { final int foo() const { return 42; } }
2100 Rebindable!(I) obj3;
2101 static assert(is(typeof(obj3) == I));
2103 Rebindable!(const I) obj4;
2104 static assert(is(typeof(obj4.get) == const I));
2105 static assert(is(typeof(obj4.stripped) == I));
2106 static assert(is(typeof(obj4.foo()) == int));
2107 obj4 = new class I {};
2109 Rebindable!(immutable C) obj5i;
2110 Rebindable!(const C) obj5c;
2114 static assert(!__traits(compiles, obj5i = obj5c));
2116 // Test the convenience functions.
2117 auto obj5convenience = rebindable(obj5i);
2118 assert(obj5convenience is obj5i);
2120 auto obj6 = rebindable(new immutable(C));
2121 static assert(is(typeof(obj6) == Rebindable!(immutable C)));
2122 assert(obj6.foo() == 42);
2124 auto obj7 = rebindable(new C);
2125 CI interface1 = obj7;
2126 auto interfaceRebind1 = rebindable(interface1);
2127 assert(interfaceRebind1.foo() == 42);
2129 const interface2 = interface1;
2130 auto interfaceRebind2 = rebindable(interface2);
2131 assert(interfaceRebind2.foo() == 42);
2133 auto arr = [1,2,3,4,5];
2134 const arrConst = arr;
2135 assert(rebindable(arr) == arr);
2136 assert(rebindable(arrConst) == arr);
2139 immutable(char[]) s7654;
2140 Rebindable!(typeof(s7654)) r7654 = s7654;
2142 foreach (T; AliasSeq!(char, wchar, char, int))
2144 static assert(is(Rebindable!(immutable(T[])) == immutable(T)[]));
2145 static assert(is(Rebindable!(const(T[])) == const(T)[]));
2146 static assert(is(Rebindable!(T[]) == T[]));
2150 static assert(!__traits(compiles, Rebindable!(int[1])));
2151 static assert(!__traits(compiles, Rebindable!(const int[1])));
2153 // Pull request 3341
2154 Rebindable!(immutable int[int]) pr3341 = [123:345];
2155 assert(pr3341[123] == 345);
2156 immutable int[int] pr3341_aa = [321:543];
2158 assert(pr3341[321] == 543);
2159 assert(rebindable(pr3341_aa)[321] == 543);
2163 Similar to $(D Rebindable!(T)) but strips all qualifiers from the reference as
2164 opposed to just constness / immutability. Primary intended use case is with
2165 shared (having thread-local reference to shared class data)
2168 T = A class or interface type.
2170 template UnqualRef(T)
2171 if (is(T == class) || is(T == interface))
2173 static if (is(T == const U, U)
2174 || is(T == immutable U, U)
2175 || is(T == shared U, U)
2176 || is(T == const shared U, U))
2180 mixin RebindableCommon!(T, U, UnqualRef);
2185 alias UnqualRef = T;
2194 static shared(Data) a;
2195 static UnqualRef!(shared Data) b;
2199 auto thread = new core.thread.Thread({
2200 a = new shared Data();
2201 b = new shared Data();
2214 alias T = UnqualRef!(const shared C);
2215 static assert(is(typeof(T.stripped) == C));
2221 Order the provided members to minimize size while preserving alignment.
2222 Alignment is not always optimal for 80-bit reals, nor for structs declared
2226 E = A list of the types to be aligned, representing fields
2227 of an aggregate such as a `struct` or `class`.
2229 names = The names of the fields that are to be aligned.
2232 A string to be mixed in to an aggregate, such as a `struct` or `class`.
2234 string alignForSize(E...)(const char[][] names...)
2236 // Sort all of the members by .alignof.
2237 // BUG: Alignment is not always optimal for align(1) structs
2238 // or 80-bit reals or 64-bit primitives on x86.
2239 // TRICK: Use the fact that .alignof is always a power of 2,
2240 // and maximum 16 on extant systems. Thus, we can perform
2241 // a very limited radix sort.
2242 // Contains the members with .alignof = 64,32,16,8,4,2,1
2244 assert(E.length == names.length,
2245 "alignForSize: There should be as many member names as the types");
2247 string[7] declaration = ["", "", "", "", "", "", ""];
2252 auto k = a >= 64? 0 : a >= 32? 1 : a >= 16? 2 : a >= 8? 3 : a >= 4? 4 : a >= 2? 5 : 6;
2253 declaration[k] ~= T.stringof ~ " " ~ names[i] ~ ";\n";
2257 foreach (decl; declaration)
2266 mixin(alignForSize!(byte[6], double)(["name", "height"]));
2272 enum x = alignForSize!(int[], char[3], short, double[5])("x", "y","z", "w");
2273 struct Foo { int x; }
2274 enum y = alignForSize!(ubyte, Foo, cdouble)("x", "y", "z");
2276 enum passNormalX = x == "double[5] w;\nint[] x;\nshort z;\nchar[3] y;\n";
2277 enum passNormalY = y == "cdouble z;\nFoo y;\nubyte x;\n";
2279 enum passAbnormalX = x == "int[] x;\ndouble[5] w;\nshort z;\nchar[3] y;\n";
2280 enum passAbnormalY = y == "Foo y;\ncdouble z;\nubyte x;\n";
2281 // ^ blame http://d.puremagic.com/issues/show_bug.cgi?id=231
2283 static assert(passNormalX || passAbnormalX && double.alignof <= (int[]).alignof);
2284 static assert(passNormalY || passAbnormalY && double.alignof <= int.alignof);
2290 immutable string[] fieldNames = ["x", "y"];
2293 mixin(alignForSize!(byte, int)(fieldNames));
2298 Defines a value paired with a distinctive "null" state that denotes
2299 the absence of a value. If default constructed, a $(D
2300 Nullable!T) object starts in the null state. Assigning it renders it
2301 non-null. Calling $(D nullify) can nullify it again.
2303 Practically $(D Nullable!T) stores a $(D T) and a $(D bool).
2308 private bool _isNull = true;
2311 Constructor initializing $(D this) with $(D value).
2314 value = The value to initialize this `Nullable` with.
2316 this(inout T value) inout
2323 If they are both null, then they are equal. If one is null and the other
2324 is not, then they are not equal. If they are both non-null, then they are
2325 equal if their values are equal.
2327 bool opEquals()(auto ref const(typeof(this)) rhs) const
2333 return _value == rhs._value;
2337 bool opEquals(U)(auto ref const(U) rhs) const
2338 if (is(typeof(this.get == rhs)))
2340 return _isNull ? false : rhs == _value;
2347 Nullable!int a = 42;
2348 Nullable!int b = 42;
2349 Nullable!int c = 27;
2351 assert(empty == empty);
2352 assert(empty == Nullable!int.init);
2360 assert(empty != 42);
2368 immutable Nullable!int a = 42;
2369 Nullable!int b = 42;
2370 immutable Nullable!int c = 29;
2371 Nullable!int d = 29;
2382 assert(a == const Nullable!int(42));
2383 assert(a != Nullable!int(29));
2389 import std.variant : Variant;
2390 Nullable!Variant a = Variant(12);
2398 import std.format : FormatSpec, formatValue;
2399 // Needs to be a template because of DMD @@BUG@@ 13737.
2400 void toString()(scope void delegate(const(char)[]) sink, FormatSpec!char fmt)
2404 sink.formatValue("Nullable.null", fmt);
2408 sink.formatValue(_value, fmt);
2413 void toString()(scope void delegate(const(char)[]) @safe sink, FormatSpec!char fmt)
2417 sink.formatValue("Nullable.null", fmt);
2421 sink.formatValue(_value, fmt);
2427 Check if `this` is in the null state.
2430 true $(B iff) `this` is in the null state, otherwise false.
2432 @property bool isNull() const @safe pure nothrow
2450 import std.array : appender;
2451 import std.format : formattedWrite;
2453 auto app = appender!string();
2455 formattedWrite(app, "%s", a);
2456 assert(app.data == "1");
2460 Forces $(D this) to the null state.
2471 Nullable!int ni = 0;
2479 Assigns $(D value) to the internally-held state. If the assignment
2480 succeeds, $(D this) becomes non-null.
2483 value = A value of type `T` to assign to this `Nullable`.
2485 void opAssign()(T value)
2492 If this `Nullable` wraps a type that already has a null value
2493 (such as a pointer), then assigning the null value to this
2494 `Nullable` is no different than assigning any other value of
2495 type `T`, and the resulting code will look very strange. It
2496 is strongly recommended that this be avoided by instead using
2497 the version of `Nullable` that takes an additional `nullValue`
2503 Nullable!(int*) npi;
2508 assert(!npi.isNull);
2512 Gets the value. $(D this) must not be in the null state.
2513 This function is also called for the implicit conversion to $(D T).
2516 The value held internally by this `Nullable`.
2518 @property ref inout(T) get() inout @safe pure nothrow
2520 enum message = "Called `get' on null Nullable!" ~ T.stringof ~ ".";
2521 assert(!isNull, message);
2528 import core.exception : AssertError;
2529 import std.exception : assertThrown, assertNotThrown;
2533 //`get` is implicitly called. Will throw
2534 //an AssertError in non-release mode
2535 assertThrown!AssertError(i = ni);
2539 assertNotThrown!AssertError(i = ni);
2544 Implicitly converts to $(D T).
2545 $(D this) must not be in the null state.
2551 auto nullable(T)(T t)
2553 return Nullable!T(t);
2559 struct CustomerRecord
2566 Nullable!CustomerRecord getByName(string name)
2568 //A bunch of hairy stuff
2570 return Nullable!CustomerRecord.init;
2573 auto queryResult = getByName("Doe, John");
2574 if (!queryResult.isNull)
2576 //Process Mr. Doe's customer record
2577 auto address = queryResult.address;
2578 auto customerNum = queryResult.customerNum;
2580 //Do some things with this customer's info
2584 //Add the customer to the database
2591 import std.exception : assertThrown;
2593 auto a = 42.nullable;
2595 assert(a.get == 42);
2599 assertThrown!Throwable(a.get);
2604 import std.exception : assertThrown;
2608 assertThrown!Throwable(a.get);
2623 assertThrown!Throwable(a += 2);
2627 auto k = Nullable!int(74);
2634 static int f(in Nullable!int x) {
2635 return x.isNull ? 42 : x.get;
2646 import std.exception : assertThrown;
2648 static struct S { int x; }
2654 assert(s.get != S(0));
2656 assert(s.x == 9190);
2658 assertThrown!Throwable(s.x = 9441);
2662 // Ensure Nullable can be used in pure/nothrow/@safe environment.
2663 function() @safe pure nothrow
2676 // Ensure Nullable can be used when the value is not pure/nothrow/@safe
2680 this(this) @system {}
2694 alias N = Nullable!int;
2699 b = a; // `N b = a;` works fine
2706 //Check nullable immutable is constructable
2708 auto a1 = Nullable!(immutable int)();
2709 auto a2 = Nullable!(immutable int)(1);
2712 //Check immutable nullable is constructable
2714 auto a1 = immutable (Nullable!int)();
2715 auto a2 = immutable (Nullable!int)(1);
2721 alias NInt = Nullable!int;
2725 //from other Nullable null
2730 //from other Nullable non-null
2735 //Construct from similar nullable
2736 auto a3 = immutable(NInt)();
2743 //from other Nullable null
2749 //from other Nullable non-null
2755 //Construct from similar nullable
2756 auto a3 = immutable(NInt)();
2764 //Check nullable is nicelly embedable in a struct
2769 static struct S2 //inspired from 9404
2776 void opAssign(S2 other)
2781 foreach (S; AliasSeq!(S1, S2))
2793 JSONValue value = null;
2794 auto na = Nullable!JSONValue(value);
2796 struct S1 { int val; }
2797 struct S2 { int* val; }
2798 struct S3 { immutable int* val; }
2802 immutable si = immutable S1(1);
2803 auto x1 = Nullable!S1(sm);
2804 auto x2 = immutable Nullable!S1(sm);
2805 auto x3 = Nullable!S1(si);
2806 auto x4 = immutable Nullable!S1(si);
2807 assert(x1.val == 1);
2808 assert(x2.val == 1);
2809 assert(x3.val == 1);
2810 assert(x4.val == 1);
2818 immutable si = immutable S2(&ni);
2819 auto x1 = Nullable!S2(sm);
2820 static assert(!__traits(compiles, { auto x2 = immutable Nullable!S2(sm); }));
2821 static assert(!__traits(compiles, { auto x3 = Nullable!S2(si); }));
2822 auto x4 = immutable Nullable!S2(si);
2823 assert(*x1.val == 10);
2824 assert(*x4.val == 10);
2829 immutable si = immutable S3(&ni);
2830 auto x1 = Nullable!S3(sm);
2831 auto x2 = immutable Nullable!S3(sm);
2832 auto x3 = Nullable!S3(si);
2833 auto x4 = immutable Nullable!S3(si);
2834 assert(*x1.val == 10);
2835 assert(*x2.val == 10);
2836 assert(*x3.val == 10);
2837 assert(*x4.val == 10);
2843 import std.datetime;
2844 Nullable!SysTime time = SysTime(0);
2848 import std.conv : to;
2852 Appender!string buffer;
2855 assert(ni.to!string() == "Nullable.null");
2857 struct Test { string s; }
2858 alias NullableTest = Nullable!Test;
2860 NullableTest nt = Test("test");
2861 assert(nt.to!string() == `Test("test")`);
2863 NullableTest ntn = Test("null");
2864 assert(ntn.to!string() == `Test("null")`);
2875 override string toString()
2877 return d.to!string();
2880 Nullable!TestToString ntts = new TestToString(2.5);
2881 assert(ntts.to!string() == "2.5");
2885 Just like $(D Nullable!T), except that the null state is defined as a
2886 particular value. For example, $(D Nullable!(uint, uint.max)) is an
2887 $(D uint) that sets aside the value $(D uint.max) to denote a null
2888 state. $(D Nullable!(T, nullValue)) is more storage-efficient than $(D
2889 Nullable!T) because it does not need to store an extra $(D bool).
2892 T = The wrapped type for which Nullable provides a null value.
2894 nullValue = The null value which denotes the null state of this
2895 `Nullable`. Must be of type `T`.
2897 struct Nullable(T, T nullValue)
2899 private T _value = nullValue;
2902 Constructor initializing $(D this) with $(D value).
2905 value = The value to initialize this `Nullable` with.
2914 import std.format : FormatSpec, formatValue;
2915 // Needs to be a template because of DMD @@BUG@@ 13737.
2916 void toString()(scope void delegate(const(char)[]) sink, FormatSpec!char fmt)
2920 sink.formatValue("Nullable.null", fmt);
2924 sink.formatValue(_value, fmt);
2930 Check if `this` is in the null state.
2933 true $(B iff) `this` is in the null state, otherwise false.
2935 @property bool isNull() const
2937 //Need to use 'is' if T is a nullable type and
2938 //nullValue is null, or it's a compiler error
2939 static if (is(CommonType!(T, typeof(null)) == T) && nullValue is null)
2941 return _value is nullValue;
2943 //Need to use 'is' if T is a float type
2944 //because NaN != NaN
2945 else static if (isFloatingPoint!T)
2947 return _value is nullValue;
2951 return _value == nullValue;
2958 Nullable!(int, -1) ni;
2959 //Initialized to "null" state
2966 // https://issues.dlang.org/show_bug.cgi?id=11135
2967 // disable test until https://issues.dlang.org/show_bug.cgi?id=15316 gets fixed
2968 version (none) @system unittest
2970 foreach (T; AliasSeq!(float, double, real))
2972 Nullable!(T, T.init) nf;
2973 //Initialized to "null" state
2975 assert(nf is typeof(nf).init);
2986 Forces $(D this) to the null state.
2996 Nullable!(int, -1) ni = 0;
3004 Assigns $(D value) to the internally-held state. If the assignment
3005 succeeds, $(D this) becomes non-null. No null checks are made. Note
3006 that the assignment may leave $(D this) in the null state.
3009 value = A value of type `T` to assign to this `Nullable`.
3010 If it is `nullvalue`, then the internal state of
3011 this `Nullable` will be set to null.
3013 void opAssign()(T value)
3019 If this `Nullable` wraps a type that already has a null value
3020 (such as a pointer), and that null value is not given for
3021 `nullValue`, then assigning the null value to this `Nullable`
3022 is no different than assigning any other value of type `T`,
3023 and the resulting code will look very strange. It is strongly
3024 recommended that this be avoided by using `T`'s "built in"
3025 null value for `nullValue`.
3030 enum nullVal = cast(int*) 0xCAFEBABE;
3031 Nullable!(int*, nullVal) npi;
3036 assert(!npi.isNull);
3040 Gets the value. $(D this) must not be in the null state.
3041 This function is also called for the implicit conversion to $(D T).
3044 The value held internally by this `Nullable`.
3046 @property ref inout(T) get() inout
3048 //@@@6169@@@: We avoid any call that might evaluate nullValue's %s,
3049 //Because it might messup get's purity and safety inference.
3050 enum message = "Called `get' on null Nullable!(" ~ T.stringof ~ ",nullValue).";
3051 assert(!isNull, message);
3058 import std.exception : assertThrown, assertNotThrown;
3060 Nullable!(int, -1) ni;
3061 //`get` is implicitly called. Will throw
3062 //an error in non-release mode
3063 assertThrown!Throwable(ni == 0);
3066 assertNotThrown!Throwable(ni == 0);
3070 Implicitly converts to $(D T).
3071 $(D this) must not be in the null state.
3077 auto nullable(alias nullValue, T)(T t)
3078 if (is (typeof(nullValue) == T))
3080 return Nullable!(T, nullValue)(t);
3086 Nullable!(size_t, size_t.max) indexOf(string[] haystack, string needle)
3088 //Find the needle, returning -1 if not found
3090 return Nullable!(size_t, size_t.max).init;
3093 void sendLunchInvite(string name)
3097 //It's safer than C...
3098 auto coworkers = ["Jane", "Jim", "Marry", "Fred"];
3099 auto pos = indexOf(coworkers, "Bob");
3102 //Send Bob an invitation to lunch
3103 sendLunchInvite(coworkers[pos]);
3107 //Bob not found; report the error
3110 //And there's no overhead
3111 static assert(Nullable!(size_t, size_t.max).sizeof == size_t.sizeof);
3117 import std.exception : assertThrown;
3119 Nullable!(int, int.min) a;
3121 assertThrown!Throwable(a.get);
3125 static assert(a.sizeof == int.sizeof);
3131 auto a = nullable!(int.min)(8);
3139 static int f(in Nullable!(int, int.min) x) {
3140 return x.isNull ? 42 : x.get;
3142 Nullable!(int, int.min) a;
3151 // Ensure Nullable can be used in pure/nothrow/@safe environment.
3152 function() @safe pure nothrow
3154 Nullable!(int, int.min) n;
3165 // Ensure Nullable can be used when the value is not pure/nothrow/@system
3169 bool opEquals(const S s) const @system { return s.x == x; }
3172 Nullable!(S, S(711)) s;
3182 //Check nullable is nicelly embedable in a struct
3185 Nullable!(int, 0) ni;
3187 static struct S2 //inspired from 9404
3189 Nullable!(int, 0) ni;
3194 void opAssign(S2 other)
3199 foreach (S; AliasSeq!(S1, S2))
3209 import std.conv : to;
3212 Nullable!(int, 1) ni = 1;
3213 assert(ni.to!string() == "Nullable.null");
3215 struct Test { string s; }
3216 alias NullableTest = Nullable!(Test, Test("null"));
3218 NullableTest nt = Test("test");
3219 assert(nt.to!string() == `Test("test")`);
3221 NullableTest ntn = Test("null");
3222 assert(ntn.to!string() == "Nullable.null");
3233 override string toString()
3235 return d.to!string();
3238 alias NullableTestToString = Nullable!(TestToString, null);
3240 NullableTestToString ntts = new TestToString(2.5);
3241 assert(ntts.to!string() == "2.5");
3246 Just like $(D Nullable!T), except that the object refers to a value
3247 sitting elsewhere in memory. This makes assignments overwrite the
3248 initially assigned value. Internally $(D NullableRef!T) only stores a
3249 pointer to $(D T) (i.e., $(D Nullable!T.sizeof == (T*).sizeof)).
3251 struct NullableRef(T)
3256 Constructor binding $(D this) to $(D value).
3259 value = The value to bind to.
3261 this(T* value) @safe pure nothrow
3268 import std.format : FormatSpec, formatValue;
3269 // Needs to be a template because of DMD @@BUG@@ 13737.
3270 void toString()(scope void delegate(const(char)[]) sink, FormatSpec!char fmt)
3274 sink.formatValue("Nullable.null", fmt);
3278 sink.formatValue(*_value, fmt);
3284 Binds the internal state to $(D value).
3287 value = A pointer to a value of type `T` to bind this `NullableRef` to.
3289 void bind(T* value) @safe pure nothrow
3297 NullableRef!int nr = new int(42);
3300 int* n = new int(1);
3306 Returns $(D true) if and only if $(D this) is in the null state.
3309 true if `this` is in the null state, otherwise false.
3311 @property bool isNull() const @safe pure nothrow
3313 return _value is null;
3322 int* n = new int(42);
3324 assert(!nr.isNull && nr == 42);
3328 Forces $(D this) to the null state.
3330 void nullify() @safe pure nothrow
3338 NullableRef!int nr = new int(42);
3346 Assigns $(D value) to the internally-held state.
3349 value = A value of type `T` to assign to this `NullableRef`.
3350 If the internal state of this `NullableRef` has not
3351 been initialized, an error will be thrown in
3354 void opAssign()(T value)
3355 if (isAssignable!T) //@@@9416@@@
3357 enum message = "Called `opAssign' on null NullableRef!" ~ T.stringof ~ ".";
3358 assert(!isNull, message);
3365 import std.exception : assertThrown, assertNotThrown;
3369 assertThrown!Throwable(nr = 42);
3371 nr.bind(new int(0));
3373 assertNotThrown!Throwable(nr = 42);
3378 Gets the value. $(D this) must not be in the null state.
3379 This function is also called for the implicit conversion to $(D T).
3381 @property ref inout(T) get() inout @safe pure nothrow
3383 enum message = "Called `get' on null NullableRef!" ~ T.stringof ~ ".";
3384 assert(!isNull, message);
3391 import std.exception : assertThrown, assertNotThrown;
3394 //`get` is implicitly called. Will throw
3395 //an error in non-release mode
3396 assertThrown!Throwable(nr == 0);
3398 nr.bind(new int(0));
3399 assertNotThrown!Throwable(nr == 0);
3403 Implicitly converts to $(D T).
3404 $(D this) must not be in the null state.
3410 auto nullableRef(T)(T* t)
3412 return NullableRef!T(t);
3418 import std.exception : assertThrown;
3421 auto a = nullableRef(&x);
3432 assertThrown!Throwable(a.get);
3433 assertThrown!Throwable(a = 71);
3441 static int f(in NullableRef!int x) {
3442 return x.isNull ? 42 : x.get;
3445 auto a = nullableRef(&x);
3452 // Ensure NullableRef can be used in pure/nothrow/@safe environment.
3453 function() @safe pure nothrow
3455 auto storage = new int;
3464 assert(*storage == 2294);
3471 // Ensure NullableRef can be used when the value is not pure/nothrow/@safe
3475 this(this) @system {}
3476 bool opEquals(const S s) const @system { return s.x == x; }
3479 auto storage = S(5);
3491 //Check nullable is nicelly embedable in a struct
3496 static struct S2 //inspired from 9404
3503 void opAssign(S2 other)
3508 foreach (S; AliasSeq!(S1, S2))
3518 import std.conv : to;
3521 NullableRef!int nri;
3522 assert(nri.to!string() == "Nullable.null");
3528 NullableRef!Test nt = new Test("test");
3529 assert(nt.to!string() == `Test("test")`);
3540 override string toString()
3542 return d.to!string();
3545 TestToString tts = new TestToString(2.5);
3546 NullableRef!TestToString ntts = &tts;
3547 assert(ntts.to!string() == "2.5");
3552 $(D BlackHole!Base) is a subclass of $(D Base) which automatically implements
3553 all abstract member functions in $(D Base) as do-nothing functions. Each
3554 auto-implemented function just returns the default value of the return type
3555 without doing anything.
3558 $(HTTP search.cpan.org/~sburke/Class-_BlackHole-0.04/lib/Class/_BlackHole.pm, Class::_BlackHole)
3559 Perl module by Sean M. Burke.
3562 Base = A non-final class for `BlackHole` to inherit from.
3565 $(LREF AutoImplement), $(LREF generateEmptyFunction)
3567 alias BlackHole(Base) = AutoImplement!(Base, generateEmptyFunction, isAbstractFunction);
3572 import std.math : isNaN;
3574 static abstract class C
3577 this(int v) { m_value = v; }
3578 int value() @property { return m_value; }
3580 abstract real realValue() @property;
3581 abstract void doSomething();
3584 auto c = new BlackHole!C(42);
3585 assert(c.value == 42);
3587 // Returns real.init which is NaN
3588 assert(c.realValue.isNaN);
3589 // Abstract functions are implemented as do-nothing
3595 import std.math : isNaN;
3599 interface I_1 { real test(); }
3600 auto o = new BlackHole!I_1;
3601 assert(o.test().isNaN()); // NaN
3608 this(int v) { m_value = v; }
3609 int value() @property { return m_value; }
3611 abstract real realValue() @property;
3612 abstract void doSomething();
3615 auto c = new BlackHole!C(42);
3616 assert(c.value == 42);
3618 assert(c.realValue.isNaN); // NaN
3625 inout(Object) foo() inout;
3632 $(D WhiteHole!Base) is a subclass of $(D Base) which automatically implements
3633 all abstract member functions as functions that always fail. These functions
3634 simply throw an $(D Error) and never return. `Whitehole` is useful for
3635 trapping the use of class member functions that haven't been implemented.
3638 $(HTTP search.cpan.org/~mschwern/Class-_WhiteHole-0.04/lib/Class/_WhiteHole.pm, Class::_WhiteHole)
3639 Perl module by Michael G Schwern.
3642 Base = A non-final class for `WhiteHole` to inherit from.
3645 $(LREF AutoImplement), $(LREF generateAssertTrap)
3647 alias WhiteHole(Base) = AutoImplement!(Base, generateAssertTrap, isAbstractFunction);
3652 import std.exception : assertThrown;
3656 abstract void notYetImplemented();
3659 auto c = new WhiteHole!C;
3660 assertThrown!NotImplementedError(c.notYetImplemented()); // throws an Error
3664 class NotImplementedError : Error
3668 super(method ~ " is not implemented");
3674 import std.exception : assertThrown;
3682 auto o = new WhiteHole!I_1;
3683 assertThrown!NotImplementedError(o.foo());
3684 assertThrown!NotImplementedError(o.bar());
3690 abstract void notYetImplemented();
3693 auto c = new WhiteHole!C;
3696 c.notYetImplemented();
3705 $(D AutoImplement) automatically implements (by default) all abstract member
3706 functions in the class or interface $(D Base) in specified way.
3708 The second version of $(D AutoImplement) automatically implements
3709 $(D Interface), while deriving from $(D BaseClass).
3712 how = template which specifies _how functions will be implemented/overridden.
3714 Two arguments are passed to $(D how): the type $(D Base) and an alias
3715 to an implemented function. Then $(D how) must return an implemented
3716 function body as a string.
3718 The generated function body can use these keywords:
3720 $(LI $(D a0), $(D a1), …: arguments passed to the function;)
3721 $(LI $(D args): a tuple of the arguments;)
3722 $(LI $(D self): an alias to the function itself;)
3723 $(LI $(D parent): an alias to the overridden function (if any).)
3726 You may want to use templated property functions (instead of Implicit
3727 Template Properties) to generate complex functions:
3728 --------------------
3729 // Prints log messages for each call to overridden functions.
3730 string generateLogger(C, alias fun)() @property
3733 enum qname = C.stringof ~ "." ~ __traits(identifier, fun);
3736 stmt ~= q{ struct Importer { import std.stdio; } };
3737 stmt ~= `Importer.writeln("Log: ` ~ qname ~ `(", args, ")");`;
3738 static if (!__traits(isAbstractFunction, fun))
3740 static if (is(ReturnType!fun == void))
3741 stmt ~= q{ parent(args); };
3744 auto r = parent(args);
3745 Importer.writeln("--> ", r);
3751 --------------------
3753 what = template which determines _what functions should be
3754 implemented/overridden.
3756 An argument is passed to $(D what): an alias to a non-final member
3757 function in $(D Base). Then $(D what) must return a boolean value.
3758 Return $(D true) to indicate that the passed function should be
3759 implemented/overridden.
3761 --------------------
3762 // Sees if fun returns something.
3763 enum bool hasValue(alias fun) = !is(ReturnType!(fun) == void);
3764 --------------------
3769 Generated code is inserted in the scope of $(D std.typecons) module. Thus,
3770 any useful functions outside $(D std.typecons) cannot be used in the generated
3771 code. To workaround this problem, you may $(D import) necessary things in a
3772 local struct, as done in the $(D generateLogger()) template in the above
3779 $(LI Variadic arguments to constructors are not forwarded to super.)
3780 $(LI Deep interface inheritance causes compile error with messages like
3781 "Error: function std.typecons._AutoImplement!(Foo)._AutoImplement.bar
3782 does not override any function". [$(BUGZILLA 2525), $(BUGZILLA 3525)] )
3783 $(LI The $(D parent) keyword is actually a delegate to the super class'
3784 corresponding member function. [$(BUGZILLA 2540)] )
3785 $(LI Using alias template parameter in $(D how) and/or $(D what) may cause
3786 strange compile error. Use template tuple parameter instead to workaround
3787 this problem. [$(BUGZILLA 4217)] )
3790 class AutoImplement(Base, alias how, alias what = isAbstractFunction) : Base
3791 if (!is(how == class))
3793 private alias autoImplement_helper_ =
3794 AutoImplement_Helper!("autoImplement_helper_", "Base", Base, typeof(this), how, what);
3795 mixin(autoImplement_helper_.code);
3799 class AutoImplement(
3800 Interface, BaseClass, alias how,
3801 alias what = isAbstractFunction) : BaseClass, Interface
3802 if (is(Interface == interface) && is(BaseClass == class))
3804 private alias autoImplement_helper_ = AutoImplement_Helper!(
3805 "autoImplement_helper_", "Interface", Interface, typeof(this), how, what);
3806 mixin(autoImplement_helper_.code);
3810 * Code-generating stuffs are encupsulated in this helper template so that
3811 * namespace pollution, which can cause name confliction with Base's public
3812 * members, should be minimized.
3814 private template AutoImplement_Helper(string myName, string baseName,
3815 Base, Self, alias generateMethodBody, alias cherrypickMethod)
3818 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
3820 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
3822 // Returns function overload sets in the class C, filtered with pred.
3823 template enumerateOverloads(C, alias pred)
3825 template Impl(names...)
3827 import std.meta : Filter;
3828 static if (names.length > 0)
3830 alias methods = Filter!(pred, MemberFunctionsTuple!(C, names[0]));
3831 alias next = Impl!(names[1 .. $]);
3833 static if (methods.length > 0)
3834 alias Impl = AliasSeq!(OverloadSet!(names[0], methods), next);
3839 alias Impl = AliasSeq!();
3842 alias enumerateOverloads = Impl!(__traits(allMembers, C));
3845 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
3847 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
3849 // Add a non-final check to the cherrypickMethod.
3850 enum bool canonicalPicker(fun.../+[BUG 4217]+/) =
3851 !__traits(isFinalFunction, fun[0]) && cherrypickMethod!(fun);
3854 * A tuple of overload sets, each item of which consists of functions to be
3855 * implemented by the generated code.
3857 alias targetOverloadSets = enumerateOverloads!(Base, canonicalPicker);
3860 * Super class of this AutoImplement instance
3862 alias Super = BaseTypeTuple!(Self)[0];
3863 static assert(is(Super == class));
3864 static assert(is(Base == interface) || is(Super == Base));
3867 * A tuple of the super class' constructors. Used for forwarding
3868 * constructor calls.
3870 static if (__traits(hasMember, Super, "__ctor"))
3871 alias ctorOverloadSet = OverloadSet!("__ctor", __traits(getOverloads, Super, "__ctor"));
3873 alias ctorOverloadSet = OverloadSet!("__ctor"); // empty
3876 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
3878 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
3881 * The generated code will be mixed into AutoImplement, which will be
3882 * instantiated in this module's scope. Thus, any user-defined types are
3883 * out of scope and cannot be used directly (i.e. by their names).
3885 * We will use FuncInfo instances for accessing return types and parameter
3886 * types of the implemented functions. The instances will be populated to
3887 * the AutoImplement's scope in a certain way; see the populate() below.
3890 // Returns the preferred identifier for the FuncInfo instance for the i-th
3891 // overloaded function with the name.
3892 template INTERNAL_FUNCINFO_ID(string name, size_t i)
3894 import std.format : format;
3896 enum string INTERNAL_FUNCINFO_ID = format("F_%s_%s", name, i);
3900 * Insert FuncInfo instances about all the target functions here. This
3901 * enables the generated code to access type information via, for example,
3902 * "autoImplement_helper_.F_foo_1".
3904 template populate(overloads...)
3906 static if (overloads.length > 0)
3908 mixin populate!(overloads[0].name, overloads[0].contents);
3909 mixin populate!(overloads[1 .. $]);
3912 template populate(string name, methods...)
3914 static if (methods.length > 0)
3916 mixin populate!(name, methods[0 .. $ - 1]);
3918 alias target = methods[$ - 1];
3919 enum ith = methods.length - 1;
3920 mixin("alias " ~ INTERNAL_FUNCINFO_ID!(name, ith) ~ " = FuncInfo!target;");
3924 public mixin populate!(targetOverloadSets);
3925 public mixin populate!( ctorOverloadSet );
3928 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
3929 // Code-generating policies
3930 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
3932 /* Common policy configurations for generating constructors and methods. */
3933 template CommonGeneratingPolicy()
3935 // base class identifier which generated code should use
3936 enum string BASE_CLASS_ID = baseName;
3938 // FuncInfo instance identifier which generated code should use
3939 template FUNCINFO_ID(string name, size_t i)
3941 enum string FUNCINFO_ID =
3942 myName ~ "." ~ INTERNAL_FUNCINFO_ID!(name, i);
3946 /* Policy configurations for generating constructors. */
3947 template ConstructorGeneratingPolicy()
3949 mixin CommonGeneratingPolicy;
3951 /* Generates constructor body. Just forward to the base class' one. */
3952 string generateFunctionBody(ctor.../+[BUG 4217]+/)() @property
3954 enum varstyle = variadicFunctionStyle!(typeof(&ctor[0]));
3956 static if (varstyle & (Variadic.c | Variadic.d))
3958 // the argptr-forwarding problem
3959 //pragma(msg, "Warning: AutoImplement!(", Base, ") ",
3960 // "ignored variadic arguments to the constructor ",
3961 // FunctionTypeOf!(typeof(&ctor[0])) );
3963 return "super(args);";
3967 /* Policy configurations for genearting target methods. */
3968 template MethodGeneratingPolicy()
3970 mixin CommonGeneratingPolicy;
3972 /* Geneartes method body. */
3973 string generateFunctionBody(func.../+[BUG 4217]+/)() @property
3975 return generateMethodBody!(Base, func); // given
3980 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
3982 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
3984 alias ConstructorGenerator = MemberFunctionGenerator!(ConstructorGeneratingPolicy!());
3985 alias MethodGenerator = MemberFunctionGenerator!(MethodGeneratingPolicy!());
3987 public enum string code =
3988 ConstructorGenerator.generateCode!( ctorOverloadSet ) ~ "\n" ~
3989 MethodGenerator.generateCode!(targetOverloadSets);
3991 debug (SHOW_GENERATED_CODE)
3993 pragma(msg, "-------------------- < ", Base, " >");
3995 pragma(msg, "--------------------");
3999 //debug = SHOW_GENERATED_CODE;
4003 // no function to implement
4006 auto o = new BlackHole!I_1;
4010 interface I_3 { void test(int, in int, out int, ref int, lazy int); }
4011 auto o = new BlackHole!I_3;
4013 // use of user-defined type
4016 interface I_4 { S test(); }
4017 auto o = new BlackHole!I_4;
4027 auto o = new BlackHole!I_5;
4029 // constructor forwarding
4033 this(int n) { assert(n == 42); }
4034 this(string s) { assert(s == "Deeee"); }
4037 auto o1 = new BlackHole!C_6(42);
4038 auto o2 = new BlackHole!C_6("Deeee");
4039 auto o3 = new BlackHole!C_6(1, 2, 3, 4);
4046 int test_pure() pure;
4047 int test_nothrow() nothrow;
4048 int test_property() @property;
4049 int test_safe() @safe;
4050 int test_trusted() @trusted;
4051 int test_system() @system;
4052 int test_pure_nothrow() pure nothrow;
4054 auto o = new BlackHole!I_7;
4060 void test_const() const;
4061 void test_immutable() immutable;
4062 void test_shared() shared;
4063 void test_shared_const() shared const;
4065 auto o = new BlackHole!I_8;
4071 private string foo_;
4077 protected string boilerplate() @property
4079 return "Boilerplate stuff.";
4082 public string foo() @property
4090 string testMethod(size_t);
4093 static string generateTestMethod(C, alias fun)() @property
4095 return "return this.boilerplate[0 .. a0];";
4098 auto o = new AutoImplement!(I_10, C_9, generateTestMethod)("Testing");
4099 assert(o.testMethod(11) == "Boilerplate");
4100 assert(o.foo == "Testing");
4102 /+ // deep inheritance
4104 // XXX [BUG 2525,3525]
4105 // NOTE: [r494] func.c(504-571) FuncDeclaration::semantic()
4106 interface I { void foo(); }
4109 static abstract class C_9 : K {}
4110 auto o = new BlackHole!C_9;
4114 // Issue 17177 - AutoImplement fails on function overload sets with "cannot infer type from overloaded function symbol"
4117 static class Issue17177
4122 Issue17177 overloaded(string n)
4136 static string how(C, alias fun)()
4138 static if (!is(ReturnType!fun == void))
4141 return parent(args);
4152 alias Implementation = AutoImplement!(Issue17177, how, templateNot!isFinalFunction);
4158 // Add prefix "issue10647_" as a workaround for issue 1238
4159 private string issue10647_generateDoNothing(C, alias fun)() @property
4163 static if (is(ReturnType!fun == void))
4167 string returnType = ReturnType!fun.stringof;
4168 stmt ~= "return "~returnType~".init;";
4173 private template issue10647_isAlwaysTrue(alias fun)
4175 enum issue10647_isAlwaysTrue = true;
4178 // Do nothing template
4179 private template issue10647_DoNothing(Base)
4181 alias issue10647_DoNothing = AutoImplement!(Base, issue10647_generateDoNothing, issue10647_isAlwaysTrue);
4184 // A class to be overridden
4185 private class issue10647_Foo{
4191 auto foo = new issue10647_DoNothing!issue10647_Foo();
4196 Used by MemberFunctionGenerator.
4198 package template OverloadSet(string nam, T...)
4200 enum string name = nam;
4205 Used by MemberFunctionGenerator.
4207 package template FuncInfo(alias func, /+[BUG 4217 ?]+/ T = typeof(&func))
4209 alias RT = ReturnType!T;
4210 alias PT = Parameters!T;
4212 package template FuncInfo(Func)
4214 alias RT = ReturnType!Func;
4215 alias PT = Parameters!Func;
4219 General-purpose member function generator.
4220 --------------------
4221 template GeneratingPolicy()
4223 // [optional] the name of the class where functions are derived
4224 enum string BASE_CLASS_ID;
4226 // [optional] define this if you have only function types
4227 enum bool WITHOUT_SYMBOL;
4229 // [optional] Returns preferred identifier for i-th parameter.
4230 template PARAMETER_VARIABLE_ID(size_t i);
4232 // Returns the identifier of the FuncInfo instance for the i-th overload
4233 // of the specified name. The identifier must be accessible in the scope
4234 // where generated code is mixed.
4235 template FUNCINFO_ID(string name, size_t i);
4237 // Returns implemented function body as a string. When WITHOUT_SYMBOL is
4238 // defined, the latter is used.
4239 template generateFunctionBody(alias func);
4240 template generateFunctionBody(string name, FuncType);
4242 --------------------
4244 package template MemberFunctionGenerator(alias Policy)
4247 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4249 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4252 enum CONSTRUCTOR_NAME = "__ctor";
4254 // true if functions are derived from a base class
4255 enum WITH_BASE_CLASS = __traits(hasMember, Policy, "BASE_CLASS_ID");
4257 // true if functions are specified as types, not symbols
4258 enum WITHOUT_SYMBOL = __traits(hasMember, Policy, "WITHOUT_SYMBOL");
4260 // preferred identifier for i-th parameter variable
4261 static if (__traits(hasMember, Policy, "PARAMETER_VARIABLE_ID"))
4263 alias PARAMETER_VARIABLE_ID = Policy.PARAMETER_VARIABLE_ID;
4267 enum string PARAMETER_VARIABLE_ID(size_t i) = format("a%s", i);
4268 // default: a0, a1, ...
4271 // Returns a tuple consisting of 0,1,2,...,n-1. For static foreach.
4272 template CountUp(size_t n)
4275 alias CountUp = AliasSeq!(CountUp!(n - 1), n - 1);
4277 alias CountUp = AliasSeq!();
4281 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4283 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4286 * Runs through all the target overload sets and generates D code which
4287 * implements all the functions in the overload sets.
4289 public string generateCode(overloads...)() @property
4293 // run through all the overload sets
4294 foreach (i_; CountUp!(0 + overloads.length)) // workaround
4296 enum i = 0 + i_; // workaround
4297 alias oset = overloads[i];
4299 code ~= generateCodeForOverloadSet!(oset);
4301 static if (WITH_BASE_CLASS && oset.name != CONSTRUCTOR_NAME)
4303 // The generated function declarations may hide existing ones
4304 // in the base class (cf. HiddenFuncError), so we put an alias
4305 // declaration here to reveal possible hidden functions.
4306 code ~= format("alias %s = %s.%s;\n",
4308 Policy.BASE_CLASS_ID, // [BUG 2540] super.
4315 // handle each overload set
4316 private string generateCodeForOverloadSet(alias oset)() @property
4320 foreach (i_; CountUp!(0 + oset.contents.length)) // workaround
4322 enum i = 0 + i_; // workaround
4323 code ~= generateFunction!(
4324 Policy.FUNCINFO_ID!(oset.name, i), oset.name,
4325 oset.contents[i]) ~ "\n";
4331 * Returns D code which implements the function func. This function
4332 * actually generates only the declarator part; the function body part is
4333 * generated by the functionGenerator() policy.
4335 public string generateFunction(
4336 string myFuncInfo, string name, func... )() @property
4338 import std.format : format;
4340 enum isCtor = (name == CONSTRUCTOR_NAME);
4342 string code; // the result
4344 auto paramsRes = generateParameters!(myFuncInfo, func)();
4345 code ~= paramsRes.imports;
4347 /*** Function Declarator ***/
4349 alias Func = FunctionTypeOf!(func);
4350 alias FA = FunctionAttribute;
4351 enum atts = functionAttributes!(func);
4352 enum realName = isCtor ? "this" : name;
4354 // FIXME?? Make it so that these aren't CTFE funcs any more, since
4355 // Format is deprecated, and format works at compile time?
4356 /* Made them CTFE funcs just for the sake of Format!(...) */
4358 // return type with optional "ref"
4359 static string make_returnType()
4365 if (atts & FA.ref_) rtype ~= "ref ";
4366 rtype ~= myFuncInfo ~ ".RT";
4370 enum returnType = make_returnType();
4372 // function attributes attached after declaration
4373 static string make_postAtts()
4376 if (atts & FA.pure_ ) poatts ~= " pure";
4377 if (atts & FA.nothrow_) poatts ~= " nothrow";
4378 if (atts & FA.property) poatts ~= " @property";
4379 if (atts & FA.safe ) poatts ~= " @safe";
4380 if (atts & FA.trusted ) poatts ~= " @trusted";
4383 enum postAtts = make_postAtts();
4385 // function storage class
4386 static string make_storageClass()
4389 if (is(Func == shared)) postc ~= " shared";
4390 if (is(Func == const)) postc ~= " const";
4391 if (is(Func == inout)) postc ~= " inout";
4392 if (is(Func == immutable)) postc ~= " immutable";
4395 enum storageClass = make_storageClass();
4398 if (__traits(isVirtualMethod, func))
4399 code ~= "override ";
4400 code ~= format("extern(%s) %s %s(%s) %s %s\n",
4401 functionLinkage!(func),
4405 postAtts, storageClass );
4408 /*** Function Body ***/
4411 enum nparams = Parameters!(func).length;
4413 /* Declare keywords: args, self and parent. */
4416 preamble ~= "alias args = AliasSeq!(" ~ enumerateParameters!(nparams) ~ ");\n";
4419 preamble ~= "alias self = " ~ name ~ ";\n";
4420 if (WITH_BASE_CLASS && !__traits(isAbstractFunction, func))
4421 preamble ~= "alias parent = AliasSeq!(__traits(getMember, super, \"" ~ name ~ "\"))[0];";
4425 static if (WITHOUT_SYMBOL)
4426 enum fbody = Policy.generateFunctionBody!(name, func);
4428 enum fbody = Policy.generateFunctionBody!(func);
4439 * Returns D code which declares function parameters,
4440 * and optionally any imports (e.g. core.vararg)
4441 * "ref int a0, real a1, ..."
4443 static struct GenParams { string imports, params; }
4444 private GenParams generateParameters(string myFuncInfo, func...)()
4446 alias STC = ParameterStorageClass;
4447 alias stcs = ParameterStorageClassTuple!(func);
4448 enum nparams = stcs.length;
4450 string imports = ""; // any imports required
4451 string params = ""; // parameters
4453 foreach (i, stc; stcs)
4455 if (i > 0) params ~= ", ";
4457 // Parameter storage classes.
4458 if (stc & STC.scope_) params ~= "scope ";
4459 if (stc & STC.out_ ) params ~= "out ";
4460 if (stc & STC.ref_ ) params ~= "ref ";
4461 if (stc & STC.lazy_ ) params ~= "lazy ";
4463 // Take parameter type from the FuncInfo.
4464 params ~= format("%s.PT[%s]", myFuncInfo, i);
4466 // Declare a parameter variable.
4467 params ~= " " ~ PARAMETER_VARIABLE_ID!(i);
4470 // Add some ellipsis part if needed.
4471 auto style = variadicFunctionStyle!(func);
4472 final switch (style)
4477 case Variadic.c, Variadic.d:
4478 imports ~= "import core.vararg;\n";
4479 // (...) or (a, b, ...)
4480 params ~= (nparams == 0) ? "..." : ", ...";
4483 case Variadic.typesafe:
4488 return typeof(return)(imports, params);
4491 // Returns D code which enumerates n parameter variables using comma as the
4492 // separator. "a0, a1, a2, a3"
4493 private string enumerateParameters(size_t n)() @property
4497 foreach (i_; CountUp!(n))
4499 enum i = 0 + i_; // workaround
4500 if (i > 0) params ~= ", ";
4501 params ~= PARAMETER_VARIABLE_ID!(i);
4509 Predefined how-policies for $(D AutoImplement). These templates are also used by
4510 $(D BlackHole) and $(D WhiteHole), respectively.
4512 template generateEmptyFunction(C, func.../+[BUG 4217]+/)
4514 static if (is(ReturnType!(func) == void))
4515 enum string generateEmptyFunction = q{
4517 else static if (functionAttributes!(func) & FunctionAttribute.ref_)
4518 enum string generateEmptyFunction = q{
4519 static typeof(return) dummy;
4523 enum string generateEmptyFunction = q{
4524 return typeof(return).init;
4529 template generateAssertTrap(C, func...)
4531 enum string generateAssertTrap =
4532 `throw new NotImplementedError("` ~ C.stringof ~ "."
4533 ~ __traits(identifier, func) ~ `");`;
4538 pragma(mangle, "_d_toObject")
4539 extern(C) pure nothrow Object typecons_d_toObject(void* p);
4543 * Avoids opCast operator overloading.
4545 private template dynamicCast(T)
4546 if (is(T == class) || is(T == interface))
4549 T dynamicCast(S)(inout S source)
4550 if (is(S == class) || is(S == interface))
4552 static if (is(Unqual!S : Unqual!T))
4554 import std.traits : QualifierOf;
4555 alias Qual = QualifierOf!S; // SharedOf or MutableOf
4556 alias TmpT = Qual!(Unqual!T);
4557 inout(TmpT) tmp = source; // bypass opCast by implicit conversion
4558 return *cast(T*)(&tmp); // + variable pointer cast + dereference
4562 return cast(T) typecons_d_toObject(*cast(void**)(&source));
4569 class C { @disable opCast(T)() {} }
4571 static assert(!__traits(compiles, cast(Object) c));
4572 auto o = dynamicCast!Object(c);
4575 interface I { @disable opCast(T)() {} Object instance(); }
4576 interface J { @disable opCast(T)() {} Object instance(); }
4577 class D : I, J { Object instance() { return this; } }
4579 static assert(!__traits(compiles, cast(J) i));
4580 J j = dynamicCast!J(i);
4581 assert(i.instance() is j.instance());
4585 * Supports structural based typesafe conversion.
4587 * If $(D Source) has structural conformance with the $(D interface) $(D Targets),
4588 * wrap creates internal wrapper class which inherits $(D Targets) and
4589 * wrap $(D src) object, then return it.
4591 template wrap(Targets...)
4592 if (Targets.length >= 1 && allSatisfy!(isMutable, Targets))
4594 import std.meta : staticMap;
4597 auto wrap(Source)(inout Source src) @trusted pure nothrow
4598 if (Targets.length == 1 && is(Source : Targets[0]))
4600 alias T = Select!(is(Source == shared), shared Targets[0], Targets[0]);
4601 return dynamicCast!(inout T)(src);
4603 // structural upcast
4604 template wrap(Source)
4605 if (!allSatisfy!(Bind!(isImplicitlyConvertible, Source), Targets))
4607 auto wrap(inout Source src)
4609 static assert(hasRequireMethods!(),
4610 "Source "~Source.stringof~
4611 " does not have structural conformance to "~
4614 alias T = Select!(is(Source == shared), shared Impl, Impl);
4615 return new inout T(src);
4618 template FuncInfo(string s, F)
4624 // Concat all Targets function members into one tuple
4625 template Concat(size_t i = 0)
4627 static if (i >= Targets.length)
4628 alias Concat = AliasSeq!();
4631 alias Concat = AliasSeq!(GetOverloadedMethods!(Targets[i]), Concat!(i + 1));
4634 // Remove duplicated functions based on the identifier name and function type covariance
4635 template Uniq(members...)
4637 static if (members.length == 0)
4638 alias Uniq = AliasSeq!();
4641 alias func = members[0];
4642 enum name = __traits(identifier, func);
4643 alias type = FunctionTypeOf!func;
4644 template check(size_t i, mem...)
4646 static if (i >= mem.length)
4647 enum ptrdiff_t check = -1;
4650 enum ptrdiff_t check =
4651 __traits(identifier, func) == __traits(identifier, mem[i]) &&
4652 !is(DerivedFunctionType!(type, FunctionTypeOf!(mem[i])) == void)
4653 ? i : check!(i + 1, mem);
4656 enum ptrdiff_t x = 1 + check!(0, members[1 .. $]);
4659 alias typex = DerivedFunctionType!(type, FunctionTypeOf!(members[x]));
4660 alias remain = Uniq!(members[1 .. x], members[x + 1 .. $]);
4662 static if (remain.length >= 1 && remain[0].name == name &&
4663 !is(DerivedFunctionType!(typex, remain[0].type) == void))
4665 alias F = DerivedFunctionType!(typex, remain[0].type);
4666 alias Uniq = AliasSeq!(FuncInfo!(name, F), remain[1 .. $]);
4669 alias Uniq = AliasSeq!(FuncInfo!(name, typex), remain);
4673 alias Uniq = AliasSeq!(FuncInfo!(name, type), Uniq!(members[1 .. $]));
4677 alias TargetMembers = Uniq!(Concat!()); // list of FuncInfo
4678 alias SourceMembers = GetOverloadedMethods!Source; // list of function symbols
4680 // Check whether all of SourceMembers satisfy covariance target in TargetMembers
4681 template hasRequireMethods(size_t i = 0)
4683 static if (i >= TargetMembers.length)
4684 enum hasRequireMethods = true;
4687 enum hasRequireMethods =
4688 findCovariantFunction!(TargetMembers[i], Source, SourceMembers) != -1 &&
4689 hasRequireMethods!(i + 1);
4693 // Internal wrapper class
4694 final class Impl : Structural, Targets
4697 Source _wrap_source;
4699 this( inout Source s) inout @safe pure nothrow { _wrap_source = s; }
4700 this(shared inout Source s) shared inout @safe pure nothrow { _wrap_source = s; }
4702 // BUG: making private should work with NVI.
4703 protected final inout(Object) _wrap_getSource() inout @trusted
4705 return dynamicCast!(inout Object)(_wrap_source);
4708 import std.conv : to;
4709 import std.functional : forward;
4710 template generateFun(size_t i)
4712 enum name = TargetMembers[i].name;
4713 enum fa = functionAttributes!(TargetMembers[i].type);
4714 static @property stc()
4717 if (fa & FunctionAttribute.property) r ~= "@property ";
4718 if (fa & FunctionAttribute.ref_) r ~= "ref ";
4719 if (fa & FunctionAttribute.pure_) r ~= "pure ";
4720 if (fa & FunctionAttribute.nothrow_) r ~= "nothrow ";
4721 if (fa & FunctionAttribute.trusted) r ~= "@trusted ";
4722 if (fa & FunctionAttribute.safe) r ~= "@safe ";
4725 static @property mod()
4727 alias type = AliasSeq!(TargetMembers[i].type)[0];
4729 static if (is(type == immutable)) r ~= " immutable";
4732 static if (is(type == shared)) r ~= " shared";
4733 static if (is(type == const)) r ~= " const";
4734 else static if (is(type == inout)) r ~= " inout";
4739 enum n = to!string(i);
4740 static if (fa & FunctionAttribute.property)
4742 static if (Parameters!(TargetMembers[i].type).length == 0)
4743 enum fbody = "_wrap_source."~name;
4745 enum fbody = "_wrap_source."~name~" = forward!args";
4749 enum fbody = "_wrap_source."~name~"(forward!args)";
4752 "override "~stc~"ReturnType!(TargetMembers["~n~"].type) "
4753 ~ name~"(Parameters!(TargetMembers["~n~"].type) args) "~mod~
4754 "{ return "~fbody~"; }";
4759 staticMap!(generateFun, staticIota!(0, TargetMembers.length)));
4764 template wrap(Targets...)
4765 if (Targets.length >= 1 && !allSatisfy!(isMutable, Targets))
4767 import std.meta : staticMap;
4769 alias wrap = .wrap!(staticMap!(Unqual, Targets));
4772 // Internal class to support dynamic cross-casting
4773 private interface Structural
4775 inout(Object) _wrap_getSource() inout @safe pure nothrow;
4779 * Extract object which wrapped by $(D wrap).
4781 template unwrap(Target)
4782 if (isMutable!Target)
4785 auto unwrap(Source)(inout Source src) @trusted pure nothrow
4786 if (is(Target : Source))
4788 alias T = Select!(is(Source == shared), shared Target, Target);
4789 return dynamicCast!(inout T)(src);
4791 // structural downcast
4792 auto unwrap(Source)(inout Source src) @trusted pure nothrow
4793 if (!is(Target : Source))
4795 alias T = Select!(is(Source == shared), shared Target, Target);
4796 Object o = dynamicCast!(Object)(src); // remove qualifier
4799 if (auto a = dynamicCast!(Structural)(o))
4801 if (auto d = dynamicCast!(inout T)(o = a._wrap_getSource()))
4804 else if (auto d = dynamicCast!(inout T)(o))
4813 template unwrap(Target)
4814 if (!isMutable!Target)
4816 alias unwrap = .unwrap!(Unqual!Target);
4825 @property int height();
4829 @property int height();
4833 int quack() { return 1; }
4834 @property int height() { return 10; }
4838 int quack() { return 2; }
4839 @property int height() { return 20; }
4842 Duck d1 = new Duck();
4843 Human h1 = new Human();
4845 interface Refleshable
4849 // does not have structural conformance
4850 static assert(!__traits(compiles, d1.wrap!Refleshable));
4851 static assert(!__traits(compiles, h1.wrap!Refleshable));
4854 Quack qd = d1.wrap!Quack;
4856 assert(qd.quack() == 1); // calls Duck.quack
4858 Duck d2 = qd.unwrap!Duck;
4861 // structural upcast
4862 Quack qh = h1.wrap!Quack;
4863 assert(qh.quack() == 2); // calls Human.quack
4864 // structural downcast
4865 Human h2 = qh.unwrap!Human;
4868 // structural upcast (two steps)
4869 Quack qx = h1.wrap!Quack; // Human -> Quack
4870 Flyer fx = qx.wrap!Flyer; // Quack -> Flyer
4871 assert(fx.height == 20); // calls Human.height
4872 // strucural downcast (two steps)
4873 Quack qy = fx.unwrap!Quack; // Flyer -> Quack
4874 Human hy = qy.unwrap!Human; // Quack -> Human
4876 // strucural downcast (one step)
4877 Human hz = fx.unwrap!Human; // Flyer -> Human
4883 import std.traits : FunctionAttribute, functionAttributes;
4884 interface A { int run(); }
4885 interface B { int stop(); @property int status(); }
4888 int run() { return 1; }
4889 int stop() { return 2; }
4890 @property int status() { return 3; }
4894 auto ab = x.wrap!(A, B);
4897 assert(a.run() == 1);
4898 assert(b.stop() == 2);
4899 assert(b.status == 3);
4900 static assert(functionAttributes!(typeof(ab).status) & FunctionAttribute.property);
4906 int draw() { return 1; }
4907 int draw(int v) { return v; }
4909 int draw() const { return 2; }
4910 int draw() shared { return 3; }
4911 int draw() shared const { return 4; }
4912 int draw() immutable { return 5; }
4919 int draw() shared const;
4920 int draw() immutable;
4928 auto sa = new shared A();
4929 auto ia = new immutable A();
4931 Drawable md = ma.wrap!Drawable;
4932 const Drawable cd = ma.wrap!Drawable;
4933 shared Drawable sd = sa.wrap!Drawable;
4934 shared const Drawable scd = sa.wrap!Drawable;
4935 immutable Drawable id = ia.wrap!Drawable;
4936 assert( md.draw() == 1);
4937 assert( cd.draw() == 2);
4938 assert( sd.draw() == 3);
4939 assert(scd.draw() == 4);
4940 assert( id.draw() == 5);
4943 Drawable2 d = ma.wrap!Drawable2;
4944 static assert(!__traits(compiles, d.draw()));
4945 assert(d.draw(10) == 10);
4951 import std.range, std.algorithm;
4953 interface MyInputRange(T)
4955 @property T front();
4957 @property bool empty();
4960 //auto o = iota(0,10,1).inputRangeObject();
4961 //pragma(msg, __traits(allMembers, typeof(o)));
4962 auto r = iota(0,10,1).inputRangeObject().wrap!(MyInputRange!int)();
4963 assert(equal(r, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]));
4974 int foo() { return 1; }
4975 @disable void opCast(T, this X)(); // !
4978 Interface i = new Pluggable().wrap!Interface;
4979 assert(i.foo() == 1);
4983 // Enhancement 10538
4991 int opDispatch(string name, A...)(A args) { return 100; }
4994 Interface i = wrap!Interface(new Pluggable());
4995 assert(i.foo() == 100);
4996 assert(i.bar(10) == 100);
4999 // Make a tuple of non-static function symbols
5000 package template GetOverloadedMethods(T)
5002 import std.meta : Filter;
5004 alias allMembers = AliasSeq!(__traits(allMembers, T));
5005 template follows(size_t i = 0)
5007 static if (i >= allMembers.length)
5009 alias follows = AliasSeq!();
5011 else static if (!__traits(compiles, mixin("T."~allMembers[i])))
5013 alias follows = follows!(i + 1);
5017 enum name = allMembers[i];
5019 template isMethod(alias f)
5021 static if (is(typeof(&f) F == F*) && is(F == function))
5022 enum isMethod = !__traits(isStaticFunction, f);
5024 enum isMethod = false;
5026 alias follows = AliasSeq!(
5027 std.meta.Filter!(isMethod, __traits(getOverloads, T, name)),
5031 alias GetOverloadedMethods = follows!();
5033 // find a function from Fs that has same identifier and covariant type with f
5034 private template findCovariantFunction(alias finfo, Source, Fs...)
5036 template check(size_t i = 0)
5038 static if (i >= Fs.length)
5039 enum ptrdiff_t check = -1;
5042 enum ptrdiff_t check =
5043 (finfo.name == __traits(identifier, Fs[i])) &&
5044 isCovariantWith!(FunctionTypeOf!(Fs[i]), finfo.type)
5045 ? i : check!(i + 1);
5049 static if (x == -1 && is(typeof(Source.opDispatch)))
5051 alias Params = Parameters!(finfo.type);
5052 enum ptrdiff_t findCovariantFunction =
5053 is(typeof(( Source).init.opDispatch!(finfo.name)(Params.init))) ||
5054 is(typeof(( const Source).init.opDispatch!(finfo.name)(Params.init))) ||
5055 is(typeof(( immutable Source).init.opDispatch!(finfo.name)(Params.init))) ||
5056 is(typeof(( shared Source).init.opDispatch!(finfo.name)(Params.init))) ||
5057 is(typeof((shared const Source).init.opDispatch!(finfo.name)(Params.init)))
5058 ? ptrdiff_t.max : -1;
5061 enum ptrdiff_t findCovariantFunction = x;
5064 private enum TypeModifier
5066 mutable = 0, // type is mutable
5067 const_ = 1, // type is const
5068 immutable_ = 2, // type is immutable
5069 shared_ = 4, // type is shared
5070 inout_ = 8, // type is wild
5072 private template TypeMod(T)
5074 static if (is(T == immutable))
5076 enum mod1 = TypeModifier.immutable_;
5081 enum mod1 = is(T == shared) ? TypeModifier.shared_ : 0;
5082 static if (is(T == const))
5083 enum mod2 = TypeModifier.const_;
5084 else static if (is(T == inout))
5085 enum mod2 = TypeModifier.inout_;
5087 enum mod2 = TypeModifier.mutable;
5089 enum TypeMod = cast(TypeModifier)(mod1 | mod2);
5094 private template UnittestFuncInfo(alias f)
5096 enum name = __traits(identifier, f);
5097 alias type = FunctionTypeOf!f;
5104 int draw() { return 1; }
5105 @property int value() { return 2; }
5106 final int run() { return 3; }
5108 alias methods = GetOverloadedMethods!A;
5111 alias @property int F2();
5113 alias nothrow @trusted uint F4();
5114 alias int F5(Object);
5115 alias bool F6(Object);
5116 static assert(methods.length == 3 + 4);
5117 static assert(__traits(identifier, methods[0]) == "draw" && is(typeof(&methods[0]) == F1*));
5118 static assert(__traits(identifier, methods[1]) == "value" && is(typeof(&methods[1]) == F2*));
5119 static assert(__traits(identifier, methods[2]) == "run" && is(typeof(&methods[2]) == F1*));
5122 @property int value();
5125 static assert(findCovariantFunction!(UnittestFuncInfo!draw, A, methods) == 0);
5126 static assert(findCovariantFunction!(UnittestFuncInfo!value, A, methods) == 1);
5127 static assert(findCovariantFunction!(UnittestFuncInfo!opEquals, A, methods) == -1);
5128 static assert(findCovariantFunction!(UnittestFuncInfo!nomatch, A, methods) == -1);
5130 // considering opDispatch
5133 void opDispatch(string name, A...)(A) {}
5135 alias methodsB = GetOverloadedMethods!B;
5136 static assert(findCovariantFunction!(UnittestFuncInfo!draw, B, methodsB) == ptrdiff_t.max);
5137 static assert(findCovariantFunction!(UnittestFuncInfo!value, B, methodsB) == ptrdiff_t.max);
5138 static assert(findCovariantFunction!(UnittestFuncInfo!opEquals, B, methodsB) == ptrdiff_t.max);
5139 static assert(findCovariantFunction!(UnittestFuncInfo!nomatch, B, methodsB) == ptrdiff_t.max);
5142 package template DerivedFunctionType(T...)
5144 static if (!T.length)
5146 alias DerivedFunctionType = void;
5148 else static if (T.length == 1)
5150 static if (is(T[0] == function))
5152 alias DerivedFunctionType = T[0];
5156 alias DerivedFunctionType = void;
5159 else static if (is(T[0] P0 == function) && is(T[1] P1 == function))
5161 alias FA = FunctionAttribute;
5163 alias F0 = T[0], R0 = ReturnType!F0, PSTC0 = ParameterStorageClassTuple!F0;
5164 alias F1 = T[1], R1 = ReturnType!F1, PSTC1 = ParameterStorageClassTuple!F1;
5165 enum FA0 = functionAttributes!F0;
5166 enum FA1 = functionAttributes!F1;
5168 template CheckParams(size_t i = 0)
5170 static if (i >= P0.length)
5171 enum CheckParams = true;
5174 enum CheckParams = (is(P0[i] == P1[i]) && PSTC0[i] == PSTC1[i]) &&
5175 CheckParams!(i + 1);
5178 static if (R0.sizeof == R1.sizeof && !is(CommonType!(R0, R1) == void) &&
5179 P0.length == P1.length && CheckParams!() && TypeMod!F0 == TypeMod!F1 &&
5180 variadicFunctionStyle!F0 == variadicFunctionStyle!F1 &&
5181 functionLinkage!F0 == functionLinkage!F1 &&
5182 ((FA0 ^ FA1) & (FA.ref_ | FA.property)) == 0)
5184 alias R = Select!(is(R0 : R1), R0, R1);
5185 alias FX = FunctionTypeOf!(R function(P0));
5186 // @system is default
5187 alias FY = SetFunctionAttributes!(FX, functionLinkage!F0, (FA0 | FA1) & ~FA.system);
5188 alias DerivedFunctionType = DerivedFunctionType!(FY, T[2 .. $]);
5191 alias DerivedFunctionType = void;
5194 alias DerivedFunctionType = void;
5198 // attribute covariance
5200 static assert(is(DerivedFunctionType!(F1, F1) == F1));
5201 alias int F2() pure nothrow;
5202 static assert(is(DerivedFunctionType!(F1, F2) == F2));
5203 alias int F3() @safe;
5204 alias int F23() @safe pure nothrow;
5205 static assert(is(DerivedFunctionType!(F2, F3) == F23));
5207 // return type covariance
5209 static assert(is(DerivedFunctionType!(F1, F4) == void));
5214 static assert(is(DerivedFunctionType!(F5, F6) == F6));
5215 alias typeof(null) F7();
5218 static assert(is(DerivedFunctionType!(F5, F7) == F7));
5219 static assert(is(DerivedFunctionType!(F7, F8) == void));
5220 static assert(is(DerivedFunctionType!(F7, F9) == F7));
5222 // variadic type equality
5224 alias int F11(int...);
5225 alias int F12(int, ...);
5226 static assert(is(DerivedFunctionType!(F10, F11) == void));
5227 static assert(is(DerivedFunctionType!(F10, F12) == void));
5228 static assert(is(DerivedFunctionType!(F11, F12) == void));
5231 alias extern(C) int F13(int);
5232 alias extern(D) int F14(int);
5233 alias extern(Windows) int F15(int);
5234 static assert(is(DerivedFunctionType!(F13, F14) == void));
5235 static assert(is(DerivedFunctionType!(F13, F15) == void));
5236 static assert(is(DerivedFunctionType!(F14, F15) == void));
5238 // ref & @property equality
5240 alias ref int F17(int);
5241 alias @property int F18(int);
5242 static assert(is(DerivedFunctionType!(F16, F17) == void));
5243 static assert(is(DerivedFunctionType!(F16, F18) == void));
5244 static assert(is(DerivedFunctionType!(F17, F18) == void));
5247 package template staticIota(int beg, int end)
5249 static if (beg + 1 >= end)
5251 static if (beg >= end)
5253 alias staticIota = AliasSeq!();
5257 alias staticIota = AliasSeq!(+beg);
5262 enum mid = beg + (end - beg) / 2;
5263 alias staticIota = AliasSeq!(staticIota!(beg, mid), staticIota!(mid, end));
5267 package template mixinAll(mixins...)
5269 static if (mixins.length == 1)
5271 static if (is(typeof(mixins[0]) == string))
5277 alias it = mixins[0];
5281 else static if (mixins.length >= 2)
5283 mixin mixinAll!(mixins[ 0 .. $/2]);
5284 mixin mixinAll!(mixins[$/2 .. $ ]);
5288 package template Bind(alias Template, args1...)
5290 alias Bind(args2...) = Template!(args1, args2);
5295 Options regarding auto-initialization of a $(D RefCounted) object (see
5296 the definition of $(D RefCounted) below).
5298 enum RefCountedAutoInitialize
5300 /// Do not auto-initialize the object
5302 /// Auto-initialize the object
5307 Defines a reference-counted object containing a $(D T) value as
5310 An instance of $(D RefCounted) is a reference to a structure,
5311 which is referred to as the $(I store), or $(I storage implementation
5312 struct) in this documentation. The store contains a reference count
5313 and the $(D T) payload. $(D RefCounted) uses $(D malloc) to allocate
5314 the store. As instances of $(D RefCounted) are copied or go out of
5315 scope, they will automatically increment or decrement the reference
5316 count. When the reference count goes down to zero, $(D RefCounted)
5317 will call $(D destroy) against the payload and call $(D free) to
5318 deallocate the store. If the $(D T) payload contains any references
5319 to GC-allocated memory, then `RefCounted` will add it to the GC memory
5320 that is scanned for pointers, and remove it from GC scanning before
5321 $(D free) is called on the store.
5323 One important consequence of $(D destroy) is that it will call the
5324 destructor of the $(D T) payload. GC-managed references are not
5325 guaranteed to be valid during a destructor call, but other members of
5326 $(D T), such as file handles or pointers to $(D malloc) memory, will
5327 still be valid during the destructor call. This allows the $(D T) to
5328 deallocate or clean up any non-GC resources immediately after the
5329 reference count has reached zero.
5331 $(D RefCounted) is unsafe and should be used with care. No references
5332 to the payload should be escaped outside the $(D RefCounted) object.
5334 The $(D autoInit) option makes the object ensure the store is
5335 automatically initialized. Leaving $(D autoInit ==
5336 RefCountedAutoInitialize.yes) (the default option) is convenient but
5337 has the cost of a test whenever the payload is accessed. If $(D
5338 autoInit == RefCountedAutoInitialize.no), user code must call either
5339 $(D refCountedStore.isInitialized) or $(D refCountedStore.ensureInitialized)
5340 before attempting to access the payload. Not doing so results in null
5341 pointer dereference.
5343 struct RefCounted(T, RefCountedAutoInitialize autoInit =
5344 RefCountedAutoInitialize.yes)
5345 if (!is(T == class) && !(is(T == interface)))
5347 extern(C) private pure nothrow @nogc static // TODO remove pure when https://issues.dlang.org/show_bug.cgi?id=15862 has been fixed
5349 pragma(mangle, "free") void pureFree( void *ptr );
5350 pragma(mangle, "gc_addRange") void pureGcAddRange( in void* p, size_t sz, const TypeInfo ti = null );
5351 pragma(mangle, "gc_removeRange") void pureGcRemoveRange( in void* p );
5354 /// $(D RefCounted) storage implementation.
5355 struct RefCountedStore
5357 import core.memory : pureMalloc;
5364 private Impl* _store;
5366 private void initialize(A...)(auto ref A args)
5368 import core.exception : onOutOfMemoryError;
5369 import std.conv : emplace;
5371 _store = cast(Impl*) pureMalloc(Impl.sizeof);
5373 onOutOfMemoryError();
5374 static if (hasIndirections!T)
5375 pureGcAddRange(&_store._payload, T.sizeof);
5376 emplace(&_store._payload, args);
5380 private void move(ref T source)
5382 import core.exception : onOutOfMemoryError;
5383 import core.stdc.string : memcpy, memset;
5385 _store = cast(Impl*) pureMalloc(Impl.sizeof);
5387 onOutOfMemoryError();
5388 static if (hasIndirections!T)
5389 pureGcAddRange(&_store._payload, T.sizeof);
5391 // Can't use std.algorithm.move(source, _store._payload)
5392 // here because it requires the target to be initialized.
5393 // Might be worth to add this as `moveEmplace`
5395 // Can avoid destructing result.
5396 static if (hasElaborateAssign!T || !isAssignable!T)
5397 memcpy(&_store._payload, &source, T.sizeof);
5399 _store._payload = source;
5401 // If the source defines a destructor or a postblit hook, we must obliterate the
5402 // object in order to avoid double freeing and undue aliasing
5403 static if (hasElaborateDestructor!T || hasElaborateCopyConstructor!T)
5405 // If T is nested struct, keep original context pointer
5406 static if (__traits(isNested, T))
5407 enum sz = T.sizeof - (void*).sizeof;
5411 auto init = typeid(T).initializer();
5412 if (init.ptr is null) // null ptr means initialize to 0s
5413 memset(&source, 0, sz);
5415 memcpy(&source, init.ptr, sz);
5422 Returns $(D true) if and only if the underlying store has been
5423 allocated and initialized.
5425 @property nothrow @safe pure @nogc
5426 bool isInitialized() const
5428 return _store !is null;
5432 Returns underlying reference count if it is allocated and initialized
5433 (a positive integer), and $(D 0) otherwise.
5435 @property nothrow @safe pure @nogc
5436 size_t refCount() const
5438 return isInitialized ? _store._count : 0;
5442 Makes sure the payload was properly initialized. Such a
5443 call is typically inserted before using the payload.
5445 void ensureInitialized()
5447 if (!isInitialized) initialize();
5451 RefCountedStore _refCounted;
5453 /// Returns storage implementation struct.
5454 @property nothrow @safe
5455 ref inout(RefCountedStore) refCountedStore() inout
5461 Constructor that initializes the payload.
5463 Postcondition: $(D refCountedStore.isInitialized)
5465 this(A...)(auto ref A args) if (A.length > 0)
5467 _refCounted.initialize(args);
5473 _refCounted.move(val);
5477 Constructor that tracks the reference count appropriately. If $(D
5478 !refCountedStore.isInitialized), does nothing.
5480 this(this) @safe pure nothrow @nogc
5482 if (!_refCounted.isInitialized) return;
5483 ++_refCounted._store._count;
5487 Destructor that tracks the reference count appropriately. If $(D
5488 !refCountedStore.isInitialized), does nothing. When the reference count goes
5489 down to zero, calls $(D destroy) agaist the payload and calls $(D free)
5490 to deallocate the corresponding resource.
5494 if (!_refCounted.isInitialized) return;
5495 assert(_refCounted._store._count > 0);
5496 if (--_refCounted._store._count)
5499 .destroy(_refCounted._store._payload);
5500 static if (hasIndirections!T)
5502 pureGcRemoveRange(&_refCounted._store._payload);
5505 pureFree(_refCounted._store);
5506 _refCounted._store = null;
5510 Assignment operators
5512 void opAssign(typeof(this) rhs)
5514 import std.algorithm.mutation : swap;
5516 swap(_refCounted._store, rhs._refCounted._store);
5520 void opAssign(T rhs)
5522 import std.algorithm.mutation : move;
5524 static if (autoInit == RefCountedAutoInitialize.yes)
5526 _refCounted.ensureInitialized();
5530 assert(_refCounted.isInitialized);
5532 move(rhs, _refCounted._store._payload);
5535 //version to have a single properly ddoc'ed function (w/ correct sig)
5539 Returns a reference to the payload. If (autoInit ==
5540 RefCountedAutoInitialize.yes), calls $(D
5541 refCountedStore.ensureInitialized). Otherwise, just issues $(D
5542 assert(refCountedStore.isInitialized)). Used with $(D alias
5543 refCountedPayload this;), so callers can just use the $(D RefCounted)
5546 $(BLUE The first overload exists only if $(D autoInit == RefCountedAutoInitialize.yes).)
5547 So if $(D autoInit == RefCountedAutoInitialize.no)
5548 or called for a constant or immutable object, then
5549 $(D refCountedPayload) will also be qualified as safe and nothrow
5550 (but will still assert if not initialized).
5553 ref T refCountedPayload() return;
5556 @property nothrow @safe pure @nogc
5557 ref inout(T) refCountedPayload() inout return;
5561 static if (autoInit == RefCountedAutoInitialize.yes)
5563 //Can't use inout here because of potential mutation
5565 ref T refCountedPayload() return
5567 _refCounted.ensureInitialized();
5568 return _refCounted._store._payload;
5572 @property nothrow @safe pure @nogc
5573 ref inout(T) refCountedPayload() inout return
5575 assert(_refCounted.isInitialized, "Attempted to access an uninitialized payload.");
5576 return _refCounted._store._payload;
5581 Returns a reference to the payload. If (autoInit ==
5582 RefCountedAutoInitialize.yes), calls $(D
5583 refCountedStore.ensureInitialized). Otherwise, just issues $(D
5584 assert(refCountedStore.isInitialized)).
5586 alias refCountedPayload this;
5590 pure @system nothrow @nogc unittest
5592 // A pair of an `int` and a `size_t` - the latter being the
5593 // reference count - will be dynamically allocated
5594 auto rc1 = RefCounted!int(5);
5596 // No more allocation, add just one extra reference count
5598 // Reference semantics
5601 // the pair will be freed when rc1 and rc2 go out of scope
5604 pure @system unittest
5608 auto rc1 = RefCounted!int(5);
5611 assert(rc1._refCounted._store._count == 1);
5613 assert(rc1._refCounted._store._count == 2);
5614 // Reference semantics
5618 assert(rc2._refCounted._store._count == 2);
5620 assert(rc1._refCounted._store._count == 2);
5622 assert(p._refCounted._store == null);
5624 // RefCounted as a member
5630 x._refCounted.initialize(y);
5634 auto another = this;
5640 assert(a.x._refCounted._store._count == 2, "BUG 4356 still unfixed");
5643 pure @system nothrow @nogc unittest
5645 import std.algorithm.mutation : swap;
5647 RefCounted!int p1, p2;
5652 @safe pure nothrow @nogc unittest
5663 alias SRC = RefCounted!S;
5667 @system pure unittest
5669 struct S { this(ref int val) { assert(val == 3); ++val; } }
5672 auto s = RefCounted!S(val);
5676 // gc_addRange coverage
5677 @system pure unittest
5679 struct S { int* p; }
5681 auto s = RefCounted!S(null);
5684 @system pure nothrow @nogc unittest
5687 a = 5; //This should not assert
5691 b = a; //This should not assert either
5694 RefCounted!(int*) c;
5698 * Initializes a `RefCounted` with `val`. The template parameter
5699 * `T` of `RefCounted` is inferred from `val`.
5700 * This function can be used to move non-copyable values to the heap.
5701 * It also disables the `autoInit` option of `RefCounted`.
5704 * val = The value to be reference counted
5706 * An initialized $(D RefCounted) containing $(D val).
5708 * $(HTTP en.cppreference.com/w/cpp/memory/shared_ptr/make_shared, C++'s make_shared)
5710 RefCounted!(T, RefCountedAutoInitialize.no) refCounted(T)(T val)
5713 res._refCounted.move(val);
5723 @disable this(this); // not copyable
5724 ~this() { name = null; }
5727 auto file = File("name");
5728 assert(file.name == "name");
5729 // file cannot be copied and has unique ownership
5730 static assert(!__traits(compiles, {auto file2 = file;}));
5732 // make the file refcounted to share ownership
5733 import std.algorithm.mutation : move;
5734 auto rcFile = refCounted(move(file));
5735 assert(rcFile.name == "name");
5736 assert(file.name == null);
5737 auto rcFile2 = rcFile;
5738 assert(rcFile.refCountedStore.refCount == 2);
5739 // file gets properly closed when last reference is dropped
5743 Creates a proxy for the value `a` that will forward all operations
5744 while disabling implicit conversions. The aliased item `a` must be
5745 an $(B lvalue). This is useful for creating a new type from the
5746 "base" type (though this is $(B not) a subtype-supertype
5747 relationship; the new type is not related to the old type in any way,
5750 The new type supports all operations that the underlying type does,
5751 including all operators such as `+`, `--`, `<`, `[]`, etc.
5754 a = The value to act as a proxy for all operations. It must
5757 mixin template Proxy(alias a)
5759 private alias ValueType = typeof({ return a; }());
5761 /* Determine if 'T.a' can referenced via a const(T).
5762 * Use T* as the parameter because 'scope' inference needs a fully
5763 * analyzed T, which doesn't work when accessibleFrom() is used in a
5764 * 'static if' in the definition of Proxy or T.
5766 private enum bool accessibleFrom(T) =
5767 is(typeof((T* self){ cast(void) mixin("(*self)."~__traits(identifier, a)); }));
5769 static if (is(typeof(this) == class))
5771 override bool opEquals(Object o)
5773 if (auto b = cast(typeof(this))o)
5775 return a == mixin("b."~__traits(identifier, a));
5780 bool opEquals(T)(T b)
5781 if (is(ValueType : T) || is(typeof(a.opEquals(b))) || is(typeof(b.opEquals(a))))
5783 static if (is(typeof(a.opEquals(b))))
5784 return a.opEquals(b);
5785 else static if (is(typeof(b.opEquals(a))))
5786 return b.opEquals(a);
5791 override int opCmp(Object o)
5793 if (auto b = cast(typeof(this))o)
5795 return a < mixin("b."~__traits(identifier, a)) ? -1
5796 : a > mixin("b."~__traits(identifier, a)) ? +1 : 0;
5798 static if (is(ValueType == class))
5801 throw new Exception("Attempt to compare a "~typeid(this).toString~" and a "~typeid(o).toString);
5804 int opCmp(T)(auto ref const T b)
5805 if (is(ValueType : T) || is(typeof(a.opCmp(b))) || is(typeof(b.opCmp(a))))
5807 static if (is(typeof(a.opCmp(b))))
5809 else static if (is(typeof(b.opCmp(a))))
5812 return a < b ? -1 : a > b ? +1 : 0;
5815 static if (accessibleFrom!(const typeof(this)))
5817 override hash_t toHash() const nothrow @trusted
5819 static if (is(typeof(&a) == ValueType*))
5822 auto v = a; // if a is (property) function
5823 return typeid(ValueType).getHash(cast(const void*)&v);
5829 auto ref opEquals(this X, B)(auto ref B b)
5831 static if (is(immutable B == immutable typeof(this)))
5833 return a == mixin("b."~__traits(identifier, a));
5839 auto ref opCmp(this X, B)(auto ref B b)
5840 if (!is(typeof(a.opCmp(b))) || !is(typeof(b.opCmp(a))))
5842 static if (is(typeof(a.opCmp(b))))
5844 else static if (is(typeof(b.opCmp(a))))
5846 else static if (isFloatingPoint!ValueType || isFloatingPoint!B)
5847 return a < b ? -1 : a > b ? +1 : a == b ? 0 : float.nan;
5849 return a < b ? -1 : (a > b);
5852 static if (accessibleFrom!(const typeof(this)))
5854 hash_t toHash() const nothrow @trusted
5856 static if (is(typeof(&a) == ValueType*))
5859 auto v = a; // if a is (property) function
5860 return typeid(ValueType).getHash(cast(const void*)&v);
5865 auto ref opCall(this X, Args...)(auto ref Args args) { return a(args); }
5867 auto ref opCast(T, this X)() { return cast(T) a; }
5869 auto ref opIndex(this X, D...)(auto ref D i) { return a[i]; }
5870 auto ref opSlice(this X )() { return a[]; }
5871 auto ref opSlice(this X, B, E)(auto ref B b, auto ref E e) { return a[b .. e]; }
5873 auto ref opUnary (string op, this X )() { return mixin(op~"a"); }
5874 auto ref opIndexUnary(string op, this X, D...)(auto ref D i) { return mixin(op~"a[i]"); }
5875 auto ref opSliceUnary(string op, this X )() { return mixin(op~"a[]"); }
5876 auto ref opSliceUnary(string op, this X, B, E)(auto ref B b, auto ref E e) { return mixin(op~"a[b .. e]"); }
5878 auto ref opBinary(string op, this X, B)(auto ref B b)
5879 if (op == "in" && is(typeof(a in b)) || op != "in")
5881 return mixin("a "~op~" b");
5883 auto ref opBinaryRight(string op, this X, B)(auto ref B b) { return mixin("b "~op~" a"); }
5885 static if (!is(typeof(this) == class))
5888 static if (isAssignable!ValueType)
5890 auto ref opAssign(this X)(auto ref typeof(this) v)
5892 a = mixin("v."~__traits(identifier, a));
5898 @disable void opAssign(this X)(auto ref typeof(this) v);
5902 auto ref opAssign (this X, V )(auto ref V v) if (!is(V == typeof(this))) { return a = v; }
5903 auto ref opIndexAssign(this X, V, D...)(auto ref V v, auto ref D i) { return a[i] = v; }
5904 auto ref opSliceAssign(this X, V )(auto ref V v) { return a[] = v; }
5905 auto ref opSliceAssign(this X, V, B, E)(auto ref V v, auto ref B b, auto ref E e) { return a[b .. e] = v; }
5907 auto ref opOpAssign (string op, this X, V )(auto ref V v)
5909 return mixin("a " ~op~"= v");
5911 auto ref opIndexOpAssign(string op, this X, V, D...)(auto ref V v, auto ref D i)
5913 return mixin("a[i] " ~op~"= v");
5915 auto ref opSliceOpAssign(string op, this X, V )(auto ref V v)
5917 return mixin("a[] " ~op~"= v");
5919 auto ref opSliceOpAssign(string op, this X, V, B, E)(auto ref V v, auto ref B b, auto ref E e)
5921 return mixin("a[b .. e] "~op~"= v");
5924 template opDispatch(string name)
5926 static if (is(typeof(__traits(getMember, a, name)) == function))
5928 // non template function
5929 auto ref opDispatch(this X, Args...)(auto ref Args args) { return mixin("a."~name~"(args)"); }
5931 else static if (is(typeof({ enum x = mixin("a."~name); })))
5933 // built-in type field, manifest constant, and static non-mutable field
5934 enum opDispatch = mixin("a."~name);
5936 else static if (is(typeof(mixin("a."~name))) || __traits(getOverloads, a, name).length != 0)
5938 // field or property function
5939 @property auto ref opDispatch(this X)() { return mixin("a."~name); }
5940 @property auto ref opDispatch(this X, V)(auto ref V v) { return mixin("a."~name~" = v"); }
5945 template opDispatch(T...)
5947 enum targs = T.length ? "!T" : "";
5948 auto ref opDispatch(this X, Args...)(auto ref Args args){ return mixin("a."~name~targs~"(args)"); }
5953 import std.traits : isArray;
5955 static if (isArray!ValueType)
5957 auto opDollar() const { return a.length; }
5959 else static if (is(typeof(a.opDollar!0)))
5961 auto ref opDollar(size_t pos)() { return a.opDollar!pos(); }
5963 else static if (is(typeof(a.opDollar) == function))
5965 auto ref opDollar() { return a.opDollar(); }
5967 else static if (is(typeof(a.opDollar)))
5969 alias opDollar = a.opDollar;
5981 this(int n){ value = n; }
5986 // Enable operations that original type has.
5989 assert(n * 2 == 22);
5991 void func(int n) { }
5993 // Disable implicit conversions to original type.
5998 ///The proxied value must be an $(B lvalue).
6003 //Won't work; the literal '1'
6004 //is an rvalue, not an lvalue
6007 //Okay, n is an lvalue
6011 this(int n) { this.n = n; }
6019 struct NewObjectType
6022 //Ok, obj is an lvalue
6025 this (Object o) { obj = o; }
6028 NewObjectType not = new Object();
6029 assert(__traits(compiles, not.toHash()));
6033 There is one exception to the fact that the new type is not related to the
6034 old type. $(DDSUBLINK spec/function,pseudo-member, Pseudo-member)
6035 functions are usable with the new type; they will be forwarded on to the
6043 assert(!f.isInfinity);
6050 this(float f) { _ = f; }
6054 assert(!nf.isInfinity);
6063 this(int n) inout { value = n; }
6066 static immutable arr = [1,2,3];
6069 foreach (T; AliasSeq!(MyInt, const MyInt, immutable MyInt))
6072 static assert(!__traits(compiles, { int x = m; }));
6073 static assert(!__traits(compiles, { void func(int n){} func(m); }));
6079 assert(cast(double) m == 10.0);
6080 assert(m + 10 == 20);
6082 assert(m * 20 == 200);
6084 assert(10 + m == 20);
6085 assert(15 - m == 5);
6086 assert(20 * m == 200);
6087 assert(50 / m == 5);
6088 static if (is(T == MyInt)) // mutable
6091 assert(m++ == 11); assert(m == 12);
6093 assert(m-- == 11); assert(m == 10);
6095 m = 20; assert(m == 20);
6097 static assert(T.max == int.max);
6098 static assert(T.min == int.min);
6099 static assert(T.init == int.init);
6100 static assert(T.str == "str");
6101 static assert(T.arr == [1,2,3]);
6106 static struct MyArray
6108 private int[] value;
6110 this(int[] arr) { value = arr; }
6111 this(immutable int[] arr) immutable { value = arr; }
6114 foreach (T; AliasSeq!(MyArray, const MyArray, immutable MyArray))
6116 static if (is(T == immutable) && !is(typeof({ T a = [1,2,3,4]; })))
6117 T a = [1,2,3,4].idup; // workaround until qualified ctor is properly supported
6120 assert(a == [1,2,3,4]);
6121 assert(a != [5,6,7,8]);
6123 version (LittleEndian)
6124 assert(cast(ulong[]) a == [0x0000_0002_0000_0001, 0x0000_0004_0000_0003]);
6126 assert(cast(ulong[]) a == [0x0000_0001_0000_0002, 0x0000_0003_0000_0004]);
6127 assert(a ~ [10,11] == [1,2,3,4,10,11]);
6129 assert(a[] == [1,2,3,4]);
6130 assert(a[2 .. 4] == [3,4]);
6131 static if (is(T == MyArray)) // mutable
6134 a = [5,6,7,8]; assert(a == [5,6,7,8]);
6135 a[0] = 0; assert(a == [0,6,7,8]);
6136 a[] = 1; assert(a == [1,1,1,1]);
6137 a[0 .. 3] = 2; assert(a == [2,2,2,1]);
6138 a[0] += 2; assert(a == [4,2,2,1]);
6139 a[] *= 2; assert(a == [8,4,4,2]);
6140 a[0 .. 2] /= 2; assert(a == [4,2,4,2]);
6150 @property int val1() const { return field; }
6151 @property void val1(int n) { field = n; }
6153 @property ref int val2() { return field; }
6155 int func(int x, int y) const { return x; }
6156 void func1(ref int a) { a = 9; }
6158 T ifti1(T)(T t) { return t; }
6159 void ifti2(Args...)(Args args) { }
6160 void ifti3(T, Args...)(Args args) { }
6162 T opCast(T)(){ return T.init; }
6164 T tempfunc(T)() { return T.init; }
6170 this(Foo f) { foo = f; }
6173 auto h = new Hoge(new Foo());
6176 static assert(!__traits(compiles, { Foo f = h; }));
6179 h.field = 1; // lhs of assign
6180 n = h.field; // rhs of assign
6181 assert(h.field == 1); // lhs of BinExp
6182 assert(1 == h.field); // rhs of BinExp
6185 // getter/setter property function
6188 assert(h.val1 == 4);
6189 assert(4 == h.val1);
6192 // ref getter property function
6195 assert(h.val2 == 8);
6196 assert(8 == h.val2);
6200 assert(h.func(2,4) == 2);
6205 assert(h.ifti1(4) == 4);
6210 assert(h.opCast!int() == 0);
6211 assert(cast(int) h == 0);
6212 const ih = new const Hoge(new Foo());
6213 static assert(!__traits(compiles, ih.opCast!int()));
6214 static assert(!__traits(compiles, cast(int) ih));
6216 // template member function
6217 assert(h.tempfunc!int() == 0);
6220 @system unittest // about Proxy inside a class
6225 mixin Proxy!payload;
6226 this(int i){ payload = i; }
6227 string opCall(string msg){ return msg; }
6228 int pow(int i){ return payload ^^ i; }
6234 mixin Proxy!payload;
6235 this(int i){ payload = new MyClass(i); }
6241 mixin Proxy!payload;
6242 this(int i){ payload = i; }
6246 Object a = new MyClass(5);
6247 Object b = new MyClass(5);
6248 Object c = new MyClass2(5);
6249 Object d = new MyClass3(5);
6251 assert((cast(MyClass) a) == 5);
6252 assert(5 == (cast(MyClass) b));
6253 assert(5 == cast(MyClass2) c);
6257 // oops! above line is unexpected, isn't it?
6258 // the reason is below.
6259 // MyClass2.opEquals knows MyClass but,
6260 // MyClass.opEquals doesn't know MyClass2.
6261 // so, c.opEquals(a) is true, but a.opEquals(c) is false.
6262 // furthermore, opEquals(T) couldn't be invoked.
6263 assert((cast(MyClass2) c) != (cast(MyClass) a));
6266 Object e = new MyClass2(7);
6267 assert(a < cast(MyClass2) e); // OK. and
6268 assert(e > a); // OK, but...
6269 // assert(a < e); // RUNTIME ERROR!
6270 // assert((cast(MyClass) a) < e); // RUNTIME ERROR!
6271 assert(3 < cast(MyClass) a);
6272 assert((cast(MyClass2) e) < 11);
6275 assert((cast(MyClass2) e)("hello") == "hello");
6278 assert((cast(MyClass)(cast(MyClass2) c)) == a);
6279 assert((cast(int)(cast(MyClass2) c)) == 5);
6285 mixin Proxy!payload;
6286 this(string s){ payload = s; }
6291 mixin Proxy!payload;
6292 this(string s){ payload = new MyClass4(s); }
6294 auto f = new MyClass4("hello");
6295 assert(f[1] == 'e');
6296 auto g = new MyClass5("hello");
6297 assert(f[1] == 'e');
6300 assert(f[2 .. 4] == "ll");
6303 assert(-(cast(MyClass2) c) == -5);
6306 assert((cast(MyClass) a) + (cast(MyClass2) c) == 10);
6307 assert(5 + cast(MyClass) a == 10);
6310 (cast(MyClass2) c) = 11;
6311 assert((cast(MyClass2) c) == 11);
6312 (cast(MyClass2) c) = new MyClass(13);
6313 assert((cast(MyClass2) c) == 13);
6316 assert((cast(MyClass2) c) += 4);
6317 assert((cast(MyClass2) c) == 17);
6320 assert((cast(MyClass2) c).pow(2) == 289);
6323 assert(f[2..$-1] == "ll");
6329 assert(hash[b] == 19);
6330 assert(hash[c] == 21);
6339 mixin Proxy!payload;
6347 @disable void opAssign(typeof(this));
6353 mixin Proxy!payload;
6356 static assert(!__traits(compiles, f = f));
6362 mixin Proxy!payload;
6364 // override default Proxy behavior
6365 void opAssign(typeof(this) rhs){}
6377 this(string s) { val = s; }
6381 names[Name("a")] = true;
6382 bool* b = Name("a") in names;
6387 // bug14213, using function for the payload
6390 int foo() { return 12; }
6395 int foo() { return 12; }
6399 assert(s + 1 == 13);
6401 assert(s * 2 == 24);
6404 // Check all floating point comparisons for both Proxy and Typedef,
6405 // also against int and a Typedef!int, to be as regression-proof
6406 // as possible. bug 15561
6409 static struct MyFloatImpl
6414 static void allFail(T0, T1)(T0 a, T1 b)
6422 foreach (T1; AliasSeq!(MyFloatImpl, Typedef!float, Typedef!double,
6423 float, real, Typedef!int, int))
6425 foreach (T2; AliasSeq!(MyFloatImpl, Typedef!float))
6430 static if (isFloatingPoint!T1 || isFloatingPoint!(TypedefType!T1))
6453 $(B Typedef) allows the creation of a unique type which is
6454 based on an existing type. Unlike the $(D alias) feature,
6455 $(B Typedef) ensures the two types are not considered as equals.
6459 alias MyInt = Typedef!int;
6460 static void takeInt(int) { }
6461 static void takeMyInt(MyInt) { }
6465 takeMyInt(i); // fails
6468 takeInt(myInt); // fails
6469 takeMyInt(myInt); // ok
6474 init = Optional initial value for the new type. For example:
6477 alias MyInt = Typedef!(int, 10);
6479 assert(myInt == 10); // default-initialized to 10
6482 cookie = Optional, used to create multiple unique types which are
6483 based on the same origin type $(D T). For example:
6486 alias TypeInt1 = Typedef!int;
6487 alias TypeInt2 = Typedef!int;
6489 // The two Typedefs are the same type.
6490 static assert(is(TypeInt1 == TypeInt2));
6492 alias MoneyEuros = Typedef!(float, float.init, "euros");
6493 alias MoneyDollars = Typedef!(float, float.init, "dollars");
6495 // The two Typedefs are _not_ the same type.
6496 static assert(!is(MoneyEuros == MoneyDollars));
6499 Note: If a library routine cannot handle the Typedef type,
6500 you can use the $(D TypedefType) template to extract the
6501 type which the Typedef wraps.
6503 struct Typedef(T, T init = T.init, string cookie=null)
6505 private T Typedef_payload = init;
6509 Typedef_payload = init;
6514 this(tdef.Typedef_payload);
6517 // We need to add special overload for cast(Typedef!X) exp,
6518 // thus we can't simply inherit Proxy!Typedef_payload
6519 T2 opCast(T2 : Typedef!(T, Unused), this X, T, Unused...)()
6521 return T2(cast(T) Typedef_payload);
6524 auto ref opCast(T2, this X)()
6526 return cast(T2) Typedef_payload;
6529 mixin Proxy!Typedef_payload;
6531 pure nothrow @nogc @safe @property
6533 alias TD = typeof(this);
6534 static if (isIntegral!T)
6536 static TD min() {return TD(T.min);}
6537 static TD max() {return TD(T.max);}
6539 else static if (isFloatingPoint!T)
6541 static TD infinity() {return TD(T.infinity);}
6542 static TD nan() {return TD(T.nan);}
6543 static TD dig() {return TD(T.dig);}
6544 static TD epsilon() {return TD(T.epsilon);}
6545 static TD mant_dig() {return TD(T.mant_dig);}
6546 static TD max_10_exp() {return TD(T.max_10_exp);}
6547 static TD max_exp() {return TD(T.max_exp);}
6548 static TD min_10_exp() {return TD(T.min_10_exp);}
6549 static TD min_exp() {return TD(T.min_exp);}
6550 static TD max() {return TD(T.max);}
6551 static TD min_normal() {return TD(T.min_normal);}
6552 TD re() {return TD(Typedef_payload.re);}
6553 TD im() {return TD(Typedef_payload.im);}
6559 Get the underlying type which a $(D Typedef) wraps.
6560 If $(D T) is not a $(D Typedef) it will alias itself to $(D T).
6562 template TypedefType(T)
6564 static if (is(T : Typedef!Arg, Arg))
6565 alias TypedefType = Arg;
6567 alias TypedefType = T;
6573 import std.typecons : Typedef, TypedefType;
6574 import std.conv : to;
6576 alias MyInt = Typedef!int;
6577 static assert(is(TypedefType!MyInt == int));
6579 /// Instantiating with a non-Typedef will return that type
6580 static assert(is(TypedefType!int == int));
6584 // extract the needed type
6585 MyInt myInt = MyInt( num.to!(TypedefType!MyInt) );
6588 // cast to the underlying type to get the value that's being wrapped
6589 int x = cast(TypedefType!MyInt) myInt;
6591 alias MyIntInit = Typedef!(int, 42);
6592 static assert(is(TypedefType!MyIntInit == int));
6593 static assert(MyIntInit() == 42);
6599 static assert(!__traits(compiles, { int y = x; }));
6600 static assert(!__traits(compiles, { long z = x; }));
6605 static assert(Typedef!int.init == int.init);
6607 Typedef!(float, 1.0) z; // specifies the init
6610 static assert(typeof(z).init == 1.0);
6612 alias Dollar = Typedef!(int, 0, "dollar");
6613 alias Yen = Typedef!(int, 0, "yen");
6614 static assert(!is(Dollar == Yen));
6616 Typedef!(int[3]) sa;
6617 static assert(sa.length == 3);
6618 static assert(typeof(sa).length == 3);
6620 Typedef!(int[3]) dollar1;
6621 assert(dollar1[0..$] is dollar1[0 .. 3]);
6623 Typedef!(int[]) dollar2;
6625 assert(dollar2[0..$] is dollar2[0 .. 3]);
6627 static struct Dollar1
6629 static struct DollarToken {}
6630 enum opDollar = DollarToken.init;
6631 auto opSlice(size_t, DollarToken) { return 1; }
6632 auto opSlice(size_t, size_t) { return 2; }
6635 Typedef!Dollar1 drange1;
6636 assert(drange1[0..$] == 1);
6637 assert(drange1[0 .. 1] == 2);
6639 static struct Dollar2
6641 size_t opDollar(size_t pos)() { return pos == 0 ? 1 : 100; }
6642 size_t opIndex(size_t i, size_t j) { return i + j; }
6645 Typedef!Dollar2 drange2;
6646 assert(drange2[$, $] == 101);
6648 static struct Dollar3
6650 size_t opDollar() { return 123; }
6651 size_t opIndex(size_t i) { return i; }
6654 Typedef!Dollar3 drange3;
6655 assert(drange3[$] == 123);
6658 @safe @nogc pure nothrow unittest // Bugzilla 11703
6660 alias I = Typedef!int;
6661 static assert(is(typeof(I.min) == I));
6662 static assert(is(typeof(I.max) == I));
6664 alias F = Typedef!double;
6665 static assert(is(typeof(F.infinity) == F));
6666 static assert(is(typeof(F.epsilon) == F));
6669 assert(!is(typeof(F.re).stringof == double));
6670 assert(!is(typeof(F.im).stringof == double));
6676 import std.typecons;
6677 import std.bitmanip;
6678 static import core.stdc.config;
6680 alias c_ulong = Typedef!(core.stdc.config.c_ulong);
6685 c_ulong, "NameOffset", 31,
6686 c_ulong, "NameIsString", 1
6691 @safe unittest // Issue 12596
6693 import std.typecons;
6694 alias TD = Typedef!int;
6700 @safe unittest // about toHash
6702 import std.typecons;
6704 alias TD = Typedef!int;
6707 assert(td[TD(1)] == 1);
6711 alias TD = Typedef!(int[]);
6713 td[TD([1,2,3,4])] = 2;
6714 assert(td[TD([1,2,3,4])] == 2);
6718 alias TD = Typedef!(int[][]);
6720 td[TD([[1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]])] = 3;
6721 assert(td[TD([[1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]])] == 3);
6725 struct MyStruct{ int x; }
6726 alias TD = Typedef!MyStruct;
6728 td[TD(MyStruct(10))] = 4;
6729 assert(TD(MyStruct(20)) !in td);
6730 assert(td[TD(MyStruct(10))] == 4);
6734 static struct MyStruct2
6737 size_t toHash() const nothrow @safe { return x; }
6738 bool opEquals(ref const MyStruct2 r) const { return r.x == x; }
6741 alias TD = Typedef!MyStruct2;
6743 td[TD(MyStruct2(50))] = 5;
6744 assert(td[TD(MyStruct2(50))] == 5);
6749 alias TD = Typedef!MyClass;
6751 auto c = new MyClass;
6753 assert(TD(new MyClass) !in td);
6754 assert(td[TD(c)] == 6);
6760 alias String = Typedef!(char[]);
6761 alias CString = Typedef!(const(char)[]);
6762 CString cs = "fubar";
6763 String s = cast(String) cs;
6765 char[] s2 = cast(char[]) cs;
6766 const(char)[] cs2 = cast(const(char)[])s;
6771 Allocates a $(D class) object right inside the current scope,
6772 therefore avoiding the overhead of $(D new). This facility is unsafe;
6773 it is the responsibility of the user to not escape a reference to the
6774 object outside the scope.
6776 The class destructor will be called when the result of `scoped()` is
6779 Scoped class instances can be embedded in a parent `class` or `struct`,
6780 just like a child struct instance. Scoped member variables must have
6781 type `typeof(scoped!Class(args))`, and be initialized with a call to
6782 scoped. See below for an example.
6785 It's illegal to move a class instance even if you are sure there
6786 are no pointers to it. As such, it is illegal to move a scoped object.
6791 // _d_newclass now use default GC alignment (looks like (void*).sizeof * 2 for
6792 // small objects). We will just use the maximum of filed alignments.
6793 alias alignment = classInstanceAlignment!T;
6794 alias aligned = _alignUp!alignment;
6796 static struct Scoped
6798 // Addition of `alignment` is required as `Scoped_store` can be misaligned in memory.
6799 private void[aligned(__traits(classInstanceSize, T) + size_t.sizeof) + alignment] Scoped_store = void;
6801 @property inout(T) Scoped_payload() inout
6803 void* alignedStore = cast(void*) aligned(cast(uintptr_t) Scoped_store.ptr);
6804 // As `Scoped` can be unaligned moved in memory class instance should be moved accordingly.
6805 immutable size_t d = alignedStore - Scoped_store.ptr;
6806 size_t* currD = cast(size_t*) &Scoped_store[$ - size_t.sizeof];
6809 import core.stdc.string : memmove;
6810 memmove(alignedStore, Scoped_store.ptr + *currD, __traits(classInstanceSize, T));
6813 return cast(inout(T)) alignedStore;
6815 alias Scoped_payload this;
6818 @disable this(this);
6822 // `destroy` will also write .init but we have no functions in druntime
6823 // for deterministic finalization and memory releasing for now.
6824 .destroy(Scoped_payload);
6828 /** Returns the _scoped object.
6829 Params: args = Arguments to pass to $(D T)'s constructor.
6831 @system auto scoped(Args...)(auto ref Args args)
6833 import std.conv : emplace;
6835 Scoped result = void;
6836 void* alignedStore = cast(void*) aligned(cast(uintptr_t) result.Scoped_store.ptr);
6837 immutable size_t d = alignedStore - result.Scoped_store.ptr;
6838 *cast(size_t*) &result.Scoped_store[$ - size_t.sizeof] = d;
6839 emplace!(Unqual!T)(result.Scoped_store[d .. $ - size_t.sizeof], args);
6855 // Standard usage, constructing A on the stack
6856 auto a1 = scoped!A();
6859 // Result of `scoped` call implicitly converts to a class reference
6861 assert(aRef.x == 42);
6863 // Scoped destruction
6865 auto a2 = scoped!A(1);
6868 // a2 is destroyed here, calling A's destructor
6870 // aRef is now an invalid reference
6872 // Here the temporary scoped A is immediately destroyed.
6873 // This means the reference is then invalid.
6876 // Wrong, should use `auto`
6877 A invalid = scoped!A();
6883 import std.algorithm.mutation : move;
6884 auto invalid = a1.move; // illegal, scoped objects can't be moved
6886 static assert(!is(typeof({
6887 auto e1 = a1; // illegal, scoped objects can't be copied
6888 assert([a1][0].x == 42); // ditto
6890 static assert(!is(typeof({
6891 alias ScopedObject = typeof(a1);
6892 auto e2 = ScopedObject(); // illegal, must be built via scoped!A
6893 auto e3 = ScopedObject(1); // ditto
6897 alias makeScopedA = scoped!A;
6898 auto a3 = makeScopedA();
6899 auto a4 = makeScopedA(1);
6901 // Use as member variable
6904 typeof(scoped!A()) a; // note the trailing parentheses
6916 assert(aRef.x == 5);
6917 destroy(b1); // calls A's destructor for b1.a
6918 // aRef is now an invalid reference
6922 assert(b2.a.x == 6);
6923 destroy(*b2); // calls A's destructor for b2.a
6926 private uintptr_t _alignUp(uintptr_t alignment)(uintptr_t n)
6927 if (alignment > 0 && !((alignment - 1) & alignment))
6929 enum badEnd = alignment - 1; // 0b11, 0b111, ...
6930 return (n + badEnd) & ~badEnd;
6933 @system unittest // Issue 6580 testcase
6935 enum alignment = (void*).alignof;
6938 static class C1 { byte b; }
6939 static class C2 { byte[2] b; }
6940 static class C3 { byte[3] b; }
6941 static class C7 { byte[7] b; }
6942 static assert(scoped!C0().sizeof % alignment == 0);
6943 static assert(scoped!C1().sizeof % alignment == 0);
6944 static assert(scoped!C2().sizeof % alignment == 0);
6945 static assert(scoped!C3().sizeof % alignment == 0);
6946 static assert(scoped!C7().sizeof % alignment == 0);
6948 enum longAlignment = long.alignof;
6951 long long_; byte byte_ = 4;
6953 this(long _long, ref int i) { long_ = _long; ++i; }
6955 static class C2long { byte[2] byte_ = [5, 6]; long long_ = 7; }
6956 static assert(scoped!C1long().sizeof % longAlignment == 0);
6957 static assert(scoped!C2long().sizeof % longAlignment == 0);
6959 void alignmentTest()
6962 auto c1long = scoped!C1long(3, var);
6964 auto c2long = scoped!C2long();
6965 assert(cast(uint)&c1long.long_ % longAlignment == 0);
6966 assert(cast(uint)&c2long.long_ % longAlignment == 0);
6967 assert(c1long.long_ == 3 && c1long.byte_ == 4);
6968 assert(c2long.byte_ == [5, 6] && c2long.long_ == 7);
6973 version (DigitalMars)
6975 void test(size_t size)
6977 import core.stdc.stdlib;
6981 foreach (i; 0 .. 10)
6986 void test(size_t size)()
6991 foreach (i; AliasSeq!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
6996 @system unittest // Original Issue 6580 testcase
6998 class C { int i; byte b; }
7000 auto sa = [scoped!C(), scoped!C()];
7001 assert(cast(uint)&sa[0].i % int.alignof == 0);
7002 assert(cast(uint)&sa[1].i % int.alignof == 0); // fails
7007 class A { int x = 1; }
7008 auto a1 = scoped!A();
7010 auto a2 = scoped!A();
7018 class A { int x = 1; this() { x = 2; } }
7019 auto a1 = scoped!A();
7021 auto a2 = scoped!A();
7029 class A { int x = 1; this(int y) { x = y; } ~this() {} }
7030 auto a1 = scoped!A(5);
7032 auto a2 = scoped!A(42);
7040 class A { static bool dead; ~this() { dead = true; } }
7041 class B : A { static bool dead; ~this() { dead = true; } }
7043 auto b = scoped!B();
7045 assert(B.dead, "asdasd");
7046 assert(A.dead, "asdasd");
7049 @system unittest // Issue 8039 testcase
7052 static struct S { ~this(){ ++dels; } }
7054 static class A { S s; }
7055 dels = 0; { scoped!A(); }
7058 static class B { S[2] s; }
7059 dels = 0; { scoped!B(); }
7062 static struct S2 { S[3] s; }
7063 static class C { S2[2] s; }
7064 dels = 0; { scoped!C(); }
7067 static class D: A { S2[2] s; }
7068 dels = 0; { scoped!D(); }
7069 assert(dels == 1+6);
7077 this() { a = this; }
7078 this(int i) { a = this; }
7080 bool check() { return this is a; }
7083 auto a1 = scoped!A();
7086 auto a2 = scoped!A(1);
7099 this() { ++sdtor; assert(sdtor == 1); }
7100 ~this() { assert(sdtor == 1); --sdtor; }
7105 static class ABob : A, Bob
7107 this() { ++sdtor; assert(sdtor == 2); }
7108 ~this() { assert(sdtor == 2); --sdtor; }
7112 scope(exit) assert(A.sdtor == 0);
7113 auto abob = scoped!ABob();
7118 static class A { this(int) {} }
7119 static assert(!__traits(compiles, scoped!A()));
7124 static class A { @property inout(int) foo() inout { return 1; } }
7126 auto a1 = scoped!A();
7127 assert(a1.foo == 1);
7128 static assert(is(typeof(a1.foo) == int));
7130 auto a2 = scoped!(const(A))();
7131 assert(a2.foo == 1);
7132 static assert(is(typeof(a2.foo) == const(int)));
7134 auto a3 = scoped!(immutable(A))();
7135 assert(a3.foo == 1);
7136 static assert(is(typeof(a3.foo) == immutable(int)));
7138 const c1 = scoped!A();
7139 assert(c1.foo == 1);
7140 static assert(is(typeof(c1.foo) == const(int)));
7142 const c2 = scoped!(const(A))();
7143 assert(c2.foo == 1);
7144 static assert(is(typeof(c2.foo) == const(int)));
7146 const c3 = scoped!(immutable(A))();
7147 assert(c3.foo == 1);
7148 static assert(is(typeof(c3.foo) == immutable(int)));
7153 class C { this(ref int val) { assert(val == 3); ++val; } }
7156 auto s = scoped!C(val);
7168 alias makeScopedC = scoped!C;
7170 auto a = makeScopedC();
7171 auto b = makeScopedC(1);
7172 auto c = makeScopedC(1, 1);
7174 static assert(is(typeof(a) == typeof(b)));
7175 static assert(is(typeof(b) == typeof(c)));
7179 Defines a simple, self-documenting yes/no flag. This makes it easy for
7180 APIs to define functions accepting flags without resorting to $(D
7181 bool), which is opaque in calls, and without needing to define an
7182 enumerated type separately. Using $(D Flag!"Name") instead of $(D
7183 bool) makes the flag's meaning visible in calls. Each yes/no flag has
7184 its own type, which makes confusions and mix-ups impossible.
7188 Code calling $(D getLine) (usually far away from its definition) can't be
7189 understood without looking at the documentation, even by users familiar with
7192 string getLine(bool keepTerminator)
7195 if (keepTerminator) ...
7199 auto line = getLine(false);
7202 Assuming the reverse meaning (i.e. "ignoreTerminator") and inserting the wrong
7203 code compiles and runs with erroneous results.
7205 After replacing the boolean parameter with an instantiation of $(D Flag), code
7206 calling $(D getLine) can be easily read and understood even by people not
7207 fluent with the API:
7210 string getLine(Flag!"keepTerminator" keepTerminator)
7213 if (keepTerminator) ...
7217 auto line = getLine(Yes.keepTerminator);
7220 The structs $(D Yes) and $(D No) are provided as shorthand for
7221 $(D Flag!"Name".yes) and $(D Flag!"Name".no) and are preferred for brevity and
7222 readability. These convenience structs mean it is usually unnecessary and
7223 counterproductive to create an alias of a $(D Flag) as a way of avoiding typing
7224 out the full type while specifying the affirmative or negative options.
7226 Passing categorical data by means of unstructured $(D bool)
7227 parameters is classified under "simple-data coupling" by Steve
7228 McConnell in the $(LUCKY Code Complete) book, along with three other
7229 kinds of coupling. The author argues citing several studies that
7230 coupling has a negative effect on code quality. $(D Flag) offers a
7231 simple structuring method for passing yes/no flags to APIs.
7233 template Flag(string name) {
7238 When creating a value of type $(D Flag!"Name"), use $(D
7239 Flag!"Name".no) for the negative option. When using a value
7240 of type $(D Flag!"Name"), compare it against $(D
7241 Flag!"Name".no) or just $(D false) or $(D 0). */
7244 /** When creating a value of type $(D Flag!"Name"), use $(D
7245 Flag!"Name".yes) for the affirmative option. When using a
7246 value of type $(D Flag!"Name"), compare it against $(D
7254 Convenience names that allow using e.g. $(D Yes.encryption) instead of
7255 $(D Flag!"encryption".yes) and $(D No.encryption) instead of $(D
7256 Flag!"encryption".no).
7260 template opDispatch(string name)
7262 enum opDispatch = Flag!name.yes;
7265 //template yes(string name) { enum Flag!name yes = Flag!name.yes; }
7270 template opDispatch(string name)
7272 enum opDispatch = Flag!name.no;
7280 assert(flag1 == Flag!"abc".no);
7281 assert(flag1 == No.abc);
7283 if (flag1) assert(false);
7286 if (!flag1) assert(false);
7287 if (flag1) {} else assert(false);
7288 assert(flag1 == Yes.abc);
7292 Detect whether an enum is of integral type and has only "flag" values
7293 (i.e. values with a bit count of exactly 1).
7294 Additionally, a zero value is allowed for compatibility with enums including
7297 template isBitFlagEnum(E)
7299 static if (is(E Base == enum) && isIntegral!Base)
7301 enum isBitFlagEnum = (E.min >= 0) &&
7303 foreach (immutable flag; EnumMembers!E)
7307 if (value != 0) return false;
7314 enum isBitFlagEnum = false;
7319 @safe pure nothrow unittest
7330 static assert(isBitFlagEnum!A);
7340 static assert(!isBitFlagEnum!B);
7348 static assert(!isBitFlagEnum!C);
7352 A typesafe structure for storing combinations of enum values.
7354 This template defines a simple struct to represent bitwise OR combinations of
7355 enum values. It can be used if all the enum values are integral constants with
7356 a bit count of at most 1, or if the $(D unsafe) parameter is explicitly set to
7358 This is much safer than using the enum itself to store
7359 the OR combination, which can produce surprising effects like this:
7367 // will throw SwitchError
7377 struct BitFlags(E, Flag!"unsafe" unsafe = No.unsafe) if (unsafe || isBitFlagEnum!(E))
7379 @safe @nogc pure nothrow:
7381 enum isBaseEnumType(T) = is(E == T);
7382 alias Base = OriginalType!E;
7384 static struct Negation
7386 @safe @nogc pure nothrow:
7390 // Prevent non-copy construction outside the module.
7405 if (allSatisfy!(isBaseEnumType, T))
7410 bool opCast(B: bool)() const
7415 Base opCast(B)() const
7416 if (isImplicitlyConvertible!(Base, B))
7421 Negation opUnary(string op)() const
7424 return Negation(~mValue);
7427 auto ref opAssign(T...)(T flags)
7428 if (allSatisfy!(isBaseEnumType, T))
7431 foreach (E flag; flags)
7438 auto ref opAssign(E flag)
7444 auto ref opOpAssign(string op: "|")(BitFlags flags)
7446 mValue |= flags.mValue;
7450 auto ref opOpAssign(string op: "&")(BitFlags flags)
7452 mValue &= flags.mValue;
7456 auto ref opOpAssign(string op: "|")(E flag)
7462 auto ref opOpAssign(string op: "&")(E flag)
7468 auto ref opOpAssign(string op: "&")(Negation negatedFlags)
7470 mValue &= negatedFlags.mValue;
7474 auto opBinary(string op)(BitFlags flags) const
7475 if (op == "|" || op == "&")
7477 BitFlags result = this;
7478 result.opOpAssign!op(flags);
7482 auto opBinary(string op)(E flag) const
7483 if (op == "|" || op == "&")
7485 BitFlags result = this;
7486 result.opOpAssign!op(flag);
7490 auto opBinary(string op: "&")(Negation negatedFlags) const
7492 BitFlags result = this;
7493 result.opOpAssign!op(negatedFlags);
7497 auto opBinaryRight(string op)(E flag) const
7498 if (op == "|" || op == "&")
7500 return opBinary!op(flag);
7504 /// BitFlags can be manipulated with the usual operators
7505 @safe @nogc pure nothrow unittest
7507 import std.traits : EnumMembers;
7509 // You can use such an enum with BitFlags straight away
7517 BitFlags!Enum flags1;
7518 assert(!(flags1 & (Enum.A | Enum.B | Enum.C)));
7520 // You need to specify the `unsafe` parameter for enum with custom values
7528 static assert(!__traits(compiles, { BitFlags!UnsafeEnum flags2; }));
7529 BitFlags!(UnsafeEnum, Yes.unsafe) flags3;
7531 immutable BitFlags!Enum flags_empty;
7532 // A default constructed BitFlags has no value set
7533 assert(!(flags_empty & Enum.A) && !(flags_empty & Enum.B) && !(flags_empty & Enum.C));
7535 // Value can be set with the | operator
7536 immutable BitFlags!Enum flags_A = flags_empty | Enum.A;
7538 // And tested with the & operator
7539 assert(flags_A & Enum.A);
7542 assert(Enum.A & flags_A);
7544 // BitFlags can be variadically initialized
7545 immutable BitFlags!Enum flags_AB = BitFlags!Enum(Enum.A, Enum.B);
7546 assert((flags_AB & Enum.A) && (flags_AB & Enum.B) && !(flags_AB & Enum.C));
7548 // Use the ~ operator for subtracting flags
7549 immutable BitFlags!Enum flags_B = flags_AB & ~BitFlags!Enum(Enum.A);
7550 assert(!(flags_B & Enum.A) && (flags_B & Enum.B) && !(flags_B & Enum.C));
7552 // You can use the EnumMembers template to set all flags
7553 immutable BitFlags!Enum flags_all = EnumMembers!Enum;
7555 // use & between BitFlags for intersection
7556 immutable BitFlags!Enum flags_BC = BitFlags!Enum(Enum.B, Enum.C);
7557 assert(flags_B == (flags_BC & flags_AB));
7559 // All the binary operators work in their assignment version
7560 BitFlags!Enum temp = flags_empty;
7562 assert(temp == (flags_empty | flags_AB));
7565 assert(temp == (flags_empty | Enum.B));
7568 assert(temp == (flags_empty & flags_AB));
7571 assert(temp == (flags_empty & Enum.A));
7573 // BitFlags with no value set evaluate to false
7574 assert(!flags_empty);
7576 // BitFlags with at least one value set evaluate to true
7579 // This can be useful to check intersection between BitFlags
7580 assert(flags_A & flags_AB);
7581 assert(flags_AB & Enum.A);
7583 // Finally, you can of course get you raw value out of flags
7584 auto value = cast(int) flags_A;
7585 assert(value == Enum.A);
7590 Replaces all occurrences of `From` into `To`, in one or more types `T`. For
7591 example, $(D ReplaceType!(int, uint, Tuple!(int, float)[string])) yields
7592 $(D Tuple!(uint, float)[string]). The types in which replacement is performed
7593 may be arbitrarily complex, including qualifiers, built-in type constructors
7594 (pointers, arrays, associative arrays, functions, and delegates), and template
7595 instantiations; replacement proceeds transitively through the type definition.
7596 However, member types in `struct`s or `class`es are not replaced because there
7597 are no ways to express the types resulting after replacement.
7599 This is an advanced type manipulation necessary e.g. for replacing the
7600 placeholder type `This` in $(REF Algebraic, std,variant).
7602 Returns: `ReplaceType` aliases itself to the type(s) that result after
7605 template ReplaceType(From, To, T...)
7607 static if (T.length == 1)
7609 static if (is(T[0] == From))
7610 alias ReplaceType = To;
7611 else static if (is(T[0] == const(U), U))
7612 alias ReplaceType = const(ReplaceType!(From, To, U));
7613 else static if (is(T[0] == immutable(U), U))
7614 alias ReplaceType = immutable(ReplaceType!(From, To, U));
7615 else static if (is(T[0] == shared(U), U))
7616 alias ReplaceType = shared(ReplaceType!(From, To, U));
7617 else static if (is(T[0] == U*, U))
7619 static if (is(U == function))
7620 alias ReplaceType = replaceTypeInFunctionType!(From, To, T[0]);
7622 alias ReplaceType = ReplaceType!(From, To, U)*;
7624 else static if (is(T[0] == delegate))
7626 alias ReplaceType = replaceTypeInFunctionType!(From, To, T[0]);
7628 else static if (is(T[0] == function))
7630 static assert(0, "Function types not supported," ~
7631 " use a function pointer type instead of " ~ T[0].stringof);
7633 else static if (is(T[0] : U!V, alias U, V...))
7635 template replaceTemplateArgs(T...)
7637 static if (is(typeof(T[0]))) // template argument is value or symbol
7638 enum replaceTemplateArgs = T[0];
7640 alias replaceTemplateArgs = ReplaceType!(From, To, T[0]);
7642 alias ReplaceType = U!(staticMap!(replaceTemplateArgs, V));
7644 else static if (is(T[0] == struct))
7645 // don't match with alias this struct below (Issue 15168)
7646 alias ReplaceType = T[0];
7647 else static if (is(T[0] == U[], U))
7648 alias ReplaceType = ReplaceType!(From, To, U)[];
7649 else static if (is(T[0] == U[n], U, size_t n))
7650 alias ReplaceType = ReplaceType!(From, To, U)[n];
7651 else static if (is(T[0] == U[V], U, V))
7653 ReplaceType!(From, To, U)[ReplaceType!(From, To, V)];
7655 alias ReplaceType = T[0];
7657 else static if (T.length > 1)
7659 alias ReplaceType = AliasSeq!(ReplaceType!(From, To, T[0]),
7660 ReplaceType!(From, To, T[1 .. $]));
7664 alias ReplaceType = AliasSeq!();
7672 is(ReplaceType!(int, string, int[]) == string[]) &&
7673 is(ReplaceType!(int, string, int[int]) == string[string]) &&
7674 is(ReplaceType!(int, string, const(int)[]) == const(string)[]) &&
7675 is(ReplaceType!(int, string, Tuple!(int[], float))
7676 == Tuple!(string[], float))
7680 private template replaceTypeInFunctionType(From, To, fun)
7682 alias RX = ReplaceType!(From, To, ReturnType!fun);
7683 alias PX = AliasSeq!(ReplaceType!(From, To, Parameters!fun));
7684 // Wrapping with AliasSeq is neccesary because ReplaceType doesn't return
7685 // tuple if Parameters!fun.length == 1
7689 enum linkage = functionLinkage!fun;
7690 alias attributes = functionAttributes!fun;
7691 enum variadicStyle = variadicFunctionStyle!fun;
7692 alias storageClasses = ParameterStorageClassTuple!fun;
7696 result ~= "extern(" ~ linkage ~ ") ";
7697 static if (attributes & FunctionAttribute.ref_)
7703 static if (is(fun == delegate))
7704 result ~= " delegate";
7706 result ~= " function";
7713 if (storageClasses[i] & ParameterStorageClass.scope_)
7715 if (storageClasses[i] & ParameterStorageClass.out_)
7717 if (storageClasses[i] & ParameterStorageClass.ref_)
7719 if (storageClasses[i] & ParameterStorageClass.lazy_)
7721 if (storageClasses[i] & ParameterStorageClass.return_)
7722 result ~= "return ";
7724 result ~= "PX[" ~ i.stringof ~ "]";
7726 static if (variadicStyle == Variadic.typesafe)
7728 else static if (variadicStyle != Variadic.no)
7732 static if (attributes & FunctionAttribute.pure_)
7734 static if (attributes & FunctionAttribute.nothrow_)
7735 result ~= " nothrow";
7736 static if (attributes & FunctionAttribute.property)
7737 result ~= " @property";
7738 static if (attributes & FunctionAttribute.trusted)
7739 result ~= " @trusted";
7740 static if (attributes & FunctionAttribute.safe)
7742 static if (attributes & FunctionAttribute.nogc)
7744 static if (attributes & FunctionAttribute.system)
7745 result ~= " @system";
7746 static if (attributes & FunctionAttribute.const_)
7748 static if (attributes & FunctionAttribute.immutable_)
7749 result ~= " immutable";
7750 static if (attributes & FunctionAttribute.inout_)
7752 static if (attributes & FunctionAttribute.shared_)
7753 result ~= " shared";
7754 static if (attributes & FunctionAttribute.return_)
7755 result ~= " return";
7759 //pragma(msg, "gen ==> ", gen());
7761 mixin("alias replaceTypeInFunctionType = " ~ gen() ~ ";");
7766 template Test(Ts...)
7768 static if (Ts.length)
7770 //pragma(msg, "Testing: ReplaceType!("~Ts[0].stringof~", "
7771 // ~Ts[1].stringof~", "~Ts[2].stringof~")");
7772 static assert(is(ReplaceType!(Ts[0], Ts[1], Ts[2]) == Ts[3]),
7773 "ReplaceType!("~Ts[0].stringof~", "~Ts[1].stringof~", "
7774 ~Ts[2].stringof~") == "
7775 ~ReplaceType!(Ts[0], Ts[1], Ts[2]).stringof);
7776 alias Test = Test!(Ts[4 .. $]);
7778 else alias Test = void;
7781 //import core.stdc.stdio;
7782 alias RefFun1 = ref int function(float, long);
7783 alias RefFun2 = ref float function(float, long);
7784 extern(C) int printf(const char*, ...) nothrow @nogc @system;
7785 extern(C) float floatPrintf(const char*, ...) nothrow @nogc @system;
7789 struct S1 { void foo() { x = 1; } }
7790 struct S2 { void bar() { x = 2; } }
7793 int, float, typeof(&func), float delegate(float),
7794 int, float, typeof(&printf), typeof(&floatPrintf),
7795 int, float, int function(out long, ...),
7796 float function(out long, ...),
7797 int, float, int function(ref float, long),
7798 float function(ref float, long),
7799 int, float, int function(ref int, long),
7800 float function(ref float, long),
7801 int, float, int function(out int, long),
7802 float function(out float, long),
7803 int, float, int function(lazy int, long),
7804 float function(lazy float, long),
7805 int, float, int function(out long, ref const int),
7806 float function(out long, ref const float),
7808 int, float, int, float,
7809 int, float, const int, const float,
7810 int, float, immutable int, immutable float,
7811 int, float, shared int, shared float,
7812 int, float, int*, float*,
7813 int, float, const(int)*, const(float)*,
7814 int, float, const(int*), const(float*),
7815 const(int)*, float, const(int*), const(float),
7816 int*, float, const(int)*, const(int)*,
7817 int, float, int[], float[],
7818 int, float, int[42], float[42],
7819 int, float, const(int)[42], const(float)[42],
7820 int, float, const(int[42]), const(float[42]),
7821 int, float, int[int], float[float],
7822 int, float, int[double], float[double],
7823 int, float, double[int], double[float],
7824 int, float, int function(float, long), float function(float, long),
7825 int, float, int function(float), float function(float),
7826 int, float, int function(float, int), float function(float, float),
7827 int, float, int delegate(float, long), float delegate(float, long),
7828 int, float, int delegate(float), float delegate(float),
7829 int, float, int delegate(float, int), float delegate(float, float),
7830 int, float, Unique!int, Unique!float,
7831 int, float, Tuple!(float, int), Tuple!(float, float),
7832 int, float, RefFun1, RefFun2,
7834 S1[1][][S1]* function(),
7835 S2[1][][S2]* function(),
7837 int[3] function( int[] arr, int[2] ...) pure @trusted,
7838 string[3] function(string[] arr, string[2] ...) pure @trusted,
7842 static struct T1 { string s; alias s this; }
7843 static struct T2 { char[10] s; alias s this; }
7844 static struct T3 { string[string] s; alias s this; }
7845 alias Pass2 = Test!(
7846 ubyte, ubyte, T1, T1,
7847 ubyte, ubyte, T2, T2,
7848 ubyte, ubyte, T3, T3,
7852 @safe unittest // Bugzilla 17116
7854 alias ConstDg = void delegate(float) const;
7855 alias B = void delegate(int) const;
7856 alias A = ReplaceType!(float, int, ConstDg);
7857 static assert(is(B == A));
7861 Ternary type with three truth values:
7864 $(LI `Ternary.yes` for `true`)
7865 $(LI `Ternary.no` for `false`)
7866 $(LI `Ternary.unknown` as an unknown state)
7869 Also known as trinary, trivalent, or trilean.
7872 $(HTTP en.wikipedia.org/wiki/Three-valued_logic,
7873 Three Valued Logic on Wikipedia)
7877 @safe @nogc nothrow pure:
7879 private ubyte value = 6;
7880 private static Ternary make(ubyte b)
7888 The possible states of the `Ternary`
7894 enum unknown = make(6);
7897 Construct and assign from a `bool`, receiving `no` for `false` and `yes`
7900 this(bool b) { value = b << 1; }
7903 void opAssign(bool b) { value = b << 1; }
7906 Construct a ternary value from another ternary value
7908 this(const Ternary b) { value = b.value; }
7911 $(TABLE Truth table for logical operations,
7912 $(TR $(TH `a`) $(TH `b`) $(TH `$(TILDE)a`) $(TH `a | b`) $(TH `a & b`) $(TH `a ^ b`))
7913 $(TR $(TD `no`) $(TD `no`) $(TD `yes`) $(TD `no`) $(TD `no`) $(TD `no`))
7914 $(TR $(TD `no`) $(TD `yes`) $(TD) $(TD `yes`) $(TD `no`) $(TD `yes`))
7915 $(TR $(TD `no`) $(TD `unknown`) $(TD) $(TD `unknown`) $(TD `no`) $(TD `unknown`))
7916 $(TR $(TD `yes`) $(TD `no`) $(TD `no`) $(TD `yes`) $(TD `no`) $(TD `yes`))
7917 $(TR $(TD `yes`) $(TD `yes`) $(TD) $(TD `yes`) $(TD `yes`) $(TD `no`))
7918 $(TR $(TD `yes`) $(TD `unknown`) $(TD) $(TD `yes`) $(TD `unknown`) $(TD `unknown`))
7919 $(TR $(TD `unknown`) $(TD `no`) $(TD `unknown`) $(TD `unknown`) $(TD `no`) $(TD `unknown`))
7920 $(TR $(TD `unknown`) $(TD `yes`) $(TD) $(TD `yes`) $(TD `unknown`) $(TD `unknown`))
7921 $(TR $(TD `unknown`) $(TD `unknown`) $(TD) $(TD `unknown`) $(TD `unknown`) $(TD `unknown`))
7924 Ternary opUnary(string s)() if (s == "~")
7926 return make((386 >> value) & 6);
7930 Ternary opBinary(string s)(Ternary rhs) if (s == "|")
7932 return make((25_512 >> (value + rhs.value)) & 6);
7936 Ternary opBinary(string s)(Ternary rhs) if (s == "&")
7938 return make((26_144 >> (value + rhs.value)) & 6);
7942 Ternary opBinary(string s)(Ternary rhs) if (s == "^")
7944 return make((26_504 >> (value + rhs.value)) & 6);
7949 @safe @nogc nothrow pure
7953 assert(a == Ternary.unknown);
7955 assert(~Ternary.yes == Ternary.no);
7956 assert(~Ternary.no == Ternary.yes);
7957 assert(~Ternary.unknown == Ternary.unknown);
7960 @safe @nogc nothrow pure
7963 alias f = Ternary.no, t = Ternary.yes, u = Ternary.unknown;
7964 Ternary[27] truthTableAnd =
7977 Ternary[27] truthTableOr =
7990 Ternary[27] truthTableXor =
8003 for (auto i = 0; i != truthTableAnd.length; i += 3)
8005 assert((truthTableAnd[i] & truthTableAnd[i + 1])
8006 == truthTableAnd[i + 2]);
8007 assert((truthTableOr[i] | truthTableOr[i + 1])
8008 == truthTableOr[i + 2]);
8009 assert((truthTableXor[i] ^ truthTableXor[i + 1])
8010 == truthTableXor[i + 2]);
8014 assert(a == Ternary.unknown);
8015 static assert(!is(typeof({ if (a) {} })));
8016 assert(!is(typeof({ auto b = Ternary(3); })));
8018 assert(a == Ternary.yes);
8020 assert(a == Ternary.no);
8021 a = Ternary.unknown;
8022 assert(a == Ternary.unknown);
8026 assert(~Ternary.yes == Ternary.no);
8027 assert(~Ternary.no == Ternary.yes);
8028 assert(~Ternary.unknown == Ternary.unknown);