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;)
10 $(TR $(TH Category) $(TH Symbols))
24 $(TR $(TD Memory allocation) $(TD
25 $(LREF SafeRefCounted)
26 $(LREF safeRefCounted)
27 $(LREF RefCountedAutoInitialize)
31 $(TR $(TD Code generation) $(TD
34 $(LREF generateAssertTrap)
35 $(LREF generateEmptyFunction)
38 $(TR $(TD Nullable) $(TD
44 $(TR $(TD Proxies) $(TD
61 Copyright: Copyright the respective authors, 2008-
62 License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0).
63 Source: $(PHOBOSSRC std/typecons.d)
64 Authors: $(HTTP erdani.org, Andrei Alexandrescu),
65 $(HTTP bartoszmilewski.wordpress.com, Bartosz Milewski),
72 import std.format.spec : singleSpec, FormatSpec;
73 import std.format.write : formatValue;
74 import std.meta : AliasSeq, allSatisfy;
75 import std.range.primitives : isOutputRange;
77 import std.internal.attributes : betterC;
82 alias Coord = Tuple!(int, "x", int, "y", int, "z");
84 c[1] = 1; // access by index
85 c.z = 1; // access by given name
86 assert(c == Coord(0, 1, 1));
88 // names can be omitted, types can be mixed
89 alias DictEntry = Tuple!(string, int);
90 auto dict = DictEntry("seven", 7);
92 // element types can be inferred
93 assert(tuple(2, 3, 4)[1] == 3);
94 // type inference works with names too
95 auto tup = tuple!("x", "y", "z")(2, 3, 4);
99 /// Rebindable references to const and immutable objects
104 void foo() const @safe {}
106 const w1 = new Widget, w2 = new Widget;
108 // w1 = w2 would not work; can't rebind const object
110 auto r = Rebindable!(const Widget)(w1);
111 // invoke method as if r were a Widget object
113 // rebind r to refer to another object
118 Encapsulates unique ownership of a resource.
120 When a `Unique!T` goes out of scope it will call `destroy`
121 on the resource `T` that it manages, unless it is transferred.
122 One important consequence of `destroy` is that it will call the
123 destructor of the resource `T`. GC-managed references are not
124 guaranteed to be valid during a destructor call, but other members of
125 `T`, such as file handles or pointers to `malloc` memory, will
126 still be valid during the destructor call. This allows the resource
127 `T` to deallocate or clean up any non-GC resources.
129 If it is desirable to persist a `Unique!T` outside of its original
130 scope, then it can be transferred. The transfer can be explicit, by
131 calling `release`, or implicit, when returning Unique from a
132 function. The resource `T` can be a polymorphic class object or
133 instance of an interface, in which case Unique behaves polymorphically
136 If `T` is a value type, then `Unique!T` will be implemented
137 as a reference to a `T`.
141 /** Represents a reference to `T`. Resolves to `T*` if `T` is a value type. */
142 static if (is(T == class) || is(T == interface))
148 // Deferred in case we get some language support for checking uniqueness.
151 Allows safe construction of `Unique`. It creates the resource and
152 guarantees unique ownership of it (unless `T` publishes aliases of
154 Note: Nested structs/classes cannot be created.
156 args = Arguments to pass to `T`'s constructor.
159 auto u = Unique!(C).create();
162 static Unique!T create(A...)(auto ref A args)
163 if (__traits(compiles, new T(args)))
171 Constructor that takes an rvalue.
172 It will ensure uniqueness, as long as the rvalue
173 isn't just a view on an lvalue (e.g., a cast).
176 Unique!Foo f = new Foo;
184 Constructor that takes an lvalue. It nulls its source.
185 The nulling will ensure uniqueness as long as there
186 are no previous aliases to the source.
195 Constructor that takes a `Unique` of a type that is convertible to our type.
197 Typically used to transfer a `Unique` rvalue of derived type to
198 a `Unique` of base type.
204 Unique!Object uo = uc.release;
214 /// Transfer ownership from a `Unique` of a type that is convertible to our type.
215 void opAssign(U)(Unique!U u)
218 // first delete any resource we own
233 /** Returns whether the resource exists. */
234 @property bool isEmpty() const
238 /** Transfer ownership to a `Unique` rvalue. Nullifies the current contents.
239 Same as calling std.algorithm.move on it.
243 import std.algorithm.mutation : move;
247 /** Forwards member access to contents. */
251 Postblit operator is undefined to prevent the cloning of `Unique` objects.
265 this(int i){this.i = i;}
269 // Construct a unique instance of S on the heap
270 Unique!S ut = new S(5);
271 // Implicit transfer of ownership
274 // Borrow a unique resource by ref
275 void increment(ref Unique!S ur)
279 void consume(Unique!S u2)
282 // Resource automatically deleted here
289 //consume(u1); // Error: u1 is not copyable
290 // Transfer ownership of the resource
297 // test conversion to base ref
303 // constructor conversion
304 Unique!Object u = Unique!C(new C);
305 static assert(!__traits(compiles, {u = new C;}));
308 assert(deleted == 1);
311 static assert(!__traits(compiles, {Unique!Object uo = uc;}));
312 Unique!Object uo = new C;
313 // opAssign conversion, deleting uo resource first
317 assert(deleted == 2);
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 auto ub2 = g(ub.release);
339 assert(!ub2.isEmpty);
359 int val() const { return 4; }
361 alias UBar = Unique!Bar;
364 debug(Unique) writeln("inside g");
369 assert(u.val() == 4);
370 // Resource automatically deleted here
372 auto ub = UBar(new BarImpl);
373 assert(BarImpl.count == 1);
376 static assert(!__traits(compiles, {auto ub3 = g(ub);}));
377 auto ub2 = g(ub.release);
379 assert(!ub2.isEmpty);
380 consume(ub2.release);
381 assert(BarImpl.count == 0);
389 int val() const { return 3; }
392 alias UFoo = Unique!(Foo);
399 auto uf = UFoo(new Foo);
402 static assert(!__traits(compiles, {auto uf3 = f(uf);}));
403 auto uf2 = f(uf.release);
405 assert(!uf2.isEmpty);
408 // ensure Unique behaves correctly through const access paths
411 struct Bar {int val;}
414 Unique!Bar bar = new Bar;
419 const Foo* ptr = &foo;
420 static assert(is(typeof(ptr) == const(Foo*)));
421 static assert(is(typeof(ptr.bar) == const(Unique!Bar)));
422 static assert(is(typeof(ptr.bar.val) == const(int)));
423 assert(ptr.bar.val == 6);
425 assert(ptr.bar.val == 7);
428 // Used in Tuple.toString
429 private template sharedToString(alias field)
430 if (is(typeof(field) == shared))
432 static immutable sharedToString = typeof(field).stringof;
435 private template sharedToString(alias field)
436 if (!is(typeof(field) == shared))
438 alias sharedToString = field;
441 private enum bool distinctFieldNames(names...) = __traits(compiles,
443 static foreach (__name; names)
444 static if (is(typeof(__name) : string))
445 mixin("enum int " ~ __name ~ " = 0;");
450 static assert(!distinctFieldNames!(string, "abc", string, "abc"));
451 static assert(distinctFieldNames!(string, "abc", int, "abd"));
452 static assert(!distinctFieldNames!(int, "abc", string, "abd", int, "abc"));
453 // https://issues.dlang.org/show_bug.cgi?id=19240
454 static assert(!distinctFieldNames!(int, "int"));
458 // Parse (type,name) pairs (FieldSpecs) out of the specified
459 // arguments. Some fields would have name, others not.
460 private template parseSpecs(Specs...)
462 static if (Specs.length == 0)
464 alias parseSpecs = AliasSeq!();
466 else static if (is(Specs[0]))
468 static if (is(typeof(Specs[1]) : string))
471 AliasSeq!(FieldSpec!(Specs[0 .. 2]),
472 parseSpecs!(Specs[2 .. $]));
477 AliasSeq!(FieldSpec!(Specs[0]),
478 parseSpecs!(Specs[1 .. $]));
483 static assert(0, "Attempted to instantiate Tuple with an "
484 ~"invalid argument: "~ Specs[0].stringof);
488 private template FieldSpec(T, string s = "")
494 // Used with staticMap.
495 private alias extractType(alias spec) = spec.Type;
496 private alias extractName(alias spec) = spec.name;
497 private template expandSpec(alias spec)
499 static if (spec.name.length == 0)
500 alias expandSpec = AliasSeq!(spec.Type);
502 alias expandSpec = AliasSeq!(spec.Type, spec.name);
506 private enum areCompatibleTuples(Tup1, Tup2, string op) =
507 isTuple!(OriginalType!Tup2) && Tup1.Types.length == Tup2.Types.length && is(typeof(
508 (ref Tup1 tup1, ref Tup2 tup2)
510 static foreach (i; 0 .. Tup1.Types.length)
512 auto lhs = typeof(tup1.field[i]).init;
513 auto rhs = typeof(tup2.field[i]).init;
514 static if (op == "=")
517 auto result = mixin("lhs "~op~" rhs");
521 private enum areBuildCompatibleTuples(Tup1, Tup2) =
522 isTuple!Tup2 && Tup1.Types.length == Tup2.Types.length && is(typeof(
524 static foreach (i; 0 .. Tup1.Types.length)
525 static assert(isBuildable!(Tup1.Types[i], Tup2.Types[i]));
528 // Returns `true` iff a `T` can be initialized from a `U`.
529 private enum isBuildable(T, U) = is(typeof(
534 // Helper for partial instantiation
535 private template isBuildableFrom(U)
537 enum isBuildableFrom(T) = isBuildable!(T, U);
542 _Tuple of values, for example $(D Tuple!(int, string)) is a record that
543 stores an `int` and a `string`. `Tuple` can be used to bundle
544 values together, notably when returning multiple values from a
545 function. If `obj` is a `Tuple`, the individual members are
546 accessible with the syntax `obj[0]` for the first field, `obj[1]`
547 for the second, and so on.
549 See_Also: $(LREF tuple).
552 Specs = A list of types (and optionally, member names) that the `Tuple` contains.
554 template Tuple(Specs...)
555 if (distinctFieldNames!(Specs))
557 import std.meta : staticMap;
559 alias fieldSpecs = parseSpecs!Specs;
561 // Generates named fields as follows:
562 // alias name_0 = Identity!(field[0]);
563 // alias name_1 = Identity!(field[1]);
565 // NOTE: field[k] is an expression (which yields a symbol of a
566 // variable) and can't be aliased directly.
567 enum injectNamedFields = ()
570 static foreach (i, val; fieldSpecs)
572 immutable si = i.stringof;
573 decl ~= "alias _" ~ si ~ " = Identity!(field[" ~ si ~ "]);";
574 if (val.name.length != 0)
576 decl ~= "alias " ~ val.name ~ " = _" ~ si ~ ";";
582 // Returns Specs for a subtuple this[from .. to] preserving field
584 alias sliceSpecs(size_t from, size_t to) =
585 staticMap!(expandSpec, fieldSpecs[from .. to]);
590 * The types of the `Tuple`'s components.
592 alias Types = staticMap!(extractType, fieldSpecs);
594 private alias _Fields = Specs;
597 static if (Specs.length == 0) @safe unittest
599 import std.meta : AliasSeq;
600 alias Fields = Tuple!(int, "id", string, float);
601 static assert(is(Fields.Types == AliasSeq!(int, string, float)));
605 * The names of the `Tuple`'s components. Unnamed fields have empty names.
607 alias fieldNames = staticMap!(extractName, fieldSpecs);
610 static if (Specs.length == 0) @safe unittest
612 import std.meta : AliasSeq;
613 alias Fields = Tuple!(int, "id", string, float);
614 static assert(Fields.fieldNames == AliasSeq!("id", "", ""));
618 * Use `t.expand` for a `Tuple` `t` to expand it into its
619 * components. The result of `expand` acts as if the `Tuple`'s components
620 * were listed as a list of values. (Ordinarily, a `Tuple` acts as a
624 mixin(injectNamedFields());
627 static if (Specs.length == 0) @safe unittest
629 auto t1 = tuple(1, " hello ", 'a');
630 assert(t1.toString() == `Tuple!(int, string, char)(1, " hello ", 'a')`);
632 void takeSeveralTypes(int n, string s, bool b)
634 assert(n == 4 && s == "test" && b == false);
637 auto t2 = tuple(4, "test", false);
638 //t.expand acting as a list of values
639 takeSeveralTypes(t2.expand);
642 static if (is(Specs))
644 // This is mostly to make t[n] work.
650 ref inout(Tuple!Types) _Tuple_super() inout @trusted
652 static foreach (i; 0 .. Types.length) // Rely on the field layout
654 static assert(typeof(return).init.tupleof[i].offsetof ==
657 return *cast(typeof(return)*) &(field[0]);
659 // This is mostly to make t[n] work.
660 alias _Tuple_super this;
663 // backwards compatibility
664 alias field = expand;
667 * Constructor taking one value for each field.
670 * values = A list of values that are either the same
671 * types as those given by the `Types` field
672 * of this `Tuple`, or can implicitly convert
673 * to those types. They must be in the same
674 * order as they appear in `Types`.
676 static if (Types.length > 0)
685 static if (Specs.length == 0) @safe unittest
687 alias ISD = Tuple!(int, string, double);
688 auto tup = ISD(1, "test", 3.2);
689 assert(tup.toString() == `Tuple!(int, string, double)(1, "test", 3.2)`);
693 * Constructor taking a compatible array.
696 * values = A compatible static array to build the `Tuple` from.
697 * Array slices are not supported.
699 this(U, size_t n)(U[n] values)
700 if (n == Types.length && allSatisfy!(isBuildableFrom!U, Types))
702 static foreach (i; 0 .. Types.length)
704 field[i] = values[i];
709 static if (Specs.length == 0) @safe unittest
712 Tuple!(int, int) t = ints;
716 * Constructor taking a compatible `Tuple`. Two `Tuple`s are compatible
717 * $(B iff) they are both of the same length, and, for each type `T` on the
718 * left-hand side, the corresponding type `U` on the right-hand side can
719 * implicitly convert to `T`.
722 * another = A compatible `Tuple` to build from. Its type must be
723 * compatible with the target `Tuple`'s type.
726 if (areBuildCompatibleTuples!(typeof(this), U))
728 field[] = another.field[];
732 static if (Specs.length == 0) @safe unittest
734 alias IntVec = Tuple!(int, int, int);
735 alias DubVec = Tuple!(double, double, double);
737 IntVec iv = tuple(1, 1, 1);
739 //Ok, int can implicitly convert to double
741 //Error: double cannot implicitly convert to int
746 * Comparison for equality. Two `Tuple`s are considered equal
747 * $(B iff) they fulfill the following criteria:
750 * $(LI Each `Tuple` is the same length.)
751 * $(LI For each type `T` on the left-hand side and each type
752 * `U` on the right-hand side, values of type `T` can be
753 * compared with values of type `U`.)
754 * $(LI For each value `v1` on the left-hand side and each value
755 * `v2` on the right-hand side, the expression `v1 == v2` is
759 * rhs = The `Tuple` to compare against. It must meeting the criteria
760 * for comparison between `Tuple`s.
763 * true if both `Tuple`s are equal, otherwise false.
765 bool opEquals(R)(R rhs)
766 if (areCompatibleTuples!(typeof(this), R, "=="))
768 return field[] == rhs.field[];
772 bool opEquals(R)(R rhs) const
773 if (areCompatibleTuples!(typeof(this), R, "=="))
775 return field[] == rhs.field[];
779 bool opEquals(R...)(auto ref R rhs)
780 if (R.length > 1 && areCompatibleTuples!(typeof(this), Tuple!R, "=="))
782 static foreach (i; 0 .. Types.length)
783 if (field[i] != rhs[i])
790 static if (Specs.length == 0) @safe unittest
792 Tuple!(int, string) t1 = tuple(1, "test");
793 Tuple!(double, string) t2 = tuple(1.0, "test");
794 //Ok, int can be compared with double and
795 //both have a value of 1
800 * Comparison for ordering.
803 * rhs = The `Tuple` to compare against. It must meet the criteria
804 * for comparison between `Tuple`s.
807 * For any values `v1` contained by the left-hand side tuple and any
808 * values `v2` contained by the right-hand side:
810 * 0 if `v1 == v2` for all members or the following value for the
811 * first position were the mentioned criteria is not satisfied:
814 * $(LI NaN, in case one of the operands is a NaN.)
815 * $(LI A negative number if the expression `v1 < v2` is true.)
816 * $(LI A positive number if the expression `v1 > v2` is true.))
819 if (areCompatibleTuples!(typeof(this), R, "<"))
821 static foreach (i; 0 .. Types.length)
823 if (field[i] != rhs.field[i])
825 import std.math.traits : isNaN;
826 static if (isFloatingPoint!(Types[i]))
831 static if (isFloatingPoint!(typeof(rhs.field[i])))
833 if (isNaN(rhs.field[i]))
836 static if (is(typeof(field[i].opCmp(rhs.field[i]))) &&
837 isFloatingPoint!(typeof(field[i].opCmp(rhs.field[i]))))
839 if (isNaN(field[i].opCmp(rhs.field[i])))
843 return field[i] < rhs.field[i] ? -1 : 1;
850 auto opCmp(R)(R rhs) const
851 if (areCompatibleTuples!(typeof(this), R, "<"))
853 static foreach (i; 0 .. Types.length)
855 if (field[i] != rhs.field[i])
857 import std.math.traits : isNaN;
858 static if (isFloatingPoint!(Types[i]))
863 static if (isFloatingPoint!(typeof(rhs.field[i])))
865 if (isNaN(rhs.field[i]))
868 static if (is(typeof(field[i].opCmp(rhs.field[i]))) &&
869 isFloatingPoint!(typeof(field[i].opCmp(rhs.field[i]))))
871 if (isNaN(field[i].opCmp(rhs.field[i])))
875 return field[i] < rhs.field[i] ? -1 : 1;
882 The first `v1` for which `v1 > v2` is true determines
883 the result. This could lead to unexpected behaviour.
885 static if (Specs.length == 0) @safe unittest
887 auto tup1 = tuple(1, 1, 1);
888 auto tup2 = tuple(1, 100, 100);
891 //Only the first result matters for comparison
898 Tuple concatenation is only allowed if all named fields are distinct (no named field of this tuple occurs in `t`
899 and no named field of `t` occurs in this tuple).
902 t = The `Tuple` to concatenate with
904 Returns: A concatenation of this tuple and `t`
906 auto opBinary(string op, T)(auto ref T t)
907 if (op == "~" && !(is(T : U[], U) && isTuple!U))
909 static if (isTuple!T)
911 static assert(distinctFieldNames!(_Fields, T._Fields),
912 "Cannot concatenate tuples with duplicate fields: " ~ fieldNames.stringof ~
913 " - " ~ T.fieldNames.stringof);
914 return Tuple!(_Fields, T._Fields)(expand, t.expand);
918 return Tuple!(_Fields, T)(expand, t);
923 auto opBinaryRight(string op, T)(auto ref T t)
924 if (op == "~" && !(is(T : U[], U) && isTuple!U))
926 static if (isTuple!T)
928 static assert(distinctFieldNames!(_Fields, T._Fields),
929 "Cannot concatenate tuples with duplicate fields: " ~ T.stringof ~
930 " - " ~ fieldNames.fieldNames.stringof);
931 return Tuple!(T._Fields, _Fields)(t.expand, expand);
935 return Tuple!(T, _Fields)(t, expand);
940 * Assignment from another `Tuple`.
943 * rhs = The source `Tuple` to assign from. Each element of the
944 * source `Tuple` must be implicitly assignable to each
945 * respective element of the target `Tuple`.
947 ref Tuple opAssign(R)(auto ref R rhs)
948 if (areCompatibleTuples!(typeof(this), R, "="))
950 import std.algorithm.mutation : swap;
952 static if (is(R : Tuple!Types) && !__traits(isRef, rhs) && isTuple!R)
956 // Cannot use swap at compile time
957 field[] = rhs.field[];
961 // Use swap-and-destroy to optimize rvalue assignment
962 swap!(Tuple!Types)(this, rhs);
967 // Do not swap; opAssign should be called on the fields.
968 field[] = rhs.field[];
974 * Renames the elements of a $(LREF Tuple).
976 * `rename` uses the passed `names` and returns a new
977 * $(LREF Tuple) using these names, with the content
979 * If fewer names are passed than there are members
980 * of the $(LREF Tuple) then those trailing members are unchanged.
981 * An empty string will remove the name for that member.
982 * It is an compile-time error to pass more names than
983 * there are members of the $(LREF Tuple).
985 ref rename(names...)() inout return
986 if (names.length == 0 || allSatisfy!(isSomeString, typeof(names)))
988 import std.algorithm.comparison : equal;
989 // to circumvent https://issues.dlang.org/show_bug.cgi?id=16418
990 static if (names.length == 0 || equal([names], [fieldNames]))
994 enum nT = Types.length;
995 enum nN = names.length;
996 static assert(nN <= nT, "Cannot have more names than tuple members");
997 alias allNames = AliasSeq!(names, fieldNames[nN .. $]);
999 import std.meta : Alias, aliasSeqOf;
1001 template GetItem(size_t idx)
1003 import std.array : empty;
1004 static if (idx < nT)
1005 alias GetItem = Alias!(Types[idx]);
1006 else static if (allNames[idx - nT].empty)
1007 alias GetItem = AliasSeq!();
1009 alias GetItem = Alias!(allNames[idx - nT]);
1012 import std.range : roundRobin, iota;
1013 alias NewTupleT = Tuple!(staticMap!(GetItem, aliasSeqOf!(
1014 roundRobin(iota(nT), iota(nT, 2*nT)))));
1015 return *(() @trusted => cast(NewTupleT*)&this)();
1020 static if (Specs.length == 0) @safe unittest
1022 auto t0 = tuple(4, "hello");
1024 auto t0Named = t0.rename!("val", "tag");
1025 assert(t0Named.val == 4);
1026 assert(t0Named.tag == "hello");
1028 Tuple!(float, "dat", size_t[2], "pos") t1;
1030 auto t1Named = t1.rename!"height";
1031 t1Named.height = 3.4f;
1032 assert(t1Named.height == 3.4f);
1033 assert(t1Named.pos == [2, 1]);
1034 t1Named.rename!"altitude".altitude = 5;
1035 assert(t1Named.height == 5);
1037 Tuple!(int, "a", int, int, "c") t2;
1039 auto t2Named = t2.rename!("", "b");
1040 // "a" no longer has a name
1041 static assert(!__traits(hasMember, typeof(t2Named), "a"));
1042 assert(t2Named[0] == 3);
1043 assert(t2Named.b == 4);
1044 assert(t2Named.c == 5);
1046 // not allowed to specify more names than the tuple has members
1047 static assert(!__traits(compiles, t2.rename!("a","b","c","d")));
1049 // use it in a range pipeline
1050 import std.range : iota, zip;
1051 import std.algorithm.iteration : map, sum;
1052 auto res = zip(iota(1, 4), iota(10, 13))
1053 .map!(t => t.rename!("a", "b"))
1054 .map!(t => t.a * t.b)
1058 const tup = Tuple!(int, "a", int, "b")(2, 3);
1059 const renamed = tup.rename!("c", "d");
1060 assert(renamed.c + renamed.d == 5);
1064 * Overload of $(LREF _rename) that takes an associative array
1065 * `translate` as a template parameter, where the keys are
1066 * either the names or indices of the members to be changed
1067 * and the new names are the corresponding values.
1068 * Every key in `translate` must be the name of a member of the
1070 * The same rules for empty strings apply as for the variadic
1071 * template overload of $(LREF _rename).
1073 ref rename(alias translate)() inout
1074 if (is(typeof(translate) : V[K], V, K) && isSomeString!V &&
1075 (isSomeString!K || is(K : size_t)))
1077 import std.meta : aliasSeqOf;
1078 import std.range : ElementType;
1079 static if (isSomeString!(ElementType!(typeof(translate.keys))))
1082 import std.conv : to;
1083 import std.algorithm.iteration : filter;
1084 import std.algorithm.searching : canFind;
1085 enum notFound = translate.keys
1086 .filter!(k => fieldNames.canFind(k) == -1);
1087 static assert(notFound.empty, "Cannot find members "
1088 ~ notFound.to!string ~ " in type "
1089 ~ typeof(this).stringof);
1091 return this.rename!(aliasSeqOf!(
1093 import std.array : empty;
1094 auto names = [fieldNames];
1095 foreach (ref n; names)
1097 if (auto p = n in translate)
1105 import std.algorithm.iteration : filter;
1106 import std.conv : to;
1107 enum invalid = translate.keys.
1108 filter!(k => k < 0 || k >= this.length);
1109 static assert(invalid.empty, "Indices " ~ invalid.to!string
1110 ~ " are out of bounds for tuple with length "
1111 ~ this.length.to!string);
1113 return this.rename!(aliasSeqOf!(
1115 auto names = [fieldNames];
1116 foreach (k, v; translate)
1124 static if (Specs.length == 0) @safe unittest
1126 //replacing names by their current name
1128 Tuple!(float, "dat", size_t[2], "pos") t1;
1130 auto t1Named = t1.rename!(["dat": "height"]);
1131 t1Named.height = 3.4;
1132 assert(t1Named.pos == [2, 1]);
1133 t1Named.rename!(["height": "altitude"]).altitude = 5;
1134 assert(t1Named.height == 5);
1136 Tuple!(int, "a", int, "b") t2;
1138 auto t2Named = t2.rename!(["a": "b", "b": "c"]);
1139 assert(t2Named.b == 3);
1140 assert(t2Named.c == 4);
1142 const t3 = Tuple!(int, "a", int, "b")(3, 4);
1143 const t3Named = t3.rename!(["a": "b", "b": "c"]);
1144 assert(t3Named.b == 3);
1145 assert(t3Named.c == 4);
1149 static if (Specs.length == 0) @system unittest
1151 //replace names by their position
1153 Tuple!(float, "dat", size_t[2], "pos") t1;
1155 auto t1Named = t1.rename!([0: "height"]);
1156 t1Named.height = 3.4;
1157 assert(t1Named.pos == [2, 1]);
1158 t1Named.rename!([0: "altitude"]).altitude = 5;
1159 assert(t1Named.height == 5);
1161 Tuple!(int, "a", int, "b", int, "c") t2;
1162 t2 = tuple(3, 4, 5);
1163 auto t2Named = t2.rename!([0: "c", 2: "a"]);
1164 assert(t2Named.a == 5);
1165 assert(t2Named.b == 4);
1166 assert(t2Named.c == 3);
1169 static if (Specs.length == 0) @system unittest
1171 //check that empty translations work fine
1172 enum string[string] a0 = null;
1173 enum string[int] a1 = null;
1174 Tuple!(float, "a", float, "b") t0;
1176 auto t1 = t0.rename!a0;
1180 auto t2 = t0.rename!a1;
1183 auto t3 = t0.rename;
1189 * Takes a slice by-reference of this `Tuple`.
1192 * from = A `size_t` designating the starting position of the slice.
1193 * to = A `size_t` designating the ending position (exclusive) of the slice.
1196 * A new `Tuple` that is a slice from `[from, to$(RPAREN)` of the original.
1197 * It has the same types and values as the range `[from, to$(RPAREN)` in
1201 ref inout(Tuple!(sliceSpecs!(from, to))) slice(size_t from, size_t to)() inout @trusted
1202 if (from <= to && to <= Types.length)
1205 (typeof(this).alignof % typeof(return).alignof == 0) &&
1206 (expand[from].offsetof % typeof(return).alignof == 0),
1207 "Slicing by reference is impossible because of an alignment mistmatch" ~
1208 " (See https://issues.dlang.org/show_bug.cgi?id=15645).");
1210 return *cast(typeof(return)*) &(field[from]);
1214 static if (Specs.length == 0) @safe unittest
1216 Tuple!(int, string, float, double) a;
1219 auto s = a.slice!(1, 3);
1220 static assert(is(typeof(s) == Tuple!(string, float)));
1221 assert(s[0] == "abc" && s[1] == 4.5);
1223 // https://issues.dlang.org/show_bug.cgi?id=15645
1224 Tuple!(int, short, bool, double) b;
1225 static assert(!__traits(compiles, b.slice!(2, 4)));
1229 Creates a hash of this `Tuple`.
1232 A `size_t` representing the hash of this `Tuple`.
1234 size_t toHash() const nothrow @safe
1237 static foreach (i, T; Types)
1239 static if (__traits(compiles, h = .hashOf(field[i])))
1240 const k = .hashOf(field[i]);
1243 // Workaround for when .hashOf is not both @safe and nothrow.
1244 static if (is(T : shared U, U) && __traits(compiles, (U* a) nothrow @safe => .hashOf(*a))
1245 && !__traits(hasMember, T, "toHash"))
1246 // BUG: Improperly casts away `shared`!
1247 const k = .hashOf(*(() @trusted => cast(U*) &field[i])());
1249 // BUG: Improperly casts away `shared`!
1250 const k = typeid(T).getHash((() @trusted => cast(const void*) &field[i])());
1255 // As in boost::hash_combine
1256 // https://www.boost.org/doc/libs/1_55_0/doc/html/hash/reference.html#boost.hash_combine
1257 h ^= k + 0x9e3779b9 + (h << 6) + (h >>> 2);
1263 * Converts to string.
1266 * The string representation of this `Tuple`.
1268 string toString()() const
1270 import std.array : appender;
1271 auto app = appender!string();
1272 this.toString((const(char)[] chunk) => app ~= chunk);
1276 import std.format.spec : FormatSpec;
1279 * Formats `Tuple` with either `%s`, `%(inner%)` or `%(inner%|sep%)`.
1281 * $(TABLE2 Formats supported by Tuple,
1282 * $(THEAD Format, Description)
1283 * $(TROW $(P `%s`), $(P Format like `Tuple!(types)(elements formatted with %s each)`.))
1284 * $(TROW $(P `%(inner%)`), $(P The format `inner` is applied the expanded `Tuple`$(COMMA) so
1285 * it may contain as many formats as the `Tuple` has fields.))
1286 * $(TROW $(P `%(inner%|sep%)`), $(P The format `inner` is one format$(COMMA) that is applied
1287 * on all fields of the `Tuple`. The inner format must be compatible to all
1291 * sink = A `char` accepting delegate
1292 * fmt = A $(REF FormatSpec, std,format)
1294 void toString(DG)(scope DG sink) const
1296 auto f = FormatSpec!char();
1301 void toString(DG, Char)(scope DG sink, scope const ref FormatSpec!Char fmt) const
1303 import std.format : format, FormatException;
1304 import std.format.write : formattedWrite;
1305 import std.range : only;
1310 foreach (i, Type; Types)
1316 // TODO: Change this once formattedWrite() works for shared objects.
1317 static if (is(Type == class) && is(Type == shared))
1319 sink(Type.stringof);
1323 formattedWrite(sink, fmt.nested, this.field[i]);
1329 formattedWrite(sink, fmt.nested, staticMap!(sharedToString, this.expand));
1332 else if (fmt.spec == 's')
1334 enum header = Unqual!(typeof(this)).stringof ~ "(",
1338 foreach (i, Type; Types)
1344 // TODO: Change this once format() works for shared objects.
1345 static if (is(Type == class) && is(Type == shared))
1347 sink(Type.stringof);
1351 sink(format!("%(%s%)")(only(field[i])));
1358 const spec = fmt.spec;
1359 throw new FormatException(
1360 "Expected '%s' or '%(...%)' or '%(...%|...%)' format specifier for type '" ~
1361 Unqual!(typeof(this)).stringof ~ "', not '%" ~ spec ~ "'.");
1366 static if (Specs.length == 0) @safe unittest
1368 import std.format : format;
1370 Tuple!(int, double)[3] tupList = [ tuple(1, 1.0), tuple(2, 4.0), tuple(3, 9.0) ];
1373 assert(format("%s", tuple("a", 1)) == `Tuple!(string, int)("a", 1)`);
1375 // One Format for each individual component
1376 assert(format("%(%#x v %.4f w %#x%)", tuple(1, 1.0, 10)) == `0x1 v 1.0000 w 0xa`);
1377 assert(format( "%#x v %.4f w %#x" , tuple(1, 1.0, 10).expand) == `0x1 v 1.0000 w 0xa`);
1379 // One Format for all components
1380 assert(format("%(>%s<%| & %)", tuple("abc", 1, 2.3, [4, 5])) == `>abc< & >1< & >2.3< & >[4, 5]<`);
1383 assert(format("%(%(f(%d) = %.1f%); %)", tupList) == `f(1) = 1.0; f(2) = 4.0; f(3) = 9.0`);
1387 static if (Specs.length == 0) @safe unittest
1389 import std.exception : assertThrown;
1390 import std.format : format, FormatException;
1392 // Error: %( %) missing.
1393 assertThrown!FormatException(
1394 format("%d, %f", tuple(1, 2.0)) == `1, 2.0`
1397 // Error: %( %| %) missing.
1398 assertThrown!FormatException(
1399 format("%d", tuple(1, 2)) == `1, 2`
1402 // Error: %d inadequate for double
1403 assertThrown!FormatException(
1404 format("%(%d%|, %)", tuple(1, 2.0)) == `1, 2.0`
1413 Tuple!(int, int) point;
1414 // assign coordinates
1423 `Tuple` members can be named. It is legal to mix named and unnamed
1424 members. The method above is still applicable to all fields.
1428 alias Entry = Tuple!(int, "index", string, "value");
1432 assert(e[1] == "Hello");
1437 A `Tuple` with named fields is a distinct type from a `Tuple` with unnamed
1438 fields, i.e. each naming imparts a separate type for the `Tuple`. Two
1439 `Tuple`s differing in naming only are still distinct, even though they
1440 might have the same structure.
1444 Tuple!(int, "x", int, "y") point1;
1445 Tuple!(int, int) point2;
1446 assert(!is(typeof(point1) == typeof(point2)));
1449 /// Use tuples as ranges
1452 import std.algorithm.iteration : sum;
1453 import std.range : only;
1454 auto t = tuple(1, 2);
1455 assert(t.expand.only.sum == 3);
1458 // https://issues.dlang.org/show_bug.cgi?id=4582
1461 static assert(!__traits(compiles, Tuple!(string, "id", int, "id")));
1462 static assert(!__traits(compiles, Tuple!(string, "str", int, "i", string, "str", float)));
1465 /// Concatenate tuples
1468 import std.meta : AliasSeq;
1469 auto t = tuple(1, "2") ~ tuple(ushort(42), true);
1470 static assert(is(t.Types == AliasSeq!(int, string, ushort, bool)));
1471 assert(t[1] == "2");
1473 assert(t[3] == true);
1476 // https://issues.dlang.org/show_bug.cgi?id=14637
1480 auto t = tuple!"foo"(1.0) ~ tuple!"bar"("3");
1481 static assert(is(t.Types == AliasSeq!(double, string)));
1482 static assert(t.fieldNames == tuple("foo", "bar"));
1483 assert(t.foo == 1.0);
1484 assert(t.bar == "3");
1487 // https://issues.dlang.org/show_bug.cgi?id=18824
1491 alias Type = Tuple!(int, string);
1493 auto t = tuple(2, "s");
1494 // Test opBinaryRight
1498 static assert(is(typeof(arr) == Type[]));
1501 static assert(is(typeof(c) == immutable(Type)[]));
1507 auto t = tuple!"foo"(1.0) ~ "3";
1508 static assert(is(t.Types == AliasSeq!(double, string)));
1509 assert(t.foo == 1.0);
1516 auto t = "2" ~ tuple!"foo"(1.0);
1517 static assert(is(t.Types == AliasSeq!(string, double)));
1518 assert(t.foo == 1.0);
1525 auto t = "2" ~ tuple!"foo"(1.0) ~ tuple(42, 3.0f) ~ real(1) ~ "a";
1526 static assert(is(t.Types == AliasSeq!(string, double, int, float, real, string)));
1527 assert(t.foo == 1.0);
1528 assert(t[0] == "2");
1529 assert(t[1] == 1.0);
1531 assert(t[3] == 3.0f);
1532 assert(t[4] == 1.0);
1533 assert(t[5] == "a");
1536 // ensure that concatenation of tuples with non-distinct fields is forbidden
1539 static assert(!__traits(compiles,
1540 tuple!("a")(0) ~ tuple!("a")("1")));
1541 static assert(!__traits(compiles,
1542 tuple!("a", "b")(0, 1) ~ tuple!("b", "a")("3", 1)));
1543 static assert(!__traits(compiles,
1544 tuple!("a")(0) ~ tuple!("b", "a")("3", 1)));
1545 static assert(!__traits(compiles,
1546 tuple!("a1", "a")(1.0, 0) ~ tuple!("a2", "a")("3", 0)));
1549 // Ensure that Tuple comparison with non-const opEquals works
1556 bool opEquals(Bad b)
1562 auto t = Tuple!(int, Bad, string)(1, Bad(1), "asdf");
1564 //Error: mutable method Bad.opEquals is not callable using a const object
1565 assert(t == AliasSeq!(1, Bad(1), "asdf"));
1568 // Ensure Tuple.toHash works
1571 Tuple!(int, int) point;
1572 assert(point.toHash == typeof(point).init.toHash);
1573 assert(tuple(1, 2) != point);
1574 assert(tuple(1, 2) == tuple(1, 2));
1576 assert(tuple(1, 2) != point);
1578 assert(tuple(1, 2) == point);
1581 @safe @betterC unittest
1583 auto t = tuple(1, 2);
1584 assert(t == tuple(1, 2));
1585 auto t3 = tuple(1, 'd');
1588 // https://issues.dlang.org/show_bug.cgi?id=20850
1589 // Assignment to enum tuple
1592 enum T : Tuple!(int*) { a = T(null) }
1597 // https://issues.dlang.org/show_bug.cgi?id=13663
1600 auto t = tuple(real.nan);
1610 float opCmp(S s) { return float.nan; }
1611 bool opEquals(S s) { return false; }
1614 auto t = tuple(S());
1620 // https://issues.dlang.org/show_bug.cgi?id=8015
1626 @property string toStr()
1637 Creates a copy of a $(LREF Tuple) with its fields in _reverse order.
1640 t = The `Tuple` to copy.
1645 auto reverse(T)(T t)
1648 import std.meta : Reverse;
1649 // @@@BUG@@@ Cannot be an internal function due to forward reference issues.
1651 // @@@BUG@@@ 9929 Need 'this' when calling template with expanded tuple
1652 // return tuple(Reverse!(t.expand));
1654 ReverseTupleType!T result;
1655 auto tup = t.expand;
1656 result.expand = Reverse!tup;
1663 auto tup = tuple(1, "2");
1664 assert(tup.reverse == tuple("2", 1));
1667 /* Get a Tuple type with the reverse specification of Tuple T. */
1668 private template ReverseTupleType(T)
1671 static if (is(T : Tuple!A, A...))
1672 alias ReverseTupleType = Tuple!(ReverseTupleSpecs!A);
1675 /* Reverse the Specs of a Tuple. */
1676 private template ReverseTupleSpecs(T...)
1678 static if (T.length > 1)
1680 static if (is(typeof(T[$-1]) : string))
1682 alias ReverseTupleSpecs = AliasSeq!(T[$-2], T[$-1], ReverseTupleSpecs!(T[0 .. $-2]));
1686 alias ReverseTupleSpecs = AliasSeq!(T[$-1], ReverseTupleSpecs!(T[0 .. $-1]));
1691 alias ReverseTupleSpecs = T;
1695 // ensure that internal Tuple unittests are compiled
1705 Tuple!(int, "a", int, "b") nosh;
1706 static assert(nosh.length == 2);
1709 assert(nosh.a == 5);
1710 assert(nosh.b == 6);
1713 Tuple!(short, double) b;
1714 static assert(b.length == 2);
1716 auto a = Tuple!(int, real)(b);
1717 assert(a[0] == 0 && a[1] == 5);
1718 a = Tuple!(int, real)(1, 2);
1719 assert(a[0] == 1 && a[1] == 2);
1720 auto c = Tuple!(int, "a", double, "b")(a);
1721 assert(c[0] == 1 && c[1] == 2);
1724 Tuple!(int, real) nosh;
1727 assert(nosh[0] == 5 && nosh[1] == 0);
1728 assert(nosh.to!string == "Tuple!(int, real)(5, 0)", nosh.to!string);
1729 Tuple!(int, int) yessh;
1734 Tuple!(int, shared A) nosh;
1736 assert(nosh[0] == 5 && nosh[1] is null);
1737 assert(nosh.to!string == "Tuple!(int, shared(A))(5, shared(A))");
1740 Tuple!(int, string) t;
1743 assert(t[0] == 10 && t[1] == "str");
1744 assert(t.to!string == `Tuple!(int, string)(10, "str")`, t.to!string);
1747 Tuple!(int, "a", double, "b") x;
1748 static assert(x.a.offsetof == x[0].offsetof);
1749 static assert(x.b.offsetof == x[1].offsetof);
1752 assert(x[0] == 5 && x[1] == 4.5);
1753 assert(x.a == 5 && x.b == 4.5);
1757 Tuple!(int, real) t;
1758 static assert(is(typeof(t[0]) == int));
1759 static assert(is(typeof(t[1]) == real));
1764 assert(*p0 == t[0]);
1765 assert(*p1 == t[1]);
1769 Tuple!(int, "x", real, "y", double, "z", string) t;
1774 auto a = t.slice!(0, 3);
1775 assert(a.length == 3);
1779 auto b = t.slice!(2, 4);
1780 assert(b.length == 2);
1782 assert(b[1] == t[3]);
1786 Tuple!(Tuple!(int, real), Tuple!(string, "s")) t;
1787 static assert(is(typeof(t[0]) == Tuple!(int, real)));
1788 static assert(is(typeof(t[1]) == Tuple!(string, "s")));
1789 static assert(is(typeof(t[0][0]) == int));
1790 static assert(is(typeof(t[0][1]) == real));
1791 static assert(is(typeof(t[1].s) == string));
1792 t[0] = tuple(10, 20.0L);
1794 assert(t[0][0] == 10);
1795 assert(t[0][1] == 20.0L);
1796 assert(t[1].s == "abc");
1803 this(this) { ++count; }
1804 ~this() { --count; }
1805 void opAssign(S rhs) { count = rhs.count; }
1808 Tuple!(S, S) ssCopy = ss;
1809 assert(ssCopy[0].count == 1);
1810 assert(ssCopy[1].count == 1);
1811 ssCopy[1] = ssCopy[0];
1812 assert(ssCopy[1].count == 2);
1814 // https://issues.dlang.org/show_bug.cgi?id=2800
1818 Tuple!(int, int) _front;
1819 @property ref Tuple!(int, int) front() return { return _front; }
1820 @property bool empty() { return _front[0] >= 10; }
1821 void popFront() { ++_front[0]; }
1825 static assert(is(typeof(a) == Tuple!(int, int)));
1826 assert(0 <= a[0] && a[0] < 10);
1830 // Construction with compatible elements
1832 auto t1 = Tuple!(int, double)(1, 1);
1834 // https://issues.dlang.org/show_bug.cgi?id=8702
1835 auto t8702a = tuple(tuple(1));
1836 auto t8702b = Tuple!(Tuple!(int))(Tuple!(int)(1));
1838 // Construction with compatible tuple
1843 Tuple!(int, "a", double, "b") y = x;
1847 static assert(!__traits(compiles, Tuple!(int, int)(y)));
1849 // https://issues.dlang.org/show_bug.cgi?id=6275
1853 alias T = Tuple!(const(int));
1856 // https://issues.dlang.org/show_bug.cgi?id=9431
1858 alias T = Tuple!(int[1][]);
1861 // https://issues.dlang.org/show_bug.cgi?id=7666
1863 auto tup = tuple(1, "2");
1864 assert(tup.reverse == tuple("2", 1));
1867 Tuple!(int, "x", string, "y") tup = tuple(1, "2");
1868 auto rev = tup.reverse;
1869 assert(rev == tuple("2", 1));
1870 assert(rev.x == 1 && rev.y == "2");
1873 Tuple!(wchar, dchar, int, "x", string, "y", char, byte, float) tup;
1874 tup = tuple('a', 'b', 3, "4", 'c', cast(byte) 0x0D, 0.00);
1875 auto rev = tup.reverse;
1876 assert(rev == tuple(0.00, cast(byte) 0x0D, 'c', "4", 3, 'b', 'a'));
1877 assert(rev.x == 3 && rev.y == "4");
1884 struct Equ1 { bool opEquals(Equ1) { return true; } }
1885 auto tm1 = tuple(Equ1.init);
1886 const tc1 = tuple(Equ1.init);
1887 static assert( is(typeof(tm1 == tm1)));
1888 static assert(!is(typeof(tm1 == tc1)));
1889 static assert(!is(typeof(tc1 == tm1)));
1890 static assert(!is(typeof(tc1 == tc1)));
1892 struct Equ2 { bool opEquals(const Equ2) const { return true; } }
1893 auto tm2 = tuple(Equ2.init);
1894 const tc2 = tuple(Equ2.init);
1895 static assert( is(typeof(tm2 == tm2)));
1896 static assert( is(typeof(tm2 == tc2)));
1897 static assert( is(typeof(tc2 == tm2)));
1898 static assert( is(typeof(tc2 == tc2)));
1900 // https://issues.dlang.org/show_bug.cgi?id=8686
1901 struct Equ3 { bool opEquals(T)(T) { return true; } }
1902 auto tm3 = tuple(Equ3.init);
1903 const tc3 = tuple(Equ3.init);
1904 static assert( is(typeof(tm3 == tm3)));
1905 static assert( is(typeof(tm3 == tc3)));
1906 static assert(!is(typeof(tc3 == tm3)));
1907 static assert(!is(typeof(tc3 == tc3)));
1909 struct Equ4 { bool opEquals(T)(T) const { return true; } }
1910 auto tm4 = tuple(Equ4.init);
1911 const tc4 = tuple(Equ4.init);
1912 static assert( is(typeof(tm4 == tm4)));
1913 static assert( is(typeof(tm4 == tc4)));
1914 static assert( is(typeof(tc4 == tm4)));
1915 static assert( is(typeof(tc4 == tc4)));
1919 struct Cmp1 { int opCmp(Cmp1) { return 0; } }
1920 auto tm1 = tuple(Cmp1.init);
1921 const tc1 = tuple(Cmp1.init);
1922 static assert( is(typeof(tm1 < tm1)));
1923 static assert(!is(typeof(tm1 < tc1)));
1924 static assert(!is(typeof(tc1 < tm1)));
1925 static assert(!is(typeof(tc1 < tc1)));
1927 struct Cmp2 { int opCmp(const Cmp2) const { return 0; } }
1928 auto tm2 = tuple(Cmp2.init);
1929 const tc2 = tuple(Cmp2.init);
1930 static assert( is(typeof(tm2 < tm2)));
1931 static assert( is(typeof(tm2 < tc2)));
1932 static assert( is(typeof(tc2 < tm2)));
1933 static assert( is(typeof(tc2 < tc2)));
1935 struct Cmp3 { int opCmp(T)(T) { return 0; } }
1936 auto tm3 = tuple(Cmp3.init);
1937 const tc3 = tuple(Cmp3.init);
1938 static assert( is(typeof(tm3 < tm3)));
1939 static assert( is(typeof(tm3 < tc3)));
1940 static assert(!is(typeof(tc3 < tm3)));
1941 static assert(!is(typeof(tc3 < tc3)));
1943 struct Cmp4 { int opCmp(T)(T) const { return 0; } }
1944 auto tm4 = tuple(Cmp4.init);
1945 const tc4 = tuple(Cmp4.init);
1946 static assert( is(typeof(tm4 < tm4)));
1947 static assert( is(typeof(tm4 < tc4)));
1948 static assert( is(typeof(tc4 < tm4)));
1949 static assert( is(typeof(tc4 < tc4)));
1951 // https://issues.dlang.org/show_bug.cgi?id=14890
1952 static void test14890(inout int[] dummy)
1954 alias V = Tuple!(int, int);
1959 inout V wv; // OK <- NG
1960 inout const V wcv; // OK <- NG
1962 static foreach (v1; AliasSeq!(mv, cv, iv, wv, wcv))
1963 static foreach (v2; AliasSeq!(mv, cv, iv, wv, wcv))
1969 int[2] ints = [ 1, 2 ];
1970 Tuple!(int, int) t = ints;
1971 assert(t[0] == 1 && t[1] == 2);
1972 Tuple!(long, uint) t2 = ints;
1973 assert(t2[0] == 1 && t2[1] == 2);
1978 auto t1 = Tuple!(int, "x", string, "y")(1, "a");
1980 assert(t1.y == "a");
1981 void foo(Tuple!(int, string) t2) {}
1984 Tuple!(int, int)[] arr;
1985 arr ~= tuple(10, 20); // OK
1986 arr ~= Tuple!(int, "x", int, "y")(10, 20); // NG -> OK
1988 static assert(is(typeof(Tuple!(int, "x", string, "y").tupleof) ==
1989 typeof(Tuple!(int, string ).tupleof)));
1993 // https://issues.dlang.org/show_bug.cgi?id=10686
1994 immutable Tuple!(int) t1;
1995 auto r1 = t1[0]; // OK
1996 immutable Tuple!(int, "x") t2;
1997 auto r2 = t2[0]; // error
2001 import std.exception : assertCTFEable;
2003 // https://issues.dlang.org/show_bug.cgi?id=10218
2007 t = tuple(2); // assignment
2013 Tuple!(immutable(Foo)[]) a;
2018 //Test non-assignable
2023 alias IS = immutable S;
2024 static assert(!isAssignable!IS);
2028 alias TIS = Tuple!IS;
2032 alias TISIS = Tuple!(IS, IS);
2033 TISIS d = tuple(s, s);
2035 TISIS e = TISIS(ss);
2038 // https://issues.dlang.org/show_bug.cgi?id=9819
2041 alias T = Tuple!(int, "x", double, "foo");
2042 static assert(T.fieldNames[0] == "x");
2043 static assert(T.fieldNames[1] == "foo");
2045 alias Fields = Tuple!(int, "id", string, float);
2046 static assert(Fields.fieldNames == AliasSeq!("id", "", ""));
2049 // https://issues.dlang.org/show_bug.cgi?id=13837
2052 // New behaviour, named arguments.
2054 typeof(tuple!("x")(1)) == Tuple!(int, "x")));
2056 typeof(tuple!("x")(1.0)) == Tuple!(double, "x")));
2058 typeof(tuple!("x")("foo")) == Tuple!(string, "x")));
2060 typeof(tuple!("x", "y")(1, 2.0)) == Tuple!(int, "x", double, "y")));
2062 auto a = tuple!("a", "b", "c")("1", 2, 3.0f);
2063 static assert(is(typeof(a.a) == string));
2064 static assert(is(typeof(a.b) == int));
2065 static assert(is(typeof(a.c) == float));
2067 // Old behaviour, but with explicit type parameters.
2069 typeof(tuple!(int, double)(1, 2.0)) == Tuple!(int, double)));
2071 typeof(tuple!(const int)(1)) == Tuple!(const int)));
2073 typeof(tuple()) == Tuple!()));
2075 // Nonsensical behaviour
2076 static assert(!__traits(compiles, tuple!(1)(2)));
2077 static assert(!__traits(compiles, tuple!("x")(1, 2)));
2078 static assert(!__traits(compiles, tuple!("x", "y")(1)));
2079 static assert(!__traits(compiles, tuple!("x")()));
2080 static assert(!__traits(compiles, tuple!("x", int)(2)));
2085 class C { override size_t toHash() const nothrow @safe { return 0; } }
2086 Tuple!(Rebindable!(const C)) a;
2091 @nogc @safe unittest
2093 alias T = Tuple!(string, "s");
2100 import std.format : format, FormatException;
2101 import std.exception : assertThrown;
2103 //enum tupStr = tuple(1, 1.0).toString; // toString is *impure*.
2104 //static assert(tupStr == `Tuple!(int, double)(1, 1)`);
2107 // https://issues.dlang.org/show_bug.cgi?id=17803, parte uno
2110 auto a = tuple(3, "foo");
2111 assert(__traits(compiles, { a = (a = a); }));
2116 Tuple!(int[]) a, b, c;
2117 a = tuple([0, 1, 2]);
2119 assert(a[0].length == b[0].length && b[0].length == c[0].length);
2120 assert(a[0].ptr == b[0].ptr && b[0].ptr == c[0].ptr);
2124 Constructs a $(LREF Tuple) object instantiated and initialized according to
2125 the given arguments.
2128 Names = An optional list of strings naming each successive field of the `Tuple`
2129 or a list of types that the elements are being casted to.
2130 For a list of names,
2131 each name matches up with the corresponding field given by `Args`.
2132 A name does not have to be provided for every field, but as
2133 the names must proceed in order, it is not possible to skip
2134 one field and name the next after it.
2135 For a list of types,
2136 there must be exactly as many types as parameters.
2138 template tuple(Names...)
2142 args = Values to initialize the `Tuple` with. The `Tuple`'s type will
2143 be inferred from the types of the values given.
2146 A new `Tuple` with its type inferred from the arguments given.
2148 auto tuple(Args...)(Args args)
2150 static if (Names.length == 0)
2152 // No specified names, just infer types from Args...
2153 return Tuple!Args(args);
2155 else static if (!is(typeof(Names[0]) : string))
2157 // Names[0] isn't a string, must be explicit types.
2158 return Tuple!Names(args);
2162 // Names[0] is a string, so must be specifying names.
2163 static assert(Names.length == Args.length,
2164 "Insufficient number of names given.");
2166 // Interleave(a, b).and(c, d) == (a, c, b, d)
2167 // This is to get the interleaving of types and names for Tuple
2168 // e.g. Tuple!(int, "x", string, "y")
2169 template Interleave(A...)
2171 template and(B...) if (B.length == 1)
2173 alias and = AliasSeq!(A[0], B[0]);
2176 template and(B...) if (B.length != 1)
2178 alias and = AliasSeq!(A[0], B[0],
2179 Interleave!(A[1..$]).and!(B[1..$]));
2182 return Tuple!(Interleave!(Args).and!(Names))(args);
2190 auto value = tuple(5, 6.7, "hello");
2191 assert(value[0] == 5);
2192 assert(value[1] == 6.7);
2193 assert(value[2] == "hello");
2195 // Field names can be provided.
2196 auto entry = tuple!("index", "value")(4, "Hello");
2197 assert(entry.index == 4);
2198 assert(entry.value == "Hello");
2202 Returns `true` if and only if `T` is an instance of `std.typecons.Tuple`.
2205 T = The type to check.
2208 true if `T` is a `Tuple` type, false otherwise.
2210 enum isTuple(T) = __traits(compiles,
2212 void f(Specs...)(Tuple!Specs tup) {}
2219 static assert(isTuple!(Tuple!()));
2220 static assert(isTuple!(Tuple!(int)));
2221 static assert(isTuple!(Tuple!(int, real, string)));
2222 static assert(isTuple!(Tuple!(int, "x", real, "y")));
2223 static assert(isTuple!(Tuple!(int, Tuple!(real), string)));
2228 static assert(isTuple!(const Tuple!(int)));
2229 static assert(isTuple!(immutable Tuple!(int)));
2231 static assert(!isTuple!(int));
2232 static assert(!isTuple!(const int));
2235 static assert(!isTuple!(S));
2238 // used by both Rebindable and UnqualRef
2239 private mixin template RebindableCommon(T, U, alias This)
2240 if (is(T == class) || is(T == interface) || isAssociativeArray!T)
2248 void opAssign(return scope T another) pure nothrow @nogc
2250 // If `T` defines `opCast` we must infer the safety
2251 static if (hasMember!(T, "opCast"))
2253 // This will allow the compiler to infer the safety of `T.opCast!U`
2254 // without generating any runtime cost
2255 if (false) { stripped = cast(U) another; }
2257 () @trusted { stripped = cast(U) another; }();
2260 void opAssign(typeof(this) another) @trusted pure nothrow @nogc
2262 stripped = another.stripped;
2265 static if (is(T == const U) && is(T == const shared U))
2267 // safely assign immutable to const / const shared
2268 void opAssign(This!(immutable U) another) @trusted pure nothrow @nogc
2270 stripped = another.stripped;
2274 this(T initializer) pure nothrow @nogc
2276 // Infer safety from opAssign
2277 opAssign(initializer);
2280 @property inout(T) get() @trusted pure nothrow @nogc return scope inout
2285 bool opEquals()(auto ref const(typeof(this)) rhs) const
2287 // Must forward explicitly because 'stripped' is part of a union.
2288 // The necessary 'toHash' is forwarded to the class via alias this.
2289 return stripped == rhs.stripped;
2292 bool opEquals(const(U) rhs) const
2294 return stripped == rhs;
2301 `Rebindable!(T)` is a simple, efficient wrapper that behaves just
2302 like an object of type `T`, except that you can reassign it to
2303 refer to another object. For completeness, `Rebindable!(T)` aliases
2304 itself away to `T` if `T` is a non-const object type.
2306 You may want to use `Rebindable` when you want to have mutable
2307 storage referring to `const` objects, for example an array of
2308 references that must be sorted in place. `Rebindable` does not
2309 break the soundness of D's type system and does not incur any of the
2310 risks usually associated with `cast`.
2313 T = An object, interface, array slice type, or associative array type.
2315 template Rebindable(T)
2316 if (is(T == class) || is(T == interface) || isDynamicArray!T || isAssociativeArray!T)
2318 static if (is(T == const U, U) || is(T == immutable U, U))
2320 static if (isDynamicArray!T)
2322 import std.range.primitives : ElementEncodingType;
2323 alias Rebindable = const(ElementEncodingType!T)[];
2329 mixin RebindableCommon!(T, U, Rebindable);
2335 alias Rebindable = T;
2339 ///Regular `const` object references cannot be reassigned.
2342 class Widget { int x; int y() @safe const { return x; } }
2343 const a = new Widget;
2346 // error! can't modify const a
2348 // error! can't modify const a
2353 However, `Rebindable!(Widget)` does allow reassignment,
2354 while otherwise behaving exactly like a $(D const Widget).
2358 class Widget { int x; int y() const @safe { return x; } }
2359 auto a = Rebindable!(const Widget)(new Widget);
2362 // error! can't modify const a
2368 // https://issues.dlang.org/show_bug.cgi?id=16054
2371 Rebindable!(immutable Object) r;
2372 static assert(__traits(compiles, r.get()));
2373 static assert(!__traits(compiles, &r.get()));
2380 override size_t toHash() const nothrow @trusted { return 42; }
2382 Rebindable!(immutable(CustomToHash)) a = new immutable CustomToHash();
2383 assert(a.toHash() == 42, "Rebindable!A should offer toHash()"
2384 ~ " by forwarding to A.toHash().");
2387 // https://issues.dlang.org/show_bug.cgi?id=18615
2388 // Rebindable!A should use A.opEqualsa
2394 override bool opEquals(Object rhsObj)
2396 if (auto rhs = cast(const(CustomOpEq)) rhsObj)
2397 return this.x == rhs.x;
2402 CustomOpEq a = new CustomOpEq();
2403 CustomOpEq b = new CustomOpEq();
2405 assert(a == b, "a.x == b.x should be true (0 == 0).");
2407 Rebindable!(const(CustomOpEq)) ra = a;
2408 Rebindable!(const(CustomOpEq)) rb = b;
2410 assert(ra == rb, "Rebindable should use CustomOpEq's opEquals, not 'is'.");
2411 assert(ra == b, "Rebindable!(someQualifier(A)) should be comparable"
2412 ~ " against const(A) via A.opEquals.");
2413 assert(a == rb, "Rebindable!(someQualifier(A)) should be comparable"
2414 ~ " against const(A) via A.opEquals.");
2418 assert(ra != b, "Rebindable!(someQualifier(A)) should be comparable"
2419 ~ " against const(A) via A.opEquals.");
2420 assert(a != rb, "Rebindable!(someQualifier(A)) should be comparable"
2421 ~ " against const(A) via A.opEquals.");
2423 Rebindable!(const(Object)) o1 = new Object();
2424 Rebindable!(const(Object)) o2 = new Object();
2426 assert(o1 == o1, "When the class doesn't provide its own opEquals,"
2427 ~ " Rebindable treats 'a == b' as 'a is b' like Object.opEquals.");
2428 assert(o1 != o2, "When the class doesn't provide its own opEquals,"
2429 ~ " Rebindable treats 'a == b' as 'a is b' like Object.opEquals.");
2430 assert(o1 != new Object(), "Rebindable!(const(Object)) should be"
2431 ~ " comparable against Object itself and use Object.opEquals.");
2434 // https://issues.dlang.org/show_bug.cgi?id=18755
2439 auto opCast(T)() @system immutable pure nothrow
2441 *(cast(uint*) 0xdeadbeef) = 0xcafebabe;
2446 static assert(!__traits(compiles, () @safe {
2447 auto r = Rebindable!(immutable Foo)(new Foo);
2449 static assert(__traits(compiles, () @system {
2450 auto r = Rebindable!(immutable Foo)(new Foo);
2455 Convenience function for creating a `Rebindable` using automatic type
2459 obj = A reference to an object, interface, associative array, or an array slice
2460 to initialize the `Rebindable` with.
2463 A newly constructed `Rebindable` initialized with the given reference.
2465 Rebindable!T rebindable(T)(T obj)
2466 if (is(T == class) || is(T == interface) || isDynamicArray!T || isAssociativeArray!T)
2479 this(int p) { payload = p; }
2483 auto c2 = c.rebindable;
2484 assert(c2.payload == 1);
2485 // passing Rebindable to rebindable
2489 assert(c2.payload == 2);
2492 assert(c3.payload == 2);
2496 This function simply returns the `Rebindable` object passed in. It's useful
2497 in generic programming cases when a given object may be either a regular
2498 `class` or a `Rebindable`.
2501 obj = An instance of Rebindable!T.
2504 `obj` without any modification.
2506 Rebindable!T rebindable(T)(Rebindable!T obj)
2511 // TODO: remove me once the rebindable overloads have been joined
2518 this(int p) { payload = p; }
2522 auto c2 = c.rebindable;
2523 assert(c2.payload == 1);
2524 // passing Rebindable to rebindable
2526 assert(c2.payload == 1);
2531 interface CI { int foo() const; }
2533 int foo() const { return 42; }
2534 @property int bar() const { return 23; }
2536 Rebindable!(C) obj0;
2537 static assert(is(typeof(obj0) == C));
2539 Rebindable!(const(C)) obj1;
2540 static assert(is(typeof(obj1.get) == const(C)), typeof(obj1.get).stringof);
2541 static assert(is(typeof(obj1.stripped) == C));
2543 assert(obj1.get !is null);
2544 obj1 = new const(C);
2545 assert(obj1.get !is null);
2547 Rebindable!(immutable(C)) obj2;
2548 static assert(is(typeof(obj2.get) == immutable(C)));
2549 static assert(is(typeof(obj2.stripped) == C));
2550 obj2 = new immutable(C);
2551 assert(obj1.get !is null);
2554 assert(obj2.foo() == 42);
2555 assert(obj2.bar == 23);
2557 interface I { final int foo() const { return 42; } }
2558 Rebindable!(I) obj3;
2559 static assert(is(typeof(obj3) == I));
2561 Rebindable!(const I) obj4;
2562 static assert(is(typeof(obj4.get) == const I));
2563 static assert(is(typeof(obj4.stripped) == I));
2564 static assert(is(typeof(obj4.foo()) == int));
2565 obj4 = new class I {};
2567 Rebindable!(immutable C) obj5i;
2568 Rebindable!(const C) obj5c;
2572 static assert(!__traits(compiles, obj5i = obj5c));
2574 // Test the convenience functions.
2575 auto obj5convenience = rebindable(obj5i);
2576 assert(obj5convenience is obj5i);
2578 auto obj6 = rebindable(new immutable(C));
2579 static assert(is(typeof(obj6) == Rebindable!(immutable C)));
2580 assert(obj6.foo() == 42);
2582 auto obj7 = rebindable(new C);
2583 CI interface1 = obj7;
2584 auto interfaceRebind1 = rebindable(interface1);
2585 assert(interfaceRebind1.foo() == 42);
2587 const interface2 = interface1;
2588 auto interfaceRebind2 = rebindable(interface2);
2589 assert(interfaceRebind2.foo() == 42);
2591 auto arr = [1,2,3,4,5];
2592 const arrConst = arr;
2593 assert(rebindable(arr) == arr);
2594 assert(rebindable(arrConst) == arr);
2596 // https://issues.dlang.org/show_bug.cgi?id=7654
2597 immutable(char[]) s7654;
2598 Rebindable!(typeof(s7654)) r7654 = s7654;
2600 static foreach (T; AliasSeq!(char, wchar, char, int))
2602 static assert(is(Rebindable!(immutable(T[])) == immutable(T)[]));
2603 static assert(is(Rebindable!(const(T[])) == const(T)[]));
2604 static assert(is(Rebindable!(T[]) == T[]));
2607 // https://issues.dlang.org/show_bug.cgi?id=12046
2608 static assert(!__traits(compiles, Rebindable!(int[1])));
2609 static assert(!__traits(compiles, Rebindable!(const int[1])));
2611 // Pull request 3341
2612 Rebindable!(immutable int[int]) pr3341 = [123:345];
2613 assert(pr3341[123] == 345);
2614 immutable int[int] pr3341_aa = [321:543];
2616 assert(pr3341[321] == 543);
2617 assert(rebindable(pr3341_aa)[321] == 543);
2621 Similar to `Rebindable!(T)` but strips all qualifiers from the reference as
2622 opposed to just constness / immutability. Primary intended use case is with
2623 shared (having thread-local reference to shared class data)
2626 T = A class or interface type.
2628 template UnqualRef(T)
2629 if (is(T == class) || is(T == interface))
2631 static if (is(T == immutable U, U)
2632 || is(T == const shared U, U)
2633 || is(T == const U, U)
2634 || is(T == shared U, U))
2638 mixin RebindableCommon!(T, U, UnqualRef);
2643 alias UnqualRef = T;
2652 static shared(Data) a;
2653 static UnqualRef!(shared Data) b;
2657 auto thread = new core.thread.Thread({
2658 a = new shared Data();
2659 b = new shared Data();
2672 alias T = UnqualRef!(const shared C);
2673 static assert(is(typeof(T.stripped) == C));
2679 Order the provided members to minimize size while preserving alignment.
2680 Alignment is not always optimal for 80-bit reals, nor for structs declared
2684 E = A list of the types to be aligned, representing fields
2685 of an aggregate such as a `struct` or `class`.
2687 names = The names of the fields that are to be aligned.
2690 A string to be mixed in to an aggregate, such as a `struct` or `class`.
2692 string alignForSize(E...)(const char[][] names...)
2694 // Sort all of the members by .alignof.
2695 // BUG: Alignment is not always optimal for align(1) structs
2696 // or 80-bit reals or 64-bit primitives on x86.
2697 // TRICK: Use the fact that .alignof is always a power of 2,
2698 // and maximum 16 on extant systems. Thus, we can perform
2699 // a very limited radix sort.
2700 // Contains the members with .alignof = 64,32,16,8,4,2,1
2702 assert(E.length == names.length,
2703 "alignForSize: There should be as many member names as the types");
2705 string[7] declaration = ["", "", "", "", "", "", ""];
2710 auto k = a >= 64? 0 : a >= 32? 1 : a >= 16? 2 : a >= 8? 3 : a >= 4? 4 : a >= 2? 5 : 6;
2711 declaration[k] ~= T.stringof ~ " " ~ names[i] ~ ";\n";
2715 foreach (decl; declaration)
2724 mixin(alignForSize!(byte[6], double)(["name", "height"]));
2730 enum x = alignForSize!(int[], char[3], short, double[5])("x", "y","z", "w");
2731 struct Foo { int x; }
2732 enum y = alignForSize!(ubyte, Foo, double)("x", "y", "z");
2734 enum passNormalX = x == "double[5] w;\nint[] x;\nshort z;\nchar[3] y;\n";
2735 enum passNormalY = y == "double z;\nFoo y;\nubyte x;\n";
2737 enum passAbnormalX = x == "int[] x;\ndouble[5] w;\nshort z;\nchar[3] y;\n";
2738 enum passAbnormalY = y == "Foo y;\ndouble z;\nubyte x;\n";
2739 // ^ blame https://issues.dlang.org/show_bug.cgi?id=231
2741 static assert(passNormalX || passAbnormalX && double.alignof <= (int[]).alignof);
2742 static assert(passNormalY || passAbnormalY && double.alignof <= int.alignof);
2745 // https://issues.dlang.org/show_bug.cgi?id=12914
2748 immutable string[] fieldNames = ["x", "y"];
2751 mixin(alignForSize!(byte, int)(fieldNames));
2756 Defines a value paired with a distinctive "null" state that denotes
2757 the absence of a value. If default constructed, a $(D
2758 Nullable!T) object starts in the null state. Assigning it renders it
2759 non-null. Calling `nullify` can nullify it again.
2761 Practically `Nullable!T` stores a `T` and a `bool`.
2764 $(LREF apply), an alternative way to use the payload.
2768 private union DontCallDestructorT
2770 import std.traits : hasIndirections;
2771 static if (hasIndirections!T)
2777 private DontCallDestructorT _value = DontCallDestructorT.init;
2779 private bool _isNull = true;
2782 * Constructor initializing `this` with `value`.
2785 * value = The value to initialize this `Nullable` with.
2787 this(inout T value) inout
2789 _value.payload = value;
2793 static if (hasElaborateDestructor!T)
2799 destroy(_value.payload);
2804 static if (__traits(hasPostblit, T))
2809 _value.payload.__xpostblit();
2812 else static if (__traits(hasCopyConstructor, T))
2814 this(ref return scope inout Nullable!T rhs) inout
2816 _isNull = rhs._isNull;
2818 _value.payload = rhs._value.payload;
2820 _value = DontCallDestructorT.init;
2825 * If they are both null, then they are equal. If one is null and the other
2826 * is not, then they are not equal. If they are both non-null, then they are
2827 * equal if their values are equal.
2829 bool opEquals(this This, Rhs)(auto ref Rhs rhs)
2830 if (!is(CommonType!(This, Rhs) == void))
2832 static if (is(This == Rhs))
2838 return _value.payload == rhs._value.payload;
2842 alias Common = CommonType!(This, Rhs);
2843 return cast(Common) this == cast(Common) rhs;
2848 bool opEquals(this This, Rhs)(auto ref Rhs rhs)
2849 if (is(CommonType!(This, Rhs) == void) && is(typeof(this.get == rhs)))
2851 return _isNull ? false : rhs == _value.payload;
2858 Nullable!int a = 42;
2859 Nullable!int b = 42;
2860 Nullable!int c = 27;
2862 assert(empty == empty);
2863 assert(empty == Nullable!int.init);
2871 assert(empty != 42);
2879 immutable Nullable!int a = 42;
2880 Nullable!int b = 42;
2881 immutable Nullable!int c = 29;
2882 Nullable!int d = 29;
2893 assert(a == const Nullable!int(42));
2894 assert(a != Nullable!int(29));
2897 // https://issues.dlang.org/show_bug.cgi?id=17482
2900 import std.variant : Variant;
2901 Nullable!Variant a = Variant(12);
2907 size_t toHash() const @safe nothrow
2909 static if (__traits(compiles, .hashOf(_value.payload)))
2910 return _isNull ? 0 : .hashOf(_value.payload);
2912 // Workaround for when .hashOf is not both @safe and nothrow.
2913 return _isNull ? 0 : typeid(T).getHash(&_value.payload);
2917 * Gives the string `"Nullable.null"` if `isNull` is `true`. Otherwise, the
2918 * result is equivalent to calling $(REF formattedWrite, std,format) on the
2922 * writer = A `char` accepting
2923 * $(REF_ALTTEXT output range, isOutputRange, std, range, primitives)
2924 * fmt = A $(REF FormatSpec, std,format) which is used to represent
2925 * the value if this Nullable is not null
2927 * A `string` if `writer` and `fmt` are not set; `void` otherwise.
2931 import std.array : appender;
2932 auto app = appender!string();
2933 auto spec = singleSpec("%s");
2934 toString(app, spec);
2939 string toString() const
2941 import std.array : appender;
2942 auto app = appender!string();
2943 auto spec = singleSpec("%s");
2944 toString(app, spec);
2949 void toString(W)(ref W writer, scope const ref FormatSpec!char fmt)
2950 if (isOutputRange!(W, char))
2952 import std.range.primitives : put;
2954 put(writer, "Nullable.null");
2956 formatValue(writer, _value.payload, fmt);
2960 void toString(W)(ref W writer, scope const ref FormatSpec!char fmt) const
2961 if (isOutputRange!(W, char))
2963 import std.range.primitives : put;
2965 put(writer, "Nullable.null");
2967 formatValue(writer, _value.payload, fmt);
2971 * Check if `this` is in the null state.
2974 * true $(B iff) `this` is in the null state, otherwise false.
2976 @property bool isNull() const @safe pure nothrow
2991 // https://issues.dlang.org/show_bug.cgi?id=14940
2994 import std.array : appender;
2995 import std.format.write : formattedWrite;
2997 auto app = appender!string();
2999 formattedWrite(app, "%s", a);
3000 assert(app.data == "1");
3003 // https://issues.dlang.org/show_bug.cgi?id=19799
3006 import std.format : format;
3008 const Nullable!string a = const(Nullable!string)();
3014 * Forces `this` to the null state.
3018 static if (is(T == class) || is(T == interface))
3019 _value.payload = null;
3021 .destroy(_value.payload);
3028 Nullable!int ni = 0;
3036 * Assigns `value` to the internally-held state. If the assignment
3037 * succeeds, `this` becomes non-null.
3040 * value = A value of type `T` to assign to this `Nullable`.
3042 Nullable opAssign()(T value)
3044 import std.algorithm.mutation : moveEmplace, move;
3046 // the lifetime of the value in copy shall be managed by
3047 // this Nullable, so we must avoid calling its destructor.
3048 auto copy = DontCallDestructorT(value);
3052 // trusted since payload is known to be uninitialized.
3053 () @trusted { moveEmplace(copy.payload, _value.payload); }();
3057 move(copy.payload, _value.payload);
3064 * If this `Nullable` wraps a type that already has a null value
3065 * (such as a pointer), then assigning the null value to this
3066 * `Nullable` is no different than assigning any other value of
3067 * type `T`, and the resulting code will look very strange. It
3068 * is strongly recommended that this be avoided by instead using
3069 * the version of `Nullable` that takes an additional `nullValue`
3070 * template argument.
3075 Nullable!(int*) npi;
3080 assert(!npi.isNull);
3084 * Gets the value if not null. If `this` is in the null state, and the optional
3085 * parameter `fallback` was provided, it will be returned. Without `fallback`,
3086 * calling `get` with a null state is invalid.
3088 * When the fallback type is different from the Nullable type, `get(T)` returns
3092 * fallback = the value to return in case the `Nullable` is null.
3095 * The value held internally by this `Nullable`.
3097 @property ref inout(T) get() inout @safe pure nothrow
3099 enum message = "Called `get' on null Nullable!" ~ T.stringof ~ ".";
3100 assert(!isNull, message);
3101 return _value.payload;
3105 @property inout(T) get()(inout(T) fallback) inout
3107 return isNull ? fallback : _value.payload;
3111 @property auto get(U)(inout(U) fallback) inout
3113 return isNull ? fallback : _value.payload;
3116 /// $(MREF_ALTTEXT Range interface, std, range, primitives) functions.
3117 alias empty = isNull;
3120 alias popFront = nullify;
3123 alias popBack = nullify;
3126 @property ref inout(T) front() inout @safe pure nothrow
3135 @property inout(typeof(this)) save() inout
3141 inout(typeof(this)) opIndex() inout
3147 inout(typeof(this)) opIndex(size_t[2] dim) inout
3148 in (dim[0] <= length && dim[1] <= length && dim[1] >= dim[0])
3150 return (dim[0] == 0 && dim[1] == 1) ? this : this.init;
3153 size_t[2] opSlice(size_t dim : 0)(size_t from, size_t to) const
3159 @property size_t length() const @safe pure nothrow
3165 alias opDollar(size_t dim : 0) = length;
3168 ref inout(T) opIndex(size_t index) inout @safe pure nothrow
3176 auto nullable(T)(T t)
3178 return Nullable!T(t);
3184 struct CustomerRecord
3191 Nullable!CustomerRecord getByName(string name)
3193 //A bunch of hairy stuff
3195 return Nullable!CustomerRecord.init;
3198 auto queryResult = getByName("Doe, John");
3199 if (!queryResult.isNull)
3201 //Process Mr. Doe's customer record
3202 auto address = queryResult.get.address;
3203 auto customerNum = queryResult.get.customerNum;
3205 //Do some things with this customer's info
3209 //Add the customer to the database
3216 import std.exception : assertThrown;
3218 auto a = 42.nullable;
3220 assert(a.get == 42);
3224 assertThrown!Throwable(a.get);
3229 import std.algorithm.iteration : each, joiner;
3230 Nullable!int a = 42;
3232 // Add each value to an array
3234 a.each!((n) => arr ~= n);
3235 assert(arr == [42]);
3236 b.each!((n) => arr ~= n);
3237 assert(arr == [42]);
3238 // Take first value from an array of Nullables
3239 Nullable!int[] c = new Nullable!int[](10);
3240 c[7] = Nullable!int(42);
3241 assert(c.joiner.front == 42);
3245 auto k = Nullable!int(74);
3252 static int f(scope const Nullable!int x) {
3253 return x.isNull ? 42 : x.get;
3264 import std.exception : assertThrown;
3266 static struct S { int x; }
3272 assert(s.get != S(0));
3274 assert(s.get.x == 9190);
3276 assertThrown!Throwable(s.get.x = 9441);
3280 // Ensure Nullable can be used in pure/nothrow/@safe environment.
3281 function() @safe pure nothrow
3294 // Ensure Nullable can be used when the value is not pure/nothrow/@safe
3298 this(this) @system {}
3305 assert(s.get.x == 5);
3310 // https://issues.dlang.org/show_bug.cgi?id=9404
3313 alias N = Nullable!int;
3318 b = a; // `N b = a;` works fine
3325 //Check nullable immutable is constructable
3327 auto a1 = Nullable!(immutable int)();
3328 auto a2 = Nullable!(immutable int)(1);
3331 //Check immutable nullable is constructable
3333 auto a1 = immutable (Nullable!int)();
3334 auto a2 = immutable (Nullable!int)(1);
3340 alias NInt = Nullable!int;
3344 //from other Nullable null
3349 //from other Nullable non-null
3354 //Construct from similar nullable
3355 auto a3 = immutable(NInt)();
3362 //from other Nullable null
3368 //from other Nullable non-null
3374 //Construct from similar nullable
3375 auto a3 = immutable(NInt)();
3383 //Check nullable is nicelly embedable in a struct
3388 static struct S2 //inspired from 9404
3395 void opAssign(ref S2 other)
3400 static foreach (S; AliasSeq!(S1, S2))
3409 // https://issues.dlang.org/show_bug.cgi?id=10268
3413 JSONValue value = null;
3414 auto na = Nullable!JSONValue(value);
3416 struct S1 { int val; }
3417 struct S2 { int* val; }
3418 struct S3 { immutable int* val; }
3422 immutable si = immutable S1(1);
3423 auto x1 = Nullable!S1(sm);
3424 auto x2 = immutable Nullable!S1(sm);
3425 auto x3 = Nullable!S1(si);
3426 auto x4 = immutable Nullable!S1(si);
3427 assert(x1.get.val == 1);
3428 assert(x2.get.val == 1);
3429 assert(x3.get.val == 1);
3430 assert(x4.get.val == 1);
3438 immutable si = immutable S2(&ni);
3439 auto x1 = Nullable!S2(sm);
3440 static assert(!__traits(compiles, { auto x2 = immutable Nullable!S2(sm); }));
3441 static assert(!__traits(compiles, { auto x3 = Nullable!S2(si); }));
3442 auto x4 = immutable Nullable!S2(si);
3443 assert(*x1.get.val == 10);
3444 assert(*x4.get.val == 10);
3449 immutable si = immutable S3(&ni);
3450 auto x1 = Nullable!S3(sm);
3451 auto x2 = immutable Nullable!S3(sm);
3452 auto x3 = Nullable!S3(si);
3453 auto x4 = immutable Nullable!S3(si);
3454 assert(*x1.get.val == 10);
3455 assert(*x2.get.val == 10);
3456 assert(*x3.get.val == 10);
3457 assert(*x4.get.val == 10);
3461 // https://issues.dlang.org/show_bug.cgi?id=10357
3464 import std.datetime;
3465 Nullable!SysTime time = SysTime(0);
3468 // https://issues.dlang.org/show_bug.cgi?id=10915
3471 import std.conv : to;
3474 Appender!string buffer;
3477 assert(ni.to!string() == "Nullable.null");
3478 assert((cast(const) ni).to!string() == "Nullable.null");
3480 struct Test { string s; }
3481 alias NullableTest = Nullable!Test;
3483 NullableTest nt = Test("test");
3484 // test output range version
3485 assert(nt.to!string() == `Test("test")`);
3486 // test appender version
3487 assert(nt.toString() == `Test("test")`);
3488 // test const version
3489 assert((cast(const) nt).toString() == `const(Test)("test")`);
3491 NullableTest ntn = Test("null");
3492 assert(ntn.to!string() == `Test("null")`);
3503 override string toString()
3505 return d.to!string();
3508 Nullable!TestToString ntts = new TestToString(2.5);
3509 assert(ntts.to!string() == "2.5");
3512 // https://issues.dlang.org/show_bug.cgi?id=14477
3515 static struct DisabledDefaultConstructor
3520 Nullable!DisabledDefaultConstructor var;
3521 var = DisabledDefaultConstructor(5);
3525 // https://issues.dlang.org/show_bug.cgi?id=17440
3528 static interface I { }
3535 canary = 0x5050DEAD;
3540 auto nc = nullable(c);
3542 assert(c.canary == 0xA71FE);
3545 auto ni = nullable(i);
3547 assert(c.canary == 0xA71FE);
3550 // https://issues.dlang.org/show_bug.cgi?id=19037
3553 import std.datetime : SysTime;
3559 nothrow invariant { assert(b == true); }
3563 static bool destroyed;
3566 this(bool b) { this.b = b; }
3567 ~this() @safe { destroyed = true; }
3569 // mustn't call opAssign on Test.init in Nullable!Test, because the invariant
3570 // will be called before opAssign on the Test.init that is in Nullable
3571 // and Test.init violates its invariant.
3572 void opAssign(Test rhs) @safe { assert(false); }
3581 Test.destroyed = false;
3585 assert(Test.destroyed);
3587 Test.destroyed = false;
3589 // don't run destructor on T.init in Nullable on scope exit!
3590 assert(!Test.destroyed);
3592 // check that the contained type's destructor is called on assignment
3597 // can't be static, since we need a specific value's pointer
3602 if (this.destroyedRef)
3604 *this.destroyedRef = true;
3615 // reset from rvalue destruction in Nullable's opAssign
3618 // overwrite Nullable
3621 // the original S should be destroyed.
3622 assert(destroyed == true);
3624 // check that the contained type's destructor is still called when required
3627 bool destructorCalled = false;
3632 ~this() { *this.destroyed = true; }
3638 assert(!destructorCalled);
3640 Nullable!S ns = Nullable!S(S(&destructorCalled));
3642 destructorCalled = false; // reset after S was destroyed in the NS constructor
3644 assert(destructorCalled);
3647 // check that toHash on Nullable is forwarded to the contained type
3652 size_t toHash() const @safe pure nothrow { return 5; }
3655 Nullable!S s1 = S();
3656 Nullable!S s2 = Nullable!S();
3658 assert(typeid(Nullable!S).getHash(&s1) == 5);
3659 assert(typeid(Nullable!S).getHash(&s2) == 0);
3662 // https://issues.dlang.org/show_bug.cgi?id=21704
3665 import std.array : staticArray;
3671 ~this() { destroyed = true; }
3675 Nullable!(Probe[1]) test = [Probe()].staticArray;
3681 // https://issues.dlang.org/show_bug.cgi?id=21705
3687 bool opEquals(S rhs) { return n == rhs.n; }
3690 Nullable!S test1 = S(1), test2 = S(1);
3694 assert(test1 == test2);
3697 // https://issues.dlang.org/show_bug.cgi?id=22101
3704 ~this() { impure++; }
3711 // https://issues.dlang.org/show_bug.cgi?id=22100
3714 Nullable!int a, b, c;
3716 a = b = c = nullable(5);
3719 // https://issues.dlang.org/show_bug.cgi?id=18374
3720 @safe pure nothrow unittest
3722 import std.algorithm.comparison : equal;
3723 import std.range : only, takeNone;
3724 import std.range.primitives : hasAssignableElements, hasLength,
3725 hasLvalueElements, hasSlicing, hasSwappableElements,
3726 isRandomAccessRange;
3727 Nullable!int a = 42;
3729 assert(a.front == 42);
3730 assert(a.back == 42);
3732 assert(a.equal(only(42)));
3733 assert(a[0 .. $].equal(only(42)));
3735 assert(a.equal(only(43)));
3737 assert(a.equal(only(42)));
3740 assert(b.equal(takeNone(b)));
3741 Nullable!int c = a.save();
3747 assert(isRandomAccessRange!(Nullable!int));
3748 assert(hasLength!(Nullable!int));
3749 assert(hasSlicing!(Nullable!int));
3750 assert(hasAssignableElements!(Nullable!int));
3751 assert(hasSwappableElements!(Nullable!int));
3752 assert(hasLvalueElements!(Nullable!int));
3756 Just like `Nullable!T`, except that the null state is defined as a
3757 particular value. For example, $(D Nullable!(uint, uint.max)) is an
3758 `uint` that sets aside the value `uint.max` to denote a null
3759 state. $(D Nullable!(T, nullValue)) is more storage-efficient than $(D
3760 Nullable!T) because it does not need to store an extra `bool`.
3763 T = The wrapped type for which Nullable provides a null value.
3765 nullValue = The null value which denotes the null state of this
3766 `Nullable`. Must be of type `T`.
3768 struct Nullable(T, T nullValue)
3770 private T _value = nullValue;
3773 Constructor initializing `this` with `value`.
3776 value = The value to initialize this `Nullable` with.
3785 import std.format.spec : FormatSpec;
3786 import std.format.write : formatValue;
3787 // Needs to be a template because of https://issues.dlang.org/show_bug.cgi?id=13737.
3788 void toString()(scope void delegate(const(char)[]) sink, scope const ref FormatSpec!char fmt)
3792 sink.formatValue("Nullable.null", fmt);
3796 sink.formatValue(_value, fmt);
3800 void toString()(scope void delegate(const(char)[]) sink, scope const ref FormatSpec!char fmt) const
3804 sink.formatValue("Nullable.null", fmt);
3808 sink.formatValue(_value, fmt);
3815 import std.conv : to;
3817 const Nullable!(ulong, 0) x = 1;
3818 assert(x.to!string == "1");
3822 Check if `this` is in the null state.
3825 true $(B iff) `this` is in the null state, otherwise false.
3827 @property bool isNull() const
3829 //Need to use 'is' if T is a nullable type and
3830 //nullValue is null, or it's a compiler error
3831 static if (is(CommonType!(T, typeof(null)) == T) && nullValue is null)
3833 return _value is nullValue;
3835 //Need to use 'is' if T is a float type
3836 //because NaN != NaN
3837 else static if (__traits(isFloating, T) || __traits(compiles, { static assert(!(nullValue == nullValue)); }))
3839 return _value is nullValue;
3843 return _value == nullValue;
3850 Nullable!(int, -1) ni;
3851 //Initialized to "null" state
3860 assert(typeof(this).init.isNull, typeof(this).stringof ~
3861 ".isNull does not work correctly because " ~ T.stringof ~
3862 " has an == operator that is non-reflexive and could not be" ~
3863 " determined before runtime to be non-reflexive!");
3866 // https://issues.dlang.org/show_bug.cgi?id=11135
3867 // disable test until https://issues.dlang.org/show_bug.cgi?id=15316 gets fixed
3868 version (none) @system unittest
3870 static foreach (T; AliasSeq!(float, double, real))
3872 Nullable!(T, T.init) nf;
3873 //Initialized to "null" state
3875 assert(nf is typeof(nf).init);
3886 Forces `this` to the null state.
3896 Nullable!(int, -1) ni = 0;
3904 Assigns `value` to the internally-held state. If the assignment
3905 succeeds, `this` becomes non-null. No null checks are made. Note
3906 that the assignment may leave `this` in the null state.
3909 value = A value of type `T` to assign to this `Nullable`.
3910 If it is `nullvalue`, then the internal state of
3911 this `Nullable` will be set to null.
3913 void opAssign()(T value)
3915 import std.algorithm.mutation : swap;
3917 swap(value, _value);
3921 If this `Nullable` wraps a type that already has a null value
3922 (such as a pointer), and that null value is not given for
3923 `nullValue`, then assigning the null value to this `Nullable`
3924 is no different than assigning any other value of type `T`,
3925 and the resulting code will look very strange. It is strongly
3926 recommended that this be avoided by using `T`'s "built in"
3927 null value for `nullValue`.
3932 enum nullVal = cast(int*) 0xCAFEBABE;
3933 Nullable!(int*, nullVal) npi;
3938 assert(!npi.isNull);
3942 Gets the value. `this` must not be in the null state.
3943 This function is also called for the implicit conversion to `T`.
3945 Preconditions: `isNull` must be `false`.
3947 The value held internally by this `Nullable`.
3949 @property ref inout(T) get() inout
3951 //@@@6169@@@: We avoid any call that might evaluate nullValue's %s,
3952 //Because it might messup get's purity and safety inference.
3953 enum message = "Called `get' on null Nullable!(" ~ T.stringof ~ ",nullValue).";
3954 assert(!isNull, message);
3961 import std.exception : assertThrown, assertNotThrown;
3963 Nullable!(int, -1) ni;
3964 //`get` is implicitly called. Will throw
3965 //an error in non-release mode
3966 assertThrown!Throwable(ni == 0);
3969 assertNotThrown!Throwable(ni == 0);
3973 Implicitly converts to `T`.
3974 `this` must not be in the null state.
3980 auto nullable(alias nullValue, T)(T t)
3981 if (is (typeof(nullValue) == T))
3983 return Nullable!(T, nullValue)(t);
3989 Nullable!(size_t, size_t.max) indexOf(string[] haystack, string needle)
3991 //Find the needle, returning -1 if not found
3993 return Nullable!(size_t, size_t.max).init;
3996 void sendLunchInvite(string name)
4000 //It's safer than C...
4001 auto coworkers = ["Jane", "Jim", "Marry", "Fred"];
4002 auto pos = indexOf(coworkers, "Bob");
4005 //Send Bob an invitation to lunch
4006 sendLunchInvite(coworkers[pos]);
4010 //Bob not found; report the error
4013 //And there's no overhead
4014 static assert(Nullable!(size_t, size_t.max).sizeof == size_t.sizeof);
4020 import std.exception : assertThrown;
4022 Nullable!(int, int.min) a;
4024 assertThrown!Throwable(a.get);
4028 static assert(a.sizeof == int.sizeof);
4034 auto a = nullable!(int.min)(8);
4040 @nogc nothrow pure @safe unittest
4042 // https://issues.dlang.org/show_bug.cgi?id=19226
4043 // fully handle non-self-equal nullValue
4044 static struct Fraction
4049 return denominator == 0;
4051 bool opEquals(const Fraction rhs) const
4053 return !isNaN && denominator == rhs.denominator;
4056 alias N = Nullable!(Fraction, Fraction.init);
4057 assert(N.init.isNull);
4062 static int f(scope const Nullable!(int, int.min) x) {
4063 return x.isNull ? 42 : x.get;
4065 Nullable!(int, int.min) a;
4074 // Ensure Nullable can be used in pure/nothrow/@safe environment.
4075 function() @safe pure nothrow
4077 Nullable!(int, int.min) n;
4088 // Ensure Nullable can be used when the value is not pure/nothrow/@system
4092 bool opEquals(const S s) const @system { return s.x == x; }
4095 Nullable!(S, S(711)) s;
4105 //Check nullable is nicelly embedable in a struct
4108 Nullable!(int, 0) ni;
4110 static struct S2 //inspired from 9404
4112 Nullable!(int, 0) ni;
4117 void opAssign(S2 other)
4122 static foreach (S; AliasSeq!(S1, S2))
4132 import std.conv : to;
4134 // https://issues.dlang.org/show_bug.cgi?id=10915
4135 Nullable!(int, 1) ni = 1;
4136 assert(ni.to!string() == "Nullable.null");
4138 struct Test { string s; }
4139 alias NullableTest = Nullable!(Test, Test("null"));
4141 NullableTest nt = Test("test");
4142 assert(nt.to!string() == `Test("test")`);
4144 NullableTest ntn = Test("null");
4145 assert(ntn.to!string() == "Nullable.null");
4156 override string toString()
4158 return d.to!string();
4161 alias NullableTestToString = Nullable!(TestToString, null);
4163 NullableTestToString ntts = new TestToString(2.5);
4164 assert(ntts.to!string() == "2.5");
4169 Unpacks the content of a `Nullable`, performs an operation and packs it again. Does nothing if isNull.
4171 When called on a `Nullable`, `apply` will unpack the value contained in the `Nullable`,
4172 pass it to the function you provide and wrap the result in another `Nullable` (if necessary).
4173 If the `Nullable` is null, `apply` will return null itself.
4177 fun = a function operating on the content of the nullable
4180 `fun(t.get).nullable` if `!t.isNull`, else `Nullable.init`.
4183 $(HTTPS en.wikipedia.org/wiki/Monad_(functional_programming)#The_Maybe_monad, The `Maybe` monad)
4185 template apply(alias fun)
4187 import std.functional : unaryFun;
4189 auto apply(T)(auto ref T t)
4190 if (isInstanceOf!(Nullable, T))
4192 alias FunType = typeof(unaryFun!fun(T.init.get));
4194 enum MustWrapReturn = !isInstanceOf!(Nullable, FunType);
4196 static if (MustWrapReturn)
4198 alias ReturnType = Nullable!FunType;
4202 alias ReturnType = FunType;
4207 static if (MustWrapReturn)
4209 return unaryFun!fun(t.get).nullable;
4213 return unaryFun!fun(t.get);
4218 return ReturnType.init;
4224 nothrow pure @nogc @safe unittest
4226 alias toFloat = i => cast(float) i;
4228 Nullable!int sample;
4230 // apply(null) results in a null `Nullable` of the function's return type.
4231 Nullable!float f = sample.apply!toFloat;
4232 assert(sample.isNull && f.isNull);
4236 // apply(non-null) calls the function and wraps the result in a `Nullable`.
4237 f = sample.apply!toFloat;
4238 assert(!sample.isNull && !f.isNull);
4239 assert(f.get == 3.0f);
4243 nothrow pure @nogc @safe unittest
4245 alias greaterThree = i => (i > 3) ? i.nullable : Nullable!(typeof(i)).init;
4247 Nullable!int sample;
4249 // when the function already returns a `Nullable`, that `Nullable` is not wrapped.
4250 auto result = sample.apply!greaterThree;
4251 assert(sample.isNull && result.isNull);
4253 // The function may decide to return a null `Nullable`.
4255 result = sample.apply!greaterThree;
4256 assert(!sample.isNull && result.isNull);
4258 // Or it may return a value already wrapped in a `Nullable`.
4260 result = sample.apply!greaterThree;
4261 assert(!sample.isNull && !result.isNull);
4262 assert(result.get == 4);
4265 // test that Nullable.get(default) can merge types
4266 @safe @nogc nothrow pure
4269 Nullable!ubyte sample = Nullable!ubyte();
4271 // Test that get(U) returns the common type of the Nullable type and the parameter type.
4272 assert(sample.get(1000) == 1000);
4275 // Workaround for https://issues.dlang.org/show_bug.cgi?id=20670
4276 @safe @nogc nothrow pure
4279 immutable struct S { }
4281 S[] array = Nullable!(S[])().get(S[].init);
4284 // regression test for https://issues.dlang.org/show_bug.cgi?id=21199
4285 @safe @nogc nothrow pure
4289 assert(S(5).nullable.apply!"a.i" == 5);
4292 // regression test for https://issues.dlang.org/show_bug.cgi?id=22176
4293 @safe @nogc nothrow pure
4301 // Nullable shouldn't cause S to generate an
4302 // opAssign that would check the invariant.
4310 Just like `Nullable!T`, except that the object refers to a value
4311 sitting elsewhere in memory. This makes assignments overwrite the
4312 initially assigned value. Internally `NullableRef!T` only stores a
4313 pointer to `T` (i.e., $(D Nullable!T.sizeof == (T*).sizeof)).
4315 struct NullableRef(T)
4320 Constructor binding `this` to `value`.
4323 value = The value to bind to.
4325 this(T* value) @safe pure nothrow
4332 import std.format.spec : FormatSpec;
4333 import std.format.write : formatValue;
4334 // Needs to be a template because of https://issues.dlang.org/show_bug.cgi?id=13737.
4335 void toString()(scope void delegate(const(char)[]) sink, scope const ref FormatSpec!char fmt)
4339 sink.formatValue("Nullable.null", fmt);
4343 sink.formatValue(*_value, fmt);
4347 void toString()(scope void delegate(const(char)[]) sink, scope const ref FormatSpec!char fmt) const
4351 sink.formatValue("Nullable.null", fmt);
4355 sink.formatValue(*_value, fmt);
4362 import std.conv : to;
4364 const NullableRef!(ulong) x = new ulong(1);
4365 assert(x.to!string == "1");
4369 Binds the internal state to `value`.
4372 value = A pointer to a value of type `T` to bind this `NullableRef` to.
4374 void bind(T* value) @safe pure nothrow
4382 NullableRef!int nr = new int(42);
4385 int* n = new int(1);
4391 Returns `true` if and only if `this` is in the null state.
4394 true if `this` is in the null state, otherwise false.
4396 @property bool isNull() const @safe pure nothrow
4398 return _value is null;
4407 int* n = new int(42);
4409 assert(!nr.isNull && nr == 42);
4413 Forces `this` to the null state.
4415 void nullify() @safe pure nothrow
4423 NullableRef!int nr = new int(42);
4431 Assigns `value` to the internally-held state.
4434 value = A value of type `T` to assign to this `NullableRef`.
4435 If the internal state of this `NullableRef` has not
4436 been initialized, an error will be thrown in
4439 void opAssign()(T value)
4440 if (isAssignable!T) //@@@9416@@@
4442 enum message = "Called `opAssign' on null NullableRef!" ~ T.stringof ~ ".";
4443 assert(!isNull, message);
4450 import std.exception : assertThrown, assertNotThrown;
4454 assertThrown!Throwable(nr = 42);
4456 nr.bind(new int(0));
4458 assertNotThrown!Throwable(nr = 42);
4463 Gets the value. `this` must not be in the null state.
4464 This function is also called for the implicit conversion to `T`.
4466 @property ref inout(T) get() inout @safe pure nothrow
4468 enum message = "Called `get' on null NullableRef!" ~ T.stringof ~ ".";
4469 assert(!isNull, message);
4476 import std.exception : assertThrown, assertNotThrown;
4479 //`get` is implicitly called. Will throw
4480 //an error in non-release mode
4481 assertThrown!Throwable(nr == 0);
4483 nr.bind(new int(0));
4484 assertNotThrown!Throwable(nr == 0);
4488 Implicitly converts to `T`.
4489 `this` must not be in the null state.
4495 auto nullableRef(T)(T* t)
4497 return NullableRef!T(t);
4503 import std.exception : assertThrown;
4506 auto a = nullableRef(&x);
4517 assertThrown!Throwable(a.get);
4518 assertThrown!Throwable(a = 71);
4526 static int f(scope const NullableRef!int x) {
4527 return x.isNull ? 42 : x.get;
4530 auto a = nullableRef(&x);
4537 // Ensure NullableRef can be used in pure/nothrow/@safe environment.
4538 function() @safe pure nothrow
4540 auto storage = new int;
4549 assert(*storage == 2294);
4556 // Ensure NullableRef can be used when the value is not pure/nothrow/@safe
4560 this(this) @system {}
4561 bool opEquals(const S s) const @system { return s.x == x; }
4564 auto storage = S(5);
4576 //Check nullable is nicelly embedable in a struct
4581 static struct S2 //inspired from 9404
4588 void opAssign(S2 other)
4593 static foreach (S; AliasSeq!(S1, S2))
4602 // https://issues.dlang.org/show_bug.cgi?id=10915
4605 import std.conv : to;
4607 NullableRef!int nri;
4608 assert(nri.to!string() == "Nullable.null");
4614 NullableRef!Test nt = new Test("test");
4615 assert(nt.to!string() == `Test("test")`);
4626 override string toString()
4628 return d.to!string();
4631 TestToString tts = new TestToString(2.5);
4632 NullableRef!TestToString ntts = &tts;
4633 assert(ntts.to!string() == "2.5");
4638 `BlackHole!Base` is a subclass of `Base` which automatically implements
4639 all abstract member functions in `Base` as do-nothing functions. Each
4640 auto-implemented function just returns the default value of the return type
4641 without doing anything.
4644 $(HTTP search.cpan.org/~sburke/Class-_BlackHole-0.04/lib/Class/_BlackHole.pm, Class::_BlackHole)
4645 Perl module by Sean M. Burke.
4648 Base = A non-final class for `BlackHole` to inherit from.
4651 $(LREF AutoImplement), $(LREF generateEmptyFunction)
4653 alias BlackHole(Base) = AutoImplement!(Base, generateEmptyFunction, isAbstractFunction);
4658 import std.math.traits : isNaN;
4660 static abstract class C
4663 this(int v) { m_value = v; }
4664 int value() @property { return m_value; }
4666 abstract real realValue() @property;
4667 abstract void doSomething();
4670 auto c = new BlackHole!C(42);
4671 assert(c.value == 42);
4673 // Returns real.init which is NaN
4674 assert(c.realValue.isNaN);
4675 // Abstract functions are implemented as do-nothing
4681 import std.math.traits : isNaN;
4685 interface I_1 { real test(); }
4686 auto o = new BlackHole!I_1;
4687 assert(o.test().isNaN()); // NaN
4694 this(int v) { m_value = v; }
4695 int value() @property { return m_value; }
4697 abstract real realValue() @property;
4698 abstract void doSomething();
4701 auto c = new BlackHole!C(42);
4702 assert(c.value == 42);
4704 assert(c.realValue.isNaN); // NaN
4708 // https://issues.dlang.org/show_bug.cgi?id=12058
4711 inout(Object) foo() inout;
4716 nothrow pure @nogc @safe unittest
4720 I foo() nothrow pure @nogc @safe return scope;
4723 scope cb = new BlackHole!I();
4729 `WhiteHole!Base` is a subclass of `Base` which automatically implements
4730 all abstract member functions as functions that always fail. These functions
4731 simply throw an `Error` and never return. `Whitehole` is useful for
4732 trapping the use of class member functions that haven't been implemented.
4735 $(HTTP search.cpan.org/~mschwern/Class-_WhiteHole-0.04/lib/Class/_WhiteHole.pm, Class::_WhiteHole)
4736 Perl module by Michael G Schwern.
4739 Base = A non-final class for `WhiteHole` to inherit from.
4742 $(LREF AutoImplement), $(LREF generateAssertTrap)
4744 alias WhiteHole(Base) = AutoImplement!(Base, generateAssertTrap, isAbstractFunction);
4749 import std.exception : assertThrown;
4753 abstract void notYetImplemented();
4756 auto c = new WhiteHole!C;
4757 assertThrown!NotImplementedError(c.notYetImplemented()); // throws an Error
4760 // https://issues.dlang.org/show_bug.cgi?id=20232
4761 nothrow pure @safe unittest
4765 I foo() nothrow pure @safe return scope;
4768 if (0) // Just checking attribute interference
4770 scope cw = new WhiteHole!I();
4776 class NotImplementedError : Error
4778 this(string method) nothrow pure @safe
4780 super(method ~ " is not implemented");
4786 import std.exception : assertThrown;
4794 auto o = new WhiteHole!I_1;
4795 assertThrown!NotImplementedError(o.foo());
4796 assertThrown!NotImplementedError(o.bar());
4802 abstract void notYetImplemented();
4805 auto c = new WhiteHole!C;
4808 c.notYetImplemented();
4817 `AutoImplement` automatically implements (by default) all abstract member
4818 functions in the class or interface `Base` in specified way.
4820 The second version of `AutoImplement` automatically implements
4821 `Interface`, while deriving from `BaseClass`.
4824 how = template which specifies _how functions will be implemented/overridden.
4826 Two arguments are passed to `how`: the type `Base` and an alias
4827 to an implemented function. Then `how` must return an implemented
4828 function body as a string.
4830 The generated function body can use these keywords:
4832 $(LI `a0`, `a1`, …: arguments passed to the function;)
4833 $(LI `args`: a tuple of the arguments;)
4834 $(LI `self`: an alias to the function itself;)
4835 $(LI `parent`: an alias to the overridden function (if any).)
4838 You may want to use templated property functions (instead of Implicit
4839 Template Properties) to generate complex functions:
4840 --------------------
4841 // Prints log messages for each call to overridden functions.
4842 string generateLogger(C, alias fun)() @property
4845 enum qname = C.stringof ~ "." ~ __traits(identifier, fun);
4848 stmt ~= q{ struct Importer { import std.stdio; } };
4849 stmt ~= `Importer.writeln("Log: ` ~ qname ~ `(", args, ")");`;
4850 static if (!__traits(isAbstractFunction, fun))
4852 static if (is(ReturnType!fun == void))
4853 stmt ~= q{ parent(args); };
4856 auto r = parent(args);
4857 Importer.writeln("--> ", r);
4863 --------------------
4865 what = template which determines _what functions should be
4866 implemented/overridden.
4868 An argument is passed to `what`: an alias to a non-final member
4869 function in `Base`. Then `what` must return a boolean value.
4870 Return `true` to indicate that the passed function should be
4871 implemented/overridden.
4873 --------------------
4874 // Sees if fun returns something.
4875 enum bool hasValue(alias fun) = !is(ReturnType!(fun) == void);
4876 --------------------
4881 Generated code is inserted in the scope of `std.typecons` module. Thus,
4882 any useful functions outside `std.typecons` cannot be used in the generated
4883 code. To workaround this problem, you may `import` necessary things in a
4884 local struct, as done in the `generateLogger()` template in the above
4891 $(LI Variadic arguments to constructors are not forwarded to super.)
4892 $(LI Deep interface inheritance causes compile error with messages like
4893 "Error: function std.typecons._AutoImplement!(Foo)._AutoImplement.bar
4894 does not override any function". [$(BUGZILLA 2525)] )
4895 $(LI The `parent` keyword is actually a delegate to the super class'
4896 corresponding member function. [$(BUGZILLA 2540)] )
4897 $(LI Using alias template parameter in `how` and/or `what` may cause
4898 strange compile error. Use template tuple parameter instead to workaround
4899 this problem. [$(BUGZILLA 4217)] )
4902 class AutoImplement(Base, alias how, alias what = isAbstractFunction) : Base
4903 if (!is(how == class))
4905 private alias autoImplement_helper_ =
4906 AutoImplement_Helper!("autoImplement_helper_", "Base", Base, typeof(this), how, what);
4907 mixin(autoImplement_helper_.code);
4911 class AutoImplement(
4912 Interface, BaseClass, alias how,
4913 alias what = isAbstractFunction) : BaseClass, Interface
4914 if (is(Interface == interface) && is(BaseClass == class))
4916 private alias autoImplement_helper_ = AutoImplement_Helper!(
4917 "autoImplement_helper_", "Interface", Interface, typeof(this), how, what);
4918 mixin(autoImplement_helper_.code);
4924 interface PackageSupplier
4930 static abstract class AbstractFallbackPackageSupplier : PackageSupplier
4932 protected PackageSupplier default_, fallback;
4934 this(PackageSupplier default_, PackageSupplier fallback)
4936 this.default_ = default_;
4937 this.fallback = fallback;
4944 template fallback(T, alias func)
4946 import std.format : format;
4947 // for all implemented methods:
4948 // - try default first
4949 // - only on a failure run & return fallback
4953 return default_.%1$s(args);
4957 return fallback.%1$s(args);
4959 }.format(__traits(identifier, func));
4962 // combines two classes and use the second one as fallback
4963 alias FallbackPackageSupplier = AutoImplement!(AbstractFallbackPackageSupplier, fallback);
4965 class FailingPackageSupplier : PackageSupplier
4967 int foo(){ throw new Exception("failure"); }
4968 int bar(){ return 2;}
4971 class BackupPackageSupplier : PackageSupplier
4973 int foo(){ return -1; }
4974 int bar(){ return -1;}
4977 auto registry = new FallbackPackageSupplier(new FailingPackageSupplier(), new BackupPackageSupplier());
4979 assert(registry.foo() == -1);
4980 assert(registry.bar() == 2);
4984 * Code-generating stuffs are encupsulated in this helper template so that
4985 * namespace pollution, which can cause name confliction with Base's public
4986 * members, should be minimized.
4988 private template AutoImplement_Helper(string myName, string baseName,
4989 Base, Self, alias generateMethodBody, alias cherrypickMethod)
4992 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4994 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4996 // Returns function overload sets in the class C, filtered with pred.
4997 template enumerateOverloads(C, alias pred)
4999 template Impl(names...)
5001 import std.meta : Filter;
5002 static if (names.length > 0)
5004 alias methods = Filter!(pred, MemberFunctionsTuple!(C, names[0]));
5005 alias next = Impl!(names[1 .. $]);
5007 static if (methods.length > 0)
5008 alias Impl = AliasSeq!(OverloadSet!(names[0], methods), next);
5013 alias Impl = AliasSeq!();
5016 alias enumerateOverloads = Impl!(__traits(allMembers, C));
5019 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5021 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5023 // Add a non-final check to the cherrypickMethod.
5024 enum bool canonicalPicker(fun.../+[https://issues.dlang.org/show_bug.cgi?id=4217]+/) =
5025 !__traits(isFinalFunction, fun[0]) && cherrypickMethod!(fun);
5028 * A tuple of overload sets, each item of which consists of functions to be
5029 * implemented by the generated code.
5031 alias targetOverloadSets = enumerateOverloads!(Base, canonicalPicker);
5034 * Super class of this AutoImplement instance
5036 alias Super = BaseTypeTuple!(Self)[0];
5037 static assert(is(Super == class));
5038 static assert(is(Base == interface) || is(Super == Base));
5041 * A tuple of the super class' constructors. Used for forwarding
5042 * constructor calls.
5044 static if (__traits(hasMember, Super, "__ctor"))
5045 alias ctorOverloadSet = OverloadSet!("__ctor", __traits(getOverloads, Super, "__ctor"));
5047 alias ctorOverloadSet = OverloadSet!("__ctor"); // empty
5050 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5052 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5055 * The generated code will be mixed into AutoImplement, which will be
5056 * instantiated in this module's scope. Thus, any user-defined types are
5057 * out of scope and cannot be used directly (i.e. by their names).
5059 * We will use FuncInfo instances for accessing return types and parameter
5060 * types of the implemented functions. The instances will be populated to
5061 * the AutoImplement's scope in a certain way; see the populate() below.
5064 // Returns the preferred identifier for the FuncInfo instance for the i-th
5065 // overloaded function with the name.
5066 template INTERNAL_FUNCINFO_ID(string name, size_t i)
5068 import std.format : format;
5070 enum string INTERNAL_FUNCINFO_ID = format("F_%s_%s", name, i);
5074 * Insert FuncInfo instances about all the target functions here. This
5075 * enables the generated code to access type information via, for example,
5076 * "autoImplement_helper_.F_foo_1".
5078 template populate(overloads...)
5080 static if (overloads.length > 0)
5082 mixin populate!(overloads[0].name, overloads[0].contents);
5083 mixin populate!(overloads[1 .. $]);
5086 template populate(string name, methods...)
5088 static if (methods.length > 0)
5090 mixin populate!(name, methods[0 .. $ - 1]);
5092 alias target = methods[$ - 1];
5093 enum ith = methods.length - 1;
5094 mixin("alias " ~ INTERNAL_FUNCINFO_ID!(name, ith) ~ " = FuncInfo!target;");
5098 public mixin populate!(targetOverloadSets);
5099 public mixin populate!( ctorOverloadSet );
5102 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5103 // Code-generating policies
5104 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5106 /* Common policy configurations for generating constructors and methods. */
5107 template CommonGeneratingPolicy()
5109 // base class identifier which generated code should use
5110 enum string BASE_CLASS_ID = baseName;
5112 // FuncInfo instance identifier which generated code should use
5113 template FUNCINFO_ID(string name, size_t i)
5115 enum string FUNCINFO_ID =
5116 myName ~ "." ~ INTERNAL_FUNCINFO_ID!(name, i);
5120 /* Policy configurations for generating constructors. */
5121 template ConstructorGeneratingPolicy()
5123 mixin CommonGeneratingPolicy;
5125 /* Generates constructor body. Just forward to the base class' one. */
5126 string generateFunctionBody(ctor.../+[https://issues.dlang.org/show_bug.cgi?id=4217]+/)() @property
5128 enum varstyle = variadicFunctionStyle!(typeof(&ctor[0]));
5130 static if (varstyle & (Variadic.c | Variadic.d))
5132 // the argptr-forwarding problem
5133 //pragma(msg, "Warning: AutoImplement!(", Base, ") ",
5134 // "ignored variadic arguments to the constructor ",
5135 // FunctionTypeOf!(typeof(&ctor[0])) );
5137 return "super(args);";
5141 /* Policy configurations for genearting target methods. */
5142 template MethodGeneratingPolicy()
5144 mixin CommonGeneratingPolicy;
5146 /* Geneartes method body. */
5147 string generateFunctionBody(func.../+[https://issues.dlang.org/show_bug.cgi?id=4217]+/)() @property
5149 return generateMethodBody!(Base, func); // given
5154 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5156 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5158 alias ConstructorGenerator = MemberFunctionGenerator!(ConstructorGeneratingPolicy!());
5159 alias MethodGenerator = MemberFunctionGenerator!(MethodGeneratingPolicy!());
5161 public enum string code =
5162 ConstructorGenerator.generateCode!( ctorOverloadSet ) ~ "\n" ~
5163 MethodGenerator.generateCode!(targetOverloadSets);
5165 debug (SHOW_GENERATED_CODE)
5167 pragma(msg, "-------------------- < ", Base, " >");
5169 pragma(msg, "--------------------");
5173 //debug = SHOW_GENERATED_CODE;
5177 // no function to implement
5180 auto o = new BlackHole!I_1;
5184 interface I_3 { void test(int, in int, out int, ref int, lazy int); }
5185 auto o = new BlackHole!I_3;
5187 // use of user-defined type
5190 interface I_4 { S test(); }
5191 auto o = new BlackHole!I_4;
5201 auto o = new BlackHole!I_5;
5203 // constructor forwarding
5207 this(int n) { assert(n == 42); }
5208 this(string s) { assert(s == "Deeee"); }
5211 auto o1 = new BlackHole!C_6(42);
5212 auto o2 = new BlackHole!C_6("Deeee");
5213 auto o3 = new BlackHole!C_6(1, 2, 3, 4);
5220 int test_pure() pure;
5221 int test_nothrow() nothrow;
5222 int test_property() @property;
5223 int test_safe() @safe;
5224 int test_trusted() @trusted;
5225 int test_system() @system;
5226 int test_pure_nothrow() pure nothrow;
5228 auto o = new BlackHole!I_7;
5234 void test_const() const;
5235 void test_immutable() immutable;
5236 void test_shared() shared;
5237 void test_shared_const() shared const;
5239 auto o = new BlackHole!I_8;
5245 private string foo_;
5251 protected string boilerplate() @property
5253 return "Boilerplate stuff.";
5256 public string foo() @property
5264 string testMethod(size_t);
5267 static string generateTestMethod(C, alias fun)() @property
5269 return "return this.boilerplate[0 .. a0];";
5272 auto o = new AutoImplement!(I_10, C_9, generateTestMethod)("Testing");
5273 assert(o.testMethod(11) == "Boilerplate");
5274 assert(o.foo == "Testing");
5276 /+ // deep inheritance
5278 // https://issues.dlang.org/show_bug.cgi?id=2525
5279 // https://issues.dlang.org/show_bug.cgi?id=3525
5280 // NOTE: [r494] func.c(504-571) FuncDeclaration::semantic()
5281 interface I { void foo(); }
5284 static abstract class C_9 : K {}
5285 auto o = new BlackHole!C_9;
5287 // test `parent` alias
5291 void simple(int) @safe;
5292 int anotherSimple(string);
5293 int overloaded(int);
5295 void overloaded(string) @safe;
5301 import std.traits : Parameters, ReturnType;
5302 import std.meta : Alias;
5304 protected ReturnType!fn _impl(alias fn)(Parameters!fn)
5305 if (is(Alias!(__traits(parent, fn)) == interface))
5307 static if (!is(typeof(return) == void))
5308 return typeof(return).init;
5312 template tpl(I, alias fn)
5313 if (is(I == interface) && __traits(isSame, __traits(parent, fn), I))
5315 enum string tpl = q{
5316 enum bool haveReturn = !is(typeof(return) == void);
5318 static if (is(typeof(return) == void))
5321 return _impl!parent(args);
5325 auto o = new AutoImplement!(I_11, C_11, tpl);
5329 // https://issues.dlang.org/show_bug.cgi?id=17177
5330 // AutoImplement fails on function overload sets with
5331 // "cannot infer type from overloaded function symbol"
5334 static class Issue17177
5339 Issue17177 overloaded(string n)
5353 static string how(C, alias fun)()
5355 static if (!is(ReturnType!fun == void))
5358 return parent(args);
5369 import std.meta : templateNot;
5370 alias Implementation = AutoImplement!(Issue17177, how, templateNot!isFinalFunction);
5373 version (StdUnittest)
5375 // https://issues.dlang.org/show_bug.cgi?id=10647
5376 // Add prefix "issue10647_" as a workaround for
5377 // https://issues.dlang.org/show_bug.cgi?id=1238
5378 private string issue10647_generateDoNothing(C, alias fun)() @property
5382 static if (is(ReturnType!fun == void))
5386 string returnType = ReturnType!fun.stringof;
5387 stmt ~= "return "~returnType~".init;";
5392 private template issue10647_isAlwaysTrue(alias fun)
5394 enum issue10647_isAlwaysTrue = true;
5397 // Do nothing template
5398 private template issue10647_DoNothing(Base)
5400 alias issue10647_DoNothing = AutoImplement!(Base, issue10647_generateDoNothing, issue10647_isAlwaysTrue);
5403 // A class to be overridden
5404 private class issue10647_Foo{
5411 auto foo = new issue10647_DoNothing!issue10647_Foo();
5416 Used by MemberFunctionGenerator.
5418 package template OverloadSet(string nam, T...)
5420 enum string name = nam;
5425 Used by MemberFunctionGenerator.
5427 package template FuncInfo(alias func)
5428 if (is(typeof(&func)))
5430 alias RT = ReturnType!(typeof(&func));
5431 alias PT = Parameters!(typeof(&func));
5433 package template FuncInfo(Func)
5435 alias RT = ReturnType!Func;
5436 alias PT = Parameters!Func;
5440 General-purpose member function generator.
5441 --------------------
5442 template GeneratingPolicy()
5444 // [optional] the name of the class where functions are derived
5445 enum string BASE_CLASS_ID;
5447 // [optional] define this if you have only function types
5448 enum bool WITHOUT_SYMBOL;
5450 // [optional] Returns preferred identifier for i-th parameter.
5451 template PARAMETER_VARIABLE_ID(size_t i);
5453 // Returns the identifier of the FuncInfo instance for the i-th overload
5454 // of the specified name. The identifier must be accessible in the scope
5455 // where generated code is mixed.
5456 template FUNCINFO_ID(string name, size_t i);
5458 // Returns implemented function body as a string. When WITHOUT_SYMBOL is
5459 // defined, the latter is used.
5460 template generateFunctionBody(alias func);
5461 template generateFunctionBody(string name, FuncType);
5463 --------------------
5465 package template MemberFunctionGenerator(alias Policy)
5468 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5470 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5472 alias format = std.format.format;
5474 enum CONSTRUCTOR_NAME = "__ctor";
5476 // true if functions are derived from a base class
5477 enum WITH_BASE_CLASS = __traits(hasMember, Policy, "BASE_CLASS_ID");
5479 // true if functions are specified as types, not symbols
5480 enum WITHOUT_SYMBOL = __traits(hasMember, Policy, "WITHOUT_SYMBOL");
5482 // preferred identifier for i-th parameter variable
5483 static if (__traits(hasMember, Policy, "PARAMETER_VARIABLE_ID"))
5485 alias PARAMETER_VARIABLE_ID = Policy.PARAMETER_VARIABLE_ID;
5489 enum string PARAMETER_VARIABLE_ID(size_t i) = format("a%s", i);
5490 // default: a0, a1, ...
5493 // Returns a tuple consisting of 0,1,2,...,n-1. For static foreach.
5494 template CountUp(size_t n)
5497 alias CountUp = AliasSeq!(CountUp!(n - 1), n - 1);
5499 alias CountUp = AliasSeq!();
5503 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5505 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5508 * Runs through all the target overload sets and generates D code which
5509 * implements all the functions in the overload sets.
5511 public string generateCode(overloads...)() @property
5515 // run through all the overload sets
5516 foreach (i_; CountUp!(0 + overloads.length)) // workaround
5518 enum i = 0 + i_; // workaround
5519 alias oset = overloads[i];
5521 code ~= generateCodeForOverloadSet!(oset);
5523 static if (WITH_BASE_CLASS && oset.name != CONSTRUCTOR_NAME)
5525 // The generated function declarations may hide existing ones
5526 // in the base class (cf. HiddenFuncError), so we put an alias
5527 // declaration here to reveal possible hidden functions.
5528 code ~= format("alias %s = %s.%s;\n",
5530 // super: https://issues.dlang.org/show_bug.cgi?id=2540
5531 Policy.BASE_CLASS_ID,
5538 // handle each overload set
5539 string generateCodeForOverloadSet(alias oset)() @property
5543 foreach (i_; CountUp!(0 + oset.contents.length)) // workaround
5545 enum i = 0 + i_; // workaround
5546 code ~= generateFunction!(
5547 Policy.FUNCINFO_ID!(oset.name, i), oset.name,
5548 oset.contents[i]) ~ "\n";
5554 * Returns D code which implements the function func. This function
5555 * actually generates only the declarator part; the function body part is
5556 * generated by the functionGenerator() policy.
5558 public string generateFunction(
5559 string myFuncInfo, string name, func... )() @property
5561 import std.format : format;
5563 enum isCtor = (name == CONSTRUCTOR_NAME);
5565 string code; // the result
5567 auto paramsRes = generateParameters!(myFuncInfo, func)();
5568 code ~= paramsRes.imports;
5570 /*** Function Declarator ***/
5572 alias Func = FunctionTypeOf!(func);
5573 alias FA = FunctionAttribute;
5574 enum atts = functionAttributes!(func);
5575 enum realName = isCtor ? "this" : name;
5577 // FIXME?? Make it so that these aren't CTFE funcs any more, since
5578 // Format is deprecated, and format works at compile time?
5579 /* Made them CTFE funcs just for the sake of Format!(...) */
5581 // return type with optional "ref"
5582 static string make_returnType()
5588 if (atts & FA.ref_) rtype ~= "ref ";
5589 rtype ~= myFuncInfo ~ ".RT";
5593 enum returnType = make_returnType();
5595 // function attributes attached after declaration
5596 static string make_postAtts()
5599 if (atts & FA.pure_ ) poatts ~= " pure";
5600 if (atts & FA.nothrow_) poatts ~= " nothrow";
5601 if (atts & FA.property) poatts ~= " @property";
5602 if (atts & FA.safe ) poatts ~= " @safe";
5603 if (atts & FA.trusted ) poatts ~= " @trusted";
5604 if (atts & FA.scope_ ) poatts ~= " scope";
5605 if (atts & FA.return_ ) poatts ~= " return";
5608 enum postAtts = make_postAtts();
5610 // function storage class
5611 static string make_storageClass()
5614 if (is(Func == shared)) postc ~= " shared";
5615 if (is(Func == const)) postc ~= " const";
5616 if (is(Func == inout)) postc ~= " inout";
5617 if (is(Func == immutable)) postc ~= " immutable";
5620 enum storageClass = make_storageClass();
5623 if (__traits(isVirtualMethod, func))
5624 code ~= "override ";
5625 code ~= format("extern(%s) %s %s(%s) %s %s\n",
5626 functionLinkage!(func),
5630 postAtts, storageClass );
5633 /*** Function Body ***/
5636 enum nparams = Parameters!(func).length;
5638 /* Declare keywords: args, self and parent. */
5641 preamble ~= "alias args = AliasSeq!(" ~ enumerateParameters!(nparams) ~ ");\n";
5644 preamble ~= "alias self = " ~ name ~ ";\n";
5645 static if (WITH_BASE_CLASS)
5646 preamble ~= `alias parent = __traits(getMember, ` ~ Policy.BASE_CLASS_ID ~ `, "` ~ name ~ `");`;
5650 static if (WITHOUT_SYMBOL)
5651 enum fbody = Policy.generateFunctionBody!(name, func);
5653 enum fbody = Policy.generateFunctionBody!(func);
5664 * Returns D code which declares function parameters,
5665 * and optionally any imports (e.g. core.vararg)
5666 * "ref int a0, real a1, ..."
5668 static struct GenParams { string imports, params; }
5669 GenParams generateParameters(string myFuncInfo, func...)()
5671 alias STC = ParameterStorageClass;
5672 alias stcs = ParameterStorageClassTuple!(func);
5673 enum nparams = stcs.length;
5675 string imports = ""; // any imports required
5676 string params = ""; // parameters
5678 foreach (i, stc; stcs)
5680 if (i > 0) params ~= ", ";
5682 // Parameter storage classes.
5683 if (stc & STC.scope_) params ~= "scope ";
5684 if (stc & STC.in_) params ~= "in ";
5685 if (stc & STC.out_ ) params ~= "out ";
5686 if (stc & STC.ref_ ) params ~= "ref ";
5687 if (stc & STC.lazy_ ) params ~= "lazy ";
5689 // Take parameter type from the FuncInfo.
5690 params ~= format("%s.PT[%s]", myFuncInfo, i);
5692 // Declare a parameter variable.
5693 params ~= " " ~ PARAMETER_VARIABLE_ID!(i);
5696 // Add some ellipsis part if needed.
5697 auto style = variadicFunctionStyle!(func);
5698 final switch (style)
5703 case Variadic.c, Variadic.d:
5704 imports ~= "import core.vararg;\n";
5705 // (...) or (a, b, ...)
5706 params ~= (nparams == 0) ? "..." : ", ...";
5709 case Variadic.typesafe:
5714 return typeof(return)(imports, params);
5717 // Returns D code which enumerates n parameter variables using comma as the
5718 // separator. "a0, a1, a2, a3"
5719 string enumerateParameters(size_t n)() @property
5723 foreach (i_; CountUp!(n))
5725 enum i = 0 + i_; // workaround
5726 if (i > 0) params ~= ", ";
5727 params ~= PARAMETER_VARIABLE_ID!(i);
5735 Predefined how-policies for `AutoImplement`. These templates are also used by
5736 `BlackHole` and `WhiteHole`, respectively.
5738 template generateEmptyFunction(C, func.../+[https://issues.dlang.org/show_bug.cgi?id=4217]+/)
5740 static if (is(ReturnType!(func) == void))
5741 enum string generateEmptyFunction = q{
5743 else static if (functionAttributes!(func) & FunctionAttribute.ref_)
5744 enum string generateEmptyFunction = q{
5745 static typeof(return) dummy;
5749 enum string generateEmptyFunction = q{
5750 return typeof(return).init;
5757 alias BlackHole(Base) = AutoImplement!(Base, generateEmptyFunction);
5765 auto i = new BlackHole!I();
5766 // generateEmptyFunction returns the default value of the return type without doing anything
5768 assert(i.bar is null);
5772 template generateAssertTrap(C, func...)
5774 enum string generateAssertTrap =
5775 `throw new NotImplementedError("` ~ C.stringof ~ "."
5776 ~ __traits(identifier, func) ~ `");`;
5782 import std.exception : assertThrown;
5784 alias WhiteHole(Base) = AutoImplement!(Base, generateAssertTrap);
5792 auto i = new WhiteHole!I();
5793 // generateAssertTrap throws an exception for every unimplemented function of the interface
5794 assertThrown!NotImplementedError(i.foo);
5795 assertThrown!NotImplementedError(i.bar);
5800 pragma(mangle, "_d_toObject")
5801 extern(C) pure nothrow Object typecons_d_toObject(void* p);
5805 * Avoids opCast operator overloading.
5807 private template dynamicCast(T)
5808 if (is(T == class) || is(T == interface))
5811 T dynamicCast(S)(inout S source)
5812 if (is(S == class) || is(S == interface))
5814 static if (is(Unqual!S : Unqual!T))
5816 import std.traits : QualifierOf;
5817 alias Qual = QualifierOf!S; // SharedOf or MutableOf
5818 alias TmpT = Qual!(Unqual!T);
5819 inout(TmpT) tmp = source; // bypass opCast by implicit conversion
5820 return *cast(T*)(&tmp); // + variable pointer cast + dereference
5824 return cast(T) typecons_d_toObject(*cast(void**)(&source));
5831 class C { @disable void opCast(T)(); }
5833 static assert(!__traits(compiles, cast(Object) c));
5834 auto o = dynamicCast!Object(c);
5837 interface I { @disable void opCast(T)(); Object instance(); }
5838 interface J { @disable void opCast(T)(); Object instance(); }
5839 class D : I, J { Object instance() { return this; } }
5841 static assert(!__traits(compiles, cast(J) i));
5842 J j = dynamicCast!J(i);
5843 assert(i.instance() is j.instance());
5847 Supports structural based typesafe conversion.
5849 If `Source` has structural conformance with the `interface` `Targets`,
5850 wrap creates an internal wrapper class which inherits `Targets` and
5851 wraps the `src` object, then returns it.
5853 `unwrap` can be used to extract objects which have been wrapped by `wrap`.
5855 template wrap(Targets...)
5856 if (Targets.length >= 1 && allSatisfy!(isMutable, Targets))
5858 import std.meta : staticMap;
5861 auto wrap(Source)(inout Source src) @trusted pure nothrow
5862 if (Targets.length == 1 && is(Source : Targets[0]))
5864 alias T = Select!(is(Source == shared), shared Targets[0], Targets[0]);
5865 return dynamicCast!(inout T)(src);
5867 // structural upcast
5868 template wrap(Source)
5869 if (!allSatisfy!(Bind!(isImplicitlyConvertible, Source), Targets))
5871 auto wrap(inout Source src)
5873 static assert(hasRequireMethods!(),
5874 "Source "~Source.stringof~
5875 " does not have structural conformance to "~
5878 alias T = Select!(is(Source == shared), shared Impl, Impl);
5879 return new inout T(src);
5882 template FuncInfo(string s, F)
5888 // https://issues.dlang.org/show_bug.cgi?id=12064: Remove NVI members
5889 template OnlyVirtual(members...)
5891 enum notFinal(alias T) = !__traits(isFinalFunction, T);
5892 import std.meta : Filter;
5893 alias OnlyVirtual = Filter!(notFinal, members);
5896 // Concat all Targets function members into one tuple
5897 template Concat(size_t i = 0)
5899 static if (i >= Targets.length)
5900 alias Concat = AliasSeq!();
5903 alias Concat = AliasSeq!(OnlyVirtual!(GetOverloadedMethods!(Targets[i]), Concat!(i + 1)));
5907 // Remove duplicated functions based on the identifier name and function type covariance
5908 template Uniq(members...)
5910 static if (members.length == 0)
5911 alias Uniq = AliasSeq!();
5914 alias func = members[0];
5915 enum name = __traits(identifier, func);
5916 alias type = FunctionTypeOf!func;
5917 template check(size_t i, mem...)
5919 static if (i >= mem.length)
5920 enum ptrdiff_t check = -1;
5923 enum ptrdiff_t check =
5924 __traits(identifier, func) == __traits(identifier, mem[i]) &&
5925 !is(DerivedFunctionType!(type, FunctionTypeOf!(mem[i])) == void)
5926 ? i : check!(i + 1, mem);
5929 enum ptrdiff_t x = 1 + check!(0, members[1 .. $]);
5932 alias typex = DerivedFunctionType!(type, FunctionTypeOf!(members[x]));
5933 alias remain = Uniq!(members[1 .. x], members[x + 1 .. $]);
5935 static if (remain.length >= 1 && remain[0].name == name &&
5936 !is(DerivedFunctionType!(typex, remain[0].type) == void))
5938 alias F = DerivedFunctionType!(typex, remain[0].type);
5939 alias Uniq = AliasSeq!(FuncInfo!(name, F), remain[1 .. $]);
5942 alias Uniq = AliasSeq!(FuncInfo!(name, typex), remain);
5946 alias Uniq = AliasSeq!(FuncInfo!(name, type), Uniq!(members[1 .. $]));
5950 alias TargetMembers = Uniq!(Concat!()); // list of FuncInfo
5951 alias SourceMembers = GetOverloadedMethods!Source; // list of function symbols
5953 // Check whether all of SourceMembers satisfy covariance target in TargetMembers
5954 template hasRequireMethods(size_t i = 0)
5956 static if (i >= TargetMembers.length)
5957 enum hasRequireMethods = true;
5960 enum hasRequireMethods =
5961 findCovariantFunction!(TargetMembers[i], Source, SourceMembers) != -1 &&
5962 hasRequireMethods!(i + 1);
5966 // Internal wrapper class
5967 final class Impl : Structural, Targets
5970 Source _wrap_source;
5972 this( inout Source s) inout @safe pure nothrow { _wrap_source = s; }
5973 this(shared inout Source s) shared inout @safe pure nothrow { _wrap_source = s; }
5975 // BUG: making private should work with NVI.
5976 protected final inout(Object) _wrap_getSource() inout @trusted
5978 return dynamicCast!(inout Object)(_wrap_source);
5981 import std.conv : to;
5982 import core.lifetime : forward;
5983 template generateFun(size_t i)
5985 enum name = TargetMembers[i].name;
5986 enum fa = functionAttributes!(TargetMembers[i].type);
5987 static @property stc()
5990 if (fa & FunctionAttribute.property) r ~= "@property ";
5991 if (fa & FunctionAttribute.ref_) r ~= "ref ";
5992 if (fa & FunctionAttribute.pure_) r ~= "pure ";
5993 if (fa & FunctionAttribute.nothrow_) r ~= "nothrow ";
5994 if (fa & FunctionAttribute.trusted) r ~= "@trusted ";
5995 if (fa & FunctionAttribute.safe) r ~= "@safe ";
5998 static @property mod()
6000 alias type = AliasSeq!(TargetMembers[i].type)[0];
6002 static if (is(type == immutable)) r ~= " immutable";
6005 static if (is(type == shared)) r ~= " shared";
6006 static if (is(type == const)) r ~= " const";
6007 else static if (is(type == inout)) r ~= " inout";
6012 enum n = to!string(i);
6013 static if (fa & FunctionAttribute.property)
6015 static if (Parameters!(TargetMembers[i].type).length == 0)
6016 enum fbody = "_wrap_source."~name;
6018 enum fbody = "_wrap_source."~name~" = forward!args";
6022 enum fbody = "_wrap_source."~name~"(forward!args)";
6025 "override "~stc~"ReturnType!(TargetMembers["~n~"].type) "
6026 ~ name~"(Parameters!(TargetMembers["~n~"].type) args) "~mod~
6027 "{ return "~fbody~"; }";
6031 static foreach (i; 0 .. TargetMembers.length)
6032 mixin(generateFun!i);
6037 template wrap(Targets...)
6038 if (Targets.length >= 1 && !allSatisfy!(isMutable, Targets))
6040 import std.meta : staticMap;
6042 alias wrap = .wrap!(staticMap!(Unqual, Targets));
6046 template unwrap(Target)
6047 if (isMutable!Target)
6050 auto unwrap(Source)(inout Source src) @trusted pure nothrow
6051 if (is(Target : Source))
6053 alias T = Select!(is(Source == shared), shared Target, Target);
6054 return dynamicCast!(inout T)(src);
6056 // structural downcast
6057 auto unwrap(Source)(inout Source src) @trusted pure nothrow
6058 if (!is(Target : Source))
6060 alias T = Select!(is(Source == shared), shared Target, Target);
6061 Object o = dynamicCast!(Object)(src); // remove qualifier
6064 if (auto a = dynamicCast!(Structural)(o))
6066 if (auto d = dynamicCast!(inout T)(o = a._wrap_getSource()))
6069 else if (auto d = dynamicCast!(inout T)(o))
6079 template unwrap(Target)
6080 if (!isMutable!Target)
6082 alias unwrap = .unwrap!(Unqual!Target);
6091 @property int height();
6095 @property int height();
6099 int quack() { return 1; }
6100 @property int height() { return 10; }
6104 int quack() { return 2; }
6105 @property int height() { return 20; }
6108 Duck d1 = new Duck();
6109 Human h1 = new Human();
6111 interface Refleshable
6116 // does not have structural conformance
6117 static assert(!__traits(compiles, d1.wrap!Refleshable));
6118 static assert(!__traits(compiles, h1.wrap!Refleshable));
6121 Quack qd = d1.wrap!Quack;
6123 assert(qd.quack() == 1); // calls Duck.quack
6125 Duck d2 = qd.unwrap!Duck;
6128 // structural upcast
6129 Quack qh = h1.wrap!Quack;
6130 assert(qh.quack() == 2); // calls Human.quack
6131 // structural downcast
6132 Human h2 = qh.unwrap!Human;
6135 // structural upcast (two steps)
6136 Quack qx = h1.wrap!Quack; // Human -> Quack
6137 Flyer fx = qx.wrap!Flyer; // Quack -> Flyer
6138 assert(fx.height == 20); // calls Human.height
6139 // structural downcast (two steps)
6140 Quack qy = fx.unwrap!Quack; // Flyer -> Quack
6141 Human hy = qy.unwrap!Human; // Quack -> Human
6143 // structural downcast (one step)
6144 Human hz = fx.unwrap!Human; // Flyer -> Human
6151 import std.traits : FunctionAttribute, functionAttributes;
6152 interface A { int run(); }
6153 interface B { int stop(); @property int status(); }
6156 int run() { return 1; }
6157 int stop() { return 2; }
6158 @property int status() { return 3; }
6162 auto ab = x.wrap!(A, B);
6165 assert(a.run() == 1);
6166 assert(b.stop() == 2);
6167 assert(b.status == 3);
6168 static assert(functionAttributes!(typeof(ab).status) & FunctionAttribute.property);
6171 // Internal class to support dynamic cross-casting
6172 private interface Structural
6174 inout(Object) _wrap_getSource() inout @safe pure nothrow;
6181 int draw() { return 1; }
6182 int draw(int v) { return v; }
6184 int draw() const { return 2; }
6185 int draw() shared { return 3; }
6186 int draw() shared const { return 4; }
6187 int draw() immutable { return 5; }
6194 int draw() shared const;
6195 int draw() immutable;
6203 auto sa = new shared A();
6204 auto ia = new immutable A();
6206 Drawable md = ma.wrap!Drawable;
6207 const Drawable cd = ma.wrap!Drawable;
6208 shared Drawable sd = sa.wrap!Drawable;
6209 shared const Drawable scd = sa.wrap!Drawable;
6210 immutable Drawable id = ia.wrap!Drawable;
6211 assert( md.draw() == 1);
6212 assert( cd.draw() == 2);
6213 assert( sd.draw() == 3);
6214 assert(scd.draw() == 4);
6215 assert( id.draw() == 5);
6218 Drawable2 d = ma.wrap!Drawable2;
6219 static assert(!__traits(compiles, d.draw()));
6220 assert(d.draw(10) == 10);
6224 // https://issues.dlang.org/show_bug.cgi?id=10377
6227 import std.range, std.algorithm;
6229 interface MyInputRange(T)
6231 @property T front();
6233 @property bool empty();
6236 //auto o = iota(0,10,1).inputRangeObject();
6237 //pragma(msg, __traits(allMembers, typeof(o)));
6238 auto r = iota(0,10,1).inputRangeObject().wrap!(MyInputRange!int)();
6239 assert(equal(r, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]));
6242 // https://issues.dlang.org/show_bug.cgi?id=10536
6251 int foo() { return 1; }
6252 @disable void opCast(T, this X)(); // !
6255 Interface i = new Pluggable().wrap!Interface;
6256 assert(i.foo() == 1);
6260 // Enhancement 10538
6268 int opDispatch(string name, A...)(A args) { return 100; }
6271 Interface i = wrap!Interface(new Pluggable());
6272 assert(i.foo() == 100);
6273 assert(i.bar(10) == 100);
6276 // https://issues.dlang.org/show_bug.cgi?id=12064
6282 final int nvi1(){return foo();}
6288 final int nvi2(){return bar();}
6293 int foo() { return 42;}
6294 int bar() { return 12064;}
6297 auto baz = new Baz();
6298 auto foobar = baz.wrap!(I, J)();
6299 assert(foobar.nvi1 == 42);
6300 assert(foobar.nvi2 == 12064);
6303 // Make a tuple of non-static function symbols
6304 package template GetOverloadedMethods(T)
6306 import std.meta : Filter;
6308 alias allMembers = __traits(allMembers, T);
6309 template follows(size_t i = 0)
6311 static if (i >= allMembers.length)
6313 alias follows = AliasSeq!();
6315 else static if (!__traits(compiles, mixin("T."~allMembers[i])))
6317 alias follows = follows!(i + 1);
6321 enum name = allMembers[i];
6323 template isMethod(alias f)
6325 static if (is(typeof(&f) F == F*) && is(F == function))
6326 enum isMethod = !__traits(isStaticFunction, f);
6328 enum isMethod = false;
6330 alias follows = AliasSeq!(
6331 Filter!(isMethod, __traits(getOverloads, T, name)),
6335 alias GetOverloadedMethods = follows!();
6337 // find a function from Fs that has same identifier and covariant type with f
6338 private template findCovariantFunction(alias finfo, Source, Fs...)
6340 template check(size_t i = 0)
6342 static if (i >= Fs.length)
6343 enum ptrdiff_t check = -1;
6346 enum ptrdiff_t check =
6347 (finfo.name == __traits(identifier, Fs[i])) &&
6348 isCovariantWith!(FunctionTypeOf!(Fs[i]), finfo.type)
6349 ? i : check!(i + 1);
6353 static if (x == -1 && is(typeof(Source.opDispatch)))
6355 alias Params = Parameters!(finfo.type);
6356 enum ptrdiff_t findCovariantFunction =
6357 is(typeof(( Source).init.opDispatch!(finfo.name)(Params.init))) ||
6358 is(typeof(( const Source).init.opDispatch!(finfo.name)(Params.init))) ||
6359 is(typeof(( immutable Source).init.opDispatch!(finfo.name)(Params.init))) ||
6360 is(typeof(( shared Source).init.opDispatch!(finfo.name)(Params.init))) ||
6361 is(typeof((shared const Source).init.opDispatch!(finfo.name)(Params.init)))
6362 ? ptrdiff_t.max : -1;
6365 enum ptrdiff_t findCovariantFunction = x;
6368 private enum TypeModifier
6370 mutable = 0, // type is mutable
6371 const_ = 1, // type is const
6372 immutable_ = 2, // type is immutable
6373 shared_ = 4, // type is shared
6374 inout_ = 8, // type is wild
6376 private template TypeMod(T)
6378 static if (is(T == immutable))
6380 enum mod1 = TypeModifier.immutable_;
6385 enum mod1 = is(T == shared) ? TypeModifier.shared_ : 0;
6386 static if (is(T == const))
6387 enum mod2 = TypeModifier.const_;
6388 else static if (is(T == inout))
6389 enum mod2 = TypeModifier.inout_;
6391 enum mod2 = TypeModifier.mutable;
6393 enum TypeMod = cast(TypeModifier)(mod1 | mod2);
6398 template UnittestFuncInfo(alias f)
6400 enum name = __traits(identifier, f);
6401 alias type = FunctionTypeOf!f;
6406 int draw() { return 1; }
6407 @property int value() { return 2; }
6408 final int run() { return 3; }
6410 alias methods = GetOverloadedMethods!A;
6413 alias @property int F2();
6415 alias nothrow @trusted uint F4();
6416 alias int F5(Object);
6417 alias bool F6(Object);
6418 static assert(methods.length == 3 + 4);
6419 static assert(__traits(identifier, methods[0]) == "draw" && is(typeof(&methods[0]) == F1*));
6420 static assert(__traits(identifier, methods[1]) == "value" && is(typeof(&methods[1]) == F2*));
6421 static assert(__traits(identifier, methods[2]) == "run" && is(typeof(&methods[2]) == F1*));
6424 @property int value();
6427 static assert(findCovariantFunction!(UnittestFuncInfo!draw, A, methods) == 0);
6428 static assert(findCovariantFunction!(UnittestFuncInfo!value, A, methods) == 1);
6429 static assert(findCovariantFunction!(UnittestFuncInfo!opEquals, A, methods) == -1);
6430 static assert(findCovariantFunction!(UnittestFuncInfo!nomatch, A, methods) == -1);
6432 // considering opDispatch
6435 void opDispatch(string name, A...)(A) {}
6437 alias methodsB = GetOverloadedMethods!B;
6438 static assert(findCovariantFunction!(UnittestFuncInfo!draw, B, methodsB) == ptrdiff_t.max);
6439 static assert(findCovariantFunction!(UnittestFuncInfo!value, B, methodsB) == ptrdiff_t.max);
6440 static assert(findCovariantFunction!(UnittestFuncInfo!opEquals, B, methodsB) == ptrdiff_t.max);
6441 static assert(findCovariantFunction!(UnittestFuncInfo!nomatch, B, methodsB) == ptrdiff_t.max);
6444 package template DerivedFunctionType(T...)
6446 static if (!T.length)
6448 alias DerivedFunctionType = void;
6450 else static if (T.length == 1)
6452 static if (is(T[0] == function))
6454 alias DerivedFunctionType = T[0];
6458 alias DerivedFunctionType = void;
6461 else static if (is(T[0] P0 == function) && is(T[1] P1 == function))
6463 alias FA = FunctionAttribute;
6465 alias F0 = T[0], R0 = ReturnType!F0, PSTC0 = ParameterStorageClassTuple!F0;
6466 alias F1 = T[1], R1 = ReturnType!F1, PSTC1 = ParameterStorageClassTuple!F1;
6467 enum FA0 = functionAttributes!F0;
6468 enum FA1 = functionAttributes!F1;
6470 template CheckParams(size_t i = 0)
6472 static if (i >= P0.length)
6473 enum CheckParams = true;
6476 enum CheckParams = (is(P0[i] == P1[i]) && PSTC0[i] == PSTC1[i]) &&
6477 CheckParams!(i + 1);
6480 static if (R0.sizeof == R1.sizeof && !is(CommonType!(R0, R1) == void) &&
6481 P0.length == P1.length && CheckParams!() && TypeMod!F0 == TypeMod!F1 &&
6482 variadicFunctionStyle!F0 == variadicFunctionStyle!F1 &&
6483 functionLinkage!F0 == functionLinkage!F1 &&
6484 ((FA0 ^ FA1) & (FA.ref_ | FA.property)) == 0)
6486 alias R = Select!(is(R0 : R1), R0, R1);
6487 alias FX = FunctionTypeOf!(R function(P0));
6488 // @system is default
6489 alias FY = SetFunctionAttributes!(FX, functionLinkage!F0, (FA0 | FA1) & ~FA.system);
6490 alias DerivedFunctionType = DerivedFunctionType!(FY, T[2 .. $]);
6493 alias DerivedFunctionType = void;
6496 alias DerivedFunctionType = void;
6500 // attribute covariance
6502 static assert(is(DerivedFunctionType!(F1, F1) == F1));
6503 alias int F2() pure nothrow;
6504 static assert(is(DerivedFunctionType!(F1, F2) == F2));
6505 alias int F3() @safe;
6506 alias int F23() @safe pure nothrow;
6507 static assert(is(DerivedFunctionType!(F2, F3) == F23));
6509 // return type covariance
6511 static assert(is(DerivedFunctionType!(F1, F4) == void));
6516 static assert(is(DerivedFunctionType!(F5, F6) == F6));
6517 alias typeof(null) F7();
6520 static assert(is(DerivedFunctionType!(F5, F7) == F7));
6521 static assert(is(DerivedFunctionType!(F7, F8) == void));
6522 static assert(is(DerivedFunctionType!(F7, F9) == F7));
6524 // variadic type equality
6526 alias int F11(int...);
6527 alias int F12(int, ...);
6528 static assert(is(DerivedFunctionType!(F10, F11) == void));
6529 static assert(is(DerivedFunctionType!(F10, F12) == void));
6530 static assert(is(DerivedFunctionType!(F11, F12) == void));
6533 alias extern(C) int F13(int);
6534 alias extern(D) int F14(int);
6535 alias extern(Windows) int F15(int);
6536 static assert(is(DerivedFunctionType!(F13, F14) == void));
6537 static assert(is(DerivedFunctionType!(F13, F15) == void));
6538 static assert(is(DerivedFunctionType!(F14, F15) == void));
6540 // ref & @property equality
6542 alias ref int F17(int);
6543 alias @property int F18(int);
6544 static assert(is(DerivedFunctionType!(F16, F17) == void));
6545 static assert(is(DerivedFunctionType!(F16, F18) == void));
6546 static assert(is(DerivedFunctionType!(F17, F18) == void));
6549 package template Bind(alias Template, args1...)
6551 alias Bind(args2...) = Template!(args1, args2);
6556 Options regarding auto-initialization of a `SafeRefCounted` object (see
6557 the definition of `SafeRefCounted` below).
6559 enum RefCountedAutoInitialize
6561 /// Do not auto-initialize the object
6563 /// Auto-initialize the object
6570 import core.exception : AssertError;
6571 import std.exception : assertThrown;
6578 SafeRefCounted!(Foo, RefCountedAutoInitialize.yes) rcAuto;
6579 SafeRefCounted!(Foo, RefCountedAutoInitialize.no) rcNoAuto;
6581 assert(rcAuto.refCountedPayload.a == 42);
6583 assertThrown!AssertError(rcNoAuto.refCountedPayload);
6584 rcNoAuto.refCountedStore.ensureInitialized;
6585 assert(rcNoAuto.refCountedPayload.a == 42);
6588 // Same the above but for old RefCounted and not documented
6591 import core.exception : AssertError;
6592 import std.exception : assertThrown;
6599 RefCounted!(Foo, RefCountedAutoInitialize.yes) rcAuto;
6600 RefCounted!(Foo, RefCountedAutoInitialize.no) rcNoAuto;
6602 assert(rcAuto.refCountedPayload.a == 42);
6604 assertThrown!AssertError(rcNoAuto.refCountedPayload);
6605 rcNoAuto.refCountedStore.ensureInitialized;
6606 assert(rcNoAuto.refCountedPayload.a == 42);
6610 Defines a reference-counted object containing a `T` value as
6613 An instance of `SafeRefCounted` is a reference to a structure,
6614 which is referred to as the $(I store), or $(I storage implementation
6615 struct) in this documentation. The store contains a reference count
6616 and the `T` payload. `SafeRefCounted` uses `malloc` to allocate
6617 the store. As instances of `SafeRefCounted` are copied or go out of
6618 scope, they will automatically increment or decrement the reference
6619 count. When the reference count goes down to zero, `SafeRefCounted`
6620 will call `destroy` against the payload and call `free` to
6621 deallocate the store. If the `T` payload contains any references
6622 to GC-allocated memory, then `SafeRefCounted` will add it to the GC memory
6623 that is scanned for pointers, and remove it from GC scanning before
6624 `free` is called on the store.
6626 One important consequence of `destroy` is that it will call the
6627 destructor of the `T` payload. GC-managed references are not
6628 guaranteed to be valid during a destructor call, but other members of
6629 `T`, such as file handles or pointers to `malloc` memory, will
6630 still be valid during the destructor call. This allows the `T` to
6631 deallocate or clean up any non-GC resources immediately after the
6632 reference count has reached zero.
6634 Without -preview=dip1000, `SafeRefCounted` is unsafe and should be
6635 used with care. No references to the payload should be escaped outside
6636 the `SafeRefCounted` object.
6638 With -preview=dip1000, `SafeRefCounted` is safe if it's payload is accessed only
6639 with the $(LREF borrow) function. Scope semantics can also prevent accidental
6640 escaping of `refCountedPayload`, but it's still up to the user to not destroy
6641 the last counted reference while the payload is in use. Due to that,
6642 `refCountedPayload` remains accessible only in `@system` code.
6644 The `autoInit` option makes the object ensure the store is
6645 automatically initialized. Leaving $(D autoInit ==
6646 RefCountedAutoInitialize.yes) (the default option) is convenient but
6647 has the cost of a test whenever the payload is accessed. If $(D
6648 autoInit == RefCountedAutoInitialize.no), user code must call either
6649 `refCountedStore.isInitialized` or `refCountedStore.ensureInitialized`
6650 before attempting to access the payload. Not doing so results in null
6651 pointer dereference.
6653 If `T.this()` is annotated with `@disable` then `autoInit` must be
6654 `RefCountedAutoInitialize.no` in order to compile.
6659 struct SafeRefCounted(T, RefCountedAutoInitialize autoInit =
6660 RefCountedAutoInitialize.yes)
6661 if (!is(T == class) && !(is(T == interface)))
6665 private enum enableGCScan = false;
6669 private enum enableGCScan = hasIndirections!T;
6672 extern(C) private pure nothrow @nogc static
6674 pragma(mangle, "free") void pureFree( void *ptr );
6675 static if (enableGCScan)
6676 import core.memory : GC;
6679 pragma(inline, true) private void checkInit()()
6680 if (autoInit == RefCountedAutoInitialize.yes)
6682 _refCounted.ensureInitialized();
6685 pragma(inline, true) private void checkInit()() inout
6686 if (autoInit == RefCountedAutoInitialize.no)
6688 assert(_refCounted.isInitialized,
6689 "Attempted to use an uninitialized payload.");
6692 /// `SafeRefCounted` storage implementation.
6693 struct RefCountedStore
6701 private Impl* _store;
6703 private void initialize(A...)(auto ref A args)
6705 import core.lifetime : emplace, forward;
6708 version (D_Exceptions) scope(failure) () @trusted { deallocateStore(); }();
6709 emplace(&_store._payload, forward!args);
6713 private void move(ref T source) nothrow pure
6715 import std.algorithm.mutation : moveEmplace;
6718 () @trusted { moveEmplace(source, _store._payload); }();
6722 // 'nothrow': can only generate an Error
6723 private void allocateStore() nothrow pure
6725 static if (enableGCScan)
6727 import std.internal.memory : enforceCalloc;
6728 auto ptr = enforceCalloc(1, Impl.sizeof);
6729 _store = () @trusted { return cast(Impl*) ptr; }();
6730 () @trusted { GC.addRange(&_store._payload, T.sizeof); }();
6734 import std.internal.memory : enforceMalloc;
6735 auto ptr = enforceMalloc(Impl.sizeof);
6736 _store = () @trusted { return cast(Impl*) ptr; }();
6740 private void deallocateStore() nothrow pure
6742 static if (enableGCScan)
6744 GC.removeRange(&this._store._payload);
6751 Returns `true` if and only if the underlying store has been
6752 allocated and initialized.
6754 @property nothrow @safe pure @nogc
6755 bool isInitialized() const
6757 return _store !is null;
6761 Returns underlying reference count if it is allocated and initialized
6762 (a positive integer), and `0` otherwise.
6764 @property nothrow @safe pure @nogc
6765 size_t refCount() const
6767 return isInitialized ? _store._count : 0;
6771 Makes sure the payload was properly initialized. Such a
6772 call is typically inserted before using the payload.
6774 This function is unavailable if `T.this()` is annotated with
6778 void ensureInitialized()()
6780 // By checking for `@disable this()` and failing early we can
6781 // produce a clearer error message.
6782 static assert(__traits(compiles, { static T t; }),
6783 "Cannot automatically initialize `" ~ fullyQualifiedName!T ~
6784 "` because `" ~ fullyQualifiedName!T ~
6785 ".this()` is annotated with `@disable`.");
6786 if (!isInitialized) initialize();
6790 RefCountedStore _refCounted;
6792 /// Returns storage implementation struct.
6793 @property nothrow @safe
6794 ref inout(RefCountedStore) refCountedStore() inout
6800 Constructor that initializes the payload.
6802 Postcondition: `refCountedStore.isInitialized`
6804 this(A...)(auto ref A args) if (A.length > 0)
6807 assert(refCountedStore.isInitialized);
6811 import core.lifetime : forward;
6812 _refCounted.initialize(forward!args);
6816 this(return scope T val)
6818 _refCounted.move(val);
6822 Constructor that tracks the reference count appropriately. If $(D
6823 !refCountedStore.isInitialized), does nothing.
6825 this(this) @safe pure nothrow @nogc
6827 if (!_refCounted.isInitialized) return;
6828 ++_refCounted._store._count;
6832 Destructor that tracks the reference count appropriately. If $(D
6833 !refCountedStore.isInitialized), does nothing. When the reference count goes
6834 down to zero, calls `destroy` agaist the payload and calls `free`
6835 to deallocate the corresponding resource.
6839 import std.traits : dip1000Enabled;
6841 // This prevents the same reference from decrementing the count twice.
6842 scope(exit) _refCounted = _refCounted.init;
6844 if (!_refCounted.isInitialized) return;
6845 assert(_refCounted._store._count > 0);
6846 if (--_refCounted._store._count) return;
6847 // Done, destroy and deallocate
6848 .destroy(_refCounted._store._payload);
6850 static if (dip1000Enabled)
6852 () @trusted { _refCounted.deallocateStore(); }();
6854 else _refCounted.deallocateStore();
6858 Assignment operators.
6860 Note: You may not assign a new payload to an uninitialized SafeRefCounted, if
6861 auto initialization is off. Assigning another counted reference is still okay.
6863 void opAssign(typeof(this) rhs)
6865 import std.algorithm.mutation : swap;
6867 swap(_refCounted._store, rhs._refCounted._store);
6871 void opAssign(T rhs)
6873 import std.algorithm.mutation : move;
6876 move(rhs, _refCounted._store._payload);
6879 //version to have a single properly ddoc'ed function (w/ correct sig)
6883 Returns a reference to the payload. If (autoInit ==
6884 RefCountedAutoInitialize.yes), calls $(D
6885 refCountedStore.ensureInitialized). Otherwise, just issues $(D
6886 assert(refCountedStore.isInitialized)). Used with $(D alias
6887 refCountedPayload this;), so callers can just use the `SafeRefCounted`
6890 $(BLUE The first overload exists only if $(D autoInit == RefCountedAutoInitialize.yes).)
6891 So if $(D autoInit == RefCountedAutoInitialize.no)
6892 or called for a constant or immutable object, then
6893 `refCountedPayload` will also be qualified as nothrow
6894 (but will still assert if not initialized).
6897 ref T refCountedPayload() return;
6900 @property nothrow @system pure @nogc
6901 ref inout(T) refCountedPayload() inout return;
6905 static if (autoInit == RefCountedAutoInitialize.yes)
6907 //Can't use inout here because of potential mutation
6909 ref T refCountedPayload() return
6912 return _refCounted._store._payload;
6917 @property nothrow @system pure @nogc
6918 ref inout(T) refCountedPayload() inout return
6921 return _refCounted._store._payload;
6927 Returns a reference to the payload. If (autoInit ==
6928 RefCountedAutoInitialize.yes), calls $(D
6929 refCountedStore.ensureInitialized). Otherwise, just issues $(D
6930 assert(refCountedStore.isInitialized)).
6932 alias refCountedPayload this;
6934 static if (is(T == struct) && !is(typeof((ref T t) => t.toString())))
6936 string toString(this This)()
6938 import std.conv : to;
6940 static if (autoInit)
6941 return to!string(refCountedPayload);
6944 if (!_refCounted.isInitialized)
6945 return This.stringof ~ "(RefCountedStore(null))";
6947 return to!string(_refCounted._store._payload);
6954 @betterC pure @system nothrow @nogc unittest
6956 // A pair of an `int` and a `size_t` - the latter being the
6957 // reference count - will be dynamically allocated
6958 auto rc1 = SafeRefCounted!int(5);
6960 // No more allocation, add just one extra reference count
6962 // Reference semantics
6965 // the pair will be freed when rc1 and rc2 go out of scope
6968 // This test can't be betterC because the test extractor won't see the private
6969 // `initialize` method accessed here
6970 pure @safe nothrow @nogc unittest
6972 auto rc1 = SafeRefCounted!(int, RefCountedAutoInitialize.no)(5);
6973 rc1._refCounted.initialize();
6976 pure @system unittest
6978 foreach (MyRefCounted; AliasSeq!(SafeRefCounted, RefCounted))
6980 MyRefCounted!int* p;
6982 auto rc1 = MyRefCounted!int(5);
6985 assert(rc1._refCounted._store._count == 1);
6987 assert(rc1._refCounted._store._count == 2);
6988 // Reference semantics
6992 assert(rc2._refCounted._store._count == 2);
6994 assert(rc1._refCounted._store._count == 2);
6996 assert(p._refCounted._store == null);
6998 // [Safe]RefCounted as a member
7004 x._refCounted.initialize(y);
7008 auto another = this;
7014 assert(a.x._refCounted._store._count == 2,
7015 "https://issues.dlang.org/show_bug.cgi?id=4356 still unfixed");
7019 @betterC pure @safe nothrow @nogc unittest
7021 import std.algorithm.mutation : swap;
7023 SafeRefCounted!int p1, p2;
7027 // Same as above but for old RefCounted and not @safe
7028 @betterC pure @system nothrow @nogc unittest
7030 import std.algorithm.mutation : swap;
7032 RefCounted!int p1, p2;
7036 // https://issues.dlang.org/show_bug.cgi?id=6606
7037 @betterC @safe pure nothrow @nogc unittest
7048 alias SRC = SafeRefCounted!S;
7051 // Same as above but for old RefCounted and not @safe
7052 @betterC @system pure nothrow @nogc unittest
7063 alias SRC = RefCounted!S;
7066 // https://issues.dlang.org/show_bug.cgi?id=6436
7067 @betterC @system pure unittest
7069 import std.meta : AliasSeq;
7072 this(int rval) { assert(rval == 1); }
7073 this(ref int lval) { assert(lval == 3); ++lval; }
7076 foreach (MyRefCounted; AliasSeq!(SafeRefCounted, RefCounted))
7078 auto s1 = MyRefCounted!S(1);
7080 auto s2 = MyRefCounted!S(lval);
7085 // gc_addRange coverage
7086 @betterC @safe pure unittest
7088 struct S { int* p; }
7090 auto s = SafeRefCounted!S(null);
7093 // Same as above but for old RefCounted and not @safe
7094 @betterC @system pure unittest
7096 struct S { int* p; }
7098 auto s = RefCounted!S(null);
7101 @betterC @system pure nothrow @nogc unittest
7103 import std.meta : AliasSeq;
7104 foreach (MyRefCounted; AliasSeq!(SafeRefCounted, RefCounted))
7107 a = 5; //This should not assert
7111 b = a; //This should not assert either
7114 MyRefCounted!(int*) c;
7118 // https://issues.dlang.org/show_bug.cgi?id=21638
7119 @betterC @system pure nothrow @nogc unittest
7121 import std.meta : AliasSeq;
7122 static struct NoDefaultCtor
7125 this(int x) @nogc nothrow pure { this.x = x; }
7129 foreach (MyRefCounted; AliasSeq!(SafeRefCounted, RefCounted))
7131 auto rc = MyRefCounted!(NoDefaultCtor, RefCountedAutoInitialize.no)(5);
7136 // https://issues.dlang.org/show_bug.cgi?id=20502
7139 alias Types = AliasSeq!(SafeRefCounted, RefCounted);
7140 alias funcs = AliasSeq!(safeRefCounted, refCounted);
7141 static foreach (aliasI; 0 .. 2)
7143 alias MyRefCounted = Types[aliasI];
7144 alias myRefCounted = funcs[aliasI];
7145 import std.conv : to;
7147 // Check that string conversion is transparent for refcounted
7148 // structs that do not have either toString or alias this.
7149 static struct A { Object a; }
7150 auto a = A(new Object());
7151 auto r = myRefCounted(a);
7152 assert(to!string(r) == to!string(a));
7153 assert(to!string(cast(const) r) == to!string(cast(const) a));
7154 // Check that string conversion is still transparent for refcounted
7155 // structs that have alias this.
7156 static struct B { int b; alias b this; }
7157 static struct C { B b; alias b this; }
7158 assert(to!string(myRefCounted(C(B(123)))) == to!string(C(B(123))));
7159 // https://issues.dlang.org/show_bug.cgi?id=22093
7160 // Check that uninitialized refcounted structs that previously could be
7161 // converted to strings still can be.
7162 alias R = typeof(r);
7164 cast(void) (((const ref R a) => to!string(a))(r2));
7165 cast(void) to!string(MyRefCounted!(A, RefCountedAutoInitialize.no).init);
7169 // We tried to make `refCountedPayload` `@safe` in
7170 // https://github.com/dlang/phobos/pull/8368 . It proved impossible, but it may
7171 // be possible in the future. This test checks for false `@safe` issues we
7180 int[] getArr1 (scope Container local)
7182 // allowed because the argument is inferred as return scope.
7186 int[] getArr2 (scope Container local)
7188 SafeRefCounted!Container rc = local;
7189 // Escapes a reference to expired reference counted struct
7191 return rc.refCountedPayload().data;
7194 int destroyFirstAndUseLater()
7196 auto rc = SafeRefCounted!int(123);
7197 int* ptr = &rc.refCountedPayload();
7202 // This is here mainly to test that safety gets inferred correctly for the
7204 static assert(isSafe!getArr1);
7205 // https://github.com/dlang/phobos/pull/8101#issuecomment-843017282
7206 // This got apparently fixed automatically by compiler updates.
7207 static assert(!isSafe!getArr2);
7208 // As of writing, this is the issue that is still preventing payload access
7209 // from being `@safe`
7210 static assert(!isSafe!destroyFirstAndUseLater);
7214 Borrows the payload of $(LREF SafeRefCounted) for use in `fun`. Inferred as `@safe`
7215 if `fun` is `@safe` and does not escape a reference to the payload.
7216 The reference count will be incremented for the duration of the operation,
7217 so destroying the last reference will not leave dangling references in
7221 fun = A callable accepting the payload either by value or by reference.
7222 refCount = The counted reference to the payload.
7224 The return value of `fun`, if any. `ref` in the return value will be
7227 For yet unknown reason, code that uses this function with UFCS syntax
7228 will not be inferred as `@safe`. It will still compile if the code is
7229 explicitly marked `@safe` and nothing in `fun` prevents that.
7231 template borrow(alias fun)
7233 import std.functional : unaryFun;
7235 auto ref borrow(RC)(RC refCount) if
7237 isInstanceOf!(SafeRefCounted, RC)
7238 && is(typeof(unaryFun!fun(refCount.refCountedPayload)))
7241 refCount.checkInit();
7243 // If `fun` escapes a reference to the payload, it will be inferred
7244 // as unsafe due to the scope storage class here.
7245 scope plPtr = &refCount._refCounted._store._payload;
7246 return unaryFun!fun(*plPtr);
7248 // We destroy our copy of the reference here, automatically destroying
7249 // the payload if `fun` destroyed the last reference outside.
7253 /// This example can be marked `@safe` with `-preview=dip1000`.
7254 @safe pure nothrow unittest
7256 auto rcInt = safeRefCounted(5);
7257 assert(rcInt.borrow!(theInt => theInt) == 5);
7258 auto sameInt = rcInt;
7259 assert(sameInt.borrow!"a" == 5);
7261 // using `ref` in the function
7262 auto arr = [0, 1, 2, 3, 4, 5, 6];
7263 sameInt.borrow!(ref (x) => arr[x]) = 10;
7264 assert(arr == [0, 1, 2, 3, 4, 10, 6]);
7266 // modifying the payload via an alias
7267 sameInt.borrow!"a*=2";
7268 assert(rcInt.borrow!"a" == 10);
7271 // Some memory safety penetration testing.
7275 int torpedoesFired = 0;
7276 struct Destroyer { ~this() @safe { torpedoesFired++; } }
7278 alias RcInt = typeof(safeRefCounted(0));
7279 auto standardUsage(RcInt arg)
7281 return borrow!((ref x) => x)(arg);
7283 ref harmlessRefReturn(RcInt arg)
7285 return borrow!(ref (ref x) => *globalPtr = x)(arg);
7287 ref problematicRefReturn(RcInt arg)
7289 return borrow!(ref (ref x) => x)(arg);
7291 auto sideChannelEscape(RcInt arg)
7293 return borrow!((ref x)
7299 auto destroyDuringApply()
7301 auto rc = safeRefCounted(Destroyer());
7302 return borrow!((ref x)
7304 // Destroys the last reference to the payload, decrementing it's
7307 // Destroy again! rc should be set to it's init value so that this
7308 // won't decrement the reference count of the original payload.
7310 // The internal reference count increment done for duration of
7311 // `apply` should make sure that the payload destructor is not yet
7312 // run, and this value thus not incremented.
7313 return torpedoesFired;
7317 // First, let's verify the dangerous functions really do what they are
7319 auto testRc = safeRefCounted(42);
7320 assert(sideChannelEscape(testRc) == 42);
7321 assert(&problematicRefReturn(testRc) == globalPtr);
7323 // Now, are the @safe attributes inferred correctly?
7324 assert(isSafe!standardUsage);
7325 assert(isSafe!harmlessRefReturn);
7326 assert(!isSafe!problematicRefReturn);
7327 assert(!isSafe!sideChannelEscape);
7328 assert(isSafe!destroyDuringApply);
7330 // Finally, we test protection against early destruction during `apply`.
7331 auto torpedoesUpToReturn = destroyDuringApply();
7332 assert(torpedoesFired == torpedoesUpToReturn + 1);
7336 * Initializes a `SafeRefCounted` with `val`. The template parameter
7337 * `T` of `SafeRefCounted` is inferred from `val`.
7338 * This function can be used to move non-copyable values to the heap.
7339 * It also disables the `autoInit` option of `SafeRefCounted`.
7342 * val = The value to be reference counted
7344 * An initialized `SafeRefCounted` containing `val`.
7346 * $(LREF refCounted)
7347 * $(HTTP en.cppreference.com/w/cpp/memory/shared_ptr/make_shared, C++'s make_shared)
7349 SafeRefCounted!(T, RefCountedAutoInitialize.no) safeRefCounted(T)(T val)
7352 res._refCounted.move(val);
7361 static size_t nDestroyed;
7363 @disable this(this); // not copyable
7364 ~this() { name = null; ++nDestroyed; }
7367 auto file = File("name");
7368 assert(file.name == "name");
7369 // file cannot be copied and has unique ownership
7370 static assert(!__traits(compiles, {auto file2 = file;}));
7372 assert(File.nDestroyed == 0);
7374 // make the file ref counted to share ownership
7376 // We write a compound statement (brace-delimited scope) in which all `SafeRefCounted!File` handles are created and deleted.
7377 // This allows us to see (after the scope) what happens after all handles have been destroyed.
7379 // We move the content of `file` to a separate (and heap-allocated) `File` object,
7380 // managed-and-accessed via one-or-multiple (initially: one) `SafeRefCounted!File` objects ("handles").
7382 // (1) invokes `file`'s destructor (=> `File.nDestroyed` is incremented from 0 to 1 and `file.name` becomes `null`);
7383 // (2) overwrites `file` with `File.init` (=> `file.name` becomes `null`).
7384 // It appears that writing `name = null;` in the destructor is redundant,
7385 // but please note that (2) is only performed if `File` defines a destructor (or post-blit operator),
7386 // and in the absence of the `nDestroyed` instrumentation there would have been no reason to define a destructor.
7387 import std.algorithm.mutation : move;
7388 auto rcFile = safeRefCounted(move(file));
7389 assert(rcFile.name == "name");
7390 assert(File.nDestroyed == 1);
7391 assert(file.name == null);
7393 // We create another `SafeRefCounted!File` handle to the same separate `File` object.
7394 // While any of the handles is still alive, the `File` object is kept alive (=> `File.nDestroyed` is not modified).
7395 auto rcFile2 = rcFile;
7396 assert(rcFile.refCountedStore.refCount == 2);
7397 assert(File.nDestroyed == 1);
7399 // The separate `File` object is deleted when the last `SafeRefCounted!File` handle is destroyed
7400 // (i.e. at the closing brace of the compound statement above, which destroys both handles: `rcFile` and `rcFile2`)
7401 // (=> `File.nDestroyed` is incremented again, from 1 to 2):
7402 assert(File.nDestroyed == 2);
7406 Creates a proxy for the value `a` that will forward all operations
7407 while disabling implicit conversions. The aliased item `a` must be
7408 an $(B lvalue). This is useful for creating a new type from the
7409 "base" type (though this is $(B not) a subtype-supertype
7410 relationship; the new type is not related to the old type in any way,
7413 The new type supports all operations that the underlying type does,
7414 including all operators such as `+`, `--`, `<`, `[]`, etc.
7417 a = The value to act as a proxy for all operations. It must
7420 mixin template Proxy(alias a)
7422 private alias ValueType = typeof({ return a; }());
7424 /* Determine if 'T.a' can referenced via a const(T).
7425 * Use T* as the parameter because 'scope' inference needs a fully
7426 * analyzed T, which doesn't work when accessibleFrom() is used in a
7427 * 'static if' in the definition of Proxy or T.
7429 private enum bool accessibleFrom(T) =
7430 is(typeof((T* self){ cast(void) mixin("(*self)."~__traits(identifier, a)); }));
7432 static if (is(typeof(this) == class))
7434 override bool opEquals(Object o)
7436 if (auto b = cast(typeof(this))o)
7438 return a == mixin("b."~__traits(identifier, a));
7443 bool opEquals(T)(T b)
7444 if (is(ValueType : T) || is(typeof(a.opEquals(b))) || is(typeof(b.opEquals(a))))
7446 static if (is(typeof(a.opEquals(b))))
7447 return a.opEquals(b);
7448 else static if (is(typeof(b.opEquals(a))))
7449 return b.opEquals(a);
7454 override int opCmp(Object o)
7456 if (auto b = cast(typeof(this))o)
7458 return a < mixin("b."~__traits(identifier, a)) ? -1
7459 : a > mixin("b."~__traits(identifier, a)) ? +1 : 0;
7461 static if (is(ValueType == class))
7464 throw new Exception("Attempt to compare a "~typeid(this).toString~" and a "~typeid(o).toString);
7467 int opCmp(T)(auto ref const T b)
7468 if (is(ValueType : T) || is(typeof(a.opCmp(b))) || is(typeof(b.opCmp(a))))
7470 static if (is(typeof(a.opCmp(b))))
7472 else static if (is(typeof(b.opCmp(a))))
7475 return a < b ? -1 : a > b ? +1 : 0;
7478 static if (accessibleFrom!(const typeof(this)))
7480 override size_t toHash() const nothrow @safe
7482 static if (__traits(compiles, .hashOf(a)))
7485 // Workaround for when .hashOf is not both @safe and nothrow.
7487 static if (is(typeof(&a) == ValueType*))
7490 auto v = a; // if a is (property) function
7491 // BUG: Improperly casts away `shared`!
7492 return typeid(ValueType).getHash((() @trusted => cast(const void*) &v)());
7499 auto ref opEquals(this X, B)(auto ref B b)
7501 static if (is(immutable B == immutable typeof(this)))
7503 return a == mixin("b."~__traits(identifier, a));
7509 auto ref opCmp(this X, B)(auto ref B b)
7511 static if (is(typeof(a.opCmp(b))))
7513 else static if (is(typeof(b.opCmp(a))))
7515 else static if (isFloatingPoint!ValueType || isFloatingPoint!B)
7516 return a < b ? -1 : a > b ? +1 : a == b ? 0 : float.nan;
7518 return a < b ? -1 : (a > b);
7521 static if (accessibleFrom!(const typeof(this)))
7523 size_t toHash() const nothrow @safe
7525 static if (__traits(compiles, .hashOf(a)))
7528 // Workaround for when .hashOf is not both @safe and nothrow.
7530 static if (is(typeof(&a) == ValueType*))
7533 auto v = a; // if a is (property) function
7534 // BUG: Improperly casts away `shared`!
7535 return typeid(ValueType).getHash((() @trusted => cast(const void*) &v)());
7541 auto ref opCall(this X, Args...)(auto ref Args args) { return a(args); }
7543 auto ref opCast(T, this X)() { return cast(T) a; }
7545 auto ref opIndex(this X, D...)(auto ref D i) { return a[i]; }
7546 auto ref opSlice(this X )() { return a[]; }
7547 auto ref opSlice(this X, B, E)(auto ref B b, auto ref E e) { return a[b .. e]; }
7549 auto ref opUnary (string op, this X )() { return mixin(op~"a"); }
7550 auto ref opIndexUnary(string op, this X, D...)(auto ref D i) { return mixin(op~"a[i]"); }
7551 auto ref opSliceUnary(string op, this X )() { return mixin(op~"a[]"); }
7552 auto ref opSliceUnary(string op, this X, B, E)(auto ref B b, auto ref E e) { return mixin(op~"a[b .. e]"); }
7554 auto ref opBinary(string op, this X, B)(auto ref B b)
7555 if (op == "in" && is(typeof(a in b)) || op != "in")
7557 return mixin("a "~op~" b");
7559 auto ref opBinaryRight(string op, this X, B)(auto ref B b) { return mixin("b "~op~" a"); }
7561 static if (!is(typeof(this) == class))
7564 static if (isAssignable!ValueType)
7566 auto ref opAssign(this X)(auto ref typeof(this) v)
7568 a = mixin("v."~__traits(identifier, a));
7574 @disable void opAssign(this X)(auto ref typeof(this) v);
7578 auto ref opAssign (this X, V )(auto ref V v) if (!is(V == typeof(this))) { return a = v; }
7579 auto ref opIndexAssign(this X, V, D...)(auto ref V v, auto ref D i) { return a[i] = v; }
7580 auto ref opSliceAssign(this X, V )(auto ref V v) { return a[] = v; }
7581 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; }
7583 auto ref opOpAssign (string op, this X, V )(auto ref V v)
7585 return mixin("a = a "~op~" v");
7587 auto ref opIndexOpAssign(string op, this X, V, D...)(auto ref V v, auto ref D i)
7589 return mixin("a[i] " ~op~"= v");
7591 auto ref opSliceOpAssign(string op, this X, V )(auto ref V v)
7593 return mixin("a[] " ~op~"= v");
7595 auto ref opSliceOpAssign(string op, this X, V, B, E)(auto ref V v, auto ref B b, auto ref E e)
7597 return mixin("a[b .. e] "~op~"= v");
7600 template opDispatch(string name)
7602 static if (is(typeof(__traits(getMember, a, name)) == function))
7604 // non template function
7605 auto ref opDispatch(this X, Args...)(auto ref Args args) { return mixin("a."~name~"(args)"); }
7607 else static if (is(typeof({ enum x = mixin("a."~name); })))
7609 // built-in type field, manifest constant, and static non-mutable field
7610 enum opDispatch = mixin("a."~name);
7612 else static if (__traits(isTemplate, mixin("a."~name)))
7615 template opDispatch(T...)
7617 enum targs = T.length ? "!T" : "";
7618 auto ref opDispatch(this X, Args...)(auto ref Args args){ return mixin("a."~name~targs~"(args)"); }
7623 // field or property function
7624 @property auto ref opDispatch(this X)() { return mixin("a."~name); }
7625 @property auto ref opDispatch(this X, V)(auto ref V v) { return mixin("a."~name~" = v"); }
7630 import std.traits : isArray;
7632 static if (isArray!ValueType)
7634 auto opDollar() const { return a.length; }
7636 else static if (is(typeof(a.opDollar!0)))
7638 auto ref opDollar(size_t pos)() { return a.opDollar!pos(); }
7640 else static if (is(typeof(a.opDollar) == function))
7642 auto ref opDollar() { return a.opDollar(); }
7644 else static if (is(typeof(a.opDollar)))
7646 alias opDollar = a.opDollar;
7658 this(int n){ value = n; }
7663 // Enable operations that original type has.
7666 assert(n * 2 == 22);
7668 void func(int n) { }
7670 // Disable implicit conversions to original type.
7675 ///The proxied value must be an $(B lvalue).
7680 //Won't work; the literal '1'
7681 //is an rvalue, not an lvalue
7684 //Okay, n is an lvalue
7688 this(int n) { this.n = n; }
7696 struct NewObjectType
7699 //Ok, obj is an lvalue
7702 this (Object o) { obj = o; }
7705 NewObjectType not = new Object();
7706 assert(__traits(compiles, not.toHash()));
7710 There is one exception to the fact that the new type is not related to the
7711 old type. $(DDSUBLINK spec/function,pseudo-member, Pseudo-member)
7712 functions are usable with the new type; they will be forwarded on to the
7717 import std.math.traits : isInfinity;
7720 assert(!f.isInfinity);
7727 this(float f) { _ = f; }
7731 assert(!nf.isInfinity);
7740 this(int n) inout { value = n; }
7743 static immutable arr = [1,2,3];
7746 static foreach (T; AliasSeq!(MyInt, const MyInt, immutable MyInt))
7749 static assert(!__traits(compiles, { int x = m; }));
7750 static assert(!__traits(compiles, { void func(int n){} func(m); }));
7756 assert(cast(double) m == 10.0);
7757 assert(m + 10 == 20);
7759 assert(m * 20 == 200);
7761 assert(10 + m == 20);
7762 assert(15 - m == 5);
7763 assert(20 * m == 200);
7764 assert(50 / m == 5);
7765 static if (is(T == MyInt)) // mutable
7768 assert(m++ == 11); assert(m == 12);
7770 assert(m-- == 11); assert(m == 10);
7772 m = 20; assert(m == 20);
7774 static assert(T.max == int.max);
7775 static assert(T.min == int.min);
7776 static assert(T.init == int.init);
7777 static assert(T.str == "str");
7778 static assert(T.arr == [1,2,3]);
7783 static struct MyArray
7785 private int[] value;
7787 this(int[] arr) { value = arr; }
7788 this(immutable int[] arr) immutable { value = arr; }
7791 static foreach (T; AliasSeq!(MyArray, const MyArray, immutable MyArray))
7793 static if (is(T == immutable) && !is(typeof({ T a = [1,2,3,4]; })))
7794 T a = [1,2,3,4].idup; // workaround until qualified ctor is properly supported
7797 assert(a == [1,2,3,4]);
7798 assert(a != [5,6,7,8]);
7800 version (LittleEndian)
7801 assert(cast(ulong[]) a == [0x0000_0002_0000_0001, 0x0000_0004_0000_0003]);
7803 assert(cast(ulong[]) a == [0x0000_0001_0000_0002, 0x0000_0003_0000_0004]);
7804 assert(a ~ [10,11] == [1,2,3,4,10,11]);
7806 assert(a[] == [1,2,3,4]);
7807 assert(a[2 .. 4] == [3,4]);
7808 static if (is(T == MyArray)) // mutable
7811 a = [5,6,7,8]; assert(a == [5,6,7,8]);
7812 a[0] = 0; assert(a == [0,6,7,8]);
7813 a[] = 1; assert(a == [1,1,1,1]);
7814 a[0 .. 3] = 2; assert(a == [2,2,2,1]);
7815 a[0] += 2; assert(a == [4,2,2,1]);
7816 a[] *= 2; assert(a == [8,4,4,2]);
7817 a[0 .. 2] /= 2; assert(a == [4,2,4,2]);
7827 @property int val1() const { return field; }
7828 @property void val1(int n) { field = n; }
7830 @property ref int val2() { return field; }
7832 int func(int x, int y) const { return x; }
7833 void func1(ref int a) { a = 9; }
7835 T ifti1(T)(T t) { return t; }
7836 void ifti2(Args...)(Args args) { }
7837 void ifti3(T, Args...)(Args args) { }
7839 T opCast(T)(){ return T.init; }
7841 T tempfunc(T)() { return T.init; }
7847 this(Foo f) { foo = f; }
7850 auto h = new Hoge(new Foo());
7853 static assert(!__traits(compiles, { Foo f = h; }));
7856 h.field = 1; // lhs of assign
7857 n = h.field; // rhs of assign
7858 assert(h.field == 1); // lhs of BinExp
7859 assert(1 == h.field); // rhs of BinExp
7862 // getter/setter property function
7865 assert(h.val1 == 4);
7866 assert(4 == h.val1);
7869 // ref getter property function
7872 assert(h.val2 == 8);
7873 assert(8 == h.val2);
7877 assert(h.func(2,4) == 2);
7882 assert(h.ifti1(4) == 4);
7886 // https://issues.dlang.org/show_bug.cgi?id=5896 test
7887 assert(h.opCast!int() == 0);
7888 assert(cast(int) h == 0);
7889 const ih = new const Hoge(new Foo());
7890 static assert(!__traits(compiles, ih.opCast!int()));
7891 static assert(!__traits(compiles, cast(int) ih));
7893 // template member function
7894 assert(h.tempfunc!int() == 0);
7897 @system unittest // about Proxy inside a class
7902 mixin Proxy!payload;
7903 this(int i){ payload = i; }
7904 string opCall(string msg){ return msg; }
7905 int pow(int i){ return payload ^^ i; }
7911 mixin Proxy!payload;
7912 this(int i){ payload = new MyClass(i); }
7918 mixin Proxy!payload;
7919 this(int i){ payload = i; }
7923 Object a = new MyClass(5);
7924 Object b = new MyClass(5);
7925 Object c = new MyClass2(5);
7926 Object d = new MyClass3(5);
7928 assert((cast(MyClass) a) == 5);
7929 assert(5 == (cast(MyClass) b));
7930 assert(5 == cast(MyClass2) c);
7934 // oops! above line is unexpected, isn't it?
7935 // the reason is below.
7936 // MyClass2.opEquals knows MyClass but,
7937 // MyClass.opEquals doesn't know MyClass2.
7938 // so, c.opEquals(a) is true, but a.opEquals(c) is false.
7939 // furthermore, opEquals(T) couldn't be invoked.
7940 assert((cast(MyClass2) c) != (cast(MyClass) a));
7943 Object e = new MyClass2(7);
7944 assert(a < cast(MyClass2) e); // OK. and
7945 assert(e > a); // OK, but...
7946 // assert(a < e); // RUNTIME ERROR!
7947 // assert((cast(MyClass) a) < e); // RUNTIME ERROR!
7948 assert(3 < cast(MyClass) a);
7949 assert((cast(MyClass2) e) < 11);
7952 assert((cast(MyClass2) e)("hello") == "hello");
7955 assert((cast(MyClass)(cast(MyClass2) c)) == a);
7956 assert((cast(int)(cast(MyClass2) c)) == 5);
7962 mixin Proxy!payload;
7963 this(string s){ payload = s; }
7968 mixin Proxy!payload;
7969 this(string s){ payload = new MyClass4(s); }
7971 auto f = new MyClass4("hello");
7972 assert(f[1] == 'e');
7973 auto g = new MyClass5("hello");
7974 assert(f[1] == 'e');
7977 assert(f[2 .. 4] == "ll");
7980 assert(-(cast(MyClass2) c) == -5);
7983 assert((cast(MyClass) a) + (cast(MyClass2) c) == 10);
7984 assert(5 + cast(MyClass) a == 10);
7987 (cast(MyClass2) c) = 11;
7988 assert((cast(MyClass2) c) == 11);
7989 (cast(MyClass2) c) = new MyClass(13);
7990 assert((cast(MyClass2) c) == 13);
7993 assert((cast(MyClass2) c) += 4);
7994 assert((cast(MyClass2) c) == 17);
7997 assert((cast(MyClass2) c).pow(2) == 289);
8000 assert(f[2..$-1] == "ll");
8006 assert(hash[b] == 19);
8007 assert(hash[c] == 21);
8016 mixin Proxy!payload;
8024 @disable void opAssign(typeof(this));
8030 mixin Proxy!payload;
8033 static assert(!__traits(compiles, f = f));
8039 mixin Proxy!payload;
8041 // override default Proxy behavior
8042 void opAssign(typeof(this) rhs){}
8048 // https://issues.dlang.org/show_bug.cgi?id=8613
8055 this(string s) { val = s; }
8059 names[Name("a")] = true;
8060 bool* b = Name("a") in names;
8063 // workaround for https://issues.dlang.org/show_bug.cgi?id=19669
8064 private enum isDIP1000 = __traits(compiles, () @safe {
8069 // excludes struct S; it's 'mixin Proxy!foo' doesn't compile with -dip1000
8070 static if (isDIP1000) {} else
8073 // https://issues.dlang.org/show_bug.cgi?id=14213
8074 // using function for the payload
8077 int foo() { return 12; }
8081 assert(s + 1 == 13);
8082 assert(s * 2 == 24);
8089 int foo() { return 12; }
8095 // Check all floating point comparisons for both Proxy and Typedef,
8096 // also against int and a Typedef!int, to be as regression-proof
8097 // as possible. https://issues.dlang.org/show_bug.cgi?id=15561
8100 static struct MyFloatImpl
8105 static void allFail(T0, T1)(T0 a, T1 b)
8113 static foreach (T1; AliasSeq!(MyFloatImpl, Typedef!float, Typedef!double,
8114 float, real, Typedef!int, int))
8116 static foreach (T2; AliasSeq!(MyFloatImpl, Typedef!float))
8121 static if (isFloatingPoint!T1 || isFloatingPoint!(TypedefType!T1))
8144 $(B Typedef) allows the creation of a unique type which is
8145 based on an existing type. Unlike the `alias` feature,
8146 $(B Typedef) ensures the two types are not considered as equals.
8150 init = Optional initial value for the new type.
8151 cookie = Optional, used to create multiple unique types which are
8152 based on the same origin type `T`
8154 Note: If a library routine cannot handle the Typedef type,
8155 you can use the `TypedefType` template to extract the
8156 type which the Typedef wraps.
8158 struct Typedef(T, T init = T.init, string cookie=null)
8160 private T Typedef_payload = init;
8162 // https://issues.dlang.org/show_bug.cgi?id=18415
8163 // prevent default construction if original type does too.
8164 static if ((is(T == struct) || is(T == union)) && !is(typeof({T t;})))
8171 Typedef_payload = init;
8176 this(tdef.Typedef_payload);
8179 // We need to add special overload for cast(Typedef!X) exp,
8180 // thus we can't simply inherit Proxy!Typedef_payload
8181 T2 opCast(T2 : Typedef!(T, Unused), this X, T, Unused...)()
8183 return T2(cast(T) Typedef_payload);
8186 auto ref opCast(T2, this X)()
8188 return cast(T2) Typedef_payload;
8191 mixin Proxy!Typedef_payload;
8193 pure nothrow @nogc @safe @property
8195 alias TD = typeof(this);
8196 static if (isIntegral!T)
8198 static TD min() {return TD(T.min);}
8199 static TD max() {return TD(T.max);}
8201 else static if (isFloatingPoint!T)
8203 static TD infinity() {return TD(T.infinity);}
8204 static TD nan() {return TD(T.nan);}
8205 static TD dig() {return TD(T.dig);}
8206 static TD epsilon() {return TD(T.epsilon);}
8207 static TD mant_dig() {return TD(T.mant_dig);}
8208 static TD max_10_exp() {return TD(T.max_10_exp);}
8209 static TD max_exp() {return TD(T.max_exp);}
8210 static TD min_10_exp() {return TD(T.min_10_exp);}
8211 static TD min_exp() {return TD(T.min_exp);}
8212 static TD max() {return TD(T.max);}
8213 static TD min_normal() {return TD(T.min_normal);}
8214 TD re() {return TD(Typedef_payload.re);}
8215 TD im() {return TD(Typedef_payload.im);}
8220 * Convert wrapped value to a human readable string
8222 string toString(this T)()
8224 import std.array : appender;
8225 auto app = appender!string();
8226 auto spec = singleSpec("%s");
8227 toString(app, spec);
8232 void toString(this T, W)(ref W writer, scope const ref FormatSpec!char fmt)
8233 if (isOutputRange!(W, char))
8235 formatValue(writer, Typedef_payload, fmt);
8241 import std.conv : to;
8244 auto td = Typedef!int(i);
8245 assert(i.to!string == td.to!string);
8252 alias MyInt = Typedef!int;
8258 /// custom initialization values
8261 alias MyIntInit = Typedef!(int, 42);
8262 static assert(is(TypedefType!MyIntInit == int));
8263 static assert(MyIntInit() == 42);
8266 /// Typedef creates a new type
8269 alias MyInt = Typedef!int;
8270 static void takeInt(int) {}
8271 static void takeMyInt(MyInt) {}
8275 static assert(!__traits(compiles, takeMyInt(i)));
8278 static assert(!__traits(compiles, takeInt(myInt)));
8279 takeMyInt(myInt); // ok
8282 /// Use the optional `cookie` argument to create different types of the same base type
8285 alias TypeInt1 = Typedef!int;
8286 alias TypeInt2 = Typedef!int;
8288 // The two Typedefs are the same type.
8289 static assert(is(TypeInt1 == TypeInt2));
8291 alias MoneyEuros = Typedef!(float, float.init, "euros");
8292 alias MoneyDollars = Typedef!(float, float.init, "dollars");
8294 // The two Typedefs are _not_ the same type.
8295 static assert(!is(MoneyEuros == MoneyDollars));
8298 // https://issues.dlang.org/show_bug.cgi?id=12461
8301 alias Int = Typedef!int;
8309 Get the underlying type which a `Typedef` wraps.
8310 If `T` is not a `Typedef` it will alias itself to `T`.
8312 template TypedefType(T)
8314 static if (is(T : Typedef!Arg, Arg))
8315 alias TypedefType = Arg;
8317 alias TypedefType = T;
8323 import std.conv : to;
8325 alias MyInt = Typedef!int;
8326 static assert(is(TypedefType!MyInt == int));
8328 /// Instantiating with a non-Typedef will return that type
8329 static assert(is(TypedefType!int == int));
8333 // extract the needed type
8334 MyInt myInt = MyInt( num.to!(TypedefType!MyInt) );
8337 // cast to the underlying type to get the value that's being wrapped
8338 int x = cast(TypedefType!MyInt) myInt;
8340 alias MyIntInit = Typedef!(int, 42);
8341 static assert(is(TypedefType!MyIntInit == int));
8342 static assert(MyIntInit() == 42);
8348 static assert(!__traits(compiles, { int y = x; }));
8349 static assert(!__traits(compiles, { long z = x; }));
8354 static assert(Typedef!int.init == int.init);
8356 Typedef!(float, 1.0) z; // specifies the init
8359 static assert(typeof(z).init == 1.0);
8361 alias Dollar = Typedef!(int, 0, "dollar");
8362 alias Yen = Typedef!(int, 0, "yen");
8363 static assert(!is(Dollar == Yen));
8365 Typedef!(int[3]) sa;
8366 static assert(sa.length == 3);
8367 static assert(typeof(sa).length == 3);
8369 Typedef!(int[3]) dollar1;
8370 assert(dollar1[0..$] is dollar1[0 .. 3]);
8372 Typedef!(int[]) dollar2;
8374 assert(dollar2[0..$] is dollar2[0 .. 3]);
8376 static struct Dollar1
8378 static struct DollarToken {}
8379 enum opDollar = DollarToken.init;
8380 auto opSlice(size_t, DollarToken) { return 1; }
8381 auto opSlice(size_t, size_t) { return 2; }
8384 Typedef!Dollar1 drange1;
8385 assert(drange1[0..$] == 1);
8386 assert(drange1[0 .. 1] == 2);
8388 static struct Dollar2
8390 size_t opDollar(size_t pos)() { return pos == 0 ? 1 : 100; }
8391 size_t opIndex(size_t i, size_t j) { return i + j; }
8394 Typedef!Dollar2 drange2;
8395 assert(drange2[$, $] == 101);
8397 static struct Dollar3
8399 size_t opDollar() { return 123; }
8400 size_t opIndex(size_t i) { return i; }
8403 Typedef!Dollar3 drange3;
8404 assert(drange3[$] == 123);
8407 // https://issues.dlang.org/show_bug.cgi?id=18415
8408 @safe @nogc pure nothrow unittest
8410 struct NoDefCtorS{@disable this();}
8411 union NoDefCtorU{@disable this();}
8412 static assert(!is(typeof({Typedef!NoDefCtorS s;})));
8413 static assert(!is(typeof({Typedef!NoDefCtorU u;})));
8416 // https://issues.dlang.org/show_bug.cgi?id=11703
8417 @safe @nogc pure nothrow unittest
8419 alias I = Typedef!int;
8420 static assert(is(typeof(I.min) == I));
8421 static assert(is(typeof(I.max) == I));
8423 alias F = Typedef!double;
8424 static assert(is(typeof(F.infinity) == F));
8425 static assert(is(typeof(F.epsilon) == F));
8428 assert(!is(typeof(F.re).stringof == double));
8429 assert(!is(typeof(F.im).stringof == double));
8434 // https://issues.dlang.org/show_bug.cgi?id=8655
8435 import std.typecons;
8436 import std.bitmanip;
8437 static import core.stdc.config;
8439 alias c_ulong = Typedef!(core.stdc.config.c_ulong);
8444 c_ulong, "NameOffset", 31,
8445 c_ulong, "NameIsString", 1
8450 // https://issues.dlang.org/show_bug.cgi?id=12596
8453 import std.typecons;
8454 alias TD = Typedef!int;
8460 @safe unittest // about toHash
8462 import std.typecons;
8464 alias TD = Typedef!int;
8467 assert(td[TD(1)] == 1);
8471 alias TD = Typedef!(int[]);
8473 td[TD([1,2,3,4])] = 2;
8474 assert(td[TD([1,2,3,4])] == 2);
8478 alias TD = Typedef!(int[][]);
8480 td[TD([[1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]])] = 3;
8481 assert(td[TD([[1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]])] == 3);
8485 struct MyStruct{ int x; }
8486 alias TD = Typedef!MyStruct;
8488 td[TD(MyStruct(10))] = 4;
8489 assert(TD(MyStruct(20)) !in td);
8490 assert(td[TD(MyStruct(10))] == 4);
8494 static struct MyStruct2
8497 size_t toHash() const nothrow @safe { return x; }
8498 bool opEquals(ref const MyStruct2 r) const { return r.x == x; }
8501 alias TD = Typedef!MyStruct2;
8503 td[TD(MyStruct2(50))] = 5;
8504 assert(td[TD(MyStruct2(50))] == 5);
8509 alias TD = Typedef!MyClass;
8511 auto c = new MyClass;
8513 assert(TD(new MyClass) !in td);
8514 assert(td[TD(c)] == 6);
8520 alias String = Typedef!(char[]);
8521 alias CString = Typedef!(const(char)[]);
8522 CString cs = "fubar";
8523 String s = cast(String) cs;
8525 char[] s2 = cast(char[]) cs;
8526 const(char)[] cs2 = cast(const(char)[])s;
8530 @system unittest // toString
8532 import std.meta : AliasSeq;
8533 import std.conv : to;
8538 static foreach (T; AliasSeq!(int, bool, float, double, real,
8541 int*, int[], int[2], int[int]))
8546 Typedef!(const T) ctd;
8547 Typedef!(immutable T) itd;
8549 assert(t.to!string() == td.to!string());
8551 static if (!(is(T == TestS) || is(T == TestC)))
8553 assert(t.to!string() == ctd.to!string());
8554 assert(t.to!string() == itd.to!string());
8559 @safe @nogc unittest // typedef'ed type with custom operators
8564 int opCmp(MyInt other)
8566 if (value < other.value)
8568 return !(value == other.value);
8572 auto m1 = Typedef!MyInt(MyInt(1));
8573 auto m2 = Typedef!MyInt(MyInt(2));
8578 Allocates a `class` object right inside the current scope,
8579 therefore avoiding the overhead of `new`. This facility is unsafe;
8580 it is the responsibility of the user to not escape a reference to the
8581 object outside the scope.
8583 The class destructor will be called when the result of `scoped()` is
8586 Scoped class instances can be embedded in a parent `class` or `struct`,
8587 just like a child struct instance. Scoped member variables must have
8588 type `typeof(scoped!Class(args))`, and be initialized with a call to
8589 scoped. See below for an example.
8592 It's illegal to move a class instance even if you are sure there
8593 are no pointers to it. As such, it is illegal to move a scoped object.
8598 // _d_newclass now use default GC alignment (looks like (void*).sizeof * 2 for
8599 // small objects). We will just use the maximum of filed alignments.
8600 enum alignment = __traits(classInstanceAlignment, T);
8601 alias aligned = _alignUp!alignment;
8603 static struct Scoped
8605 // Addition of `alignment` is required as `Scoped_store` can be misaligned in memory.
8606 private void[aligned(__traits(classInstanceSize, T) + size_t.sizeof) + alignment] Scoped_store = void;
8608 @property inout(T) Scoped_payload() inout
8610 void* alignedStore = cast(void*) aligned(cast(size_t) Scoped_store.ptr);
8611 // As `Scoped` can be unaligned moved in memory class instance should be moved accordingly.
8612 immutable size_t d = alignedStore - Scoped_store.ptr;
8613 size_t* currD = cast(size_t*) &Scoped_store[$ - size_t.sizeof];
8616 import core.stdc.string : memmove;
8617 memmove(alignedStore, Scoped_store.ptr + *currD, __traits(classInstanceSize, T));
8620 return cast(inout(T)) alignedStore;
8622 alias Scoped_payload this;
8625 @disable this(this);
8629 // `destroy` will also write .init but we have no functions in druntime
8630 // for deterministic finalization and memory releasing for now.
8631 .destroy(Scoped_payload);
8635 /** Returns the _scoped object.
8636 Params: args = Arguments to pass to `T`'s constructor.
8638 @system auto scoped(Args...)(auto ref Args args)
8640 import core.lifetime : emplace, forward;
8642 Scoped result = void;
8643 void* alignedStore = cast(void*) aligned(cast(size_t) result.Scoped_store.ptr);
8644 immutable size_t d = alignedStore - result.Scoped_store.ptr;
8645 *cast(size_t*) &result.Scoped_store[$ - size_t.sizeof] = d;
8646 emplace!(Unqual!T)(result.Scoped_store[d .. $ - size_t.sizeof], forward!args);
8662 // Standard usage, constructing A on the stack
8663 auto a1 = scoped!A();
8666 // Result of `scoped` call implicitly converts to a class reference
8668 assert(aRef.x == 42);
8670 // Scoped destruction
8672 auto a2 = scoped!A(1);
8675 // a2 is destroyed here, calling A's destructor
8677 // aRef is now an invalid reference
8679 // Here the temporary scoped A is immediately destroyed.
8680 // This means the reference is then invalid.
8683 // Wrong, should use `auto`
8684 A invalid = scoped!A();
8690 import std.algorithm.mutation : move;
8691 auto invalid = a1.move; // illegal, scoped objects can't be moved
8693 static assert(!is(typeof({
8694 auto e1 = a1; // illegal, scoped objects can't be copied
8695 assert([a1][0].x == 42); // ditto
8697 static assert(!is(typeof({
8698 alias ScopedObject = typeof(a1);
8699 auto e2 = ScopedObject(); // illegal, must be built via scoped!A
8700 auto e3 = ScopedObject(1); // ditto
8704 alias makeScopedA = scoped!A;
8705 auto a3 = makeScopedA();
8706 auto a4 = makeScopedA(1);
8708 // Use as member variable
8711 typeof(scoped!A()) a; // note the trailing parentheses
8723 assert(aRef.x == 5);
8724 destroy(b1); // calls A's destructor for b1.a
8725 // aRef is now an invalid reference
8729 assert(b2.a.x == 6);
8730 destroy(*b2); // calls A's destructor for b2.a
8733 private size_t _alignUp(size_t alignment)(size_t n)
8734 if (alignment > 0 && !((alignment - 1) & alignment))
8736 enum badEnd = alignment - 1; // 0b11, 0b111, ...
8737 return (n + badEnd) & ~badEnd;
8740 // https://issues.dlang.org/show_bug.cgi?id=6580 testcase
8743 enum alignment = (void*).alignof;
8746 static class C1 { byte b; }
8747 static class C2 { byte[2] b; }
8748 static class C3 { byte[3] b; }
8749 static class C7 { byte[7] b; }
8750 static assert(scoped!C0().sizeof % alignment == 0);
8751 static assert(scoped!C1().sizeof % alignment == 0);
8752 static assert(scoped!C2().sizeof % alignment == 0);
8753 static assert(scoped!C3().sizeof % alignment == 0);
8754 static assert(scoped!C7().sizeof % alignment == 0);
8756 enum longAlignment = long.alignof;
8759 long long_; byte byte_ = 4;
8761 this(long _long, ref int i) { long_ = _long; ++i; }
8763 static class C2long { byte[2] byte_ = [5, 6]; long long_ = 7; }
8764 static assert(scoped!C1long().sizeof % longAlignment == 0);
8765 static assert(scoped!C2long().sizeof % longAlignment == 0);
8767 void alignmentTest()
8770 auto c1long = scoped!C1long(3, var);
8772 auto c2long = scoped!C2long();
8773 assert(cast(uint)&c1long.long_ % longAlignment == 0);
8774 assert(cast(uint)&c2long.long_ % longAlignment == 0);
8775 assert(c1long.long_ == 3 && c1long.byte_ == 4);
8776 assert(c2long.byte_ == [5, 6] && c2long.long_ == 7);
8781 version (DigitalMars)
8783 void test(size_t size)
8785 import core.stdc.stdlib : alloca;
8786 cast(void) alloca(size);
8789 foreach (i; 0 .. 10)
8794 void test(size_t size)()
8799 static foreach (i; 0 .. 11)
8804 // Original https://issues.dlang.org/show_bug.cgi?id=6580 testcase
8807 class C { int i; byte b; }
8809 auto sa = [scoped!C(), scoped!C()];
8810 assert(cast(uint)&sa[0].i % int.alignof == 0);
8811 assert(cast(uint)&sa[1].i % int.alignof == 0); // fails
8816 class A { int x = 1; }
8817 auto a1 = scoped!A();
8819 auto a2 = scoped!A();
8827 class A { int x = 1; this() { x = 2; } }
8828 auto a1 = scoped!A();
8830 auto a2 = scoped!A();
8838 class A { int x = 1; this(int y) { x = y; } ~this() {} }
8839 auto a1 = scoped!A(5);
8841 auto a2 = scoped!A(42);
8849 class A { static bool dead; ~this() { dead = true; } }
8850 class B : A { static bool dead; ~this() { dead = true; } }
8852 auto b = scoped!B();
8854 assert(B.dead, "asdasd");
8855 assert(A.dead, "asdasd");
8858 // https://issues.dlang.org/show_bug.cgi?id=8039 testcase
8862 static struct S { ~this(){ ++dels; } }
8864 static class A { S s; }
8865 dels = 0; { scoped!A(); }
8868 static class B { S[2] s; }
8869 dels = 0; { scoped!B(); }
8872 static struct S2 { S[3] s; }
8873 static class C { S2[2] s; }
8874 dels = 0; { scoped!C(); }
8877 static class D: A { S2[2] s; }
8878 dels = 0; { scoped!D(); }
8879 assert(dels == 1+6);
8884 // https://issues.dlang.org/show_bug.cgi?id=4500
8887 this() { a = this; }
8888 this(int i) { a = this; }
8890 bool check() { return this is a; }
8893 auto a1 = scoped!A();
8896 auto a2 = scoped!A(1);
8909 this() { ++sdtor; assert(sdtor == 1); }
8910 ~this() { assert(sdtor == 1); --sdtor; }
8915 static class ABob : A, Bob
8917 this() { ++sdtor; assert(sdtor == 2); }
8918 ~this() { assert(sdtor == 2); --sdtor; }
8922 scope(exit) assert(A.sdtor == 0);
8923 auto abob = scoped!ABob();
8928 static class A { this(int) {} }
8929 static assert(!__traits(compiles, scoped!A()));
8934 static class A { @property inout(int) foo() inout { return 1; } }
8936 auto a1 = scoped!A();
8937 assert(a1.foo == 1);
8938 static assert(is(typeof(a1.foo) == int));
8940 auto a2 = scoped!(const(A))();
8941 assert(a2.foo == 1);
8942 static assert(is(typeof(a2.foo) == const(int)));
8944 auto a3 = scoped!(immutable(A))();
8945 assert(a3.foo == 1);
8946 static assert(is(typeof(a3.foo) == immutable(int)));
8948 const c1 = scoped!A();
8949 assert(c1.foo == 1);
8950 static assert(is(typeof(c1.foo) == const(int)));
8952 const c2 = scoped!(const(A))();
8953 assert(c2.foo == 1);
8954 static assert(is(typeof(c2.foo) == const(int)));
8956 const c3 = scoped!(immutable(A))();
8957 assert(c3.foo == 1);
8958 static assert(is(typeof(c3.foo) == immutable(int)));
8965 this(int rval) { assert(rval == 1); }
8966 this(ref int lval) { assert(lval == 3); ++lval; }
8969 auto c1 = scoped!C(1);
8971 auto c2 = scoped!C(lval);
8983 alias makeScopedC = scoped!C;
8985 auto a = makeScopedC();
8986 auto b = makeScopedC(1);
8987 auto c = makeScopedC(1, 1);
8989 static assert(is(typeof(a) == typeof(b)));
8990 static assert(is(typeof(b) == typeof(c)));
8994 Defines a simple, self-documenting yes/no flag. This makes it easy for
8995 APIs to define functions accepting flags without resorting to $(D
8996 bool), which is opaque in calls, and without needing to define an
8997 enumerated type separately. Using `Flag!"Name"` instead of $(D
8998 bool) makes the flag's meaning visible in calls. Each yes/no flag has
8999 its own type, which makes confusions and mix-ups impossible.
9003 Code calling `getLine` (usually far away from its definition) can't be
9004 understood without looking at the documentation, even by users familiar with
9007 string getLine(bool keepTerminator)
9010 if (keepTerminator) ...
9014 auto line = getLine(false);
9017 Assuming the reverse meaning (i.e. "ignoreTerminator") and inserting the wrong
9018 code compiles and runs with erroneous results.
9020 After replacing the boolean parameter with an instantiation of `Flag`, code
9021 calling `getLine` can be easily read and understood even by people not
9022 fluent with the API:
9025 string getLine(Flag!"keepTerminator" keepTerminator)
9028 if (keepTerminator) ...
9032 auto line = getLine(Yes.keepTerminator);
9035 The structs `Yes` and `No` are provided as shorthand for
9036 `Flag!"Name".yes` and `Flag!"Name".no` and are preferred for brevity and
9037 readability. These convenience structs mean it is usually unnecessary and
9038 counterproductive to create an alias of a `Flag` as a way of avoiding typing
9039 out the full type while specifying the affirmative or negative options.
9041 Passing categorical data by means of unstructured `bool`
9042 parameters is classified under "simple-data coupling" by Steve
9043 McConnell in the $(LUCKY Code Complete) book, along with three other
9044 kinds of coupling. The author argues citing several studies that
9045 coupling has a negative effect on code quality. `Flag` offers a
9046 simple structuring method for passing yes/no flags to APIs.
9048 template Flag(string name) {
9053 When creating a value of type `Flag!"Name"`, use $(D
9054 Flag!"Name".no) for the negative option. When using a value
9055 of type `Flag!"Name"`, compare it against $(D
9056 Flag!"Name".no) or just `false` or `0`. */
9059 /** When creating a value of type `Flag!"Name"`, use $(D
9060 Flag!"Name".yes) for the affirmative option. When using a
9061 value of type `Flag!"Name"`, compare it against $(D
9073 assert(flag == Flag!"abc".no);
9074 assert(flag == No.abc);
9076 if (flag) assert(0);
9082 auto flag = Yes.abc;
9085 assert(flag == Yes.abc);
9086 if (!flag) assert(0);
9087 if (flag) {} else assert(0);
9091 Convenience names that allow using e.g. `Yes.encryption` instead of
9092 `Flag!"encryption".yes` and `No.encryption` instead of $(D
9093 Flag!"encryption".no).
9097 template opDispatch(string name)
9099 enum opDispatch = Flag!name.yes;
9102 //template yes(string name) { enum Flag!name yes = Flag!name.yes; }
9107 template opDispatch(string name)
9109 enum opDispatch = Flag!name.no;
9118 assert(flag == Flag!"abc".no);
9119 assert(flag == No.abc);
9121 if (flag) assert(0);
9127 auto flag = Yes.abc;
9130 assert(flag == Yes.abc);
9131 if (!flag) assert(0);
9132 if (flag) {} else assert(0);
9136 Detect whether an enum is of integral type and has only "flag" values
9137 (i.e. values with a bit count of exactly 1).
9138 Additionally, a zero value is allowed for compatibility with enums including
9141 template isBitFlagEnum(E)
9143 static if (is(E Base == enum) && isIntegral!Base)
9145 enum isBitFlagEnum = (E.min >= 0) &&
9147 static foreach (immutable flag; EnumMembers!E)
9151 if (value != 0) return false;
9158 enum isBitFlagEnum = false;
9163 @safe pure nothrow unittest
9174 static assert(isBitFlagEnum!A);
9177 /// Test an enum with default (consecutive) values
9178 @safe pure nothrow unittest
9188 static assert(!isBitFlagEnum!B);
9191 /// Test an enum with non-integral values
9192 @safe pure nothrow unittest
9200 static assert(!isBitFlagEnum!C);
9204 A typesafe structure for storing combinations of enum values.
9206 This template defines a simple struct to represent bitwise OR combinations of
9207 enum values. It can be used if all the enum values are integral constants with
9208 a bit count of at most 1, or if the `unsafe` parameter is explicitly set to
9210 This is much safer than using the enum itself to store
9211 the OR combination, which can produce surprising effects like this:
9219 // will throw SwitchError
9229 struct BitFlags(E, Flag!"unsafe" unsafe = No.unsafe)
9230 if (unsafe || isBitFlagEnum!(E))
9232 @safe @nogc pure nothrow:
9234 enum isBaseEnumType(T) = is(E == T);
9235 alias Base = OriginalType!E;
9245 if (allSatisfy!(isBaseEnumType, T))
9250 bool opCast(B: bool)() const
9255 Base opCast(B)() const
9261 auto opUnary(string op)() const
9264 return BitFlags(cast(E) cast(Base) ~mValue);
9267 auto ref opAssign(T...)(T flags)
9268 if (allSatisfy!(isBaseEnumType, T))
9271 foreach (E flag; flags)
9278 auto ref opAssign(E flag)
9284 auto ref opOpAssign(string op: "|")(BitFlags flags)
9286 mValue |= flags.mValue;
9290 auto ref opOpAssign(string op: "&")(BitFlags flags)
9292 mValue &= flags.mValue;
9296 auto ref opOpAssign(string op: "|")(E flag)
9302 auto ref opOpAssign(string op: "&")(E flag)
9308 auto opBinary(string op)(BitFlags flags) const
9309 if (op == "|" || op == "&")
9311 BitFlags result = this;
9312 result.opOpAssign!op(flags);
9316 auto opBinary(string op)(E flag) const
9317 if (op == "|" || op == "&")
9319 BitFlags result = this;
9320 result.opOpAssign!op(flag);
9324 auto opBinaryRight(string op)(E flag) const
9325 if (op == "|" || op == "&")
9327 return opBinary!op(flag);
9330 bool opDispatch(string name)() const
9331 if (__traits(hasMember, E, name))
9333 enum e = __traits(getMember, E, name);
9334 return (mValue & e) == e;
9337 void opDispatch(string name)(bool set)
9338 if (__traits(hasMember, E, name))
9340 enum e = __traits(getMember, E, name);
9348 /// Set values with the | operator and test with &
9349 @safe @nogc pure nothrow unittest
9356 // A default constructed BitFlags has no value set
9357 immutable BitFlags!Enum flags_empty;
9358 assert(!flags_empty.A);
9360 // Value can be set with the | operator
9361 immutable flags_A = flags_empty | Enum.A;
9363 // and tested using property access
9366 // or the & operator
9367 assert(flags_A & Enum.A);
9369 assert(Enum.A & flags_A);
9372 /// A default constructed BitFlags has no value set
9373 @safe @nogc pure nothrow unittest
9383 immutable BitFlags!Enum flags_empty;
9384 assert(!(flags_empty & (Enum.A | Enum.B | Enum.C)));
9385 assert(!(flags_empty & Enum.A) && !(flags_empty & Enum.B) && !(flags_empty & Enum.C));
9388 // BitFlags can be variadically initialized
9389 @safe @nogc pure nothrow unittest
9391 import std.traits : EnumMembers;
9400 // Values can also be set using property access
9401 BitFlags!Enum flags;
9403 assert(flags & Enum.A);
9405 assert(!(flags & Enum.A));
9407 // BitFlags can be variadically initialized
9408 immutable BitFlags!Enum flags_AB = BitFlags!Enum(Enum.A, Enum.B);
9409 assert(flags_AB.A && flags_AB.B && !flags_AB.C);
9411 // You can use the EnumMembers template to set all flags
9412 immutable BitFlags!Enum flags_all = EnumMembers!Enum;
9413 assert(flags_all.A && flags_all.B && flags_all.C);
9416 /// Binary operations: subtracting and intersecting flags
9417 @safe @nogc pure nothrow unittest
9425 immutable BitFlags!Enum flags_AB = BitFlags!Enum(Enum.A, Enum.B);
9426 immutable BitFlags!Enum flags_BC = BitFlags!Enum(Enum.B, Enum.C);
9428 // Use the ~ operator for subtracting flags
9429 immutable BitFlags!Enum flags_B = flags_AB & ~BitFlags!Enum(Enum.A);
9430 assert(!flags_B.A && flags_B.B && !flags_B.C);
9432 // use & between BitFlags for intersection
9433 assert(flags_B == (flags_BC & flags_AB));
9436 /// All the binary operators work in their assignment version
9437 @safe @nogc pure nothrow unittest
9445 BitFlags!Enum flags_empty, temp, flags_AB;
9446 flags_AB = Enum.A | Enum.B;
9449 assert(temp == (flags_empty | flags_AB));
9453 assert(temp == (flags_empty | Enum.B));
9457 assert(temp == (flags_empty & flags_AB));
9461 assert(temp == (flags_empty & Enum.A));
9464 /// Conversion to bool and int
9465 @safe @nogc pure nothrow unittest
9473 BitFlags!Enum flags;
9475 // BitFlags with no value set evaluate to false
9478 // BitFlags with at least one value set evaluate to true
9482 // This can be useful to check intersection between BitFlags
9483 BitFlags!Enum flags_AB = Enum.A | Enum.B;
9484 assert(flags & flags_AB);
9485 assert(flags & Enum.A);
9487 // You can of course get you raw value out of flags
9488 auto value = cast(int) flags;
9489 assert(value == Enum.A);
9492 /// You need to specify the `unsafe` parameter for enums with custom values
9493 @safe @nogc pure nothrow unittest
9502 static assert(!__traits(compiles, { BitFlags!UnsafeEnum flags; }));
9503 BitFlags!(UnsafeEnum, Yes.unsafe) flags;
9505 // property access tests for exact match of unsafe enums
9507 assert(!flags.BC); // only B
9509 assert(flags.BC); // both B and C
9511 assert(!flags.BC); // only C
9513 // property access sets all bits of unsafe enum group
9516 assert(!flags.A && flags.B && flags.C);
9519 assert(flags.A && !flags.B && !flags.C);
9522 // Negation of BitFlags should work with any base type.
9523 // Double-negation of BitFlags should work.
9524 @safe @nogc pure nothrow unittest
9526 static foreach (alias Base; AliasSeq!(
9544 auto flags = BitFlags!Enum(Enum.A);
9546 assert(flags == ~~flags);
9550 private enum false_(T) = false;
9554 Replaces all occurrences of `From` into `To`, in one or more types `T`. For
9555 example, `ReplaceType!(int, uint, Tuple!(int, float)[string])` yields
9556 `Tuple!(uint, float)[string]`. The types in which replacement is performed
9557 may be arbitrarily complex, including qualifiers, built-in type constructors
9558 (pointers, arrays, associative arrays, functions, and delegates), and template
9559 instantiations; replacement proceeds transitively through the type definition.
9560 However, member types in `struct`s or `class`es are not replaced because there
9561 are no ways to express the types resulting after replacement.
9563 This is an advanced type manipulation necessary e.g. for replacing the
9564 placeholder type `This` in $(REF Algebraic, std,variant).
9566 Returns: `ReplaceType` aliases itself to the type(s) that result after
9569 alias ReplaceType(From, To, T...) = ReplaceTypeUnless!(false_, From, To, T);
9575 is(ReplaceType!(int, string, int[]) == string[]) &&
9576 is(ReplaceType!(int, string, int[int]) == string[string]) &&
9577 is(ReplaceType!(int, string, const(int)[]) == const(string)[]) &&
9578 is(ReplaceType!(int, string, Tuple!(int[], float))
9579 == Tuple!(string[], float))
9584 Like $(LREF ReplaceType), but does not perform replacement in types for which
9585 `pred` evaluates to `true`.
9587 template ReplaceTypeUnless(alias pred, From, To, T...)
9591 static if (T.length == 1)
9593 static if (pred!(T[0]))
9594 alias ReplaceTypeUnless = T[0];
9595 else static if (is(T[0] == From))
9596 alias ReplaceTypeUnless = To;
9597 else static if (is(T[0] == const(U), U))
9598 alias ReplaceTypeUnless = const(ReplaceTypeUnless!(pred, From, To, U));
9599 else static if (is(T[0] == immutable(U), U))
9600 alias ReplaceTypeUnless = immutable(ReplaceTypeUnless!(pred, From, To, U));
9601 else static if (is(T[0] == shared(U), U))
9602 alias ReplaceTypeUnless = shared(ReplaceTypeUnless!(pred, From, To, U));
9603 else static if (is(T[0] == U*, U))
9605 static if (is(U == function))
9606 alias ReplaceTypeUnless = replaceTypeInFunctionTypeUnless!(pred, From, To, T[0]);
9608 alias ReplaceTypeUnless = ReplaceTypeUnless!(pred, From, To, U)*;
9610 else static if (is(T[0] == delegate))
9612 alias ReplaceTypeUnless = replaceTypeInFunctionTypeUnless!(pred, From, To, T[0]);
9614 else static if (is(T[0] == function))
9616 static assert(0, "Function types not supported," ~
9617 " use a function pointer type instead of " ~ T[0].stringof);
9619 else static if (is(T[0] == U!V, alias U, V...))
9621 template replaceTemplateArgs(T...)
9623 static if (is(typeof(T[0]))) { // template argument is value or symbol
9624 static if (__traits(compiles, { alias _ = T[0]; }))
9626 alias replaceTemplateArgs = T[0];
9629 enum replaceTemplateArgs = T[0];
9631 alias replaceTemplateArgs = ReplaceTypeUnless!(pred, From, To, T[0]);
9633 alias ReplaceTypeUnless = U!(staticMap!(replaceTemplateArgs, V));
9635 else static if (is(T[0] == struct))
9636 // don't match with alias this struct below
9637 // https://issues.dlang.org/show_bug.cgi?id=15168
9638 alias ReplaceTypeUnless = T[0];
9639 else static if (is(T[0] == U[], U))
9640 alias ReplaceTypeUnless = ReplaceTypeUnless!(pred, From, To, U)[];
9641 else static if (is(T[0] == U[n], U, size_t n))
9642 alias ReplaceTypeUnless = ReplaceTypeUnless!(pred, From, To, U)[n];
9643 else static if (is(T[0] == U[V], U, V))
9644 alias ReplaceTypeUnless =
9645 ReplaceTypeUnless!(pred, From, To, U)[ReplaceTypeUnless!(pred, From, To, V)];
9647 alias ReplaceTypeUnless = T[0];
9649 else static if (T.length > 1)
9651 alias ReplaceTypeUnless = AliasSeq!(ReplaceTypeUnless!(pred, From, To, T[0]),
9652 ReplaceTypeUnless!(pred, From, To, T[1 .. $]));
9656 alias ReplaceTypeUnless = AliasSeq!();
9663 import std.traits : isArray;
9666 is(ReplaceTypeUnless!(isArray, int, string, int*) == string*) &&
9667 is(ReplaceTypeUnless!(isArray, int, string, int[]) == int[]) &&
9668 is(ReplaceTypeUnless!(isArray, int, string, Tuple!(int, int[]))
9669 == Tuple!(string, int[]))
9673 private template replaceTypeInFunctionTypeUnless(alias pred, From, To, fun)
9675 alias RX = ReplaceTypeUnless!(pred, From, To, ReturnType!fun);
9676 alias PX = AliasSeq!(ReplaceTypeUnless!(pred, From, To, Parameters!fun));
9677 // Wrapping with AliasSeq is neccesary because ReplaceType doesn't return
9678 // tuple if Parameters!fun.length == 1
9682 enum linkage = functionLinkage!fun;
9683 alias attributes = functionAttributes!fun;
9684 enum variadicStyle = variadicFunctionStyle!fun;
9685 alias storageClasses = ParameterStorageClassTuple!fun;
9689 result ~= "extern(" ~ linkage ~ ") ";
9690 static if (attributes & FunctionAttribute.ref_)
9696 static if (is(fun == delegate))
9697 result ~= " delegate";
9699 result ~= " function";
9702 static foreach (i; 0 .. PX.length)
9706 if (storageClasses[i] & ParameterStorageClass.scope_)
9708 if (storageClasses[i] & ParameterStorageClass.in_)
9710 if (storageClasses[i] & ParameterStorageClass.out_)
9712 if (storageClasses[i] & ParameterStorageClass.ref_)
9714 if (storageClasses[i] & ParameterStorageClass.lazy_)
9716 if (storageClasses[i] & ParameterStorageClass.return_)
9717 result ~= "return ";
9719 result ~= "PX[" ~ i.stringof ~ "]";
9721 static if (variadicStyle == Variadic.typesafe)
9723 else static if (variadicStyle != Variadic.no)
9727 static if (attributes & FunctionAttribute.pure_)
9729 static if (attributes & FunctionAttribute.nothrow_)
9730 result ~= " nothrow";
9731 static if (attributes & FunctionAttribute.property)
9732 result ~= " @property";
9733 static if (attributes & FunctionAttribute.trusted)
9734 result ~= " @trusted";
9735 static if (attributes & FunctionAttribute.safe)
9737 static if (attributes & FunctionAttribute.nogc)
9739 static if (attributes & FunctionAttribute.system)
9740 result ~= " @system";
9741 static if (attributes & FunctionAttribute.const_)
9743 static if (attributes & FunctionAttribute.immutable_)
9744 result ~= " immutable";
9745 static if (attributes & FunctionAttribute.inout_)
9747 static if (attributes & FunctionAttribute.shared_)
9748 result ~= " shared";
9749 static if (attributes & FunctionAttribute.return_)
9750 result ~= " return";
9751 static if (attributes & FunctionAttribute.live)
9757 mixin("alias replaceTypeInFunctionTypeUnless = " ~ gen() ~ ";");
9762 template Test(Ts...)
9764 static if (Ts.length)
9766 //pragma(msg, "Testing: ReplaceType!("~Ts[0].stringof~", "
9767 // ~Ts[1].stringof~", "~Ts[2].stringof~")");
9768 static assert(is(ReplaceType!(Ts[0], Ts[1], Ts[2]) == Ts[3]),
9769 "ReplaceType!("~Ts[0].stringof~", "~Ts[1].stringof~", "
9770 ~Ts[2].stringof~") == "
9771 ~ReplaceType!(Ts[0], Ts[1], Ts[2]).stringof);
9772 alias Test = Test!(Ts[4 .. $]);
9774 else alias Test = void;
9777 //import core.stdc.stdio;
9778 alias RefFun1 = ref int function(float, long);
9779 alias RefFun2 = ref float function(float, long);
9780 extern(C) int printf(const char*, ...) nothrow @nogc @system;
9781 extern(C) float floatPrintf(const char*, ...) nothrow @nogc @system;
9785 struct S1 { void foo() { x = 1; } }
9786 struct S2 { void bar() { x = 2; } }
9789 int, float, typeof(&func), float delegate(float),
9790 int, float, typeof(&printf), typeof(&floatPrintf),
9791 int, float, int function(out long, ...),
9792 float function(out long, ...),
9793 int, float, int function(ref float, long),
9794 float function(ref float, long),
9795 int, float, int function(ref int, long),
9796 float function(ref float, long),
9797 int, float, int function(out int, long),
9798 float function(out float, long),
9799 int, float, int function(lazy int, long),
9800 float function(lazy float, long),
9801 int, float, int function(out long, ref const int),
9802 float function(out long, ref const float),
9803 int, float, int function(in long, ref const int),
9804 float function(in long, ref const float),
9805 int, float, int function(long, in int),
9806 float function(long, in float),
9808 int, float, int, float,
9809 int, float, const int, const float,
9810 int, float, immutable int, immutable float,
9811 int, float, shared int, shared float,
9812 int, float, int*, float*,
9813 int, float, const(int)*, const(float)*,
9814 int, float, const(int*), const(float*),
9815 const(int)*, float, const(int*), const(float),
9816 int*, float, const(int)*, const(int)*,
9817 int, float, int[], float[],
9818 int, float, int[42], float[42],
9819 int, float, const(int)[42], const(float)[42],
9820 int, float, const(int[42]), const(float[42]),
9821 int, float, int[int], float[float],
9822 int, float, int[double], float[double],
9823 int, float, double[int], double[float],
9824 int, float, int function(float, long), float function(float, long),
9825 int, float, int function(float), float function(float),
9826 int, float, int function(float, int), float function(float, float),
9827 int, float, int delegate(float, long), float delegate(float, long),
9828 int, float, int delegate(float), float delegate(float),
9829 int, float, int delegate(float, int), float delegate(float, float),
9830 int, float, Unique!int, Unique!float,
9831 int, float, Tuple!(float, int), Tuple!(float, float),
9832 int, float, RefFun1, RefFun2,
9834 S1[1][][S1]* function(),
9835 S2[1][][S2]* function(),
9837 int[3] function( int[] arr, int[2] ...) pure @trusted,
9838 string[3] function(string[] arr, string[2] ...) pure @trusted,
9841 // https://issues.dlang.org/show_bug.cgi?id=15168
9842 static struct T1 { string s; alias s this; }
9843 static struct T2 { char[10] s; alias s this; }
9844 static struct T3 { string[string] s; alias s this; }
9845 alias Pass2 = Test!(
9846 ubyte, ubyte, T1, T1,
9847 ubyte, ubyte, T2, T2,
9848 ubyte, ubyte, T3, T3,
9852 // https://issues.dlang.org/show_bug.cgi?id=17116
9855 alias ConstDg = void delegate(float) const;
9856 alias B = void delegate(int) const;
9857 alias A = ReplaceType!(float, int, ConstDg);
9858 static assert(is(B == A));
9861 // https://issues.dlang.org/show_bug.cgi?id=19696
9864 static struct T(U) {}
9865 static struct S { T!int t; alias t this; }
9866 static assert(is(ReplaceType!(float, float, S) == S));
9869 // https://issues.dlang.org/show_bug.cgi?id=19697
9874 static assert(is(ReplaceType!(float, float, C)));
9877 // https://issues.dlang.org/show_bug.cgi?id=16132
9882 static assert(is(ReplaceType!(int, string, C) == C));
9885 // https://issues.dlang.org/show_bug.cgi?id=22325
9888 static struct Foo(alias f) {}
9889 static void bar() {}
9890 alias _ = ReplaceType!(int, int, Foo!bar);
9894 Ternary type with three truth values:
9897 $(LI `Ternary.yes` for `true`)
9898 $(LI `Ternary.no` for `false`)
9899 $(LI `Ternary.unknown` as an unknown state)
9902 Also known as trinary, trivalent, or trilean.
9905 $(HTTP en.wikipedia.org/wiki/Three-valued_logic,
9906 Three Valued Logic on Wikipedia)
9910 @safe @nogc nothrow pure:
9912 private ubyte value = 6;
9913 private static Ternary make(ubyte b)
9921 The possible states of the `Ternary`
9927 enum unknown = make(6);
9930 Construct and assign from a `bool`, receiving `no` for `false` and `yes`
9933 this(bool b) { value = b << 1; }
9936 void opAssign(bool b) { value = b << 1; }
9939 Construct a ternary value from another ternary value
9941 this(const Ternary b) { value = b.value; }
9944 $(TABLE Truth table for logical operations,
9945 $(TR $(TH `a`) $(TH `b`) $(TH `$(TILDE)a`) $(TH `a | b`) $(TH `a & b`) $(TH `a ^ b`))
9946 $(TR $(TD `no`) $(TD `no`) $(TD `yes`) $(TD `no`) $(TD `no`) $(TD `no`))
9947 $(TR $(TD `no`) $(TD `yes`) $(TD) $(TD `yes`) $(TD `no`) $(TD `yes`))
9948 $(TR $(TD `no`) $(TD `unknown`) $(TD) $(TD `unknown`) $(TD `no`) $(TD `unknown`))
9949 $(TR $(TD `yes`) $(TD `no`) $(TD `no`) $(TD `yes`) $(TD `no`) $(TD `yes`))
9950 $(TR $(TD `yes`) $(TD `yes`) $(TD) $(TD `yes`) $(TD `yes`) $(TD `no`))
9951 $(TR $(TD `yes`) $(TD `unknown`) $(TD) $(TD `yes`) $(TD `unknown`) $(TD `unknown`))
9952 $(TR $(TD `unknown`) $(TD `no`) $(TD `unknown`) $(TD `unknown`) $(TD `no`) $(TD `unknown`))
9953 $(TR $(TD `unknown`) $(TD `yes`) $(TD) $(TD `yes`) $(TD `unknown`) $(TD `unknown`))
9954 $(TR $(TD `unknown`) $(TD `unknown`) $(TD) $(TD `unknown`) $(TD `unknown`) $(TD `unknown`))
9957 Ternary opUnary(string s)() if (s == "~")
9959 return make((386 >> value) & 6);
9963 Ternary opBinary(string s)(Ternary rhs) if (s == "|")
9965 return make((25_512 >> (value + rhs.value)) & 6);
9969 Ternary opBinary(string s)(Ternary rhs) if (s == "&")
9971 return make((26_144 >> (value + rhs.value)) & 6);
9975 Ternary opBinary(string s)(Ternary rhs) if (s == "^")
9977 return make((26_504 >> (value + rhs.value)) & 6);
9981 Ternary opBinary(string s)(bool rhs)
9982 if (s == "|" || s == "&" || s == "^")
9984 return this.opBinary!s(Ternary(rhs));
9989 @safe @nogc nothrow pure
9993 assert(a == Ternary.unknown);
9995 assert(~Ternary.yes == Ternary.no);
9996 assert(~Ternary.no == Ternary.yes);
9997 assert(~Ternary.unknown == Ternary.unknown);
10000 @safe @nogc nothrow pure
10003 alias f = Ternary.no, t = Ternary.yes, u = Ternary.unknown;
10004 Ternary[27] truthTableAnd =
10017 Ternary[27] truthTableOr =
10030 Ternary[27] truthTableXor =
10043 for (auto i = 0; i != truthTableAnd.length; i += 3)
10045 assert((truthTableAnd[i] & truthTableAnd[i + 1])
10046 == truthTableAnd[i + 2]);
10047 assert((truthTableOr[i] | truthTableOr[i + 1])
10048 == truthTableOr[i + 2]);
10049 assert((truthTableXor[i] ^ truthTableXor[i + 1])
10050 == truthTableXor[i + 2]);
10054 assert(a == Ternary.unknown);
10055 static assert(!is(typeof({ if (a) {} })));
10056 assert(!is(typeof({ auto b = Ternary(3); })));
10058 assert(a == Ternary.yes);
10060 assert(a == Ternary.no);
10061 a = Ternary.unknown;
10062 assert(a == Ternary.unknown);
10066 assert(~Ternary.yes == Ternary.no);
10067 assert(~Ternary.no == Ternary.yes);
10068 assert(~Ternary.unknown == Ternary.unknown);
10071 @safe @nogc nothrow pure
10074 Ternary a = Ternary(true);
10075 assert(a == Ternary.yes);
10076 assert((a & false) == Ternary.no);
10077 assert((a | false) == Ternary.yes);
10078 assert((a ^ true) == Ternary.no);
10079 assert((a ^ false) == Ternary.yes);
10082 // https://issues.dlang.org/show_bug.cgi?id=22511
10088 @disable this(this);
10089 this(ref return scope inout S rhs) inout
10091 this.b = rhs.b + 1;
10095 Nullable!S s1 = S(1);
10096 assert(s1.get().b == 2);
10097 Nullable!S s2 = s1;
10098 assert(s2.get().b == 3);
10106 this(this) { ++b; }
10109 Nullable!S s1 = S(1);
10110 assert(s1.get().b == 2);
10111 Nullable!S s2 = s1;
10112 assert(s2.get().b == 3);
10115 /// The old version of $(LREF SafeRefCounted), before $(LREF borrow) existed.
10116 /// Old code may be relying on `@safe`ty of some of the member functions which
10117 /// cannot be safe in the new scheme, and
10118 /// can avoid breakage by continuing to use this. `SafeRefCounted` should be
10119 /// preferred, as this type is outdated and unrecommended for new code.
10120 struct RefCounted(T, RefCountedAutoInitialize autoInit =
10121 RefCountedAutoInitialize.yes)
10123 version (D_BetterC)
10125 private enum enableGCScan = false;
10129 private enum enableGCScan = hasIndirections!T;
10132 extern(C) private pure nothrow @nogc static
10134 pragma(mangle, "free") void pureFree( void *ptr );
10135 static if (enableGCScan)
10136 import core.memory : GC;
10139 struct RefCountedStore
10141 private struct Impl
10147 private Impl* _store;
10149 private void initialize(A...)(auto ref A args)
10151 import core.lifetime : emplace, forward;
10154 version (D_Exceptions) scope(failure) deallocateStore();
10155 emplace(&_store._payload, forward!args);
10159 private void move(ref T source) nothrow pure
10161 import std.algorithm.mutation : moveEmplace;
10164 moveEmplace(source, _store._payload);
10168 // 'nothrow': can only generate an Error
10169 private void allocateStore() nothrow pure
10171 static if (enableGCScan)
10173 import std.internal.memory : enforceCalloc;
10174 _store = cast(Impl*) enforceCalloc(1, Impl.sizeof);
10175 GC.addRange(&_store._payload, T.sizeof);
10179 import std.internal.memory : enforceMalloc;
10180 _store = cast(Impl*) enforceMalloc(Impl.sizeof);
10184 private void deallocateStore() nothrow pure
10186 static if (enableGCScan)
10188 GC.removeRange(&this._store._payload);
10194 @property nothrow @safe pure @nogc
10195 bool isInitialized() const
10197 return _store !is null;
10200 @property nothrow @safe pure @nogc
10201 size_t refCount() const
10203 return isInitialized ? _store._count : 0;
10206 void ensureInitialized()()
10208 // By checking for `@disable this()` and failing early we can
10209 // produce a clearer error message.
10210 static assert(__traits(compiles, { static T t; }),
10211 "Cannot automatically initialize `" ~ fullyQualifiedName!T ~
10212 "` because `" ~ fullyQualifiedName!T ~
10213 ".this()` is annotated with `@disable`.");
10214 if (!isInitialized) initialize();
10218 RefCountedStore _refCounted;
10220 @property nothrow @safe
10221 ref inout(RefCountedStore) refCountedStore() inout
10223 return _refCounted;
10226 this(A...)(auto ref A args) if (A.length > 0)
10229 assert(refCountedStore.isInitialized);
10233 import core.lifetime : forward;
10234 _refCounted.initialize(forward!args);
10239 _refCounted.move(val);
10242 this(this) @safe pure nothrow @nogc
10244 if (!_refCounted.isInitialized) return;
10245 ++_refCounted._store._count;
10250 if (!_refCounted.isInitialized) return;
10251 assert(_refCounted._store._count > 0);
10252 if (--_refCounted._store._count)
10254 // Done, destroy and deallocate
10255 .destroy(_refCounted._store._payload);
10256 _refCounted.deallocateStore();
10259 void opAssign(typeof(this) rhs)
10261 import std.algorithm.mutation : swap;
10263 swap(_refCounted._store, rhs._refCounted._store);
10266 void opAssign(T rhs)
10268 import std.algorithm.mutation : move;
10270 static if (autoInit == RefCountedAutoInitialize.yes)
10272 _refCounted.ensureInitialized();
10276 assert(_refCounted.isInitialized);
10278 move(rhs, _refCounted._store._payload);
10281 static if (autoInit == RefCountedAutoInitialize.yes)
10283 //Can't use inout here because of potential mutation
10285 ref T refCountedPayload() return
10287 _refCounted.ensureInitialized();
10288 return _refCounted._store._payload;
10292 @property nothrow @safe pure @nogc
10293 ref inout(T) refCountedPayload() inout return
10295 assert(_refCounted.isInitialized, "Attempted to access an uninitialized payload.");
10296 return _refCounted._store._payload;
10299 alias refCountedPayload this;
10301 static if (is(T == struct) && !is(typeof((ref T t) => t.toString())))
10303 string toString(this This)()
10305 import std.conv : to;
10307 static if (autoInit)
10308 return to!string(refCountedPayload);
10311 if (!_refCounted.isInitialized)
10312 return This.stringof ~ "(RefCountedStore(null))";
10314 return to!string(_refCounted._store._payload);
10321 @betterC pure @system nothrow @nogc unittest
10323 auto rc1 = RefCounted!int(5);
10330 // More unit tests below SafeRefCounted
10333 * Like $(LREF safeRefCounted) but used to initialize $(LREF RefCounted)
10334 * instead. Intended for backwards compatibility, otherwise it is preferable
10335 * to use `safeRefCounted`.
10337 RefCounted!(T, RefCountedAutoInitialize.no) refCounted(T)(T val)
10339 typeof(return) res;
10340 res._refCounted.move(val);
10349 static size_t nDestroyed;
10351 @disable this(this); // not copyable
10352 ~this() { name = null; ++nDestroyed; }
10355 auto file = File("name");
10356 assert(file.name == "name");
10357 static assert(!__traits(compiles, {auto file2 = file;}));
10358 assert(File.nDestroyed == 0);
10361 import std.algorithm.mutation : move;
10362 auto rcFile = refCounted(move(file));
10363 assert(rcFile.name == "name");
10364 assert(File.nDestroyed == 1);
10365 assert(file.name == null);
10367 auto rcFile2 = rcFile;
10368 assert(rcFile.refCountedStore.refCount == 2);
10369 assert(File.nDestroyed == 1);
10372 assert(File.nDestroyed == 2);
10375 // More unit tests below safeRefCounted