d: Merge upstream dmd, druntime b65767825f, phobos 92dc5a4e9.
[official-gcc.git] / libphobos / src / std / typecons.d
blob460cd427ed0a3f7f5d7487180c131297aaeab925
1 // Written in the D programming language.
3 /**
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;)
8 $(DIVC quickindex,
9 $(BOOKTABLE,
10 $(TR $(TH Category) $(TH Symbols))
11 $(TR $(TD Tuple) $(TD
12 $(LREF isTuple)
13 $(LREF Tuple)
14 $(LREF tuple)
15 $(LREF reverse)
17 $(TR $(TD Flags) $(TD
18 $(LREF BitFlags)
19 $(LREF isBitFlagEnum)
20 $(LREF Flag)
21 $(LREF No)
22 $(LREF Yes)
24 $(TR $(TD Memory allocation) $(TD
25 $(LREF SafeRefCounted)
26 $(LREF safeRefCounted)
27 $(LREF RefCountedAutoInitialize)
28 $(LREF scoped)
29 $(LREF Unique)
31 $(TR $(TD Code generation) $(TD
32 $(LREF AutoImplement)
33 $(LREF BlackHole)
34 $(LREF generateAssertTrap)
35 $(LREF generateEmptyFunction)
36 $(LREF WhiteHole)
38 $(TR $(TD Nullable) $(TD
39 $(LREF Nullable)
40 $(LREF nullable)
41 $(LREF NullableRef)
42 $(LREF nullableRef)
44 $(TR $(TD Proxies) $(TD
45 $(LREF Proxy)
46 $(LREF rebindable)
47 $(LREF Rebindable)
48 $(LREF ReplaceType)
49 $(LREF unwrap)
50 $(LREF wrap)
52 $(TR $(TD Types) $(TD
53 $(LREF alignForSize)
54 $(LREF Ternary)
55 $(LREF Typedef)
56 $(LREF TypedefType)
57 $(LREF UnqualRef)
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),
66 Don Clugston,
67 Shin Fujishiro,
68 Kenji Hara
70 module std.typecons;
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;
76 import std.traits;
77 import std.internal.attributes : betterC;
79 /// Value tuples
80 @safe unittest
82 alias Coord = Tuple!(int, "x", int, "y", int, "z");
83 Coord c;
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);
96 assert(tup.y == 3);
99 /// Rebindable references to const and immutable objects
100 @safe unittest
102 class Widget
104 void foo() const @safe {}
106 const w1 = new Widget, w2 = new Widget;
107 w1.foo();
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
112 r.foo();
113 // rebind r to refer to another object
114 r = w2;
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
134 too.
136 If `T` is a value type, then `Unique!T` will be implemented
137 as a reference to a `T`.
139 struct Unique(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))
143 alias RefT = T;
144 else
145 alias RefT = T*;
147 public:
148 // Deferred in case we get some language support for checking uniqueness.
149 version (None)
151 Allows safe construction of `Unique`. It creates the resource and
152 guarantees unique ownership of it (unless `T` publishes aliases of
153 `this`).
154 Note: Nested structs/classes cannot be created.
155 Params:
156 args = Arguments to pass to `T`'s constructor.
158 static class C {}
159 auto u = Unique!(C).create();
162 static Unique!T create(A...)(auto ref A args)
163 if (__traits(compiles, new T(args)))
165 Unique!T u;
166 u._p = new T(args);
167 return u;
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).
174 Typical usage:
175 ----
176 Unique!Foo f = new Foo;
177 ----
179 this(RefT p)
181 _p = p;
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.
188 this(ref RefT p)
190 _p = p;
191 p = null;
192 assert(p is null);
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.
199 Example:
201 class C : Object {}
203 Unique!C uc = new C;
204 Unique!Object uo = uc.release;
207 this(U)(Unique!U u)
208 if (is(u.RefT:RefT))
210 _p = u._p;
211 u._p = null;
214 /// Transfer ownership from a `Unique` of a type that is convertible to our type.
215 void opAssign(U)(Unique!U u)
216 if (is(u.RefT:RefT))
218 // first delete any resource we own
219 destroy(this);
220 _p = u._p;
221 u._p = null;
224 ~this()
226 if (_p !is null)
228 static if (is(T == class) || is(T == interface))
229 destroy(_p);
230 else
231 destroy(*_p);
232 _p = null;
236 /** Returns whether the resource exists. */
237 @property bool isEmpty() const
239 return _p is null;
241 /** Transfer ownership to a `Unique` rvalue. Nullifies the current contents.
242 Same as calling std.algorithm.move on it.
244 Unique release()
246 import std.algorithm.mutation : move;
247 return this.move;
250 /** Forwards member access to contents. */
251 mixin Proxy!_p;
254 Postblit operator is undefined to prevent the cloning of `Unique` objects.
256 @disable this(this);
258 private:
259 RefT _p;
263 @safe unittest
265 struct S
267 int i;
268 this(int i){this.i = i;}
270 Unique!S produce()
272 // Construct a unique instance of S on the heap
273 Unique!S ut = new S(5);
274 // Implicit transfer of ownership
275 return ut;
277 // Borrow a unique resource by ref
278 void increment(ref Unique!S ur)
280 ur.i++;
282 void consume(Unique!S u2)
284 assert(u2.i == 6);
285 // Resource automatically deleted here
287 Unique!S u1;
288 assert(u1.isEmpty);
289 u1 = produce();
290 assert(u1.i == 5);
291 increment(u1);
292 assert(u1.i == 6);
293 //consume(u1); // Error: u1 is not copyable
294 // Transfer ownership of the resource
295 consume(u1.release);
296 assert(u1.isEmpty);
299 @safe unittest
301 int i;
302 struct S
304 ~this()
306 // check context pointer still exists - dtor also called before GC frees struct
307 if (this.tupleof[0])
308 i++;
312 Unique!S u = new S;
314 assert(i == 1);
317 @system unittest
319 // test conversion to base ref
320 int deleted = 0;
321 class C
323 ~this(){deleted++;}
325 // constructor conversion
326 Unique!Object u = Unique!C(new C);
327 static assert(!__traits(compiles, {u = new C;}));
328 assert(!u.isEmpty);
329 destroy(u);
330 assert(deleted == 1);
332 Unique!C uc = new C;
333 static assert(!__traits(compiles, {Unique!Object uo = uc;}));
334 Unique!Object uo = new C;
335 // opAssign conversion, deleting uo resource first
336 uo = uc.release;
337 assert(uc.isEmpty);
338 assert(!uo.isEmpty);
339 assert(deleted == 2);
342 @system unittest
344 class Bar
346 ~this() { debug(Unique) writeln(" Bar destructor"); }
347 int val() const { return 4; }
349 alias UBar = Unique!(Bar);
350 UBar g(UBar u)
352 debug(Unique) writeln("inside g");
353 return u.release;
355 auto ub = UBar(new Bar);
356 assert(!ub.isEmpty);
357 assert(ub.val == 4);
358 static assert(!__traits(compiles, {auto ub3 = g(ub);}));
359 auto ub2 = g(ub.release);
360 assert(ub.isEmpty);
361 assert(!ub2.isEmpty);
364 @system unittest
366 interface Bar
368 int val() const;
370 class BarImpl : Bar
372 static int count;
373 this()
375 count++;
377 ~this()
379 count--;
381 int val() const { return 4; }
383 alias UBar = Unique!Bar;
384 UBar g(UBar u)
386 debug(Unique) writeln("inside g");
387 return u.release;
389 void consume(UBar u)
391 assert(u.val() == 4);
392 // Resource automatically deleted here
394 auto ub = UBar(new BarImpl);
395 assert(BarImpl.count == 1);
396 assert(!ub.isEmpty);
397 assert(ub.val == 4);
398 static assert(!__traits(compiles, {auto ub3 = g(ub);}));
399 auto ub2 = g(ub.release);
400 assert(ub.isEmpty);
401 assert(!ub2.isEmpty);
402 consume(ub2.release);
403 assert(BarImpl.count == 0);
406 @safe unittest
408 struct Foo
410 ~this() { }
411 int val() const { return 3; }
412 @disable this(this);
414 alias UFoo = Unique!(Foo);
416 UFoo f(UFoo u)
418 return u.release;
421 auto uf = UFoo(new Foo);
422 assert(!uf.isEmpty);
423 assert(uf.val == 3);
424 static assert(!__traits(compiles, {auto uf3 = f(uf);}));
425 auto uf2 = f(uf.release);
426 assert(uf.isEmpty);
427 assert(!uf2.isEmpty);
430 // ensure Unique behaves correctly through const access paths
431 @system unittest
433 struct Bar {int val;}
434 struct Foo
436 Unique!Bar bar = new Bar;
439 Foo foo;
440 foo.bar.val = 6;
441 const Foo* ptr = &foo;
442 static assert(is(typeof(ptr) == const(Foo*)));
443 static assert(is(typeof(ptr.bar) == const(Unique!Bar)));
444 static assert(is(typeof(ptr.bar.val) == const(int)));
445 assert(ptr.bar.val == 6);
446 foo.bar.val = 7;
447 assert(ptr.bar.val == 7);
450 // Used in Tuple.toString
451 private template sharedToString(alias field)
452 if (is(typeof(field) == shared))
454 static immutable sharedToString = typeof(field).stringof;
457 private template sharedToString(alias field)
458 if (!is(typeof(field) == shared))
460 alias sharedToString = field;
463 private enum bool distinctFieldNames(names...) = __traits(compiles,
465 static foreach (__name; names)
466 static if (is(typeof(__name) : string))
467 mixin("enum int " ~ __name ~ " = 0;");
470 @safe unittest
472 static assert(!distinctFieldNames!(string, "abc", string, "abc"));
473 static assert(distinctFieldNames!(string, "abc", int, "abd"));
474 static assert(!distinctFieldNames!(int, "abc", string, "abd", int, "abc"));
475 // https://issues.dlang.org/show_bug.cgi?id=19240
476 static assert(!distinctFieldNames!(int, "int"));
480 // Parse (type,name) pairs (FieldSpecs) out of the specified
481 // arguments. Some fields would have name, others not.
482 private template parseSpecs(Specs...)
484 static if (Specs.length == 0)
486 alias parseSpecs = AliasSeq!();
488 else static if (is(Specs[0]))
490 static if (is(typeof(Specs[1]) : string))
492 alias parseSpecs =
493 AliasSeq!(FieldSpec!(Specs[0 .. 2]),
494 parseSpecs!(Specs[2 .. $]));
496 else
498 alias parseSpecs =
499 AliasSeq!(FieldSpec!(Specs[0]),
500 parseSpecs!(Specs[1 .. $]));
503 else
505 static assert(0, "Attempted to instantiate Tuple with an "
506 ~"invalid argument: "~ Specs[0].stringof);
510 private template FieldSpec(T, string s = "")
512 alias Type = T;
513 alias name = s;
516 // Used with staticMap.
517 private alias extractType(alias spec) = spec.Type;
518 private alias extractName(alias spec) = spec.name;
519 private template expandSpec(alias spec)
521 static if (spec.name.length == 0)
522 alias expandSpec = AliasSeq!(spec.Type);
523 else
524 alias expandSpec = AliasSeq!(spec.Type, spec.name);
528 private enum areCompatibleTuples(Tup1, Tup2, string op) =
529 isTuple!(OriginalType!Tup2) && Tup1.Types.length == Tup2.Types.length && is(typeof(
530 (ref Tup1 tup1, ref Tup2 tup2)
532 static foreach (i; 0 .. Tup1.Types.length)
534 auto lhs = typeof(tup1.field[i]).init;
535 auto rhs = typeof(tup2.field[i]).init;
536 static if (op == "=")
537 lhs = rhs;
538 else
539 auto result = mixin("lhs "~op~" rhs");
541 }));
543 private enum areBuildCompatibleTuples(Tup1, Tup2) =
544 isTuple!Tup2 && Tup1.Types.length == Tup2.Types.length && is(typeof(
546 static foreach (i; 0 .. Tup1.Types.length)
547 static assert(isBuildable!(Tup1.Types[i], Tup2.Types[i]));
548 }));
550 // Returns `true` iff a `T` can be initialized from a `U`.
551 private enum isBuildable(T, U) = is(typeof(
553 U u = U.init;
554 T t = u;
555 }));
556 // Helper for partial instantiation
557 private template isBuildableFrom(U)
559 enum isBuildableFrom(T) = isBuildable!(T, U);
562 private enum hasCopyCtor(T) = __traits(hasCopyConstructor, T);
564 // T is expected to be an instantiation of Tuple.
565 private template noMemberHasCopyCtor(T)
567 import std.meta : anySatisfy;
568 enum noMemberHasCopyCtor = !anySatisfy!(hasCopyCtor, T.Types);
572 _Tuple of values, for example $(D Tuple!(int, string)) is a record that
573 stores an `int` and a `string`. `Tuple` can be used to bundle
574 values together, notably when returning multiple values from a
575 function. If `obj` is a `Tuple`, the individual members are
576 accessible with the syntax `obj[0]` for the first field, `obj[1]`
577 for the second, and so on.
579 See_Also: $(LREF tuple).
581 Params:
582 Specs = A list of types (and optionally, member names) that the `Tuple` contains.
584 template Tuple(Specs...)
585 if (distinctFieldNames!(Specs))
587 import std.meta : staticMap;
589 alias fieldSpecs = parseSpecs!Specs;
591 // Generates named fields as follows:
592 // alias name_0 = Identity!(field[0]);
593 // alias name_1 = Identity!(field[1]);
594 // :
595 // NOTE: field[k] is an expression (which yields a symbol of a
596 // variable) and can't be aliased directly.
597 enum injectNamedFields = ()
599 string decl = "";
600 static foreach (i, val; fieldSpecs)
602 immutable si = i.stringof;
603 decl ~= "alias _" ~ si ~ " = Identity!(field[" ~ si ~ "]);";
604 if (val.name.length != 0)
606 decl ~= "alias " ~ val.name ~ " = _" ~ si ~ ";";
609 return decl;
612 // Returns Specs for a subtuple this[from .. to] preserving field
613 // names if any.
614 alias sliceSpecs(size_t from, size_t to) =
615 staticMap!(expandSpec, fieldSpecs[from .. to]);
617 struct Tuple
620 * The types of the `Tuple`'s components.
622 alias Types = staticMap!(extractType, fieldSpecs);
624 private alias _Fields = Specs;
627 static if (Specs.length == 0) @safe unittest
629 import std.meta : AliasSeq;
630 alias Fields = Tuple!(int, "id", string, float);
631 static assert(is(Fields.Types == AliasSeq!(int, string, float)));
635 * The names of the `Tuple`'s components. Unnamed fields have empty names.
637 alias fieldNames = staticMap!(extractName, fieldSpecs);
640 static if (Specs.length == 0) @safe unittest
642 import std.meta : AliasSeq;
643 alias Fields = Tuple!(int, "id", string, float);
644 static assert(Fields.fieldNames == AliasSeq!("id", "", ""));
648 * Use `t.expand` for a `Tuple` `t` to expand it into its
649 * components. The result of `expand` acts as if the `Tuple`'s components
650 * were listed as a list of values. (Ordinarily, a `Tuple` acts as a
651 * single value.)
653 Types expand;
654 mixin(injectNamedFields());
657 static if (Specs.length == 0) @safe unittest
659 auto t1 = tuple(1, " hello ", 'a');
660 assert(t1.toString() == `Tuple!(int, string, char)(1, " hello ", 'a')`);
662 void takeSeveralTypes(int n, string s, bool b)
664 assert(n == 4 && s == "test" && b == false);
667 auto t2 = tuple(4, "test", false);
668 //t.expand acting as a list of values
669 takeSeveralTypes(t2.expand);
672 static if (is(Specs))
674 // This is mostly to make t[n] work.
675 alias expand this;
677 else
679 @property
680 ref inout(Tuple!Types) _Tuple_super() inout @trusted
682 static foreach (i; 0 .. Types.length) // Rely on the field layout
684 static assert(typeof(return).init.tupleof[i].offsetof ==
685 expand[i].offsetof);
687 return *cast(typeof(return)*) &(field[0]);
689 // This is mostly to make t[n] work.
690 alias _Tuple_super this;
693 // backwards compatibility
694 alias field = expand;
697 * Constructor taking one value for each field.
699 * Params:
700 * values = A list of values that are either the same
701 * types as those given by the `Types` field
702 * of this `Tuple`, or can implicitly convert
703 * to those types. They must be in the same
704 * order as they appear in `Types`.
706 static if (Types.length > 0)
708 this(Types values)
710 field[] = values[];
715 static if (Specs.length == 0) @safe unittest
717 alias ISD = Tuple!(int, string, double);
718 auto tup = ISD(1, "test", 3.2);
719 assert(tup.toString() == `Tuple!(int, string, double)(1, "test", 3.2)`);
723 * Constructor taking a compatible array.
725 * Params:
726 * values = A compatible static array to build the `Tuple` from.
727 * Array slices are not supported.
729 this(U, size_t n)(U[n] values)
730 if (n == Types.length && allSatisfy!(isBuildableFrom!U, Types))
732 static foreach (i; 0 .. Types.length)
734 field[i] = values[i];
739 static if (Specs.length == 0) @safe unittest
741 int[2] ints;
742 Tuple!(int, int) t = ints;
746 * Constructor taking a compatible `Tuple`. Two `Tuple`s are compatible
747 * $(B iff) they are both of the same length, and, for each type `T` on the
748 * left-hand side, the corresponding type `U` on the right-hand side can
749 * implicitly convert to `T`.
751 * Params:
752 * another = A compatible `Tuple` to build from. Its type must be
753 * compatible with the target `Tuple`'s type.
755 this(U)(U another)
756 if (areBuildCompatibleTuples!(typeof(this), U) &&
757 (noMemberHasCopyCtor!(typeof(this)) || !is(Unqual!U == Unqual!(typeof(this)))))
759 field[] = another.field[];
763 static if (Specs.length == 0) @safe unittest
765 alias IntVec = Tuple!(int, int, int);
766 alias DubVec = Tuple!(double, double, double);
768 IntVec iv = tuple(1, 1, 1);
770 //Ok, int can implicitly convert to double
771 DubVec dv = iv;
772 //Error: double cannot implicitly convert to int
773 //IntVec iv2 = dv;
777 * Comparison for equality. Two `Tuple`s are considered equal
778 * $(B iff) they fulfill the following criteria:
780 * $(UL
781 * $(LI Each `Tuple` is the same length.)
782 * $(LI For each type `T` on the left-hand side and each type
783 * `U` on the right-hand side, values of type `T` can be
784 * compared with values of type `U`.)
785 * $(LI For each value `v1` on the left-hand side and each value
786 * `v2` on the right-hand side, the expression `v1 == v2` is
787 * true.))
789 * Params:
790 * rhs = The `Tuple` to compare against. It must meeting the criteria
791 * for comparison between `Tuple`s.
793 * Returns:
794 * true if both `Tuple`s are equal, otherwise false.
796 bool opEquals(R)(R rhs)
797 if (areCompatibleTuples!(typeof(this), R, "=="))
799 return field[] == rhs.field[];
802 /// ditto
803 bool opEquals(R)(R rhs) const
804 if (areCompatibleTuples!(typeof(this), R, "=="))
806 return field[] == rhs.field[];
809 /// ditto
810 bool opEquals(R...)(auto ref R rhs)
811 if (R.length > 1 && areCompatibleTuples!(typeof(this), Tuple!R, "=="))
813 static foreach (i; 0 .. Types.length)
814 if (field[i] != rhs[i])
815 return false;
817 return true;
821 static if (Specs.length == 0) @safe unittest
823 Tuple!(int, string) t1 = tuple(1, "test");
824 Tuple!(double, string) t2 = tuple(1.0, "test");
825 //Ok, int can be compared with double and
826 //both have a value of 1
827 assert(t1 == t2);
831 * Comparison for ordering.
833 * Params:
834 * rhs = The `Tuple` to compare against. It must meet the criteria
835 * for comparison between `Tuple`s.
837 * Returns:
838 * For any values `v1` contained by the left-hand side tuple and any
839 * values `v2` contained by the right-hand side:
841 * 0 if `v1 == v2` for all members or the following value for the
842 * first position were the mentioned criteria is not satisfied:
844 * $(UL
845 * $(LI NaN, in case one of the operands is a NaN.)
846 * $(LI A negative number if the expression `v1 < v2` is true.)
847 * $(LI A positive number if the expression `v1 > v2` is true.))
849 auto opCmp(R)(R rhs)
850 if (areCompatibleTuples!(typeof(this), R, "<"))
852 static foreach (i; 0 .. Types.length)
854 if (field[i] != rhs.field[i])
856 import std.math.traits : isNaN;
857 static if (isFloatingPoint!(Types[i]))
859 if (isNaN(field[i]))
860 return float.nan;
862 static if (isFloatingPoint!(typeof(rhs.field[i])))
864 if (isNaN(rhs.field[i]))
865 return float.nan;
867 static if (is(typeof(field[i].opCmp(rhs.field[i]))) &&
868 isFloatingPoint!(typeof(field[i].opCmp(rhs.field[i]))))
870 if (isNaN(field[i].opCmp(rhs.field[i])))
871 return float.nan;
874 return field[i] < rhs.field[i] ? -1 : 1;
877 return 0;
880 /// ditto
881 auto opCmp(R)(R rhs) const
882 if (areCompatibleTuples!(typeof(this), R, "<"))
884 static foreach (i; 0 .. Types.length)
886 if (field[i] != rhs.field[i])
888 import std.math.traits : isNaN;
889 static if (isFloatingPoint!(Types[i]))
891 if (isNaN(field[i]))
892 return float.nan;
894 static if (isFloatingPoint!(typeof(rhs.field[i])))
896 if (isNaN(rhs.field[i]))
897 return float.nan;
899 static if (is(typeof(field[i].opCmp(rhs.field[i]))) &&
900 isFloatingPoint!(typeof(field[i].opCmp(rhs.field[i]))))
902 if (isNaN(field[i].opCmp(rhs.field[i])))
903 return float.nan;
906 return field[i] < rhs.field[i] ? -1 : 1;
909 return 0;
913 The first `v1` for which `v1 > v2` is true determines
914 the result. This could lead to unexpected behaviour.
916 static if (Specs.length == 0) @safe unittest
918 auto tup1 = tuple(1, 1, 1);
919 auto tup2 = tuple(1, 100, 100);
920 assert(tup1 < tup2);
922 //Only the first result matters for comparison
923 tup1[0] = 2;
924 assert(tup1 > tup2);
928 Concatenate Tuples.
929 Tuple concatenation is only allowed if all named fields are distinct (no named field of this tuple occurs in `t`
930 and no named field of `t` occurs in this tuple).
932 Params:
933 t = The `Tuple` to concatenate with
935 Returns: A concatenation of this tuple and `t`
937 auto opBinary(string op, T)(auto ref T t)
938 if (op == "~" && !(is(T : U[], U) && isTuple!U))
940 static if (isTuple!T)
942 static assert(distinctFieldNames!(_Fields, T._Fields),
943 "Cannot concatenate tuples with duplicate fields: " ~ fieldNames.stringof ~
944 " - " ~ T.fieldNames.stringof);
945 return Tuple!(_Fields, T._Fields)(expand, t.expand);
947 else
949 return Tuple!(_Fields, T)(expand, t);
953 /// ditto
954 auto opBinaryRight(string op, T)(auto ref T t)
955 if (op == "~" && !(is(T : U[], U) && isTuple!U))
957 static if (isTuple!T)
959 static assert(distinctFieldNames!(_Fields, T._Fields),
960 "Cannot concatenate tuples with duplicate fields: " ~ T.stringof ~
961 " - " ~ fieldNames.fieldNames.stringof);
962 return Tuple!(T._Fields, _Fields)(t.expand, expand);
964 else
966 return Tuple!(T, _Fields)(t, expand);
971 * Assignment from another `Tuple`.
973 * Params:
974 * rhs = The source `Tuple` to assign from. Each element of the
975 * source `Tuple` must be implicitly assignable to each
976 * respective element of the target `Tuple`.
978 ref Tuple opAssign(R)(auto ref R rhs)
979 if (areCompatibleTuples!(typeof(this), R, "="))
981 import std.algorithm.mutation : swap;
983 static if (is(R : Tuple!Types) && !__traits(isRef, rhs) && isTuple!R)
985 if (__ctfe)
987 // Cannot use swap at compile time
988 field[] = rhs.field[];
990 else
992 // Use swap-and-destroy to optimize rvalue assignment
993 swap!(Tuple!Types)(this, rhs);
996 else
998 // Do not swap; opAssign should be called on the fields.
999 field[] = rhs.field[];
1001 return this;
1005 * Renames the elements of a $(LREF Tuple).
1007 * `rename` uses the passed `names` and returns a new
1008 * $(LREF Tuple) using these names, with the content
1009 * unchanged.
1010 * If fewer names are passed than there are members
1011 * of the $(LREF Tuple) then those trailing members are unchanged.
1012 * An empty string will remove the name for that member.
1013 * It is an compile-time error to pass more names than
1014 * there are members of the $(LREF Tuple).
1016 ref rename(names...)() inout return
1017 if (names.length == 0 || allSatisfy!(isSomeString, typeof(names)))
1019 import std.algorithm.comparison : equal;
1020 // to circumvent https://issues.dlang.org/show_bug.cgi?id=16418
1021 static if (names.length == 0 || equal([names], [fieldNames]))
1022 return this;
1023 else
1025 enum nT = Types.length;
1026 enum nN = names.length;
1027 static assert(nN <= nT, "Cannot have more names than tuple members");
1028 alias allNames = AliasSeq!(names, fieldNames[nN .. $]);
1030 import std.meta : Alias, aliasSeqOf;
1032 template GetItem(size_t idx)
1034 import std.array : empty;
1035 static if (idx < nT)
1036 alias GetItem = Alias!(Types[idx]);
1037 else static if (allNames[idx - nT].empty)
1038 alias GetItem = AliasSeq!();
1039 else
1040 alias GetItem = Alias!(allNames[idx - nT]);
1043 import std.range : roundRobin, iota;
1044 alias NewTupleT = Tuple!(staticMap!(GetItem, aliasSeqOf!(
1045 roundRobin(iota(nT), iota(nT, 2*nT)))));
1046 return *(() @trusted => cast(NewTupleT*)&this)();
1051 static if (Specs.length == 0) @safe unittest
1053 auto t0 = tuple(4, "hello");
1055 auto t0Named = t0.rename!("val", "tag");
1056 assert(t0Named.val == 4);
1057 assert(t0Named.tag == "hello");
1059 Tuple!(float, "dat", size_t[2], "pos") t1;
1060 t1.pos = [2, 1];
1061 auto t1Named = t1.rename!"height";
1062 t1Named.height = 3.4f;
1063 assert(t1Named.height == 3.4f);
1064 assert(t1Named.pos == [2, 1]);
1065 t1Named.rename!"altitude".altitude = 5;
1066 assert(t1Named.height == 5);
1068 Tuple!(int, "a", int, int, "c") t2;
1069 t2 = tuple(3,4,5);
1070 auto t2Named = t2.rename!("", "b");
1071 // "a" no longer has a name
1072 static assert(!__traits(hasMember, typeof(t2Named), "a"));
1073 assert(t2Named[0] == 3);
1074 assert(t2Named.b == 4);
1075 assert(t2Named.c == 5);
1077 // not allowed to specify more names than the tuple has members
1078 static assert(!__traits(compiles, t2.rename!("a","b","c","d")));
1080 // use it in a range pipeline
1081 import std.range : iota, zip;
1082 import std.algorithm.iteration : map, sum;
1083 auto res = zip(iota(1, 4), iota(10, 13))
1084 .map!(t => t.rename!("a", "b"))
1085 .map!(t => t.a * t.b)
1086 .sum;
1087 assert(res == 68);
1089 const tup = Tuple!(int, "a", int, "b")(2, 3);
1090 const renamed = tup.rename!("c", "d");
1091 assert(renamed.c + renamed.d == 5);
1095 * Overload of $(LREF _rename) that takes an associative array
1096 * `translate` as a template parameter, where the keys are
1097 * either the names or indices of the members to be changed
1098 * and the new names are the corresponding values.
1099 * Every key in `translate` must be the name of a member of the
1100 * $(LREF tuple).
1101 * The same rules for empty strings apply as for the variadic
1102 * template overload of $(LREF _rename).
1104 ref rename(alias translate)() inout
1105 if (is(typeof(translate) : V[K], V, K) && isSomeString!V &&
1106 (isSomeString!K || is(K : size_t)))
1108 import std.meta : aliasSeqOf;
1109 import std.range : ElementType;
1110 static if (isSomeString!(ElementType!(typeof(translate.keys))))
1113 import std.conv : to;
1114 import std.algorithm.iteration : filter;
1115 import std.algorithm.searching : canFind;
1116 enum notFound = translate.keys
1117 .filter!(k => fieldNames.canFind(k) == -1);
1118 static assert(notFound.empty, "Cannot find members "
1119 ~ notFound.to!string ~ " in type "
1120 ~ typeof(this).stringof);
1122 return this.rename!(aliasSeqOf!(
1124 import std.array : empty;
1125 auto names = [fieldNames];
1126 foreach (ref n; names)
1127 if (!n.empty)
1128 if (auto p = n in translate)
1129 n = *p;
1130 return names;
1131 }()));
1133 else
1136 import std.algorithm.iteration : filter;
1137 import std.conv : to;
1138 enum invalid = translate.keys.
1139 filter!(k => k < 0 || k >= this.length);
1140 static assert(invalid.empty, "Indices " ~ invalid.to!string
1141 ~ " are out of bounds for tuple with length "
1142 ~ this.length.to!string);
1144 return this.rename!(aliasSeqOf!(
1146 auto names = [fieldNames];
1147 foreach (k, v; translate)
1148 names[k] = v;
1149 return names;
1150 }()));
1155 static if (Specs.length == 0) @safe unittest
1157 //replacing names by their current name
1159 Tuple!(float, "dat", size_t[2], "pos") t1;
1160 t1.pos = [2, 1];
1161 auto t1Named = t1.rename!(["dat": "height"]);
1162 t1Named.height = 3.4;
1163 assert(t1Named.pos == [2, 1]);
1164 t1Named.rename!(["height": "altitude"]).altitude = 5;
1165 assert(t1Named.height == 5);
1167 Tuple!(int, "a", int, "b") t2;
1168 t2 = tuple(3, 4);
1169 auto t2Named = t2.rename!(["a": "b", "b": "c"]);
1170 assert(t2Named.b == 3);
1171 assert(t2Named.c == 4);
1173 const t3 = Tuple!(int, "a", int, "b")(3, 4);
1174 const t3Named = t3.rename!(["a": "b", "b": "c"]);
1175 assert(t3Named.b == 3);
1176 assert(t3Named.c == 4);
1180 static if (Specs.length == 0) @system unittest
1182 //replace names by their position
1184 Tuple!(float, "dat", size_t[2], "pos") t1;
1185 t1.pos = [2, 1];
1186 auto t1Named = t1.rename!([0: "height"]);
1187 t1Named.height = 3.4;
1188 assert(t1Named.pos == [2, 1]);
1189 t1Named.rename!([0: "altitude"]).altitude = 5;
1190 assert(t1Named.height == 5);
1192 Tuple!(int, "a", int, "b", int, "c") t2;
1193 t2 = tuple(3, 4, 5);
1194 auto t2Named = t2.rename!([0: "c", 2: "a"]);
1195 assert(t2Named.a == 5);
1196 assert(t2Named.b == 4);
1197 assert(t2Named.c == 3);
1200 static if (Specs.length == 0) @system unittest
1202 //check that empty translations work fine
1203 enum string[string] a0 = null;
1204 enum string[int] a1 = null;
1205 Tuple!(float, "a", float, "b") t0;
1207 auto t1 = t0.rename!a0;
1209 t1.a = 3;
1210 t1.b = 4;
1211 auto t2 = t0.rename!a1;
1212 t2.a = 3;
1213 t2.b = 4;
1214 auto t3 = t0.rename;
1215 t3.a = 3;
1216 t3.b = 4;
1220 * Takes a slice by-reference of this `Tuple`.
1222 * Params:
1223 * from = A `size_t` designating the starting position of the slice.
1224 * to = A `size_t` designating the ending position (exclusive) of the slice.
1226 * Returns:
1227 * A new `Tuple` that is a slice from `[from, to$(RPAREN)` of the original.
1228 * It has the same types and values as the range `[from, to$(RPAREN)` in
1229 * the original.
1231 @property
1232 ref inout(Tuple!(sliceSpecs!(from, to))) slice(size_t from, size_t to)() inout @trusted
1233 if (from <= to && to <= Types.length)
1235 static assert(
1236 (typeof(this).alignof % typeof(return).alignof == 0) &&
1237 (expand[from].offsetof % typeof(return).alignof == 0),
1238 "Slicing by reference is impossible because of an alignment mistmatch" ~
1239 " (See https://issues.dlang.org/show_bug.cgi?id=15645).");
1241 return *cast(typeof(return)*) &(field[from]);
1245 static if (Specs.length == 0) @safe unittest
1247 Tuple!(int, string, float, double) a;
1248 a[1] = "abc";
1249 a[2] = 4.5;
1250 auto s = a.slice!(1, 3);
1251 static assert(is(typeof(s) == Tuple!(string, float)));
1252 assert(s[0] == "abc" && s[1] == 4.5);
1254 // https://issues.dlang.org/show_bug.cgi?id=15645
1255 Tuple!(int, short, bool, double) b;
1256 static assert(!__traits(compiles, b.slice!(2, 4)));
1260 Creates a hash of this `Tuple`.
1262 Returns:
1263 A `size_t` representing the hash of this `Tuple`.
1265 size_t toHash() const nothrow @safe
1267 size_t h = 0;
1268 static foreach (i, T; Types)
1270 static if (__traits(compiles, h = .hashOf(field[i])))
1271 const k = .hashOf(field[i]);
1272 else
1274 // Workaround for when .hashOf is not both @safe and nothrow.
1275 static if (is(T : shared U, U) && __traits(compiles, (U* a) nothrow @safe => .hashOf(*a))
1276 && !__traits(hasMember, T, "toHash"))
1277 // BUG: Improperly casts away `shared`!
1278 const k = .hashOf(*(() @trusted => cast(U*) &field[i])());
1279 else
1280 // BUG: Improperly casts away `shared`!
1281 const k = typeid(T).getHash((() @trusted => cast(const void*) &field[i])());
1283 static if (i == 0)
1284 h = k;
1285 else
1286 // As in boost::hash_combine
1287 // https://www.boost.org/doc/libs/1_55_0/doc/html/hash/reference.html#boost.hash_combine
1288 h ^= k + 0x9e3779b9 + (h << 6) + (h >>> 2);
1290 return h;
1294 * Converts to string.
1296 * Returns:
1297 * The string representation of this `Tuple`.
1299 string toString()() const
1301 import std.array : appender;
1302 auto app = appender!string();
1303 this.toString((const(char)[] chunk) => app ~= chunk);
1304 return app.data;
1307 import std.format.spec : FormatSpec;
1310 * Formats `Tuple` with either `%s`, `%(inner%)` or `%(inner%|sep%)`.
1312 * $(TABLE2 Formats supported by Tuple,
1313 * $(THEAD Format, Description)
1314 * $(TROW $(P `%s`), $(P Format like `Tuple!(types)(elements formatted with %s each)`.))
1315 * $(TROW $(P `%(inner%)`), $(P The format `inner` is applied the expanded `Tuple`$(COMMA) so
1316 * it may contain as many formats as the `Tuple` has fields.))
1317 * $(TROW $(P `%(inner%|sep%)`), $(P The format `inner` is one format$(COMMA) that is applied
1318 * on all fields of the `Tuple`. The inner format must be compatible to all
1319 * of them.)))
1321 * Params:
1322 * sink = A `char` accepting delegate
1323 * fmt = A $(REF FormatSpec, std,format)
1325 void toString(DG)(scope DG sink) const
1327 auto f = FormatSpec!char();
1328 toString(sink, f);
1331 /// ditto
1332 void toString(DG, Char)(scope DG sink, scope const ref FormatSpec!Char fmt) const
1334 import std.format : format, FormatException;
1335 import std.format.write : formattedWrite;
1336 import std.range : only;
1337 if (fmt.nested)
1339 if (fmt.sep)
1341 foreach (i, Type; Types)
1343 static if (i > 0)
1345 sink(fmt.sep);
1347 // TODO: Change this once formattedWrite() works for shared objects.
1348 static if (is(Type == class) && is(Type == shared))
1350 sink(Type.stringof);
1352 else
1354 formattedWrite(sink, fmt.nested, this.field[i]);
1358 else
1360 formattedWrite(sink, fmt.nested, staticMap!(sharedToString, this.expand));
1363 else if (fmt.spec == 's')
1365 enum header = Unqual!(typeof(this)).stringof ~ "(",
1366 footer = ")",
1367 separator = ", ";
1368 sink(header);
1369 foreach (i, Type; Types)
1371 static if (i > 0)
1373 sink(separator);
1375 // TODO: Change this once format() works for shared objects.
1376 static if (is(Type == class) && is(Type == shared))
1378 sink(Type.stringof);
1380 else
1382 sink(format!("%(%s%)")(only(field[i])));
1385 sink(footer);
1387 else
1389 const spec = fmt.spec;
1390 throw new FormatException(
1391 "Expected '%s' or '%(...%)' or '%(...%|...%)' format specifier for type '" ~
1392 Unqual!(typeof(this)).stringof ~ "', not '%" ~ spec ~ "'.");
1397 static if (Specs.length == 0) @safe unittest
1399 import std.format : format;
1401 Tuple!(int, double)[3] tupList = [ tuple(1, 1.0), tuple(2, 4.0), tuple(3, 9.0) ];
1403 // Default format
1404 assert(format("%s", tuple("a", 1)) == `Tuple!(string, int)("a", 1)`);
1406 // One Format for each individual component
1407 assert(format("%(%#x v %.4f w %#x%)", tuple(1, 1.0, 10)) == `0x1 v 1.0000 w 0xa`);
1408 assert(format( "%#x v %.4f w %#x" , tuple(1, 1.0, 10).expand) == `0x1 v 1.0000 w 0xa`);
1410 // One Format for all components
1411 assert(format("%(>%s<%| & %)", tuple("abc", 1, 2.3, [4, 5])) == `>abc< & >1< & >2.3< & >[4, 5]<`);
1413 // Array of Tuples
1414 assert(format("%(%(f(%d) = %.1f%); %)", tupList) == `f(1) = 1.0; f(2) = 4.0; f(3) = 9.0`);
1418 static if (Specs.length == 0) @safe unittest
1420 import std.exception : assertThrown;
1421 import std.format : format, FormatException;
1423 // Error: %( %) missing.
1424 assertThrown!FormatException(
1425 format("%d, %f", tuple(1, 2.0)) == `1, 2.0`
1428 // Error: %( %| %) missing.
1429 assertThrown!FormatException(
1430 format("%d", tuple(1, 2)) == `1, 2`
1433 // Error: %d inadequate for double
1434 assertThrown!FormatException(
1435 format("%(%d%|, %)", tuple(1, 2.0)) == `1, 2.0`
1442 @safe unittest
1444 Tuple!(int, int) point;
1445 // assign coordinates
1446 point[0] = 5;
1447 point[1] = 6;
1448 // read coordinates
1449 auto x = point[0];
1450 auto y = point[1];
1454 `Tuple` members can be named. It is legal to mix named and unnamed
1455 members. The method above is still applicable to all fields.
1457 @safe unittest
1459 alias Entry = Tuple!(int, "index", string, "value");
1460 Entry e;
1461 e.index = 4;
1462 e.value = "Hello";
1463 assert(e[1] == "Hello");
1464 assert(e[0] == 4);
1468 A `Tuple` with named fields is a distinct type from a `Tuple` with unnamed
1469 fields, i.e. each naming imparts a separate type for the `Tuple`. Two
1470 `Tuple`s differing in naming only are still distinct, even though they
1471 might have the same structure.
1473 @safe unittest
1475 Tuple!(int, "x", int, "y") point1;
1476 Tuple!(int, int) point2;
1477 assert(!is(typeof(point1) == typeof(point2)));
1480 /// Use tuples as ranges
1481 @safe unittest
1483 import std.algorithm.iteration : sum;
1484 import std.range : only;
1485 auto t = tuple(1, 2);
1486 assert(t.expand.only.sum == 3);
1489 // https://issues.dlang.org/show_bug.cgi?id=4582
1490 @safe unittest
1492 static assert(!__traits(compiles, Tuple!(string, "id", int, "id")));
1493 static assert(!__traits(compiles, Tuple!(string, "str", int, "i", string, "str", float)));
1496 /// Concatenate tuples
1497 @safe unittest
1499 import std.meta : AliasSeq;
1500 auto t = tuple(1, "2") ~ tuple(ushort(42), true);
1501 static assert(is(t.Types == AliasSeq!(int, string, ushort, bool)));
1502 assert(t[1] == "2");
1503 assert(t[2] == 42);
1504 assert(t[3] == true);
1507 // https://issues.dlang.org/show_bug.cgi?id=14637
1508 // tuple concat
1509 @safe unittest
1511 auto t = tuple!"foo"(1.0) ~ tuple!"bar"("3");
1512 static assert(is(t.Types == AliasSeq!(double, string)));
1513 static assert(t.fieldNames == tuple("foo", "bar"));
1514 assert(t.foo == 1.0);
1515 assert(t.bar == "3");
1518 // https://issues.dlang.org/show_bug.cgi?id=18824
1519 // tuple concat
1520 @safe unittest
1522 alias Type = Tuple!(int, string);
1523 Type[] arr;
1524 auto t = tuple(2, "s");
1525 // Test opBinaryRight
1526 arr = arr ~ t;
1527 // Test opBinary
1528 arr = t ~ arr;
1529 static assert(is(typeof(arr) == Type[]));
1530 immutable Type[] b;
1531 auto c = b ~ t;
1532 static assert(is(typeof(c) == immutable(Type)[]));
1535 // tuple concat
1536 @safe unittest
1538 auto t = tuple!"foo"(1.0) ~ "3";
1539 static assert(is(t.Types == AliasSeq!(double, string)));
1540 assert(t.foo == 1.0);
1541 assert(t[1]== "3");
1544 // tuple concat
1545 @safe unittest
1547 auto t = "2" ~ tuple!"foo"(1.0);
1548 static assert(is(t.Types == AliasSeq!(string, double)));
1549 assert(t.foo == 1.0);
1550 assert(t[0]== "2");
1553 // tuple concat
1554 @safe unittest
1556 auto t = "2" ~ tuple!"foo"(1.0) ~ tuple(42, 3.0f) ~ real(1) ~ "a";
1557 static assert(is(t.Types == AliasSeq!(string, double, int, float, real, string)));
1558 assert(t.foo == 1.0);
1559 assert(t[0] == "2");
1560 assert(t[1] == 1.0);
1561 assert(t[2] == 42);
1562 assert(t[3] == 3.0f);
1563 assert(t[4] == 1.0);
1564 assert(t[5] == "a");
1567 // ensure that concatenation of tuples with non-distinct fields is forbidden
1568 @safe unittest
1570 static assert(!__traits(compiles,
1571 tuple!("a")(0) ~ tuple!("a")("1")));
1572 static assert(!__traits(compiles,
1573 tuple!("a", "b")(0, 1) ~ tuple!("b", "a")("3", 1)));
1574 static assert(!__traits(compiles,
1575 tuple!("a")(0) ~ tuple!("b", "a")("3", 1)));
1576 static assert(!__traits(compiles,
1577 tuple!("a1", "a")(1.0, 0) ~ tuple!("a2", "a")("3", 0)));
1580 // Ensure that Tuple comparison with non-const opEquals works
1581 @safe unittest
1583 static struct Bad
1585 int a;
1587 bool opEquals(Bad b)
1589 return a == b.a;
1593 auto t = Tuple!(int, Bad, string)(1, Bad(1), "asdf");
1595 //Error: mutable method Bad.opEquals is not callable using a const object
1596 assert(t == AliasSeq!(1, Bad(1), "asdf"));
1599 // Ensure Tuple.toHash works
1600 @safe unittest
1602 Tuple!(int, int) point;
1603 assert(point.toHash == typeof(point).init.toHash);
1604 assert(tuple(1, 2) != point);
1605 assert(tuple(1, 2) == tuple(1, 2));
1606 point[0] = 1;
1607 assert(tuple(1, 2) != point);
1608 point[1] = 2;
1609 assert(tuple(1, 2) == point);
1612 @safe @betterC unittest
1614 auto t = tuple(1, 2);
1615 assert(t == tuple(1, 2));
1616 auto t3 = tuple(1, 'd');
1619 // https://issues.dlang.org/show_bug.cgi?id=20850
1620 // Assignment to enum tuple
1621 @safe unittest
1623 enum T : Tuple!(int*) { a = T(null) }
1624 T t;
1625 t = T.a;
1628 // https://issues.dlang.org/show_bug.cgi?id=13663
1629 @safe unittest
1631 auto t = tuple(real.nan);
1632 assert(!(t > t));
1633 assert(!(t < t));
1634 assert(!(t == t));
1637 @safe unittest
1639 struct S
1641 float opCmp(S s) { return float.nan; }
1642 bool opEquals(S s) { return false; }
1645 auto t = tuple(S());
1646 assert(!(t > t));
1647 assert(!(t < t));
1648 assert(!(t == t));
1651 // https://issues.dlang.org/show_bug.cgi?id=8015
1652 @safe unittest
1654 struct MyStruct
1656 string str;
1657 @property string toStr()
1659 return str;
1661 alias toStr this;
1664 Tuple!(MyStruct) t;
1667 // https://issues.dlang.org/show_bug.cgi?id=24465
1668 @safe unittest
1671 static struct S
1673 this(ref return scope inout(S) rhs) scope @trusted inout pure nothrow {}
1676 static void foo(Tuple!S)
1680 Tuple!S t;
1681 foo(t);
1683 auto t2 = Tuple!S(t);
1687 static struct S {}
1688 Tuple!S t;
1689 auto t2 = Tuple!S(t);
1691 // This can't be done if Tuple has a copy constructor, because it's not
1692 // allowed to have an rvalue constructor at that point, and the
1693 // compiler doesn't to something intelligent like transform it into a
1694 // move instead. However, it has been legal with Tuple for a while
1695 // (maybe even since it was first added) when the type doesn't have a
1696 // copy constructor, so this is testing to make sure that the fix to
1697 // make copy constructors work doesn't mess up the rvalue constructor
1698 // when none of the Tuple's members have copy constructors.
1699 auto t3 = Tuple!S(Tuple!S.init);
1704 Creates a copy of a $(LREF Tuple) with its fields in _reverse order.
1706 Params:
1707 t = The `Tuple` to copy.
1709 Returns:
1710 A new `Tuple`.
1712 auto reverse(T)(T t)
1713 if (isTuple!T)
1715 import std.meta : Reverse;
1716 // @@@BUG@@@ Cannot be an internal function due to forward reference issues.
1718 // @@@BUG@@@ 9929 Need 'this' when calling template with expanded tuple
1719 // return tuple(Reverse!(t.expand));
1721 ReverseTupleType!T result;
1722 auto tup = t.expand;
1723 result.expand = Reverse!tup;
1724 return result;
1728 @safe unittest
1730 auto tup = tuple(1, "2");
1731 assert(tup.reverse == tuple("2", 1));
1734 /* Get a Tuple type with the reverse specification of Tuple T. */
1735 private template ReverseTupleType(T)
1736 if (isTuple!T)
1738 static if (is(T : Tuple!A, A...))
1739 alias ReverseTupleType = Tuple!(ReverseTupleSpecs!A);
1742 /* Reverse the Specs of a Tuple. */
1743 private template ReverseTupleSpecs(T...)
1745 static if (T.length > 1)
1747 static if (is(typeof(T[$-1]) : string))
1749 alias ReverseTupleSpecs = AliasSeq!(T[$-2], T[$-1], ReverseTupleSpecs!(T[0 .. $-2]));
1751 else
1753 alias ReverseTupleSpecs = AliasSeq!(T[$-1], ReverseTupleSpecs!(T[0 .. $-1]));
1756 else
1758 alias ReverseTupleSpecs = T;
1762 // ensure that internal Tuple unittests are compiled
1763 @safe unittest
1765 Tuple!() t;
1768 @safe unittest
1770 import std.conv;
1772 Tuple!(int, "a", int, "b") nosh;
1773 static assert(nosh.length == 2);
1774 nosh.a = 5;
1775 nosh.b = 6;
1776 assert(nosh.a == 5);
1777 assert(nosh.b == 6);
1780 Tuple!(short, double) b;
1781 static assert(b.length == 2);
1782 b[1] = 5;
1783 auto a = Tuple!(int, real)(b);
1784 assert(a[0] == 0 && a[1] == 5);
1785 a = Tuple!(int, real)(1, 2);
1786 assert(a[0] == 1 && a[1] == 2);
1787 auto c = Tuple!(int, "a", double, "b")(a);
1788 assert(c[0] == 1 && c[1] == 2);
1791 Tuple!(int, real) nosh;
1792 nosh[0] = 5;
1793 nosh[1] = 0;
1794 assert(nosh[0] == 5 && nosh[1] == 0);
1795 assert(nosh.to!string == "Tuple!(int, real)(5, 0)", nosh.to!string);
1796 Tuple!(int, int) yessh;
1797 nosh = yessh;
1800 class A {}
1801 Tuple!(int, shared A) nosh;
1802 nosh[0] = 5;
1803 assert(nosh[0] == 5 && nosh[1] is null);
1804 assert(nosh.to!string == "Tuple!(int, shared(A))(5, shared(A))");
1807 Tuple!(int, string) t;
1808 t[0] = 10;
1809 t[1] = "str";
1810 assert(t[0] == 10 && t[1] == "str");
1811 assert(t.to!string == `Tuple!(int, string)(10, "str")`, t.to!string);
1814 Tuple!(int, "a", double, "b") x;
1815 static assert(x.a.offsetof == x[0].offsetof);
1816 static assert(x.b.offsetof == x[1].offsetof);
1817 x.b = 4.5;
1818 x.a = 5;
1819 assert(x[0] == 5 && x[1] == 4.5);
1820 assert(x.a == 5 && x.b == 4.5);
1822 // indexing
1824 Tuple!(int, real) t;
1825 static assert(is(typeof(t[0]) == int));
1826 static assert(is(typeof(t[1]) == real));
1827 int* p0 = &t[0];
1828 real* p1 = &t[1];
1829 t[0] = 10;
1830 t[1] = -200.0L;
1831 assert(*p0 == t[0]);
1832 assert(*p1 == t[1]);
1834 // slicing
1836 Tuple!(int, "x", real, "y", double, "z", string) t;
1837 t[0] = 10;
1838 t[1] = 11;
1839 t[2] = 12;
1840 t[3] = "abc";
1841 auto a = t.slice!(0, 3);
1842 assert(a.length == 3);
1843 assert(a.x == t.x);
1844 assert(a.y == t.y);
1845 assert(a.z == t.z);
1846 auto b = t.slice!(2, 4);
1847 assert(b.length == 2);
1848 assert(b.z == t.z);
1849 assert(b[1] == t[3]);
1851 // nesting
1853 Tuple!(Tuple!(int, real), Tuple!(string, "s")) t;
1854 static assert(is(typeof(t[0]) == Tuple!(int, real)));
1855 static assert(is(typeof(t[1]) == Tuple!(string, "s")));
1856 static assert(is(typeof(t[0][0]) == int));
1857 static assert(is(typeof(t[0][1]) == real));
1858 static assert(is(typeof(t[1].s) == string));
1859 t[0] = tuple(10, 20.0L);
1860 t[1].s = "abc";
1861 assert(t[0][0] == 10);
1862 assert(t[0][1] == 20.0L);
1863 assert(t[1].s == "abc");
1865 // non-POD
1867 static struct S
1869 int count;
1870 this(this) { ++count; }
1871 ~this() { --count; }
1872 void opAssign(S rhs) { count = rhs.count; }
1874 Tuple!(S, S) ss;
1875 Tuple!(S, S) ssCopy = ss;
1876 assert(ssCopy[0].count == 1);
1877 assert(ssCopy[1].count == 1);
1878 ssCopy[1] = ssCopy[0];
1879 assert(ssCopy[1].count == 2);
1881 // https://issues.dlang.org/show_bug.cgi?id=2800
1883 static struct R
1885 Tuple!(int, int) _front;
1886 @property ref Tuple!(int, int) front() return { return _front; }
1887 @property bool empty() { return _front[0] >= 10; }
1888 void popFront() { ++_front[0]; }
1890 foreach (a; R())
1892 static assert(is(typeof(a) == Tuple!(int, int)));
1893 assert(0 <= a[0] && a[0] < 10);
1894 assert(a[1] == 0);
1897 // Construction with compatible elements
1899 auto t1 = Tuple!(int, double)(1, 1);
1901 // https://issues.dlang.org/show_bug.cgi?id=8702
1902 auto t8702a = tuple(tuple(1));
1903 auto t8702b = Tuple!(Tuple!(int))(Tuple!(int)(1));
1905 // Construction with compatible tuple
1907 Tuple!(int, int) x;
1908 x[0] = 10;
1909 x[1] = 20;
1910 Tuple!(int, "a", double, "b") y = x;
1911 assert(y.a == 10);
1912 assert(y.b == 20);
1913 // incompatible
1914 static assert(!__traits(compiles, Tuple!(int, int)(y)));
1916 // https://issues.dlang.org/show_bug.cgi?id=6275
1918 const int x = 1;
1919 auto t1 = tuple(x);
1920 alias T = Tuple!(const(int));
1921 auto t2 = T(1);
1923 // https://issues.dlang.org/show_bug.cgi?id=9431
1925 alias T = Tuple!(int[1][]);
1926 auto t = T([[10]]);
1928 // https://issues.dlang.org/show_bug.cgi?id=7666
1930 auto tup = tuple(1, "2");
1931 assert(tup.reverse == tuple("2", 1));
1934 Tuple!(int, "x", string, "y") tup = tuple(1, "2");
1935 auto rev = tup.reverse;
1936 assert(rev == tuple("2", 1));
1937 assert(rev.x == 1 && rev.y == "2");
1940 Tuple!(wchar, dchar, int, "x", string, "y", char, byte, float) tup;
1941 tup = tuple('a', 'b', 3, "4", 'c', cast(byte) 0x0D, 0.00);
1942 auto rev = tup.reverse;
1943 assert(rev == tuple(0.00, cast(byte) 0x0D, 'c', "4", 3, 'b', 'a'));
1944 assert(rev.x == 3 && rev.y == "4");
1947 @safe unittest
1949 // opEquals
1951 struct Equ1 { bool opEquals(Equ1) { return true; } }
1952 auto tm1 = tuple(Equ1.init);
1953 const tc1 = tuple(Equ1.init);
1954 static assert( is(typeof(tm1 == tm1)));
1955 static assert(!is(typeof(tm1 == tc1)));
1956 static assert(!is(typeof(tc1 == tm1)));
1957 static assert(!is(typeof(tc1 == tc1)));
1959 struct Equ2 { bool opEquals(const Equ2) const { return true; } }
1960 auto tm2 = tuple(Equ2.init);
1961 const tc2 = tuple(Equ2.init);
1962 static assert( is(typeof(tm2 == tm2)));
1963 static assert( is(typeof(tm2 == tc2)));
1964 static assert( is(typeof(tc2 == tm2)));
1965 static assert( is(typeof(tc2 == tc2)));
1967 // https://issues.dlang.org/show_bug.cgi?id=8686
1968 struct Equ3 { bool opEquals(T)(T) { return true; } }
1969 auto tm3 = tuple(Equ3.init);
1970 const tc3 = tuple(Equ3.init);
1971 static assert( is(typeof(tm3 == tm3)));
1972 static assert( is(typeof(tm3 == tc3)));
1973 static assert(!is(typeof(tc3 == tm3)));
1974 static assert(!is(typeof(tc3 == tc3)));
1976 struct Equ4 { bool opEquals(T)(T) const { return true; } }
1977 auto tm4 = tuple(Equ4.init);
1978 const tc4 = tuple(Equ4.init);
1979 static assert( is(typeof(tm4 == tm4)));
1980 static assert( is(typeof(tm4 == tc4)));
1981 static assert( is(typeof(tc4 == tm4)));
1982 static assert( is(typeof(tc4 == tc4)));
1984 // opCmp
1986 struct Cmp1 { int opCmp(Cmp1) { return 0; } }
1987 auto tm1 = tuple(Cmp1.init);
1988 const tc1 = tuple(Cmp1.init);
1989 static assert( is(typeof(tm1 < tm1)));
1990 static assert(!is(typeof(tm1 < tc1)));
1991 static assert(!is(typeof(tc1 < tm1)));
1992 static assert(!is(typeof(tc1 < tc1)));
1994 struct Cmp2 { int opCmp(const Cmp2) const { return 0; } }
1995 auto tm2 = tuple(Cmp2.init);
1996 const tc2 = tuple(Cmp2.init);
1997 static assert( is(typeof(tm2 < tm2)));
1998 static assert( is(typeof(tm2 < tc2)));
1999 static assert( is(typeof(tc2 < tm2)));
2000 static assert( is(typeof(tc2 < tc2)));
2002 struct Cmp3 { int opCmp(T)(T) { return 0; } }
2003 auto tm3 = tuple(Cmp3.init);
2004 const tc3 = tuple(Cmp3.init);
2005 static assert( is(typeof(tm3 < tm3)));
2006 static assert( is(typeof(tm3 < tc3)));
2007 static assert(!is(typeof(tc3 < tm3)));
2008 static assert(!is(typeof(tc3 < tc3)));
2010 struct Cmp4 { int opCmp(T)(T) const { return 0; } }
2011 auto tm4 = tuple(Cmp4.init);
2012 const tc4 = tuple(Cmp4.init);
2013 static assert( is(typeof(tm4 < tm4)));
2014 static assert( is(typeof(tm4 < tc4)));
2015 static assert( is(typeof(tc4 < tm4)));
2016 static assert( is(typeof(tc4 < tc4)));
2018 // https://issues.dlang.org/show_bug.cgi?id=14890
2019 static void test14890(inout int[] dummy)
2021 alias V = Tuple!(int, int);
2023 V mv;
2024 const V cv;
2025 immutable V iv;
2026 inout V wv; // OK <- NG
2027 inout const V wcv; // OK <- NG
2029 static foreach (v1; AliasSeq!(mv, cv, iv, wv, wcv))
2030 static foreach (v2; AliasSeq!(mv, cv, iv, wv, wcv))
2032 assert(!(v1 < v2));
2036 int[2] ints = [ 1, 2 ];
2037 Tuple!(int, int) t = ints;
2038 assert(t[0] == 1 && t[1] == 2);
2039 Tuple!(long, uint) t2 = ints;
2040 assert(t2[0] == 1 && t2[1] == 2);
2043 @safe unittest
2045 auto t1 = Tuple!(int, "x", string, "y")(1, "a");
2046 assert(t1.x == 1);
2047 assert(t1.y == "a");
2048 void foo(Tuple!(int, string) t2) {}
2049 foo(t1);
2051 Tuple!(int, int)[] arr;
2052 arr ~= tuple(10, 20); // OK
2053 arr ~= Tuple!(int, "x", int, "y")(10, 20); // NG -> OK
2055 static assert(is(typeof(Tuple!(int, "x", string, "y").tupleof) ==
2056 typeof(Tuple!(int, string ).tupleof)));
2058 @safe unittest
2060 // https://issues.dlang.org/show_bug.cgi?id=10686
2061 immutable Tuple!(int) t1;
2062 auto r1 = t1[0]; // OK
2063 immutable Tuple!(int, "x") t2;
2064 auto r2 = t2[0]; // error
2066 @safe unittest
2068 import std.exception : assertCTFEable;
2070 // https://issues.dlang.org/show_bug.cgi?id=10218
2071 assertCTFEable!(
2073 auto t = tuple(1);
2074 t = tuple(2); // assignment
2077 @safe unittest
2079 class Foo{}
2080 Tuple!(immutable(Foo)[]) a;
2083 @safe unittest
2085 //Test non-assignable
2086 static struct S
2088 int* p;
2090 alias IS = immutable S;
2091 static assert(!isAssignable!IS);
2093 auto s = IS.init;
2095 alias TIS = Tuple!IS;
2096 TIS a = tuple(s);
2097 TIS b = a;
2099 alias TISIS = Tuple!(IS, IS);
2100 TISIS d = tuple(s, s);
2101 IS[2] ss;
2102 TISIS e = TISIS(ss);
2105 // https://issues.dlang.org/show_bug.cgi?id=9819
2106 @safe unittest
2108 alias T = Tuple!(int, "x", double, "foo");
2109 static assert(T.fieldNames[0] == "x");
2110 static assert(T.fieldNames[1] == "foo");
2112 alias Fields = Tuple!(int, "id", string, float);
2113 static assert(Fields.fieldNames == AliasSeq!("id", "", ""));
2116 // https://issues.dlang.org/show_bug.cgi?id=13837
2117 @safe unittest
2119 // New behaviour, named arguments.
2120 static assert(is(
2121 typeof(tuple!("x")(1)) == Tuple!(int, "x")));
2122 static assert(is(
2123 typeof(tuple!("x")(1.0)) == Tuple!(double, "x")));
2124 static assert(is(
2125 typeof(tuple!("x")("foo")) == Tuple!(string, "x")));
2126 static assert(is(
2127 typeof(tuple!("x", "y")(1, 2.0)) == Tuple!(int, "x", double, "y")));
2129 auto a = tuple!("a", "b", "c")("1", 2, 3.0f);
2130 static assert(is(typeof(a.a) == string));
2131 static assert(is(typeof(a.b) == int));
2132 static assert(is(typeof(a.c) == float));
2134 // Old behaviour, but with explicit type parameters.
2135 static assert(is(
2136 typeof(tuple!(int, double)(1, 2.0)) == Tuple!(int, double)));
2137 static assert(is(
2138 typeof(tuple!(const int)(1)) == Tuple!(const int)));
2139 static assert(is(
2140 typeof(tuple()) == Tuple!()));
2142 // Nonsensical behaviour
2143 static assert(!__traits(compiles, tuple!(1)(2)));
2144 static assert(!__traits(compiles, tuple!("x")(1, 2)));
2145 static assert(!__traits(compiles, tuple!("x", "y")(1)));
2146 static assert(!__traits(compiles, tuple!("x")()));
2147 static assert(!__traits(compiles, tuple!("x", int)(2)));
2150 @safe unittest
2152 class C { override size_t toHash() const nothrow @safe { return 0; } }
2153 Tuple!(Rebindable!(const C)) a;
2154 Tuple!(const C) b;
2155 a = b;
2158 @nogc @safe unittest
2160 alias T = Tuple!(string, "s");
2161 T x;
2162 x = T.init;
2165 @safe unittest
2167 import std.format : format, FormatException;
2168 import std.exception : assertThrown;
2170 //enum tupStr = tuple(1, 1.0).toString; // toString is *impure*.
2171 //static assert(tupStr == `Tuple!(int, double)(1, 1)`);
2174 // https://issues.dlang.org/show_bug.cgi?id=17803, parte uno
2175 @safe unittest
2177 auto a = tuple(3, "foo");
2178 assert(__traits(compiles, { a = (a = a); }));
2180 // Ditto
2181 @safe unittest
2183 Tuple!(int[]) a, b, c;
2184 a = tuple([0, 1, 2]);
2185 c = b = a;
2186 assert(a[0].length == b[0].length && b[0].length == c[0].length);
2187 assert(a[0].ptr == b[0].ptr && b[0].ptr == c[0].ptr);
2191 Constructs a $(LREF Tuple) object instantiated and initialized according to
2192 the given arguments.
2194 Params:
2195 Names = An optional list of strings naming each successive field of the `Tuple`
2196 or a list of types that the elements are being casted to.
2197 For a list of names,
2198 each name matches up with the corresponding field given by `Args`.
2199 A name does not have to be provided for every field, but as
2200 the names must proceed in order, it is not possible to skip
2201 one field and name the next after it.
2202 For a list of types,
2203 there must be exactly as many types as parameters.
2205 template tuple(Names...)
2208 Params:
2209 args = Values to initialize the `Tuple` with. The `Tuple`'s type will
2210 be inferred from the types of the values given.
2212 Returns:
2213 A new `Tuple` with its type inferred from the arguments given.
2215 auto tuple(Args...)(Args args)
2217 static if (Names.length == 0)
2219 // No specified names, just infer types from Args...
2220 return Tuple!Args(args);
2222 else static if (!is(typeof(Names[0]) : string))
2224 // Names[0] isn't a string, must be explicit types.
2225 return Tuple!Names(args);
2227 else
2229 // Names[0] is a string, so must be specifying names.
2230 static assert(Names.length == Args.length,
2231 "Insufficient number of names given.");
2233 // Interleave(a, b).and(c, d) == (a, c, b, d)
2234 // This is to get the interleaving of types and names for Tuple
2235 // e.g. Tuple!(int, "x", string, "y")
2236 template Interleave(A...)
2238 template and(B...) if (B.length == 1)
2240 alias and = AliasSeq!(A[0], B[0]);
2243 template and(B...) if (B.length != 1)
2245 alias and = AliasSeq!(A[0], B[0],
2246 Interleave!(A[1..$]).and!(B[1..$]));
2249 return Tuple!(Interleave!(Args).and!(Names))(args);
2255 @safe unittest
2257 auto value = tuple(5, 6.7, "hello");
2258 assert(value[0] == 5);
2259 assert(value[1] == 6.7);
2260 assert(value[2] == "hello");
2262 // Field names can be provided.
2263 auto entry = tuple!("index", "value")(4, "Hello");
2264 assert(entry.index == 4);
2265 assert(entry.value == "Hello");
2269 Returns `true` if and only if `T` is an instance of `std.typecons.Tuple`.
2271 Params:
2272 T = The type to check.
2274 Returns:
2275 true if `T` is a `Tuple` type, false otherwise.
2277 enum isTuple(T) = __traits(compiles,
2279 void f(Specs...)(Tuple!Specs tup) {}
2280 f(T.init);
2281 } );
2284 @safe unittest
2286 static assert(isTuple!(Tuple!()));
2287 static assert(isTuple!(Tuple!(int)));
2288 static assert(isTuple!(Tuple!(int, real, string)));
2289 static assert(isTuple!(Tuple!(int, "x", real, "y")));
2290 static assert(isTuple!(Tuple!(int, Tuple!(real), string)));
2293 @safe unittest
2295 static assert(isTuple!(const Tuple!(int)));
2296 static assert(isTuple!(immutable Tuple!(int)));
2298 static assert(!isTuple!(int));
2299 static assert(!isTuple!(const int));
2301 struct S {}
2302 static assert(!isTuple!(S));
2305 // used by both Rebindable and UnqualRef
2306 private mixin template RebindableCommon(T, U, alias This)
2307 if (is(T == class) || is(T == interface) || isAssociativeArray!T)
2309 private union
2311 T original;
2312 U stripped;
2315 void opAssign(return scope T another) pure nothrow @nogc
2317 // If `T` defines `opCast` we must infer the safety
2318 static if (hasMember!(T, "opCast"))
2320 // This will allow the compiler to infer the safety of `T.opCast!U`
2321 // without generating any runtime cost
2322 if (false) { stripped = cast(U) another; }
2324 () @trusted { stripped = cast(U) another; }();
2327 void opAssign(typeof(this) another) @trusted pure nothrow @nogc
2329 stripped = another.stripped;
2332 static if (is(T == const U) && is(T == const shared U))
2334 // safely assign immutable to const / const shared
2335 void opAssign(This!(immutable U) another) @trusted pure nothrow @nogc
2337 stripped = another.stripped;
2341 this(T initializer) pure nothrow @nogc
2343 // Infer safety from opAssign
2344 opAssign(initializer);
2347 @property inout(T) get() @trusted pure nothrow @nogc return scope inout
2349 return original;
2352 bool opEquals()(auto ref const(typeof(this)) rhs) const
2354 // Must forward explicitly because 'stripped' is part of a union.
2355 // The necessary 'toHash' is forwarded to the class via alias this.
2356 return stripped == rhs.stripped;
2359 bool opEquals(const(U) rhs) const
2361 return stripped == rhs;
2364 alias get this;
2368 `Rebindable!(T)` is a simple, efficient wrapper that behaves just
2369 like an object of type `T`, except that you can reassign it to
2370 refer to another object. For completeness, `Rebindable!(T)` aliases
2371 itself away to `T` if `T` is a non-const object type.
2373 You may want to use `Rebindable` when you want to have mutable
2374 storage referring to `const` objects, for example an array of
2375 references that must be sorted in place. `Rebindable` does not
2376 break the soundness of D's type system and does not incur any of the
2377 risks usually associated with `cast`.
2379 Params:
2380 T = Any type.
2382 template Rebindable(T)
2383 if (is(T == class) || is(T == interface) || isDynamicArray!T || isAssociativeArray!T)
2385 static if (is(T == const U, U) || is(T == immutable U, U))
2387 static if (isDynamicArray!T)
2389 import std.range.primitives : ElementEncodingType;
2390 alias Rebindable = const(ElementEncodingType!T)[];
2392 else
2394 struct Rebindable
2396 mixin RebindableCommon!(T, U, Rebindable);
2400 else
2402 alias Rebindable = T;
2406 ///Regular `const` object references cannot be reassigned.
2407 @safe unittest
2409 class Widget { int x; int y() @safe const { return x; } }
2410 const a = new Widget;
2411 // Fine
2412 a.y();
2413 // error! can't modify const a
2414 // a.x = 5;
2415 // error! can't modify const a
2416 // a = new Widget;
2420 However, `Rebindable!(Widget)` does allow reassignment,
2421 while otherwise behaving exactly like a $(D const Widget).
2423 @safe unittest
2425 class Widget { int x; int y() const @safe { return x; } }
2426 auto a = Rebindable!(const Widget)(new Widget);
2427 // Fine
2428 a.y();
2429 // error! can't modify const a
2430 // a.x = 5;
2431 // Fine
2432 a = new Widget;
2435 // https://issues.dlang.org/show_bug.cgi?id=16054
2436 @safe unittest
2438 Rebindable!(immutable Object) r;
2439 static assert(__traits(compiles, r.get()));
2440 static assert(!__traits(compiles, &r.get()));
2443 /// ditto
2444 struct Rebindable(T)
2445 if (!is(T == class) && !is(T == interface) && !isDynamicArray!T && !isAssociativeArray!T)
2447 private:
2448 static if (isAssignable!(typeof(cast() T.init)))
2450 enum useQualifierCast = true;
2452 typeof(cast() T.init) data;
2454 else
2456 enum useQualifierCast = false;
2458 align(T.alignof)
2459 static struct Payload
2461 static if (hasIndirections!T)
2463 void[T.sizeof] data;
2465 else
2467 ubyte[T.sizeof] data;
2471 Payload data;
2474 public:
2476 static if (!__traits(compiles, { T value; }))
2478 @disable this();
2482 * Constructs a `Rebindable` from a given value.
2484 this(T value) @trusted
2486 static if (useQualifierCast)
2488 this.data = cast() value;
2490 else
2492 set(value);
2497 * Overwrites the currently stored value with `value`.
2499 void opAssign(this This)(T value) @trusted
2501 clear;
2502 set(value);
2506 * Returns the value currently stored in the `Rebindable`.
2508 T get(this This)() @property @trusted
2510 static if (useQualifierCast)
2512 return cast(T) this.data;
2514 else
2516 return *cast(T*) &this.data;
2520 static if (!useQualifierCast)
2522 ~this() @trusted
2524 clear;
2529 alias get this;
2531 private:
2533 void set(this This)(T value)
2535 static if (useQualifierCast)
2537 this.data = cast() value;
2539 else
2541 // As we're escaping a copy of `value`, deliberately leak a copy:
2542 static union DontCallDestructor
2544 T value;
2546 DontCallDestructor copy = DontCallDestructor(value);
2547 this.data = *cast(Payload*) &copy;
2551 void clear(this This)()
2553 // work around reinterpreting cast being impossible in CTFE
2554 if (__ctfe)
2556 return;
2559 // call possible struct destructors
2560 .destroy!(No.initialize)(*cast(T*) &this.data);
2564 /// Using Rebindable in a generic algorithm:
2565 @safe unittest
2567 import std.range.primitives : front, popFront;
2569 // simple version of std.algorithm.searching.maxElement
2570 typeof(R.init.front) maxElement(R)(R r)
2572 auto max = rebindable(r.front);
2573 r.popFront;
2574 foreach (e; r)
2575 if (e > max)
2576 max = e; // Rebindable allows const-correct reassignment
2577 return max;
2579 struct S
2581 char[] arr;
2582 alias arr this; // for comparison
2584 // can't convert to mutable
2585 const S cs;
2586 static assert(!__traits(compiles, { S s = cs; }));
2588 alias CS = const S;
2589 CS[] arr = [CS("harp"), CS("apple"), CS("pot")];
2590 CS ms = maxElement(arr);
2591 assert(ms.arr == "pot");
2594 // https://issues.dlang.org/show_bug.cgi?id=18615
2595 // Rebindable!A should use A.opEqualsa
2596 @system unittest
2598 class CustomOpEq
2600 int x;
2601 override bool opEquals(Object rhsObj)
2603 if (auto rhs = cast(const(CustomOpEq)) rhsObj)
2604 return this.x == rhs.x;
2605 else
2606 return false;
2609 CustomOpEq a = new CustomOpEq();
2610 CustomOpEq b = new CustomOpEq();
2611 assert(a !is b);
2612 assert(a == b, "a.x == b.x should be true (0 == 0).");
2614 Rebindable!(const(CustomOpEq)) ra = a;
2615 Rebindable!(const(CustomOpEq)) rb = b;
2616 assert(ra !is rb);
2617 assert(ra == rb, "Rebindable should use CustomOpEq's opEquals, not 'is'.");
2618 assert(ra == b, "Rebindable!(someQualifier(A)) should be comparable"
2619 ~ " against const(A) via A.opEquals.");
2620 assert(a == rb, "Rebindable!(someQualifier(A)) should be comparable"
2621 ~ " against const(A) via A.opEquals.");
2623 b.x = 1;
2624 assert(a != b);
2625 assert(ra != b, "Rebindable!(someQualifier(A)) should be comparable"
2626 ~ " against const(A) via A.opEquals.");
2627 assert(a != rb, "Rebindable!(someQualifier(A)) should be comparable"
2628 ~ " against const(A) via A.opEquals.");
2630 Rebindable!(const(Object)) o1 = new Object();
2631 Rebindable!(const(Object)) o2 = new Object();
2632 assert(o1 !is o2);
2633 assert(o1 == o1, "When the class doesn't provide its own opEquals,"
2634 ~ " Rebindable treats 'a == b' as 'a is b' like Object.opEquals.");
2635 assert(o1 != o2, "When the class doesn't provide its own opEquals,"
2636 ~ " Rebindable treats 'a == b' as 'a is b' like Object.opEquals.");
2637 assert(o1 != new Object(), "Rebindable!(const(Object)) should be"
2638 ~ " comparable against Object itself and use Object.opEquals.");
2642 @system unittest
2644 static struct S
2646 int* ptr;
2648 S s = S(new int);
2650 const cs = s;
2651 // Can't assign s.ptr to cs.ptr
2652 static assert(!__traits(compiles, {s = cs;}));
2654 Rebindable!(const S) rs = s;
2655 assert(rs.ptr is s.ptr);
2656 // rs.ptr is const
2657 static assert(!__traits(compiles, {rs.ptr = null;}));
2659 // Can't assign s.ptr to rs.ptr
2660 static assert(!__traits(compiles, {s = rs;}));
2662 const S cs2 = rs;
2663 // Rebind rs
2664 rs = cs2;
2665 rs = S();
2666 assert(rs.ptr is null);
2669 // https://issues.dlang.org/show_bug.cgi?id=18755
2670 @safe unittest
2672 static class Foo
2674 auto opCast(T)() @system immutable pure nothrow
2676 *(cast(uint*) 0xdeadbeef) = 0xcafebabe;
2677 return T.init;
2681 static assert(!__traits(compiles, () @safe {
2682 auto r = Rebindable!(immutable Foo)(new Foo);
2683 }));
2684 static assert(__traits(compiles, () @system {
2685 auto r = Rebindable!(immutable Foo)(new Foo);
2686 }));
2689 @safe unittest
2691 class CustomToHash
2693 override size_t toHash() const nothrow @trusted { return 42; }
2695 Rebindable!(immutable(CustomToHash)) a = new immutable CustomToHash();
2696 assert(a.toHash() == 42, "Rebindable!A should offer toHash()"
2697 ~ " by forwarding to A.toHash().");
2700 // Test Rebindable!immutable
2701 @safe unittest
2703 static struct S
2705 int* ptr;
2707 S s = S(new int);
2709 Rebindable!(immutable S) ri = S(new int);
2710 assert(ri.ptr !is null);
2711 static assert(!__traits(compiles, {ri.ptr = null;}));
2713 // ri is not compatible with mutable S
2714 static assert(!__traits(compiles, {s = ri;}));
2715 static assert(!__traits(compiles, {ri = s;}));
2717 auto ri2 = ri;
2718 assert(ri2.ptr == ri.ptr);
2720 const S cs3 = ri;
2721 static assert(!__traits(compiles, {ri = cs3;}));
2723 immutable S si = ri;
2724 // Rebind ri
2725 ri = si;
2726 ri = S();
2727 assert(ri.ptr is null);
2729 // Test RB!immutable -> RB!const
2730 Rebindable!(const S) rc = ri;
2731 assert(rc.ptr is null);
2732 ri = S(new int);
2733 rc = ri;
2734 assert(rc.ptr !is null);
2736 // test rebindable, opAssign
2737 rc.destroy;
2738 assert(rc.ptr is null);
2739 rc = rebindable(cs3);
2740 rc = rebindable(si);
2741 assert(rc.ptr !is null);
2743 ri.destroy;
2744 assert(ri.ptr is null);
2745 ri = rebindable(si);
2746 assert(ri.ptr !is null);
2749 // Test disabled default ctor
2750 @safe unittest
2752 static struct ND
2754 int i;
2755 @disable this();
2756 this(int i) inout {this.i = i;}
2758 static assert(!__traits(compiles, Rebindable!ND()));
2760 Rebindable!(const ND) rb = const ND(1);
2761 assert(rb.i == 1);
2762 rb = immutable ND(2);
2763 assert(rb.i == 2);
2764 rb = rebindable(const ND(3));
2765 assert(rb.i == 3);
2766 static assert(!__traits(compiles, rb.i++));
2769 // Test copying
2770 @safe unittest
2772 int del;
2773 int post;
2774 struct S
2776 int* ptr;
2777 int level;
2778 this(this)
2780 post++;
2781 level++;
2783 ~this()
2785 del++;
2789 // test ref count
2791 Rebindable!S rc = S(new int);
2793 assert(post == del - 1);
2796 @safe unittest
2798 int del;
2799 int post;
2800 struct S
2802 immutable int x;
2803 int level;
2804 this(this)
2806 post++;
2807 level++;
2809 ~this()
2811 del++;
2815 // test ref count
2817 Rebindable!S rc = S(0);
2819 assert(post == del - 1);
2823 Convenience function for creating a `Rebindable` using automatic type
2824 inference.
2826 Params:
2827 obj = A reference to a value to initialize the `Rebindable` with.
2829 Returns:
2830 A newly constructed `Rebindable` initialized with the given reference.
2832 Rebindable!T rebindable(T)(T obj)
2833 if (is(T == class) || is(T == interface) || isDynamicArray!T || isAssociativeArray!T)
2835 typeof(return) ret;
2836 ret = obj;
2837 return ret;
2841 @system unittest
2843 class C
2845 int payload;
2846 this(int p) { payload = p; }
2848 const c = new C(1);
2850 auto c2 = c.rebindable;
2851 assert(c2.payload == 1);
2852 // passing Rebindable to rebindable
2853 c2 = c2.rebindable;
2855 c2 = new C(2);
2856 assert(c2.payload == 2);
2858 const c3 = c2.get;
2859 assert(c3.payload == 2);
2862 /// ditto
2863 Rebindable!T rebindable(T)(T value)
2864 if (!is(T == class) && !is(T == interface) && !isDynamicArray!T && !isAssociativeArray!T
2865 && !is(T : Rebindable!U, U))
2867 return Rebindable!T(value);
2871 @safe unittest
2873 immutable struct S
2875 int[] array;
2877 auto s1 = [3].idup.rebindable;
2878 s1 = [4].idup.rebindable;
2879 assert(s1 == [4]);
2883 This function simply returns the `Rebindable` object passed in. It's useful
2884 in generic programming cases when a given object may be either a regular
2885 `class` or a `Rebindable`.
2887 Params:
2888 obj = An instance of Rebindable!T.
2890 Returns:
2891 `obj` without any modification.
2893 Rebindable!T rebindable(T)(Rebindable!T obj)
2895 return obj;
2898 // TODO: remove me once the rebindable overloads have been joined
2900 @system unittest
2902 class C
2904 int payload;
2905 this(int p) { payload = p; }
2907 const c = new C(1);
2909 auto c2 = c.rebindable;
2910 assert(c2.payload == 1);
2911 // passing Rebindable to rebindable
2912 c2 = c2.rebindable;
2913 assert(c2.payload == 1);
2916 @system unittest
2918 interface CI { int foo() const; }
2919 class C : CI {
2920 int foo() const { return 42; }
2921 @property int bar() const { return 23; }
2923 Rebindable!(C) obj0;
2924 static assert(is(typeof(obj0) == C));
2926 Rebindable!(const(C)) obj1;
2927 static assert(is(typeof(obj1.get) == const(C)), typeof(obj1.get).stringof);
2928 static assert(is(typeof(obj1.stripped) == C));
2929 obj1 = new C;
2930 assert(obj1.get !is null);
2931 obj1 = new const(C);
2932 assert(obj1.get !is null);
2934 Rebindable!(immutable(C)) obj2;
2935 static assert(is(typeof(obj2.get) == immutable(C)));
2936 static assert(is(typeof(obj2.stripped) == C));
2937 obj2 = new immutable(C);
2938 assert(obj1.get !is null);
2940 // test opDot
2941 assert(obj2.foo() == 42);
2942 assert(obj2.bar == 23);
2944 interface I { final int foo() const { return 42; } }
2945 Rebindable!(I) obj3;
2946 static assert(is(typeof(obj3) == I));
2948 Rebindable!(const I) obj4;
2949 static assert(is(typeof(obj4.get) == const I));
2950 static assert(is(typeof(obj4.stripped) == I));
2951 static assert(is(typeof(obj4.foo()) == int));
2952 obj4 = new class I {};
2954 Rebindable!(immutable C) obj5i;
2955 Rebindable!(const C) obj5c;
2956 obj5c = obj5c;
2957 obj5c = obj5i;
2958 obj5i = obj5i;
2959 static assert(!__traits(compiles, obj5i = obj5c));
2961 // Test the convenience functions.
2962 auto obj5convenience = rebindable(obj5i);
2963 assert(obj5convenience is obj5i);
2965 auto obj6 = rebindable(new immutable(C));
2966 static assert(is(typeof(obj6) == Rebindable!(immutable C)));
2967 assert(obj6.foo() == 42);
2969 auto obj7 = rebindable(new C);
2970 CI interface1 = obj7;
2971 auto interfaceRebind1 = rebindable(interface1);
2972 assert(interfaceRebind1.foo() == 42);
2974 const interface2 = interface1;
2975 auto interfaceRebind2 = rebindable(interface2);
2976 assert(interfaceRebind2.foo() == 42);
2978 auto arr = [1,2,3,4,5];
2979 const arrConst = arr;
2980 assert(rebindable(arr) == arr);
2981 assert(rebindable(arrConst) == arr);
2983 // https://issues.dlang.org/show_bug.cgi?id=7654
2984 immutable(char[]) s7654;
2985 Rebindable!(typeof(s7654)) r7654 = s7654;
2987 static foreach (T; AliasSeq!(char, wchar, char, int))
2989 static assert(is(Rebindable!(immutable(T[])) == immutable(T)[]));
2990 static assert(is(Rebindable!(const(T[])) == const(T)[]));
2991 static assert(is(Rebindable!(T[]) == T[]));
2994 // Pull request 3341
2995 Rebindable!(immutable int[int]) pr3341 = [123:345];
2996 assert(pr3341[123] == 345);
2997 immutable int[int] pr3341_aa = [321:543];
2998 pr3341 = pr3341_aa;
2999 assert(pr3341[321] == 543);
3000 assert(rebindable(pr3341_aa)[321] == 543);
3003 package(std) struct Rebindable2(T)
3005 private:
3006 static if (isAssignable!(typeof(cast() T.init)))
3008 enum useQualifierCast = true;
3010 typeof(cast() T.init) data;
3012 else
3014 enum useQualifierCast = false;
3016 align(T.alignof)
3017 static struct Payload
3019 static if (hasIndirections!T)
3021 void[T.sizeof] data;
3023 else
3025 ubyte[T.sizeof] data;
3029 Payload data;
3032 public:
3034 static if (!__traits(compiles, { T value; }))
3036 @disable this();
3040 * Constructs a `Rebindable2` from a given value.
3042 this(T value) @trusted
3044 static if (useQualifierCast)
3046 this.data = cast() value;
3048 else
3050 set(value);
3055 * Overwrites the currently stored value with `value`.
3057 void opAssign(this This)(T value) @trusted
3059 clear;
3060 set(value);
3064 * Returns the value currently stored in the `Rebindable2`.
3066 T get(this This)() @property @trusted
3068 static if (useQualifierCast)
3070 return cast(T) this.data;
3072 else
3074 return *cast(T*) &this.data;
3078 /// Ditto
3079 inout(T) get() inout @property @trusted
3081 static if (useQualifierCast)
3083 return cast(inout(T)) this.data;
3085 else
3087 return *cast(inout(T)*) &this.data;
3091 static if (!useQualifierCast)
3093 ~this() @trusted
3095 clear;
3099 private:
3101 void set(this This)(T value)
3103 static if (useQualifierCast)
3105 this.data = cast() value;
3107 else
3109 // As we're escaping a copy of `value`, deliberately leak a copy:
3110 static union DontCallDestructor
3112 T value;
3114 DontCallDestructor copy = DontCallDestructor(value);
3115 this.data = *cast(Payload*) &copy;
3119 void clear(this This)()
3121 // work around reinterpreting cast being impossible in CTFE
3122 if (__ctfe)
3124 return;
3127 // call possible struct destructors
3128 .destroy!(No.initialize)(*cast(T*) &this.data);
3132 package(std) Rebindable2!T rebindable2(T)(T value)
3134 return Rebindable2!T(value);
3138 Similar to `Rebindable!(T)` but strips all qualifiers from the reference as
3139 opposed to just constness / immutability. Primary intended use case is with
3140 shared (having thread-local reference to shared class data)
3142 Params:
3143 T = A class or interface type.
3145 template UnqualRef(T)
3146 if (is(T == class) || is(T == interface))
3148 static if (is(T == immutable U, U)
3149 || is(T == const shared U, U)
3150 || is(T == const U, U)
3151 || is(T == shared U, U))
3153 struct UnqualRef
3155 mixin RebindableCommon!(T, U, UnqualRef);
3158 else
3160 alias UnqualRef = T;
3165 @system unittest
3167 class Data {}
3169 static shared(Data) a;
3170 static UnqualRef!(shared Data) b;
3172 import core.thread;
3174 auto thread = new core.thread.Thread({
3175 a = new shared Data();
3176 b = new shared Data();
3179 thread.start();
3180 thread.join();
3182 assert(a !is null);
3183 assert(b is null);
3186 @safe unittest
3188 class C { }
3189 alias T = UnqualRef!(const shared C);
3190 static assert(is(typeof(T.stripped) == C));
3196 Order the provided members to minimize size while preserving alignment.
3197 Alignment is not always optimal for 80-bit reals, nor for structs declared
3198 as align(1).
3200 Params:
3201 E = A list of the types to be aligned, representing fields
3202 of an aggregate such as a `struct` or `class`.
3204 names = The names of the fields that are to be aligned.
3206 Returns:
3207 A string to be mixed in to an aggregate, such as a `struct` or `class`.
3209 string alignForSize(E...)(const char[][] names...)
3211 // Sort all of the members by .alignof.
3212 // BUG: Alignment is not always optimal for align(1) structs
3213 // or 80-bit reals or 64-bit primitives on x86.
3214 // TRICK: Use the fact that .alignof is always a power of 2,
3215 // and maximum 16 on extant systems. Thus, we can perform
3216 // a very limited radix sort.
3217 // Contains the members with .alignof = 64,32,16,8,4,2,1
3219 assert(E.length == names.length,
3220 "alignForSize: There should be as many member names as the types");
3222 string[7] declaration = ["", "", "", "", "", "", ""];
3224 foreach (i, T; E)
3226 auto a = T.alignof;
3227 auto k = a >= 64? 0 : a >= 32? 1 : a >= 16? 2 : a >= 8? 3 : a >= 4? 4 : a >= 2? 5 : 6;
3228 declaration[k] ~= T.stringof ~ " " ~ names[i] ~ ";\n";
3231 auto s = "";
3232 foreach (decl; declaration)
3233 s ~= decl;
3234 return s;
3238 @safe unittest
3240 struct Banner {
3241 mixin(alignForSize!(byte[6], double)(["name", "height"]));
3245 @safe unittest
3247 enum x = alignForSize!(int[], char[3], short, double[5])("x", "y","z", "w");
3248 struct Foo { int x; }
3249 enum y = alignForSize!(ubyte, Foo, double)("x", "y", "z");
3251 enum passNormalX = x == "double[5] w;\nint[] x;\nshort z;\nchar[3] y;\n";
3252 enum passNormalY = y == "double z;\nFoo y;\nubyte x;\n";
3254 enum passAbnormalX = x == "int[] x;\ndouble[5] w;\nshort z;\nchar[3] y;\n";
3255 enum passAbnormalY = y == "Foo y;\ndouble z;\nubyte x;\n";
3256 // ^ blame https://issues.dlang.org/show_bug.cgi?id=231
3258 static assert(passNormalX || passAbnormalX && double.alignof <= (int[]).alignof);
3259 static assert(passNormalY || passAbnormalY && double.alignof <= int.alignof);
3262 // https://issues.dlang.org/show_bug.cgi?id=12914
3263 @safe unittest
3265 immutable string[] fieldNames = ["x", "y"];
3266 struct S
3268 mixin(alignForSize!(byte, int)(fieldNames));
3273 Defines a value paired with a distinctive "null" state that denotes
3274 the absence of a value. If default constructed, a $(D
3275 Nullable!T) object starts in the null state. Assigning it renders it
3276 non-null. Calling `nullify` can nullify it again.
3278 Practically `Nullable!T` stores a `T` and a `bool`.
3280 See also:
3281 $(LREF apply), an alternative way to use the payload.
3283 struct Nullable(T)
3285 private union DontCallDestructorT
3287 import std.traits : hasIndirections;
3288 static if (hasIndirections!T)
3289 T payload;
3290 else
3291 T payload = void;
3294 private DontCallDestructorT _value = DontCallDestructorT.init;
3296 private bool _isNull = true;
3299 * Constructor initializing `this` with `value`.
3301 * Params:
3302 * value = The value to initialize this `Nullable` with.
3304 static if (isCopyable!T)
3305 this(inout T value) inout
3307 _value.payload = value;
3308 _isNull = false;
3310 else
3311 this(T value) inout
3313 import std.algorithm.mutation : move;
3314 _value.payload = move(value);
3315 _isNull = false;
3318 static if (hasElaborateDestructor!T)
3320 ~this()
3322 if (!_isNull)
3324 import std.traits : Unqual;
3325 auto ptr = () @trusted { return cast(Unqual!T*) &_value.payload; }();
3326 destroy!false(*ptr);
3331 static if (!isCopyable!T)
3332 @disable this(this);
3333 else
3334 static if (__traits(hasPostblit, T))
3336 this(this)
3338 if (!_isNull)
3339 _value.payload.__xpostblit();
3342 else static if (__traits(hasCopyConstructor, T))
3344 this(ref return scope inout Nullable!T rhs) inout
3346 _isNull = rhs._isNull;
3347 if (!_isNull)
3348 _value.payload = rhs._value.payload;
3349 else
3350 _value = DontCallDestructorT.init;
3355 * If they are both null, then they are equal. If one is null and the other
3356 * is not, then they are not equal. If they are both non-null, then they are
3357 * equal if their values are equal.
3359 bool opEquals(this This, Rhs)(auto ref Rhs rhs)
3360 if (!is(CommonType!(This, Rhs) == void))
3362 static if (is(This == Rhs))
3364 if (_isNull)
3365 return rhs._isNull;
3366 if (rhs._isNull)
3367 return false;
3368 return _value.payload == rhs._value.payload;
3370 else
3372 alias Common = CommonType!(This, Rhs);
3373 return cast(Common) this == cast(Common) rhs;
3377 /// Ditto
3378 bool opEquals(this This, Rhs)(auto ref Rhs rhs)
3379 if (is(CommonType!(This, Rhs) == void) && is(typeof(this.get == rhs)))
3381 return _isNull ? false : rhs == _value.payload;
3385 @safe unittest
3387 Nullable!int empty;
3388 Nullable!int a = 42;
3389 Nullable!int b = 42;
3390 Nullable!int c = 27;
3392 assert(empty == empty);
3393 assert(empty == Nullable!int.init);
3394 assert(empty != a);
3395 assert(empty != b);
3396 assert(empty != c);
3398 assert(a == b);
3399 assert(a != c);
3401 assert(empty != 42);
3402 assert(a == 42);
3403 assert(c != 42);
3406 @safe unittest
3408 // Test constness
3409 immutable Nullable!int a = 42;
3410 Nullable!int b = 42;
3411 immutable Nullable!int c = 29;
3412 Nullable!int d = 29;
3413 immutable e = 42;
3414 int f = 29;
3415 assert(a == a);
3416 assert(a == b);
3417 assert(a != c);
3418 assert(a != d);
3419 assert(a == e);
3420 assert(a != f);
3422 // Test rvalue
3423 assert(a == const Nullable!int(42));
3424 assert(a != Nullable!int(29));
3427 // https://issues.dlang.org/show_bug.cgi?id=17482
3428 @system unittest
3430 import std.variant : Variant;
3431 Nullable!Variant a = Variant(12);
3432 assert(a == 12);
3433 Nullable!Variant e;
3434 assert(e != 12);
3437 size_t toHash() const @safe nothrow
3439 static if (__traits(compiles, .hashOf(_value.payload)))
3440 return _isNull ? 0 : .hashOf(_value.payload);
3441 else
3442 // Workaround for when .hashOf is not both @safe and nothrow.
3443 return _isNull ? 0 : typeid(T).getHash(&_value.payload);
3447 * Gives the string `"Nullable.null"` if `isNull` is `true`. Otherwise, the
3448 * result is equivalent to calling $(REF formattedWrite, std,format) on the
3449 * underlying value.
3451 * Params:
3452 * writer = A `char` accepting
3453 * $(REF_ALTTEXT output range, isOutputRange, std, range, primitives)
3454 * fmt = A $(REF FormatSpec, std,format) which is used to represent
3455 * the value if this Nullable is not null
3456 * Returns:
3457 * A `string` if `writer` and `fmt` are not set; `void` otherwise.
3459 string toString()
3461 import std.array : appender;
3462 auto app = appender!string();
3463 auto spec = singleSpec("%s");
3464 toString(app, spec);
3465 return app.data;
3468 /// ditto
3469 string toString() const
3471 import std.array : appender;
3472 auto app = appender!string();
3473 auto spec = singleSpec("%s");
3474 toString(app, spec);
3475 return app.data;
3478 /// ditto
3479 void toString(W)(ref W writer, scope const ref FormatSpec!char fmt)
3480 if (isOutputRange!(W, char))
3482 import std.range.primitives : put;
3483 if (isNull)
3484 put(writer, "Nullable.null");
3485 else
3486 formatValue(writer, _value.payload, fmt);
3489 /// ditto
3490 void toString(W)(ref W writer, scope const ref FormatSpec!char fmt) const
3491 if (isOutputRange!(W, char))
3493 import std.range.primitives : put;
3494 if (isNull)
3495 put(writer, "Nullable.null");
3496 else
3497 formatValue(writer, _value.payload, fmt);
3501 * Check if `this` is in the null state.
3503 * Returns:
3504 * true $(B iff) `this` is in the null state, otherwise false.
3506 @property bool isNull() const @safe pure nothrow
3508 return _isNull;
3512 @safe unittest
3514 Nullable!int ni;
3515 assert(ni.isNull);
3517 ni = 0;
3518 assert(!ni.isNull);
3521 // https://issues.dlang.org/show_bug.cgi?id=14940
3522 @safe unittest
3524 import std.array : appender;
3525 import std.format.write : formattedWrite;
3527 auto app = appender!string();
3528 Nullable!int a = 1;
3529 formattedWrite(app, "%s", a);
3530 assert(app.data == "1");
3533 // https://issues.dlang.org/show_bug.cgi?id=19799
3534 @safe unittest
3536 import std.format : format;
3538 const Nullable!string a = const(Nullable!string)();
3540 format!"%s"(a);
3544 * Forces `this` to the null state.
3546 void nullify()()
3548 static if (is(T == class) || is(T == interface))
3549 _value.payload = null;
3550 else
3551 .destroy(_value.payload);
3552 _isNull = true;
3556 @safe unittest
3558 Nullable!int ni = 0;
3559 assert(!ni.isNull);
3561 ni.nullify();
3562 assert(ni.isNull);
3566 * Assigns `value` to the internally-held state. If the assignment
3567 * succeeds, `this` becomes non-null.
3569 * Params:
3570 * value = A value of type `T` to assign to this `Nullable`.
3572 ref Nullable opAssign()(T value) return
3574 import std.algorithm.mutation : moveEmplace, move;
3576 if (_isNull)
3578 // trusted since payload is known to be uninitialized.
3579 () @trusted { moveEmplace(value, _value.payload); }();
3581 else
3583 move(value, _value.payload);
3585 _isNull = false;
3586 return this;
3590 * If this `Nullable` wraps a type that already has a null value
3591 * (such as a pointer), then assigning the null value to this
3592 * `Nullable` is no different than assigning any other value of
3593 * type `T`, and the resulting code will look very strange. It
3594 * is strongly recommended that this be avoided by instead using
3595 * the version of `Nullable` that takes an additional `nullValue`
3596 * template argument.
3598 @safe unittest
3600 //Passes
3601 Nullable!(int*) npi;
3602 assert(npi.isNull);
3604 //Passes?!
3605 npi = null;
3606 assert(!npi.isNull);
3610 * Gets the value if not null. If `this` is in the null state, and the optional
3611 * parameter `fallback` was provided, it will be returned. Without `fallback`,
3612 * calling `get` with a null state is invalid.
3614 * When the fallback type is different from the Nullable type, `get(T)` returns
3615 * the common type.
3617 * Params:
3618 * fallback = the value to return in case the `Nullable` is null.
3620 * Returns:
3621 * The value held internally by this `Nullable`.
3623 @property ref inout(T) get() inout @safe pure nothrow
3625 enum message = "Called `get' on null Nullable!" ~ T.stringof ~ ".";
3626 assert(!isNull, message);
3627 return _value.payload;
3630 /// ditto
3631 @property inout(T) get()(inout(T) fallback) inout
3633 return isNull ? fallback : _value.payload;
3636 /// ditto
3637 @property auto get(U)(inout(U) fallback) inout
3639 return isNull ? fallback : _value.payload;
3642 /// $(MREF_ALTTEXT Range interface, std, range, primitives) functions.
3643 alias empty = isNull;
3645 /// ditto
3646 alias popFront = nullify;
3648 /// ditto
3649 alias popBack = nullify;
3651 /// ditto
3652 @property ref inout(T) front() inout @safe pure nothrow
3654 return get();
3657 /// ditto
3658 alias back = front;
3660 /// ditto
3661 static if (isCopyable!T)
3662 @property inout(typeof(this)) save() inout
3664 return this;
3667 /// ditto
3668 static if (isCopyable!T)
3669 inout(typeof(this)) opIndex(size_t[2] dim) inout
3670 in (dim[0] <= length && dim[1] <= length && dim[1] >= dim[0])
3672 return (dim[0] == 0 && dim[1] == 1) ? this : this.init;
3674 /// ditto
3675 size_t[2] opSlice(size_t dim : 0)(size_t from, size_t to) const
3677 return [from, to];
3680 /// ditto
3681 @property size_t length() const @safe pure nothrow
3683 return !empty;
3686 /// ditto
3687 alias opDollar(size_t dim : 0) = length;
3689 /// ditto
3690 ref inout(T) opIndex(size_t index) inout @safe pure nothrow
3691 in (index < length)
3693 return get();
3697 * Converts `Nullable` to a range. Works even when the contained type is `immutable`.
3699 auto opSlice(this This)()
3701 static struct NullableRange
3703 private This value;
3705 // starts out true if value is null
3706 private bool empty_;
3708 @property bool empty() const @safe pure nothrow
3710 return empty_;
3713 void popFront() @safe pure nothrow
3715 empty_ = true;
3718 alias popBack = popFront;
3720 @property ref inout(typeof(value.get())) front() inout @safe pure nothrow
3722 return value.get();
3725 alias back = front;
3727 @property inout(typeof(this)) save() inout
3729 return this;
3732 size_t[2] opSlice(size_t dim : 0)(size_t from, size_t to) const
3734 return [from, to];
3737 @property size_t length() const @safe pure nothrow
3739 return !empty;
3742 alias opDollar(size_t dim : 0) = length;
3744 ref inout(typeof(value.get())) opIndex(size_t index) inout @safe pure nothrow
3745 in (index < length)
3747 return value.get();
3750 inout(typeof(this)) opIndex(size_t[2] dim) inout
3751 in (dim[0] <= length && dim[1] <= length && dim[1] >= dim[0])
3753 return (dim[0] == 0 && dim[1] == 1) ? this : this.init;
3756 auto opIndex() inout
3758 return this;
3761 return NullableRange(this, isNull);
3765 /// ditto
3766 auto nullable(T)(T t)
3768 return Nullable!T(t);
3772 @safe unittest
3774 struct CustomerRecord
3776 string name;
3777 string address;
3778 int customerNum;
3781 Nullable!CustomerRecord getByName(string name)
3783 //A bunch of hairy stuff
3785 return Nullable!CustomerRecord.init;
3788 auto queryResult = getByName("Doe, John");
3789 if (!queryResult.isNull)
3791 //Process Mr. Doe's customer record
3792 auto address = queryResult.get.address;
3793 auto customerNum = queryResult.get.customerNum;
3795 //Do some things with this customer's info
3797 else
3799 //Add the customer to the database
3804 @system unittest
3806 import std.exception : assertThrown;
3808 auto a = 42.nullable;
3809 assert(!a.isNull);
3810 assert(a.get == 42);
3812 a.nullify();
3813 assert(a.isNull);
3814 assertThrown!Throwable(a.get);
3817 @safe unittest
3819 import std.algorithm.iteration : each, joiner;
3820 Nullable!int a = 42;
3821 Nullable!int b;
3822 // Add each value to an array
3823 int[] arr;
3824 a.each!((n) => arr ~= n);
3825 assert(arr == [42]);
3826 b.each!((n) => arr ~= n);
3827 assert(arr == [42]);
3828 // Take first value from an array of Nullables
3829 Nullable!int[] c = new Nullable!int[](10);
3830 c[7] = Nullable!int(42);
3831 assert(c.joiner.front == 42);
3833 @safe unittest
3835 auto k = Nullable!int(74);
3836 assert(k == 74);
3837 k.nullify();
3838 assert(k.isNull);
3840 @safe unittest
3842 static int f(scope const Nullable!int x) {
3843 return x.isNull ? 42 : x.get;
3845 Nullable!int a;
3846 assert(f(a) == 42);
3847 a = 8;
3848 assert(f(a) == 8);
3849 a.nullify();
3850 assert(f(a) == 42);
3852 @system unittest
3854 import std.exception : assertThrown;
3856 static struct S { int x; }
3857 Nullable!S s;
3858 assert(s.isNull);
3859 s = S(6);
3860 assert(s == S(6));
3861 assert(s != S(0));
3862 assert(s.get != S(0));
3863 s.get.x = 9190;
3864 assert(s.get.x == 9190);
3865 s.nullify();
3866 assertThrown!Throwable(s.get.x = 9441);
3868 @safe unittest
3870 // Ensure Nullable can be used in pure/nothrow/@safe environment.
3871 function() @safe pure nothrow
3873 Nullable!int n;
3874 assert(n.isNull);
3875 n = 4;
3876 assert(!n.isNull);
3877 assert(n == 4);
3878 n.nullify();
3879 assert(n.isNull);
3880 }();
3882 @system unittest
3884 // Ensure Nullable can be used when the value is not pure/nothrow/@safe
3885 static struct S
3887 int x;
3888 this(this) @system {}
3891 Nullable!S s;
3892 assert(s.isNull);
3893 s = S(5);
3894 assert(!s.isNull);
3895 assert(s.get.x == 5);
3896 s.nullify();
3897 assert(s.isNull);
3900 // https://issues.dlang.org/show_bug.cgi?id=9404
3901 @safe unittest
3903 alias N = Nullable!int;
3905 void foo(N a)
3907 N b;
3908 b = a; // `N b = a;` works fine
3910 N n;
3911 foo(n);
3913 @safe unittest
3915 //Check nullable immutable is constructable
3917 auto a1 = Nullable!(immutable int)();
3918 auto a2 = Nullable!(immutable int)(1);
3919 auto i = a2.get;
3921 //Check immutable nullable is constructable
3923 auto a1 = immutable (Nullable!int)();
3924 auto a2 = immutable (Nullable!int)(1);
3925 auto i = a2.get;
3928 @safe unittest
3930 alias NInt = Nullable!int;
3932 //Construct tests
3934 //from other Nullable null
3935 NInt a1;
3936 NInt b1 = a1;
3937 assert(b1.isNull);
3939 //from other Nullable non-null
3940 NInt a2 = NInt(1);
3941 NInt b2 = a2;
3942 assert(b2 == 1);
3944 //Construct from similar nullable
3945 auto a3 = immutable(NInt)();
3946 NInt b3 = a3;
3947 assert(b3.isNull);
3950 //Assign tests
3952 //from other Nullable null
3953 NInt a1;
3954 NInt b1;
3955 b1 = a1;
3956 assert(b1.isNull);
3958 //from other Nullable non-null
3959 NInt a2 = NInt(1);
3960 NInt b2;
3961 b2 = a2;
3962 assert(b2 == 1);
3964 //Construct from similar nullable
3965 auto a3 = immutable(NInt)();
3966 NInt b3 = a3;
3967 b3 = a3;
3968 assert(b3.isNull);
3971 @safe unittest
3973 //Check nullable is nicelly embedable in a struct
3974 static struct S1
3976 Nullable!int ni;
3978 static struct S2 //inspired from 9404
3980 Nullable!int ni;
3981 this(ref S2 other)
3983 ni = other.ni;
3985 void opAssign(ref S2 other)
3987 ni = other.ni;
3990 static foreach (S; AliasSeq!(S1, S2))
3992 S a;
3993 S b = a;
3994 S c;
3995 c = a;
3999 // https://issues.dlang.org/show_bug.cgi?id=10268
4000 @system unittest
4002 import std.json;
4003 JSONValue value = null;
4004 auto na = Nullable!JSONValue(value);
4006 struct S1 { int val; }
4007 struct S2 { int* val; }
4008 struct S3 { immutable int* val; }
4011 auto sm = S1(1);
4012 immutable si = immutable S1(1);
4013 auto x1 = Nullable!S1(sm);
4014 auto x2 = immutable Nullable!S1(sm);
4015 auto x3 = Nullable!S1(si);
4016 auto x4 = immutable Nullable!S1(si);
4017 assert(x1.get.val == 1);
4018 assert(x2.get.val == 1);
4019 assert(x3.get.val == 1);
4020 assert(x4.get.val == 1);
4023 auto nm = 10;
4024 immutable ni = 10;
4027 auto sm = S2(&nm);
4028 immutable si = immutable S2(&ni);
4029 auto x1 = Nullable!S2(sm);
4030 static assert(!__traits(compiles, { auto x2 = immutable Nullable!S2(sm); }));
4031 static assert(!__traits(compiles, { auto x3 = Nullable!S2(si); }));
4032 auto x4 = immutable Nullable!S2(si);
4033 assert(*x1.get.val == 10);
4034 assert(*x4.get.val == 10);
4038 auto sm = S3(&ni);
4039 immutable si = immutable S3(&ni);
4040 auto x1 = Nullable!S3(sm);
4041 auto x2 = immutable Nullable!S3(sm);
4042 auto x3 = Nullable!S3(si);
4043 auto x4 = immutable Nullable!S3(si);
4044 assert(*x1.get.val == 10);
4045 assert(*x2.get.val == 10);
4046 assert(*x3.get.val == 10);
4047 assert(*x4.get.val == 10);
4051 // https://issues.dlang.org/show_bug.cgi?id=10357
4052 @safe unittest
4054 import std.datetime;
4055 Nullable!SysTime time = SysTime(0);
4058 // https://issues.dlang.org/show_bug.cgi?id=10915
4059 @system unittest
4061 import std.conv : to;
4062 import std.array;
4064 Appender!string buffer;
4066 Nullable!int ni;
4067 assert(ni.to!string() == "Nullable.null");
4068 assert((cast(const) ni).to!string() == "Nullable.null");
4070 struct Test { string s; }
4071 alias NullableTest = Nullable!Test;
4073 NullableTest nt = Test("test");
4074 // test output range version
4075 assert(nt.to!string() == `Test("test")`);
4076 // test appender version
4077 assert(nt.toString() == `Test("test")`);
4078 // test const version
4079 assert((cast(const) nt).toString() == `const(Test)("test")`);
4081 NullableTest ntn = Test("null");
4082 assert(ntn.to!string() == `Test("null")`);
4084 class TestToString
4086 double d;
4088 this (double d)
4090 this.d = d;
4093 override string toString()
4095 return d.to!string();
4098 Nullable!TestToString ntts = new TestToString(2.5);
4099 assert(ntts.to!string() == "2.5");
4102 // https://issues.dlang.org/show_bug.cgi?id=14477
4103 @safe unittest
4105 static struct DisabledDefaultConstructor
4107 @disable this();
4108 this(int i) { }
4110 Nullable!DisabledDefaultConstructor var;
4111 var = DisabledDefaultConstructor(5);
4112 var.nullify;
4115 // https://issues.dlang.org/show_bug.cgi?id=17440
4116 @system unittest
4118 static interface I { }
4120 static class C : I
4122 int canary;
4123 ~this()
4125 canary = 0x5050DEAD;
4128 auto c = new C;
4129 c.canary = 0xA71FE;
4130 auto nc = nullable(c);
4131 nc.nullify;
4132 assert(c.canary == 0xA71FE);
4134 I i = c;
4135 auto ni = nullable(i);
4136 ni.nullify;
4137 assert(c.canary == 0xA71FE);
4140 // https://issues.dlang.org/show_bug.cgi?id=19037
4141 @safe unittest
4143 import std.datetime : SysTime;
4145 struct Test
4147 SysTime _st;
4149 static bool destroyed;
4151 @disable this();
4152 this(int _dummy) {}
4153 ~this() @safe { destroyed = true; }
4155 // mustn't call opAssign on Test.init in Nullable!Test, because the invariant
4156 // will be called before opAssign on the Test.init that is in Nullable
4157 // and Test.init violates its invariant.
4158 void opAssign(Test rhs) @safe { assert(false); }
4162 Nullable!Test nt;
4164 nt = Test(1);
4166 // destroy value
4167 Test.destroyed = false;
4169 nt.nullify;
4171 assert(Test.destroyed);
4173 Test.destroyed = false;
4175 // don't run destructor on T.init in Nullable on scope exit!
4176 assert(!Test.destroyed);
4178 // check that the contained type's destructor is called on assignment
4179 @system unittest
4181 struct S
4183 // can't be static, since we need a specific value's pointer
4184 bool* destroyedRef;
4186 ~this()
4188 if (this.destroyedRef)
4190 *this.destroyedRef = true;
4195 Nullable!S ns;
4197 bool destroyed;
4199 ns = S(&destroyed);
4201 // reset from rvalue destruction in Nullable's opAssign
4202 destroyed = false;
4204 // overwrite Nullable
4205 ns = S(null);
4207 // the original S should be destroyed.
4208 assert(destroyed == true);
4210 // check that the contained type's destructor is still called when required
4211 @system unittest
4213 bool destructorCalled = false;
4215 struct S
4217 bool* destroyed;
4218 ~this() { *this.destroyed = true; }
4222 Nullable!S ns;
4224 assert(!destructorCalled);
4226 Nullable!S ns = Nullable!S(S(&destructorCalled));
4228 destructorCalled = false; // reset after S was destroyed in the NS constructor
4230 assert(destructorCalled);
4233 // check that toHash on Nullable is forwarded to the contained type
4234 @system unittest
4236 struct S
4238 size_t toHash() const @safe pure nothrow { return 5; }
4241 Nullable!S s1 = S();
4242 Nullable!S s2 = Nullable!S();
4244 assert(typeid(Nullable!S).getHash(&s1) == 5);
4245 assert(typeid(Nullable!S).getHash(&s2) == 0);
4248 // https://issues.dlang.org/show_bug.cgi?id=21704
4249 @safe unittest
4251 import std.array : staticArray;
4253 bool destroyed;
4255 struct Probe
4257 ~this() { destroyed = true; }
4261 Nullable!(Probe[1]) test = [Probe()].staticArray;
4262 destroyed = false;
4264 assert(destroyed);
4267 // https://issues.dlang.org/show_bug.cgi?id=21705
4268 @safe unittest
4270 static struct S
4272 int n;
4273 bool opEquals(S rhs) { return n == rhs.n; }
4276 Nullable!S test1 = S(1), test2 = S(1);
4277 S s = S(1);
4279 assert(test1 == s);
4280 assert(test1 == test2);
4283 // https://issues.dlang.org/show_bug.cgi?id=22101
4284 @safe unittest
4286 static int impure;
4288 struct S
4290 ~this() { impure++; }
4293 Nullable!S s;
4294 s.get(S());
4297 // https://issues.dlang.org/show_bug.cgi?id=22100
4298 @safe unittest
4300 Nullable!int a, b, c;
4301 a = b = c = 5;
4302 a = b = c = nullable(5);
4305 // https://issues.dlang.org/show_bug.cgi?id=18374
4306 @safe pure nothrow unittest
4308 import std.algorithm.comparison : equal;
4309 import std.range : only, takeNone;
4310 import std.range.primitives : hasAssignableElements, hasLength,
4311 hasLvalueElements, hasSlicing, hasSwappableElements,
4312 isRandomAccessRange;
4313 Nullable!int a = 42;
4314 assert(!a.empty);
4315 assert(a.front == 42);
4316 assert(a.back == 42);
4317 assert(a[0] == 42);
4318 assert(a.equal(only(42)));
4319 assert(a[0 .. $].equal(only(42)));
4320 a[0] = 43;
4321 assert(a.equal(only(43)));
4322 --a[0];
4323 assert(a.equal(only(42)));
4324 Nullable!int b;
4325 assert(b.empty);
4326 assert(b.equal(takeNone(b)));
4327 Nullable!int c = a.save();
4328 assert(!c.empty);
4329 c.popFront();
4330 assert(!a.empty);
4331 assert(c.empty);
4333 assert(isRandomAccessRange!(Nullable!int));
4334 assert(hasLength!(Nullable!int));
4335 assert(hasSlicing!(Nullable!int));
4336 assert(hasAssignableElements!(Nullable!int));
4337 assert(hasSwappableElements!(Nullable!int));
4338 assert(hasLvalueElements!(Nullable!int));
4341 // https://issues.dlang.org/show_bug.cgi?id=23640
4342 @safe pure nothrow unittest
4344 import std.algorithm.comparison : equal;
4345 import std.range : only;
4346 import std.range.primitives : hasLength, hasSlicing,
4347 isRandomAccessRange;
4348 static immutable struct S { int[] array; }
4349 auto value = S([42]);
4350 alias ImmutableNullable = immutable Nullable!S;
4351 auto a = ImmutableNullable(value)[];
4352 alias Range = typeof(a);
4353 assert(isRandomAccessRange!Range);
4354 assert(hasLength!Range);
4355 assert(hasSlicing!Range);
4356 assert(!a.empty);
4357 assert(a.front == value);
4358 assert(a.back == value);
4359 assert(a[0] == value);
4360 assert(a.equal(only(value)));
4361 assert(a[0 .. $].equal(only(value)));
4362 Range b = a.save();
4363 assert(!b.empty);
4364 b.popFront();
4365 assert(!a.empty);
4366 assert(b.empty);
4369 // https://issues.dlang.org/show_bug.cgi?id=24403
4370 @safe unittest
4372 static bool destroyed;
4373 static struct S { ~this() { destroyed = true; } }
4376 Nullable!S s = S.init;
4377 destroyed = false;
4379 assert(destroyed);
4382 Nullable!(const S) s = S.init;
4383 destroyed = false;
4385 assert(destroyed);
4388 Nullable!(immutable S) s = S.init;
4389 destroyed = false;
4391 assert(destroyed);
4394 Nullable!(shared S) s = S.init;
4395 destroyed = false;
4397 assert(destroyed);
4401 Just like `Nullable!T`, except that the null state is defined as a
4402 particular value. For example, $(D Nullable!(uint, uint.max)) is an
4403 `uint` that sets aside the value `uint.max` to denote a null
4404 state. $(D Nullable!(T, nullValue)) is more storage-efficient than $(D
4405 Nullable!T) because it does not need to store an extra `bool`.
4407 Params:
4408 T = The wrapped type for which Nullable provides a null value.
4410 nullValue = The null value which denotes the null state of this
4411 `Nullable`. Must be of type `T`.
4413 struct Nullable(T, T nullValue)
4415 private T _value = nullValue;
4418 Constructor initializing `this` with `value`.
4420 Params:
4421 value = The value to initialize this `Nullable` with.
4423 this(T value)
4425 _value = value;
4428 template toString()
4430 import std.format.spec : FormatSpec;
4431 import std.format.write : formatValue;
4432 // Needs to be a template because of https://issues.dlang.org/show_bug.cgi?id=13737.
4433 void toString()(scope void delegate(const(char)[]) sink, scope const ref FormatSpec!char fmt)
4435 if (isNull)
4437 sink.formatValue("Nullable.null", fmt);
4439 else
4441 sink.formatValue(_value, fmt);
4445 void toString()(scope void delegate(const(char)[]) sink, scope const ref FormatSpec!char fmt) const
4447 if (isNull)
4449 sink.formatValue("Nullable.null", fmt);
4451 else
4453 sink.formatValue(_value, fmt);
4458 @system unittest
4460 import std.conv : to;
4462 const Nullable!(ulong, 0) x = 1;
4463 assert(x.to!string == "1");
4467 Check if `this` is in the null state.
4469 Returns:
4470 true $(B iff) `this` is in the null state, otherwise false.
4472 @property bool isNull() const
4474 //Need to use 'is' if T is a nullable type and
4475 //nullValue is null, or it's a compiler error
4476 static if (is(CommonType!(T, typeof(null)) == T) && nullValue is null)
4478 return _value is nullValue;
4480 //Need to use 'is' if T is a float type
4481 //because NaN != NaN
4482 else static if (__traits(isFloating, T) || __traits(compiles, { static assert(!(nullValue == nullValue)); }))
4484 return _value is nullValue;
4486 else
4488 return _value == nullValue;
4493 @safe unittest
4495 Nullable!(int, -1) ni;
4496 //Initialized to "null" state
4497 assert(ni.isNull);
4499 ni = 0;
4500 assert(!ni.isNull);
4503 @system unittest
4505 assert(typeof(this).init.isNull, typeof(this).stringof ~
4506 ".isNull does not work correctly because " ~ T.stringof ~
4507 " has an == operator that is non-reflexive and could not be" ~
4508 " determined before runtime to be non-reflexive!");
4511 // https://issues.dlang.org/show_bug.cgi?id=11135
4512 // disable test until https://issues.dlang.org/show_bug.cgi?id=15316 gets fixed
4513 version (none) @system unittest
4515 static foreach (T; AliasSeq!(float, double, real))
4517 Nullable!(T, T.init) nf;
4518 //Initialized to "null" state
4519 assert(nf.isNull);
4520 assert(nf is typeof(nf).init);
4522 nf = 0;
4523 assert(!nf.isNull);
4525 nf.nullify();
4526 assert(nf.isNull);
4531 Forces `this` to the null state.
4533 void nullify()()
4535 _value = nullValue;
4539 @safe unittest
4541 Nullable!(int, -1) ni = 0;
4542 assert(!ni.isNull);
4544 ni = -1;
4545 assert(ni.isNull);
4549 Assigns `value` to the internally-held state. If the assignment
4550 succeeds, `this` becomes non-null. No null checks are made. Note
4551 that the assignment may leave `this` in the null state.
4553 Params:
4554 value = A value of type `T` to assign to this `Nullable`.
4555 If it is `nullvalue`, then the internal state of
4556 this `Nullable` will be set to null.
4558 void opAssign()(T value)
4560 import std.algorithm.mutation : swap;
4562 swap(value, _value);
4566 If this `Nullable` wraps a type that already has a null value
4567 (such as a pointer), and that null value is not given for
4568 `nullValue`, then assigning the null value to this `Nullable`
4569 is no different than assigning any other value of type `T`,
4570 and the resulting code will look very strange. It is strongly
4571 recommended that this be avoided by using `T`'s "built in"
4572 null value for `nullValue`.
4574 @system unittest
4576 //Passes
4577 enum nullVal = cast(int*) 0xCAFEBABE;
4578 Nullable!(int*, nullVal) npi;
4579 assert(npi.isNull);
4581 //Passes?!
4582 npi = null;
4583 assert(!npi.isNull);
4587 Gets the value. `this` must not be in the null state.
4588 This function is also called for the implicit conversion to `T`.
4590 Preconditions: `isNull` must be `false`.
4591 Returns:
4592 The value held internally by this `Nullable`.
4594 @property ref inout(T) get() inout
4596 //@@@6169@@@: We avoid any call that might evaluate nullValue's %s,
4597 //Because it might messup get's purity and safety inference.
4598 enum message = "Called `get' on null Nullable!(" ~ T.stringof ~ ",nullValue).";
4599 assert(!isNull, message);
4600 return _value;
4604 @system unittest
4606 import std.exception : assertThrown, assertNotThrown;
4608 Nullable!(int, -1) ni;
4609 //`get` is implicitly called. Will throw
4610 //an error in non-release mode
4611 assertThrown!Throwable(ni == 0);
4613 ni = 0;
4614 assertNotThrown!Throwable(ni == 0);
4618 Implicitly converts to `T`.
4619 `this` must not be in the null state.
4621 alias get this;
4624 /// ditto
4625 auto nullable(alias nullValue, T)(T t)
4626 if (is (typeof(nullValue) == T))
4628 return Nullable!(T, nullValue)(t);
4632 @safe unittest
4634 Nullable!(size_t, size_t.max) indexOf(string[] haystack, string needle)
4636 //Find the needle, returning -1 if not found
4638 return Nullable!(size_t, size_t.max).init;
4641 void sendLunchInvite(string name)
4645 //It's safer than C...
4646 auto coworkers = ["Jane", "Jim", "Marry", "Fred"];
4647 auto pos = indexOf(coworkers, "Bob");
4648 if (!pos.isNull)
4650 //Send Bob an invitation to lunch
4651 sendLunchInvite(coworkers[pos]);
4653 else
4655 //Bob not found; report the error
4658 //And there's no overhead
4659 static assert(Nullable!(size_t, size_t.max).sizeof == size_t.sizeof);
4663 @system unittest
4665 import std.exception : assertThrown;
4667 Nullable!(int, int.min) a;
4668 assert(a.isNull);
4669 assertThrown!Throwable(a.get);
4670 a = 5;
4671 assert(!a.isNull);
4672 assert(a == 5);
4673 static assert(a.sizeof == int.sizeof);
4677 @safe unittest
4679 auto a = nullable!(int.min)(8);
4680 assert(a == 8);
4681 a.nullify();
4682 assert(a.isNull);
4685 @nogc nothrow pure @safe unittest
4687 // https://issues.dlang.org/show_bug.cgi?id=19226
4688 // fully handle non-self-equal nullValue
4689 static struct Fraction
4691 int denominator;
4692 bool isNaN() const
4694 return denominator == 0;
4696 bool opEquals(const Fraction rhs) const
4698 return !isNaN && denominator == rhs.denominator;
4701 alias N = Nullable!(Fraction, Fraction.init);
4702 assert(N.init.isNull);
4705 @safe unittest
4707 static int f(scope const Nullable!(int, int.min) x) {
4708 return x.isNull ? 42 : x.get;
4710 Nullable!(int, int.min) a;
4711 assert(f(a) == 42);
4712 a = 8;
4713 assert(f(a) == 8);
4714 a.nullify();
4715 assert(f(a) == 42);
4717 @safe unittest
4719 // Ensure Nullable can be used in pure/nothrow/@safe environment.
4720 function() @safe pure nothrow
4722 Nullable!(int, int.min) n;
4723 assert(n.isNull);
4724 n = 4;
4725 assert(!n.isNull);
4726 assert(n == 4);
4727 n.nullify();
4728 assert(n.isNull);
4729 }();
4731 @system unittest
4733 // Ensure Nullable can be used when the value is not pure/nothrow/@system
4734 static struct S
4736 int x;
4737 bool opEquals(const S s) const @system { return s.x == x; }
4740 Nullable!(S, S(711)) s;
4741 assert(s.isNull);
4742 s = S(5);
4743 assert(!s.isNull);
4744 assert(s.x == 5);
4745 s.nullify();
4746 assert(s.isNull);
4748 @safe unittest
4750 //Check nullable is nicelly embedable in a struct
4751 static struct S1
4753 Nullable!(int, 0) ni;
4755 static struct S2 //inspired from 9404
4757 Nullable!(int, 0) ni;
4758 this(S2 other)
4760 ni = other.ni;
4762 void opAssign(S2 other)
4764 ni = other.ni;
4767 static foreach (S; AliasSeq!(S1, S2))
4769 S a;
4770 S b = a;
4771 S c;
4772 c = a;
4775 @system unittest
4777 import std.conv : to;
4779 // https://issues.dlang.org/show_bug.cgi?id=10915
4780 Nullable!(int, 1) ni = 1;
4781 assert(ni.to!string() == "Nullable.null");
4783 struct Test { string s; }
4784 alias NullableTest = Nullable!(Test, Test("null"));
4786 NullableTest nt = Test("test");
4787 assert(nt.to!string() == `Test("test")`);
4789 NullableTest ntn = Test("null");
4790 assert(ntn.to!string() == "Nullable.null");
4792 class TestToString
4794 double d;
4796 this(double d)
4798 this.d = d;
4801 override string toString()
4803 return d.to!string();
4806 alias NullableTestToString = Nullable!(TestToString, null);
4808 NullableTestToString ntts = new TestToString(2.5);
4809 assert(ntts.to!string() == "2.5");
4812 // apply
4814 Unpacks the content of a `Nullable`, performs an operation and packs it again. Does nothing if isNull.
4816 When called on a `Nullable`, `apply` will unpack the value contained in the `Nullable`,
4817 pass it to the function you provide and wrap the result in another `Nullable` (if necessary).
4818 If the `Nullable` is null, `apply` will return null itself.
4820 Params:
4821 t = a `Nullable`
4822 fun = a function operating on the content of the nullable
4824 Returns:
4825 `fun(t.get).nullable` if `!t.isNull`, else `Nullable.init`.
4827 See also:
4828 $(HTTPS en.wikipedia.org/wiki/Monad_(functional_programming)#The_Maybe_monad, The `Maybe` monad)
4830 template apply(alias fun)
4832 import std.functional : unaryFun;
4834 auto apply(T)(auto ref T t)
4835 if (isInstanceOf!(Nullable, T))
4837 alias FunType = typeof(unaryFun!fun(T.init.get));
4839 enum MustWrapReturn = !isInstanceOf!(Nullable, FunType);
4841 static if (MustWrapReturn)
4843 alias ReturnType = Nullable!FunType;
4845 else
4847 alias ReturnType = FunType;
4850 if (!t.isNull)
4852 static if (MustWrapReturn)
4854 return unaryFun!fun(t.get).nullable;
4856 else
4858 return unaryFun!fun(t.get);
4861 else
4863 return ReturnType.init;
4869 nothrow pure @nogc @safe unittest
4871 alias toFloat = i => cast(float) i;
4873 Nullable!int sample;
4875 // apply(null) results in a null `Nullable` of the function's return type.
4876 Nullable!float f = sample.apply!toFloat;
4877 assert(sample.isNull && f.isNull);
4879 sample = 3;
4881 // apply(non-null) calls the function and wraps the result in a `Nullable`.
4882 f = sample.apply!toFloat;
4883 assert(!sample.isNull && !f.isNull);
4884 assert(f.get == 3.0f);
4888 nothrow pure @nogc @safe unittest
4890 alias greaterThree = i => (i > 3) ? i.nullable : Nullable!(typeof(i)).init;
4892 Nullable!int sample;
4894 // when the function already returns a `Nullable`, that `Nullable` is not wrapped.
4895 auto result = sample.apply!greaterThree;
4896 assert(sample.isNull && result.isNull);
4898 // The function may decide to return a null `Nullable`.
4899 sample = 3;
4900 result = sample.apply!greaterThree;
4901 assert(!sample.isNull && result.isNull);
4903 // Or it may return a value already wrapped in a `Nullable`.
4904 sample = 4;
4905 result = sample.apply!greaterThree;
4906 assert(!sample.isNull && !result.isNull);
4907 assert(result.get == 4);
4910 // test that Nullable.get(default) can merge types
4911 @safe @nogc nothrow pure
4912 unittest
4914 Nullable!ubyte sample = Nullable!ubyte();
4916 // Test that get(U) returns the common type of the Nullable type and the parameter type.
4917 assert(sample.get(1000) == 1000);
4920 // Workaround for https://issues.dlang.org/show_bug.cgi?id=20670
4921 @safe @nogc nothrow pure
4922 unittest
4924 immutable struct S { }
4926 S[] array = Nullable!(S[])().get(S[].init);
4929 // regression test for https://issues.dlang.org/show_bug.cgi?id=21199
4930 @safe @nogc nothrow pure
4931 unittest
4933 struct S { int i; }
4934 assert(S(5).nullable.apply!"a.i" == 5);
4937 // regression test for https://issues.dlang.org/show_bug.cgi?id=22176
4938 @safe @nogc nothrow pure
4939 unittest
4941 struct S
4943 int i;
4944 invariant(i != 0);
4946 // Nullable shouldn't cause S to generate an
4947 // opAssign that would check the invariant.
4948 Nullable!int j;
4950 S s;
4951 s = S(5);
4955 Just like `Nullable!T`, except that the object refers to a value
4956 sitting elsewhere in memory. This makes assignments overwrite the
4957 initially assigned value. Internally `NullableRef!T` only stores a
4958 pointer to `T` (i.e., $(D Nullable!T.sizeof == (T*).sizeof)).
4960 struct NullableRef(T)
4962 private T* _value;
4965 Constructor binding `this` to `value`.
4967 Params:
4968 value = The value to bind to.
4970 this(T* value) @safe pure nothrow
4972 _value = value;
4975 template toString()
4977 import std.format.spec : FormatSpec;
4978 import std.format.write : formatValue;
4979 // Needs to be a template because of https://issues.dlang.org/show_bug.cgi?id=13737.
4980 void toString()(scope void delegate(const(char)[]) sink, scope const ref FormatSpec!char fmt)
4982 if (isNull)
4984 sink.formatValue("Nullable.null", fmt);
4986 else
4988 sink.formatValue(*_value, fmt);
4992 void toString()(scope void delegate(const(char)[]) sink, scope const ref FormatSpec!char fmt) const
4994 if (isNull)
4996 sink.formatValue("Nullable.null", fmt);
4998 else
5000 sink.formatValue(*_value, fmt);
5005 @system unittest
5007 import std.conv : to;
5009 const NullableRef!(ulong) x = new ulong(1);
5010 assert(x.to!string == "1");
5014 Binds the internal state to `value`.
5016 Params:
5017 value = A pointer to a value of type `T` to bind this `NullableRef` to.
5019 void bind(T* value) @safe pure nothrow
5021 _value = value;
5025 @safe unittest
5027 NullableRef!int nr = new int(42);
5028 assert(nr == 42);
5030 int* n = new int(1);
5031 nr.bind(n);
5032 assert(nr == 1);
5036 Returns `true` if and only if `this` is in the null state.
5038 Returns:
5039 true if `this` is in the null state, otherwise false.
5041 @property bool isNull() const @safe pure nothrow
5043 return _value is null;
5047 @safe unittest
5049 NullableRef!int nr;
5050 assert(nr.isNull);
5052 int* n = new int(42);
5053 nr.bind(n);
5054 assert(!nr.isNull && nr == 42);
5058 Forces `this` to the null state.
5060 void nullify() @safe pure nothrow
5062 _value = null;
5066 @safe unittest
5068 NullableRef!int nr = new int(42);
5069 assert(!nr.isNull);
5071 nr.nullify();
5072 assert(nr.isNull);
5076 Assigns `value` to the internally-held state.
5078 Params:
5079 value = A value of type `T` to assign to this `NullableRef`.
5080 If the internal state of this `NullableRef` has not
5081 been initialized, an error will be thrown in
5082 non-release mode.
5084 void opAssign()(T value)
5085 if (isAssignable!T) //@@@9416@@@
5087 enum message = "Called `opAssign' on null NullableRef!" ~ T.stringof ~ ".";
5088 assert(!isNull, message);
5089 *_value = value;
5093 @system unittest
5095 import std.exception : assertThrown, assertNotThrown;
5097 NullableRef!int nr;
5098 assert(nr.isNull);
5099 assertThrown!Throwable(nr = 42);
5101 nr.bind(new int(0));
5102 assert(!nr.isNull);
5103 assertNotThrown!Throwable(nr = 42);
5104 assert(nr == 42);
5108 Gets the value. `this` must not be in the null state.
5109 This function is also called for the implicit conversion to `T`.
5111 @property ref inout(T) get() inout @safe pure nothrow
5113 enum message = "Called `get' on null NullableRef!" ~ T.stringof ~ ".";
5114 assert(!isNull, message);
5115 return *_value;
5119 @system unittest
5121 import std.exception : assertThrown, assertNotThrown;
5123 NullableRef!int nr;
5124 //`get` is implicitly called. Will throw
5125 //an error in non-release mode
5126 assertThrown!Throwable(nr == 0);
5128 nr.bind(new int(0));
5129 assertNotThrown!Throwable(nr == 0);
5133 Implicitly converts to `T`.
5134 `this` must not be in the null state.
5136 alias get this;
5139 /// ditto
5140 auto nullableRef(T)(T* t)
5142 return NullableRef!T(t);
5146 @system unittest
5148 import std.exception : assertThrown;
5150 int x = 5, y = 7;
5151 auto a = nullableRef(&x);
5152 assert(!a.isNull);
5153 assert(a == 5);
5154 assert(x == 5);
5155 a = 42;
5156 assert(x == 42);
5157 assert(!a.isNull);
5158 assert(a == 42);
5159 a.nullify();
5160 assert(x == 42);
5161 assert(a.isNull);
5162 assertThrown!Throwable(a.get);
5163 assertThrown!Throwable(a = 71);
5164 a.bind(&y);
5165 assert(a == 7);
5166 y = 135;
5167 assert(a == 135);
5169 @system unittest
5171 static int f(scope const NullableRef!int x) {
5172 return x.isNull ? 42 : x.get;
5174 int x = 5;
5175 auto a = nullableRef(&x);
5176 assert(f(a) == 5);
5177 a.nullify();
5178 assert(f(a) == 42);
5180 @safe unittest
5182 // Ensure NullableRef can be used in pure/nothrow/@safe environment.
5183 function() @safe pure nothrow
5185 auto storage = new int;
5186 *storage = 19902;
5187 NullableRef!int n;
5188 assert(n.isNull);
5189 n.bind(storage);
5190 assert(!n.isNull);
5191 assert(n == 19902);
5192 n = 2294;
5193 assert(n == 2294);
5194 assert(*storage == 2294);
5195 n.nullify();
5196 assert(n.isNull);
5197 }();
5199 @system unittest
5201 // Ensure NullableRef can be used when the value is not pure/nothrow/@safe
5202 static struct S
5204 int x;
5205 this(this) @system {}
5206 bool opEquals(const S s) const @system { return s.x == x; }
5209 auto storage = S(5);
5211 NullableRef!S s;
5212 assert(s.isNull);
5213 s.bind(&storage);
5214 assert(!s.isNull);
5215 assert(s.x == 5);
5216 s.nullify();
5217 assert(s.isNull);
5219 @safe unittest
5221 //Check nullable is nicelly embedable in a struct
5222 static struct S1
5224 NullableRef!int ni;
5226 static struct S2 //inspired from 9404
5228 NullableRef!int ni;
5229 this(S2 other)
5231 ni = other.ni;
5233 void opAssign(S2 other)
5235 ni = other.ni;
5238 static foreach (S; AliasSeq!(S1, S2))
5240 S a;
5241 S b = a;
5242 S c;
5243 c = a;
5247 // https://issues.dlang.org/show_bug.cgi?id=10915
5248 @system unittest
5250 import std.conv : to;
5252 NullableRef!int nri;
5253 assert(nri.to!string() == "Nullable.null");
5255 struct Test
5257 string s;
5259 NullableRef!Test nt = new Test("test");
5260 assert(nt.to!string() == `Test("test")`);
5262 class TestToString
5264 double d;
5266 this(double d)
5268 this.d = d;
5271 override string toString()
5273 return d.to!string();
5276 TestToString tts = new TestToString(2.5);
5277 NullableRef!TestToString ntts = &tts;
5278 assert(ntts.to!string() == "2.5");
5283 `BlackHole!Base` is a subclass of `Base` which automatically implements
5284 all abstract member functions in `Base` as do-nothing functions. Each
5285 auto-implemented function just returns the default value of the return type
5286 without doing anything.
5288 The name came from
5289 $(HTTP search.cpan.org/~sburke/Class-_BlackHole-0.04/lib/Class/_BlackHole.pm, Class::_BlackHole)
5290 Perl module by Sean M. Burke.
5292 Params:
5293 Base = A non-final class for `BlackHole` to inherit from.
5295 See_Also:
5296 $(LREF AutoImplement), $(LREF generateEmptyFunction)
5298 alias BlackHole(Base) = AutoImplement!(Base, generateEmptyFunction, isAbstractFunction);
5301 @system unittest
5303 import std.math.traits : isNaN;
5305 static abstract class C
5307 int m_value;
5308 this(int v) { m_value = v; }
5309 int value() @property { return m_value; }
5311 abstract real realValue() @property;
5312 abstract void doSomething();
5315 auto c = new BlackHole!C(42);
5316 assert(c.value == 42);
5318 // Returns real.init which is NaN
5319 assert(c.realValue.isNaN);
5320 // Abstract functions are implemented as do-nothing
5321 c.doSomething();
5324 @system unittest
5326 import std.math.traits : isNaN;
5328 // return default
5330 interface I_1 { real test(); }
5331 auto o = new BlackHole!I_1;
5332 assert(o.test().isNaN()); // NaN
5334 // doc example
5336 static class C
5338 int m_value;
5339 this(int v) { m_value = v; }
5340 int value() @property { return m_value; }
5342 abstract real realValue() @property;
5343 abstract void doSomething();
5346 auto c = new BlackHole!C(42);
5347 assert(c.value == 42);
5349 assert(c.realValue.isNaN); // NaN
5350 c.doSomething();
5353 // https://issues.dlang.org/show_bug.cgi?id=12058
5354 interface Foo
5356 inout(Object) foo() inout;
5358 BlackHole!Foo o;
5361 nothrow pure @nogc @safe unittest
5363 static interface I
5365 I foo() nothrow pure @nogc @safe return scope;
5368 scope cb = new BlackHole!I();
5369 cb.foo();
5374 `WhiteHole!Base` is a subclass of `Base` which automatically implements
5375 all abstract member functions as functions that always fail. These functions
5376 simply throw an `Error` and never return. `Whitehole` is useful for
5377 trapping the use of class member functions that haven't been implemented.
5379 The name came from
5380 $(HTTP search.cpan.org/~mschwern/Class-_WhiteHole-0.04/lib/Class/_WhiteHole.pm, Class::_WhiteHole)
5381 Perl module by Michael G Schwern.
5383 Params:
5384 Base = A non-final class for `WhiteHole` to inherit from.
5386 See_Also:
5387 $(LREF AutoImplement), $(LREF generateAssertTrap)
5389 alias WhiteHole(Base) = AutoImplement!(Base, generateAssertTrap, isAbstractFunction);
5392 @system unittest
5394 import std.exception : assertThrown;
5396 static class C
5398 abstract void notYetImplemented();
5401 auto c = new WhiteHole!C;
5402 assertThrown!NotImplementedError(c.notYetImplemented()); // throws an Error
5405 // https://issues.dlang.org/show_bug.cgi?id=20232
5406 nothrow pure @safe unittest
5408 static interface I
5410 I foo() nothrow pure @safe return scope;
5413 if (0) // Just checking attribute interference
5415 scope cw = new WhiteHole!I();
5416 cw.foo();
5420 // / ditto
5421 class NotImplementedError : Error
5423 this(string method) nothrow pure @safe
5425 super(method ~ " is not implemented");
5429 @system unittest
5431 import std.exception : assertThrown;
5432 // nothrow
5434 interface I_1
5436 void foo();
5437 void bar() nothrow;
5439 auto o = new WhiteHole!I_1;
5440 assertThrown!NotImplementedError(o.foo());
5441 assertThrown!NotImplementedError(o.bar());
5443 // doc example
5445 static class C
5447 abstract void notYetImplemented();
5450 auto c = new WhiteHole!C;
5453 c.notYetImplemented();
5454 assert(0);
5456 catch (Error e) {}
5462 `AutoImplement` automatically implements (by default) all abstract member
5463 functions in the class or interface `Base` in specified way.
5465 The second version of `AutoImplement` automatically implements
5466 `Interface`, while deriving from `BaseClass`.
5468 Params:
5469 how = template which specifies _how functions will be implemented/overridden.
5471 Two arguments are passed to `how`: the type `Base` and an alias
5472 to an implemented function. Then `how` must return an implemented
5473 function body as a string.
5475 The generated function body can use these keywords:
5476 $(UL
5477 $(LI `a0`, `a1`, &hellip;: arguments passed to the function;)
5478 $(LI `args`: a tuple of the arguments;)
5479 $(LI `self`: an alias to the function itself;)
5480 $(LI `parent`: an alias to the overridden function (if any).)
5483 You may want to use templated property functions (instead of Implicit
5484 Template Properties) to generate complex functions:
5485 --------------------
5486 // Prints log messages for each call to overridden functions.
5487 string generateLogger(C, alias fun)() @property
5489 import std.traits;
5490 enum qname = C.stringof ~ "." ~ __traits(identifier, fun);
5491 string stmt;
5493 stmt ~= q{ struct Importer { import std.stdio; } };
5494 stmt ~= `Importer.writeln("Log: ` ~ qname ~ `(", args, ")");`;
5495 static if (!__traits(isAbstractFunction, fun))
5497 static if (is(ReturnType!fun == void))
5498 stmt ~= q{ parent(args); };
5499 else
5500 stmt ~= q{
5501 auto r = parent(args);
5502 Importer.writeln("--> ", r);
5503 return r;
5506 return stmt;
5508 --------------------
5510 what = template which determines _what functions should be
5511 implemented/overridden.
5513 An argument is passed to `what`: an alias to a non-final member
5514 function in `Base`. Then `what` must return a boolean value.
5515 Return `true` to indicate that the passed function should be
5516 implemented/overridden.
5518 --------------------
5519 // Sees if fun returns something.
5520 enum bool hasValue(alias fun) = !is(ReturnType!(fun) == void);
5521 --------------------
5524 Note:
5526 Generated code is inserted in the scope of `std.typecons` module. Thus,
5527 any useful functions outside `std.typecons` cannot be used in the generated
5528 code. To workaround this problem, you may `import` necessary things in a
5529 local struct, as done in the `generateLogger()` template in the above
5530 example.
5533 BUGS:
5535 $(UL
5536 $(LI Variadic arguments to constructors are not forwarded to super.)
5537 $(LI Deep interface inheritance causes compile error with messages like
5538 "Error: function std.typecons._AutoImplement!(Foo)._AutoImplement.bar
5539 does not override any function". [$(BUGZILLA 2525)] )
5540 $(LI The `parent` keyword is actually a delegate to the super class'
5541 corresponding member function. [$(BUGZILLA 2540)] )
5542 $(LI Using alias template parameter in `how` and/or `what` may cause
5543 strange compile error. Use template tuple parameter instead to workaround
5544 this problem. [$(BUGZILLA 4217)] )
5547 class AutoImplement(Base, alias how, alias what = isAbstractFunction) : Base
5548 if (!is(how == class))
5550 private alias autoImplement_helper_ =
5551 AutoImplement_Helper!("autoImplement_helper_", "Base", Base, typeof(this), how, what);
5552 mixin(autoImplement_helper_.code);
5555 /// ditto
5556 class AutoImplement(
5557 Interface, BaseClass, alias how,
5558 alias what = isAbstractFunction) : BaseClass, Interface
5559 if (is(Interface == interface) && is(BaseClass == class))
5561 private alias autoImplement_helper_ = AutoImplement_Helper!(
5562 "autoImplement_helper_", "Interface", Interface, typeof(this), how, what);
5563 mixin(autoImplement_helper_.code);
5567 @system unittest
5569 interface PackageSupplier
5571 int foo();
5572 int bar();
5575 static abstract class AbstractFallbackPackageSupplier : PackageSupplier
5577 protected PackageSupplier default_, fallback;
5579 this(PackageSupplier default_, PackageSupplier fallback)
5581 this.default_ = default_;
5582 this.fallback = fallback;
5585 abstract int foo();
5586 abstract int bar();
5589 template fallback(T, alias func)
5591 import std.format : format;
5592 // for all implemented methods:
5593 // - try default first
5594 // - only on a failure run & return fallback
5595 enum fallback = q{
5598 return default_.%1$s(args);
5600 catch (Exception)
5602 return fallback.%1$s(args);
5604 }.format(__traits(identifier, func));
5607 // combines two classes and use the second one as fallback
5608 alias FallbackPackageSupplier = AutoImplement!(AbstractFallbackPackageSupplier, fallback);
5610 class FailingPackageSupplier : PackageSupplier
5612 int foo(){ throw new Exception("failure"); }
5613 int bar(){ return 2;}
5616 class BackupPackageSupplier : PackageSupplier
5618 int foo(){ return -1; }
5619 int bar(){ return -1;}
5622 auto registry = new FallbackPackageSupplier(new FailingPackageSupplier(), new BackupPackageSupplier());
5624 assert(registry.foo() == -1);
5625 assert(registry.bar() == 2);
5629 * Code-generating stuffs are encupsulated in this helper template so that
5630 * namespace pollution, which can cause name confliction with Base's public
5631 * members, should be minimized.
5633 private template AutoImplement_Helper(string myName, string baseName,
5634 Base, Self, alias generateMethodBody, alias cherrypickMethod)
5636 private static:
5637 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5638 // Internal stuffs
5639 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5641 // Returns function overload sets in the class C, filtered with pred.
5642 template enumerateOverloads(C, alias pred)
5644 template Impl(names...)
5646 import std.meta : Filter;
5647 static if (names.length > 0)
5649 alias methods = Filter!(pred, MemberFunctionsTuple!(C, names[0]));
5650 alias next = Impl!(names[1 .. $]);
5652 static if (methods.length > 0)
5653 alias Impl = AliasSeq!(OverloadSet!(names[0], methods), next);
5654 else
5655 alias Impl = next;
5657 else
5658 alias Impl = AliasSeq!();
5661 alias enumerateOverloads = Impl!(__traits(allMembers, C));
5664 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5665 // Target functions
5666 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5668 // Add a non-final check to the cherrypickMethod.
5669 enum bool canonicalPicker(fun.../+[https://issues.dlang.org/show_bug.cgi?id=4217]+/) =
5670 !__traits(isFinalFunction, fun[0]) && cherrypickMethod!(fun);
5673 * A tuple of overload sets, each item of which consists of functions to be
5674 * implemented by the generated code.
5676 alias targetOverloadSets = enumerateOverloads!(Base, canonicalPicker);
5679 * Super class of this AutoImplement instance
5681 alias Super = BaseTypeTuple!(Self)[0];
5682 static assert(is(Super == class));
5683 static assert(is(Base == interface) || is(Super == Base));
5686 * A tuple of the super class' constructors. Used for forwarding
5687 * constructor calls.
5689 static if (__traits(hasMember, Super, "__ctor"))
5690 alias ctorOverloadSet = OverloadSet!("__ctor", __traits(getOverloads, Super, "__ctor"));
5691 else
5692 alias ctorOverloadSet = OverloadSet!("__ctor"); // empty
5695 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5696 // Type information
5697 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5700 * The generated code will be mixed into AutoImplement, which will be
5701 * instantiated in this module's scope. Thus, any user-defined types are
5702 * out of scope and cannot be used directly (i.e. by their names).
5704 * We will use FuncInfo instances for accessing return types and parameter
5705 * types of the implemented functions. The instances will be populated to
5706 * the AutoImplement's scope in a certain way; see the populate() below.
5709 // Returns the preferred identifier for the FuncInfo instance for the i-th
5710 // overloaded function with the name.
5711 template INTERNAL_FUNCINFO_ID(string name, size_t i)
5713 import std.format : format;
5715 enum string INTERNAL_FUNCINFO_ID = format("F_%s_%s", name, i);
5719 * Insert FuncInfo instances about all the target functions here. This
5720 * enables the generated code to access type information via, for example,
5721 * "autoImplement_helper_.F_foo_1".
5723 template populate(overloads...)
5725 static if (overloads.length > 0)
5727 mixin populate!(overloads[0].name, overloads[0].contents);
5728 mixin populate!(overloads[1 .. $]);
5731 template populate(string name, methods...)
5733 static if (methods.length > 0)
5735 mixin populate!(name, methods[0 .. $ - 1]);
5737 alias target = methods[$ - 1];
5738 enum ith = methods.length - 1;
5739 mixin("alias " ~ INTERNAL_FUNCINFO_ID!(name, ith) ~ " = FuncInfo!target;");
5743 public mixin populate!(targetOverloadSets);
5744 public mixin populate!( ctorOverloadSet );
5747 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5748 // Code-generating policies
5749 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5751 /* Common policy configurations for generating constructors and methods. */
5752 template CommonGeneratingPolicy()
5754 // base class identifier which generated code should use
5755 enum string BASE_CLASS_ID = baseName;
5757 // FuncInfo instance identifier which generated code should use
5758 template FUNCINFO_ID(string name, size_t i)
5760 enum string FUNCINFO_ID =
5761 myName ~ "." ~ INTERNAL_FUNCINFO_ID!(name, i);
5765 /* Policy configurations for generating constructors. */
5766 template ConstructorGeneratingPolicy()
5768 mixin CommonGeneratingPolicy;
5770 /* Generates constructor body. Just forward to the base class' one. */
5771 string generateFunctionBody(ctor.../+[https://issues.dlang.org/show_bug.cgi?id=4217]+/)() @property
5773 enum varstyle = variadicFunctionStyle!(typeof(&ctor[0]));
5775 static if (varstyle & (Variadic.c | Variadic.d))
5777 // the argptr-forwarding problem
5778 //pragma(msg, "Warning: AutoImplement!(", Base, ") ",
5779 // "ignored variadic arguments to the constructor ",
5780 // FunctionTypeOf!(typeof(&ctor[0])) );
5782 return "super(args);";
5786 /* Policy configurations for genearting target methods. */
5787 template MethodGeneratingPolicy()
5789 mixin CommonGeneratingPolicy;
5791 /* Geneartes method body. */
5792 string generateFunctionBody(func.../+[https://issues.dlang.org/show_bug.cgi?id=4217]+/)() @property
5794 return generateMethodBody!(Base, func); // given
5799 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5800 // Generated code
5801 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5803 alias ConstructorGenerator = MemberFunctionGenerator!(ConstructorGeneratingPolicy!());
5804 alias MethodGenerator = MemberFunctionGenerator!(MethodGeneratingPolicy!());
5806 public enum string code =
5807 ConstructorGenerator.generateCode!( ctorOverloadSet ) ~ "\n" ~
5808 MethodGenerator.generateCode!(targetOverloadSets);
5810 debug (SHOW_GENERATED_CODE)
5812 pragma(msg, "-------------------- < ", Base, " >");
5813 pragma(msg, code);
5814 pragma(msg, "--------------------");
5818 //debug = SHOW_GENERATED_CODE;
5819 @system unittest
5821 import core.vararg;
5822 // no function to implement
5824 interface I_1 {}
5825 auto o = new BlackHole!I_1;
5827 // parameters
5829 interface I_3 { void test(int, in int, out int, ref int, lazy int); }
5830 auto o = new BlackHole!I_3;
5832 // use of user-defined type
5834 struct S {}
5835 interface I_4 { S test(); }
5836 auto o = new BlackHole!I_4;
5838 // overloads
5840 interface I_5
5842 void test(string);
5843 real test(real);
5844 int test();
5846 auto o = new BlackHole!I_5;
5848 // constructor forwarding
5850 static class C_6
5852 this(int n) { assert(n == 42); }
5853 this(string s) { assert(s == "Deeee"); }
5854 this(...) {}
5856 auto o1 = new BlackHole!C_6(42);
5857 auto o2 = new BlackHole!C_6("Deeee");
5858 auto o3 = new BlackHole!C_6(1, 2, 3, 4);
5860 // attributes
5862 interface I_7
5864 ref int test_ref();
5865 int test_pure() pure;
5866 int test_nothrow() nothrow;
5867 int test_property() @property;
5868 int test_safe() @safe;
5869 int test_trusted() @trusted;
5870 int test_system() @system;
5871 int test_pure_nothrow() pure nothrow;
5873 auto o = new BlackHole!I_7;
5875 // storage classes
5877 interface I_8
5879 void test_const() const;
5880 void test_immutable() immutable;
5881 void test_shared() shared;
5882 void test_shared_const() shared const;
5884 auto o = new BlackHole!I_8;
5886 // use baseclass
5888 static class C_9
5890 private string foo_;
5892 this(string s) {
5893 foo_ = s;
5896 protected string boilerplate() @property
5898 return "Boilerplate stuff.";
5901 public string foo() @property
5903 return foo_;
5907 interface I_10
5909 string testMethod(size_t);
5912 static string generateTestMethod(C, alias fun)() @property
5914 return "return this.boilerplate[0 .. a0];";
5917 auto o = new AutoImplement!(I_10, C_9, generateTestMethod)("Testing");
5918 assert(o.testMethod(11) == "Boilerplate");
5919 assert(o.foo == "Testing");
5921 /+ // deep inheritance
5923 // https://issues.dlang.org/show_bug.cgi?id=2525
5924 // https://issues.dlang.org/show_bug.cgi?id=3525
5925 // NOTE: [r494] func.c(504-571) FuncDeclaration::semantic()
5926 interface I { void foo(); }
5927 interface J : I {}
5928 interface K : J {}
5929 static abstract class C_9 : K {}
5930 auto o = new BlackHole!C_9;
5932 // test `parent` alias
5934 interface I_11
5936 void simple(int) @safe;
5937 int anotherSimple(string);
5938 int overloaded(int);
5939 /+ XXX [BUG 19715]
5940 void overloaded(string) @safe;
5944 static class C_11
5946 import std.traits : Parameters, ReturnType;
5947 import std.meta : Alias;
5949 protected ReturnType!fn _impl(alias fn)(Parameters!fn)
5950 if (is(Alias!(__traits(parent, fn)) == interface))
5952 static if (!is(typeof(return) == void))
5953 return typeof(return).init;
5957 template tpl(I, alias fn)
5958 if (is(I == interface) && __traits(isSame, __traits(parent, fn), I))
5960 enum string tpl = q{
5961 enum bool haveReturn = !is(typeof(return) == void);
5963 static if (is(typeof(return) == void))
5964 _impl!parent(args);
5965 else
5966 return _impl!parent(args);
5970 auto o = new AutoImplement!(I_11, C_11, tpl);
5974 // https://issues.dlang.org/show_bug.cgi?id=17177
5975 // AutoImplement fails on function overload sets with
5976 // "cannot infer type from overloaded function symbol"
5977 @system unittest
5979 static class Issue17177
5981 private string n_;
5983 public {
5984 Issue17177 overloaded(string n)
5986 this.n_ = n;
5988 return this;
5991 string overloaded()
5993 return this.n_;
5998 static string how(C, alias fun)()
6000 static if (!is(ReturnType!fun == void))
6002 return q{
6003 return parent(args);
6006 else
6008 return q{
6009 parent(args);
6014 import std.meta : templateNot;
6015 alias Implementation = AutoImplement!(Issue17177, how, templateNot!isFinalFunction);
6018 version (StdUnittest)
6020 // https://issues.dlang.org/show_bug.cgi?id=10647
6021 // Add prefix "issue10647_" as a workaround for
6022 // https://issues.dlang.org/show_bug.cgi?id=1238
6023 private string issue10647_generateDoNothing(C, alias fun)() @property
6025 string stmt;
6027 static if (is(ReturnType!fun == void))
6028 stmt ~= "";
6029 else
6031 string returnType = ReturnType!fun.stringof;
6032 stmt ~= "return "~returnType~".init;";
6034 return stmt;
6037 private template issue10647_isAlwaysTrue(alias fun)
6039 enum issue10647_isAlwaysTrue = true;
6042 // Do nothing template
6043 private template issue10647_DoNothing(Base)
6045 alias issue10647_DoNothing = AutoImplement!(Base, issue10647_generateDoNothing, issue10647_isAlwaysTrue);
6048 // A class to be overridden
6049 private class issue10647_Foo{
6050 void bar(int a) { }
6054 @system unittest
6056 auto foo = new issue10647_DoNothing!issue10647_Foo();
6057 foo.bar(13);
6061 Used by MemberFunctionGenerator.
6063 package template OverloadSet(string nam, T...)
6065 enum string name = nam;
6066 alias contents = T;
6070 Used by MemberFunctionGenerator.
6072 package template FuncInfo(alias func)
6073 if (is(typeof(&func)))
6075 alias RT = ReturnType!(typeof(&func));
6076 alias PT = Parameters!(typeof(&func));
6078 package template FuncInfo(Func)
6080 alias RT = ReturnType!Func;
6081 alias PT = Parameters!Func;
6085 General-purpose member function generator.
6086 --------------------
6087 template GeneratingPolicy()
6089 // [optional] the name of the class where functions are derived
6090 enum string BASE_CLASS_ID;
6092 // [optional] define this if you have only function types
6093 enum bool WITHOUT_SYMBOL;
6095 // [optional] Returns preferred identifier for i-th parameter.
6096 template PARAMETER_VARIABLE_ID(size_t i);
6098 // Returns the identifier of the FuncInfo instance for the i-th overload
6099 // of the specified name. The identifier must be accessible in the scope
6100 // where generated code is mixed.
6101 template FUNCINFO_ID(string name, size_t i);
6103 // Returns implemented function body as a string. When WITHOUT_SYMBOL is
6104 // defined, the latter is used.
6105 template generateFunctionBody(alias func);
6106 template generateFunctionBody(string name, FuncType);
6108 --------------------
6110 package template MemberFunctionGenerator(alias Policy)
6112 private static:
6113 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
6114 // Internal stuffs
6115 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
6116 import std.format;
6117 alias format = std.format.format;
6119 enum CONSTRUCTOR_NAME = "__ctor";
6121 // true if functions are derived from a base class
6122 enum WITH_BASE_CLASS = __traits(hasMember, Policy, "BASE_CLASS_ID");
6124 // true if functions are specified as types, not symbols
6125 enum WITHOUT_SYMBOL = __traits(hasMember, Policy, "WITHOUT_SYMBOL");
6127 // preferred identifier for i-th parameter variable
6128 static if (__traits(hasMember, Policy, "PARAMETER_VARIABLE_ID"))
6130 alias PARAMETER_VARIABLE_ID = Policy.PARAMETER_VARIABLE_ID;
6132 else
6134 enum string PARAMETER_VARIABLE_ID(size_t i) = format("a%s", i);
6135 // default: a0, a1, ...
6138 // Returns a tuple consisting of 0,1,2,...,n-1. For static foreach.
6139 template CountUp(size_t n)
6141 static if (n > 0)
6142 alias CountUp = AliasSeq!(CountUp!(n - 1), n - 1);
6143 else
6144 alias CountUp = AliasSeq!();
6148 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
6149 // Code generator
6150 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
6153 * Runs through all the target overload sets and generates D code which
6154 * implements all the functions in the overload sets.
6156 public string generateCode(overloads...)() @property
6158 string code = "";
6160 // run through all the overload sets
6161 foreach (i_; CountUp!(0 + overloads.length)) // workaround
6163 enum i = 0 + i_; // workaround
6164 alias oset = overloads[i];
6166 code ~= generateCodeForOverloadSet!(oset);
6168 static if (WITH_BASE_CLASS && oset.name != CONSTRUCTOR_NAME)
6170 // The generated function declarations may hide existing ones
6171 // in the base class (cf. HiddenFuncError), so we put an alias
6172 // declaration here to reveal possible hidden functions.
6173 code ~= format("alias %s = %s.%s;\n",
6174 oset.name,
6175 // super: https://issues.dlang.org/show_bug.cgi?id=2540
6176 Policy.BASE_CLASS_ID,
6177 oset.name);
6180 return code;
6183 // handle each overload set
6184 string generateCodeForOverloadSet(alias oset)() @property
6186 string code = "";
6188 foreach (i_; CountUp!(0 + oset.contents.length)) // workaround
6190 enum i = 0 + i_; // workaround
6191 code ~= generateFunction!(
6192 Policy.FUNCINFO_ID!(oset.name, i), oset.name,
6193 oset.contents[i]) ~ "\n";
6195 return code;
6199 * Returns D code which implements the function func. This function
6200 * actually generates only the declarator part; the function body part is
6201 * generated by the functionGenerator() policy.
6203 public string generateFunction(
6204 string myFuncInfo, string name, func... )() @property
6206 import std.format : format;
6208 enum isCtor = (name == CONSTRUCTOR_NAME);
6210 string code; // the result
6212 auto paramsRes = generateParameters!(myFuncInfo, func)();
6213 code ~= paramsRes.imports;
6215 /*** Function Declarator ***/
6217 alias Func = FunctionTypeOf!(func);
6218 alias FA = FunctionAttribute;
6219 enum atts = functionAttributes!(func);
6220 enum realName = isCtor ? "this" : name;
6222 // FIXME?? Make it so that these aren't CTFE funcs any more, since
6223 // Format is deprecated, and format works at compile time?
6224 /* Made them CTFE funcs just for the sake of Format!(...) */
6226 // return type with optional "ref"
6227 static string make_returnType()
6229 string rtype = "";
6231 if (!isCtor)
6233 if (atts & FA.ref_) rtype ~= "ref ";
6234 rtype ~= myFuncInfo ~ ".RT";
6236 return rtype;
6238 enum returnType = make_returnType();
6240 // function attributes attached after declaration
6241 static string make_postAtts()
6243 string poatts = "";
6244 if (atts & FA.pure_ ) poatts ~= " pure";
6245 if (atts & FA.nothrow_) poatts ~= " nothrow";
6246 if (atts & FA.property) poatts ~= " @property";
6247 if (atts & FA.safe ) poatts ~= " @safe";
6248 if (atts & FA.trusted ) poatts ~= " @trusted";
6249 if (atts & FA.scope_ ) poatts ~= " scope";
6250 if (atts & FA.return_ ) poatts ~= " return";
6251 return poatts;
6253 enum postAtts = make_postAtts();
6255 // function storage class
6256 static string make_storageClass()
6258 string postc = "";
6259 if (is(Func == shared)) postc ~= " shared";
6260 if (is(Func == const)) postc ~= " const";
6261 if (is(Func == inout)) postc ~= " inout";
6262 if (is(Func == immutable)) postc ~= " immutable";
6263 return postc;
6265 enum storageClass = make_storageClass();
6268 if (__traits(isVirtualMethod, func))
6269 code ~= "override ";
6270 code ~= format("extern(%s) %s %s(%s) %s %s\n",
6271 functionLinkage!(func),
6272 returnType,
6273 realName,
6274 paramsRes.params,
6275 postAtts, storageClass );
6278 /*** Function Body ***/
6279 code ~= "{\n";
6281 enum nparams = Parameters!(func).length;
6283 /* Declare keywords: args, self and parent. */
6284 string preamble;
6286 preamble ~= "alias args = AliasSeq!(" ~ enumerateParameters!(nparams) ~ ");\n";
6287 if (!isCtor)
6289 preamble ~= "alias self = " ~ name ~ ";\n";
6290 static if (WITH_BASE_CLASS)
6291 preamble ~= `alias parent = __traits(getMember, ` ~ Policy.BASE_CLASS_ID ~ `, "` ~ name ~ `");`;
6294 // Function body
6295 static if (WITHOUT_SYMBOL)
6296 enum fbody = Policy.generateFunctionBody!(name, func);
6297 else
6298 enum fbody = Policy.generateFunctionBody!(func);
6300 code ~= preamble;
6301 code ~= fbody;
6303 code ~= "}";
6305 return code;
6309 * Returns D code which declares function parameters,
6310 * and optionally any imports (e.g. core.vararg)
6311 * "ref int a0, real a1, ..."
6313 static struct GenParams { string imports, params; }
6314 GenParams generateParameters(string myFuncInfo, func...)()
6316 alias STC = ParameterStorageClass;
6317 alias stcs = ParameterStorageClassTuple!(func);
6318 enum nparams = stcs.length;
6320 string imports = ""; // any imports required
6321 string params = ""; // parameters
6323 foreach (i, stc; stcs)
6325 if (i > 0) params ~= ", ";
6327 // Parameter storage classes.
6328 if (stc & STC.scope_) params ~= "scope ";
6329 if (stc & STC.in_) params ~= "in ";
6330 if (stc & STC.out_ ) params ~= "out ";
6331 if (stc & STC.ref_ ) params ~= "ref ";
6332 if (stc & STC.lazy_ ) params ~= "lazy ";
6334 // Take parameter type from the FuncInfo.
6335 params ~= format("%s.PT[%s]", myFuncInfo, i);
6337 // Declare a parameter variable.
6338 params ~= " " ~ PARAMETER_VARIABLE_ID!(i);
6341 // Add some ellipsis part if needed.
6342 auto style = variadicFunctionStyle!(func);
6343 final switch (style)
6345 case Variadic.no:
6346 break;
6348 case Variadic.c, Variadic.d:
6349 imports ~= "import core.vararg;\n";
6350 // (...) or (a, b, ...)
6351 params ~= (nparams == 0) ? "..." : ", ...";
6352 break;
6354 case Variadic.typesafe:
6355 params ~= " ...";
6356 break;
6359 return typeof(return)(imports, params);
6362 // Returns D code which enumerates n parameter variables using comma as the
6363 // separator. "a0, a1, a2, a3"
6364 string enumerateParameters(size_t n)() @property
6366 string params = "";
6368 foreach (i_; CountUp!(n))
6370 enum i = 0 + i_; // workaround
6371 if (i > 0) params ~= ", ";
6372 params ~= PARAMETER_VARIABLE_ID!(i);
6374 return params;
6380 Predefined how-policies for `AutoImplement`. These templates are also used by
6381 `BlackHole` and `WhiteHole`, respectively.
6383 template generateEmptyFunction(C, func.../+[https://issues.dlang.org/show_bug.cgi?id=4217]+/)
6385 static if (is(ReturnType!(func) == void))
6386 enum string generateEmptyFunction = q{
6388 else static if (functionAttributes!(func) & FunctionAttribute.ref_)
6389 enum string generateEmptyFunction = q{
6390 static typeof(return) dummy;
6391 return dummy;
6393 else
6394 enum string generateEmptyFunction = q{
6395 return typeof(return).init;
6400 @system unittest
6402 alias BlackHole(Base) = AutoImplement!(Base, generateEmptyFunction);
6404 interface I
6406 int foo();
6407 string bar();
6410 auto i = new BlackHole!I();
6411 // generateEmptyFunction returns the default value of the return type without doing anything
6412 assert(i.foo == 0);
6413 assert(i.bar is null);
6416 /// ditto
6417 template generateAssertTrap(C, func...)
6419 enum string generateAssertTrap =
6420 `throw new NotImplementedError("` ~ C.stringof ~ "."
6421 ~ __traits(identifier, func) ~ `");`;
6425 @system unittest
6427 import std.exception : assertThrown;
6429 alias WhiteHole(Base) = AutoImplement!(Base, generateAssertTrap);
6431 interface I
6433 int foo();
6434 string bar();
6437 auto i = new WhiteHole!I();
6438 // generateAssertTrap throws an exception for every unimplemented function of the interface
6439 assertThrown!NotImplementedError(i.foo);
6440 assertThrown!NotImplementedError(i.bar);
6443 private
6445 pragma(mangle, "_d_toObject")
6446 extern(C) pure nothrow Object typecons_d_toObject(void* p);
6450 * Avoids opCast operator overloading.
6452 private template dynamicCast(T)
6453 if (is(T == class) || is(T == interface))
6455 @trusted
6456 T dynamicCast(S)(inout S source)
6457 if (is(S == class) || is(S == interface))
6459 static if (is(Unqual!S : Unqual!T))
6461 import std.traits : QualifierOf;
6462 alias Qual = QualifierOf!S; // SharedOf or MutableOf
6463 alias TmpT = Qual!(Unqual!T);
6464 inout(TmpT) tmp = source; // bypass opCast by implicit conversion
6465 return *cast(T*)(&tmp); // + variable pointer cast + dereference
6467 else
6469 return cast(T) typecons_d_toObject(*cast(void**)(&source));
6474 @system unittest
6476 class C { @disable void opCast(T)(); }
6477 auto c = new C;
6478 static assert(!__traits(compiles, cast(Object) c));
6479 auto o = dynamicCast!Object(c);
6480 assert(c is o);
6482 interface I { @disable void opCast(T)(); Object instance(); }
6483 interface J { @disable void opCast(T)(); Object instance(); }
6484 class D : I, J { Object instance() { return this; } }
6485 I i = new D();
6486 static assert(!__traits(compiles, cast(J) i));
6487 J j = dynamicCast!J(i);
6488 assert(i.instance() is j.instance());
6492 Supports structural based typesafe conversion.
6494 If `Source` has structural conformance with the `interface` `Targets`,
6495 wrap creates an internal wrapper class which inherits `Targets` and
6496 wraps the `src` object, then returns it.
6498 `unwrap` can be used to extract objects which have been wrapped by `wrap`.
6500 template wrap(Targets...)
6501 if (Targets.length >= 1 && allSatisfy!(isMutable, Targets))
6503 import std.meta : staticMap;
6505 // strict upcast
6506 auto wrap(Source)(inout Source src) @trusted pure nothrow
6507 if (Targets.length == 1 && is(Source : Targets[0]))
6509 alias T = Select!(is(Source == shared), shared Targets[0], Targets[0]);
6510 return dynamicCast!(inout T)(src);
6512 // structural upcast
6513 template wrap(Source)
6514 if (!allSatisfy!(Bind!(isImplicitlyConvertible, Source), Targets))
6516 auto wrap(inout Source src)
6518 static assert(hasRequireMethods!(),
6519 "Source "~Source.stringof~
6520 " does not have structural conformance to "~
6521 Targets.stringof);
6523 alias T = Select!(is(Source == shared), shared Impl, Impl);
6524 return new inout T(src);
6527 template FuncInfo(string s, F)
6529 enum name = s;
6530 alias type = F;
6533 // https://issues.dlang.org/show_bug.cgi?id=12064: Remove NVI members
6534 template OnlyVirtual(members...)
6536 enum notFinal(alias T) = !__traits(isFinalFunction, T);
6537 import std.meta : Filter;
6538 alias OnlyVirtual = Filter!(notFinal, members);
6541 // Concat all Targets function members into one tuple
6542 template Concat(size_t i = 0)
6544 static if (i >= Targets.length)
6545 alias Concat = AliasSeq!();
6546 else
6548 alias Concat = AliasSeq!(OnlyVirtual!(GetOverloadedMethods!(Targets[i]), Concat!(i + 1)));
6552 // Remove duplicated functions based on the identifier name and function type covariance
6553 template Uniq(members...)
6555 static if (members.length == 0)
6556 alias Uniq = AliasSeq!();
6557 else
6559 alias func = members[0];
6560 enum name = __traits(identifier, func);
6561 alias type = FunctionTypeOf!func;
6562 template check(size_t i, mem...)
6564 static if (i >= mem.length)
6565 enum ptrdiff_t check = -1;
6566 else
6568 enum ptrdiff_t check =
6569 __traits(identifier, func) == __traits(identifier, mem[i]) &&
6570 !is(DerivedFunctionType!(type, FunctionTypeOf!(mem[i])) == void)
6571 ? i : check!(i + 1, mem);
6574 enum ptrdiff_t x = 1 + check!(0, members[1 .. $]);
6575 static if (x >= 1)
6577 alias typex = DerivedFunctionType!(type, FunctionTypeOf!(members[x]));
6578 alias remain = Uniq!(members[1 .. x], members[x + 1 .. $]);
6580 static if (remain.length >= 1 && remain[0].name == name &&
6581 !is(DerivedFunctionType!(typex, remain[0].type) == void))
6583 alias F = DerivedFunctionType!(typex, remain[0].type);
6584 alias Uniq = AliasSeq!(FuncInfo!(name, F), remain[1 .. $]);
6586 else
6587 alias Uniq = AliasSeq!(FuncInfo!(name, typex), remain);
6589 else
6591 alias Uniq = AliasSeq!(FuncInfo!(name, type), Uniq!(members[1 .. $]));
6595 alias TargetMembers = Uniq!(Concat!()); // list of FuncInfo
6596 alias SourceMembers = GetOverloadedMethods!Source; // list of function symbols
6598 // Check whether all of SourceMembers satisfy covariance target in TargetMembers
6599 template hasRequireMethods(size_t i = 0)
6601 static if (i >= TargetMembers.length)
6602 enum hasRequireMethods = true;
6603 else
6605 enum hasRequireMethods =
6606 findCovariantFunction!(TargetMembers[i], Source, SourceMembers) != -1 &&
6607 hasRequireMethods!(i + 1);
6611 // Internal wrapper class
6612 final class Impl : Structural, Targets
6614 private:
6615 Source _wrap_source;
6617 this( inout Source s) inout @safe pure nothrow { _wrap_source = s; }
6618 this(shared inout Source s) shared inout @safe pure nothrow { _wrap_source = s; }
6620 // BUG: making private should work with NVI.
6621 protected final inout(Object) _wrap_getSource() inout @trusted
6623 return dynamicCast!(inout Object)(_wrap_source);
6626 import std.conv : to;
6627 import core.lifetime : forward;
6628 template generateFun(size_t i)
6630 enum name = TargetMembers[i].name;
6631 enum fa = functionAttributes!(TargetMembers[i].type);
6632 static @property stc()
6634 string r;
6635 if (fa & FunctionAttribute.property) r ~= "@property ";
6636 if (fa & FunctionAttribute.ref_) r ~= "ref ";
6637 if (fa & FunctionAttribute.pure_) r ~= "pure ";
6638 if (fa & FunctionAttribute.nothrow_) r ~= "nothrow ";
6639 if (fa & FunctionAttribute.trusted) r ~= "@trusted ";
6640 if (fa & FunctionAttribute.safe) r ~= "@safe ";
6641 return r;
6643 static @property mod()
6645 alias type = AliasSeq!(TargetMembers[i].type)[0];
6646 string r;
6647 static if (is(type == immutable)) r ~= " immutable";
6648 else
6650 static if (is(type == shared)) r ~= " shared";
6651 static if (is(type == const)) r ~= " const";
6652 else static if (is(type == inout)) r ~= " inout";
6653 //else --> mutable
6655 return r;
6657 enum n = to!string(i);
6658 static if (fa & FunctionAttribute.property)
6660 static if (Parameters!(TargetMembers[i].type).length == 0)
6661 enum fbody = "_wrap_source."~name;
6662 else
6663 enum fbody = "_wrap_source."~name~" = forward!args";
6665 else
6667 enum fbody = "_wrap_source."~name~"(forward!args)";
6669 enum generateFun =
6670 "override "~stc~"ReturnType!(TargetMembers["~n~"].type) "
6671 ~ name~"(Parameters!(TargetMembers["~n~"].type) args) "~mod~
6672 "{ return "~fbody~"; }";
6675 public:
6676 static foreach (i; 0 .. TargetMembers.length)
6677 mixin(generateFun!i);
6681 /// ditto
6682 template wrap(Targets...)
6683 if (Targets.length >= 1 && !allSatisfy!(isMutable, Targets))
6685 import std.meta : staticMap;
6687 alias wrap = .wrap!(staticMap!(Unqual, Targets));
6690 /// ditto
6691 template unwrap(Target)
6692 if (isMutable!Target)
6694 // strict downcast
6695 auto unwrap(Source)(inout Source src) @trusted pure nothrow
6696 if (is(Target : Source))
6698 alias T = Select!(is(Source == shared), shared Target, Target);
6699 return dynamicCast!(inout T)(src);
6701 // structural downcast
6702 auto unwrap(Source)(inout Source src) @trusted pure nothrow
6703 if (!is(Target : Source))
6705 alias T = Select!(is(Source == shared), shared Target, Target);
6706 Object o = dynamicCast!(Object)(src); // remove qualifier
6709 if (auto a = dynamicCast!(Structural)(o))
6711 if (auto d = dynamicCast!(inout T)(o = a._wrap_getSource()))
6712 return d;
6714 else if (auto d = dynamicCast!(inout T)(o))
6715 return d;
6716 else
6717 break;
6718 } while (o);
6719 return null;
6723 /// ditto
6724 template unwrap(Target)
6725 if (!isMutable!Target)
6727 alias unwrap = .unwrap!(Unqual!Target);
6731 @system unittest
6733 interface Quack
6735 int quack();
6736 @property int height();
6738 interface Flyer
6740 @property int height();
6742 class Duck : Quack
6744 int quack() { return 1; }
6745 @property int height() { return 10; }
6747 class Human
6749 int quack() { return 2; }
6750 @property int height() { return 20; }
6753 Duck d1 = new Duck();
6754 Human h1 = new Human();
6756 interface Refleshable
6758 int reflesh();
6761 // does not have structural conformance
6762 static assert(!__traits(compiles, d1.wrap!Refleshable));
6763 static assert(!__traits(compiles, h1.wrap!Refleshable));
6765 // strict upcast
6766 Quack qd = d1.wrap!Quack;
6767 assert(qd is d1);
6768 assert(qd.quack() == 1); // calls Duck.quack
6769 // strict downcast
6770 Duck d2 = qd.unwrap!Duck;
6771 assert(d2 is d1);
6773 // structural upcast
6774 Quack qh = h1.wrap!Quack;
6775 assert(qh.quack() == 2); // calls Human.quack
6776 // structural downcast
6777 Human h2 = qh.unwrap!Human;
6778 assert(h2 is h1);
6780 // structural upcast (two steps)
6781 Quack qx = h1.wrap!Quack; // Human -> Quack
6782 Flyer fx = qx.wrap!Flyer; // Quack -> Flyer
6783 assert(fx.height == 20); // calls Human.height
6784 // structural downcast (two steps)
6785 Quack qy = fx.unwrap!Quack; // Flyer -> Quack
6786 Human hy = qy.unwrap!Human; // Quack -> Human
6787 assert(hy is h1);
6788 // structural downcast (one step)
6789 Human hz = fx.unwrap!Human; // Flyer -> Human
6790 assert(hz is h1);
6794 @system unittest
6796 import std.traits : FunctionAttribute, functionAttributes;
6797 interface A { int run(); }
6798 interface B { int stop(); @property int status(); }
6799 class X
6801 int run() { return 1; }
6802 int stop() { return 2; }
6803 @property int status() { return 3; }
6806 auto x = new X();
6807 auto ab = x.wrap!(A, B);
6808 A a = ab;
6809 B b = ab;
6810 assert(a.run() == 1);
6811 assert(b.stop() == 2);
6812 assert(b.status == 3);
6813 static assert(functionAttributes!(typeof(ab).status) & FunctionAttribute.property);
6816 // Internal class to support dynamic cross-casting
6817 private interface Structural
6819 inout(Object) _wrap_getSource() inout @safe pure nothrow;
6822 @system unittest
6824 class A
6826 int draw() { return 1; }
6827 int draw(int v) { return v; }
6829 int draw() const { return 2; }
6830 int draw() shared { return 3; }
6831 int draw() shared const { return 4; }
6832 int draw() immutable { return 5; }
6834 interface Drawable
6836 int draw();
6837 int draw() const;
6838 int draw() shared;
6839 int draw() shared const;
6840 int draw() immutable;
6842 interface Drawable2
6844 int draw(int v);
6847 auto ma = new A();
6848 auto sa = new shared A();
6849 auto ia = new immutable A();
6851 Drawable md = ma.wrap!Drawable;
6852 const Drawable cd = ma.wrap!Drawable;
6853 shared Drawable sd = sa.wrap!Drawable;
6854 shared const Drawable scd = sa.wrap!Drawable;
6855 immutable Drawable id = ia.wrap!Drawable;
6856 assert( md.draw() == 1);
6857 assert( cd.draw() == 2);
6858 assert( sd.draw() == 3);
6859 assert(scd.draw() == 4);
6860 assert( id.draw() == 5);
6863 Drawable2 d = ma.wrap!Drawable2;
6864 static assert(!__traits(compiles, d.draw()));
6865 assert(d.draw(10) == 10);
6869 // https://issues.dlang.org/show_bug.cgi?id=10377
6870 @system unittest
6872 import std.range, std.algorithm;
6874 interface MyInputRange(T)
6876 @property T front();
6877 void popFront();
6878 @property bool empty();
6881 //auto o = iota(0,10,1).inputRangeObject();
6882 //pragma(msg, __traits(allMembers, typeof(o)));
6883 auto r = iota(0,10,1).inputRangeObject().wrap!(MyInputRange!int)();
6884 assert(equal(r, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]));
6887 // https://issues.dlang.org/show_bug.cgi?id=10536
6888 @system unittest
6890 interface Interface
6892 int foo();
6894 class Pluggable
6896 int foo() { return 1; }
6897 @disable void opCast(T, this X)(); // !
6900 Interface i = new Pluggable().wrap!Interface;
6901 assert(i.foo() == 1);
6903 @system unittest
6905 // Enhancement 10538
6906 interface Interface
6908 int foo();
6909 int bar(int);
6911 class Pluggable
6913 int opDispatch(string name, A...)(A args) { return 100; }
6916 Interface i = wrap!Interface(new Pluggable());
6917 assert(i.foo() == 100);
6918 assert(i.bar(10) == 100);
6921 // https://issues.dlang.org/show_bug.cgi?id=12064
6922 @system unittest
6924 interface I
6926 int foo();
6927 final int nvi1(){return foo();}
6930 interface J
6932 int bar();
6933 final int nvi2(){return bar();}
6936 class Baz
6938 int foo() { return 42;}
6939 int bar() { return 12064;}
6942 auto baz = new Baz();
6943 auto foobar = baz.wrap!(I, J)();
6944 assert(foobar.nvi1 == 42);
6945 assert(foobar.nvi2 == 12064);
6948 // Make a tuple of non-static function symbols
6949 package template GetOverloadedMethods(T)
6951 import std.meta : Filter;
6953 alias allMembers = __traits(allMembers, T);
6954 template follows(size_t i = 0)
6956 static if (i >= allMembers.length)
6958 alias follows = AliasSeq!();
6960 else static if (!__traits(compiles, mixin("T."~allMembers[i])))
6962 alias follows = follows!(i + 1);
6964 else
6966 enum name = allMembers[i];
6968 template isMethod(alias f)
6970 static if (is(typeof(&f) F == F*) && is(F == function))
6971 enum isMethod = !__traits(isStaticFunction, f);
6972 else
6973 enum isMethod = false;
6975 alias follows = AliasSeq!(
6976 Filter!(isMethod, __traits(getOverloads, T, name)),
6977 follows!(i + 1));
6980 alias GetOverloadedMethods = follows!();
6982 // find a function from Fs that has same identifier and covariant type with f
6983 private template findCovariantFunction(alias finfo, Source, Fs...)
6985 template check(size_t i = 0)
6987 static if (i >= Fs.length)
6988 enum ptrdiff_t check = -1;
6989 else
6991 enum ptrdiff_t check =
6992 (finfo.name == __traits(identifier, Fs[i])) &&
6993 isCovariantWith!(FunctionTypeOf!(Fs[i]), finfo.type)
6994 ? i : check!(i + 1);
6997 enum x = check!();
6998 static if (x == -1 && is(typeof(Source.opDispatch)))
7000 alias Params = Parameters!(finfo.type);
7001 enum ptrdiff_t findCovariantFunction =
7002 is(typeof(( Source).init.opDispatch!(finfo.name)(Params.init))) ||
7003 is(typeof(( const Source).init.opDispatch!(finfo.name)(Params.init))) ||
7004 is(typeof(( immutable Source).init.opDispatch!(finfo.name)(Params.init))) ||
7005 is(typeof(( shared Source).init.opDispatch!(finfo.name)(Params.init))) ||
7006 is(typeof((shared const Source).init.opDispatch!(finfo.name)(Params.init)))
7007 ? ptrdiff_t.max : -1;
7009 else
7010 enum ptrdiff_t findCovariantFunction = x;
7013 private enum TypeModifier
7015 mutable = 0, // type is mutable
7016 const_ = 1, // type is const
7017 immutable_ = 2, // type is immutable
7018 shared_ = 4, // type is shared
7019 inout_ = 8, // type is wild
7021 private template TypeMod(T)
7023 static if (is(T == immutable))
7025 enum mod1 = TypeModifier.immutable_;
7026 enum mod2 = 0;
7028 else
7030 enum mod1 = is(T == shared) ? TypeModifier.shared_ : 0;
7031 static if (is(T == const))
7032 enum mod2 = TypeModifier.const_;
7033 else static if (is(T == inout))
7034 enum mod2 = TypeModifier.inout_;
7035 else
7036 enum mod2 = TypeModifier.mutable;
7038 enum TypeMod = cast(TypeModifier)(mod1 | mod2);
7041 @system unittest
7043 template UnittestFuncInfo(alias f)
7045 enum name = __traits(identifier, f);
7046 alias type = FunctionTypeOf!f;
7049 class A
7051 int draw() { return 1; }
7052 @property int value() { return 2; }
7053 final int run() { return 3; }
7055 alias methods = GetOverloadedMethods!A;
7057 alias int F1();
7058 alias @property int F2();
7059 alias string F3();
7060 alias nothrow @trusted uint F4();
7061 alias int F5(Object);
7062 alias bool F6(Object);
7063 static assert(methods.length == 3 + 4);
7064 static assert(__traits(identifier, methods[0]) == "draw" && is(typeof(&methods[0]) == F1*));
7065 static assert(__traits(identifier, methods[1]) == "value" && is(typeof(&methods[1]) == F2*));
7066 static assert(__traits(identifier, methods[2]) == "run" && is(typeof(&methods[2]) == F1*));
7068 int draw();
7069 @property int value();
7070 void opEquals();
7071 int nomatch();
7072 static assert(findCovariantFunction!(UnittestFuncInfo!draw, A, methods) == 0);
7073 static assert(findCovariantFunction!(UnittestFuncInfo!value, A, methods) == 1);
7074 static assert(findCovariantFunction!(UnittestFuncInfo!opEquals, A, methods) == -1);
7075 static assert(findCovariantFunction!(UnittestFuncInfo!nomatch, A, methods) == -1);
7077 // considering opDispatch
7078 class B
7080 void opDispatch(string name, A...)(A) {}
7082 alias methodsB = GetOverloadedMethods!B;
7083 static assert(findCovariantFunction!(UnittestFuncInfo!draw, B, methodsB) == ptrdiff_t.max);
7084 static assert(findCovariantFunction!(UnittestFuncInfo!value, B, methodsB) == ptrdiff_t.max);
7085 static assert(findCovariantFunction!(UnittestFuncInfo!opEquals, B, methodsB) == ptrdiff_t.max);
7086 static assert(findCovariantFunction!(UnittestFuncInfo!nomatch, B, methodsB) == ptrdiff_t.max);
7089 package template DerivedFunctionType(T...)
7091 static if (!T.length)
7093 alias DerivedFunctionType = void;
7095 else static if (T.length == 1)
7097 static if (is(T[0] == function))
7099 alias DerivedFunctionType = T[0];
7101 else
7103 alias DerivedFunctionType = void;
7106 else static if (is(T[0] P0 == function) && is(T[1] P1 == function))
7108 alias FA = FunctionAttribute;
7110 alias F0 = T[0], R0 = ReturnType!F0, PSTC0 = ParameterStorageClassTuple!F0;
7111 alias F1 = T[1], R1 = ReturnType!F1, PSTC1 = ParameterStorageClassTuple!F1;
7112 enum FA0 = functionAttributes!F0;
7113 enum FA1 = functionAttributes!F1;
7115 template CheckParams(size_t i = 0)
7117 static if (i >= P0.length)
7118 enum CheckParams = true;
7119 else
7121 enum CheckParams = (is(P0[i] == P1[i]) && PSTC0[i] == PSTC1[i]) &&
7122 CheckParams!(i + 1);
7125 static if (R0.sizeof == R1.sizeof && !is(CommonType!(R0, R1) == void) &&
7126 P0.length == P1.length && CheckParams!() && TypeMod!F0 == TypeMod!F1 &&
7127 variadicFunctionStyle!F0 == variadicFunctionStyle!F1 &&
7128 functionLinkage!F0 == functionLinkage!F1 &&
7129 ((FA0 ^ FA1) & (FA.ref_ | FA.property)) == 0)
7131 alias R = Select!(is(R0 : R1), R0, R1);
7132 alias FX = FunctionTypeOf!(R function(P0));
7133 // @system is default
7134 alias FY = SetFunctionAttributes!(FX, functionLinkage!F0, (FA0 | FA1) & ~FA.system);
7135 alias DerivedFunctionType = DerivedFunctionType!(FY, T[2 .. $]);
7137 else
7138 alias DerivedFunctionType = void;
7140 else
7141 alias DerivedFunctionType = void;
7143 @safe unittest
7145 // attribute covariance
7146 alias int F1();
7147 static assert(is(DerivedFunctionType!(F1, F1) == F1));
7148 alias int F2() pure nothrow;
7149 static assert(is(DerivedFunctionType!(F1, F2) == F2));
7150 alias int F3() @safe;
7151 alias int F23() @safe pure nothrow;
7152 static assert(is(DerivedFunctionType!(F2, F3) == F23));
7154 // return type covariance
7155 alias long F4();
7156 static assert(is(DerivedFunctionType!(F1, F4) == void));
7157 class C {}
7158 class D : C {}
7159 alias C F5();
7160 alias D F6();
7161 static assert(is(DerivedFunctionType!(F5, F6) == F6));
7162 alias typeof(null) F7();
7163 alias int[] F8();
7164 alias int* F9();
7165 static assert(is(DerivedFunctionType!(F5, F7) == F7));
7166 static assert(is(DerivedFunctionType!(F7, F8) == void));
7167 static assert(is(DerivedFunctionType!(F7, F9) == F7));
7169 // variadic type equality
7170 alias int F10(int);
7171 alias int F11(int...);
7172 alias int F12(int, ...);
7173 static assert(is(DerivedFunctionType!(F10, F11) == void));
7174 static assert(is(DerivedFunctionType!(F10, F12) == void));
7175 static assert(is(DerivedFunctionType!(F11, F12) == void));
7177 // linkage equality
7178 alias extern(C) int F13(int);
7179 alias extern(D) int F14(int);
7180 alias extern(Windows) int F15(int);
7181 static assert(is(DerivedFunctionType!(F13, F14) == void));
7182 static assert(is(DerivedFunctionType!(F13, F15) == void));
7183 static assert(is(DerivedFunctionType!(F14, F15) == void));
7185 // ref & @property equality
7186 alias int F16(int);
7187 alias ref int F17(int);
7188 alias @property int F18(int);
7189 static assert(is(DerivedFunctionType!(F16, F17) == void));
7190 static assert(is(DerivedFunctionType!(F16, F18) == void));
7191 static assert(is(DerivedFunctionType!(F17, F18) == void));
7194 package template Bind(alias Template, args1...)
7196 alias Bind(args2...) = Template!(args1, args2);
7201 Options regarding auto-initialization of a `SafeRefCounted` object (see
7202 the definition of `SafeRefCounted` below).
7204 enum RefCountedAutoInitialize
7206 /// Do not auto-initialize the object
7208 /// Auto-initialize the object
7209 yes,
7213 @system unittest
7215 import core.exception : AssertError;
7216 import std.exception : assertThrown;
7218 struct Foo
7220 int a = 42;
7223 SafeRefCounted!(Foo, RefCountedAutoInitialize.yes) rcAuto;
7224 SafeRefCounted!(Foo, RefCountedAutoInitialize.no) rcNoAuto;
7226 assert(rcAuto.refCountedPayload.a == 42);
7228 assertThrown!AssertError(rcNoAuto.refCountedPayload);
7229 rcNoAuto.refCountedStore.ensureInitialized;
7230 assert(rcNoAuto.refCountedPayload.a == 42);
7233 // Same the above but for old RefCounted and not documented
7234 @system unittest
7236 import core.exception : AssertError;
7237 import std.exception : assertThrown;
7239 struct Foo
7241 int a = 42;
7244 RefCounted!(Foo, RefCountedAutoInitialize.yes) rcAuto;
7245 RefCounted!(Foo, RefCountedAutoInitialize.no) rcNoAuto;
7247 assert(rcAuto.refCountedPayload.a == 42);
7249 assertThrown!AssertError(rcNoAuto.refCountedPayload);
7250 rcNoAuto.refCountedStore.ensureInitialized;
7251 assert(rcNoAuto.refCountedPayload.a == 42);
7255 Defines a reference-counted object containing a `T` value as
7256 payload.
7258 An instance of `SafeRefCounted` is a reference to a structure,
7259 which is referred to as the $(I store), or $(I storage implementation
7260 struct) in this documentation. The store contains a reference count
7261 and the `T` payload. `SafeRefCounted` uses `malloc` to allocate
7262 the store. As instances of `SafeRefCounted` are copied or go out of
7263 scope, they will automatically increment or decrement the reference
7264 count. When the reference count goes down to zero, `SafeRefCounted`
7265 will call `destroy` against the payload and call `free` to
7266 deallocate the store. If the `T` payload contains any references
7267 to GC-allocated memory, then `SafeRefCounted` will add it to the GC memory
7268 that is scanned for pointers, and remove it from GC scanning before
7269 `free` is called on the store.
7271 One important consequence of `destroy` is that it will call the
7272 destructor of the `T` payload. GC-managed references are not
7273 guaranteed to be valid during a destructor call, but other members of
7274 `T`, such as file handles or pointers to `malloc` memory, will
7275 still be valid during the destructor call. This allows the `T` to
7276 deallocate or clean up any non-GC resources immediately after the
7277 reference count has reached zero.
7279 Without -preview=dip1000, `SafeRefCounted` is unsafe and should be
7280 used with care. No references to the payload should be escaped outside
7281 the `SafeRefCounted` object.
7283 With -preview=dip1000, `SafeRefCounted` is safe if it's payload is accessed only
7284 with the $(LREF borrow) function. Scope semantics can also prevent accidental
7285 escaping of `refCountedPayload`, but it's still up to the user to not destroy
7286 the last counted reference while the payload is in use. Due to that,
7287 `refCountedPayload` remains accessible only in `@system` code.
7289 The `autoInit` option makes the object ensure the store is
7290 automatically initialized. Leaving $(D autoInit ==
7291 RefCountedAutoInitialize.yes) (the default option) is convenient but
7292 has the cost of a test whenever the payload is accessed. If $(D
7293 autoInit == RefCountedAutoInitialize.no), user code must call either
7294 `refCountedStore.isInitialized` or `refCountedStore.ensureInitialized`
7295 before attempting to access the payload. Not doing so results in null
7296 pointer dereference.
7298 If `T.this()` is annotated with `@disable` then `autoInit` must be
7299 `RefCountedAutoInitialize.no` in order to compile.
7301 See_Also:
7302 $(LREF RefCounted)
7304 struct SafeRefCounted(T, RefCountedAutoInitialize autoInit =
7305 RefCountedAutoInitialize.yes)
7306 if (!is(T == class) && !(is(T == interface)))
7308 version (D_BetterC)
7310 private enum enableGCScan = false;
7312 else
7314 private enum enableGCScan = hasIndirections!T;
7317 extern(C) private pure nothrow @nogc static
7319 pragma(mangle, "free") void pureFree( void *ptr );
7320 static if (enableGCScan)
7321 import core.memory : GC;
7324 pragma(inline, true) private void checkInit()()
7325 if (autoInit == RefCountedAutoInitialize.yes)
7327 _refCounted.ensureInitialized();
7330 pragma(inline, true) private void checkInit()() inout
7331 if (autoInit == RefCountedAutoInitialize.no)
7333 assert(_refCounted.isInitialized,
7334 "Attempted to use an uninitialized payload.");
7337 /// `SafeRefCounted` storage implementation.
7338 struct RefCountedStore
7340 private struct Impl
7342 T _payload;
7343 size_t _count;
7346 private Impl* _store;
7348 private void initialize(A...)(auto ref A args)
7350 import core.lifetime : emplace, forward;
7352 allocateStore();
7353 version (D_Exceptions) scope(failure) () @trusted { deallocateStore(); }();
7354 emplace(&_store._payload, forward!args);
7355 _store._count = 1;
7358 private void move(ref T source) nothrow pure
7360 import std.algorithm.mutation : moveEmplace;
7362 allocateStore();
7363 () @trusted { moveEmplace(source, _store._payload); }();
7364 _store._count = 1;
7367 // 'nothrow': can only generate an Error
7368 private void allocateStore() nothrow pure
7370 static if (enableGCScan)
7372 import std.internal.memory : enforceCalloc;
7373 auto ptr = enforceCalloc(1, Impl.sizeof);
7374 _store = () @trusted { return cast(Impl*) ptr; }();
7375 () @trusted { GC.addRange(&_store._payload, T.sizeof); }();
7377 else
7379 import std.internal.memory : enforceMalloc;
7380 auto ptr = enforceMalloc(Impl.sizeof);
7381 _store = () @trusted { return cast(Impl*) ptr; }();
7385 private void deallocateStore() nothrow pure
7387 static if (enableGCScan)
7389 GC.removeRange(&this._store._payload);
7391 pureFree(_store);
7392 _store = null;
7396 Returns `true` if and only if the underlying store has been
7397 allocated and initialized.
7399 @property nothrow @safe pure @nogc
7400 bool isInitialized() const
7402 return _store !is null;
7406 Returns underlying reference count if it is allocated and initialized
7407 (a positive integer), and `0` otherwise.
7409 @property nothrow @safe pure @nogc
7410 size_t refCount() const
7412 return isInitialized ? _store._count : 0;
7416 Makes sure the payload was properly initialized. Such a
7417 call is typically inserted before using the payload.
7419 This function is unavailable if `T.this()` is annotated with
7420 `@disable`.
7422 @safe pure nothrow
7423 void ensureInitialized()()
7425 // By checking for `@disable this()` and failing early we can
7426 // produce a clearer error message.
7427 static assert(__traits(compiles, { static T t; }),
7428 "Cannot automatically initialize `" ~ fullyQualifiedName!T ~
7429 "` because `" ~ fullyQualifiedName!T ~
7430 ".this()` is annotated with `@disable`.");
7431 if (!isInitialized) initialize();
7435 RefCountedStore _refCounted;
7437 /// Returns storage implementation struct.
7438 @property nothrow @safe
7439 ref inout(RefCountedStore) refCountedStore() inout
7441 return _refCounted;
7445 Constructor that initializes the payload.
7447 Postcondition: `refCountedStore.isInitialized`
7449 this(A...)(auto ref A args) if (A.length > 0)
7452 assert(refCountedStore.isInitialized);
7456 import core.lifetime : forward;
7457 _refCounted.initialize(forward!args);
7460 /// Ditto
7461 this(return scope T val)
7463 _refCounted.move(val);
7467 Constructor that tracks the reference count appropriately. If $(D
7468 !refCountedStore.isInitialized), does nothing.
7470 this(this) @safe pure nothrow @nogc
7472 if (!_refCounted.isInitialized) return;
7473 ++_refCounted._store._count;
7477 Destructor that tracks the reference count appropriately. If $(D
7478 !refCountedStore.isInitialized), does nothing. When the reference count goes
7479 down to zero, calls `destroy` agaist the payload and calls `free`
7480 to deallocate the corresponding resource.
7482 ~this()
7484 import std.traits : dip1000Enabled;
7486 // This prevents the same reference from decrementing the count twice.
7487 scope(exit) _refCounted = _refCounted.init;
7489 if (!_refCounted.isInitialized) return;
7490 assert(_refCounted._store._count > 0);
7491 if (--_refCounted._store._count) return;
7492 // Done, destroy and deallocate
7493 .destroy(_refCounted._store._payload);
7495 static if (dip1000Enabled)
7497 () @trusted { _refCounted.deallocateStore(); }();
7499 else _refCounted.deallocateStore();
7503 Assignment operators.
7505 Note: You may not assign a new payload to an uninitialized SafeRefCounted, if
7506 auto initialization is off. Assigning another counted reference is still okay.
7508 void opAssign(typeof(this) rhs)
7510 import std.algorithm.mutation : swap;
7512 swap(_refCounted._store, rhs._refCounted._store);
7515 /// Ditto
7516 void opAssign(T rhs)
7518 import std.algorithm.mutation : move;
7520 checkInit();
7521 move(rhs, _refCounted._store._payload);
7524 //version to have a single properly ddoc'ed function (w/ correct sig)
7525 version (StdDdoc)
7528 Returns a reference to the payload. If (autoInit ==
7529 RefCountedAutoInitialize.yes), calls $(D
7530 refCountedStore.ensureInitialized). Otherwise, just issues $(D
7531 assert(refCountedStore.isInitialized)). Used with $(D alias
7532 refCountedPayload this;), so callers can just use the `SafeRefCounted`
7533 object as a `T`.
7535 $(BLUE The first overload exists only if $(D autoInit == RefCountedAutoInitialize.yes).)
7536 So if $(D autoInit == RefCountedAutoInitialize.no)
7537 or called for a constant or immutable object, then
7538 `refCountedPayload` will also be qualified as nothrow
7539 (but will still assert if not initialized).
7541 @property @system
7542 ref T refCountedPayload() return;
7544 /// ditto
7545 @property nothrow @system pure @nogc
7546 ref inout(T) refCountedPayload() inout return;
7548 else
7550 static if (autoInit == RefCountedAutoInitialize.yes)
7552 //Can't use inout here because of potential mutation
7553 @property @system
7554 ref T refCountedPayload() return
7556 checkInit();
7557 return _refCounted._store._payload;
7560 else
7562 @property nothrow @system pure @nogc
7563 ref inout(T) refCountedPayload() inout return
7565 checkInit();
7566 return _refCounted._store._payload;
7572 Returns a reference to the payload. If (autoInit ==
7573 RefCountedAutoInitialize.yes), calls $(D
7574 refCountedStore.ensureInitialized). Otherwise, just issues $(D
7575 assert(refCountedStore.isInitialized)).
7577 alias refCountedPayload this;
7579 static if (is(T == struct) && !is(typeof((ref T t) => t.toString())))
7581 string toString(this This)()
7583 import std.conv : to;
7585 static if (autoInit)
7586 return to!string(refCountedPayload);
7587 else
7589 if (!_refCounted.isInitialized)
7590 return This.stringof ~ "(RefCountedStore(null))";
7591 else
7592 return to!string(_refCounted._store._payload);
7599 @betterC pure @system nothrow @nogc unittest
7601 // A pair of an `int` and a `size_t` - the latter being the
7602 // reference count - will be dynamically allocated
7603 auto rc1 = SafeRefCounted!int(5);
7604 assert(rc1 == 5);
7605 // No more allocation, add just one extra reference count
7606 auto rc2 = rc1;
7607 // Reference semantics
7608 rc2 = 42;
7609 assert(rc1 == 42);
7610 // the pair will be freed when rc1 and rc2 go out of scope
7613 // This test can't be betterC because the test extractor won't see the private
7614 // `initialize` method accessed here
7615 pure @safe nothrow @nogc unittest
7617 auto rc1 = SafeRefCounted!(int, RefCountedAutoInitialize.no)(5);
7618 rc1._refCounted.initialize();
7621 pure @system unittest
7623 foreach (MyRefCounted; AliasSeq!(SafeRefCounted, RefCounted))
7625 MyRefCounted!int* p;
7626 auto rc1 = MyRefCounted!int(5);
7627 p = &rc1;
7628 assert(rc1 == 5);
7629 assert(rc1._refCounted._store._count == 1);
7631 auto rc2 = rc1;
7632 assert(rc1._refCounted._store._count == 2);
7633 // Reference semantics
7634 rc2 = 42;
7635 assert(rc1 == 42);
7636 rc2 = rc2;
7637 assert(rc2._refCounted._store._count == 2);
7638 rc1 = rc2;
7639 assert(rc1._refCounted._store._count == 2);
7641 // Artificially end scope of rc1 by calling ~this() explicitly
7642 rc1.__xdtor();
7643 assert(p._refCounted._store == null);
7645 // [Safe]RefCounted as a member
7646 struct A
7648 MyRefCounted!int x;
7649 this(int y)
7651 x._refCounted.initialize(y);
7653 A copy()
7655 auto another = this;
7656 return another;
7659 auto a = A(4);
7660 auto b = a.copy();
7661 assert(a.x._refCounted._store._count == 2,
7662 "https://issues.dlang.org/show_bug.cgi?id=4356 still unfixed");
7666 @betterC pure @safe nothrow @nogc unittest
7668 import std.algorithm.mutation : swap;
7670 SafeRefCounted!int p1, p2;
7671 swap(p1, p2);
7674 // Same as above but for old RefCounted and not @safe
7675 @betterC pure @system nothrow @nogc unittest
7677 import std.algorithm.mutation : swap;
7679 RefCounted!int p1, p2;
7680 swap(p1, p2);
7683 // https://issues.dlang.org/show_bug.cgi?id=6606
7684 @betterC @safe pure nothrow @nogc unittest
7686 union U {
7687 size_t i;
7688 void* p;
7691 struct S {
7692 U u;
7695 alias SRC = SafeRefCounted!S;
7698 // Same as above but for old RefCounted and not @safe
7699 @betterC @system pure nothrow @nogc unittest
7701 union U {
7702 size_t i;
7703 void* p;
7706 struct S {
7707 U u;
7710 alias SRC = RefCounted!S;
7713 // https://issues.dlang.org/show_bug.cgi?id=6436
7714 @betterC @system pure unittest
7716 import std.meta : AliasSeq;
7717 struct S
7719 this(int rval) { assert(rval == 1); }
7720 this(ref int lval) { assert(lval == 3); ++lval; }
7723 foreach (MyRefCounted; AliasSeq!(SafeRefCounted, RefCounted))
7725 auto s1 = MyRefCounted!S(1);
7726 int lval = 3;
7727 auto s2 = MyRefCounted!S(lval);
7728 assert(lval == 4);
7732 // gc_addRange coverage
7733 @betterC @safe pure unittest
7735 struct S { int* p; }
7737 auto s = SafeRefCounted!S(null);
7740 // Same as above but for old RefCounted and not @safe
7741 @betterC @system pure unittest
7743 struct S { int* p; }
7745 auto s = RefCounted!S(null);
7748 @betterC @system pure nothrow @nogc unittest
7750 import std.meta : AliasSeq;
7751 foreach (MyRefCounted; AliasSeq!(SafeRefCounted, RefCounted))
7753 MyRefCounted!int a;
7754 a = 5; //This should not assert
7755 assert(a == 5);
7757 MyRefCounted!int b;
7758 b = a; //This should not assert either
7759 assert(b == 5);
7761 MyRefCounted!(int*) c;
7765 // https://issues.dlang.org/show_bug.cgi?id=21638
7766 @betterC @system pure nothrow @nogc unittest
7768 import std.meta : AliasSeq;
7769 static struct NoDefaultCtor
7771 @disable this();
7772 this(int x) @nogc nothrow pure { this.x = x; }
7773 int x;
7776 foreach (MyRefCounted; AliasSeq!(SafeRefCounted, RefCounted))
7778 auto rc = MyRefCounted!(NoDefaultCtor, RefCountedAutoInitialize.no)(5);
7779 assert(rc.x == 5);
7783 // https://issues.dlang.org/show_bug.cgi?id=20502
7784 @system unittest
7786 alias Types = AliasSeq!(SafeRefCounted, RefCounted);
7787 alias funcs = AliasSeq!(safeRefCounted, refCounted);
7788 static foreach (aliasI; 0 .. 2)
7790 alias MyRefCounted = Types[aliasI];
7791 alias myRefCounted = funcs[aliasI];
7792 import std.conv : to;
7794 // Check that string conversion is transparent for refcounted
7795 // structs that do not have either toString or alias this.
7796 static struct A { Object a; }
7797 auto a = A(new Object());
7798 auto r = myRefCounted(a);
7799 assert(to!string(r) == to!string(a));
7800 assert(to!string(cast(const) r) == to!string(cast(const) a));
7801 // Check that string conversion is still transparent for refcounted
7802 // structs that have alias this.
7803 static struct B { int b; alias b this; }
7804 static struct C { B b; alias b this; }
7805 assert(to!string(myRefCounted(C(B(123)))) == to!string(C(B(123))));
7806 // https://issues.dlang.org/show_bug.cgi?id=22093
7807 // Check that uninitialized refcounted structs that previously could be
7808 // converted to strings still can be.
7809 alias R = typeof(r);
7810 R r2;
7811 cast(void) (((const ref R a) => to!string(a))(r2));
7812 cast(void) to!string(MyRefCounted!(A, RefCountedAutoInitialize.no).init);
7816 // We tried to make `refCountedPayload` `@safe` in
7817 // https://github.com/dlang/phobos/pull/8368 . It proved impossible, but it may
7818 // be possible in the future. This test checks for false `@safe` issues we
7819 // encountered.
7820 @safe unittest
7822 struct Container
7824 int[] data;
7827 int[] getArr1 (scope Container local)
7829 // allowed because the argument is inferred as return scope.
7830 return local.data;
7833 int[] getArr2 (scope Container local)
7835 SafeRefCounted!Container rc = local;
7836 // Escapes a reference to expired reference counted struct
7837 // don't do this!
7838 return rc.refCountedPayload().data;
7841 int destroyFirstAndUseLater()
7843 auto rc = SafeRefCounted!int(123);
7844 int* ptr = &rc.refCountedPayload();
7845 destroy(rc);
7846 return *ptr;
7849 // This is here mainly to test that safety gets inferred correctly for the
7850 // next tests
7851 static assert(isSafe!getArr1);
7852 // https://github.com/dlang/phobos/pull/8101#issuecomment-843017282
7853 // This got apparently fixed automatically by compiler updates.
7854 static assert(!isSafe!getArr2);
7855 // As of writing, this is the issue that is still preventing payload access
7856 // from being `@safe`
7857 static assert(!isSafe!destroyFirstAndUseLater);
7861 Borrows the payload of $(LREF SafeRefCounted) for use in `fun`. Inferred as `@safe`
7862 if `fun` is `@safe` and does not escape a reference to the payload.
7863 The reference count will be incremented for the duration of the operation,
7864 so destroying the last reference will not leave dangling references in
7865 `fun`.
7867 Params:
7868 fun = A callable accepting the payload either by value or by reference.
7869 refCount = The counted reference to the payload.
7870 Returns:
7871 The return value of `fun`, if any. `ref` in the return value will be
7872 forwarded.
7873 Issues:
7874 For yet unknown reason, code that uses this function with UFCS syntax
7875 will not be inferred as `@safe`. It will still compile if the code is
7876 explicitly marked `@safe` and nothing in `fun` prevents that.
7878 template borrow(alias fun)
7880 import std.functional : unaryFun;
7882 auto ref borrow(RC)(RC refCount) if
7884 isInstanceOf!(SafeRefCounted, RC)
7885 && is(typeof(unaryFun!fun(refCount.refCountedPayload)))
7888 refCount.checkInit();
7890 // If `fun` escapes a reference to the payload, it will be inferred
7891 // as unsafe due to the scope storage class here.
7892 scope plPtr = &refCount._refCounted._store._payload;
7893 return unaryFun!fun(*plPtr);
7895 // We destroy our copy of the reference here, automatically destroying
7896 // the payload if `fun` destroyed the last reference outside.
7900 /// This example can be marked `@safe` with `-preview=dip1000`.
7901 @safe pure nothrow unittest
7903 auto rcInt = safeRefCounted(5);
7904 assert(rcInt.borrow!(theInt => theInt) == 5);
7905 auto sameInt = rcInt;
7906 assert(sameInt.borrow!"a" == 5);
7908 // using `ref` in the function
7909 auto arr = [0, 1, 2, 3, 4, 5, 6];
7910 sameInt.borrow!(ref (x) => arr[x]) = 10;
7911 assert(arr == [0, 1, 2, 3, 4, 10, 6]);
7913 // modifying the payload via an alias
7914 sameInt.borrow!"a*=2";
7915 assert(rcInt.borrow!"a" == 10);
7918 // Some memory safety penetration testing.
7919 @system unittest
7921 int* globalPtr;
7922 int torpedoesFired = 0;
7923 struct Destroyer { ~this() @safe { torpedoesFired++; } }
7925 alias RcInt = typeof(safeRefCounted(0));
7926 auto standardUsage(RcInt arg)
7928 return borrow!((ref x) => x)(arg);
7930 ref harmlessRefReturn(RcInt arg)
7932 return borrow!(ref (ref x) => *globalPtr = x)(arg);
7934 ref problematicRefReturn(RcInt arg)
7936 return borrow!(ref (ref x) => x)(arg);
7938 auto sideChannelEscape(RcInt arg)
7940 return borrow!((ref x)
7942 globalPtr = &x;
7943 return x;
7944 })(arg);
7946 auto destroyDuringApply()
7948 auto rc = safeRefCounted(Destroyer());
7949 return borrow!((ref x)
7951 // Destroys the last reference to the payload, decrementing it's
7952 // reference count.
7953 rc.__dtor();
7954 // Destroy again! rc should be set to it's init value so that this
7955 // won't decrement the reference count of the original payload.
7956 rc.__dtor();
7957 // The internal reference count increment done for duration of
7958 // `apply` should make sure that the payload destructor is not yet
7959 // run, and this value thus not incremented.
7960 return torpedoesFired;
7961 })(rc);
7964 // First, let's verify the dangerous functions really do what they are
7965 // supposed to do.
7966 auto testRc = safeRefCounted(42);
7967 assert(sideChannelEscape(testRc) == 42);
7968 assert(&problematicRefReturn(testRc) == globalPtr);
7970 // Now, are the @safe attributes inferred correctly?
7971 assert(isSafe!standardUsage);
7972 assert(isSafe!harmlessRefReturn);
7973 assert(!isSafe!problematicRefReturn);
7974 assert(!isSafe!sideChannelEscape);
7975 assert(isSafe!destroyDuringApply);
7977 // Finally, we test protection against early destruction during `apply`.
7978 auto torpedoesUpToReturn = destroyDuringApply();
7979 assert(torpedoesFired == torpedoesUpToReturn + 1);
7983 * Initializes a `SafeRefCounted` with `val`. The template parameter
7984 * `T` of `SafeRefCounted` is inferred from `val`.
7985 * This function can be used to move non-copyable values to the heap.
7986 * It also disables the `autoInit` option of `SafeRefCounted`.
7988 * Params:
7989 * val = The value to be reference counted
7990 * Returns:
7991 * An initialized `SafeRefCounted` containing `val`.
7992 * See_Also:
7993 * $(LREF refCounted)
7994 * $(HTTP en.cppreference.com/w/cpp/memory/shared_ptr/make_shared, C++'s make_shared)
7996 SafeRefCounted!(T, RefCountedAutoInitialize.no) safeRefCounted(T)(T val)
7998 typeof(return) res;
7999 res._refCounted.move(val);
8000 return res;
8004 @system unittest
8006 static struct File
8008 static size_t nDestroyed;
8009 string name;
8010 @disable this(this); // not copyable
8011 ~this() { name = null; ++nDestroyed; }
8014 auto file = File("name");
8015 assert(file.name == "name");
8016 // file cannot be copied and has unique ownership
8017 static assert(!__traits(compiles, {auto file2 = file;}));
8019 assert(File.nDestroyed == 0);
8021 // make the file ref counted to share ownership
8022 // Note:
8023 // We write a compound statement (brace-delimited scope) in which all `SafeRefCounted!File` handles are created and deleted.
8024 // This allows us to see (after the scope) what happens after all handles have been destroyed.
8026 // We move the content of `file` to a separate (and heap-allocated) `File` object,
8027 // managed-and-accessed via one-or-multiple (initially: one) `SafeRefCounted!File` objects ("handles").
8028 // This "moving":
8029 // (1) invokes `file`'s destructor (=> `File.nDestroyed` is incremented from 0 to 1 and `file.name` becomes `null`);
8030 // (2) overwrites `file` with `File.init` (=> `file.name` becomes `null`).
8031 // It appears that writing `name = null;` in the destructor is redundant,
8032 // but please note that (2) is only performed if `File` defines a destructor (or post-blit operator),
8033 // and in the absence of the `nDestroyed` instrumentation there would have been no reason to define a destructor.
8034 import std.algorithm.mutation : move;
8035 auto rcFile = safeRefCounted(move(file));
8036 assert(rcFile.name == "name");
8037 assert(File.nDestroyed == 1);
8038 assert(file.name == null);
8040 // We create another `SafeRefCounted!File` handle to the same separate `File` object.
8041 // While any of the handles is still alive, the `File` object is kept alive (=> `File.nDestroyed` is not modified).
8042 auto rcFile2 = rcFile;
8043 assert(rcFile.refCountedStore.refCount == 2);
8044 assert(File.nDestroyed == 1);
8046 // The separate `File` object is deleted when the last `SafeRefCounted!File` handle is destroyed
8047 // (i.e. at the closing brace of the compound statement above, which destroys both handles: `rcFile` and `rcFile2`)
8048 // (=> `File.nDestroyed` is incremented again, from 1 to 2):
8049 assert(File.nDestroyed == 2);
8053 Creates a proxy for the value `a` that will forward all operations
8054 while disabling implicit conversions. The aliased item `a` must be
8055 an $(B lvalue). This is useful for creating a new type from the
8056 "base" type (though this is $(B not) a subtype-supertype
8057 relationship; the new type is not related to the old type in any way,
8058 by design).
8060 The new type supports all operations that the underlying type does,
8061 including all operators such as `+`, `--`, `<`, `[]`, etc.
8063 Params:
8064 a = The value to act as a proxy for all operations. It must
8065 be an lvalue.
8067 mixin template Proxy(alias a)
8069 private alias ValueType = typeof({ return a; }());
8071 /* Determine if 'T.a' can referenced via a const(T).
8072 * Use T* as the parameter because 'scope' inference needs a fully
8073 * analyzed T, which doesn't work when accessibleFrom() is used in a
8074 * 'static if' in the definition of Proxy or T.
8076 private enum bool accessibleFrom(T) =
8077 is(typeof((T* self){ cast(void) mixin("(*self)."~__traits(identifier, a)); }));
8079 static if (is(typeof(this) == class))
8081 override bool opEquals(Object o)
8083 if (auto b = cast(typeof(this))o)
8085 return a == mixin("b."~__traits(identifier, a));
8087 return false;
8090 bool opEquals(T)(T b)
8091 if (is(ValueType : T) || is(typeof(a.opEquals(b))) || is(typeof(b.opEquals(a))))
8093 static if (is(typeof(a.opEquals(b))))
8094 return a.opEquals(b);
8095 else static if (is(typeof(b.opEquals(a))))
8096 return b.opEquals(a);
8097 else
8098 return a == b;
8101 override int opCmp(Object o)
8103 if (auto b = cast(typeof(this))o)
8105 return a < mixin("b."~__traits(identifier, a)) ? -1
8106 : a > mixin("b."~__traits(identifier, a)) ? +1 : 0;
8108 static if (is(ValueType == class))
8109 return a.opCmp(o);
8110 else
8111 throw new Exception("Attempt to compare a "~typeid(this).toString~" and a "~typeid(o).toString);
8114 int opCmp(T)(auto ref const T b)
8115 if (is(ValueType : T) || is(typeof(a.opCmp(b))) || is(typeof(b.opCmp(a))))
8117 static if (is(typeof(a.opCmp(b))))
8118 return a.opCmp(b);
8119 else static if (is(typeof(b.opCmp(a))))
8120 return -b.opCmp(a);
8121 else
8122 return a < b ? -1 : a > b ? +1 : 0;
8125 static if (accessibleFrom!(const typeof(this)))
8127 override size_t toHash() const nothrow @safe
8129 static if (__traits(compiles, .hashOf(a)))
8130 return .hashOf(a);
8131 else
8132 // Workaround for when .hashOf is not both @safe and nothrow.
8134 static if (is(typeof(&a) == ValueType*))
8135 alias v = a;
8136 else
8137 auto v = a; // if a is (property) function
8138 // BUG: Improperly casts away `shared`!
8139 return typeid(ValueType).getHash((() @trusted => cast(const void*) &v)());
8144 else
8146 auto ref opEquals(this X, B)(auto ref B b)
8148 static if (is(immutable B == immutable typeof(this)))
8150 return a == mixin("b."~__traits(identifier, a));
8152 else
8153 return a == b;
8156 auto ref opCmp(this X, B)(auto ref B b)
8158 static if (is(typeof(a.opCmp(b))))
8159 return a.opCmp(b);
8160 else static if (is(typeof(b.opCmp(a))))
8161 return -b.opCmp(a);
8162 else static if (isFloatingPoint!ValueType || isFloatingPoint!B)
8163 return a < b ? -1 : a > b ? +1 : a == b ? 0 : float.nan;
8164 else
8165 return a < b ? -1 : (a > b);
8168 static if (accessibleFrom!(const typeof(this)))
8170 size_t toHash() const nothrow @safe
8172 static if (__traits(compiles, .hashOf(a)))
8173 return .hashOf(a);
8174 else
8175 // Workaround for when .hashOf is not both @safe and nothrow.
8177 static if (is(typeof(&a) == ValueType*))
8178 alias v = a;
8179 else
8180 auto v = a; // if a is (property) function
8181 // BUG: Improperly casts away `shared`!
8182 return typeid(ValueType).getHash((() @trusted => cast(const void*) &v)());
8188 auto ref opCall(this X, Args...)(auto ref Args args) { return a(args); }
8190 auto ref opCast(T, this X)() { return cast(T) a; }
8192 auto ref opIndex(this X, D...)(auto ref D i) { return a[i]; }
8193 auto ref opSlice(this X )() { return a[]; }
8194 auto ref opSlice(this X, B, E)(auto ref B b, auto ref E e) { return a[b .. e]; }
8196 auto ref opUnary (string op, this X )() { return mixin(op~"a"); }
8197 auto ref opIndexUnary(string op, this X, D...)(auto ref D i) { return mixin(op~"a[i]"); }
8198 auto ref opSliceUnary(string op, this X )() { return mixin(op~"a[]"); }
8199 auto ref opSliceUnary(string op, this X, B, E)(auto ref B b, auto ref E e) { return mixin(op~"a[b .. e]"); }
8201 auto ref opBinary(string op, this X, B)(auto ref B b)
8202 if (op == "in" && is(typeof(a in b)) || op != "in")
8204 return mixin("a "~op~" b");
8206 auto ref opBinaryRight(string op, this X, B)(auto ref B b) { return mixin("b "~op~" a"); }
8208 static if (!is(typeof(this) == class))
8210 import std.traits;
8211 static if (isAssignable!ValueType)
8213 auto ref opAssign(this X)(auto ref typeof(this) v)
8215 a = mixin("v."~__traits(identifier, a));
8216 return this;
8219 else
8221 @disable void opAssign(this X)(auto ref typeof(this) v);
8225 auto ref opAssign (this X, V )(auto ref V v) if (!is(V == typeof(this))) { return a = v; }
8226 auto ref opIndexAssign(this X, V, D...)(auto ref V v, auto ref D i) { return a[i] = v; }
8227 auto ref opSliceAssign(this X, V )(auto ref V v) { return a[] = v; }
8228 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; }
8230 auto ref opOpAssign (string op, this X, V )(auto ref V v)
8232 return mixin("a = a "~op~" v");
8234 auto ref opIndexOpAssign(string op, this X, V, D...)(auto ref V v, auto ref D i)
8236 return mixin("a[i] " ~op~"= v");
8238 auto ref opSliceOpAssign(string op, this X, V )(auto ref V v)
8240 return mixin("a[] " ~op~"= v");
8242 auto ref opSliceOpAssign(string op, this X, V, B, E)(auto ref V v, auto ref B b, auto ref E e)
8244 return mixin("a[b .. e] "~op~"= v");
8247 template opDispatch(string name)
8249 static if (is(typeof(__traits(getMember, a, name)) == function))
8251 // non template function
8252 auto ref opDispatch(this X, Args...)(auto ref Args args) { return mixin("a."~name~"(args)"); }
8254 else static if (is(typeof({ enum x = mixin("a."~name); })))
8256 // built-in type field, manifest constant, and static non-mutable field
8257 enum opDispatch = mixin("a."~name);
8259 else static if (__traits(isTemplate, mixin("a."~name)))
8261 // member template
8262 template opDispatch(T...)
8264 enum targs = T.length ? "!T" : "";
8265 auto ref opDispatch(this X, Args...)(auto ref Args args){ return mixin("a."~name~targs~"(args)"); }
8268 else
8270 // field or property function
8271 @property auto ref opDispatch(this X)() { return mixin("a."~name); }
8272 @property auto ref opDispatch(this X, V)(auto ref V v) { return mixin("a."~name~" = v"); }
8277 import std.traits : isArray;
8279 static if (isArray!ValueType)
8281 auto opDollar() const { return a.length; }
8283 else static if (is(typeof(a.opDollar!0)))
8285 auto ref opDollar(size_t pos)() { return a.opDollar!pos(); }
8287 else static if (is(typeof(a.opDollar) == function))
8289 auto ref opDollar() { return a.opDollar(); }
8291 else static if (is(typeof(a.opDollar)))
8293 alias opDollar = a.opDollar;
8298 @safe unittest
8300 struct MyInt
8302 private int value;
8303 mixin Proxy!value;
8305 this(int n){ value = n; }
8308 MyInt n = 10;
8310 // Enable operations that original type has.
8311 ++n;
8312 assert(n == 11);
8313 assert(n * 2 == 22);
8315 void func(int n) { }
8317 // Disable implicit conversions to original type.
8318 //int x = n;
8319 //func(n);
8322 ///The proxied value must be an $(B lvalue).
8323 @safe unittest
8325 struct NewIntType
8327 //Won't work; the literal '1'
8328 //is an rvalue, not an lvalue
8329 //mixin Proxy!1;
8331 //Okay, n is an lvalue
8332 int n;
8333 mixin Proxy!n;
8335 this(int n) { this.n = n; }
8338 NewIntType nit = 0;
8339 nit++;
8340 assert(nit == 1);
8343 struct NewObjectType
8345 Object obj;
8346 //Ok, obj is an lvalue
8347 mixin Proxy!obj;
8349 this (Object o) { obj = o; }
8352 NewObjectType not = new Object();
8353 assert(__traits(compiles, not.toHash()));
8357 There is one exception to the fact that the new type is not related to the
8358 old type. $(DDSUBLINK spec/function,pseudo-member, Pseudo-member)
8359 functions are usable with the new type; they will be forwarded on to the
8360 proxied value.
8362 @safe unittest
8364 import std.math.traits : isInfinity;
8366 float f = 1.0;
8367 assert(!f.isInfinity);
8369 struct NewFloat
8371 float _;
8372 mixin Proxy!_;
8374 this(float f) { _ = f; }
8377 NewFloat nf = 1.0f;
8378 assert(!nf.isInfinity);
8381 @safe unittest
8383 static struct MyInt
8385 private int value;
8386 mixin Proxy!value;
8387 this(int n) inout { value = n; }
8389 enum str = "str";
8390 static immutable arr = [1,2,3];
8393 static foreach (T; AliasSeq!(MyInt, const MyInt, immutable MyInt))
8395 T m = 10;
8396 static assert(!__traits(compiles, { int x = m; }));
8397 static assert(!__traits(compiles, { void func(int n){} func(m); }));
8398 assert(m == 10);
8399 assert(m != 20);
8400 assert(m < 20);
8401 assert(+m == 10);
8402 assert(-m == -10);
8403 assert(cast(double) m == 10.0);
8404 assert(m + 10 == 20);
8405 assert(m - 5 == 5);
8406 assert(m * 20 == 200);
8407 assert(m / 2 == 5);
8408 assert(10 + m == 20);
8409 assert(15 - m == 5);
8410 assert(20 * m == 200);
8411 assert(50 / m == 5);
8412 static if (is(T == MyInt)) // mutable
8414 assert(++m == 11);
8415 assert(m++ == 11); assert(m == 12);
8416 assert(--m == 11);
8417 assert(m-- == 11); assert(m == 10);
8418 m = m;
8419 m = 20; assert(m == 20);
8421 static assert(T.max == int.max);
8422 static assert(T.min == int.min);
8423 static assert(T.init == int.init);
8424 static assert(T.str == "str");
8425 static assert(T.arr == [1,2,3]);
8428 @system unittest
8430 static struct MyArray
8432 private int[] value;
8433 mixin Proxy!value;
8434 this(int[] arr) { value = arr; }
8435 this(immutable int[] arr) immutable { value = arr; }
8438 static foreach (T; AliasSeq!(MyArray, const MyArray, immutable MyArray))
8440 static if (is(T == immutable) && !is(typeof({ T a = [1,2,3,4]; })))
8441 T a = [1,2,3,4].idup; // workaround until qualified ctor is properly supported
8442 else
8443 T a = [1,2,3,4];
8444 assert(a == [1,2,3,4]);
8445 assert(a != [5,6,7,8]);
8446 assert(+a[0] == 1);
8447 version (LittleEndian)
8448 assert(cast(ulong[]) a == [0x0000_0002_0000_0001, 0x0000_0004_0000_0003]);
8449 else
8450 assert(cast(ulong[]) a == [0x0000_0001_0000_0002, 0x0000_0003_0000_0004]);
8451 assert(a ~ [10,11] == [1,2,3,4,10,11]);
8452 assert(a[0] == 1);
8453 assert(a[] == [1,2,3,4]);
8454 assert(a[2 .. 4] == [3,4]);
8455 static if (is(T == MyArray)) // mutable
8457 a = a;
8458 a = [5,6,7,8]; assert(a == [5,6,7,8]);
8459 a[0] = 0; assert(a == [0,6,7,8]);
8460 a[] = 1; assert(a == [1,1,1,1]);
8461 a[0 .. 3] = 2; assert(a == [2,2,2,1]);
8462 a[0] += 2; assert(a == [4,2,2,1]);
8463 a[] *= 2; assert(a == [8,4,4,2]);
8464 a[0 .. 2] /= 2; assert(a == [4,2,4,2]);
8468 @system unittest
8470 class Foo
8472 int field;
8474 @property int val1() const { return field; }
8475 @property void val1(int n) { field = n; }
8477 @property ref int val2() { return field; }
8479 int func(int x, int y) const { return x; }
8480 void func1(ref int a) { a = 9; }
8482 T ifti1(T)(T t) { return t; }
8483 void ifti2(Args...)(Args args) { }
8484 void ifti3(T, Args...)(Args args) { }
8486 T opCast(T)(){ return T.init; }
8488 T tempfunc(T)() { return T.init; }
8490 class Hoge
8492 Foo foo;
8493 mixin Proxy!foo;
8494 this(Foo f) { foo = f; }
8497 auto h = new Hoge(new Foo());
8498 int n;
8500 static assert(!__traits(compiles, { Foo f = h; }));
8502 // field
8503 h.field = 1; // lhs of assign
8504 n = h.field; // rhs of assign
8505 assert(h.field == 1); // lhs of BinExp
8506 assert(1 == h.field); // rhs of BinExp
8507 assert(n == 1);
8509 // getter/setter property function
8510 h.val1 = 4;
8511 n = h.val1;
8512 assert(h.val1 == 4);
8513 assert(4 == h.val1);
8514 assert(n == 4);
8516 // ref getter property function
8517 h.val2 = 8;
8518 n = h.val2;
8519 assert(h.val2 == 8);
8520 assert(8 == h.val2);
8521 assert(n == 8);
8523 // member function
8524 assert(h.func(2,4) == 2);
8525 h.func1(n);
8526 assert(n == 9);
8528 // IFTI
8529 assert(h.ifti1(4) == 4);
8530 h.ifti2(4);
8531 h.ifti3!int(4, 3);
8533 // https://issues.dlang.org/show_bug.cgi?id=5896 test
8534 assert(h.opCast!int() == 0);
8535 assert(cast(int) h == 0);
8536 const ih = new const Hoge(new Foo());
8537 static assert(!__traits(compiles, ih.opCast!int()));
8538 static assert(!__traits(compiles, cast(int) ih));
8540 // template member function
8541 assert(h.tempfunc!int() == 0);
8544 @system unittest // about Proxy inside a class
8546 class MyClass
8548 int payload;
8549 mixin Proxy!payload;
8550 this(int i){ payload = i; }
8551 string opCall(string msg){ return msg; }
8552 int pow(int i){ return payload ^^ i; }
8555 class MyClass2
8557 MyClass payload;
8558 mixin Proxy!payload;
8559 this(int i){ payload = new MyClass(i); }
8562 class MyClass3
8564 int payload;
8565 mixin Proxy!payload;
8566 this(int i){ payload = i; }
8569 // opEquals
8570 Object a = new MyClass(5);
8571 Object b = new MyClass(5);
8572 Object c = new MyClass2(5);
8573 Object d = new MyClass3(5);
8574 assert(a == b);
8575 assert((cast(MyClass) a) == 5);
8576 assert(5 == (cast(MyClass) b));
8577 assert(5 == cast(MyClass2) c);
8578 assert(a != d);
8580 assert(c != a);
8581 // oops! above line is unexpected, isn't it?
8582 // the reason is below.
8583 // MyClass2.opEquals knows MyClass but,
8584 // MyClass.opEquals doesn't know MyClass2.
8585 // so, c.opEquals(a) is true, but a.opEquals(c) is false.
8586 // furthermore, opEquals(T) couldn't be invoked.
8587 assert((cast(MyClass2) c) != (cast(MyClass) a));
8589 // opCmp
8590 Object e = new MyClass2(7);
8591 assert(a < cast(MyClass2) e); // OK. and
8592 assert(e > a); // OK, but...
8593 // assert(a < e); // RUNTIME ERROR!
8594 // assert((cast(MyClass) a) < e); // RUNTIME ERROR!
8595 assert(3 < cast(MyClass) a);
8596 assert((cast(MyClass2) e) < 11);
8598 // opCall
8599 assert((cast(MyClass2) e)("hello") == "hello");
8601 // opCast
8602 assert((cast(MyClass)(cast(MyClass2) c)) == a);
8603 assert((cast(int)(cast(MyClass2) c)) == 5);
8605 // opIndex
8606 class MyClass4
8608 string payload;
8609 mixin Proxy!payload;
8610 this(string s){ payload = s; }
8612 class MyClass5
8614 MyClass4 payload;
8615 mixin Proxy!payload;
8616 this(string s){ payload = new MyClass4(s); }
8618 auto f = new MyClass4("hello");
8619 assert(f[1] == 'e');
8620 auto g = new MyClass5("hello");
8621 assert(f[1] == 'e');
8623 // opSlice
8624 assert(f[2 .. 4] == "ll");
8626 // opUnary
8627 assert(-(cast(MyClass2) c) == -5);
8629 // opBinary
8630 assert((cast(MyClass) a) + (cast(MyClass2) c) == 10);
8631 assert(5 + cast(MyClass) a == 10);
8633 // opAssign
8634 (cast(MyClass2) c) = 11;
8635 assert((cast(MyClass2) c) == 11);
8636 (cast(MyClass2) c) = new MyClass(13);
8637 assert((cast(MyClass2) c) == 13);
8639 // opOpAssign
8640 assert((cast(MyClass2) c) += 4);
8641 assert((cast(MyClass2) c) == 17);
8643 // opDispatch
8644 assert((cast(MyClass2) c).pow(2) == 289);
8646 // opDollar
8647 assert(f[2..$-1] == "ll");
8649 // toHash
8650 int[Object] hash;
8651 hash[a] = 19;
8652 hash[c] = 21;
8653 assert(hash[b] == 19);
8654 assert(hash[c] == 21);
8657 @safe unittest
8659 struct MyInt
8661 int payload;
8663 mixin Proxy!payload;
8666 MyInt v;
8667 v = v;
8669 struct Foo
8671 @disable void opAssign(typeof(this));
8673 struct MyFoo
8675 Foo payload;
8677 mixin Proxy!payload;
8679 MyFoo f;
8680 static assert(!__traits(compiles, f = f));
8682 struct MyFoo2
8684 Foo payload;
8686 mixin Proxy!payload;
8688 // override default Proxy behavior
8689 void opAssign(typeof(this) rhs){}
8691 MyFoo2 f2;
8692 f2 = f2;
8695 // https://issues.dlang.org/show_bug.cgi?id=8613
8696 @safe unittest
8698 static struct Name
8700 mixin Proxy!val;
8701 private string val;
8702 this(string s) { val = s; }
8705 bool[Name] names;
8706 names[Name("a")] = true;
8707 bool* b = Name("a") in names;
8710 // workaround for https://issues.dlang.org/show_bug.cgi?id=19669
8711 private enum isDIP1000 = __traits(compiles, () @safe {
8712 int x;
8713 int* p;
8714 p = &x;
8716 // excludes struct S; it's 'mixin Proxy!foo' doesn't compile with -dip1000
8717 static if (isDIP1000) {} else
8718 @system unittest
8720 // https://issues.dlang.org/show_bug.cgi?id=14213
8721 // using function for the payload
8722 static struct S
8724 int foo() { return 12; }
8725 mixin Proxy!foo;
8727 S s;
8728 assert(s + 1 == 13);
8729 assert(s * 2 == 24);
8732 @system unittest
8734 static class C
8736 int foo() { return 12; }
8737 mixin Proxy!foo;
8739 C c = new C();
8742 // Check all floating point comparisons for both Proxy and Typedef,
8743 // also against int and a Typedef!int, to be as regression-proof
8744 // as possible. https://issues.dlang.org/show_bug.cgi?id=15561
8745 @safe unittest
8747 static struct MyFloatImpl
8749 float value;
8750 mixin Proxy!value;
8752 static void allFail(T0, T1)(T0 a, T1 b)
8754 assert(!(a == b));
8755 assert(!(a<b));
8756 assert(!(a <= b));
8757 assert(!(a>b));
8758 assert(!(a >= b));
8760 static foreach (T1; AliasSeq!(MyFloatImpl, Typedef!float, Typedef!double,
8761 float, real, Typedef!int, int))
8763 static foreach (T2; AliasSeq!(MyFloatImpl, Typedef!float))
8765 T1 a;
8766 T2 b;
8768 static if (isFloatingPoint!T1 || isFloatingPoint!(TypedefType!T1))
8769 allFail(a, b);
8770 a = 3;
8771 allFail(a, b);
8773 b = 4;
8774 assert(a != b);
8775 assert(a<b);
8776 assert(a <= b);
8777 assert(!(a>b));
8778 assert(!(a >= b));
8780 a = 4;
8781 assert(a == b);
8782 assert(!(a<b));
8783 assert(a <= b);
8784 assert(!(a>b));
8785 assert(a >= b);
8791 $(B Typedef) allows the creation of a unique type which is
8792 based on an existing type. Unlike the `alias` feature,
8793 $(B Typedef) ensures the two types are not considered as equals.
8795 Params:
8797 init = Optional initial value for the new type.
8798 cookie = Optional, used to create multiple unique types which are
8799 based on the same origin type `T`
8801 Note: If a library routine cannot handle the Typedef type,
8802 you can use the `TypedefType` template to extract the
8803 type which the Typedef wraps.
8805 struct Typedef(T, T init = T.init, string cookie=null)
8807 private T Typedef_payload = init;
8809 // https://issues.dlang.org/show_bug.cgi?id=18415
8810 // prevent default construction if original type does too.
8811 static if ((is(T == struct) || is(T == union)) && !is(typeof({T t;})))
8813 @disable this();
8816 this(T init)
8818 Typedef_payload = init;
8821 this(Typedef tdef)
8823 this(tdef.Typedef_payload);
8826 // We need to add special overload for cast(Typedef!X) exp,
8827 // thus we can't simply inherit Proxy!Typedef_payload
8828 T2 opCast(T2 : Typedef!(T, Unused), this X, T, Unused...)()
8830 return T2(cast(T) Typedef_payload);
8833 auto ref opCast(T2, this X)()
8835 return cast(T2) Typedef_payload;
8838 mixin Proxy!Typedef_payload;
8840 pure nothrow @nogc @safe @property
8842 alias TD = typeof(this);
8843 static if (isIntegral!T)
8845 static TD min() {return TD(T.min);}
8846 static TD max() {return TD(T.max);}
8848 else static if (isFloatingPoint!T)
8850 static TD infinity() {return TD(T.infinity);}
8851 static TD nan() {return TD(T.nan);}
8852 static TD dig() {return TD(T.dig);}
8853 static TD epsilon() {return TD(T.epsilon);}
8854 static TD mant_dig() {return TD(T.mant_dig);}
8855 static TD max_10_exp() {return TD(T.max_10_exp);}
8856 static TD max_exp() {return TD(T.max_exp);}
8857 static TD min_10_exp() {return TD(T.min_10_exp);}
8858 static TD min_exp() {return TD(T.min_exp);}
8859 static TD max() {return TD(T.max);}
8860 static TD min_normal() {return TD(T.min_normal);}
8861 TD re() {return TD(Typedef_payload.re);}
8862 TD im() {return TD(Typedef_payload.im);}
8867 * Convert wrapped value to a human readable string
8869 string toString(this T)()
8871 import std.array : appender;
8872 auto app = appender!string();
8873 auto spec = singleSpec("%s");
8874 toString(app, spec);
8875 return app.data;
8878 /// ditto
8879 void toString(this T, W)(ref W writer, scope const ref FormatSpec!char fmt)
8880 if (isOutputRange!(W, char))
8882 formatValue(writer, Typedef_payload, fmt);
8886 @safe unittest
8888 import std.conv : to;
8890 int i = 123;
8891 auto td = Typedef!int(i);
8892 assert(i.to!string == td.to!string);
8897 @safe unittest
8899 alias MyInt = Typedef!int;
8900 MyInt foo = 10;
8901 foo++;
8902 assert(foo == 11);
8905 /// custom initialization values
8906 @safe unittest
8908 alias MyIntInit = Typedef!(int, 42);
8909 static assert(is(TypedefType!MyIntInit == int));
8910 static assert(MyIntInit() == 42);
8913 /// Typedef creates a new type
8914 @safe unittest
8916 alias MyInt = Typedef!int;
8917 static void takeInt(int) {}
8918 static void takeMyInt(MyInt) {}
8920 int i;
8921 takeInt(i); // ok
8922 static assert(!__traits(compiles, takeMyInt(i)));
8924 MyInt myInt;
8925 static assert(!__traits(compiles, takeInt(myInt)));
8926 takeMyInt(myInt); // ok
8929 /// Use the optional `cookie` argument to create different types of the same base type
8930 @safe unittest
8932 alias TypeInt1 = Typedef!int;
8933 alias TypeInt2 = Typedef!int;
8935 // The two Typedefs are the same type.
8936 static assert(is(TypeInt1 == TypeInt2));
8938 alias MoneyEuros = Typedef!(float, float.init, "euros");
8939 alias MoneyDollars = Typedef!(float, float.init, "dollars");
8941 // The two Typedefs are _not_ the same type.
8942 static assert(!is(MoneyEuros == MoneyDollars));
8945 // https://issues.dlang.org/show_bug.cgi?id=12461
8946 @safe unittest
8948 alias Int = Typedef!int;
8950 Int a, b;
8951 a += b;
8952 assert(a == 0);
8956 Get the underlying type which a `Typedef` wraps.
8957 If `T` is not a `Typedef` it will alias itself to `T`.
8959 template TypedefType(T)
8961 static if (is(T : Typedef!Arg, Arg))
8962 alias TypedefType = Arg;
8963 else
8964 alias TypedefType = T;
8968 @safe unittest
8970 import std.conv : to;
8972 alias MyInt = Typedef!int;
8973 static assert(is(TypedefType!MyInt == int));
8975 /// Instantiating with a non-Typedef will return that type
8976 static assert(is(TypedefType!int == int));
8978 string num = "5";
8980 // extract the needed type
8981 MyInt myInt = MyInt( num.to!(TypedefType!MyInt) );
8982 assert(myInt == 5);
8984 // cast to the underlying type to get the value that's being wrapped
8985 int x = cast(TypedefType!MyInt) myInt;
8987 alias MyIntInit = Typedef!(int, 42);
8988 static assert(is(TypedefType!MyIntInit == int));
8989 static assert(MyIntInit() == 42);
8992 @safe unittest
8994 Typedef!int x = 10;
8995 static assert(!__traits(compiles, { int y = x; }));
8996 static assert(!__traits(compiles, { long z = x; }));
8998 Typedef!int y = 10;
8999 assert(x == y);
9001 static assert(Typedef!int.init == int.init);
9003 Typedef!(float, 1.0) z; // specifies the init
9004 assert(z == 1.0);
9006 static assert(typeof(z).init == 1.0);
9008 alias Dollar = Typedef!(int, 0, "dollar");
9009 alias Yen = Typedef!(int, 0, "yen");
9010 static assert(!is(Dollar == Yen));
9012 Typedef!(int[3]) sa;
9013 static assert(sa.length == 3);
9014 static assert(typeof(sa).length == 3);
9016 Typedef!(int[3]) dollar1;
9017 assert(dollar1[0..$] is dollar1[0 .. 3]);
9019 Typedef!(int[]) dollar2;
9020 dollar2.length = 3;
9021 assert(dollar2[0..$] is dollar2[0 .. 3]);
9023 static struct Dollar1
9025 static struct DollarToken {}
9026 enum opDollar = DollarToken.init;
9027 auto opSlice(size_t, DollarToken) { return 1; }
9028 auto opSlice(size_t, size_t) { return 2; }
9031 Typedef!Dollar1 drange1;
9032 assert(drange1[0..$] == 1);
9033 assert(drange1[0 .. 1] == 2);
9035 static struct Dollar2
9037 size_t opDollar(size_t pos)() { return pos == 0 ? 1 : 100; }
9038 size_t opIndex(size_t i, size_t j) { return i + j; }
9041 Typedef!Dollar2 drange2;
9042 assert(drange2[$, $] == 101);
9044 static struct Dollar3
9046 size_t opDollar() { return 123; }
9047 size_t opIndex(size_t i) { return i; }
9050 Typedef!Dollar3 drange3;
9051 assert(drange3[$] == 123);
9054 // https://issues.dlang.org/show_bug.cgi?id=18415
9055 @safe @nogc pure nothrow unittest
9057 struct NoDefCtorS{@disable this();}
9058 union NoDefCtorU{@disable this();}
9059 static assert(!is(typeof({Typedef!NoDefCtorS s;})));
9060 static assert(!is(typeof({Typedef!NoDefCtorU u;})));
9063 // https://issues.dlang.org/show_bug.cgi?id=11703
9064 @safe @nogc pure nothrow unittest
9066 alias I = Typedef!int;
9067 static assert(is(typeof(I.min) == I));
9068 static assert(is(typeof(I.max) == I));
9070 alias F = Typedef!double;
9071 static assert(is(typeof(F.infinity) == F));
9072 static assert(is(typeof(F.epsilon) == F));
9074 F f;
9075 assert(!is(typeof(F.re).stringof == double));
9076 assert(!is(typeof(F.im).stringof == double));
9079 @safe unittest
9081 // https://issues.dlang.org/show_bug.cgi?id=8655
9082 import std.typecons;
9083 import std.bitmanip;
9084 static import core.stdc.config;
9086 alias c_ulong = Typedef!(core.stdc.config.c_ulong);
9088 static struct Foo
9090 mixin(bitfields!(
9091 c_ulong, "NameOffset", 31,
9092 c_ulong, "NameIsString", 1
9097 // https://issues.dlang.org/show_bug.cgi?id=12596
9098 @safe unittest
9100 import std.typecons;
9101 alias TD = Typedef!int;
9102 TD x = TD(1);
9103 TD y = TD(x);
9104 assert(x == y);
9107 @safe unittest // about toHash
9109 import std.typecons;
9111 alias TD = Typedef!int;
9112 int[TD] td;
9113 td[TD(1)] = 1;
9114 assert(td[TD(1)] == 1);
9118 alias TD = Typedef!(int[]);
9119 int[TD] td;
9120 td[TD([1,2,3,4])] = 2;
9121 assert(td[TD([1,2,3,4])] == 2);
9125 alias TD = Typedef!(int[][]);
9126 int[TD] td;
9127 td[TD([[1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]])] = 3;
9128 assert(td[TD([[1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]])] == 3);
9132 struct MyStruct{ int x; }
9133 alias TD = Typedef!MyStruct;
9134 int[TD] td;
9135 td[TD(MyStruct(10))] = 4;
9136 assert(TD(MyStruct(20)) !in td);
9137 assert(td[TD(MyStruct(10))] == 4);
9141 static struct MyStruct2
9143 int x;
9144 size_t toHash() const nothrow @safe { return x; }
9145 bool opEquals(ref const MyStruct2 r) const { return r.x == x; }
9148 alias TD = Typedef!MyStruct2;
9149 int[TD] td;
9150 td[TD(MyStruct2(50))] = 5;
9151 assert(td[TD(MyStruct2(50))] == 5);
9155 class MyClass{}
9156 alias TD = Typedef!MyClass;
9157 int[TD] td;
9158 auto c = new MyClass;
9159 td[TD(c)] = 6;
9160 assert(TD(new MyClass) !in td);
9161 assert(td[TD(c)] == 6);
9165 @system unittest
9167 alias String = Typedef!(char[]);
9168 alias CString = Typedef!(const(char)[]);
9169 CString cs = "fubar";
9170 String s = cast(String) cs;
9171 assert(cs == s);
9172 char[] s2 = cast(char[]) cs;
9173 const(char)[] cs2 = cast(const(char)[])s;
9174 assert(s2 == cs2);
9177 @system unittest // toString
9179 import std.meta : AliasSeq;
9180 import std.conv : to;
9182 struct TestS {}
9183 class TestC {}
9185 static foreach (T; AliasSeq!(int, bool, float, double, real,
9186 char, dchar, wchar,
9187 TestS, TestC,
9188 int*, int[], int[2], int[int]))
9190 T t;
9192 Typedef!T td;
9193 Typedef!(const T) ctd;
9194 Typedef!(immutable T) itd;
9196 assert(t.to!string() == td.to!string());
9198 static if (!(is(T == TestS) || is(T == TestC)))
9200 assert(t.to!string() == ctd.to!string());
9201 assert(t.to!string() == itd.to!string());
9206 @safe @nogc unittest // typedef'ed type with custom operators
9208 static struct MyInt
9210 int value;
9211 int opCmp(MyInt other)
9213 if (value < other.value)
9214 return -1;
9215 return !(value == other.value);
9219 auto m1 = Typedef!MyInt(MyInt(1));
9220 auto m2 = Typedef!MyInt(MyInt(2));
9221 assert(m1 < m2);
9225 Allocates a `class` object right inside the current scope,
9226 therefore avoiding the overhead of `new`. This facility is unsafe;
9227 it is the responsibility of the user to not escape a reference to the
9228 object outside the scope.
9230 The class destructor will be called when the result of `scoped()` is
9231 itself destroyed.
9233 Scoped class instances can be embedded in a parent `class` or `struct`,
9234 just like a child struct instance. Scoped member variables must have
9235 type `typeof(scoped!Class(args))`, and be initialized with a call to
9236 scoped. See below for an example.
9238 Note:
9239 It's illegal to move a class instance even if you are sure there
9240 are no pointers to it. As such, it is illegal to move a scoped object.
9242 template scoped(T)
9243 if (is(T == class))
9245 // _d_newclass now use default GC alignment (looks like (void*).sizeof * 2 for
9246 // small objects). We will just use the maximum of filed alignments.
9247 enum alignment = __traits(classInstanceAlignment, T);
9248 alias aligned = _alignUp!alignment;
9250 static struct Scoped
9252 // Addition of `alignment` is required as `Scoped_store` can be misaligned in memory.
9253 private void[aligned(__traits(classInstanceSize, T) + size_t.sizeof) + alignment] Scoped_store = void;
9255 @property inout(T) Scoped_payload() inout
9257 void* alignedStore = cast(void*) aligned(cast(size_t) Scoped_store.ptr);
9258 // As `Scoped` can be unaligned moved in memory class instance should be moved accordingly.
9259 immutable size_t d = alignedStore - Scoped_store.ptr;
9260 size_t* currD = cast(size_t*) &Scoped_store[$ - size_t.sizeof];
9261 if (d != *currD)
9263 import core.stdc.string : memmove;
9264 memmove(alignedStore, Scoped_store.ptr + *currD, __traits(classInstanceSize, T));
9265 *currD = d;
9267 return cast(inout(T)) alignedStore;
9269 alias Scoped_payload this;
9271 @disable this();
9272 @disable this(this);
9274 ~this()
9276 // `destroy` will also write .init but we have no functions in druntime
9277 // for deterministic finalization and memory releasing for now.
9278 .destroy(Scoped_payload);
9282 /** Returns the _scoped object.
9283 Params: args = Arguments to pass to `T`'s constructor.
9285 @system auto scoped(Args...)(auto ref Args args)
9287 import core.lifetime : emplace, forward;
9289 Scoped result = void;
9290 void* alignedStore = cast(void*) aligned(cast(size_t) result.Scoped_store.ptr);
9291 immutable size_t d = alignedStore - result.Scoped_store.ptr;
9292 *cast(size_t*) &result.Scoped_store[$ - size_t.sizeof] = d;
9293 emplace!(Unqual!T)(result.Scoped_store[d .. $ - size_t.sizeof], forward!args);
9294 return result;
9299 @system unittest
9301 class A
9303 int x;
9304 this() {x = 0;}
9305 this(int i){x = i;}
9306 ~this() {}
9309 // Standard usage, constructing A on the stack
9310 auto a1 = scoped!A();
9311 a1.x = 42;
9313 // Result of `scoped` call implicitly converts to a class reference
9314 A aRef = a1;
9315 assert(aRef.x == 42);
9317 // Scoped destruction
9319 auto a2 = scoped!A(1);
9320 assert(a2.x == 1);
9321 aRef = a2;
9322 // a2 is destroyed here, calling A's destructor
9324 // aRef is now an invalid reference
9326 // Here the temporary scoped A is immediately destroyed.
9327 // This means the reference is then invalid.
9328 version (Bug)
9330 // Wrong, should use `auto`
9331 A invalid = scoped!A();
9334 // Restrictions
9335 version (Bug)
9337 import std.algorithm.mutation : move;
9338 auto invalid = a1.move; // illegal, scoped objects can't be moved
9340 static assert(!is(typeof({
9341 auto e1 = a1; // illegal, scoped objects can't be copied
9342 assert([a1][0].x == 42); // ditto
9343 })));
9344 static assert(!is(typeof({
9345 alias ScopedObject = typeof(a1);
9346 auto e2 = ScopedObject(); // illegal, must be built via scoped!A
9347 auto e3 = ScopedObject(1); // ditto
9348 })));
9350 // Use with alias
9351 alias makeScopedA = scoped!A;
9352 auto a3 = makeScopedA();
9353 auto a4 = makeScopedA(1);
9355 // Use as member variable
9356 struct B
9358 typeof(scoped!A()) a; // note the trailing parentheses
9360 this(int i)
9362 // construct member
9363 a = scoped!A(i);
9367 // Stack-allocate
9368 auto b1 = B(5);
9369 aRef = b1.a;
9370 assert(aRef.x == 5);
9371 destroy(b1); // calls A's destructor for b1.a
9372 // aRef is now an invalid reference
9374 // Heap-allocate
9375 auto b2 = new B(6);
9376 assert(b2.a.x == 6);
9377 destroy(*b2); // calls A's destructor for b2.a
9380 private size_t _alignUp(size_t alignment)(size_t n)
9381 if (alignment > 0 && !((alignment - 1) & alignment))
9383 enum badEnd = alignment - 1; // 0b11, 0b111, ...
9384 return (n + badEnd) & ~badEnd;
9387 // https://issues.dlang.org/show_bug.cgi?id=6580 testcase
9388 @system unittest
9390 enum alignment = (void*).alignof;
9392 static class C0 { }
9393 static class C1 { byte b; }
9394 static class C2 { byte[2] b; }
9395 static class C3 { byte[3] b; }
9396 static class C7 { byte[7] b; }
9397 static assert(scoped!C0().sizeof % alignment == 0);
9398 static assert(scoped!C1().sizeof % alignment == 0);
9399 static assert(scoped!C2().sizeof % alignment == 0);
9400 static assert(scoped!C3().sizeof % alignment == 0);
9401 static assert(scoped!C7().sizeof % alignment == 0);
9403 enum longAlignment = long.alignof;
9404 static class C1long
9406 long long_; byte byte_ = 4;
9407 this() { }
9408 this(long _long, ref int i) { long_ = _long; ++i; }
9410 static class C2long { byte[2] byte_ = [5, 6]; long long_ = 7; }
9411 static assert(scoped!C1long().sizeof % longAlignment == 0);
9412 static assert(scoped!C2long().sizeof % longAlignment == 0);
9414 void alignmentTest()
9416 int var = 5;
9417 auto c1long = scoped!C1long(3, var);
9418 assert(var == 6);
9419 auto c2long = scoped!C2long();
9420 assert(cast(uint)&c1long.long_ % longAlignment == 0);
9421 assert(cast(uint)&c2long.long_ % longAlignment == 0);
9422 assert(c1long.long_ == 3 && c1long.byte_ == 4);
9423 assert(c2long.byte_ == [5, 6] && c2long.long_ == 7);
9426 alignmentTest();
9428 version (DigitalMars)
9430 void test(size_t size)
9432 import core.stdc.stdlib : alloca;
9433 cast(void) alloca(size);
9434 alignmentTest();
9436 foreach (i; 0 .. 10)
9437 test(i);
9439 else
9441 void test(size_t size)()
9443 byte[size] arr;
9444 alignmentTest();
9446 static foreach (i; 0 .. 11)
9447 test!i();
9451 // Original https://issues.dlang.org/show_bug.cgi?id=6580 testcase
9452 @system unittest
9454 class C { int i; byte b; }
9456 auto sa = [scoped!C(), scoped!C()];
9457 assert(cast(uint)&sa[0].i % int.alignof == 0);
9458 assert(cast(uint)&sa[1].i % int.alignof == 0); // fails
9461 @system unittest
9463 class A { int x = 1; }
9464 auto a1 = scoped!A();
9465 assert(a1.x == 1);
9466 auto a2 = scoped!A();
9467 a1.x = 42;
9468 a2.x = 53;
9469 assert(a1.x == 42);
9472 @system unittest
9474 class A { int x = 1; this() { x = 2; } }
9475 auto a1 = scoped!A();
9476 assert(a1.x == 2);
9477 auto a2 = scoped!A();
9478 a1.x = 42;
9479 a2.x = 53;
9480 assert(a1.x == 42);
9483 @system unittest
9485 class A { int x = 1; this(int y) { x = y; } ~this() {} }
9486 auto a1 = scoped!A(5);
9487 assert(a1.x == 5);
9488 auto a2 = scoped!A(42);
9489 a1.x = 42;
9490 a2.x = 53;
9491 assert(a1.x == 42);
9494 @system unittest
9496 class A { static bool dead; ~this() { dead = true; } }
9497 class B : A { static bool dead; ~this() { dead = true; } }
9499 auto b = scoped!B();
9501 assert(B.dead, "asdasd");
9502 assert(A.dead, "asdasd");
9505 // https://issues.dlang.org/show_bug.cgi?id=8039 testcase
9506 @system unittest
9508 static int dels;
9509 static struct S { ~this(){ ++dels; } }
9511 static class A { S s; }
9512 dels = 0; { scoped!A(); }
9513 assert(dels == 1);
9515 static class B { S[2] s; }
9516 dels = 0; { scoped!B(); }
9517 assert(dels == 2);
9519 static struct S2 { S[3] s; }
9520 static class C { S2[2] s; }
9521 dels = 0; { scoped!C(); }
9522 assert(dels == 6);
9524 static class D: A { S2[2] s; }
9525 dels = 0; { scoped!D(); }
9526 assert(dels == 1+6);
9529 @system unittest
9531 // https://issues.dlang.org/show_bug.cgi?id=4500
9532 class A
9534 this() { a = this; }
9535 this(int i) { a = this; }
9536 A a;
9537 bool check() { return this is a; }
9540 auto a1 = scoped!A();
9541 assert(a1.check());
9543 auto a2 = scoped!A(1);
9544 assert(a2.check());
9546 a1.a = a1;
9547 assert(a1.check());
9550 @system unittest
9552 static class A
9554 static int sdtor;
9556 this() { ++sdtor; assert(sdtor == 1); }
9557 ~this() { assert(sdtor == 1); --sdtor; }
9560 interface Bob {}
9562 static class ABob : A, Bob
9564 this() { ++sdtor; assert(sdtor == 2); }
9565 ~this() { assert(sdtor == 2); --sdtor; }
9568 A.sdtor = 0;
9569 scope(exit) assert(A.sdtor == 0);
9570 auto abob = scoped!ABob();
9573 @safe unittest
9575 static class A { this(int) {} }
9576 static assert(!__traits(compiles, scoped!A()));
9579 @system unittest
9581 static class A { @property inout(int) foo() inout { return 1; } }
9583 auto a1 = scoped!A();
9584 assert(a1.foo == 1);
9585 static assert(is(typeof(a1.foo) == int));
9587 auto a2 = scoped!(const(A))();
9588 assert(a2.foo == 1);
9589 static assert(is(typeof(a2.foo) == const(int)));
9591 auto a3 = scoped!(immutable(A))();
9592 assert(a3.foo == 1);
9593 static assert(is(typeof(a3.foo) == immutable(int)));
9595 const c1 = scoped!A();
9596 assert(c1.foo == 1);
9597 static assert(is(typeof(c1.foo) == const(int)));
9599 const c2 = scoped!(const(A))();
9600 assert(c2.foo == 1);
9601 static assert(is(typeof(c2.foo) == const(int)));
9603 const c3 = scoped!(immutable(A))();
9604 assert(c3.foo == 1);
9605 static assert(is(typeof(c3.foo) == immutable(int)));
9608 @system unittest
9610 class C
9612 this(int rval) { assert(rval == 1); }
9613 this(ref int lval) { assert(lval == 3); ++lval; }
9616 auto c1 = scoped!C(1);
9617 int lval = 3;
9618 auto c2 = scoped!C(lval);
9619 assert(lval == 4);
9622 @system unittest
9624 class C
9626 this(){}
9627 this(int){}
9628 this(int, int){}
9630 alias makeScopedC = scoped!C;
9632 auto a = makeScopedC();
9633 auto b = makeScopedC(1);
9634 auto c = makeScopedC(1, 1);
9636 static assert(is(typeof(a) == typeof(b)));
9637 static assert(is(typeof(b) == typeof(c)));
9641 Defines a simple, self-documenting yes/no flag. This makes it easy for
9642 APIs to define functions accepting flags without resorting to $(D
9643 bool), which is opaque in calls, and without needing to define an
9644 enumerated type separately. Using `Flag!"Name"` instead of $(D
9645 bool) makes the flag's meaning visible in calls. Each yes/no flag has
9646 its own type, which makes confusions and mix-ups impossible.
9648 Example:
9650 Code calling `getLine` (usually far away from its definition) can't be
9651 understood without looking at the documentation, even by users familiar with
9652 the API:
9653 ----
9654 string getLine(bool keepTerminator)
9657 if (keepTerminator) ...
9661 auto line = getLine(false);
9662 ----
9664 Assuming the reverse meaning (i.e. "ignoreTerminator") and inserting the wrong
9665 code compiles and runs with erroneous results.
9667 After replacing the boolean parameter with an instantiation of `Flag`, code
9668 calling `getLine` can be easily read and understood even by people not
9669 fluent with the API:
9671 ----
9672 string getLine(Flag!"keepTerminator" keepTerminator)
9675 if (keepTerminator) ...
9679 auto line = getLine(Yes.keepTerminator);
9680 ----
9682 The structs `Yes` and `No` are provided as shorthand for
9683 `Flag!"Name".yes` and `Flag!"Name".no` and are preferred for brevity and
9684 readability. These convenience structs mean it is usually unnecessary and
9685 counterproductive to create an alias of a `Flag` as a way of avoiding typing
9686 out the full type while specifying the affirmative or negative options.
9688 Passing categorical data by means of unstructured `bool`
9689 parameters is classified under "simple-data coupling" by Steve
9690 McConnell in the $(LUCKY Code Complete) book, along with three other
9691 kinds of coupling. The author argues citing several studies that
9692 coupling has a negative effect on code quality. `Flag` offers a
9693 simple structuring method for passing yes/no flags to APIs.
9695 template Flag(string name) {
9697 enum Flag : bool
9700 When creating a value of type `Flag!"Name"`, use $(D
9701 Flag!"Name".no) for the negative option. When using a value
9702 of type `Flag!"Name"`, compare it against $(D
9703 Flag!"Name".no) or just `false` or `0`. */
9704 no = false,
9706 /** When creating a value of type `Flag!"Name"`, use $(D
9707 Flag!"Name".yes) for the affirmative option. When using a
9708 value of type `Flag!"Name"`, compare it against $(D
9709 Flag!"Name".yes).
9711 yes = true
9716 @safe unittest
9718 Flag!"abc" flag;
9720 assert(flag == Flag!"abc".no);
9721 assert(flag == No.abc);
9722 assert(!flag);
9723 if (flag) assert(0);
9727 @safe unittest
9729 auto flag = Yes.abc;
9731 assert(flag);
9732 assert(flag == Yes.abc);
9733 if (!flag) assert(0);
9734 if (flag) {} else assert(0);
9738 Convenience names that allow using e.g. `Yes.encryption` instead of
9739 `Flag!"encryption".yes` and `No.encryption` instead of $(D
9740 Flag!"encryption".no).
9742 struct Yes
9744 template opDispatch(string name)
9746 enum opDispatch = Flag!name.yes;
9749 //template yes(string name) { enum Flag!name yes = Flag!name.yes; }
9751 /// Ditto
9752 struct No
9754 template opDispatch(string name)
9756 enum opDispatch = Flag!name.no;
9761 @safe unittest
9763 Flag!"abc" flag;
9765 assert(flag == Flag!"abc".no);
9766 assert(flag == No.abc);
9767 assert(!flag);
9768 if (flag) assert(0);
9772 @safe unittest
9774 auto flag = Yes.abc;
9776 assert(flag);
9777 assert(flag == Yes.abc);
9778 if (!flag) assert(0);
9779 if (flag) {} else assert(0);
9783 Detect whether an enum is of integral type and has only "flag" values
9784 (i.e. values with a bit count of exactly 1).
9785 Additionally, a zero value is allowed for compatibility with enums including
9786 a "None" value.
9788 template isBitFlagEnum(E)
9790 static if (is(E Base == enum) && isIntegral!Base)
9792 enum isBitFlagEnum = (E.min >= 0) &&
9794 static foreach (immutable flag; EnumMembers!E)
9796 Base value = flag;
9797 value &= value - 1;
9798 if (value != 0) return false;
9800 return true;
9801 }();
9803 else
9805 enum isBitFlagEnum = false;
9810 @safe pure nothrow unittest
9812 enum A
9814 None,
9815 A = 1 << 0,
9816 B = 1 << 1,
9817 C = 1 << 2,
9818 D = 1 << 3,
9821 static assert(isBitFlagEnum!A);
9824 /// Test an enum with default (consecutive) values
9825 @safe pure nothrow unittest
9827 enum B
9832 D // D == 3
9835 static assert(!isBitFlagEnum!B);
9838 /// Test an enum with non-integral values
9839 @safe pure nothrow unittest
9841 enum C: double
9843 A = 1 << 0,
9844 B = 1 << 1
9847 static assert(!isBitFlagEnum!C);
9851 A typesafe structure for storing combinations of enum values.
9853 This template defines a simple struct to represent bitwise OR combinations of
9854 enum values. It can be used if all the enum values are integral constants with
9855 a bit count of at most 1, or if the `unsafe` parameter is explicitly set to
9856 Yes.
9857 This is much safer than using the enum itself to store
9858 the OR combination, which can produce surprising effects like this:
9859 ----
9860 enum E
9862 A = 1 << 0,
9863 B = 1 << 1
9865 E e = E.A | E.B;
9866 // will throw SwitchError
9867 final switch (e)
9869 case E.A:
9870 return;
9871 case E.B:
9872 return;
9874 ----
9876 struct BitFlags(E, Flag!"unsafe" unsafe = No.unsafe)
9877 if (unsafe || isBitFlagEnum!(E))
9879 @safe @nogc pure nothrow:
9880 private:
9881 enum isBaseEnumType(T) = is(E == T);
9882 alias Base = OriginalType!E;
9883 Base mValue;
9885 public:
9886 this(E flag)
9888 this = flag;
9891 this(T...)(T flags)
9892 if (allSatisfy!(isBaseEnumType, T))
9894 this = flags;
9897 bool opCast(B: bool)() const
9899 return mValue != 0;
9902 Base opCast(B)() const
9903 if (is(Base : B))
9905 return mValue;
9908 auto opUnary(string op)() const
9909 if (op == "~")
9911 return BitFlags(cast(E) cast(Base) ~mValue);
9914 auto ref opAssign(T...)(T flags)
9915 if (allSatisfy!(isBaseEnumType, T))
9917 mValue = 0;
9918 foreach (E flag; flags)
9920 mValue |= flag;
9922 return this;
9925 auto ref opAssign(E flag)
9927 mValue = flag;
9928 return this;
9931 auto ref opOpAssign(string op: "|")(BitFlags flags)
9933 mValue |= flags.mValue;
9934 return this;
9937 auto ref opOpAssign(string op: "&")(BitFlags flags)
9939 mValue &= flags.mValue;
9940 return this;
9943 auto ref opOpAssign(string op: "|")(E flag)
9945 mValue |= flag;
9946 return this;
9949 auto ref opOpAssign(string op: "&")(E flag)
9951 mValue &= flag;
9952 return this;
9955 auto opBinary(string op)(BitFlags flags) const
9956 if (op == "|" || op == "&")
9958 BitFlags result = this;
9959 result.opOpAssign!op(flags);
9960 return result;
9963 auto opBinary(string op)(E flag) const
9964 if (op == "|" || op == "&")
9966 BitFlags result = this;
9967 result.opOpAssign!op(flag);
9968 return result;
9971 auto opBinaryRight(string op)(E flag) const
9972 if (op == "|" || op == "&")
9974 return opBinary!op(flag);
9977 bool opDispatch(string name)() const
9978 if (__traits(hasMember, E, name))
9980 enum e = __traits(getMember, E, name);
9981 return (mValue & e) == e;
9984 void opDispatch(string name)(bool set)
9985 if (__traits(hasMember, E, name))
9987 enum e = __traits(getMember, E, name);
9988 if (set)
9989 mValue |= e;
9990 else
9991 mValue &= ~e;
9995 /// Set values with the | operator and test with &
9996 @safe @nogc pure nothrow unittest
9998 enum Enum
10000 A = 1 << 0,
10003 // A default constructed BitFlags has no value set
10004 immutable BitFlags!Enum flags_empty;
10005 assert(!flags_empty.A);
10007 // Value can be set with the | operator
10008 immutable flags_A = flags_empty | Enum.A;
10010 // and tested using property access
10011 assert(flags_A.A);
10013 // or the & operator
10014 assert(flags_A & Enum.A);
10015 // which commutes.
10016 assert(Enum.A & flags_A);
10019 /// A default constructed BitFlags has no value set
10020 @safe @nogc pure nothrow unittest
10022 enum Enum
10024 None,
10025 A = 1 << 0,
10026 B = 1 << 1,
10027 C = 1 << 2
10030 immutable BitFlags!Enum flags_empty;
10031 assert(!(flags_empty & (Enum.A | Enum.B | Enum.C)));
10032 assert(!(flags_empty & Enum.A) && !(flags_empty & Enum.B) && !(flags_empty & Enum.C));
10035 // BitFlags can be variadically initialized
10036 @safe @nogc pure nothrow unittest
10038 import std.traits : EnumMembers;
10040 enum Enum
10042 A = 1 << 0,
10043 B = 1 << 1,
10044 C = 1 << 2
10047 // Values can also be set using property access
10048 BitFlags!Enum flags;
10049 flags.A = true;
10050 assert(flags & Enum.A);
10051 flags.A = false;
10052 assert(!(flags & Enum.A));
10054 // BitFlags can be variadically initialized
10055 immutable BitFlags!Enum flags_AB = BitFlags!Enum(Enum.A, Enum.B);
10056 assert(flags_AB.A && flags_AB.B && !flags_AB.C);
10058 // You can use the EnumMembers template to set all flags
10059 immutable BitFlags!Enum flags_all = EnumMembers!Enum;
10060 assert(flags_all.A && flags_all.B && flags_all.C);
10063 /// Binary operations: subtracting and intersecting flags
10064 @safe @nogc pure nothrow unittest
10066 enum Enum
10068 A = 1 << 0,
10069 B = 1 << 1,
10070 C = 1 << 2,
10072 immutable BitFlags!Enum flags_AB = BitFlags!Enum(Enum.A, Enum.B);
10073 immutable BitFlags!Enum flags_BC = BitFlags!Enum(Enum.B, Enum.C);
10075 // Use the ~ operator for subtracting flags
10076 immutable BitFlags!Enum flags_B = flags_AB & ~BitFlags!Enum(Enum.A);
10077 assert(!flags_B.A && flags_B.B && !flags_B.C);
10079 // use & between BitFlags for intersection
10080 assert(flags_B == (flags_BC & flags_AB));
10083 /// All the binary operators work in their assignment version
10084 @safe @nogc pure nothrow unittest
10086 enum Enum
10088 A = 1 << 0,
10089 B = 1 << 1,
10092 BitFlags!Enum flags_empty, temp, flags_AB;
10093 flags_AB = Enum.A | Enum.B;
10095 temp |= flags_AB;
10096 assert(temp == (flags_empty | flags_AB));
10098 temp = flags_empty;
10099 temp |= Enum.B;
10100 assert(temp == (flags_empty | Enum.B));
10102 temp = flags_empty;
10103 temp &= flags_AB;
10104 assert(temp == (flags_empty & flags_AB));
10106 temp = flags_empty;
10107 temp &= Enum.A;
10108 assert(temp == (flags_empty & Enum.A));
10111 /// Conversion to bool and int
10112 @safe @nogc pure nothrow unittest
10114 enum Enum
10116 A = 1 << 0,
10117 B = 1 << 1,
10120 BitFlags!Enum flags;
10122 // BitFlags with no value set evaluate to false
10123 assert(!flags);
10125 // BitFlags with at least one value set evaluate to true
10126 flags |= Enum.A;
10127 assert(flags);
10129 // This can be useful to check intersection between BitFlags
10130 BitFlags!Enum flags_AB = Enum.A | Enum.B;
10131 assert(flags & flags_AB);
10132 assert(flags & Enum.A);
10134 // You can of course get you raw value out of flags
10135 auto value = cast(int) flags;
10136 assert(value == Enum.A);
10139 /// You need to specify the `unsafe` parameter for enums with custom values
10140 @safe @nogc pure nothrow unittest
10142 enum UnsafeEnum
10144 A = 1,
10145 B = 2,
10146 C = 4,
10147 BC = B|C
10149 static assert(!__traits(compiles, { BitFlags!UnsafeEnum flags; }));
10150 BitFlags!(UnsafeEnum, Yes.unsafe) flags;
10152 // property access tests for exact match of unsafe enums
10153 flags.B = true;
10154 assert(!flags.BC); // only B
10155 flags.C = true;
10156 assert(flags.BC); // both B and C
10157 flags.B = false;
10158 assert(!flags.BC); // only C
10160 // property access sets all bits of unsafe enum group
10161 flags = flags.init;
10162 flags.BC = true;
10163 assert(!flags.A && flags.B && flags.C);
10164 flags.A = true;
10165 flags.BC = false;
10166 assert(flags.A && !flags.B && !flags.C);
10169 // Negation of BitFlags should work with any base type.
10170 // Double-negation of BitFlags should work.
10171 @safe @nogc pure nothrow unittest
10173 static foreach (alias Base; AliasSeq!(
10174 byte,
10175 ubyte,
10176 short,
10177 ushort,
10178 int,
10179 uint,
10180 long,
10181 ulong,
10184 enum Enum : Base
10186 A = 1 << 0,
10187 B = 1 << 1,
10188 C = 1 << 2,
10191 auto flags = BitFlags!Enum(Enum.A);
10193 assert(flags == ~~flags);
10197 private enum false_(T) = false;
10199 // ReplaceType
10201 Replaces all occurrences of `From` into `To`, in one or more types `T`. For
10202 example, `ReplaceType!(int, uint, Tuple!(int, float)[string])` yields
10203 `Tuple!(uint, float)[string]`. The types in which replacement is performed
10204 may be arbitrarily complex, including qualifiers, built-in type constructors
10205 (pointers, arrays, associative arrays, functions, and delegates), and template
10206 instantiations; replacement proceeds transitively through the type definition.
10207 However, member types in `struct`s or `class`es are not replaced because there
10208 are no ways to express the types resulting after replacement.
10210 This is an advanced type manipulation necessary e.g. for replacing the
10211 placeholder type `This` in $(REF Algebraic, std,variant).
10213 Returns: `ReplaceType` aliases itself to the type(s) that result after
10214 replacement.
10216 alias ReplaceType(From, To, T...) = ReplaceTypeUnless!(false_, From, To, T);
10219 @safe unittest
10221 static assert(
10222 is(ReplaceType!(int, string, int[]) == string[]) &&
10223 is(ReplaceType!(int, string, int[int]) == string[string]) &&
10224 is(ReplaceType!(int, string, const(int)[]) == const(string)[]) &&
10225 is(ReplaceType!(int, string, Tuple!(int[], float))
10226 == Tuple!(string[], float))
10231 Like $(LREF ReplaceType), but does not perform replacement in types for which
10232 `pred` evaluates to `true`.
10234 template ReplaceTypeUnless(alias pred, From, To, T...)
10236 import std.meta;
10238 static if (T.length == 1)
10240 static if (pred!(T[0]))
10241 alias ReplaceTypeUnless = T[0];
10242 else static if (is(T[0] == From))
10243 alias ReplaceTypeUnless = To;
10244 else static if (is(T[0] == const(U), U))
10245 alias ReplaceTypeUnless = const(ReplaceTypeUnless!(pred, From, To, U));
10246 else static if (is(T[0] == immutable(U), U))
10247 alias ReplaceTypeUnless = immutable(ReplaceTypeUnless!(pred, From, To, U));
10248 else static if (is(T[0] == shared(U), U))
10249 alias ReplaceTypeUnless = shared(ReplaceTypeUnless!(pred, From, To, U));
10250 else static if (is(T[0] == U*, U))
10252 static if (is(U == function))
10253 alias ReplaceTypeUnless = replaceTypeInFunctionTypeUnless!(pred, From, To, T[0]);
10254 else
10255 alias ReplaceTypeUnless = ReplaceTypeUnless!(pred, From, To, U)*;
10257 else static if (is(T[0] == delegate))
10259 alias ReplaceTypeUnless = replaceTypeInFunctionTypeUnless!(pred, From, To, T[0]);
10261 else static if (is(T[0] == function))
10263 static assert(0, "Function types not supported," ~
10264 " use a function pointer type instead of " ~ T[0].stringof);
10266 else static if (is(T[0] == U!V, alias U, V...))
10268 template replaceTemplateArgs(T...)
10270 static if (is(typeof(T[0]))) { // template argument is value or symbol
10271 static if (__traits(compiles, { alias _ = T[0]; }))
10272 // it's a symbol
10273 alias replaceTemplateArgs = T[0];
10274 else
10275 // it's a value
10276 enum replaceTemplateArgs = T[0];
10277 } else
10278 alias replaceTemplateArgs = ReplaceTypeUnless!(pred, From, To, T[0]);
10280 alias ReplaceTypeUnless = U!(staticMap!(replaceTemplateArgs, V));
10282 else static if (is(T[0] == struct))
10283 // don't match with alias this struct below
10284 // https://issues.dlang.org/show_bug.cgi?id=15168
10285 alias ReplaceTypeUnless = T[0];
10286 else static if (is(T[0] == U[], U))
10287 alias ReplaceTypeUnless = ReplaceTypeUnless!(pred, From, To, U)[];
10288 else static if (is(T[0] == U[n], U, size_t n))
10289 alias ReplaceTypeUnless = ReplaceTypeUnless!(pred, From, To, U)[n];
10290 else static if (is(T[0] == U[V], U, V))
10291 alias ReplaceTypeUnless =
10292 ReplaceTypeUnless!(pred, From, To, U)[ReplaceTypeUnless!(pred, From, To, V)];
10293 else
10294 alias ReplaceTypeUnless = T[0];
10296 else static if (T.length > 1)
10298 alias ReplaceTypeUnless = AliasSeq!(ReplaceTypeUnless!(pred, From, To, T[0]),
10299 ReplaceTypeUnless!(pred, From, To, T[1 .. $]));
10301 else
10303 alias ReplaceTypeUnless = AliasSeq!();
10308 @safe unittest
10310 import std.traits : isArray;
10312 static assert(
10313 is(ReplaceTypeUnless!(isArray, int, string, int*) == string*) &&
10314 is(ReplaceTypeUnless!(isArray, int, string, int[]) == int[]) &&
10315 is(ReplaceTypeUnless!(isArray, int, string, Tuple!(int, int[]))
10316 == Tuple!(string, int[]))
10320 private template replaceTypeInFunctionTypeUnless(alias pred, From, To, fun)
10322 alias RX = ReplaceTypeUnless!(pred, From, To, ReturnType!fun);
10323 alias PX = AliasSeq!(ReplaceTypeUnless!(pred, From, To, Parameters!fun));
10324 // Wrapping with AliasSeq is neccesary because ReplaceType doesn't return
10325 // tuple if Parameters!fun.length == 1
10327 string gen()
10329 enum linkage = functionLinkage!fun;
10330 alias attributes = functionAttributes!fun;
10331 enum variadicStyle = variadicFunctionStyle!fun;
10332 alias storageClasses = ParameterStorageClassTuple!fun;
10334 string result;
10336 result ~= "extern(" ~ linkage ~ ") ";
10337 static if (attributes & FunctionAttribute.ref_)
10339 result ~= "ref ";
10342 result ~= "RX";
10343 static if (is(fun == delegate))
10344 result ~= " delegate";
10345 else
10346 result ~= " function";
10348 result ~= "(";
10349 static foreach (i; 0 .. PX.length)
10351 if (i)
10352 result ~= ", ";
10353 if (storageClasses[i] & ParameterStorageClass.scope_)
10354 result ~= "scope ";
10355 if (storageClasses[i] & ParameterStorageClass.in_)
10356 result ~= "in ";
10357 if (storageClasses[i] & ParameterStorageClass.out_)
10358 result ~= "out ";
10359 if (storageClasses[i] & ParameterStorageClass.ref_)
10360 result ~= "ref ";
10361 if (storageClasses[i] & ParameterStorageClass.lazy_)
10362 result ~= "lazy ";
10363 if (storageClasses[i] & ParameterStorageClass.return_)
10364 result ~= "return ";
10366 result ~= "PX[" ~ i.stringof ~ "]";
10368 static if (variadicStyle == Variadic.typesafe)
10369 result ~= " ...";
10370 else static if (variadicStyle != Variadic.no)
10371 result ~= ", ...";
10372 result ~= ")";
10374 static if (attributes & FunctionAttribute.pure_)
10375 result ~= " pure";
10376 static if (attributes & FunctionAttribute.nothrow_)
10377 result ~= " nothrow";
10378 static if (attributes & FunctionAttribute.property)
10379 result ~= " @property";
10380 static if (attributes & FunctionAttribute.trusted)
10381 result ~= " @trusted";
10382 static if (attributes & FunctionAttribute.safe)
10383 result ~= " @safe";
10384 static if (attributes & FunctionAttribute.nogc)
10385 result ~= " @nogc";
10386 static if (attributes & FunctionAttribute.system)
10387 result ~= " @system";
10388 static if (attributes & FunctionAttribute.const_)
10389 result ~= " const";
10390 static if (attributes & FunctionAttribute.immutable_)
10391 result ~= " immutable";
10392 static if (attributes & FunctionAttribute.inout_)
10393 result ~= " inout";
10394 static if (attributes & FunctionAttribute.shared_)
10395 result ~= " shared";
10396 static if (attributes & FunctionAttribute.return_)
10397 result ~= " return";
10398 static if (attributes & FunctionAttribute.live)
10399 result ~= " @live";
10401 return result;
10404 mixin("alias replaceTypeInFunctionTypeUnless = " ~ gen() ~ ";");
10407 @safe unittest
10409 template Test(Ts...)
10411 static if (Ts.length)
10413 //pragma(msg, "Testing: ReplaceType!("~Ts[0].stringof~", "
10414 // ~Ts[1].stringof~", "~Ts[2].stringof~")");
10415 static assert(is(ReplaceType!(Ts[0], Ts[1], Ts[2]) == Ts[3]),
10416 "ReplaceType!("~Ts[0].stringof~", "~Ts[1].stringof~", "
10417 ~Ts[2].stringof~") == "
10418 ~ReplaceType!(Ts[0], Ts[1], Ts[2]).stringof);
10419 alias Test = Test!(Ts[4 .. $]);
10421 else alias Test = void;
10424 //import core.stdc.stdio;
10425 alias RefFun1 = ref int function(float, long);
10426 alias RefFun2 = ref float function(float, long);
10427 extern(C) int printf(const char*, ...) nothrow @nogc @system;
10428 extern(C) float floatPrintf(const char*, ...) nothrow @nogc @system;
10429 int func(float);
10431 int x;
10432 struct S1 { void foo() { x = 1; } }
10433 struct S2 { void bar() { x = 2; } }
10435 alias Pass = Test!(
10436 int, float, typeof(&func), float delegate(float),
10437 int, float, typeof(&printf), typeof(&floatPrintf),
10438 int, float, int function(out long, ...),
10439 float function(out long, ...),
10440 int, float, int function(ref float, long),
10441 float function(ref float, long),
10442 int, float, int function(ref int, long),
10443 float function(ref float, long),
10444 int, float, int function(out int, long),
10445 float function(out float, long),
10446 int, float, int function(lazy int, long),
10447 float function(lazy float, long),
10448 int, float, int function(out long, ref const int),
10449 float function(out long, ref const float),
10450 int, float, int function(in long, ref const int),
10451 float function(in long, ref const float),
10452 int, float, int function(long, in int),
10453 float function(long, in float),
10454 int, int, int, int,
10455 int, float, int, float,
10456 int, float, const int, const float,
10457 int, float, immutable int, immutable float,
10458 int, float, shared int, shared float,
10459 int, float, int*, float*,
10460 int, float, const(int)*, const(float)*,
10461 int, float, const(int*), const(float*),
10462 const(int)*, float, const(int*), const(float),
10463 int*, float, const(int)*, const(int)*,
10464 int, float, int[], float[],
10465 int, float, int[42], float[42],
10466 int, float, const(int)[42], const(float)[42],
10467 int, float, const(int[42]), const(float[42]),
10468 int, float, int[int], float[float],
10469 int, float, int[double], float[double],
10470 int, float, double[int], double[float],
10471 int, float, int function(float, long), float function(float, long),
10472 int, float, int function(float), float function(float),
10473 int, float, int function(float, int), float function(float, float),
10474 int, float, int delegate(float, long), float delegate(float, long),
10475 int, float, int delegate(float), float delegate(float),
10476 int, float, int delegate(float, int), float delegate(float, float),
10477 int, float, Unique!int, Unique!float,
10478 int, float, Tuple!(float, int), Tuple!(float, float),
10479 int, float, RefFun1, RefFun2,
10480 S1, S2,
10481 S1[1][][S1]* function(),
10482 S2[1][][S2]* function(),
10483 int, string,
10484 int[3] function( int[] arr, int[2] ...) pure @trusted,
10485 string[3] function(string[] arr, string[2] ...) pure @trusted,
10488 // https://issues.dlang.org/show_bug.cgi?id=15168
10489 static struct T1 { string s; alias s this; }
10490 static struct T2 { char[10] s; alias s this; }
10491 static struct T3 { string[string] s; alias s this; }
10492 alias Pass2 = Test!(
10493 ubyte, ubyte, T1, T1,
10494 ubyte, ubyte, T2, T2,
10495 ubyte, ubyte, T3, T3,
10499 // https://issues.dlang.org/show_bug.cgi?id=17116
10500 @safe unittest
10502 alias ConstDg = void delegate(float) const;
10503 alias B = void delegate(int) const;
10504 alias A = ReplaceType!(float, int, ConstDg);
10505 static assert(is(B == A));
10508 // https://issues.dlang.org/show_bug.cgi?id=19696
10509 @safe unittest
10511 static struct T(U) {}
10512 static struct S { T!int t; alias t this; }
10513 static assert(is(ReplaceType!(float, float, S) == S));
10516 // https://issues.dlang.org/show_bug.cgi?id=19697
10517 @safe unittest
10519 class D(T) {}
10520 class C : D!C {}
10521 static assert(is(ReplaceType!(float, float, C)));
10524 // https://issues.dlang.org/show_bug.cgi?id=16132
10525 @safe unittest
10527 interface I(T) {}
10528 class C : I!int {}
10529 static assert(is(ReplaceType!(int, string, C) == C));
10532 // https://issues.dlang.org/show_bug.cgi?id=22325
10533 @safe unittest
10535 static struct Foo(alias f) {}
10536 static void bar() {}
10537 alias _ = ReplaceType!(int, int, Foo!bar);
10541 Ternary type with three truth values:
10543 $(UL
10544 $(LI `Ternary.yes` for `true`)
10545 $(LI `Ternary.no` for `false`)
10546 $(LI `Ternary.unknown` as an unknown state)
10549 Also known as trinary, trivalent, or trilean.
10551 See_Also:
10552 $(HTTP en.wikipedia.org/wiki/Three-valued_logic,
10553 Three Valued Logic on Wikipedia)
10555 struct Ternary
10557 @safe @nogc nothrow pure:
10559 private ubyte value = 6;
10560 private static Ternary make(ubyte b)
10562 Ternary r = void;
10563 r.value = b;
10564 return r;
10568 The possible states of the `Ternary`
10570 enum no = make(0);
10571 /// ditto
10572 enum yes = make(2);
10573 /// ditto
10574 enum unknown = make(6);
10577 Construct and assign from a `bool`, receiving `no` for `false` and `yes`
10578 for `true`.
10580 this(bool b) { value = b << 1; }
10582 /// ditto
10583 void opAssign(bool b) { value = b << 1; }
10586 Construct a ternary value from another ternary value
10588 this(const Ternary b) { value = b.value; }
10591 $(TABLE Truth table for logical operations,
10592 $(TR $(TH `a`) $(TH `b`) $(TH `$(TILDE)a`) $(TH `a | b`) $(TH `a & b`) $(TH `a ^ b`))
10593 $(TR $(TD `no`) $(TD `no`) $(TD `yes`) $(TD `no`) $(TD `no`) $(TD `no`))
10594 $(TR $(TD `no`) $(TD `yes`) $(TD) $(TD `yes`) $(TD `no`) $(TD `yes`))
10595 $(TR $(TD `no`) $(TD `unknown`) $(TD) $(TD `unknown`) $(TD `no`) $(TD `unknown`))
10596 $(TR $(TD `yes`) $(TD `no`) $(TD `no`) $(TD `yes`) $(TD `no`) $(TD `yes`))
10597 $(TR $(TD `yes`) $(TD `yes`) $(TD) $(TD `yes`) $(TD `yes`) $(TD `no`))
10598 $(TR $(TD `yes`) $(TD `unknown`) $(TD) $(TD `yes`) $(TD `unknown`) $(TD `unknown`))
10599 $(TR $(TD `unknown`) $(TD `no`) $(TD `unknown`) $(TD `unknown`) $(TD `no`) $(TD `unknown`))
10600 $(TR $(TD `unknown`) $(TD `yes`) $(TD) $(TD `yes`) $(TD `unknown`) $(TD `unknown`))
10601 $(TR $(TD `unknown`) $(TD `unknown`) $(TD) $(TD `unknown`) $(TD `unknown`) $(TD `unknown`))
10604 Ternary opUnary(string s)() if (s == "~")
10606 return make((386 >> value) & 6);
10609 /// ditto
10610 Ternary opBinary(string s)(Ternary rhs) if (s == "|")
10612 return make((25_512 >> (value + rhs.value)) & 6);
10615 /// ditto
10616 Ternary opBinary(string s)(Ternary rhs) if (s == "&")
10618 return make((26_144 >> (value + rhs.value)) & 6);
10621 /// ditto
10622 Ternary opBinary(string s)(Ternary rhs) if (s == "^")
10624 return make((26_504 >> (value + rhs.value)) & 6);
10627 /// ditto
10628 Ternary opBinary(string s)(bool rhs)
10629 if (s == "|" || s == "&" || s == "^")
10631 return this.opBinary!s(Ternary(rhs));
10636 @safe @nogc nothrow pure
10637 unittest
10639 Ternary a;
10640 assert(a == Ternary.unknown);
10642 assert(~Ternary.yes == Ternary.no);
10643 assert(~Ternary.no == Ternary.yes);
10644 assert(~Ternary.unknown == Ternary.unknown);
10647 @safe @nogc nothrow pure
10648 unittest
10650 alias f = Ternary.no, t = Ternary.yes, u = Ternary.unknown;
10651 Ternary[27] truthTableAnd =
10653 t, t, t,
10654 t, u, u,
10655 t, f, f,
10656 u, t, u,
10657 u, u, u,
10658 u, f, f,
10659 f, t, f,
10660 f, u, f,
10661 f, f, f,
10664 Ternary[27] truthTableOr =
10666 t, t, t,
10667 t, u, t,
10668 t, f, t,
10669 u, t, t,
10670 u, u, u,
10671 u, f, u,
10672 f, t, t,
10673 f, u, u,
10674 f, f, f,
10677 Ternary[27] truthTableXor =
10679 t, t, f,
10680 t, u, u,
10681 t, f, t,
10682 u, t, u,
10683 u, u, u,
10684 u, f, u,
10685 f, t, t,
10686 f, u, u,
10687 f, f, f,
10690 for (auto i = 0; i != truthTableAnd.length; i += 3)
10692 assert((truthTableAnd[i] & truthTableAnd[i + 1])
10693 == truthTableAnd[i + 2]);
10694 assert((truthTableOr[i] | truthTableOr[i + 1])
10695 == truthTableOr[i + 2]);
10696 assert((truthTableXor[i] ^ truthTableXor[i + 1])
10697 == truthTableXor[i + 2]);
10700 Ternary a;
10701 assert(a == Ternary.unknown);
10702 static assert(!is(typeof({ if (a) {} })));
10703 assert(!is(typeof({ auto b = Ternary(3); })));
10704 a = true;
10705 assert(a == Ternary.yes);
10706 a = false;
10707 assert(a == Ternary.no);
10708 a = Ternary.unknown;
10709 assert(a == Ternary.unknown);
10710 Ternary b;
10711 b = a;
10712 assert(b == a);
10713 assert(~Ternary.yes == Ternary.no);
10714 assert(~Ternary.no == Ternary.yes);
10715 assert(~Ternary.unknown == Ternary.unknown);
10718 @safe @nogc nothrow pure
10719 unittest
10721 Ternary a = Ternary(true);
10722 assert(a == Ternary.yes);
10723 assert((a & false) == Ternary.no);
10724 assert((a | false) == Ternary.yes);
10725 assert((a ^ true) == Ternary.no);
10726 assert((a ^ false) == Ternary.yes);
10729 // https://issues.dlang.org/show_bug.cgi?id=22511
10730 @safe unittest
10732 static struct S
10734 int b;
10735 @disable this(this);
10736 this(ref return scope inout S rhs) inout
10738 this.b = rhs.b + 1;
10742 Nullable!S s1 = S(1);
10743 assert(s1.get().b == 2);
10744 Nullable!S s2 = s1;
10745 assert(s2.get().b == 3);
10748 @safe unittest
10750 static struct S
10752 int b;
10753 this(this) { ++b; }
10756 Nullable!S s1 = S(1);
10757 assert(s1.get().b == 2);
10758 Nullable!S s2 = s1;
10759 assert(s2.get().b == 3);
10762 // https://issues.dlang.org/show_bug.cgi?id=24318
10763 @system unittest
10765 static struct S
10767 @disable this(this);
10768 int i;
10771 Nullable!S s = S(1);
10772 assert(s.get().i == 1);
10773 s = S(2);
10774 assert(s.get().i == 2);
10777 /// The old version of $(LREF SafeRefCounted), before $(LREF borrow) existed.
10778 /// Old code may be relying on `@safe`ty of some of the member functions which
10779 /// cannot be safe in the new scheme, and
10780 /// can avoid breakage by continuing to use this. `SafeRefCounted` should be
10781 /// preferred, as this type is outdated and unrecommended for new code.
10782 struct RefCounted(T, RefCountedAutoInitialize autoInit =
10783 RefCountedAutoInitialize.yes)
10785 version (D_BetterC)
10787 private enum enableGCScan = false;
10789 else
10791 private enum enableGCScan = hasIndirections!T;
10794 extern(C) private pure nothrow @nogc static
10796 pragma(mangle, "free") void pureFree( void *ptr );
10797 static if (enableGCScan)
10798 import core.memory : GC;
10801 struct RefCountedStore
10803 private struct Impl
10805 T _payload;
10806 size_t _count;
10809 private Impl* _store;
10811 private void initialize(A...)(auto ref A args)
10813 import core.lifetime : emplace, forward;
10815 allocateStore();
10816 version (D_Exceptions) scope(failure) deallocateStore();
10817 emplace(&_store._payload, forward!args);
10818 _store._count = 1;
10821 private void move(ref T source) nothrow pure
10823 import std.algorithm.mutation : moveEmplace;
10825 allocateStore();
10826 moveEmplace(source, _store._payload);
10827 _store._count = 1;
10830 // 'nothrow': can only generate an Error
10831 private void allocateStore() nothrow pure
10833 static if (enableGCScan)
10835 import std.internal.memory : enforceCalloc;
10836 _store = cast(Impl*) enforceCalloc(1, Impl.sizeof);
10837 GC.addRange(&_store._payload, T.sizeof);
10839 else
10841 import std.internal.memory : enforceMalloc;
10842 _store = cast(Impl*) enforceMalloc(Impl.sizeof);
10846 private void deallocateStore() nothrow pure
10848 static if (enableGCScan)
10850 GC.removeRange(&this._store._payload);
10852 pureFree(_store);
10853 _store = null;
10856 @property nothrow @safe pure @nogc
10857 bool isInitialized() const
10859 return _store !is null;
10862 @property nothrow @safe pure @nogc
10863 size_t refCount() const
10865 return isInitialized ? _store._count : 0;
10868 void ensureInitialized()()
10870 // By checking for `@disable this()` and failing early we can
10871 // produce a clearer error message.
10872 static assert(__traits(compiles, { static T t; }),
10873 "Cannot automatically initialize `" ~ fullyQualifiedName!T ~
10874 "` because `" ~ fullyQualifiedName!T ~
10875 ".this()` is annotated with `@disable`.");
10876 if (!isInitialized) initialize();
10880 RefCountedStore _refCounted;
10882 @property nothrow @safe
10883 ref inout(RefCountedStore) refCountedStore() inout
10885 return _refCounted;
10888 this(A...)(auto ref A args) if (A.length > 0)
10891 assert(refCountedStore.isInitialized);
10895 import core.lifetime : forward;
10896 _refCounted.initialize(forward!args);
10899 this(T val)
10901 _refCounted.move(val);
10904 this(this) @safe pure nothrow @nogc
10906 if (!_refCounted.isInitialized) return;
10907 ++_refCounted._store._count;
10910 ~this()
10912 if (!_refCounted.isInitialized) return;
10913 assert(_refCounted._store._count > 0);
10914 if (--_refCounted._store._count)
10915 return;
10916 // Done, destroy and deallocate
10917 .destroy(_refCounted._store._payload);
10918 _refCounted.deallocateStore();
10921 void opAssign(typeof(this) rhs)
10923 import std.algorithm.mutation : swap;
10925 swap(_refCounted._store, rhs._refCounted._store);
10928 void opAssign(T rhs)
10930 import std.algorithm.mutation : move;
10932 static if (autoInit == RefCountedAutoInitialize.yes)
10934 _refCounted.ensureInitialized();
10936 else
10938 assert(_refCounted.isInitialized);
10940 move(rhs, _refCounted._store._payload);
10943 static if (autoInit == RefCountedAutoInitialize.yes)
10945 //Can't use inout here because of potential mutation
10946 @property
10947 ref T refCountedPayload() return
10949 _refCounted.ensureInitialized();
10950 return _refCounted._store._payload;
10954 @property nothrow @safe pure @nogc
10955 ref inout(T) refCountedPayload() inout return
10957 assert(_refCounted.isInitialized, "Attempted to access an uninitialized payload.");
10958 return _refCounted._store._payload;
10961 alias refCountedPayload this;
10963 static if (is(T == struct) && !is(typeof((ref T t) => t.toString())))
10965 string toString(this This)()
10967 import std.conv : to;
10969 static if (autoInit)
10970 return to!string(refCountedPayload);
10971 else
10973 if (!_refCounted.isInitialized)
10974 return This.stringof ~ "(RefCountedStore(null))";
10975 else
10976 return to!string(_refCounted._store._payload);
10983 @betterC pure @system nothrow @nogc unittest
10985 auto rc1 = RefCounted!int(5);
10986 assert(rc1 == 5);
10987 auto rc2 = rc1;
10988 rc2 = 42;
10989 assert(rc1 == 42);
10992 // More unit tests below SafeRefCounted
10995 * Like $(LREF safeRefCounted) but used to initialize $(LREF RefCounted)
10996 * instead. Intended for backwards compatibility, otherwise it is preferable
10997 * to use `safeRefCounted`.
10999 RefCounted!(T, RefCountedAutoInitialize.no) refCounted(T)(T val)
11001 typeof(return) res;
11002 res._refCounted.move(val);
11003 return res;
11007 @system unittest
11009 static struct File
11011 static size_t nDestroyed;
11012 string name;
11013 @disable this(this); // not copyable
11014 ~this() { name = null; ++nDestroyed; }
11017 auto file = File("name");
11018 assert(file.name == "name");
11019 static assert(!__traits(compiles, {auto file2 = file;}));
11020 assert(File.nDestroyed == 0);
11023 import std.algorithm.mutation : move;
11024 auto rcFile = refCounted(move(file));
11025 assert(rcFile.name == "name");
11026 assert(File.nDestroyed == 1);
11027 assert(file.name == null);
11029 auto rcFile2 = rcFile;
11030 assert(rcFile.refCountedStore.refCount == 2);
11031 assert(File.nDestroyed == 1);
11034 assert(File.nDestroyed == 2);
11037 // More unit tests below safeRefCounted