xref: /netbsd-src/external/gpl3/gcc/dist/libphobos/src/std/typecons.d (revision 0a3071956a3a9fdebdbf7f338cf2d439b45fc728)
1 // Written in the D programming language.
2 
3 /**
4 This module implements a variety of type constructors, i.e., templates
5 that allow construction of new, useful general-purpose types.
6 
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)
16 ))
17 $(TR $(TD Flags) $(TD
18     $(LREF BitFlags)
19     $(LREF isBitFlagEnum)
20     $(LREF Flag)
21     $(LREF No)
22     $(LREF Yes)
23 ))
24 $(TR $(TD Memory allocation) $(TD
25     $(LREF RefCounted)
26     $(LREF refCounted)
27     $(LREF RefCountedAutoInitialize)
28     $(LREF scoped)
29     $(LREF Unique)
30 ))
31 $(TR $(TD Code generation) $(TD
32     $(LREF AutoImplement)
33     $(LREF BlackHole)
34     $(LREF generateAssertTrap)
35     $(LREF generateEmptyFunction)
36     $(LREF WhiteHole)
37 ))
38 $(TR $(TD Nullable) $(TD
39     $(LREF Nullable)
40     $(LREF nullable)
41     $(LREF NullableRef)
42     $(LREF nullableRef)
43 ))
44 $(TR $(TD Proxies) $(TD
45     $(LREF Proxy)
46     $(LREF rebindable)
47     $(LREF Rebindable)
48     $(LREF ReplaceType)
49     $(LREF unwrap)
50     $(LREF wrap)
51 ))
52 $(TR $(TD Types) $(TD
53     $(LREF alignForSize)
54     $(LREF Ternary)
55     $(LREF Typedef)
56     $(LREF TypedefType)
57     $(LREF UnqualRef)
58 ))
59 ))
60 
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
69  */
70 module std.typecons;
71 
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;
78 
79 /// Value tuples
80 @safe unittest
81 {
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));
87 
88     // names can be omitted, types can be mixed
89     alias DictEntry = Tuple!(string, int);
90     auto dict = DictEntry("seven", 7);
91 
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);
97 }
98 
99 /// Rebindable references to const and immutable objects
100 @safe unittest
101 {
102     class Widget
103     {
foo()104         void foo() const @safe {}
105     }
106     const w1 = new Widget, w2 = new Widget;
107     w1.foo();
108     // w1 = w2 would not work; can't rebind const object
109 
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;
115 }
116 
117 /**
118 Encapsulates unique ownership of a resource.
119 
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.
128 
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.
135 
136 If `T` is a value type, then `Unique!T` will be implemented
137 as a reference to a `T`.
138 */
Unique(T)139 struct Unique(T)
140 {
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*;
146 
147 public:
148     // Deferred in case we get some language support for checking uniqueness.
149     version (None)
150     /**
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.
157     ---
158     static class C {}
159     auto u = Unique!(C).create();
160     ---
161     */
162     static Unique!T create(A...)(auto ref A args)
163     if (__traits(compiles, new T(args)))
164     {
165         Unique!T u;
166         u._p = new T(args);
167         return u;
168     }
169 
170     /**
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     ----
178     */
179     this(RefT p)
180     {
181         _p = p;
182     }
183     /**
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.
187     */
188     this(ref RefT p)
189     {
190         _p = p;
191         p = null;
192         assert(p is null);
193     }
194     /**
195     Constructor that takes a `Unique` of a type that is convertible to our type.
196 
197     Typically used to transfer a `Unique` rvalue of derived type to
198     a `Unique` of base type.
199     Example:
200     ---
201     class C : Object {}
202 
203     Unique!C uc = new C;
204     Unique!Object uo = uc.release;
205     ---
206     */
207     this(U)(Unique!U u)
208     if (is(u.RefT:RefT))
209     {
210         _p = u._p;
211         u._p = null;
212     }
213 
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))
217     {
218         // first delete any resource we own
219         destroy(this);
220         _p = u._p;
221         u._p = null;
222     }
223 
224     ~this()
225     {
226         if (_p !is null)
227         {
228             destroy(_p);
229             _p = null;
230         }
231     }
232 
233     /** Returns whether the resource exists. */
234     @property bool isEmpty() const
235     {
236         return _p is null;
237     }
238     /** Transfer ownership to a `Unique` rvalue. Nullifies the current contents.
239     Same as calling std.algorithm.move on it.
240     */
241     Unique release()
242     {
243         import std.algorithm.mutation : move;
244         return this.move;
245     }
246 
247     /** Forwards member access to contents. */
248     mixin Proxy!_p;
249 
250     /**
251     Postblit operator is undefined to prevent the cloning of `Unique` objects.
252     */
253     @disable this(this);
254 
255 private:
256     RefT _p;
257 }
258 
259 ///
260 @safe unittest
261 {
262     static struct S
263     {
264         int i;
thisS265         this(int i){this.i = i;}
266     }
267     Unique!S produce()
268     {
269         // Construct a unique instance of S on the heap
270         Unique!S ut = new S(5);
271         // Implicit transfer of ownership
272         return ut;
273     }
274     // Borrow a unique resource by ref
275     void increment(ref Unique!S ur)
276     {
277         ur.i++;
278     }
279     void consume(Unique!S u2)
280     {
281         assert(u2.i == 6);
282         // Resource automatically deleted here
283     }
284     Unique!S u1;
285     assert(u1.isEmpty);
286     u1 = produce();
287     increment(u1);
288     assert(u1.i == 6);
289     //consume(u1); // Error: u1 is not copyable
290     // Transfer ownership of the resource
291     consume(u1.release);
292     assert(u1.isEmpty);
293 }
294 
295 @system unittest
296 {
297     // test conversion to base ref
298     int deleted = 0;
299     class C
300     {
~this()301         ~this(){deleted++;}
302     }
303     // constructor conversion
304     Unique!Object u = Unique!C(new C);
305     static assert(!__traits(compiles, {u = new C;}));
306     assert(!u.isEmpty);
307     destroy(u);
308     assert(deleted == 1);
309 
310     Unique!C uc = new C;
311     static assert(!__traits(compiles, {Unique!Object uo = uc;}));
312     Unique!Object uo = new C;
313     // opAssign conversion, deleting uo resource first
314     uo = uc.release;
315     assert(uc.isEmpty);
316     assert(!uo.isEmpty);
317     assert(deleted == 2);
318 }
319 
320 @system unittest
321 {
322     class Bar
323     {
~this()324         ~this() { debug(Unique) writeln("    Bar destructor"); }
val()325         int val() const { return 4; }
326     }
327     alias UBar = Unique!(Bar);
g(UBar u)328     UBar g(UBar u)
329     {
330         debug(Unique) writeln("inside g");
331         return u.release;
332     }
333     auto ub = UBar(new Bar);
334     assert(!ub.isEmpty);
335     assert(ub.val == 4);
336     static assert(!__traits(compiles, {auto ub3 = g(ub);}));
337     auto ub2 = g(ub.release);
338     assert(ub.isEmpty);
339     assert(!ub2.isEmpty);
340 }
341 
342 @system unittest
343 {
344     interface Bar
345     {
346         int val() const;
347     }
348     class BarImpl : Bar
349     {
350         static int count;
this()351         this()
352         {
353             count++;
354         }
~this()355         ~this()
356         {
357             count--;
358         }
val()359         int val() const { return 4; }
360     }
361     alias UBar = Unique!Bar;
g(UBar u)362     UBar g(UBar u)
363     {
364         debug(Unique) writeln("inside g");
365         return u.release;
366     }
consume(UBar u)367     void consume(UBar u)
368     {
369         assert(u.val() == 4);
370         // Resource automatically deleted here
371     }
372     auto ub = UBar(new BarImpl);
373     assert(BarImpl.count == 1);
374     assert(!ub.isEmpty);
375     assert(ub.val == 4);
376     static assert(!__traits(compiles, {auto ub3 = g(ub);}));
377     auto ub2 = g(ub.release);
378     assert(ub.isEmpty);
379     assert(!ub2.isEmpty);
380     consume(ub2.release);
381     assert(BarImpl.count == 0);
382 }
383 
384 @safe unittest
385 {
386     struct Foo
387     {
~thisFoo388         ~this() { }
valFoo389         int val() const { return 3; }
390         @disable this(this);
391     }
392     alias UFoo = Unique!(Foo);
393 
f(UFoo u)394     UFoo f(UFoo u)
395     {
396         return u.release;
397     }
398 
399     auto uf = UFoo(new Foo);
400     assert(!uf.isEmpty);
401     assert(uf.val == 3);
402     static assert(!__traits(compiles, {auto uf3 = f(uf);}));
403     auto uf2 = f(uf.release);
404     assert(uf.isEmpty);
405     assert(!uf2.isEmpty);
406 }
407 
408 // ensure Unique behaves correctly through const access paths
409 @system unittest
410 {
411     struct Bar {int val;}
412     struct Foo
413     {
414         Unique!Bar bar = new Bar;
415     }
416 
417     Foo foo;
418     foo.bar.val = 6;
419     const Foo* ptr = &foo;
420     static assert(is(typeof(ptr) == const(Foo*)));
421     static assert(is(typeof(ptr.bar) == const(Unique!Bar)));
422     static assert(is(typeof(ptr.bar.val) == const(int)));
423     assert(ptr.bar.val == 6);
424     foo.bar.val = 7;
425     assert(ptr.bar.val == 7);
426 }
427 
428 // Used in Tuple.toString
429 private template sharedToString(alias field)
430 if (is(typeof(field) == shared))
431 {
432     static immutable sharedToString = typeof(field).stringof;
433 }
434 
435 private template sharedToString(alias field)
436 if (!is(typeof(field) == shared))
437 {
438     alias sharedToString = field;
439 }
440 
441 private enum bool distinctFieldNames(names...) = __traits(compiles,
442 {
443     static foreach (__name; names)
444         static if (is(typeof(__name) : string))
445             mixin("enum int " ~ __name ~ " = 0;");
446 });
447 
448 @safe unittest
449 {
450     static assert(!distinctFieldNames!(string, "abc", string, "abc"));
451     static assert(distinctFieldNames!(string, "abc", int, "abd"));
452     static assert(!distinctFieldNames!(int, "abc", string, "abd", int, "abc"));
453     // https://issues.dlang.org/show_bug.cgi?id=19240
454     static assert(!distinctFieldNames!(int, "int"));
455 }
456 
457 
458 // Parse (type,name) pairs (FieldSpecs) out of the specified
459 // arguments. Some fields would have name, others not.
parseSpecs(Specs...)460 private template parseSpecs(Specs...)
461 {
462     static if (Specs.length == 0)
463     {
464         alias parseSpecs = AliasSeq!();
465     }
466     else static if (is(Specs[0]))
467     {
468         static if (is(typeof(Specs[1]) : string))
469         {
470             alias parseSpecs =
471                 AliasSeq!(FieldSpec!(Specs[0 .. 2]),
472                           parseSpecs!(Specs[2 .. $]));
473         }
474         else
475         {
476             alias parseSpecs =
477                 AliasSeq!(FieldSpec!(Specs[0]),
478                           parseSpecs!(Specs[1 .. $]));
479         }
480     }
481     else
482     {
483         static assert(0, "Attempted to instantiate Tuple with an "
484                         ~"invalid argument: "~ Specs[0].stringof);
485     }
486 }
487 
488 private template FieldSpec(T, string s = "")
489 {
490     alias Type = T;
491     alias name = s;
492 }
493 
494 // Used with staticMap.
495 private alias extractType(alias spec) = spec.Type;
496 private alias extractName(alias spec) = spec.name;
expandSpec(alias spec)497 private template expandSpec(alias spec)
498 {
499     static if (spec.name.length == 0)
500         alias expandSpec = AliasSeq!(spec.Type);
501     else
502         alias expandSpec = AliasSeq!(spec.Type, spec.name);
503 }
504 
505 
506 private enum areCompatibleTuples(Tup1, Tup2, string op) =
507     isTuple!(OriginalType!Tup2) && Tup1.Types.length == Tup2.Types.length && is(typeof(
508     (ref Tup1 tup1, ref Tup2 tup2)
509     {
510         static foreach (i; 0 .. Tup1.Types.length)
511         {{
512             auto lhs = typeof(tup1.field[i]).init;
513             auto rhs = typeof(tup2.field[i]).init;
514             static if (op == "=")
515                 lhs = rhs;
516             else
517                 auto result = mixin("lhs "~op~" rhs");
518         }}
519     }));
520 
521 private enum areBuildCompatibleTuples(Tup1, Tup2) =
522     isTuple!Tup2 && Tup1.Types.length == Tup2.Types.length && is(typeof(
523     {
524         static foreach (i; 0 .. Tup1.Types.length)
525             static assert(isBuildable!(Tup1.Types[i], Tup2.Types[i]));
526     }));
527 
528 // Returns `true` iff a `T` can be initialized from a `U`.
529 private enum isBuildable(T, U) = is(typeof(
530     {
531         U u = U.init;
532         T t = u;
533     }));
534 // Helper for partial instantiation
isBuildableFrom(U)535 private template isBuildableFrom(U)
536 {
537     enum isBuildableFrom(T) = isBuildable!(T, U);
538 }
539 
540 
541 /**
542 _Tuple of values, for example $(D Tuple!(int, string)) is a record that
543 stores an `int` and a `string`. `Tuple` can be used to bundle
544 values together, notably when returning multiple values from a
545 function. If `obj` is a `Tuple`, the individual members are
546 accessible with the syntax `obj[0]` for the first field, `obj[1]`
547 for the second, and so on.
548 
549 See_Also: $(LREF tuple).
550 
551 Params:
552     Specs = A list of types (and optionally, member names) that the `Tuple` contains.
553 */
554 template Tuple(Specs...)
555 if (distinctFieldNames!(Specs))
556 {
557     import std.meta : staticMap;
558 
559     alias fieldSpecs = parseSpecs!Specs;
560 
561     // Generates named fields as follows:
562     //    alias name_0 = Identity!(field[0]);
563     //    alias name_1 = Identity!(field[1]);
564     //      :
565     // NOTE: field[k] is an expression (which yields a symbol of a
566     //       variable) and can't be aliased directly.
567     enum injectNamedFields = ()
568     {
569         string decl = "";
foreach(i,val;fieldSpecs)570         static foreach (i, val; fieldSpecs)
571         {{
572             immutable si = i.stringof;
573             decl ~= "alias _" ~ si ~ " = Identity!(field[" ~ si ~ "]);";
574             if (val.name.length != 0)
575             {
576                 decl ~= "alias " ~ val.name ~ " = _" ~ si ~ ";";
577             }
578         }}
579         return decl;
580     };
581 
582     // Returns Specs for a subtuple this[from .. to] preserving field
583     // names if any.
584     alias sliceSpecs(size_t from, size_t to) =
585         staticMap!(expandSpec, fieldSpecs[from .. to]);
586 
587     struct Tuple
588     {
589         /**
590          * The types of the `Tuple`'s components.
591          */
592         alias Types = staticMap!(extractType, fieldSpecs);
593 
594         private alias _Fields = Specs;
595 
596         ///
597         static if (Specs.length == 0) @safe unittest
598         {
599             import std.meta : AliasSeq;
600             alias Fields = Tuple!(int, "id", string, float);
601             static assert(is(Fields.Types == AliasSeq!(int, string, float)));
602         }
603 
604         /**
605          * The names of the `Tuple`'s components. Unnamed fields have empty names.
606          */
607         alias fieldNames = staticMap!(extractName, fieldSpecs);
608 
609         ///
610         static if (Specs.length == 0) @safe unittest
611         {
612             import std.meta : AliasSeq;
613             alias Fields = Tuple!(int, "id", string, float);
614             static assert(Fields.fieldNames == AliasSeq!("id", "", ""));
615         }
616 
617         /**
618          * Use `t.expand` for a `Tuple` `t` to expand it into its
619          * components. The result of `expand` acts as if the `Tuple`'s components
620          * were listed as a list of values. (Ordinarily, a `Tuple` acts as a
621          * single value.)
622          */
623         Types expand;
624         mixin(injectNamedFields());
625 
626         ///
627         static if (Specs.length == 0) @safe unittest
628         {
629             auto t1 = tuple(1, " hello ", 'a');
630             assert(t1.toString() == `Tuple!(int, string, char)(1, " hello ", 'a')`);
631 
takeSeveralTypesTuple632             void takeSeveralTypes(int n, string s, bool b)
633             {
634                 assert(n == 4 && s == "test" && b == false);
635             }
636 
637             auto t2 = tuple(4, "test", false);
638             //t.expand acting as a list of values
639             takeSeveralTypes(t2.expand);
640         }
641 
642         static if (is(Specs))
643         {
644             // This is mostly to make t[n] work.
645             alias expand this;
646         }
647         else
648         {
649             @property
_Tuple_superTuple650             ref inout(Tuple!Types) _Tuple_super() inout @trusted
651             {
652                 static foreach (i; 0 .. Types.length)   // Rely on the field layout
653                 {
654                     static assert(typeof(return).init.tupleof[i].offsetof ==
655                                                        expand[i].offsetof);
656                 }
657                 return *cast(typeof(return)*) &(field[0]);
658             }
659             // This is mostly to make t[n] work.
660             alias _Tuple_super this;
661         }
662 
663         // backwards compatibility
664         alias field = expand;
665 
666         /**
667          * Constructor taking one value for each field.
668          *
669          * Params:
670          *     values = A list of values that are either the same
671          *              types as those given by the `Types` field
672          *              of this `Tuple`, or can implicitly convert
673          *              to those types. They must be in the same
674          *              order as they appear in `Types`.
675          */
676         static if (Types.length > 0)
677         {
thisTuple678             this(Types values)
679             {
680                 field[] = values[];
681             }
682         }
683 
684         ///
685         static if (Specs.length == 0) @safe unittest
686         {
687             alias ISD = Tuple!(int, string, double);
688             auto tup = ISD(1, "test", 3.2);
689             assert(tup.toString() == `Tuple!(int, string, double)(1, "test", 3.2)`);
690         }
691 
692         /**
693          * Constructor taking a compatible array.
694          *
695          * Params:
696          *     values = A compatible static array to build the `Tuple` from.
697          *              Array slices are not supported.
698          */
699         this(U, size_t n)(U[n] values)
700         if (n == Types.length && allSatisfy!(isBuildableFrom!U, Types))
701         {
702             static foreach (i; 0 .. Types.length)
703             {
704                 field[i] = values[i];
705             }
706         }
707 
708         ///
709         static if (Specs.length == 0) @safe unittest
710         {
711             int[2] ints;
712             Tuple!(int, int) t = ints;
713         }
714 
715         /**
716          * Constructor taking a compatible `Tuple`. Two `Tuple`s are compatible
717          * $(B iff) they are both of the same length, and, for each type `T` on the
718          * left-hand side, the corresponding type `U` on the right-hand side can
719          * implicitly convert to `T`.
720          *
721          * Params:
722          *     another = A compatible `Tuple` to build from. Its type must be
723          *               compatible with the target `Tuple`'s type.
724          */
725         this(U)(U another)
726         if (areBuildCompatibleTuples!(typeof(this), U))
727         {
728             field[] = another.field[];
729         }
730 
731         ///
732         static if (Specs.length == 0) @safe unittest
733         {
734             alias IntVec = Tuple!(int, int, int);
735             alias DubVec = Tuple!(double, double, double);
736 
737             IntVec iv = tuple(1, 1, 1);
738 
739             //Ok, int can implicitly convert to double
740             DubVec dv = iv;
741             //Error: double cannot implicitly convert to int
742             //IntVec iv2 = dv;
743         }
744 
745         /**
746          * Comparison for equality. Two `Tuple`s are considered equal
747          * $(B iff) they fulfill the following criteria:
748          *
749          * $(UL
750          *   $(LI Each `Tuple` is the same length.)
751          *   $(LI For each type `T` on the left-hand side and each type
752          *        `U` on the right-hand side, values of type `T` can be
753          *        compared with values of type `U`.)
754          *   $(LI For each value `v1` on the left-hand side and each value
755          *        `v2` on the right-hand side, the expression `v1 == v2` is
756          *        true.))
757          *
758          * Params:
759          *     rhs = The `Tuple` to compare against. It must meeting the criteria
760          *           for comparison between `Tuple`s.
761          *
762          * Returns:
763          *     true if both `Tuple`s are equal, otherwise false.
764          */
765         bool opEquals(R)(R rhs)
766         if (areCompatibleTuples!(typeof(this), R, "=="))
767         {
768             return field[] == rhs.field[];
769         }
770 
771         /// ditto
772         bool opEquals(R)(R rhs) const
773         if (areCompatibleTuples!(typeof(this), R, "=="))
774         {
775             return field[] == rhs.field[];
776         }
777 
778         /// ditto
779         bool opEquals(R...)(auto ref R rhs)
780         if (R.length > 1 && areCompatibleTuples!(typeof(this), Tuple!R, "=="))
781         {
782             static foreach (i; 0 .. Types.length)
783                 if (field[i] != rhs[i])
784                     return false;
785 
786             return true;
787         }
788 
789         ///
790         static if (Specs.length == 0) @safe unittest
791         {
792             Tuple!(int, string) t1 = tuple(1, "test");
793             Tuple!(double, string) t2 =  tuple(1.0, "test");
794             //Ok, int can be compared with double and
795             //both have a value of 1
796             assert(t1 == t2);
797         }
798 
799         /**
800          * Comparison for ordering.
801          *
802          * Params:
803          *     rhs = The `Tuple` to compare against. It must meet the criteria
804          *           for comparison between `Tuple`s.
805          *
806          * Returns:
807          * For any values `v1` contained by the left-hand side tuple and any
808          * values `v2` contained by the right-hand side:
809          *
810          * 0 if `v1 == v2` for all members or the following value for the
811          * first position were the mentioned criteria is not satisfied:
812          *
813          * $(UL
814          *   $(LI NaN, in case one of the operands is a NaN.)
815          *   $(LI A negative number if the expression `v1 < v2` is true.)
816          *   $(LI A positive number if the expression `v1 > v2` is true.))
817          */
818         auto opCmp(R)(R rhs)
819         if (areCompatibleTuples!(typeof(this), R, "<"))
820         {
821             static foreach (i; 0 .. Types.length)
822             {
823                 if (field[i] != rhs.field[i])
824                 {
825                     import std.math.traits : isNaN;
826                     static if (isFloatingPoint!(Types[i]))
827                     {
828                         if (isNaN(field[i]))
829                             return float.nan;
830                     }
831                     static if (isFloatingPoint!(typeof(rhs.field[i])))
832                     {
833                         if (isNaN(rhs.field[i]))
834                             return float.nan;
835                     }
836                     static if (is(typeof(field[i].opCmp(rhs.field[i]))) &&
837                                isFloatingPoint!(typeof(field[i].opCmp(rhs.field[i]))))
838                     {
839                         if (isNaN(field[i].opCmp(rhs.field[i])))
840                             return float.nan;
841                     }
842 
843                     return field[i] < rhs.field[i] ? -1 : 1;
844                 }
845             }
846             return 0;
847         }
848 
849         /// ditto
850         auto opCmp(R)(R rhs) const
851         if (areCompatibleTuples!(typeof(this), R, "<"))
852         {
853             static foreach (i; 0 .. Types.length)
854             {
855                 if (field[i] != rhs.field[i])
856                 {
857                     import std.math.traits : isNaN;
858                     static if (isFloatingPoint!(Types[i]))
859                     {
860                         if (isNaN(field[i]))
861                             return float.nan;
862                     }
863                     static if (isFloatingPoint!(typeof(rhs.field[i])))
864                     {
865                         if (isNaN(rhs.field[i]))
866                             return float.nan;
867                     }
868                     static if (is(typeof(field[i].opCmp(rhs.field[i]))) &&
869                                isFloatingPoint!(typeof(field[i].opCmp(rhs.field[i]))))
870                     {
871                         if (isNaN(field[i].opCmp(rhs.field[i])))
872                             return float.nan;
873                     }
874 
875                     return field[i] < rhs.field[i] ? -1 : 1;
876                 }
877             }
878             return 0;
879         }
880 
881         /**
882             The first `v1` for which `v1 > v2` is true determines
883             the result. This could lead to unexpected behaviour.
884          */
885         static if (Specs.length == 0) @safe unittest
886         {
887             auto tup1 = tuple(1, 1, 1);
888             auto tup2 = tuple(1, 100, 100);
889             assert(tup1 < tup2);
890 
891             //Only the first result matters for comparison
892             tup1[0] = 2;
893             assert(tup1 > tup2);
894         }
895 
896         /**
897          Concatenate Tuples.
898          Tuple concatenation is only allowed if all named fields are distinct (no named field of this tuple occurs in `t`
899          and no named field of `t` occurs in this tuple).
900 
901          Params:
902              t = The `Tuple` to concatenate with
903 
904          Returns: A concatenation of this tuple and `t`
905          */
906         auto opBinary(string op, T)(auto ref T t)
907         if (op == "~" && !(is(T : U[], U) && isTuple!U))
908         {
909             static if (isTuple!T)
910             {
911                 static assert(distinctFieldNames!(_Fields, T._Fields),
912                     "Cannot concatenate tuples with duplicate fields: " ~ fieldNames.stringof ~
913                     " - " ~ T.fieldNames.stringof);
914                 return Tuple!(_Fields, T._Fields)(expand, t.expand);
915             }
916             else
917             {
918                 return Tuple!(_Fields, T)(expand, t);
919             }
920         }
921 
922         /// ditto
923         auto opBinaryRight(string op, T)(auto ref T t)
924         if (op == "~" && !(is(T : U[], U) && isTuple!U))
925         {
926             static if (isTuple!T)
927             {
928                 static assert(distinctFieldNames!(_Fields, T._Fields),
929                     "Cannot concatenate tuples with duplicate fields: " ~ T.stringof ~
930                     " - " ~ fieldNames.fieldNames.stringof);
931                 return Tuple!(T._Fields, _Fields)(t.expand, expand);
932             }
933             else
934             {
935                 return Tuple!(T, _Fields)(t, expand);
936             }
937         }
938 
939         /**
940          * Assignment from another `Tuple`.
941          *
942          * Params:
943          *     rhs = The source `Tuple` to assign from. Each element of the
944          *           source `Tuple` must be implicitly assignable to each
945          *           respective element of the target `Tuple`.
946          */
947         ref Tuple opAssign(R)(auto ref R rhs)
948         if (areCompatibleTuples!(typeof(this), R, "="))
949         {
950             import std.algorithm.mutation : swap;
951 
952             static if (is(R : Tuple!Types) && !__traits(isRef, rhs) && isTuple!R)
953             {
954                 if (__ctfe)
955                 {
956                     // Cannot use swap at compile time
957                     field[] = rhs.field[];
958                 }
959                 else
960                 {
961                     // Use swap-and-destroy to optimize rvalue assignment
962                     swap!(Tuple!Types)(this, rhs);
963                 }
964             }
965             else
966             {
967                 // Do not swap; opAssign should be called on the fields.
968                 field[] = rhs.field[];
969             }
970             return this;
971         }
972 
973         /**
974          * Renames the elements of a $(LREF Tuple).
975          *
976          * `rename` uses the passed `names` and returns a new
977          * $(LREF Tuple) using these names, with the content
978          * unchanged.
979          * If fewer names are passed than there are members
980          * of the $(LREF Tuple) then those trailing members are unchanged.
981          * An empty string will remove the name for that member.
982          * It is an compile-time error to pass more names than
983          * there are members of the $(LREF Tuple).
984          */
985         ref rename(names...)() inout return
986         if (names.length == 0 || allSatisfy!(isSomeString, typeof(names)))
987         {
988             import std.algorithm.comparison : equal;
989             // to circumvent https://issues.dlang.org/show_bug.cgi?id=16418
990             static if (names.length == 0 || equal([names], [fieldNames]))
991                 return this;
992             else
993             {
994                 enum nT = Types.length;
995                 enum nN = names.length;
996                 static assert(nN <= nT, "Cannot have more names than tuple members");
997                 alias allNames = AliasSeq!(names, fieldNames[nN .. $]);
998 
999                 import std.meta : Alias, aliasSeqOf;
1000 
1001                 template GetItem(size_t idx)
1002                 {
1003                     import std.array : empty;
1004                     static if (idx < nT)
1005                         alias GetItem = Alias!(Types[idx]);
1006                     else static if (allNames[idx - nT].empty)
1007                         alias GetItem = AliasSeq!();
1008                     else
1009                         alias GetItem = Alias!(allNames[idx - nT]);
1010                 }
1011 
1012                 import std.range : roundRobin, iota;
1013                 alias NewTupleT = Tuple!(staticMap!(GetItem, aliasSeqOf!(
1014                         roundRobin(iota(nT), iota(nT, 2*nT)))));
1015                 return *(() @trusted => cast(NewTupleT*)&this)();
1016             }
1017         }
1018 
1019         ///
1020         static if (Specs.length == 0) @safe unittest
1021         {
1022             auto t0 = tuple(4, "hello");
1023 
1024             auto t0Named = t0.rename!("val", "tag");
1025             assert(t0Named.val == 4);
1026             assert(t0Named.tag == "hello");
1027 
1028             Tuple!(float, "dat", size_t[2], "pos") t1;
1029             t1.pos = [2, 1];
1030             auto t1Named = t1.rename!"height";
1031             t1Named.height = 3.4f;
1032             assert(t1Named.height == 3.4f);
1033             assert(t1Named.pos == [2, 1]);
1034             t1Named.rename!"altitude".altitude = 5;
1035             assert(t1Named.height == 5);
1036 
1037             Tuple!(int, "a", int, int, "c") t2;
1038             t2 = tuple(3,4,5);
1039             auto t2Named = t2.rename!("", "b");
1040             // "a" no longer has a name
1041             static assert(!__traits(hasMember, typeof(t2Named), "a"));
1042             assert(t2Named[0] == 3);
1043             assert(t2Named.b == 4);
1044             assert(t2Named.c == 5);
1045 
1046             // not allowed to specify more names than the tuple has members
1047             static assert(!__traits(compiles, t2.rename!("a","b","c","d")));
1048 
1049             // use it in a range pipeline
1050             import std.range : iota, zip;
1051             import std.algorithm.iteration : map, sum;
1052             auto res = zip(iota(1, 4), iota(10, 13))
1053                 .map!(t => t.rename!("a", "b"))
1054                 .map!(t => t.a * t.b)
1055                 .sum;
1056             assert(res == 68);
1057 
1058             const tup = Tuple!(int, "a", int, "b")(2, 3);
1059             const renamed = tup.rename!("c", "d");
1060             assert(renamed.c + renamed.d == 5);
1061         }
1062 
1063         /**
1064          * Overload of $(LREF _rename) that takes an associative array
1065          * `translate` as a template parameter, where the keys are
1066          * either the names or indices of the members to be changed
1067          * and the new names are the corresponding values.
1068          * Every key in `translate` must be the name of a member of the
1069          * $(LREF tuple).
1070          * The same rules for empty strings apply as for the variadic
1071          * template overload of $(LREF _rename).
1072         */
1073         ref rename(alias translate)() inout
1074         if (is(typeof(translate) : V[K], V, K) && isSomeString!V &&
1075                 (isSomeString!K || is(K : size_t)))
1076         {
1077             import std.meta : aliasSeqOf;
1078             import std.range : ElementType;
1079             static if (isSomeString!(ElementType!(typeof(translate.keys))))
1080             {
1081                 {
1082                     import std.conv : to;
1083                     import std.algorithm.iteration : filter;
1084                     import std.algorithm.searching : canFind;
1085                     enum notFound = translate.keys
1086                         .filter!(k => fieldNames.canFind(k) == -1);
1087                     static assert(notFound.empty, "Cannot find members "
1088                         ~ notFound.to!string ~ " in type "
1089                         ~ typeof(this).stringof);
1090                 }
1091                 return this.rename!(aliasSeqOf!(
1092                     {
1093                         import std.array : empty;
1094                         auto names = [fieldNames];
1095                         foreach (ref n; names)
1096                             if (!n.empty)
1097                                 if (auto p = n in translate)
1098                                     n = *p;
1099                         return names;
1100                     }()));
1101             }
1102             else
1103             {
1104                 {
1105                     import std.algorithm.iteration : filter;
1106                     import std.conv : to;
1107                     enum invalid = translate.keys.
1108                         filter!(k => k < 0 || k >= this.length);
1109                     static assert(invalid.empty, "Indices " ~ invalid.to!string
1110                         ~ " are out of bounds for tuple with length "
1111                         ~ this.length.to!string);
1112                 }
1113                 return this.rename!(aliasSeqOf!(
1114                     {
1115                         auto names = [fieldNames];
1116                         foreach (k, v; translate)
1117                             names[k] = v;
1118                         return names;
1119                     }()));
1120             }
1121         }
1122 
1123         ///
1124         static if (Specs.length == 0) @safe unittest
1125         {
1126             //replacing names by their current name
1127 
1128             Tuple!(float, "dat", size_t[2], "pos") t1;
1129             t1.pos = [2, 1];
1130             auto t1Named = t1.rename!(["dat": "height"]);
1131             t1Named.height = 3.4;
1132             assert(t1Named.pos == [2, 1]);
1133             t1Named.rename!(["height": "altitude"]).altitude = 5;
1134             assert(t1Named.height == 5);
1135 
1136             Tuple!(int, "a", int, "b") t2;
1137             t2 = tuple(3, 4);
1138             auto t2Named = t2.rename!(["a": "b", "b": "c"]);
1139             assert(t2Named.b == 3);
1140             assert(t2Named.c == 4);
1141 
1142             const t3 = Tuple!(int, "a", int, "b")(3, 4);
1143             const t3Named = t3.rename!(["a": "b", "b": "c"]);
1144             assert(t3Named.b == 3);
1145             assert(t3Named.c == 4);
1146         }
1147 
1148         ///
1149         static if (Specs.length == 0) @safe unittest
1150         {
1151             //replace names by their position
1152 
1153             Tuple!(float, "dat", size_t[2], "pos") t1;
1154             t1.pos = [2, 1];
1155             auto t1Named = t1.rename!([0: "height"]);
1156             t1Named.height = 3.4;
1157             assert(t1Named.pos == [2, 1]);
1158             t1Named.rename!([0: "altitude"]).altitude = 5;
1159             assert(t1Named.height == 5);
1160 
1161             Tuple!(int, "a", int, "b", int, "c") t2;
1162             t2 = tuple(3, 4, 5);
1163             auto t2Named = t2.rename!([0: "c", 2: "a"]);
1164             assert(t2Named.a == 5);
1165             assert(t2Named.b == 4);
1166             assert(t2Named.c == 3);
1167         }
1168 
1169         static if (Specs.length == 0) @safe unittest
1170         {
1171             //check that empty translations work fine
1172             enum string[string] a0 = null;
1173             enum string[int] a1 = null;
1174             Tuple!(float, "a", float, "b") t0;
1175 
1176             auto t1 = t0.rename!a0;
1177 
1178             t1.a = 3;
1179             t1.b = 4;
1180             auto t2 = t0.rename!a1;
1181             t2.a = 3;
1182             t2.b = 4;
1183             auto t3 = t0.rename;
1184             t3.a = 3;
1185             t3.b = 4;
1186         }
1187 
1188         /**
1189          * Takes a slice by-reference of this `Tuple`.
1190          *
1191          * Params:
1192          *     from = A `size_t` designating the starting position of the slice.
1193          *     to = A `size_t` designating the ending position (exclusive) of the slice.
1194          *
1195          * Returns:
1196          *     A new `Tuple` that is a slice from `[from, to$(RPAREN)` of the original.
1197          *     It has the same types and values as the range `[from, to$(RPAREN)` in
1198          *     the original.
1199          */
1200         @property
1201         ref inout(Tuple!(sliceSpecs!(from, to))) slice(size_t from, size_t to)() inout @trusted
1202         if (from <= to && to <= Types.length)
1203         {
1204             static assert(
1205                 (typeof(this).alignof % typeof(return).alignof == 0) &&
1206                 (expand[from].offsetof % typeof(return).alignof == 0),
1207                 "Slicing by reference is impossible because of an alignment mistmatch" ~
1208                 " (See https://issues.dlang.org/show_bug.cgi?id=15645).");
1209 
1210             return *cast(typeof(return)*) &(field[from]);
1211         }
1212 
1213         ///
1214         static if (Specs.length == 0) @safe unittest
1215         {
1216             Tuple!(int, string, float, double) a;
1217             a[1] = "abc";
1218             a[2] = 4.5;
1219             auto s = a.slice!(1, 3);
1220             static assert(is(typeof(s) == Tuple!(string, float)));
1221             assert(s[0] == "abc" && s[1] == 4.5);
1222 
1223             // https://issues.dlang.org/show_bug.cgi?id=15645
1224             Tuple!(int, short, bool, double) b;
1225             static assert(!__traits(compiles, b.slice!(2, 4)));
1226         }
1227 
1228         /**
1229             Creates a hash of this `Tuple`.
1230 
1231             Returns:
1232                 A `size_t` representing the hash of this `Tuple`.
1233          */
1234         size_t toHash() const nothrow @safe
1235         {
1236             size_t h = 0;
1237             static foreach (i, T; Types)
1238             {{
1239                 static if (__traits(compiles, h = .hashOf(field[i])))
1240                     const k = .hashOf(field[i]);
1241                 else
1242                 {
1243                     // Workaround for when .hashOf is not both @safe and nothrow.
1244                     static if (is(T : shared U, U) && __traits(compiles, (U* a) nothrow @safe => .hashOf(*a))
1245                             && !__traits(hasMember, T, "toHash"))
1246                         // BUG: Improperly casts away `shared`!
1247                         const k = .hashOf(*(() @trusted => cast(U*) &field[i])());
1248                     else
1249                         // BUG: Improperly casts away `shared`!
1250                         const k = typeid(T).getHash((() @trusted => cast(const void*) &field[i])());
1251                 }
1252                 static if (i == 0)
1253                     h = k;
1254                 else
1255                     // As in boost::hash_combine
1256                     // https://www.boost.org/doc/libs/1_55_0/doc/html/hash/reference.html#boost.hash_combine
1257                     h ^= k + 0x9e3779b9 + (h << 6) + (h >>> 2);
1258             }}
1259             return h;
1260         }
1261 
1262         /**
1263          * Converts to string.
1264          *
1265          * Returns:
1266          *     The string representation of this `Tuple`.
1267          */
1268         string toString()() const
1269         {
1270             import std.array : appender;
1271             auto app = appender!string();
1272             this.toString((const(char)[] chunk) => app ~= chunk);
1273             return app.data;
1274         }
1275 
1276         import std.format.spec : FormatSpec;
1277 
1278         /**
1279          * Formats `Tuple` with either `%s`, `%(inner%)` or `%(inner%|sep%)`.
1280          *
1281          * $(TABLE2 Formats supported by Tuple,
1282          * $(THEAD Format, Description)
1283          * $(TROW $(P `%s`), $(P Format like `Tuple!(types)(elements formatted with %s each)`.))
1284          * $(TROW $(P `%(inner%)`), $(P The format `inner` is applied the expanded `Tuple`$(COMMA) so
1285          *      it may contain as many formats as the `Tuple` has fields.))
1286          * $(TROW $(P `%(inner%|sep%)`), $(P The format `inner` is one format$(COMMA) that is applied
1287          *      on all fields of the `Tuple`. The inner format must be compatible to all
1288          *      of them.)))
1289          *
1290          * Params:
1291          *     sink = A `char` accepting delegate
1292          *     fmt = A $(REF FormatSpec, std,format)
1293          */
toStringTuple1294         void toString(DG)(scope DG sink) const
1295         {
1296             auto f = FormatSpec!char();
1297             toString(sink, f);
1298         }
1299 
1300         /// ditto
toStringTuple1301         void toString(DG, Char)(scope DG sink, scope const ref FormatSpec!Char fmt) const
1302         {
1303             import std.format : format, FormatException;
1304             import std.format.write : formattedWrite;
1305             import std.range : only;
1306             if (fmt.nested)
1307             {
1308                 if (fmt.sep)
1309                 {
1310                     foreach (i, Type; Types)
1311                     {
1312                         static if (i > 0)
1313                         {
1314                             sink(fmt.sep);
1315                         }
1316                         // TODO: Change this once formattedWrite() works for shared objects.
1317                         static if (is(Type == class) && is(Type == shared))
1318                         {
1319                             sink(Type.stringof);
1320                         }
1321                         else
1322                         {
1323                             formattedWrite(sink, fmt.nested, this.field[i]);
1324                         }
1325                     }
1326                 }
1327                 else
1328                 {
1329                     formattedWrite(sink, fmt.nested, staticMap!(sharedToString, this.expand));
1330                 }
1331             }
1332             else if (fmt.spec == 's')
1333             {
1334                 enum header = Unqual!(typeof(this)).stringof ~ "(",
1335                      footer = ")",
1336                      separator = ", ";
1337                 sink(header);
1338                 foreach (i, Type; Types)
1339                 {
1340                     static if (i > 0)
1341                     {
1342                         sink(separator);
1343                     }
1344                     // TODO: Change this once format() works for shared objects.
1345                     static if (is(Type == class) && is(Type == shared))
1346                     {
1347                         sink(Type.stringof);
1348                     }
1349                     else
1350                     {
1351                         sink(format!("%(%s%)")(only(field[i])));
1352                     }
1353                 }
1354                 sink(footer);
1355             }
1356             else
1357             {
1358                 const spec = fmt.spec;
1359                 throw new FormatException(
1360                     "Expected '%s' or '%(...%)' or '%(...%|...%)' format specifier for type '" ~
1361                         Unqual!(typeof(this)).stringof ~ "', not '%" ~ spec ~ "'.");
1362             }
1363         }
1364 
1365         ///
1366         static if (Specs.length == 0) @safe unittest
1367         {
1368             import std.format : format;
1369 
1370             Tuple!(int, double)[3] tupList = [ tuple(1, 1.0), tuple(2, 4.0), tuple(3, 9.0) ];
1371 
1372             // Default format
1373             assert(format("%s", tuple("a", 1)) == `Tuple!(string, int)("a", 1)`);
1374 
1375             // One Format for each individual component
1376             assert(format("%(%#x v %.4f w %#x%)", tuple(1, 1.0, 10))         == `0x1 v 1.0000 w 0xa`);
1377             assert(format(  "%#x v %.4f w %#x"  , tuple(1, 1.0, 10).expand)  == `0x1 v 1.0000 w 0xa`);
1378 
1379             // One Format for all components
1380             assert(format("%(>%s<%| & %)", tuple("abc", 1, 2.3, [4, 5])) == `>abc< & >1< & >2.3< & >[4, 5]<`);
1381 
1382             // Array of Tuples
1383             assert(format("%(%(f(%d) = %.1f%);  %)", tupList) == `f(1) = 1.0;  f(2) = 4.0;  f(3) = 9.0`);
1384         }
1385 
1386         ///
1387         static if (Specs.length == 0) @safe unittest
1388         {
1389             import std.exception : assertThrown;
1390             import std.format : format, FormatException;
1391 
1392             // Error: %( %) missing.
1393             assertThrown!FormatException(
1394                 format("%d, %f", tuple(1, 2.0)) == `1, 2.0`
1395             );
1396 
1397             // Error: %( %| %) missing.
1398             assertThrown!FormatException(
1399                 format("%d", tuple(1, 2)) == `1, 2`
1400             );
1401 
1402             // Error: %d inadequate for double
1403             assertThrown!FormatException(
1404                 format("%(%d%|, %)", tuple(1, 2.0)) == `1, 2.0`
1405             );
1406         }
1407     }
1408 }
1409 
1410 ///
1411 @safe unittest
1412 {
1413     Tuple!(int, int) point;
1414     // assign coordinates
1415     point[0] = 5;
1416     point[1] = 6;
1417     // read coordinates
1418     auto x = point[0];
1419     auto y = point[1];
1420 }
1421 
1422 /**
1423     `Tuple` members can be named. It is legal to mix named and unnamed
1424     members. The method above is still applicable to all fields.
1425  */
1426 @safe unittest
1427 {
1428     alias Entry = Tuple!(int, "index", string, "value");
1429     Entry e;
1430     e.index = 4;
1431     e.value = "Hello";
1432     assert(e[1] == "Hello");
1433     assert(e[0] == 4);
1434 }
1435 
1436 /**
1437     A `Tuple` with named fields is a distinct type from a `Tuple` with unnamed
1438     fields, i.e. each naming imparts a separate type for the `Tuple`. Two
1439     `Tuple`s differing in naming only are still distinct, even though they
1440     might have the same structure.
1441  */
1442 @safe unittest
1443 {
1444     Tuple!(int, "x", int, "y") point1;
1445     Tuple!(int, int) point2;
1446     assert(!is(typeof(point1) == typeof(point2)));
1447 }
1448 
1449 /// Use tuples as ranges
1450 @safe unittest
1451 {
1452     import std.algorithm.iteration : sum;
1453     import std.range : only;
1454     auto t = tuple(1, 2);
1455     assert(t.expand.only.sum == 3);
1456 }
1457 
1458 // https://issues.dlang.org/show_bug.cgi?id=4582
1459 @safe unittest
1460 {
1461     static assert(!__traits(compiles, Tuple!(string, "id", int, "id")));
1462     static assert(!__traits(compiles, Tuple!(string, "str", int, "i", string, "str", float)));
1463 }
1464 
1465 /// Concatenate tuples
1466 @safe unittest
1467 {
1468     import std.meta : AliasSeq;
1469     auto t = tuple(1, "2") ~ tuple(ushort(42), true);
1470     static assert(is(t.Types == AliasSeq!(int, string, ushort, bool)));
1471     assert(t[1] == "2");
1472     assert(t[2] == 42);
1473     assert(t[3] == true);
1474 }
1475 
1476 // https://issues.dlang.org/show_bug.cgi?id=14637
1477 // tuple concat
1478 @safe unittest
1479 {
1480     auto t = tuple!"foo"(1.0) ~ tuple!"bar"("3");
1481     static assert(is(t.Types == AliasSeq!(double, string)));
1482     static assert(t.fieldNames == tuple("foo", "bar"));
1483     assert(t.foo == 1.0);
1484     assert(t.bar == "3");
1485 }
1486 
1487 // https://issues.dlang.org/show_bug.cgi?id=18824
1488 // tuple concat
1489 @safe unittest
1490 {
1491     alias Type = Tuple!(int, string);
1492     Type[] arr;
1493     auto t = tuple(2, "s");
1494     // Test opBinaryRight
1495     arr = arr ~ t;
1496     // Test opBinary
1497     arr = t ~ arr;
1498     static assert(is(typeof(arr) == Type[]));
1499     immutable Type[] b;
1500     auto c = b ~ t;
1501     static assert(is(typeof(c) == immutable(Type)[]));
1502 }
1503 
1504 // tuple concat
1505 @safe unittest
1506 {
1507     auto t = tuple!"foo"(1.0) ~ "3";
1508     static assert(is(t.Types == AliasSeq!(double, string)));
1509     assert(t.foo == 1.0);
1510     assert(t[1]== "3");
1511 }
1512 
1513 // tuple concat
1514 @safe unittest
1515 {
1516     auto t = "2" ~ tuple!"foo"(1.0);
1517     static assert(is(t.Types == AliasSeq!(string, double)));
1518     assert(t.foo == 1.0);
1519     assert(t[0]== "2");
1520 }
1521 
1522 // tuple concat
1523 @safe unittest
1524 {
1525     auto t = "2" ~ tuple!"foo"(1.0) ~ tuple(42, 3.0f) ~ real(1) ~ "a";
1526     static assert(is(t.Types == AliasSeq!(string, double, int, float, real, string)));
1527     assert(t.foo == 1.0);
1528     assert(t[0] == "2");
1529     assert(t[1] == 1.0);
1530     assert(t[2] == 42);
1531     assert(t[3] == 3.0f);
1532     assert(t[4] == 1.0);
1533     assert(t[5] == "a");
1534 }
1535 
1536 // ensure that concatenation of tuples with non-distinct fields is forbidden
1537 @safe unittest
1538 {
1539     static assert(!__traits(compiles,
1540         tuple!("a")(0) ~ tuple!("a")("1")));
1541     static assert(!__traits(compiles,
1542         tuple!("a", "b")(0, 1) ~ tuple!("b", "a")("3", 1)));
1543     static assert(!__traits(compiles,
1544         tuple!("a")(0) ~ tuple!("b", "a")("3", 1)));
1545     static assert(!__traits(compiles,
1546         tuple!("a1", "a")(1.0, 0) ~ tuple!("a2", "a")("3", 0)));
1547 }
1548 
1549 // Ensure that Tuple comparison with non-const opEquals works
1550 @safe unittest
1551 {
1552     static struct Bad
1553     {
1554         int a;
1555 
1556         bool opEquals(Bad b)
1557         {
1558             return a == b.a;
1559         }
1560     }
1561 
1562     auto t = Tuple!(int, Bad, string)(1, Bad(1), "asdf");
1563 
1564     //Error: mutable method Bad.opEquals is not callable using a const object
1565     assert(t == AliasSeq!(1, Bad(1), "asdf"));
1566 }
1567 
1568 // Ensure Tuple.toHash works
1569 @safe unittest
1570 {
1571     Tuple!(int, int) point;
1572     assert(point.toHash == typeof(point).init.toHash);
1573     assert(tuple(1, 2) != point);
1574     assert(tuple(1, 2) == tuple(1, 2));
1575     point[0] = 1;
1576     assert(tuple(1, 2) != point);
1577     point[1] = 2;
1578     assert(tuple(1, 2) == point);
1579 }
1580 
1581 @safe @betterC unittest
1582 {
1583     auto t = tuple(1, 2);
1584     assert(t == tuple(1, 2));
1585     auto t3 = tuple(1, 'd');
1586 }
1587 
1588 // https://issues.dlang.org/show_bug.cgi?id=20850
1589 // Assignment to enum tuple
1590 @safe unittest
1591 {
1592     enum T : Tuple!(int*) { a = T(null) }
1593     T t;
1594     t = T.a;
1595 }
1596 
1597 // https://issues.dlang.org/show_bug.cgi?id=13663
1598 @safe unittest
1599 {
1600     auto t = tuple(real.nan);
1601     assert(!(t > t));
1602     assert(!(t < t));
1603     assert(!(t == t));
1604 }
1605 
1606 @safe unittest
1607 {
1608     struct S
1609     {
1610         float opCmp(S s) { return float.nan; }
1611         bool opEquals(S s) { return false; }
1612     }
1613 
1614     auto t = tuple(S());
1615     assert(!(t > t));
1616     assert(!(t < t));
1617     assert(!(t == t));
1618 }
1619 
1620 // https://issues.dlang.org/show_bug.cgi?id=8015
1621 @safe unittest
1622 {
1623     struct MyStruct
1624     {
1625         string str;
1626         @property string toStr()
1627         {
1628             return str;
1629         }
1630         alias toStr this;
1631     }
1632 
1633     Tuple!(MyStruct) t;
1634 }
1635 
1636 /**
1637     Creates a copy of a $(LREF Tuple) with its fields in _reverse order.
1638 
1639     Params:
1640         t = The `Tuple` to copy.
1641 
1642     Returns:
1643         A new `Tuple`.
1644  */
1645 auto reverse(T)(T t)
1646 if (isTuple!T)
1647 {
1648     import std.meta : Reverse;
1649     // @@@BUG@@@ Cannot be an internal function due to forward reference issues.
1650 
1651     // @@@BUG@@@ 9929 Need 'this' when calling template with expanded tuple
1652     // return tuple(Reverse!(t.expand));
1653 
1654     ReverseTupleType!T result;
1655     auto tup = t.expand;
1656     result.expand = Reverse!tup;
1657     return result;
1658 }
1659 
1660 ///
1661 @safe unittest
1662 {
1663     auto tup = tuple(1, "2");
1664     assert(tup.reverse == tuple("2", 1));
1665 }
1666 
1667 /* Get a Tuple type with the reverse specification of Tuple T. */
1668 private template ReverseTupleType(T)
1669 if (isTuple!T)
1670 {
1671     static if (is(T : Tuple!A, A...))
1672         alias ReverseTupleType = Tuple!(ReverseTupleSpecs!A);
1673 }
1674 
1675 /* Reverse the Specs of a Tuple. */
1676 private template ReverseTupleSpecs(T...)
1677 {
1678     static if (T.length > 1)
1679     {
1680         static if (is(typeof(T[$-1]) : string))
1681         {
1682             alias ReverseTupleSpecs = AliasSeq!(T[$-2], T[$-1], ReverseTupleSpecs!(T[0 .. $-2]));
1683         }
1684         else
1685         {
1686             alias ReverseTupleSpecs = AliasSeq!(T[$-1], ReverseTupleSpecs!(T[0 .. $-1]));
1687         }
1688     }
1689     else
1690     {
1691         alias ReverseTupleSpecs = T;
1692     }
1693 }
1694 
1695 // ensure that internal Tuple unittests are compiled
1696 @safe unittest
1697 {
1698     Tuple!() t;
1699 }
1700 
1701 @safe unittest
1702 {
1703     import std.conv;
1704     {
1705         Tuple!(int, "a", int, "b") nosh;
1706         static assert(nosh.length == 2);
1707         nosh.a = 5;
1708         nosh.b = 6;
1709         assert(nosh.a == 5);
1710         assert(nosh.b == 6);
1711     }
1712     {
1713         Tuple!(short, double) b;
1714         static assert(b.length == 2);
1715         b[1] = 5;
1716         auto a = Tuple!(int, real)(b);
1717         assert(a[0] == 0 && a[1] == 5);
1718         a = Tuple!(int, real)(1, 2);
1719         assert(a[0] == 1 && a[1] == 2);
1720         auto c = Tuple!(int, "a", double, "b")(a);
1721         assert(c[0] == 1 && c[1] == 2);
1722     }
1723     {
1724         Tuple!(int, real) nosh;
1725         nosh[0] = 5;
1726         nosh[1] = 0;
1727         assert(nosh[0] == 5 && nosh[1] == 0);
1728         assert(nosh.to!string == "Tuple!(int, real)(5, 0)", nosh.to!string);
1729         Tuple!(int, int) yessh;
1730         nosh = yessh;
1731     }
1732     {
1733         class A {}
1734         Tuple!(int, shared A) nosh;
1735         nosh[0] = 5;
1736         assert(nosh[0] == 5 && nosh[1] is null);
1737         assert(nosh.to!string == "Tuple!(int, shared(A))(5, shared(A))");
1738     }
1739     {
1740         Tuple!(int, string) t;
1741         t[0] = 10;
1742         t[1] = "str";
1743         assert(t[0] == 10 && t[1] == "str");
1744         assert(t.to!string == `Tuple!(int, string)(10, "str")`, t.to!string);
1745     }
1746     {
1747         Tuple!(int, "a", double, "b") x;
1748         static assert(x.a.offsetof == x[0].offsetof);
1749         static assert(x.b.offsetof == x[1].offsetof);
1750         x.b = 4.5;
1751         x.a = 5;
1752         assert(x[0] == 5 && x[1] == 4.5);
1753         assert(x.a == 5 && x.b == 4.5);
1754     }
1755     // indexing
1756     {
1757         Tuple!(int, real) t;
1758         static assert(is(typeof(t[0]) == int));
1759         static assert(is(typeof(t[1]) == real));
1760         int* p0 = &t[0];
1761         real* p1 = &t[1];
1762         t[0] = 10;
1763         t[1] = -200.0L;
1764         assert(*p0 == t[0]);
1765         assert(*p1 == t[1]);
1766     }
1767     // slicing
1768     {
1769         Tuple!(int, "x", real, "y", double, "z", string) t;
1770         t[0] = 10;
1771         t[1] = 11;
1772         t[2] = 12;
1773         t[3] = "abc";
1774         auto a = t.slice!(0, 3);
1775         assert(a.length == 3);
1776         assert(a.x == t.x);
1777         assert(a.y == t.y);
1778         assert(a.z == t.z);
1779         auto b = t.slice!(2, 4);
1780         assert(b.length == 2);
1781         assert(b.z == t.z);
1782         assert(b[1] == t[3]);
1783     }
1784     // nesting
1785     {
1786         Tuple!(Tuple!(int, real), Tuple!(string, "s")) t;
1787         static assert(is(typeof(t[0]) == Tuple!(int, real)));
1788         static assert(is(typeof(t[1]) == Tuple!(string, "s")));
1789         static assert(is(typeof(t[0][0]) == int));
1790         static assert(is(typeof(t[0][1]) == real));
1791         static assert(is(typeof(t[1].s) == string));
1792         t[0] = tuple(10, 20.0L);
1793         t[1].s = "abc";
1794         assert(t[0][0] == 10);
1795         assert(t[0][1] == 20.0L);
1796         assert(t[1].s == "abc");
1797     }
1798     // non-POD
1799     {
1800         static struct S
1801         {
1802             int count;
1803             this(this) { ++count; }
1804             ~this() { --count; }
1805             void opAssign(S rhs) { count = rhs.count; }
1806         }
1807         Tuple!(S, S) ss;
1808         Tuple!(S, S) ssCopy = ss;
1809         assert(ssCopy[0].count == 1);
1810         assert(ssCopy[1].count == 1);
1811         ssCopy[1] = ssCopy[0];
1812         assert(ssCopy[1].count == 2);
1813     }
1814     // https://issues.dlang.org/show_bug.cgi?id=2800
1815     {
1816         static struct R
1817         {
1818             Tuple!(int, int) _front;
1819             @property ref Tuple!(int, int) front() return { return _front;  }
1820             @property bool empty() { return _front[0] >= 10; }
1821             void popFront() { ++_front[0]; }
1822         }
1823         foreach (a; R())
1824         {
1825             static assert(is(typeof(a) == Tuple!(int, int)));
1826             assert(0 <= a[0] && a[0] < 10);
1827             assert(a[1] == 0);
1828         }
1829     }
1830     // Construction with compatible elements
1831     {
1832         auto t1 = Tuple!(int, double)(1, 1);
1833 
1834         // https://issues.dlang.org/show_bug.cgi?id=8702
1835         auto t8702a = tuple(tuple(1));
1836         auto t8702b = Tuple!(Tuple!(int))(Tuple!(int)(1));
1837     }
1838     // Construction with compatible tuple
1839     {
1840         Tuple!(int, int) x;
1841         x[0] = 10;
1842         x[1] = 20;
1843         Tuple!(int, "a", double, "b") y = x;
1844         assert(y.a == 10);
1845         assert(y.b == 20);
1846         // incompatible
1847         static assert(!__traits(compiles, Tuple!(int, int)(y)));
1848     }
1849     // https://issues.dlang.org/show_bug.cgi?id=6275
1850     {
1851         const int x = 1;
1852         auto t1 = tuple(x);
1853         alias T = Tuple!(const(int));
1854         auto t2 = T(1);
1855     }
1856     // https://issues.dlang.org/show_bug.cgi?id=9431
1857     {
1858         alias T = Tuple!(int[1][]);
1859         auto t = T([[10]]);
1860     }
1861     // https://issues.dlang.org/show_bug.cgi?id=7666
1862     {
1863         auto tup = tuple(1, "2");
1864         assert(tup.reverse == tuple("2", 1));
1865     }
1866     {
1867         Tuple!(int, "x", string, "y") tup = tuple(1, "2");
1868         auto rev = tup.reverse;
1869         assert(rev == tuple("2", 1));
1870         assert(rev.x == 1 && rev.y == "2");
1871     }
1872     {
1873         Tuple!(wchar, dchar, int, "x", string, "y", char, byte, float) tup;
1874         tup = tuple('a', 'b', 3, "4", 'c', cast(byte) 0x0D, 0.00);
1875         auto rev = tup.reverse;
1876         assert(rev == tuple(0.00, cast(byte) 0x0D, 'c', "4", 3, 'b', 'a'));
1877         assert(rev.x == 3 && rev.y == "4");
1878     }
1879 }
1880 @safe unittest
1881 {
1882     // opEquals
1883     {
1884         struct Equ1 { bool opEquals(Equ1) { return true; } }
1885         auto  tm1 = tuple(Equ1.init);
1886         const tc1 = tuple(Equ1.init);
1887         static assert( is(typeof(tm1 == tm1)));
1888         static assert(!is(typeof(tm1 == tc1)));
1889         static assert(!is(typeof(tc1 == tm1)));
1890         static assert(!is(typeof(tc1 == tc1)));
1891 
1892         struct Equ2 { bool opEquals(const Equ2) const { return true; } }
1893         auto  tm2 = tuple(Equ2.init);
1894         const tc2 = tuple(Equ2.init);
1895         static assert( is(typeof(tm2 == tm2)));
1896         static assert( is(typeof(tm2 == tc2)));
1897         static assert( is(typeof(tc2 == tm2)));
1898         static assert( is(typeof(tc2 == tc2)));
1899 
1900         // https://issues.dlang.org/show_bug.cgi?id=8686
1901         struct Equ3 { bool opEquals(T)(T) { return true; } }
1902         auto  tm3 = tuple(Equ3.init);
1903         const tc3 = tuple(Equ3.init);
1904         static assert( is(typeof(tm3 == tm3)));
1905         static assert( is(typeof(tm3 == tc3)));
1906         static assert(!is(typeof(tc3 == tm3)));
1907         static assert(!is(typeof(tc3 == tc3)));
1908 
1909         struct Equ4 { bool opEquals(T)(T) const { return true; } }
1910         auto  tm4 = tuple(Equ4.init);
1911         const tc4 = tuple(Equ4.init);
1912         static assert( is(typeof(tm4 == tm4)));
1913         static assert( is(typeof(tm4 == tc4)));
1914         static assert( is(typeof(tc4 == tm4)));
1915         static assert( is(typeof(tc4 == tc4)));
1916     }
1917     // opCmp
1918     {
1919         struct Cmp1 { int opCmp(Cmp1) { return 0; } }
1920         auto  tm1 = tuple(Cmp1.init);
1921         const tc1 = tuple(Cmp1.init);
1922         static assert( is(typeof(tm1 < tm1)));
1923         static assert(!is(typeof(tm1 < tc1)));
1924         static assert(!is(typeof(tc1 < tm1)));
1925         static assert(!is(typeof(tc1 < tc1)));
1926 
1927         struct Cmp2 { int opCmp(const Cmp2) const { return 0; } }
1928         auto  tm2 = tuple(Cmp2.init);
1929         const tc2 = tuple(Cmp2.init);
1930         static assert( is(typeof(tm2 < tm2)));
1931         static assert( is(typeof(tm2 < tc2)));
1932         static assert( is(typeof(tc2 < tm2)));
1933         static assert( is(typeof(tc2 < tc2)));
1934 
1935         struct Cmp3 { int opCmp(T)(T) { return 0; } }
1936         auto  tm3 = tuple(Cmp3.init);
1937         const tc3 = tuple(Cmp3.init);
1938         static assert( is(typeof(tm3 < tm3)));
1939         static assert( is(typeof(tm3 < tc3)));
1940         static assert(!is(typeof(tc3 < tm3)));
1941         static assert(!is(typeof(tc3 < tc3)));
1942 
1943         struct Cmp4 { int opCmp(T)(T) const { return 0; } }
1944         auto  tm4 = tuple(Cmp4.init);
1945         const tc4 = tuple(Cmp4.init);
1946         static assert( is(typeof(tm4 < tm4)));
1947         static assert( is(typeof(tm4 < tc4)));
1948         static assert( is(typeof(tc4 < tm4)));
1949         static assert( is(typeof(tc4 < tc4)));
1950     }
1951     // https://issues.dlang.org/show_bug.cgi?id=14890
1952     static void test14890(inout int[] dummy)
1953     {
1954         alias V = Tuple!(int, int);
1955 
1956                     V mv;
1957               const V cv;
1958           immutable V iv;
1959               inout V wv;   // OK <- NG
1960         inout const V wcv;  // OK <- NG
1961 
1962         static foreach (v1; AliasSeq!(mv, cv, iv, wv, wcv))
1963         static foreach (v2; AliasSeq!(mv, cv, iv, wv, wcv))
1964         {
1965             assert(!(v1 < v2));
1966         }
1967     }
1968     {
1969         int[2] ints = [ 1, 2 ];
1970         Tuple!(int, int) t = ints;
1971         assert(t[0] == 1 && t[1] == 2);
1972         Tuple!(long, uint) t2 = ints;
1973         assert(t2[0] == 1 && t2[1] == 2);
1974     }
1975 }
1976 @safe unittest
1977 {
1978     auto t1 = Tuple!(int, "x", string, "y")(1, "a");
1979     assert(t1.x == 1);
1980     assert(t1.y == "a");
1981     void foo(Tuple!(int, string) t2) {}
1982     foo(t1);
1983 
1984     Tuple!(int, int)[] arr;
1985     arr ~= tuple(10, 20); // OK
1986     arr ~= Tuple!(int, "x", int, "y")(10, 20); // NG -> OK
1987 
1988     static assert(is(typeof(Tuple!(int, "x", string, "y").tupleof) ==
1989                      typeof(Tuple!(int,      string     ).tupleof)));
1990 }
1991 @safe unittest
1992 {
1993     // https://issues.dlang.org/show_bug.cgi?id=10686
1994     immutable Tuple!(int) t1;
1995     auto r1 = t1[0]; // OK
1996     immutable Tuple!(int, "x") t2;
1997     auto r2 = t2[0]; // error
1998 }
1999 @safe unittest
2000 {
2001     import std.exception : assertCTFEable;
2002 
2003     // https://issues.dlang.org/show_bug.cgi?id=10218
2004     assertCTFEable!(
2005     {
2006         auto t = tuple(1);
2007         t = tuple(2);   // assignment
2008     });
2009 }
2010 @safe unittest
2011 {
2012     class Foo{}
2013     Tuple!(immutable(Foo)[]) a;
2014 }
2015 
2016 @safe unittest
2017 {
2018     //Test non-assignable
2019     static struct S
2020     {
2021         int* p;
2022     }
2023     alias IS = immutable S;
2024     static assert(!isAssignable!IS);
2025 
2026     auto s = IS.init;
2027 
2028     alias TIS = Tuple!IS;
2029     TIS a = tuple(s);
2030     TIS b = a;
2031 
2032     alias TISIS = Tuple!(IS, IS);
2033     TISIS d = tuple(s, s);
2034     IS[2] ss;
2035     TISIS e = TISIS(ss);
2036 }
2037 
2038 // https://issues.dlang.org/show_bug.cgi?id=9819
2039 @safe unittest
2040 {
2041     alias T = Tuple!(int, "x", double, "foo");
2042     static assert(T.fieldNames[0] == "x");
2043     static assert(T.fieldNames[1] == "foo");
2044 
2045     alias Fields = Tuple!(int, "id", string, float);
2046     static assert(Fields.fieldNames == AliasSeq!("id", "", ""));
2047 }
2048 
2049 // https://issues.dlang.org/show_bug.cgi?id=13837
2050 @safe unittest
2051 {
2052     // New behaviour, named arguments.
2053     static assert(is(
2054         typeof(tuple!("x")(1)) == Tuple!(int, "x")));
2055     static assert(is(
2056         typeof(tuple!("x")(1.0)) == Tuple!(double, "x")));
2057     static assert(is(
2058         typeof(tuple!("x")("foo")) == Tuple!(string, "x")));
2059     static assert(is(
2060         typeof(tuple!("x", "y")(1, 2.0)) == Tuple!(int, "x", double, "y")));
2061 
2062     auto a = tuple!("a", "b", "c")("1", 2, 3.0f);
2063     static assert(is(typeof(a.a) == string));
2064     static assert(is(typeof(a.b) == int));
2065     static assert(is(typeof(a.c) == float));
2066 
2067     // Old behaviour, but with explicit type parameters.
2068     static assert(is(
2069         typeof(tuple!(int, double)(1, 2.0)) == Tuple!(int, double)));
2070     static assert(is(
2071         typeof(tuple!(const int)(1)) == Tuple!(const int)));
2072     static assert(is(
2073         typeof(tuple()) == Tuple!()));
2074 
2075     // Nonsensical behaviour
2076     static assert(!__traits(compiles, tuple!(1)(2)));
2077     static assert(!__traits(compiles, tuple!("x")(1, 2)));
2078     static assert(!__traits(compiles, tuple!("x", "y")(1)));
2079     static assert(!__traits(compiles, tuple!("x")()));
2080     static assert(!__traits(compiles, tuple!("x", int)(2)));
2081 }
2082 
2083 @safe unittest
2084 {
2085     class C { override size_t toHash() const nothrow @safe { return 0; } }
2086     Tuple!(Rebindable!(const C)) a;
2087     Tuple!(const C) b;
2088     a = b;
2089 }
2090 
2091 @nogc @safe unittest
2092 {
2093     alias T = Tuple!(string, "s");
2094     T x;
2095     x = T.init;
2096 }
2097 
2098 @safe unittest
2099 {
2100     import std.format : format, FormatException;
2101     import std.exception : assertThrown;
2102 
2103     //enum tupStr = tuple(1, 1.0).toString; // toString is *impure*.
2104     //static assert(tupStr == `Tuple!(int, double)(1, 1)`);
2105 }
2106 
2107 // https://issues.dlang.org/show_bug.cgi?id=17803, parte uno
2108 @safe unittest
2109 {
2110     auto a = tuple(3, "foo");
2111     assert(__traits(compiles, { a = (a = a); }));
2112 }
2113 // Ditto
2114 @safe unittest
2115 {
2116     Tuple!(int[]) a, b, c;
2117     a = tuple([0, 1, 2]);
2118     c = b = a;
2119     assert(a[0].length == b[0].length && b[0].length == c[0].length);
2120     assert(a[0].ptr == b[0].ptr && b[0].ptr == c[0].ptr);
2121 }
2122 
2123 /**
2124     Constructs a $(LREF Tuple) object instantiated and initialized according to
2125     the given arguments.
2126 
2127     Params:
2128         Names = An optional list of strings naming each successive field of the `Tuple`
2129                 or a list of types that the elements are being casted to.
2130                 For a list of names,
2131                 each name matches up with the corresponding field given by `Args`.
2132                 A name does not have to be provided for every field, but as
2133                 the names must proceed in order, it is not possible to skip
2134                 one field and name the next after it.
2135                 For a list of types,
2136                 there must be exactly as many types as parameters.
2137 */
2138 template tuple(Names...)
2139 {
2140     /**
2141     Params:
2142         args = Values to initialize the `Tuple` with. The `Tuple`'s type will
2143                be inferred from the types of the values given.
2144 
2145     Returns:
2146         A new `Tuple` with its type inferred from the arguments given.
2147      */
2148     auto tuple(Args...)(Args args)
2149     {
2150         static if (Names.length == 0)
2151         {
2152             // No specified names, just infer types from Args...
2153             return Tuple!Args(args);
2154         }
2155         else static if (!is(typeof(Names[0]) : string))
2156         {
2157             // Names[0] isn't a string, must be explicit types.
2158             return Tuple!Names(args);
2159         }
2160         else
2161         {
2162             // Names[0] is a string, so must be specifying names.
2163             static assert(Names.length == Args.length,
2164                 "Insufficient number of names given.");
2165 
2166             // Interleave(a, b).and(c, d) == (a, c, b, d)
2167             // This is to get the interleaving of types and names for Tuple
2168             // e.g. Tuple!(int, "x", string, "y")
2169             template Interleave(A...)
2170             {
2171                 template and(B...) if (B.length == 1)
2172                 {
2173                     alias and = AliasSeq!(A[0], B[0]);
2174                 }
2175 
2176                 template and(B...) if (B.length != 1)
2177                 {
2178                     alias and = AliasSeq!(A[0], B[0],
2179                         Interleave!(A[1..$]).and!(B[1..$]));
2180                 }
2181             }
2182             return Tuple!(Interleave!(Args).and!(Names))(args);
2183         }
2184     }
2185 }
2186 
2187 ///
2188 @safe unittest
2189 {
2190     auto value = tuple(5, 6.7, "hello");
2191     assert(value[0] == 5);
2192     assert(value[1] == 6.7);
2193     assert(value[2] == "hello");
2194 
2195     // Field names can be provided.
2196     auto entry = tuple!("index", "value")(4, "Hello");
2197     assert(entry.index == 4);
2198     assert(entry.value == "Hello");
2199 }
2200 
2201 /**
2202     Returns `true` if and only if `T` is an instance of `std.typecons.Tuple`.
2203 
2204     Params:
2205         T = The type to check.
2206 
2207     Returns:
2208         true if `T` is a `Tuple` type, false otherwise.
2209  */
2210 enum isTuple(T) = __traits(compiles,
2211                            {
2212                                void f(Specs...)(Tuple!Specs tup) {}
2213                                f(T.init);
2214                            } );
2215 
2216 ///
2217 @safe unittest
2218 {
2219     static assert(isTuple!(Tuple!()));
2220     static assert(isTuple!(Tuple!(int)));
2221     static assert(isTuple!(Tuple!(int, real, string)));
2222     static assert(isTuple!(Tuple!(int, "x", real, "y")));
2223     static assert(isTuple!(Tuple!(int, Tuple!(real), string)));
2224 }
2225 
2226 @safe unittest
2227 {
2228     static assert(isTuple!(const Tuple!(int)));
2229     static assert(isTuple!(immutable Tuple!(int)));
2230 
2231     static assert(!isTuple!(int));
2232     static assert(!isTuple!(const int));
2233 
2234     struct S {}
2235     static assert(!isTuple!(S));
2236 }
2237 
2238 // used by both Rebindable and UnqualRef
2239 private mixin template RebindableCommon(T, U, alias This)
2240 if (is(T == class) || is(T == interface) || isAssociativeArray!T)
2241 {
2242     private union
2243     {
2244         T original;
2245         U stripped;
2246     }
2247 
2248     void opAssign(return scope T another) pure nothrow @nogc
2249     {
2250         // If `T` defines `opCast` we must infer the safety
2251         static if (hasMember!(T, "opCast"))
2252         {
2253             // This will allow the compiler to infer the safety of `T.opCast!U`
2254             // without generating any runtime cost
2255             if (false) { stripped = cast(U) another; }
2256         }
2257         () @trusted { stripped = cast(U) another; }();
2258     }
2259 
2260     void opAssign(typeof(this) another) @trusted pure nothrow @nogc
2261     {
2262         stripped = another.stripped;
2263     }
2264 
2265     static if (is(T == const U) && is(T == const shared U))
2266     {
2267         // safely assign immutable to const / const shared
2268         void opAssign(This!(immutable U) another) @trusted pure nothrow @nogc
2269         {
2270             stripped = another.stripped;
2271         }
2272     }
2273 
2274     this(T initializer) pure nothrow @nogc
2275     {
2276         // Infer safety from opAssign
2277         opAssign(initializer);
2278     }
2279 
2280     @property inout(T) get() @trusted pure nothrow @nogc return scope inout
2281     {
2282         return original;
2283     }
2284 
2285     bool opEquals()(auto ref const(typeof(this)) rhs) const
2286     {
2287         // Must forward explicitly because 'stripped' is part of a union.
2288         // The necessary 'toHash' is forwarded to the class via alias this.
2289         return stripped == rhs.stripped;
2290     }
2291 
2292     bool opEquals(const(U) rhs) const
2293     {
2294         return stripped == rhs;
2295     }
2296 
2297     alias get this;
2298 }
2299 
2300 /**
2301 `Rebindable!(T)` is a simple, efficient wrapper that behaves just
2302 like an object of type `T`, except that you can reassign it to
2303 refer to another object. For completeness, `Rebindable!(T)` aliases
2304 itself away to `T` if `T` is a non-const object type.
2305 
2306 You may want to use `Rebindable` when you want to have mutable
2307 storage referring to `const` objects, for example an array of
2308 references that must be sorted in place. `Rebindable` does not
2309 break the soundness of D's type system and does not incur any of the
2310 risks usually associated with `cast`.
2311 
2312 Params:
2313     T = An object, interface, array slice type, or associative array type.
2314  */
2315 template Rebindable(T)
2316 if (is(T == class) || is(T == interface) || isDynamicArray!T || isAssociativeArray!T)
2317 {
2318     static if (is(T == const U, U) || is(T == immutable U, U))
2319     {
2320         static if (isDynamicArray!T)
2321         {
2322             import std.range.primitives : ElementEncodingType;
2323             alias Rebindable = const(ElementEncodingType!T)[];
2324         }
2325         else
2326         {
2327             struct Rebindable
2328             {
2329                 mixin RebindableCommon!(T, U, Rebindable);
2330             }
2331         }
2332     }
2333     else
2334     {
2335         alias Rebindable = T;
2336     }
2337 }
2338 
2339 ///Regular `const` object references cannot be reassigned.
2340 @safe unittest
2341 {
2342     class Widget { int x; int y() @safe const { return x; } }
2343     const a = new Widget;
2344     // Fine
2345     a.y();
2346     // error! can't modify const a
2347     // a.x = 5;
2348     // error! can't modify const a
2349     // a = new Widget;
2350 }
2351 
2352 /**
2353     However, `Rebindable!(Widget)` does allow reassignment,
2354     while otherwise behaving exactly like a $(D const Widget).
2355  */
2356 @safe unittest
2357 {
2358     class Widget { int x; int y() const @safe { return x; } }
2359     auto a = Rebindable!(const Widget)(new Widget);
2360     // Fine
2361     a.y();
2362     // error! can't modify const a
2363     // a.x = 5;
2364     // Fine
2365     a = new Widget;
2366 }
2367 
2368 // https://issues.dlang.org/show_bug.cgi?id=16054
2369 @safe unittest
2370 {
2371     Rebindable!(immutable Object) r;
2372     static assert(__traits(compiles, r.get()));
2373     static assert(!__traits(compiles, &r.get()));
2374 }
2375 
2376 @safe unittest
2377 {
2378     class CustomToHash
2379     {
2380         override size_t toHash() const nothrow @trusted { return 42; }
2381     }
2382     Rebindable!(immutable(CustomToHash)) a = new immutable CustomToHash();
2383     assert(a.toHash() == 42, "Rebindable!A should offer toHash()"
2384         ~ " by forwarding to A.toHash().");
2385 }
2386 
2387 // https://issues.dlang.org/show_bug.cgi?id=18615
2388 // Rebindable!A should use A.opEqualsa
2389 @system unittest
2390 {
2391     class CustomOpEq
2392     {
2393         int x;
2394         override bool opEquals(Object rhsObj)
2395         {
2396             if (auto rhs = cast(const(CustomOpEq)) rhsObj)
2397                 return this.x == rhs.x;
2398             else
2399                 return false;
2400         }
2401     }
2402     CustomOpEq a = new CustomOpEq();
2403     CustomOpEq b = new CustomOpEq();
2404     assert(a !is b);
2405     assert(a == b, "a.x == b.x should be true (0 == 0).");
2406 
2407     Rebindable!(const(CustomOpEq)) ra = a;
2408     Rebindable!(const(CustomOpEq)) rb = b;
2409     assert(ra !is rb);
2410     assert(ra == rb, "Rebindable should use CustomOpEq's opEquals, not 'is'.");
2411     assert(ra == b, "Rebindable!(someQualifier(A)) should be comparable"
2412         ~ " against const(A) via A.opEquals.");
2413     assert(a == rb, "Rebindable!(someQualifier(A)) should be comparable"
2414         ~ " against const(A) via A.opEquals.");
2415 
2416     b.x = 1;
2417     assert(a != b);
2418     assert(ra != b, "Rebindable!(someQualifier(A)) should be comparable"
2419         ~ " against const(A) via A.opEquals.");
2420     assert(a != rb, "Rebindable!(someQualifier(A)) should be comparable"
2421         ~ " against const(A) via A.opEquals.");
2422 
2423     Rebindable!(const(Object)) o1 = new Object();
2424     Rebindable!(const(Object)) o2 = new Object();
2425     assert(o1 !is o2);
2426     assert(o1 == o1, "When the class doesn't provide its own opEquals,"
2427         ~ " Rebindable treats 'a == b' as 'a is b' like Object.opEquals.");
2428     assert(o1 != o2, "When the class doesn't provide its own opEquals,"
2429         ~ " Rebindable treats 'a == b' as 'a is b' like Object.opEquals.");
2430     assert(o1 != new Object(), "Rebindable!(const(Object)) should be"
2431         ~ " comparable against Object itself and use Object.opEquals.");
2432 }
2433 
2434 // https://issues.dlang.org/show_bug.cgi?id=18755
2435 @safe unittest
2436 {
2437     static class Foo
2438     {
2439         auto opCast(T)() @system immutable pure nothrow
2440         {
2441             *(cast(uint*) 0xdeadbeef) = 0xcafebabe;
2442             return T.init;
2443         }
2444     }
2445 
2446     static assert(!__traits(compiles, () @safe {
2447         auto r = Rebindable!(immutable Foo)(new Foo);
2448     }));
2449     static assert(__traits(compiles, () @system {
2450         auto r = Rebindable!(immutable Foo)(new Foo);
2451     }));
2452 }
2453 
2454 /**
2455 Convenience function for creating a `Rebindable` using automatic type
2456 inference.
2457 
2458 Params:
2459     obj = A reference to an object, interface, associative array, or an array slice
2460           to initialize the `Rebindable` with.
2461 
2462 Returns:
2463     A newly constructed `Rebindable` initialized with the given reference.
2464 */
2465 Rebindable!T rebindable(T)(T obj)
2466 if (is(T == class) || is(T == interface) || isDynamicArray!T || isAssociativeArray!T)
2467 {
2468     typeof(return) ret;
2469     ret = obj;
2470     return ret;
2471 }
2472 
2473 ///
2474 @system unittest
2475 {
2476     class C
2477     {
2478         int payload;
2479         this(int p) { payload = p; }
2480     }
2481     const c = new C(1);
2482 
2483     auto c2 = c.rebindable;
2484     assert(c2.payload == 1);
2485     // passing Rebindable to rebindable
2486     c2 = c2.rebindable;
2487 
2488     c2 = new C(2);
2489     assert(c2.payload == 2);
2490 
2491     const c3 = c2.get;
2492     assert(c3.payload == 2);
2493 }
2494 
2495 /**
2496 This function simply returns the `Rebindable` object passed in.  It's useful
2497 in generic programming cases when a given object may be either a regular
2498 `class` or a `Rebindable`.
2499 
2500 Params:
2501     obj = An instance of Rebindable!T.
2502 
2503 Returns:
2504     `obj` without any modification.
2505 */
2506 Rebindable!T rebindable(T)(Rebindable!T obj)
2507 {
2508     return obj;
2509 }
2510 
2511 // TODO: remove me once the rebindable overloads have been joined
2512 ///
2513 @system unittest
2514 {
2515     class C
2516     {
2517         int payload;
2518         this(int p) { payload = p; }
2519     }
2520     const c = new C(1);
2521 
2522     auto c2 = c.rebindable;
2523     assert(c2.payload == 1);
2524     // passing Rebindable to rebindable
2525     c2 = c2.rebindable;
2526     assert(c2.payload == 1);
2527 }
2528 
2529 @system unittest
2530 {
2531     interface CI { int foo() const; }
2532     class C : CI {
2533       int foo() const { return 42; }
2534       @property int bar() const { return 23; }
2535     }
2536     Rebindable!(C) obj0;
2537     static assert(is(typeof(obj0) == C));
2538 
2539     Rebindable!(const(C)) obj1;
2540     static assert(is(typeof(obj1.get) == const(C)), typeof(obj1.get).stringof);
2541     static assert(is(typeof(obj1.stripped) == C));
2542     obj1 = new C;
2543     assert(obj1.get !is null);
2544     obj1 = new const(C);
2545     assert(obj1.get !is null);
2546 
2547     Rebindable!(immutable(C)) obj2;
2548     static assert(is(typeof(obj2.get) == immutable(C)));
2549     static assert(is(typeof(obj2.stripped) == C));
2550     obj2 = new immutable(C);
2551     assert(obj1.get !is null);
2552 
2553     // test opDot
2554     assert(obj2.foo() == 42);
2555     assert(obj2.bar == 23);
2556 
2557     interface I { final int foo() const { return 42; } }
2558     Rebindable!(I) obj3;
2559     static assert(is(typeof(obj3) == I));
2560 
2561     Rebindable!(const I) obj4;
2562     static assert(is(typeof(obj4.get) == const I));
2563     static assert(is(typeof(obj4.stripped) == I));
2564     static assert(is(typeof(obj4.foo()) == int));
2565     obj4 = new class I {};
2566 
2567     Rebindable!(immutable C) obj5i;
2568     Rebindable!(const C) obj5c;
2569     obj5c = obj5c;
2570     obj5c = obj5i;
2571     obj5i = obj5i;
2572     static assert(!__traits(compiles, obj5i = obj5c));
2573 
2574     // Test the convenience functions.
2575     auto obj5convenience = rebindable(obj5i);
2576     assert(obj5convenience is obj5i);
2577 
2578     auto obj6 = rebindable(new immutable(C));
2579     static assert(is(typeof(obj6) == Rebindable!(immutable C)));
2580     assert(obj6.foo() == 42);
2581 
2582     auto obj7 = rebindable(new C);
2583     CI interface1 = obj7;
2584     auto interfaceRebind1 = rebindable(interface1);
2585     assert(interfaceRebind1.foo() == 42);
2586 
2587     const interface2 = interface1;
2588     auto interfaceRebind2 = rebindable(interface2);
2589     assert(interfaceRebind2.foo() == 42);
2590 
2591     auto arr = [1,2,3,4,5];
2592     const arrConst = arr;
2593     assert(rebindable(arr) == arr);
2594     assert(rebindable(arrConst) == arr);
2595 
2596     // https://issues.dlang.org/show_bug.cgi?id=7654
2597     immutable(char[]) s7654;
2598     Rebindable!(typeof(s7654)) r7654 = s7654;
2599 
2600     static foreach (T; AliasSeq!(char, wchar, char, int))
2601     {
2602         static assert(is(Rebindable!(immutable(T[])) == immutable(T)[]));
2603         static assert(is(Rebindable!(const(T[])) == const(T)[]));
2604         static assert(is(Rebindable!(T[]) == T[]));
2605     }
2606 
2607     // https://issues.dlang.org/show_bug.cgi?id=12046
2608     static assert(!__traits(compiles, Rebindable!(int[1])));
2609     static assert(!__traits(compiles, Rebindable!(const int[1])));
2610 
2611     // Pull request 3341
2612     Rebindable!(immutable int[int]) pr3341 = [123:345];
2613     assert(pr3341[123] == 345);
2614     immutable int[int] pr3341_aa = [321:543];
2615     pr3341 = pr3341_aa;
2616     assert(pr3341[321] == 543);
2617     assert(rebindable(pr3341_aa)[321] == 543);
2618 }
2619 
2620 /**
2621     Similar to `Rebindable!(T)` but strips all qualifiers from the reference as
2622     opposed to just constness / immutability. Primary intended use case is with
2623     shared (having thread-local reference to shared class data)
2624 
2625     Params:
2626         T = A class or interface type.
2627  */
2628 template UnqualRef(T)
2629 if (is(T == class) || is(T == interface))
2630 {
2631     static if (is(T == immutable U, U)
2632         || is(T == const shared U, U)
2633         || is(T == const U, U)
2634         || is(T == shared U, U))
2635     {
2636         struct UnqualRef
2637         {
2638             mixin RebindableCommon!(T, U, UnqualRef);
2639         }
2640     }
2641     else
2642     {
2643         alias UnqualRef = T;
2644     }
2645 }
2646 
2647 ///
2648 @system unittest
2649 {
2650     class Data {}
2651 
2652     static shared(Data) a;
2653     static UnqualRef!(shared Data) b;
2654 
2655     import core.thread;
2656 
2657     auto thread = new core.thread.Thread({
2658         a = new shared Data();
2659         b = new shared Data();
2660     });
2661 
2662     thread.start();
2663     thread.join();
2664 
2665     assert(a !is null);
2666     assert(b is null);
2667 }
2668 
2669 @safe unittest
2670 {
2671     class C { }
2672     alias T = UnqualRef!(const shared C);
2673     static assert(is(typeof(T.stripped) == C));
2674 }
2675 
2676 
2677 
2678 /**
2679   Order the provided members to minimize size while preserving alignment.
2680   Alignment is not always optimal for 80-bit reals, nor for structs declared
2681   as align(1).
2682 
2683   Params:
2684       E = A list of the types to be aligned, representing fields
2685           of an aggregate such as a `struct` or `class`.
2686 
2687       names = The names of the fields that are to be aligned.
2688 
2689   Returns:
2690       A string to be mixed in to an aggregate, such as a `struct` or `class`.
2691 */
2692 string alignForSize(E...)(const char[][] names...)
2693 {
2694     // Sort all of the members by .alignof.
2695     // BUG: Alignment is not always optimal for align(1) structs
2696     // or 80-bit reals or 64-bit primitives on x86.
2697     // TRICK: Use the fact that .alignof is always a power of 2,
2698     // and maximum 16 on extant systems. Thus, we can perform
2699     // a very limited radix sort.
2700     // Contains the members with .alignof = 64,32,16,8,4,2,1
2701 
2702     assert(E.length == names.length,
2703         "alignForSize: There should be as many member names as the types");
2704 
2705     string[7] declaration = ["", "", "", "", "", "", ""];
2706 
2707     foreach (i, T; E)
2708     {
2709         auto a = T.alignof;
2710         auto k = a >= 64? 0 : a >= 32? 1 : a >= 16? 2 : a >= 8? 3 : a >= 4? 4 : a >= 2? 5 : 6;
2711         declaration[k] ~= T.stringof ~ " " ~ names[i] ~ ";\n";
2712     }
2713 
2714     auto s = "";
2715     foreach (decl; declaration)
2716         s ~= decl;
2717     return s;
2718 }
2719 
2720 ///
2721 @safe unittest
2722 {
2723     struct Banner {
2724         mixin(alignForSize!(byte[6], double)(["name", "height"]));
2725     }
2726 }
2727 
2728 @safe unittest
2729 {
2730     enum x = alignForSize!(int[], char[3], short, double[5])("x", "y","z", "w");
2731     struct Foo { int x; }
2732     enum y = alignForSize!(ubyte, Foo, double)("x", "y", "z");
2733 
2734     enum passNormalX = x == "double[5] w;\nint[] x;\nshort z;\nchar[3] y;\n";
2735     enum passNormalY = y == "double z;\nFoo y;\nubyte x;\n";
2736 
2737     enum passAbnormalX = x == "int[] x;\ndouble[5] w;\nshort z;\nchar[3] y;\n";
2738     enum passAbnormalY = y == "Foo y;\ndouble z;\nubyte x;\n";
2739     // ^ blame https://issues.dlang.org/show_bug.cgi?id=231
2740 
2741     static assert(passNormalX || passAbnormalX && double.alignof <= (int[]).alignof);
2742     static assert(passNormalY || passAbnormalY && double.alignof <= int.alignof);
2743 }
2744 
2745 // https://issues.dlang.org/show_bug.cgi?id=12914
2746 @safe unittest
2747 {
2748     immutable string[] fieldNames = ["x", "y"];
2749     struct S
2750     {
2751         mixin(alignForSize!(byte, int)(fieldNames));
2752     }
2753 }
2754 
2755 /**
2756 Defines a value paired with a distinctive "null" state that denotes
2757 the absence of a value. If default constructed, a $(D
2758 Nullable!T) object starts in the null state. Assigning it renders it
2759 non-null. Calling `nullify` can nullify it again.
2760 
2761 Practically `Nullable!T` stores a `T` and a `bool`.
2762  */
2763 struct Nullable(T)
2764 {
2765     private union DontCallDestructorT
2766     {
2767         import std.traits : hasIndirections;
2768         static if (hasIndirections!T)
2769             T payload;
2770         else
2771             T payload = void;
2772     }
2773 
2774     private DontCallDestructorT _value = DontCallDestructorT.init;
2775 
2776     private bool _isNull = true;
2777 
2778     /**
2779      * Constructor initializing `this` with `value`.
2780      *
2781      * Params:
2782      *     value = The value to initialize this `Nullable` with.
2783      */
2784     this(inout T value) inout
2785     {
2786         _value.payload = value;
2787         _isNull = false;
2788     }
2789 
2790     static if (hasElaborateDestructor!T)
2791     {
2792         ~this()
2793         {
2794             if (!_isNull)
2795             {
2796                 destroy(_value.payload);
2797             }
2798         }
2799     }
2800 
2801     static if (__traits(hasPostblit, T))
2802     {
2803         this(this)
2804         {
2805             if (!_isNull)
2806                 _value.payload.__xpostblit();
2807         }
2808     }
2809     else static if (__traits(hasCopyConstructor, T))
2810     {
2811         this(ref return scope inout Nullable!T rhs) inout
2812         {
2813             _isNull = rhs._isNull;
2814             if (!_isNull)
2815                 _value.payload = rhs._value.payload;
2816             else
2817                 _value = DontCallDestructorT.init;
2818         }
2819     }
2820 
2821     /**
2822      * If they are both null, then they are equal. If one is null and the other
2823      * is not, then they are not equal. If they are both non-null, then they are
2824      * equal if their values are equal.
2825      */
2826     bool opEquals(this This, Rhs)(auto ref Rhs rhs)
2827     if (!is(CommonType!(This, Rhs) == void))
2828     {
2829         static if (is(This == Rhs))
2830         {
2831             if (_isNull)
2832                 return rhs._isNull;
2833             if (rhs._isNull)
2834                 return false;
2835             return _value.payload == rhs._value.payload;
2836         }
2837         else
2838         {
2839             alias Common = CommonType!(This, Rhs);
2840             return cast(Common) this == cast(Common) rhs;
2841         }
2842     }
2843 
2844     /// Ditto
2845     bool opEquals(this This, Rhs)(auto ref Rhs rhs)
2846     if (is(CommonType!(This, Rhs) == void) && is(typeof(this.get == rhs)))
2847     {
2848         return _isNull ? false : rhs == _value.payload;
2849     }
2850 
2851     ///
2852     @safe unittest
2853     {
2854         Nullable!int empty;
2855         Nullable!int a = 42;
2856         Nullable!int b = 42;
2857         Nullable!int c = 27;
2858 
2859         assert(empty == empty);
2860         assert(empty == Nullable!int.init);
2861         assert(empty != a);
2862         assert(empty != b);
2863         assert(empty != c);
2864 
2865         assert(a == b);
2866         assert(a != c);
2867 
2868         assert(empty != 42);
2869         assert(a == 42);
2870         assert(c != 42);
2871     }
2872 
2873     @safe unittest
2874     {
2875         // Test constness
2876         immutable Nullable!int a = 42;
2877         Nullable!int b = 42;
2878         immutable Nullable!int c = 29;
2879         Nullable!int d = 29;
2880         immutable e = 42;
2881         int f = 29;
2882         assert(a == a);
2883         assert(a == b);
2884         assert(a != c);
2885         assert(a != d);
2886         assert(a == e);
2887         assert(a != f);
2888 
2889         // Test rvalue
2890         assert(a == const Nullable!int(42));
2891         assert(a != Nullable!int(29));
2892     }
2893 
2894     // https://issues.dlang.org/show_bug.cgi?id=17482
2895     @system unittest
2896     {
2897         import std.variant : Variant;
2898         Nullable!Variant a = Variant(12);
2899         assert(a == 12);
2900         Nullable!Variant e;
2901         assert(e != 12);
2902     }
2903 
2904     size_t toHash() const @safe nothrow
2905     {
2906         static if (__traits(compiles, .hashOf(_value.payload)))
2907             return _isNull ? 0 : .hashOf(_value.payload);
2908         else
2909             // Workaround for when .hashOf is not both @safe and nothrow.
2910             return _isNull ? 0 : typeid(T).getHash(&_value.payload);
2911     }
2912 
2913     /**
2914      * Gives the string `"Nullable.null"` if `isNull` is `true`. Otherwise, the
2915      * result is equivalent to calling $(REF formattedWrite, std,format) on the
2916      * underlying value.
2917      *
2918      * Params:
2919      *     writer = A `char` accepting
2920      *     $(REF_ALTTEXT output range, isOutputRange, std, range, primitives)
2921      *     fmt = A $(REF FormatSpec, std,format) which is used to represent
2922      *     the value if this Nullable is not null
2923      * Returns:
2924      *     A `string` if `writer` and `fmt` are not set; `void` otherwise.
2925      */
2926     string toString()
2927     {
2928         import std.array : appender;
2929         auto app = appender!string();
2930         auto spec = singleSpec("%s");
2931         toString(app, spec);
2932         return app.data;
2933     }
2934 
2935     /// ditto
2936     string toString() const
2937     {
2938         import std.array : appender;
2939         auto app = appender!string();
2940         auto spec = singleSpec("%s");
2941         toString(app, spec);
2942         return app.data;
2943     }
2944 
2945     /// ditto
2946     void toString(W)(ref W writer, scope const ref FormatSpec!char fmt)
2947     if (isOutputRange!(W, char))
2948     {
2949         import std.range.primitives : put;
2950         if (isNull)
2951             put(writer, "Nullable.null");
2952         else
2953             formatValue(writer, _value.payload, fmt);
2954     }
2955 
2956     /// ditto
2957     void toString(W)(ref W writer, scope const ref FormatSpec!char fmt) const
2958     if (isOutputRange!(W, char))
2959     {
2960         import std.range.primitives : put;
2961         if (isNull)
2962             put(writer, "Nullable.null");
2963         else
2964             formatValue(writer, _value.payload, fmt);
2965     }
2966 
2967     /**
2968      * Check if `this` is in the null state.
2969      *
2970      * Returns:
2971      *     true $(B iff) `this` is in the null state, otherwise false.
2972      */
2973     @property bool isNull() const @safe pure nothrow
2974     {
2975         return _isNull;
2976     }
2977 
2978     ///
2979     @safe unittest
2980     {
2981         Nullable!int ni;
2982         assert(ni.isNull);
2983 
2984         ni = 0;
2985         assert(!ni.isNull);
2986     }
2987 
2988     // https://issues.dlang.org/show_bug.cgi?id=14940
2989     @safe unittest
2990     {
2991         import std.array : appender;
2992         import std.format.write : formattedWrite;
2993 
2994         auto app = appender!string();
2995         Nullable!int a = 1;
2996         formattedWrite(app, "%s", a);
2997         assert(app.data == "1");
2998     }
2999 
3000     // https://issues.dlang.org/show_bug.cgi?id=19799
3001     @safe unittest
3002     {
3003         import std.format : format;
3004 
3005         const Nullable!string a = const(Nullable!string)();
3006 
3007         format!"%s"(a);
3008     }
3009 
3010     /**
3011      * Forces `this` to the null state.
3012      */
3013     void nullify()()
3014     {
3015         static if (is(T == class) || is(T == interface))
3016             _value.payload = null;
3017         else
3018             .destroy(_value.payload);
3019         _isNull = true;
3020     }
3021 
3022     ///
3023     @safe unittest
3024     {
3025         Nullable!int ni = 0;
3026         assert(!ni.isNull);
3027 
3028         ni.nullify();
3029         assert(ni.isNull);
3030     }
3031 
3032     /**
3033      * Assigns `value` to the internally-held state. If the assignment
3034      * succeeds, `this` becomes non-null.
3035      *
3036      * Params:
3037      *     value = A value of type `T` to assign to this `Nullable`.
3038      */
3039     Nullable opAssign()(T value)
3040     {
3041         import std.algorithm.mutation : moveEmplace, move;
3042 
3043         // the lifetime of the value in copy shall be managed by
3044         // this Nullable, so we must avoid calling its destructor.
3045         auto copy = DontCallDestructorT(value);
3046 
3047         if (_isNull)
3048         {
3049             // trusted since payload is known to be uninitialized.
3050             () @trusted { moveEmplace(copy.payload, _value.payload); }();
3051         }
3052         else
3053         {
3054             move(copy.payload, _value.payload);
3055         }
3056         _isNull = false;
3057         return this;
3058     }
3059 
3060     /**
3061      * If this `Nullable` wraps a type that already has a null value
3062      * (such as a pointer), then assigning the null value to this
3063      * `Nullable` is no different than assigning any other value of
3064      * type `T`, and the resulting code will look very strange. It
3065      * is strongly recommended that this be avoided by instead using
3066      * the version of `Nullable` that takes an additional `nullValue`
3067      * template argument.
3068      */
3069     @safe unittest
3070     {
3071         //Passes
3072         Nullable!(int*) npi;
3073         assert(npi.isNull);
3074 
3075         //Passes?!
3076         npi = null;
3077         assert(!npi.isNull);
3078     }
3079 
3080     /**
3081      * Gets the value if not null. If `this` is in the null state, and the optional
3082      * parameter `fallback` was provided, it will be returned. Without `fallback`,
3083      * calling `get` with a null state is invalid.
3084      *
3085      * When the fallback type is different from the Nullable type, `get(T)` returns
3086      * the common type.
3087      *
3088      * Params:
3089      *     fallback = the value to return in case the `Nullable` is null.
3090      *
3091      * Returns:
3092      *     The value held internally by this `Nullable`.
3093      */
3094     @property ref inout(T) get() inout @safe pure nothrow
3095     {
3096         enum message = "Called `get' on null Nullable!" ~ T.stringof ~ ".";
3097         assert(!isNull, message);
3098         return _value.payload;
3099     }
3100 
3101     /// ditto
3102     @property inout(T) get()(inout(T) fallback) inout
3103     {
3104         return isNull ? fallback : _value.payload;
3105     }
3106 
3107     /// ditto
3108     @property auto get(U)(inout(U) fallback) inout
3109     {
3110         return isNull ? fallback : _value.payload;
3111     }
3112 
3113     /// $(MREF_ALTTEXT Range interface, std, range, primitives) functions.
3114     alias empty = isNull;
3115 
3116     /// ditto
3117     alias popFront = nullify;
3118 
3119     /// ditto
3120     alias popBack = nullify;
3121 
3122     /// ditto
3123     @property ref inout(T) front() inout @safe pure nothrow
3124     {
3125         return get();
3126     }
3127 
3128     /// ditto
3129     alias back = front;
3130 
3131     /// ditto
3132     @property inout(typeof(this)) save() inout
3133     {
3134         return this;
3135     }
3136 
3137     /// ditto
3138     inout(typeof(this)) opIndex() inout
3139     {
3140         return this;
3141     }
3142 
3143     /// ditto
3144     inout(typeof(this)) opIndex(size_t[2] dim) inout
3145     in (dim[0] <= length && dim[1] <= length && dim[1] >= dim[0])
3146     {
3147         return (dim[0] == 0 && dim[1] == 1) ? this : this.init;
3148     }
3149     /// ditto
3150     size_t[2] opSlice(size_t dim : 0)(size_t from, size_t to) const
3151     {
3152         return [from, to];
3153     }
3154 
3155     /// ditto
3156     @property size_t length() const @safe pure nothrow
3157     {
3158         return !empty;
3159     }
3160 
3161     /// ditto
3162     alias opDollar(size_t dim : 0) = length;
3163 
3164     /// ditto
3165     ref inout(T) opIndex(size_t index) inout @safe pure nothrow
3166     in (index < length)
3167     {
3168         return get();
3169     }
3170 }
3171 
3172 /// ditto
3173 auto nullable(T)(T t)
3174 {
3175     return Nullable!T(t);
3176 }
3177 
3178 ///
3179 @safe unittest
3180 {
3181     struct CustomerRecord
3182     {
3183         string name;
3184         string address;
3185         int customerNum;
3186     }
3187 
3188     Nullable!CustomerRecord getByName(string name)
3189     {
3190         //A bunch of hairy stuff
3191 
3192         return Nullable!CustomerRecord.init;
3193     }
3194 
3195     auto queryResult = getByName("Doe, John");
3196     if (!queryResult.isNull)
3197     {
3198         //Process Mr. Doe's customer record
3199         auto address = queryResult.get.address;
3200         auto customerNum = queryResult.get.customerNum;
3201 
3202         //Do some things with this customer's info
3203     }
3204     else
3205     {
3206         //Add the customer to the database
3207     }
3208 }
3209 
3210 ///
3211 @system unittest
3212 {
3213     import std.exception : assertThrown;
3214 
3215     auto a = 42.nullable;
3216     assert(!a.isNull);
3217     assert(a.get == 42);
3218 
3219     a.nullify();
3220     assert(a.isNull);
3221     assertThrown!Throwable(a.get);
3222 }
3223 ///
3224 @safe unittest
3225 {
3226     import std.algorithm.iteration : each, joiner;
3227     Nullable!int a = 42;
3228     Nullable!int b;
3229     // Add each value to an array
3230     int[] arr;
3231     a.each!((n) => arr ~= n);
3232     assert(arr == [42]);
3233     b.each!((n) => arr ~= n);
3234     assert(arr == [42]);
3235     // Take first value from an array of Nullables
3236     Nullable!int[] c = new Nullable!int[](10);
3237     c[7] = Nullable!int(42);
3238     assert(c.joiner.front == 42);
3239 }
3240 @safe unittest
3241 {
3242     auto k = Nullable!int(74);
3243     assert(k == 74);
3244     k.nullify();
3245     assert(k.isNull);
3246 }
3247 @safe unittest
3248 {
3249     static int f(scope const Nullable!int x) {
3250         return x.isNull ? 42 : x.get;
3251     }
3252     Nullable!int a;
3253     assert(f(a) == 42);
3254     a = 8;
3255     assert(f(a) == 8);
3256     a.nullify();
3257     assert(f(a) == 42);
3258 }
3259 @system unittest
3260 {
3261     import std.exception : assertThrown;
3262 
3263     static struct S { int x; }
3264     Nullable!S s;
3265     assert(s.isNull);
3266     s = S(6);
3267     assert(s == S(6));
3268     assert(s != S(0));
3269     assert(s.get != S(0));
3270     s.get.x = 9190;
3271     assert(s.get.x == 9190);
3272     s.nullify();
3273     assertThrown!Throwable(s.get.x = 9441);
3274 }
3275 @safe unittest
3276 {
3277     // Ensure Nullable can be used in pure/nothrow/@safe environment.
3278     function() @safe pure nothrow
3279     {
3280         Nullable!int n;
3281         assert(n.isNull);
3282         n = 4;
3283         assert(!n.isNull);
3284         assert(n == 4);
3285         n.nullify();
3286         assert(n.isNull);
3287     }();
3288 }
3289 @system unittest
3290 {
3291     // Ensure Nullable can be used when the value is not pure/nothrow/@safe
3292     static struct S
3293     {
3294         int x;
3295         this(this) @system {}
3296     }
3297 
3298     Nullable!S s;
3299     assert(s.isNull);
3300     s = S(5);
3301     assert(!s.isNull);
3302     assert(s.get.x == 5);
3303     s.nullify();
3304     assert(s.isNull);
3305 }
3306 
3307 // https://issues.dlang.org/show_bug.cgi?id=9404
3308 @safe unittest
3309 {
3310     alias N = Nullable!int;
3311 
3312     void foo(N a)
3313     {
3314         N b;
3315         b = a; // `N b = a;` works fine
3316     }
3317     N n;
3318     foo(n);
3319 }
3320 @safe unittest
3321 {
3322     //Check nullable immutable is constructable
3323     {
3324         auto a1 = Nullable!(immutable int)();
3325         auto a2 = Nullable!(immutable int)(1);
3326         auto i = a2.get;
3327     }
3328     //Check immutable nullable is constructable
3329     {
3330         auto a1 = immutable (Nullable!int)();
3331         auto a2 = immutable (Nullable!int)(1);
3332         auto i = a2.get;
3333     }
3334 }
3335 @safe unittest
3336 {
3337     alias NInt   = Nullable!int;
3338 
3339     //Construct tests
3340     {
3341         //from other Nullable null
3342         NInt a1;
3343         NInt b1 = a1;
3344         assert(b1.isNull);
3345 
3346         //from other Nullable non-null
3347         NInt a2 = NInt(1);
3348         NInt b2 = a2;
3349         assert(b2 == 1);
3350 
3351         //Construct from similar nullable
3352         auto a3 = immutable(NInt)();
3353         NInt b3 = a3;
3354         assert(b3.isNull);
3355     }
3356 
3357     //Assign tests
3358     {
3359         //from other Nullable null
3360         NInt a1;
3361         NInt b1;
3362         b1 = a1;
3363         assert(b1.isNull);
3364 
3365         //from other Nullable non-null
3366         NInt a2 = NInt(1);
3367         NInt b2;
3368         b2 = a2;
3369         assert(b2 == 1);
3370 
3371         //Construct from similar nullable
3372         auto a3 = immutable(NInt)();
3373         NInt b3 = a3;
3374         b3 = a3;
3375         assert(b3.isNull);
3376     }
3377 }
3378 @safe unittest
3379 {
3380     //Check nullable is nicelly embedable in a struct
3381     static struct S1
3382     {
3383         Nullable!int ni;
3384     }
3385     static struct S2 //inspired from 9404
3386     {
3387         Nullable!int ni;
3388         this(ref S2 other)
3389         {
3390             ni = other.ni;
3391         }
3392         void opAssign(ref S2 other)
3393         {
3394             ni = other.ni;
3395         }
3396     }
3397     static foreach (S; AliasSeq!(S1, S2))
3398     {{
3399         S a;
3400         S b = a;
3401         S c;
3402         c = a;
3403     }}
3404 }
3405 
3406 // https://issues.dlang.org/show_bug.cgi?id=10268
3407 @system unittest
3408 {
3409     import std.json;
3410     JSONValue value = null;
3411     auto na = Nullable!JSONValue(value);
3412 
3413     struct S1 { int val; }
3414     struct S2 { int* val; }
3415     struct S3 { immutable int* val; }
3416 
3417     {
3418         auto sm = S1(1);
3419         immutable si = immutable S1(1);
3420         auto x1 =           Nullable!S1(sm);
3421         auto x2 = immutable Nullable!S1(sm);
3422         auto x3 =           Nullable!S1(si);
3423         auto x4 = immutable Nullable!S1(si);
3424         assert(x1.get.val == 1);
3425         assert(x2.get.val == 1);
3426         assert(x3.get.val == 1);
3427         assert(x4.get.val == 1);
3428     }
3429 
3430     auto nm = 10;
3431     immutable ni = 10;
3432 
3433     {
3434         auto sm = S2(&nm);
3435         immutable si = immutable S2(&ni);
3436         auto x1 =           Nullable!S2(sm);
3437         static assert(!__traits(compiles, { auto x2 = immutable Nullable!S2(sm); }));
3438         static assert(!__traits(compiles, { auto x3 =           Nullable!S2(si); }));
3439         auto x4 = immutable Nullable!S2(si);
3440         assert(*x1.get.val == 10);
3441         assert(*x4.get.val == 10);
3442     }
3443 
3444     {
3445         auto sm = S3(&ni);
3446         immutable si = immutable S3(&ni);
3447         auto x1 =           Nullable!S3(sm);
3448         auto x2 = immutable Nullable!S3(sm);
3449         auto x3 =           Nullable!S3(si);
3450         auto x4 = immutable Nullable!S3(si);
3451         assert(*x1.get.val == 10);
3452         assert(*x2.get.val == 10);
3453         assert(*x3.get.val == 10);
3454         assert(*x4.get.val == 10);
3455     }
3456 }
3457 
3458 // https://issues.dlang.org/show_bug.cgi?id=10357
3459 @safe unittest
3460 {
3461     import std.datetime;
3462     Nullable!SysTime time = SysTime(0);
3463 }
3464 
3465 // https://issues.dlang.org/show_bug.cgi?id=10915
3466 @system unittest
3467 {
3468     import std.conv : to;
3469     import std.array;
3470 
3471     Appender!string buffer;
3472 
3473     Nullable!int ni;
3474     assert(ni.to!string() == "Nullable.null");
3475     assert((cast(const) ni).to!string() == "Nullable.null");
3476 
3477     struct Test { string s; }
3478     alias NullableTest = Nullable!Test;
3479 
3480     NullableTest nt = Test("test");
3481     // test output range version
3482     assert(nt.to!string() == `Test("test")`);
3483     // test appender version
3484     assert(nt.toString() == `Test("test")`);
3485     // test const version
3486     assert((cast(const) nt).toString() == `const(Test)("test")`);
3487 
3488     NullableTest ntn = Test("null");
3489     assert(ntn.to!string() == `Test("null")`);
3490 
3491     class TestToString
3492     {
3493         double d;
3494 
3495         this (double d)
3496         {
3497             this.d = d;
3498         }
3499 
3500         override string toString()
3501         {
3502             return d.to!string();
3503         }
3504     }
3505     Nullable!TestToString ntts = new TestToString(2.5);
3506     assert(ntts.to!string() == "2.5");
3507 }
3508 
3509 // https://issues.dlang.org/show_bug.cgi?id=14477
3510 @safe unittest
3511 {
3512     static struct DisabledDefaultConstructor
3513     {
3514         @disable this();
3515         this(int i) { }
3516     }
3517     Nullable!DisabledDefaultConstructor var;
3518     var = DisabledDefaultConstructor(5);
3519     var.nullify;
3520 }
3521 
3522 // https://issues.dlang.org/show_bug.cgi?id=17440
3523 @system unittest
3524 {
3525     static interface I { }
3526 
3527     static class C : I
3528     {
3529         int canary;
3530         ~this()
3531         {
3532             canary = 0x5050DEAD;
3533         }
3534     }
3535     auto c = new C;
3536     c.canary = 0xA71FE;
3537     auto nc = nullable(c);
3538     nc.nullify;
3539     assert(c.canary == 0xA71FE);
3540 
3541     I i = c;
3542     auto ni = nullable(i);
3543     ni.nullify;
3544     assert(c.canary == 0xA71FE);
3545 }
3546 
3547 // https://issues.dlang.org/show_bug.cgi?id=19037
3548 @safe unittest
3549 {
3550     import std.datetime : SysTime;
3551 
3552     struct Test
3553     {
3554         bool b;
3555 
3556         nothrow invariant { assert(b == true); }
3557 
3558         SysTime _st;
3559 
3560         static bool destroyed;
3561 
3562         @disable this();
3563         this(bool b) { this.b = b; }
3564         ~this() @safe { destroyed = true; }
3565 
3566         // mustn't call opAssign on Test.init in Nullable!Test, because the invariant
3567         // will be called before opAssign on the Test.init that is in Nullable
3568         // and Test.init violates its invariant.
3569         void opAssign(Test rhs) @safe { assert(false); }
3570     }
3571 
3572     {
3573         Nullable!Test nt;
3574 
3575         nt = Test(true);
3576 
3577         // destroy value
3578         Test.destroyed = false;
3579 
3580         nt.nullify;
3581 
3582         assert(Test.destroyed);
3583 
3584         Test.destroyed = false;
3585     }
3586     // don't run destructor on T.init in Nullable on scope exit!
3587     assert(!Test.destroyed);
3588 }
3589 // check that the contained type's destructor is called on assignment
3590 @system unittest
3591 {
3592     struct S
3593     {
3594         // can't be static, since we need a specific value's pointer
3595         bool* destroyedRef;
3596 
3597         ~this()
3598         {
3599             if (this.destroyedRef)
3600             {
3601                 *this.destroyedRef = true;
3602             }
3603         }
3604     }
3605 
3606     Nullable!S ns;
3607 
3608     bool destroyed;
3609 
3610     ns = S(&destroyed);
3611 
3612     // reset from rvalue destruction in Nullable's opAssign
3613     destroyed = false;
3614 
3615     // overwrite Nullable
3616     ns = S(null);
3617 
3618     // the original S should be destroyed.
3619     assert(destroyed == true);
3620 }
3621 // check that the contained type's destructor is still called when required
3622 @system unittest
3623 {
3624     bool destructorCalled = false;
3625 
3626     struct S
3627     {
3628         bool* destroyed;
3629         ~this() { *this.destroyed = true; }
3630     }
3631 
3632     {
3633         Nullable!S ns;
3634     }
3635     assert(!destructorCalled);
3636     {
3637         Nullable!S ns = Nullable!S(S(&destructorCalled));
3638 
3639         destructorCalled = false; // reset after S was destroyed in the NS constructor
3640     }
3641     assert(destructorCalled);
3642 }
3643 
3644 // check that toHash on Nullable is forwarded to the contained type
3645 @system unittest
3646 {
3647     struct S
3648     {
3649         size_t toHash() const @safe pure nothrow { return 5; }
3650     }
3651 
3652     Nullable!S s1 = S();
3653     Nullable!S s2 = Nullable!S();
3654 
3655     assert(typeid(Nullable!S).getHash(&s1) == 5);
3656     assert(typeid(Nullable!S).getHash(&s2) == 0);
3657 }
3658 
3659 // https://issues.dlang.org/show_bug.cgi?id=21704
3660 @safe unittest
3661 {
3662     import std.array : staticArray;
3663 
3664     bool destroyed;
3665 
3666     struct Probe
3667     {
3668         ~this() { destroyed = true; }
3669     }
3670 
3671     {
3672         Nullable!(Probe[1]) test = [Probe()].staticArray;
3673         destroyed = false;
3674     }
3675     assert(destroyed);
3676 }
3677 
3678 // https://issues.dlang.org/show_bug.cgi?id=21705
3679 @safe unittest
3680 {
3681     static struct S
3682     {
3683         int n;
3684         bool opEquals(S rhs) { return n == rhs.n; }
3685     }
3686 
3687     Nullable!S test1 = S(1), test2 = S(1);
3688     S s = S(1);
3689 
3690     assert(test1 == s);
3691     assert(test1 == test2);
3692 }
3693 
3694 // https://issues.dlang.org/show_bug.cgi?id=22101
3695 @safe unittest
3696 {
3697     static int impure;
3698 
3699     struct S
3700     {
3701         ~this() { impure++; }
3702     }
3703 
3704     Nullable!S s;
3705     s.get(S());
3706 }
3707 
3708 // https://issues.dlang.org/show_bug.cgi?id=22100
3709 @safe unittest
3710 {
3711     Nullable!int a, b, c;
3712     a = b = c = 5;
3713     a = b = c = nullable(5);
3714 }
3715 
3716 // https://issues.dlang.org/show_bug.cgi?id=18374
3717 @safe pure nothrow unittest
3718 {
3719     import std.algorithm.comparison : equal;
3720     import std.range : only, takeNone;
3721     import std.range.primitives : hasAssignableElements, hasLength,
3722         hasLvalueElements, hasSlicing, hasSwappableElements,
3723         isRandomAccessRange;
3724     Nullable!int a = 42;
3725     assert(!a.empty);
3726     assert(a.front == 42);
3727     assert(a.back == 42);
3728     assert(a[0] == 42);
3729     assert(a.equal(only(42)));
3730     assert(a[0 .. $].equal(only(42)));
3731     a[0] = 43;
3732     assert(a.equal(only(43)));
3733     --a[0];
3734     assert(a.equal(only(42)));
3735     Nullable!int b;
3736     assert(b.empty);
3737     assert(b.equal(takeNone(b)));
3738     Nullable!int c = a.save();
3739     assert(!c.empty);
3740     c.popFront();
3741     assert(!a.empty);
3742     assert(c.empty);
3743 
3744     assert(isRandomAccessRange!(Nullable!int));
3745     assert(hasLength!(Nullable!int));
3746     assert(hasSlicing!(Nullable!int));
3747     assert(hasAssignableElements!(Nullable!int));
3748     assert(hasSwappableElements!(Nullable!int));
3749     assert(hasLvalueElements!(Nullable!int));
3750 }
3751 
3752 /**
3753 Just like `Nullable!T`, except that the null state is defined as a
3754 particular value. For example, $(D Nullable!(uint, uint.max)) is an
3755 `uint` that sets aside the value `uint.max` to denote a null
3756 state. $(D Nullable!(T, nullValue)) is more storage-efficient than $(D
3757 Nullable!T) because it does not need to store an extra `bool`.
3758 
3759 Params:
3760     T = The wrapped type for which Nullable provides a null value.
3761 
3762     nullValue = The null value which denotes the null state of this
3763                 `Nullable`. Must be of type `T`.
3764  */
3765 struct Nullable(T, T nullValue)
3766 {
3767     private T _value = nullValue;
3768 
3769 /**
3770 Constructor initializing `this` with `value`.
3771 
3772 Params:
3773     value = The value to initialize this `Nullable` with.
3774  */
3775     this(T value)
3776     {
3777         _value = value;
3778     }
3779 
3780     template toString()
3781     {
3782         import std.format.spec : FormatSpec;
3783         import std.format.write : formatValue;
3784         // Needs to be a template because of https://issues.dlang.org/show_bug.cgi?id=13737.
3785         void toString()(scope void delegate(const(char)[]) sink, scope const ref FormatSpec!char fmt)
3786         {
3787             if (isNull)
3788             {
3789                 sink.formatValue("Nullable.null", fmt);
3790             }
3791             else
3792             {
3793                 sink.formatValue(_value, fmt);
3794             }
3795         }
3796 
3797         void toString()(scope void delegate(const(char)[]) sink, scope const ref FormatSpec!char fmt) const
3798         {
3799             if (isNull)
3800             {
3801                 sink.formatValue("Nullable.null", fmt);
3802             }
3803             else
3804             {
3805                 sink.formatValue(_value, fmt);
3806             }
3807         }
3808     }
3809 
3810 @system unittest
3811 {
3812     import std.conv : to;
3813 
3814     const Nullable!(ulong, 0) x = 1;
3815     assert(x.to!string == "1");
3816 }
3817 
3818 /**
3819 Check if `this` is in the null state.
3820 
3821 Returns:
3822     true $(B iff) `this` is in the null state, otherwise false.
3823  */
3824     @property bool isNull() const
3825     {
3826         //Need to use 'is' if T is a nullable type and
3827         //nullValue is null, or it's a compiler error
3828         static if (is(CommonType!(T, typeof(null)) == T) && nullValue is null)
3829         {
3830             return _value is nullValue;
3831         }
3832         //Need to use 'is' if T is a float type
3833         //because NaN != NaN
3834         else static if (__traits(isFloating, T) || __traits(compiles, { static assert(!(nullValue == nullValue)); }))
3835         {
3836             return _value is nullValue;
3837         }
3838         else
3839         {
3840             return _value == nullValue;
3841         }
3842     }
3843 
3844 ///
3845 @safe unittest
3846 {
3847     Nullable!(int, -1) ni;
3848     //Initialized to "null" state
3849     assert(ni.isNull);
3850 
3851     ni = 0;
3852     assert(!ni.isNull);
3853 }
3854 
3855 @system unittest
3856 {
3857     assert(typeof(this).init.isNull, typeof(this).stringof ~
3858         ".isNull does not work correctly because " ~ T.stringof ~
3859         " has an == operator that is non-reflexive and could not be" ~
3860         " determined before runtime to be non-reflexive!");
3861 }
3862 
3863 // https://issues.dlang.org/show_bug.cgi?id=11135
3864 // disable test until https://issues.dlang.org/show_bug.cgi?id=15316 gets fixed
3865 version (none) @system unittest
3866 {
3867     static foreach (T; AliasSeq!(float, double, real))
3868     {{
3869         Nullable!(T, T.init) nf;
3870         //Initialized to "null" state
3871         assert(nf.isNull);
3872         assert(nf is typeof(nf).init);
3873 
3874         nf = 0;
3875         assert(!nf.isNull);
3876 
3877         nf.nullify();
3878         assert(nf.isNull);
3879     }}
3880 }
3881 
3882 /**
3883 Forces `this` to the null state.
3884  */
3885     void nullify()()
3886     {
3887         _value = nullValue;
3888     }
3889 
3890 ///
3891 @safe unittest
3892 {
3893     Nullable!(int, -1) ni = 0;
3894     assert(!ni.isNull);
3895 
3896     ni = -1;
3897     assert(ni.isNull);
3898 }
3899 
3900 /**
3901 Assigns `value` to the internally-held state. If the assignment
3902 succeeds, `this` becomes non-null. No null checks are made. Note
3903 that the assignment may leave `this` in the null state.
3904 
3905 Params:
3906     value = A value of type `T` to assign to this `Nullable`.
3907             If it is `nullvalue`, then the internal state of
3908             this `Nullable` will be set to null.
3909  */
3910     void opAssign()(T value)
3911     {
3912         import std.algorithm.mutation : swap;
3913 
3914         swap(value, _value);
3915     }
3916 
3917 /**
3918     If this `Nullable` wraps a type that already has a null value
3919     (such as a pointer), and that null value is not given for
3920     `nullValue`, then assigning the null value to this `Nullable`
3921     is no different than assigning any other value of type `T`,
3922     and the resulting code will look very strange. It is strongly
3923     recommended that this be avoided by using `T`'s "built in"
3924     null value for `nullValue`.
3925  */
3926 @system unittest
3927 {
3928     //Passes
3929     enum nullVal = cast(int*) 0xCAFEBABE;
3930     Nullable!(int*, nullVal) npi;
3931     assert(npi.isNull);
3932 
3933     //Passes?!
3934     npi = null;
3935     assert(!npi.isNull);
3936 }
3937 
3938 /**
3939 Gets the value. `this` must not be in the null state.
3940 This function is also called for the implicit conversion to `T`.
3941 
3942 Preconditions: `isNull` must be `false`.
3943 Returns:
3944     The value held internally by this `Nullable`.
3945  */
3946     @property ref inout(T) get() inout
3947     {
3948         //@@@6169@@@: We avoid any call that might evaluate nullValue's %s,
3949         //Because it might messup get's purity and safety inference.
3950         enum message = "Called `get' on null Nullable!(" ~ T.stringof ~ ",nullValue).";
3951         assert(!isNull, message);
3952         return _value;
3953     }
3954 
3955 ///
3956 @system unittest
3957 {
3958     import std.exception : assertThrown, assertNotThrown;
3959 
3960     Nullable!(int, -1) ni;
3961     //`get` is implicitly called. Will throw
3962     //an error in non-release mode
3963     assertThrown!Throwable(ni == 0);
3964 
3965     ni = 0;
3966     assertNotThrown!Throwable(ni == 0);
3967 }
3968 
3969 /**
3970 Implicitly converts to `T`.
3971 `this` must not be in the null state.
3972  */
3973     alias get this;
3974 }
3975 
3976 /// ditto
3977 auto nullable(alias nullValue, T)(T t)
3978 if (is (typeof(nullValue) == T))
3979 {
3980     return Nullable!(T, nullValue)(t);
3981 }
3982 
3983 ///
3984 @safe unittest
3985 {
3986     Nullable!(size_t, size_t.max) indexOf(string[] haystack, string needle)
3987     {
3988         //Find the needle, returning -1 if not found
3989 
3990         return Nullable!(size_t, size_t.max).init;
3991     }
3992 
3993     void sendLunchInvite(string name)
3994     {
3995     }
3996 
3997     //It's safer than C...
3998     auto coworkers = ["Jane", "Jim", "Marry", "Fred"];
3999     auto pos = indexOf(coworkers, "Bob");
4000     if (!pos.isNull)
4001     {
4002         //Send Bob an invitation to lunch
4003         sendLunchInvite(coworkers[pos]);
4004     }
4005     else
4006     {
4007         //Bob not found; report the error
4008     }
4009 
4010     //And there's no overhead
4011     static assert(Nullable!(size_t, size_t.max).sizeof == size_t.sizeof);
4012 }
4013 
4014 ///
4015 @system unittest
4016 {
4017     import std.exception : assertThrown;
4018 
4019     Nullable!(int, int.min) a;
4020     assert(a.isNull);
4021     assertThrown!Throwable(a.get);
4022     a = 5;
4023     assert(!a.isNull);
4024     assert(a == 5);
4025     static assert(a.sizeof == int.sizeof);
4026 }
4027 
4028 ///
4029 @safe unittest
4030 {
4031     auto a = nullable!(int.min)(8);
4032     assert(a == 8);
4033     a.nullify();
4034     assert(a.isNull);
4035 }
4036 
4037 @nogc nothrow pure @safe unittest
4038 {
4039     // https://issues.dlang.org/show_bug.cgi?id=19226
4040     // fully handle non-self-equal nullValue
4041     static struct Fraction
4042     {
4043         int denominator;
4044         bool isNaN() const
4045         {
4046             return denominator == 0;
4047         }
4048         bool opEquals(const Fraction rhs) const
4049         {
4050             return !isNaN && denominator == rhs.denominator;
4051         }
4052     }
4053     alias N = Nullable!(Fraction, Fraction.init);
4054     assert(N.init.isNull);
4055 }
4056 
4057 @safe unittest
4058 {
4059     static int f(scope const Nullable!(int, int.min) x) {
4060         return x.isNull ? 42 : x.get;
4061     }
4062     Nullable!(int, int.min) a;
4063     assert(f(a) == 42);
4064     a = 8;
4065     assert(f(a) == 8);
4066     a.nullify();
4067     assert(f(a) == 42);
4068 }
4069 @safe unittest
4070 {
4071     // Ensure Nullable can be used in pure/nothrow/@safe environment.
4072     function() @safe pure nothrow
4073     {
4074         Nullable!(int, int.min) n;
4075         assert(n.isNull);
4076         n = 4;
4077         assert(!n.isNull);
4078         assert(n == 4);
4079         n.nullify();
4080         assert(n.isNull);
4081     }();
4082 }
4083 @system unittest
4084 {
4085     // Ensure Nullable can be used when the value is not pure/nothrow/@system
4086     static struct S
4087     {
4088         int x;
4089         bool opEquals(const S s) const @system { return s.x == x; }
4090     }
4091 
4092     Nullable!(S, S(711)) s;
4093     assert(s.isNull);
4094     s = S(5);
4095     assert(!s.isNull);
4096     assert(s.x == 5);
4097     s.nullify();
4098     assert(s.isNull);
4099 }
4100 @safe unittest
4101 {
4102     //Check nullable is nicelly embedable in a struct
4103     static struct S1
4104     {
4105         Nullable!(int, 0) ni;
4106     }
4107     static struct S2 //inspired from 9404
4108     {
4109         Nullable!(int, 0) ni;
4110         this(S2 other)
4111         {
4112             ni = other.ni;
4113         }
4114         void opAssign(S2 other)
4115         {
4116             ni = other.ni;
4117         }
4118     }
4119     static foreach (S; AliasSeq!(S1, S2))
4120     {{
4121         S a;
4122         S b = a;
4123         S c;
4124         c = a;
4125     }}
4126 }
4127 @system unittest
4128 {
4129     import std.conv : to;
4130 
4131     // https://issues.dlang.org/show_bug.cgi?id=10915
4132     Nullable!(int, 1) ni = 1;
4133     assert(ni.to!string() == "Nullable.null");
4134 
4135     struct Test { string s; }
4136     alias NullableTest = Nullable!(Test, Test("null"));
4137 
4138     NullableTest nt = Test("test");
4139     assert(nt.to!string() == `Test("test")`);
4140 
4141     NullableTest ntn = Test("null");
4142     assert(ntn.to!string() == "Nullable.null");
4143 
4144     class TestToString
4145     {
4146         double d;
4147 
4148         this(double d)
4149         {
4150             this.d = d;
4151         }
4152 
4153         override string toString()
4154         {
4155             return d.to!string();
4156         }
4157     }
4158     alias NullableTestToString = Nullable!(TestToString, null);
4159 
4160     NullableTestToString ntts = new TestToString(2.5);
4161     assert(ntts.to!string() == "2.5");
4162 }
4163 
4164 // apply
4165 /**
4166 Unpacks the content of a `Nullable`, performs an operation and packs it again. Does nothing if isNull.
4167 
4168 When called on a `Nullable`, `apply` will unpack the value contained in the `Nullable`,
4169 pass it to the function you provide and wrap the result in another `Nullable` (if necessary).
4170 If the `Nullable` is null, `apply` will return null itself.
4171 
4172 Params:
4173     t = a `Nullable`
4174     fun = a function operating on the content of the nullable
4175 
4176 Returns:
4177     `fun(t.get).nullable` if `!t.isNull`, else `Nullable.init`.
4178 
4179 See also:
4180     $(HTTPS en.wikipedia.org/wiki/Monad_(functional_programming)#The_Maybe_monad, The `Maybe` monad)
4181  */
4182 template apply(alias fun)
4183 {
4184     import std.functional : unaryFun;
4185 
4186     auto apply(T)(auto ref T t)
4187     if (isInstanceOf!(Nullable, T))
4188     {
4189         alias FunType = typeof(unaryFun!fun(T.init.get));
4190 
4191         enum MustWrapReturn = !isInstanceOf!(Nullable, FunType);
4192 
4193         static if (MustWrapReturn)
4194         {
4195             alias ReturnType = Nullable!FunType;
4196         }
4197         else
4198         {
4199             alias ReturnType = FunType;
4200         }
4201 
4202         if (!t.isNull)
4203         {
4204             static if (MustWrapReturn)
4205             {
4206                 return unaryFun!fun(t.get).nullable;
4207             }
4208             else
4209             {
4210                 return unaryFun!fun(t.get);
4211             }
4212         }
4213         else
4214         {
4215             return ReturnType.init;
4216         }
4217     }
4218 }
4219 
4220 ///
4221 nothrow pure @nogc @safe unittest
4222 {
4223     alias toFloat = i => cast(float) i;
4224 
4225     Nullable!int sample;
4226 
4227     // apply(null) results in a null `Nullable` of the function's return type.
4228     Nullable!float f = sample.apply!toFloat;
4229     assert(sample.isNull && f.isNull);
4230 
4231     sample = 3;
4232 
4233     // apply(non-null) calls the function and wraps the result in a `Nullable`.
4234     f = sample.apply!toFloat;
4235     assert(!sample.isNull && !f.isNull);
4236     assert(f.get == 3.0f);
4237 }
4238 
4239 ///
4240 nothrow pure @nogc @safe unittest
4241 {
4242     alias greaterThree = i => (i > 3) ? i.nullable : Nullable!(typeof(i)).init;
4243 
4244     Nullable!int sample;
4245 
4246     // when the function already returns a `Nullable`, that `Nullable` is not wrapped.
4247     auto result = sample.apply!greaterThree;
4248     assert(sample.isNull && result.isNull);
4249 
4250     // The function may decide to return a null `Nullable`.
4251     sample = 3;
4252     result = sample.apply!greaterThree;
4253     assert(!sample.isNull && result.isNull);
4254 
4255     // Or it may return a value already wrapped in a `Nullable`.
4256     sample = 4;
4257     result = sample.apply!greaterThree;
4258     assert(!sample.isNull && !result.isNull);
4259     assert(result.get == 4);
4260 }
4261 
4262 // test that Nullable.get(default) can merge types
4263 @safe @nogc nothrow pure
4264 unittest
4265 {
4266     Nullable!ubyte sample = Nullable!ubyte();
4267 
4268     // Test that get(U) returns the common type of the Nullable type and the parameter type.
4269     assert(sample.get(1000) == 1000);
4270 }
4271 
4272 // Workaround for https://issues.dlang.org/show_bug.cgi?id=20670
4273 @safe @nogc nothrow pure
4274 unittest
4275 {
4276     immutable struct S { }
4277 
4278     S[] array = Nullable!(S[])().get(S[].init);
4279 }
4280 
4281 // regression test for https://issues.dlang.org/show_bug.cgi?id=21199
4282 @safe @nogc nothrow pure
4283 unittest
4284 {
4285     struct S { int i; }
4286     assert(S(5).nullable.apply!"a.i" == 5);
4287 }
4288 
4289 // regression test for https://issues.dlang.org/show_bug.cgi?id=22176
4290 @safe @nogc nothrow pure
4291 unittest
4292 {
4293     struct S
4294     {
4295         int i;
4296         invariant(i != 0);
4297 
4298         // Nullable shouldn't cause S to generate an
4299         // opAssign that would check the invariant.
4300         Nullable!int j;
4301     }
4302     S s;
4303     s = S(5);
4304 }
4305 
4306 /**
4307 Just like `Nullable!T`, except that the object refers to a value
4308 sitting elsewhere in memory. This makes assignments overwrite the
4309 initially assigned value. Internally `NullableRef!T` only stores a
4310 pointer to `T` (i.e., $(D Nullable!T.sizeof == (T*).sizeof)).
4311  */
4312 struct NullableRef(T)
4313 {
4314     private T* _value;
4315 
4316 /**
4317 Constructor binding `this` to `value`.
4318 
4319 Params:
4320     value = The value to bind to.
4321  */
4322     this(T* value) @safe pure nothrow
4323     {
4324         _value = value;
4325     }
4326 
4327     template toString()
4328     {
4329         import std.format.spec : FormatSpec;
4330         import std.format.write : formatValue;
4331         // Needs to be a template because of https://issues.dlang.org/show_bug.cgi?id=13737.
4332         void toString()(scope void delegate(const(char)[]) sink, scope const ref FormatSpec!char fmt)
4333         {
4334             if (isNull)
4335             {
4336                 sink.formatValue("Nullable.null", fmt);
4337             }
4338             else
4339             {
4340                 sink.formatValue(*_value, fmt);
4341             }
4342         }
4343 
4344         void toString()(scope void delegate(const(char)[]) sink, scope const ref FormatSpec!char fmt) const
4345         {
4346             if (isNull)
4347             {
4348                 sink.formatValue("Nullable.null", fmt);
4349             }
4350             else
4351             {
4352                 sink.formatValue(*_value, fmt);
4353             }
4354         }
4355     }
4356 
4357 @system unittest
4358 {
4359     import std.conv : to;
4360 
4361     const NullableRef!(ulong) x = new ulong(1);
4362     assert(x.to!string == "1");
4363 }
4364 
4365 /**
4366 Binds the internal state to `value`.
4367 
4368 Params:
4369     value = A pointer to a value of type `T` to bind this `NullableRef` to.
4370  */
4371     void bind(T* value) @safe pure nothrow
4372     {
4373         _value = value;
4374     }
4375 
4376     ///
4377     @safe unittest
4378     {
4379         NullableRef!int nr = new int(42);
4380         assert(nr == 42);
4381 
4382         int* n = new int(1);
4383         nr.bind(n);
4384         assert(nr == 1);
4385     }
4386 
4387 /**
4388 Returns `true` if and only if `this` is in the null state.
4389 
4390 Returns:
4391     true if `this` is in the null state, otherwise false.
4392  */
4393     @property bool isNull() const @safe pure nothrow
4394     {
4395         return _value is null;
4396     }
4397 
4398     ///
4399     @safe unittest
4400     {
4401         NullableRef!int nr;
4402         assert(nr.isNull);
4403 
4404         int* n = new int(42);
4405         nr.bind(n);
4406         assert(!nr.isNull && nr == 42);
4407     }
4408 
4409 /**
4410 Forces `this` to the null state.
4411  */
4412     void nullify() @safe pure nothrow
4413     {
4414         _value = null;
4415     }
4416 
4417     ///
4418     @safe unittest
4419     {
4420         NullableRef!int nr = new int(42);
4421         assert(!nr.isNull);
4422 
4423         nr.nullify();
4424         assert(nr.isNull);
4425     }
4426 
4427 /**
4428 Assigns `value` to the internally-held state.
4429 
4430 Params:
4431     value = A value of type `T` to assign to this `NullableRef`.
4432             If the internal state of this `NullableRef` has not
4433             been initialized, an error will be thrown in
4434             non-release mode.
4435  */
4436     void opAssign()(T value)
4437         if (isAssignable!T) //@@@9416@@@
4438     {
4439         enum message = "Called `opAssign' on null NullableRef!" ~ T.stringof ~ ".";
4440         assert(!isNull, message);
4441         *_value = value;
4442     }
4443 
4444     ///
4445     @system unittest
4446     {
4447         import std.exception : assertThrown, assertNotThrown;
4448 
4449         NullableRef!int nr;
4450         assert(nr.isNull);
4451         assertThrown!Throwable(nr = 42);
4452 
4453         nr.bind(new int(0));
4454         assert(!nr.isNull);
4455         assertNotThrown!Throwable(nr = 42);
4456         assert(nr == 42);
4457     }
4458 
4459 /**
4460 Gets the value. `this` must not be in the null state.
4461 This function is also called for the implicit conversion to `T`.
4462  */
4463     @property ref inout(T) get() inout @safe pure nothrow
4464     {
4465         enum message = "Called `get' on null NullableRef!" ~ T.stringof ~ ".";
4466         assert(!isNull, message);
4467         return *_value;
4468     }
4469 
4470     ///
4471     @system unittest
4472     {
4473         import std.exception : assertThrown, assertNotThrown;
4474 
4475         NullableRef!int nr;
4476         //`get` is implicitly called. Will throw
4477         //an error in non-release mode
4478         assertThrown!Throwable(nr == 0);
4479 
4480         nr.bind(new int(0));
4481         assertNotThrown!Throwable(nr == 0);
4482     }
4483 
4484 /**
4485 Implicitly converts to `T`.
4486 `this` must not be in the null state.
4487  */
4488     alias get this;
4489 }
4490 
4491 /// ditto
4492 auto nullableRef(T)(T* t)
4493 {
4494     return NullableRef!T(t);
4495 }
4496 
4497 ///
4498 @system unittest
4499 {
4500     import std.exception : assertThrown;
4501 
4502     int x = 5, y = 7;
4503     auto a = nullableRef(&x);
4504     assert(!a.isNull);
4505     assert(a == 5);
4506     assert(x == 5);
4507     a = 42;
4508     assert(x == 42);
4509     assert(!a.isNull);
4510     assert(a == 42);
4511     a.nullify();
4512     assert(x == 42);
4513     assert(a.isNull);
4514     assertThrown!Throwable(a.get);
4515     assertThrown!Throwable(a = 71);
4516     a.bind(&y);
4517     assert(a == 7);
4518     y = 135;
4519     assert(a == 135);
4520 }
4521 @system unittest
4522 {
4523     static int f(scope const NullableRef!int x) {
4524         return x.isNull ? 42 : x.get;
4525     }
4526     int x = 5;
4527     auto a = nullableRef(&x);
4528     assert(f(a) == 5);
4529     a.nullify();
4530     assert(f(a) == 42);
4531 }
4532 @safe unittest
4533 {
4534     // Ensure NullableRef can be used in pure/nothrow/@safe environment.
4535     function() @safe pure nothrow
4536     {
4537         auto storage = new int;
4538         *storage = 19902;
4539         NullableRef!int n;
4540         assert(n.isNull);
4541         n.bind(storage);
4542         assert(!n.isNull);
4543         assert(n == 19902);
4544         n = 2294;
4545         assert(n == 2294);
4546         assert(*storage == 2294);
4547         n.nullify();
4548         assert(n.isNull);
4549     }();
4550 }
4551 @system unittest
4552 {
4553     // Ensure NullableRef can be used when the value is not pure/nothrow/@safe
4554     static struct S
4555     {
4556         int x;
4557         this(this) @system {}
4558         bool opEquals(const S s) const @system { return s.x == x; }
4559     }
4560 
4561     auto storage = S(5);
4562 
4563     NullableRef!S s;
4564     assert(s.isNull);
4565     s.bind(&storage);
4566     assert(!s.isNull);
4567     assert(s.x == 5);
4568     s.nullify();
4569     assert(s.isNull);
4570 }
4571 @safe unittest
4572 {
4573     //Check nullable is nicelly embedable in a struct
4574     static struct S1
4575     {
4576         NullableRef!int ni;
4577     }
4578     static struct S2 //inspired from 9404
4579     {
4580         NullableRef!int ni;
4581         this(S2 other)
4582         {
4583             ni = other.ni;
4584         }
4585         void opAssign(S2 other)
4586         {
4587             ni = other.ni;
4588         }
4589     }
4590     static foreach (S; AliasSeq!(S1, S2))
4591     {{
4592         S a;
4593         S b = a;
4594         S c;
4595         c = a;
4596     }}
4597 }
4598 
4599 // https://issues.dlang.org/show_bug.cgi?id=10915
4600 @system unittest
4601 {
4602     import std.conv : to;
4603 
4604     NullableRef!int nri;
4605     assert(nri.to!string() == "Nullable.null");
4606 
4607     struct Test
4608     {
4609         string s;
4610     }
4611     NullableRef!Test nt = new Test("test");
4612     assert(nt.to!string() == `Test("test")`);
4613 
4614     class TestToString
4615     {
4616         double d;
4617 
4618         this(double d)
4619         {
4620             this.d = d;
4621         }
4622 
4623         override string toString()
4624         {
4625             return d.to!string();
4626         }
4627     }
4628     TestToString tts = new TestToString(2.5);
4629     NullableRef!TestToString ntts = &tts;
4630     assert(ntts.to!string() == "2.5");
4631 }
4632 
4633 
4634 /**
4635 `BlackHole!Base` is a subclass of `Base` which automatically implements
4636 all abstract member functions in `Base` as do-nothing functions.  Each
4637 auto-implemented function just returns the default value of the return type
4638 without doing anything.
4639 
4640 The name came from
4641 $(HTTP search.cpan.org/~sburke/Class-_BlackHole-0.04/lib/Class/_BlackHole.pm, Class::_BlackHole)
4642 Perl module by Sean M. Burke.
4643 
4644 Params:
4645     Base = A non-final class for `BlackHole` to inherit from.
4646 
4647 See_Also:
4648   $(LREF AutoImplement), $(LREF generateEmptyFunction)
4649  */
4650 alias BlackHole(Base) = AutoImplement!(Base, generateEmptyFunction, isAbstractFunction);
4651 
4652 ///
4653 @system unittest
4654 {
4655     import std.math.traits : isNaN;
4656 
4657     static abstract class C
4658     {
4659         int m_value;
4660         this(int v) { m_value = v; }
4661         int value() @property { return m_value; }
4662 
4663         abstract real realValue() @property;
4664         abstract void doSomething();
4665     }
4666 
4667     auto c = new BlackHole!C(42);
4668     assert(c.value == 42);
4669 
4670     // Returns real.init which is NaN
4671     assert(c.realValue.isNaN);
4672     // Abstract functions are implemented as do-nothing
4673     c.doSomething();
4674 }
4675 
4676 @system unittest
4677 {
4678     import std.math.traits : isNaN;
4679 
4680     // return default
4681     {
4682         interface I_1 { real test(); }
4683         auto o = new BlackHole!I_1;
4684         assert(o.test().isNaN()); // NaN
4685     }
4686     // doc example
4687     {
4688         static class C
4689         {
4690             int m_value;
4691             this(int v) { m_value = v; }
4692             int value() @property { return m_value; }
4693 
4694             abstract real realValue() @property;
4695             abstract void doSomething();
4696         }
4697 
4698         auto c = new BlackHole!C(42);
4699         assert(c.value == 42);
4700 
4701         assert(c.realValue.isNaN); // NaN
4702         c.doSomething();
4703     }
4704 
4705     // https://issues.dlang.org/show_bug.cgi?id=12058
4706     interface Foo
4707     {
4708         inout(Object) foo() inout;
4709     }
4710     BlackHole!Foo o;
4711 }
4712 
4713 nothrow pure @nogc @safe unittest
4714 {
4715     static interface I
4716     {
4717         I foo() nothrow pure @nogc @safe return scope;
4718     }
4719 
4720     scope cb = new BlackHole!I();
4721     cb.foo();
4722 }
4723 
4724 
4725 /**
4726 `WhiteHole!Base` is a subclass of `Base` which automatically implements
4727 all abstract member functions as functions that always fail. These functions
4728 simply throw an `Error` and never return. `Whitehole` is useful for
4729 trapping the use of class member functions that haven't been implemented.
4730 
4731 The name came from
4732 $(HTTP search.cpan.org/~mschwern/Class-_WhiteHole-0.04/lib/Class/_WhiteHole.pm, Class::_WhiteHole)
4733 Perl module by Michael G Schwern.
4734 
4735 Params:
4736     Base = A non-final class for `WhiteHole` to inherit from.
4737 
4738 See_Also:
4739   $(LREF AutoImplement), $(LREF generateAssertTrap)
4740  */
4741 alias WhiteHole(Base) = AutoImplement!(Base, generateAssertTrap, isAbstractFunction);
4742 
4743 ///
4744 @system unittest
4745 {
4746     import std.exception : assertThrown;
4747 
4748     static class C
4749     {
4750         abstract void notYetImplemented();
4751     }
4752 
4753     auto c = new WhiteHole!C;
4754     assertThrown!NotImplementedError(c.notYetImplemented()); // throws an Error
4755 }
4756 
4757 // https://issues.dlang.org/show_bug.cgi?id=20232
4758 nothrow pure @safe unittest
4759 {
4760     static interface I
4761     {
4762         I foo() nothrow pure @safe return scope;
4763     }
4764 
4765     if (0) // Just checking attribute interference
4766     {
4767         scope cw = new WhiteHole!I();
4768         cw.foo();
4769     }
4770 }
4771 
4772 // / ditto
4773 class NotImplementedError : Error
4774 {
4775     this(string method) nothrow pure @safe
4776     {
4777         super(method ~ " is not implemented");
4778     }
4779 }
4780 
4781 @system unittest
4782 {
4783     import std.exception : assertThrown;
4784     // nothrow
4785     {
4786         interface I_1
4787         {
4788             void foo();
4789             void bar() nothrow;
4790         }
4791         auto o = new WhiteHole!I_1;
4792         assertThrown!NotImplementedError(o.foo());
4793         assertThrown!NotImplementedError(o.bar());
4794     }
4795     // doc example
4796     {
4797         static class C
4798         {
4799             abstract void notYetImplemented();
4800         }
4801 
4802         auto c = new WhiteHole!C;
4803         try
4804         {
4805             c.notYetImplemented();
4806             assert(0);
4807         }
4808         catch (Error e) {}
4809     }
4810 }
4811 
4812 
4813 /**
4814 `AutoImplement` automatically implements (by default) all abstract member
4815 functions in the class or interface `Base` in specified way.
4816 
4817 The second version of `AutoImplement` automatically implements
4818 `Interface`, while deriving from `BaseClass`.
4819 
4820 Params:
4821   how  = template which specifies _how functions will be implemented/overridden.
4822 
4823          Two arguments are passed to `how`: the type `Base` and an alias
4824          to an implemented function.  Then `how` must return an implemented
4825          function body as a string.
4826 
4827          The generated function body can use these keywords:
4828          $(UL
4829             $(LI `a0`, `a1`, &hellip;: arguments passed to the function;)
4830             $(LI `args`: a tuple of the arguments;)
4831             $(LI `self`: an alias to the function itself;)
4832             $(LI `parent`: an alias to the overridden function (if any).)
4833          )
4834 
4835         You may want to use templated property functions (instead of Implicit
4836         Template Properties) to generate complex functions:
4837 --------------------
4838 // Prints log messages for each call to overridden functions.
4839 string generateLogger(C, alias fun)() @property
4840 {
4841     import std.traits;
4842     enum qname = C.stringof ~ "." ~ __traits(identifier, fun);
4843     string stmt;
4844 
4845     stmt ~= q{ struct Importer { import std.stdio; } };
4846     stmt ~= `Importer.writeln("Log: ` ~ qname ~ `(", args, ")");`;
4847     static if (!__traits(isAbstractFunction, fun))
4848     {
4849         static if (is(ReturnType!fun == void))
4850             stmt ~= q{ parent(args); };
4851         else
4852             stmt ~= q{
4853                 auto r = parent(args);
4854                 Importer.writeln("--> ", r);
4855                 return r;
4856             };
4857     }
4858     return stmt;
4859 }
4860 --------------------
4861 
4862   what = template which determines _what functions should be
4863          implemented/overridden.
4864 
4865          An argument is passed to `what`: an alias to a non-final member
4866          function in `Base`.  Then `what` must return a boolean value.
4867          Return `true` to indicate that the passed function should be
4868          implemented/overridden.
4869 
4870 --------------------
4871 // Sees if fun returns something.
4872 enum bool hasValue(alias fun) = !is(ReturnType!(fun) == void);
4873 --------------------
4874 
4875 
4876 Note:
4877 
4878 Generated code is inserted in the scope of `std.typecons` module.  Thus,
4879 any useful functions outside `std.typecons` cannot be used in the generated
4880 code.  To workaround this problem, you may `import` necessary things in a
4881 local struct, as done in the `generateLogger()` template in the above
4882 example.
4883 
4884 
4885 BUGS:
4886 
4887 $(UL
4888  $(LI Variadic arguments to constructors are not forwarded to super.)
4889  $(LI Deep interface inheritance causes compile error with messages like
4890       "Error: function std.typecons._AutoImplement!(Foo)._AutoImplement.bar
4891       does not override any function".  [$(BUGZILLA 2525)] )
4892  $(LI The `parent` keyword is actually a delegate to the super class'
4893       corresponding member function.  [$(BUGZILLA 2540)] )
4894  $(LI Using alias template parameter in `how` and/or `what` may cause
4895      strange compile error.  Use template tuple parameter instead to workaround
4896      this problem.  [$(BUGZILLA 4217)] )
4897 )
4898  */
4899 class AutoImplement(Base, alias how, alias what = isAbstractFunction) : Base
4900 if (!is(how == class))
4901 {
4902     private alias autoImplement_helper_ =
4903         AutoImplement_Helper!("autoImplement_helper_", "Base", Base, typeof(this), how, what);
4904     mixin(autoImplement_helper_.code);
4905 }
4906 
4907 /// ditto
4908 class AutoImplement(
4909     Interface, BaseClass, alias how,
4910     alias what = isAbstractFunction) : BaseClass, Interface
4911 if (is(Interface == interface) && is(BaseClass == class))
4912 {
4913     private alias autoImplement_helper_ = AutoImplement_Helper!(
4914             "autoImplement_helper_", "Interface", Interface, typeof(this), how, what);
4915     mixin(autoImplement_helper_.code);
4916 }
4917 
4918 ///
4919 @system unittest
4920 {
4921     interface PackageSupplier
4922     {
4923         int foo();
4924         int bar();
4925     }
4926 
4927     static abstract class AbstractFallbackPackageSupplier : PackageSupplier
4928     {
4929         protected PackageSupplier default_, fallback;
4930 
4931         this(PackageSupplier default_, PackageSupplier fallback)
4932         {
4933             this.default_ = default_;
4934             this.fallback = fallback;
4935         }
4936 
4937         abstract int foo();
4938         abstract int bar();
4939     }
4940 
4941     template fallback(T, alias func)
4942     {
4943         import std.format : format;
4944         // for all implemented methods:
4945         // - try default first
4946         // - only on a failure run & return fallback
4947         enum fallback = q{
4948             try
4949             {
4950                 return default_.%1$s(args);
4951             }
4952             catch (Exception)
4953             {
4954                 return fallback.%1$s(args);
4955             }
4956         }.format(__traits(identifier, func));
4957     }
4958 
4959     // combines two classes and use the second one as fallback
4960     alias FallbackPackageSupplier = AutoImplement!(AbstractFallbackPackageSupplier, fallback);
4961 
4962     class FailingPackageSupplier : PackageSupplier
4963     {
4964         int foo(){ throw new Exception("failure"); }
4965         int bar(){ return 2;}
4966     }
4967 
4968     class BackupPackageSupplier : PackageSupplier
4969     {
4970         int foo(){ return -1; }
4971         int bar(){ return -1;}
4972     }
4973 
4974     auto registry = new FallbackPackageSupplier(new FailingPackageSupplier(), new BackupPackageSupplier());
4975 
4976     assert(registry.foo() == -1);
4977     assert(registry.bar() == 2);
4978 }
4979 
4980 /*
4981  * Code-generating stuffs are encupsulated in this helper template so that
4982  * namespace pollution, which can cause name confliction with Base's public
4983  * members, should be minimized.
4984  */
4985 private template AutoImplement_Helper(string myName, string baseName,
4986         Base, Self, alias generateMethodBody, alias cherrypickMethod)
4987 {
4988 private static:
4989     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4990     // Internal stuffs
4991     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4992 
4993     // Returns function overload sets in the class C, filtered with pred.
4994     template enumerateOverloads(C, alias pred)
4995     {
4996         template Impl(names...)
4997         {
4998             import std.meta : Filter;
4999             static if (names.length > 0)
5000             {
5001                 alias methods = Filter!(pred, MemberFunctionsTuple!(C, names[0]));
5002                 alias next = Impl!(names[1 .. $]);
5003 
5004                 static if (methods.length > 0)
5005                     alias Impl = AliasSeq!(OverloadSet!(names[0], methods), next);
5006                 else
5007                     alias Impl = next;
5008             }
5009             else
5010                 alias Impl = AliasSeq!();
5011         }
5012 
5013         alias enumerateOverloads = Impl!(__traits(allMembers, C));
5014     }
5015 
5016     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5017     // Target functions
5018     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5019 
5020     // Add a non-final check to the cherrypickMethod.
5021     enum bool canonicalPicker(fun.../+[https://issues.dlang.org/show_bug.cgi?id=4217]+/) =
5022         !__traits(isFinalFunction, fun[0]) && cherrypickMethod!(fun);
5023 
5024     /*
5025      * A tuple of overload sets, each item of which consists of functions to be
5026      * implemented by the generated code.
5027      */
5028     alias targetOverloadSets = enumerateOverloads!(Base, canonicalPicker);
5029 
5030     /*
5031      * Super class of this AutoImplement instance
5032      */
5033     alias Super = BaseTypeTuple!(Self)[0];
5034     static assert(is(Super == class));
5035     static assert(is(Base == interface) || is(Super == Base));
5036 
5037     /*
5038      * A tuple of the super class' constructors.  Used for forwarding
5039      * constructor calls.
5040      */
5041     static if (__traits(hasMember, Super, "__ctor"))
5042         alias ctorOverloadSet = OverloadSet!("__ctor", __traits(getOverloads, Super, "__ctor"));
5043     else
5044         alias ctorOverloadSet = OverloadSet!("__ctor"); // empty
5045 
5046 
5047     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5048     // Type information
5049     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5050 
5051     /*
5052      * The generated code will be mixed into AutoImplement, which will be
5053      * instantiated in this module's scope.  Thus, any user-defined types are
5054      * out of scope and cannot be used directly (i.e. by their names).
5055      *
5056      * We will use FuncInfo instances for accessing return types and parameter
5057      * types of the implemented functions.  The instances will be populated to
5058      * the AutoImplement's scope in a certain way; see the populate() below.
5059      */
5060 
5061     // Returns the preferred identifier for the FuncInfo instance for the i-th
5062     // overloaded function with the name.
5063     template INTERNAL_FUNCINFO_ID(string name, size_t i)
5064     {
5065         import std.format : format;
5066 
5067         enum string INTERNAL_FUNCINFO_ID = format("F_%s_%s", name, i);
5068     }
5069 
5070     /*
5071      * Insert FuncInfo instances about all the target functions here.  This
5072      * enables the generated code to access type information via, for example,
5073      * "autoImplement_helper_.F_foo_1".
5074      */
5075     template populate(overloads...)
5076     {
5077         static if (overloads.length > 0)
5078         {
5079             mixin populate!(overloads[0].name, overloads[0].contents);
5080             mixin populate!(overloads[1 .. $]);
5081         }
5082     }
5083     template populate(string name, methods...)
5084     {
5085         static if (methods.length > 0)
5086         {
5087             mixin populate!(name, methods[0 .. $ - 1]);
5088             //
5089             alias target = methods[$ - 1];
5090             enum ith = methods.length - 1;
5091             mixin("alias " ~ INTERNAL_FUNCINFO_ID!(name, ith) ~ " = FuncInfo!target;");
5092         }
5093     }
5094 
5095     public mixin populate!(targetOverloadSets);
5096     public mixin populate!(  ctorOverloadSet );
5097 
5098 
5099     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5100     // Code-generating policies
5101     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5102 
5103     /* Common policy configurations for generating constructors and methods. */
5104     template CommonGeneratingPolicy()
5105     {
5106         // base class identifier which generated code should use
5107         enum string BASE_CLASS_ID = baseName;
5108 
5109         // FuncInfo instance identifier which generated code should use
5110         template FUNCINFO_ID(string name, size_t i)
5111         {
5112             enum string FUNCINFO_ID =
5113                 myName ~ "." ~ INTERNAL_FUNCINFO_ID!(name, i);
5114         }
5115     }
5116 
5117     /* Policy configurations for generating constructors. */
5118     template ConstructorGeneratingPolicy()
5119     {
5120         mixin CommonGeneratingPolicy;
5121 
5122         /* Generates constructor body.  Just forward to the base class' one. */
5123         string generateFunctionBody(ctor.../+[https://issues.dlang.org/show_bug.cgi?id=4217]+/)() @property
5124         {
5125             enum varstyle = variadicFunctionStyle!(typeof(&ctor[0]));
5126 
5127             static if (varstyle & (Variadic.c | Variadic.d))
5128             {
5129                 // the argptr-forwarding problem
5130                 //pragma(msg, "Warning: AutoImplement!(", Base, ") ",
5131                 //        "ignored variadic arguments to the constructor ",
5132                 //        FunctionTypeOf!(typeof(&ctor[0])) );
5133             }
5134             return "super(args);";
5135         }
5136     }
5137 
5138     /* Policy configurations for genearting target methods. */
5139     template MethodGeneratingPolicy()
5140     {
5141         mixin CommonGeneratingPolicy;
5142 
5143         /* Geneartes method body. */
5144         string generateFunctionBody(func.../+[https://issues.dlang.org/show_bug.cgi?id=4217]+/)() @property
5145         {
5146             return generateMethodBody!(Base, func); // given
5147         }
5148     }
5149 
5150 
5151     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5152     // Generated code
5153     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5154 
5155     alias ConstructorGenerator = MemberFunctionGenerator!(ConstructorGeneratingPolicy!());
5156     alias MethodGenerator      = MemberFunctionGenerator!(MethodGeneratingPolicy!());
5157 
5158     public enum string code =
5159         ConstructorGenerator.generateCode!(  ctorOverloadSet ) ~ "\n" ~
5160              MethodGenerator.generateCode!(targetOverloadSets);
5161 
5162     debug (SHOW_GENERATED_CODE)
5163     {
5164         pragma(msg, "-------------------- < ", Base, " >");
5165         pragma(msg, code);
5166         pragma(msg, "--------------------");
5167     }
5168 }
5169 
5170 //debug = SHOW_GENERATED_CODE;
5171 @system unittest
5172 {
5173     import core.vararg;
5174     // no function to implement
5175     {
5176         interface I_1 {}
5177         auto o = new BlackHole!I_1;
5178     }
5179     // parameters
5180     {
5181         interface I_3 { void test(int, in int, out int, ref int, lazy int); }
5182         auto o = new BlackHole!I_3;
5183     }
5184     // use of user-defined type
5185     {
5186         struct S {}
5187         interface I_4 { S test(); }
5188         auto o = new BlackHole!I_4;
5189     }
5190     // overloads
5191     {
5192         interface I_5
5193         {
5194             void test(string);
5195             real test(real);
5196             int  test();
5197         }
5198         auto o = new BlackHole!I_5;
5199     }
5200     // constructor forwarding
5201     {
5202         static class C_6
5203         {
5204             this(int n) { assert(n == 42); }
5205             this(string s) { assert(s == "Deeee"); }
5206             this(...) {}
5207         }
5208         auto o1 = new BlackHole!C_6(42);
5209         auto o2 = new BlackHole!C_6("Deeee");
5210         auto o3 = new BlackHole!C_6(1, 2, 3, 4);
5211     }
5212     // attributes
5213     {
5214         interface I_7
5215         {
5216             ref int test_ref();
5217             int test_pure() pure;
5218             int test_nothrow() nothrow;
5219             int test_property() @property;
5220             int test_safe() @safe;
5221             int test_trusted() @trusted;
5222             int test_system() @system;
5223             int test_pure_nothrow() pure nothrow;
5224         }
5225         auto o = new BlackHole!I_7;
5226     }
5227     // storage classes
5228     {
5229         interface I_8
5230         {
5231             void test_const() const;
5232             void test_immutable() immutable;
5233             void test_shared() shared;
5234             void test_shared_const() shared const;
5235         }
5236         auto o = new BlackHole!I_8;
5237     }
5238     // use baseclass
5239     {
5240         static class C_9
5241         {
5242             private string foo_;
5243 
5244             this(string s) {
5245                 foo_ = s;
5246             }
5247 
5248             protected string boilerplate() @property
5249             {
5250                 return "Boilerplate stuff.";
5251             }
5252 
5253             public string foo() @property
5254             {
5255                 return foo_;
5256             }
5257         }
5258 
5259         interface I_10
5260         {
5261             string testMethod(size_t);
5262         }
5263 
5264         static string generateTestMethod(C, alias fun)() @property
5265         {
5266             return "return this.boilerplate[0 .. a0];";
5267         }
5268 
5269         auto o = new AutoImplement!(I_10, C_9, generateTestMethod)("Testing");
5270         assert(o.testMethod(11) == "Boilerplate");
5271         assert(o.foo == "Testing");
5272     }
5273     /+ // deep inheritance
5274     {
5275     // https://issues.dlang.org/show_bug.cgi?id=2525
5276     // https://issues.dlang.org/show_bug.cgi?id=3525
5277     // NOTE: [r494] func.c(504-571) FuncDeclaration::semantic()
5278         interface I { void foo(); }
5279         interface J : I {}
5280         interface K : J {}
5281         static abstract class C_9 : K {}
5282         auto o = new BlackHole!C_9;
5283     }+/
5284     // test `parent` alias
5285     {
5286         interface I_11
5287         {
5288             void simple(int) @safe;
5289             int anotherSimple(string);
5290             int overloaded(int);
5291             /+ XXX [BUG 19715]
5292             void overloaded(string) @safe;
5293             +/
5294         }
5295 
5296         static class C_11
5297         {
5298             import std.traits : Parameters, ReturnType;
5299             import std.meta : Alias;
5300 
5301             protected ReturnType!fn _impl(alias fn)(Parameters!fn)
5302             if (is(Alias!(__traits(parent, fn)) == interface))
5303             {
5304                 static if (!is(typeof(return) == void))
5305                     return typeof(return).init;
5306             }
5307         }
5308 
5309         template tpl(I, alias fn)
5310         if (is(I == interface) && __traits(isSame, __traits(parent, fn), I))
5311         {
5312             enum string tpl = q{
5313                 enum bool haveReturn = !is(typeof(return) == void);
5314 
5315                 static if (is(typeof(return) == void))
5316                     _impl!parent(args);
5317                 else
5318                     return _impl!parent(args);
5319             };
5320         }
5321 
5322         auto o = new AutoImplement!(I_11, C_11, tpl);
5323     }
5324 }
5325 
5326 // https://issues.dlang.org/show_bug.cgi?id=17177
5327 // AutoImplement fails on function overload sets with
5328 // "cannot infer type from overloaded function symbol"
5329 @system unittest
5330 {
5331     static class Issue17177
5332     {
5333         private string n_;
5334 
5335         public {
5336             Issue17177 overloaded(string n)
5337             {
5338                 this.n_ = n;
5339 
5340                 return this;
5341             }
5342 
5343             string overloaded()
5344             {
5345                 return this.n_;
5346             }
5347         }
5348     }
5349 
5350     static string how(C, alias fun)()
5351     {
5352         static if (!is(ReturnType!fun == void))
5353         {
5354             return q{
5355                 return parent(args);
5356             };
5357         }
5358         else
5359         {
5360             return q{
5361                 parent(args);
5362             };
5363         }
5364     }
5365 
5366     import std.meta : templateNot;
5367     alias Implementation = AutoImplement!(Issue17177, how, templateNot!isFinalFunction);
5368 }
5369 
5370 version (StdUnittest)
5371 {
5372     // https://issues.dlang.org/show_bug.cgi?id=10647
5373     // Add prefix "issue10647_" as a workaround for
5374     // https://issues.dlang.org/show_bug.cgi?id=1238
5375     private string issue10647_generateDoNothing(C, alias fun)() @property
5376     {
5377         string stmt;
5378 
5379         static if (is(ReturnType!fun == void))
5380             stmt ~= "";
5381         else
5382         {
5383             string returnType = ReturnType!fun.stringof;
5384             stmt ~= "return "~returnType~".init;";
5385         }
5386         return stmt;
5387     }
5388 
5389     private template issue10647_isAlwaysTrue(alias fun)
5390     {
5391         enum issue10647_isAlwaysTrue = true;
5392     }
5393 
5394     // Do nothing template
5395     private template issue10647_DoNothing(Base)
5396     {
5397         alias issue10647_DoNothing = AutoImplement!(Base, issue10647_generateDoNothing, issue10647_isAlwaysTrue);
5398     }
5399 
5400     // A class to be overridden
5401     private class issue10647_Foo{
5402         void bar(int a) { }
5403     }
5404 }
5405 
5406 @system unittest
5407 {
5408     auto foo = new issue10647_DoNothing!issue10647_Foo();
5409     foo.bar(13);
5410 }
5411 
5412 /*
5413 Used by MemberFunctionGenerator.
5414  */
5415 package template OverloadSet(string nam, T...)
5416 {
5417     enum string name = nam;
5418     alias contents = T;
5419 }
5420 
5421 /*
5422 Used by MemberFunctionGenerator.
5423  */
5424 package template FuncInfo(alias func)
5425 if (is(typeof(&func)))
5426 {
5427     alias RT = ReturnType!(typeof(&func));
5428     alias PT = Parameters!(typeof(&func));
5429 }
5430 package template FuncInfo(Func)
5431 {
5432     alias RT = ReturnType!Func;
5433     alias PT = Parameters!Func;
5434 }
5435 
5436 /*
5437 General-purpose member function generator.
5438 --------------------
5439 template GeneratingPolicy()
5440 {
5441     // [optional] the name of the class where functions are derived
5442     enum string BASE_CLASS_ID;
5443 
5444     // [optional] define this if you have only function types
5445     enum bool WITHOUT_SYMBOL;
5446 
5447     // [optional] Returns preferred identifier for i-th parameter.
5448     template PARAMETER_VARIABLE_ID(size_t i);
5449 
5450     // Returns the identifier of the FuncInfo instance for the i-th overload
5451     // of the specified name.  The identifier must be accessible in the scope
5452     // where generated code is mixed.
5453     template FUNCINFO_ID(string name, size_t i);
5454 
5455     // Returns implemented function body as a string.  When WITHOUT_SYMBOL is
5456     // defined, the latter is used.
5457     template generateFunctionBody(alias func);
5458     template generateFunctionBody(string name, FuncType);
5459 }
5460 --------------------
5461  */
5462 package template MemberFunctionGenerator(alias Policy)
5463 {
5464 private static:
5465     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5466     // Internal stuffs
5467     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5468     import std.format;
5469     alias format = std.format.format;
5470 
5471     enum CONSTRUCTOR_NAME = "__ctor";
5472 
5473     // true if functions are derived from a base class
5474     enum WITH_BASE_CLASS = __traits(hasMember, Policy, "BASE_CLASS_ID");
5475 
5476     // true if functions are specified as types, not symbols
5477     enum WITHOUT_SYMBOL = __traits(hasMember, Policy, "WITHOUT_SYMBOL");
5478 
5479     // preferred identifier for i-th parameter variable
5480     static if (__traits(hasMember, Policy, "PARAMETER_VARIABLE_ID"))
5481     {
5482         alias PARAMETER_VARIABLE_ID = Policy.PARAMETER_VARIABLE_ID;
5483     }
5484     else
5485     {
5486         enum string PARAMETER_VARIABLE_ID(size_t i) = format("a%s", i);
5487             // default: a0, a1, ...
5488     }
5489 
5490     // Returns a tuple consisting of 0,1,2,...,n-1.  For static foreach.
5491     template CountUp(size_t n)
5492     {
5493         static if (n > 0)
5494             alias CountUp = AliasSeq!(CountUp!(n - 1), n - 1);
5495         else
5496             alias CountUp = AliasSeq!();
5497     }
5498 
5499 
5500     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5501     // Code generator
5502     //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5503 
5504     /*
5505      * Runs through all the target overload sets and generates D code which
5506      * implements all the functions in the overload sets.
5507      */
5508     public string generateCode(overloads...)() @property
5509     {
5510         string code = "";
5511 
5512         // run through all the overload sets
5513         foreach (i_; CountUp!(0 + overloads.length)) // workaround
5514         {
5515             enum i = 0 + i_; // workaround
5516             alias oset = overloads[i];
5517 
5518             code ~= generateCodeForOverloadSet!(oset);
5519 
5520             static if (WITH_BASE_CLASS && oset.name != CONSTRUCTOR_NAME)
5521             {
5522                 // The generated function declarations may hide existing ones
5523                 // in the base class (cf. HiddenFuncError), so we put an alias
5524                 // declaration here to reveal possible hidden functions.
5525                 code ~= format("alias %s = %s.%s;\n",
5526                             oset.name,
5527                             // super: https://issues.dlang.org/show_bug.cgi?id=2540
5528                             Policy.BASE_CLASS_ID,
5529                             oset.name);
5530             }
5531         }
5532         return code;
5533     }
5534 
5535     // handle each overload set
5536     private string generateCodeForOverloadSet(alias oset)() @property
5537     {
5538         string code = "";
5539 
5540         foreach (i_; CountUp!(0 + oset.contents.length)) // workaround
5541         {
5542             enum i = 0 + i_; // workaround
5543             code ~= generateFunction!(
5544                     Policy.FUNCINFO_ID!(oset.name, i), oset.name,
5545                     oset.contents[i]) ~ "\n";
5546         }
5547         return code;
5548     }
5549 
5550     /*
5551      * Returns D code which implements the function func.  This function
5552      * actually generates only the declarator part; the function body part is
5553      * generated by the functionGenerator() policy.
5554      */
5555     public string generateFunction(
5556             string myFuncInfo, string name, func... )() @property
5557     {
5558         import std.format : format;
5559 
5560         enum isCtor = (name == CONSTRUCTOR_NAME);
5561 
5562         string code; // the result
5563 
5564         auto paramsRes = generateParameters!(myFuncInfo, func)();
5565         code ~= paramsRes.imports;
5566 
5567         /*** Function Declarator ***/
5568         {
5569             alias Func = FunctionTypeOf!(func);
5570             alias FA = FunctionAttribute;
5571             enum atts     = functionAttributes!(func);
5572             enum realName = isCtor ? "this" : name;
5573 
5574             // FIXME?? Make it so that these aren't CTFE funcs any more, since
5575             // Format is deprecated, and format works at compile time?
5576             /* Made them CTFE funcs just for the sake of Format!(...) */
5577 
5578             // return type with optional "ref"
5579             static string make_returnType()
5580             {
5581                 string rtype = "";
5582 
5583                 if (!isCtor)
5584                 {
5585                     if (atts & FA.ref_) rtype ~= "ref ";
5586                     rtype ~= myFuncInfo ~ ".RT";
5587                 }
5588                 return rtype;
5589             }
5590             enum returnType = make_returnType();
5591 
5592             // function attributes attached after declaration
5593             static string make_postAtts()
5594             {
5595                 string poatts = "";
5596                 if (atts & FA.pure_   ) poatts ~= " pure";
5597                 if (atts & FA.nothrow_) poatts ~= " nothrow";
5598                 if (atts & FA.property) poatts ~= " @property";
5599                 if (atts & FA.safe    ) poatts ~= " @safe";
5600                 if (atts & FA.trusted ) poatts ~= " @trusted";
5601                 if (atts & FA.scope_ )  poatts ~= " scope";
5602                 if (atts & FA.return_ ) poatts ~= " return";
5603                 return poatts;
5604             }
5605             enum postAtts = make_postAtts();
5606 
5607             // function storage class
5608             static string make_storageClass()
5609             {
5610                 string postc = "";
5611                 if (is(Func ==    shared)) postc ~= " shared";
5612                 if (is(Func ==     const)) postc ~= " const";
5613                 if (is(Func ==     inout)) postc ~= " inout";
5614                 if (is(Func == immutable)) postc ~= " immutable";
5615                 return postc;
5616             }
5617             enum storageClass = make_storageClass();
5618 
5619             //
5620             if (__traits(isVirtualMethod, func))
5621                 code ~= "override ";
5622             code ~= format("extern(%s) %s %s(%s) %s %s\n",
5623                     functionLinkage!(func),
5624                     returnType,
5625                     realName,
5626                     paramsRes.params,
5627                     postAtts, storageClass );
5628         }
5629 
5630         /*** Function Body ***/
5631         code ~= "{\n";
5632         {
5633             enum nparams = Parameters!(func).length;
5634 
5635             /* Declare keywords: args, self and parent. */
5636             string preamble;
5637 
5638             preamble ~= "alias args = AliasSeq!(" ~ enumerateParameters!(nparams) ~ ");\n";
5639             if (!isCtor)
5640             {
5641                 preamble ~= "alias self = " ~ name ~ ";\n";
5642                 static if (WITH_BASE_CLASS)
5643                     preamble ~= `alias parent = __traits(getMember, ` ~ Policy.BASE_CLASS_ID ~ `, "` ~ name ~ `");`;
5644             }
5645 
5646             // Function body
5647             static if (WITHOUT_SYMBOL)
5648                 enum fbody = Policy.generateFunctionBody!(name, func);
5649             else
5650                 enum fbody = Policy.generateFunctionBody!(func);
5651 
5652             code ~= preamble;
5653             code ~= fbody;
5654         }
5655         code ~= "}";
5656 
5657         return code;
5658     }
5659 
5660     /*
5661      * Returns D code which declares function parameters,
5662      * and optionally any imports (e.g. core.vararg)
5663      * "ref int a0, real a1, ..."
5664      */
5665     static struct GenParams { string imports, params; }
5666     private GenParams generateParameters(string myFuncInfo, func...)()
5667     {
5668         alias STC = ParameterStorageClass;
5669         alias stcs = ParameterStorageClassTuple!(func);
5670         enum nparams = stcs.length;
5671 
5672         string imports = ""; // any imports required
5673         string params = ""; // parameters
5674 
5675         foreach (i, stc; stcs)
5676         {
5677             if (i > 0) params ~= ", ";
5678 
5679             // Parameter storage classes.
5680             if (stc & STC.scope_) params ~= "scope ";
5681             if (stc & STC.in_)    params ~= "in ";
5682             if (stc & STC.out_  ) params ~= "out ";
5683             if (stc & STC.ref_  ) params ~= "ref ";
5684             if (stc & STC.lazy_ ) params ~= "lazy ";
5685 
5686             // Take parameter type from the FuncInfo.
5687             params ~= format("%s.PT[%s]", myFuncInfo, i);
5688 
5689             // Declare a parameter variable.
5690             params ~= " " ~ PARAMETER_VARIABLE_ID!(i);
5691         }
5692 
5693         // Add some ellipsis part if needed.
5694         auto style = variadicFunctionStyle!(func);
5695         final switch (style)
5696         {
5697             case Variadic.no:
5698                 break;
5699 
5700             case Variadic.c, Variadic.d:
5701                 imports ~= "import core.vararg;\n";
5702                 // (...) or (a, b, ...)
5703                 params ~= (nparams == 0) ? "..." : ", ...";
5704                 break;
5705 
5706             case Variadic.typesafe:
5707                 params ~= " ...";
5708                 break;
5709         }
5710 
5711         return typeof(return)(imports, params);
5712     }
5713 
5714     // Returns D code which enumerates n parameter variables using comma as the
5715     // separator.  "a0, a1, a2, a3"
5716     private string enumerateParameters(size_t n)() @property
5717     {
5718         string params = "";
5719 
5720         foreach (i_; CountUp!(n))
5721         {
5722             enum i = 0 + i_; // workaround
5723             if (i > 0) params ~= ", ";
5724             params ~= PARAMETER_VARIABLE_ID!(i);
5725         }
5726         return params;
5727     }
5728 }
5729 
5730 
5731 /**
5732 Predefined how-policies for `AutoImplement`.  These templates are also used by
5733 `BlackHole` and `WhiteHole`, respectively.
5734  */
5735 template generateEmptyFunction(C, func.../+[https://issues.dlang.org/show_bug.cgi?id=4217]+/)
5736 {
5737     static if (is(ReturnType!(func) == void))
5738         enum string generateEmptyFunction = q{
5739         };
5740     else static if (functionAttributes!(func) & FunctionAttribute.ref_)
5741         enum string generateEmptyFunction = q{
5742             static typeof(return) dummy;
5743             return dummy;
5744         };
5745     else
5746         enum string generateEmptyFunction = q{
5747             return typeof(return).init;
5748         };
5749 }
5750 
5751 ///
5752 @system unittest
5753 {
5754     alias BlackHole(Base) = AutoImplement!(Base, generateEmptyFunction);
5755 
5756     interface I
5757     {
5758         int foo();
5759         string bar();
5760     }
5761 
5762     auto i = new BlackHole!I();
5763     // generateEmptyFunction returns the default value of the return type without doing anything
5764     assert(i.foo == 0);
5765     assert(i.bar is null);
5766 }
5767 
5768 /// ditto
5769 template generateAssertTrap(C, func...)
5770 {
5771     enum string generateAssertTrap =
5772         `throw new NotImplementedError("` ~ C.stringof ~ "."
5773                 ~ __traits(identifier, func) ~ `");`;
5774 }
5775 
5776 ///
5777 @system unittest
5778 {
5779     import std.exception : assertThrown;
5780 
5781     alias WhiteHole(Base) = AutoImplement!(Base, generateAssertTrap);
5782 
5783     interface I
5784     {
5785         int foo();
5786         string bar();
5787     }
5788 
5789     auto i = new WhiteHole!I();
5790     // generateAssertTrap throws an exception for every unimplemented function of the interface
5791     assertThrown!NotImplementedError(i.foo);
5792     assertThrown!NotImplementedError(i.bar);
5793 }
5794 
5795 private
5796 {
5797     pragma(mangle, "_d_toObject")
5798     extern(C) pure nothrow Object typecons_d_toObject(void* p);
5799 }
5800 
5801 /*
5802  * Avoids opCast operator overloading.
5803  */
5804 private template dynamicCast(T)
5805 if (is(T == class) || is(T == interface))
5806 {
5807     @trusted
5808     T dynamicCast(S)(inout S source)
5809     if (is(S == class) || is(S == interface))
5810     {
5811         static if (is(Unqual!S : Unqual!T))
5812         {
5813             import std.traits : QualifierOf;
5814             alias Qual = QualifierOf!S; // SharedOf or MutableOf
5815             alias TmpT = Qual!(Unqual!T);
5816             inout(TmpT) tmp = source;   // bypass opCast by implicit conversion
5817             return *cast(T*)(&tmp);     // + variable pointer cast + dereference
5818         }
5819         else
5820         {
5821             return cast(T) typecons_d_toObject(*cast(void**)(&source));
5822         }
5823     }
5824 }
5825 
5826 @system unittest
5827 {
5828     class C { @disable void opCast(T)(); }
5829     auto c = new C;
5830     static assert(!__traits(compiles, cast(Object) c));
5831     auto o = dynamicCast!Object(c);
5832     assert(c is o);
5833 
5834     interface I { @disable void opCast(T)(); Object instance(); }
5835     interface J { @disable void opCast(T)(); Object instance(); }
5836     class D : I, J { Object instance() { return this; } }
5837     I i = new D();
5838     static assert(!__traits(compiles, cast(J) i));
5839     J j = dynamicCast!J(i);
5840     assert(i.instance() is j.instance());
5841 }
5842 
5843 /**
5844 Supports structural based typesafe conversion.
5845 
5846 If `Source` has structural conformance with the `interface` `Targets`,
5847 wrap creates an internal wrapper class which inherits `Targets` and
5848 wraps the `src` object, then returns it.
5849 
5850 `unwrap` can be used to extract objects which have been wrapped by `wrap`.
5851 */
5852 template wrap(Targets...)
5853 if (Targets.length >= 1 && allSatisfy!(isMutable, Targets))
5854 {
5855     import std.meta : staticMap;
5856 
5857     // strict upcast
5858     auto wrap(Source)(inout Source src) @trusted pure nothrow
5859     if (Targets.length == 1 && is(Source : Targets[0]))
5860     {
5861         alias T = Select!(is(Source == shared), shared Targets[0], Targets[0]);
5862         return dynamicCast!(inout T)(src);
5863     }
5864     // structural upcast
5865     template wrap(Source)
5866     if (!allSatisfy!(Bind!(isImplicitlyConvertible, Source), Targets))
5867     {
5868         auto wrap(inout Source src)
5869         {
5870             static assert(hasRequireMethods!(),
5871                           "Source "~Source.stringof~
5872                           " does not have structural conformance to "~
5873                           Targets.stringof);
5874 
5875             alias T = Select!(is(Source == shared), shared Impl, Impl);
5876             return new inout T(src);
5877         }
5878 
5879         template FuncInfo(string s, F)
5880         {
5881             enum name = s;
5882             alias type = F;
5883         }
5884 
5885         // https://issues.dlang.org/show_bug.cgi?id=12064: Remove NVI members
5886         template OnlyVirtual(members...)
5887         {
5888             enum notFinal(alias T) = !__traits(isFinalFunction, T);
5889             import std.meta : Filter;
5890             alias OnlyVirtual = Filter!(notFinal, members);
5891         }
5892 
5893         // Concat all Targets function members into one tuple
5894         template Concat(size_t i = 0)
5895         {
5896             static if (i >= Targets.length)
5897                 alias Concat = AliasSeq!();
5898             else
5899             {
5900                 alias Concat = AliasSeq!(OnlyVirtual!(GetOverloadedMethods!(Targets[i]), Concat!(i + 1)));
5901             }
5902         }
5903 
5904         // Remove duplicated functions based on the identifier name and function type covariance
5905         template Uniq(members...)
5906         {
5907             static if (members.length == 0)
5908                 alias Uniq = AliasSeq!();
5909             else
5910             {
5911                 alias func = members[0];
5912                 enum  name = __traits(identifier, func);
5913                 alias type = FunctionTypeOf!func;
5914                 template check(size_t i, mem...)
5915                 {
5916                     static if (i >= mem.length)
5917                         enum ptrdiff_t check = -1;
5918                     else
5919                     {
5920                         enum ptrdiff_t check =
5921                             __traits(identifier, func) == __traits(identifier, mem[i]) &&
5922                             !is(DerivedFunctionType!(type, FunctionTypeOf!(mem[i])) == void)
5923                           ? i : check!(i + 1, mem);
5924                     }
5925                 }
5926                 enum ptrdiff_t x = 1 + check!(0, members[1 .. $]);
5927                 static if (x >= 1)
5928                 {
5929                     alias typex = DerivedFunctionType!(type, FunctionTypeOf!(members[x]));
5930                     alias remain = Uniq!(members[1 .. x], members[x + 1 .. $]);
5931 
5932                     static if (remain.length >= 1 && remain[0].name == name &&
5933                                !is(DerivedFunctionType!(typex, remain[0].type) == void))
5934                     {
5935                         alias F = DerivedFunctionType!(typex, remain[0].type);
5936                         alias Uniq = AliasSeq!(FuncInfo!(name, F), remain[1 .. $]);
5937                     }
5938                     else
5939                         alias Uniq = AliasSeq!(FuncInfo!(name, typex), remain);
5940                 }
5941                 else
5942                 {
5943                     alias Uniq = AliasSeq!(FuncInfo!(name, type), Uniq!(members[1 .. $]));
5944                 }
5945             }
5946         }
5947         alias TargetMembers = Uniq!(Concat!());             // list of FuncInfo
5948         alias SourceMembers = GetOverloadedMethods!Source;  // list of function symbols
5949 
5950         // Check whether all of SourceMembers satisfy covariance target in TargetMembers
5951         template hasRequireMethods(size_t i = 0)
5952         {
5953             static if (i >= TargetMembers.length)
5954                 enum hasRequireMethods = true;
5955             else
5956             {
5957                 enum hasRequireMethods =
5958                     findCovariantFunction!(TargetMembers[i], Source, SourceMembers) != -1 &&
5959                     hasRequireMethods!(i + 1);
5960             }
5961         }
5962 
5963         // Internal wrapper class
5964         final class Impl : Structural, Targets
5965         {
5966         private:
5967             Source _wrap_source;
5968 
5969             this(       inout Source s)        inout @safe pure nothrow { _wrap_source = s; }
5970             this(shared inout Source s) shared inout @safe pure nothrow { _wrap_source = s; }
5971 
5972             // BUG: making private should work with NVI.
5973             protected final inout(Object) _wrap_getSource() inout @trusted
5974             {
5975                 return dynamicCast!(inout Object)(_wrap_source);
5976             }
5977 
5978             import std.conv : to;
5979             import core.lifetime : forward;
5980             template generateFun(size_t i)
5981             {
5982                 enum name = TargetMembers[i].name;
5983                 enum fa = functionAttributes!(TargetMembers[i].type);
5984                 static @property stc()
5985                 {
5986                     string r;
5987                     if (fa & FunctionAttribute.property)    r ~= "@property ";
5988                     if (fa & FunctionAttribute.ref_)        r ~= "ref ";
5989                     if (fa & FunctionAttribute.pure_)       r ~= "pure ";
5990                     if (fa & FunctionAttribute.nothrow_)    r ~= "nothrow ";
5991                     if (fa & FunctionAttribute.trusted)     r ~= "@trusted ";
5992                     if (fa & FunctionAttribute.safe)        r ~= "@safe ";
5993                     return r;
5994                 }
5995                 static @property mod()
5996                 {
5997                     alias type = AliasSeq!(TargetMembers[i].type)[0];
5998                     string r;
5999                     static if (is(type == immutable))       r ~= " immutable";
6000                     else
6001                     {
6002                         static if (is(type == shared))      r ~= " shared";
6003                         static if (is(type == const))       r ~= " const";
6004                         else static if (is(type == inout))  r ~= " inout";
6005                         //else  --> mutable
6006                     }
6007                     return r;
6008                 }
6009                 enum n = to!string(i);
6010                 static if (fa & FunctionAttribute.property)
6011                 {
6012                     static if (Parameters!(TargetMembers[i].type).length == 0)
6013                         enum fbody = "_wrap_source."~name;
6014                     else
6015                         enum fbody = "_wrap_source."~name~" = forward!args";
6016                 }
6017                 else
6018                 {
6019                         enum fbody = "_wrap_source."~name~"(forward!args)";
6020                 }
6021                 enum generateFun =
6022                     "override "~stc~"ReturnType!(TargetMembers["~n~"].type) "
6023                     ~ name~"(Parameters!(TargetMembers["~n~"].type) args) "~mod~
6024                     "{ return "~fbody~"; }";
6025             }
6026 
6027         public:
6028             static foreach (i; 0 .. TargetMembers.length)
6029                 mixin(generateFun!i);
6030         }
6031     }
6032 }
6033 /// ditto
6034 template wrap(Targets...)
6035 if (Targets.length >= 1 && !allSatisfy!(isMutable, Targets))
6036 {
6037     import std.meta : staticMap;
6038 
6039     alias wrap = .wrap!(staticMap!(Unqual, Targets));
6040 }
6041 
6042 /// ditto
6043 template unwrap(Target)
6044 if (isMutable!Target)
6045 {
6046     // strict downcast
6047     auto unwrap(Source)(inout Source src) @trusted pure nothrow
6048     if (is(Target : Source))
6049     {
6050         alias T = Select!(is(Source == shared), shared Target, Target);
6051         return dynamicCast!(inout T)(src);
6052     }
6053     // structural downcast
6054     auto unwrap(Source)(inout Source src) @trusted pure nothrow
6055     if (!is(Target : Source))
6056     {
6057         alias T = Select!(is(Source == shared), shared Target, Target);
6058         Object o = dynamicCast!(Object)(src);   // remove qualifier
6059         do
6060         {
6061             if (auto a = dynamicCast!(Structural)(o))
6062             {
6063                 if (auto d = dynamicCast!(inout T)(o = a._wrap_getSource()))
6064                     return d;
6065             }
6066             else if (auto d = dynamicCast!(inout T)(o))
6067                 return d;
6068             else
6069                 break;
6070         } while (o);
6071         return null;
6072     }
6073 }
6074 
6075 /// ditto
6076 template unwrap(Target)
6077 if (!isMutable!Target)
6078 {
6079     alias unwrap = .unwrap!(Unqual!Target);
6080 }
6081 
6082 ///
6083 @system unittest
6084 {
6085     interface Quack
6086     {
6087         int quack();
6088         @property int height();
6089     }
6090     interface Flyer
6091     {
6092         @property int height();
6093     }
6094     class Duck : Quack
6095     {
6096         int quack() { return 1; }
6097         @property int height() { return 10; }
6098     }
6099     class Human
6100     {
6101         int quack() { return 2; }
6102         @property int height() { return 20; }
6103     }
6104 
6105     Duck d1 = new Duck();
6106     Human h1 = new Human();
6107 
6108     interface Refleshable
6109     {
6110         int reflesh();
6111     }
6112 
6113     // does not have structural conformance
6114     static assert(!__traits(compiles, d1.wrap!Refleshable));
6115     static assert(!__traits(compiles, h1.wrap!Refleshable));
6116 
6117     // strict upcast
6118     Quack qd = d1.wrap!Quack;
6119     assert(qd is d1);
6120     assert(qd.quack() == 1);    // calls Duck.quack
6121     // strict downcast
6122     Duck d2 = qd.unwrap!Duck;
6123     assert(d2 is d1);
6124 
6125     // structural upcast
6126     Quack qh = h1.wrap!Quack;
6127     assert(qh.quack() == 2);    // calls Human.quack
6128     // structural downcast
6129     Human h2 = qh.unwrap!Human;
6130     assert(h2 is h1);
6131 
6132     // structural upcast (two steps)
6133     Quack qx = h1.wrap!Quack;   // Human -> Quack
6134     Flyer fx = qx.wrap!Flyer;   // Quack -> Flyer
6135     assert(fx.height == 20);    // calls Human.height
6136     // structural downcast (two steps)
6137     Quack qy = fx.unwrap!Quack; // Flyer -> Quack
6138     Human hy = qy.unwrap!Human; // Quack -> Human
6139     assert(hy is h1);
6140     // structural downcast (one step)
6141     Human hz = fx.unwrap!Human; // Flyer -> Human
6142     assert(hz is h1);
6143 }
6144 
6145 ///
6146 @system unittest
6147 {
6148     import std.traits : FunctionAttribute, functionAttributes;
6149     interface A { int run(); }
6150     interface B { int stop(); @property int status(); }
6151     class X
6152     {
6153         int run() { return 1; }
6154         int stop() { return 2; }
6155         @property int status() { return 3; }
6156     }
6157 
6158     auto x = new X();
6159     auto ab = x.wrap!(A, B);
6160     A a = ab;
6161     B b = ab;
6162     assert(a.run() == 1);
6163     assert(b.stop() == 2);
6164     assert(b.status == 3);
6165     static assert(functionAttributes!(typeof(ab).status) & FunctionAttribute.property);
6166 }
6167 
6168 // Internal class to support dynamic cross-casting
6169 private interface Structural
6170 {
6171     inout(Object) _wrap_getSource() inout @safe pure nothrow;
6172 }
6173 
6174 @system unittest
6175 {
6176     class A
6177     {
6178         int draw()              { return 1; }
6179         int draw(int v)         { return v; }
6180 
6181         int draw() const        { return 2; }
6182         int draw() shared       { return 3; }
6183         int draw() shared const { return 4; }
6184         int draw() immutable    { return 5; }
6185     }
6186     interface Drawable
6187     {
6188         int draw();
6189         int draw() const;
6190         int draw() shared;
6191         int draw() shared const;
6192         int draw() immutable;
6193     }
6194     interface Drawable2
6195     {
6196         int draw(int v);
6197     }
6198 
6199     auto ma = new A();
6200     auto sa = new shared A();
6201     auto ia = new immutable A();
6202     {
6203                      Drawable  md = ma.wrap!Drawable;
6204                const Drawable  cd = ma.wrap!Drawable;
6205               shared Drawable  sd = sa.wrap!Drawable;
6206         shared const Drawable scd = sa.wrap!Drawable;
6207            immutable Drawable  id = ia.wrap!Drawable;
6208         assert( md.draw() == 1);
6209         assert( cd.draw() == 2);
6210         assert( sd.draw() == 3);
6211         assert(scd.draw() == 4);
6212         assert( id.draw() == 5);
6213     }
6214     {
6215         Drawable2 d = ma.wrap!Drawable2;
6216         static assert(!__traits(compiles, d.draw()));
6217         assert(d.draw(10) == 10);
6218     }
6219 }
6220 
6221 // https://issues.dlang.org/show_bug.cgi?id=10377
6222 @system unittest
6223 {
6224     import std.range, std.algorithm;
6225 
6226     interface MyInputRange(T)
6227     {
6228         @property T front();
6229         void popFront();
6230         @property bool empty();
6231     }
6232 
6233     //auto o = iota(0,10,1).inputRangeObject();
6234     //pragma(msg, __traits(allMembers, typeof(o)));
6235     auto r = iota(0,10,1).inputRangeObject().wrap!(MyInputRange!int)();
6236     assert(equal(r, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]));
6237 }
6238 
6239 // https://issues.dlang.org/show_bug.cgi?id=10536
6240 @system unittest
6241 {
6242     interface Interface
6243     {
6244         int foo();
6245     }
6246     class Pluggable
6247     {
6248         int foo() { return 1; }
6249         @disable void opCast(T, this X)();  // !
6250     }
6251 
6252     Interface i = new Pluggable().wrap!Interface;
6253     assert(i.foo() == 1);
6254 }
6255 @system unittest
6256 {
6257     // Enhancement 10538
6258     interface Interface
6259     {
6260         int foo();
6261         int bar(int);
6262     }
6263     class Pluggable
6264     {
6265         int opDispatch(string name, A...)(A args) { return 100; }
6266     }
6267 
6268     Interface i = wrap!Interface(new Pluggable());
6269     assert(i.foo() == 100);
6270     assert(i.bar(10) == 100);
6271 }
6272 
6273 // https://issues.dlang.org/show_bug.cgi?id=12064
6274 @system unittest
6275 {
6276     interface I
6277     {
6278         int foo();
6279         final int nvi1(){return foo();}
6280     }
6281 
6282     interface J
6283     {
6284         int bar();
6285         final int nvi2(){return bar();}
6286     }
6287 
6288     class Baz
6289     {
6290         int foo() { return 42;}
6291         int bar() { return 12064;}
6292     }
6293 
6294     auto baz = new Baz();
6295     auto foobar = baz.wrap!(I, J)();
6296     assert(foobar.nvi1 == 42);
6297     assert(foobar.nvi2 == 12064);
6298 }
6299 
6300 // Make a tuple of non-static function symbols
6301 package template GetOverloadedMethods(T)
6302 {
6303     import std.meta : Filter;
6304 
6305     alias allMembers = __traits(allMembers, T);
6306     template follows(size_t i = 0)
6307     {
6308         static if (i >= allMembers.length)
6309         {
6310             alias follows = AliasSeq!();
6311         }
6312         else static if (!__traits(compiles, mixin("T."~allMembers[i])))
6313         {
6314             alias follows = follows!(i + 1);
6315         }
6316         else
6317         {
6318             enum name = allMembers[i];
6319 
6320             template isMethod(alias f)
6321             {
6322                 static if (is(typeof(&f) F == F*) && is(F == function))
6323                     enum isMethod = !__traits(isStaticFunction, f);
6324                 else
6325                     enum isMethod = false;
6326             }
6327             alias follows = AliasSeq!(
6328                 Filter!(isMethod, __traits(getOverloads, T, name)),
6329                 follows!(i + 1));
6330         }
6331     }
6332     alias GetOverloadedMethods = follows!();
6333 }
6334 // find a function from Fs that has same identifier and covariant type with f
6335 private template findCovariantFunction(alias finfo, Source, Fs...)
6336 {
6337     template check(size_t i = 0)
6338     {
6339         static if (i >= Fs.length)
6340             enum ptrdiff_t check = -1;
6341         else
6342         {
6343             enum ptrdiff_t check =
6344                 (finfo.name == __traits(identifier, Fs[i])) &&
6345                 isCovariantWith!(FunctionTypeOf!(Fs[i]), finfo.type)
6346               ? i : check!(i + 1);
6347         }
6348     }
6349     enum x = check!();
6350     static if (x == -1 && is(typeof(Source.opDispatch)))
6351     {
6352         alias Params = Parameters!(finfo.type);
6353         enum ptrdiff_t findCovariantFunction =
6354             is(typeof((             Source).init.opDispatch!(finfo.name)(Params.init))) ||
6355             is(typeof((       const Source).init.opDispatch!(finfo.name)(Params.init))) ||
6356             is(typeof((   immutable Source).init.opDispatch!(finfo.name)(Params.init))) ||
6357             is(typeof((      shared Source).init.opDispatch!(finfo.name)(Params.init))) ||
6358             is(typeof((shared const Source).init.opDispatch!(finfo.name)(Params.init)))
6359           ? ptrdiff_t.max : -1;
6360     }
6361     else
6362         enum ptrdiff_t findCovariantFunction = x;
6363 }
6364 
6365 private enum TypeModifier
6366 {
6367     mutable     = 0,    // type is mutable
6368     const_      = 1,    // type is const
6369     immutable_  = 2,    // type is immutable
6370     shared_     = 4,    // type is shared
6371     inout_      = 8,    // type is wild
6372 }
6373 private template TypeMod(T)
6374 {
6375     static if (is(T == immutable))
6376     {
6377         enum mod1 = TypeModifier.immutable_;
6378         enum mod2 = 0;
6379     }
6380     else
6381     {
6382         enum mod1 = is(T == shared) ? TypeModifier.shared_ : 0;
6383         static if (is(T == const))
6384             enum mod2 = TypeModifier.const_;
6385         else static if (is(T == inout))
6386             enum mod2 = TypeModifier.inout_;
6387         else
6388             enum mod2 = TypeModifier.mutable;
6389     }
6390     enum TypeMod = cast(TypeModifier)(mod1 | mod2);
6391 }
6392 
6393 @system unittest
6394 {
6395     template UnittestFuncInfo(alias f)
6396     {
6397         enum name = __traits(identifier, f);
6398         alias type = FunctionTypeOf!f;
6399     }
6400 
6401     class A
6402     {
6403         int draw() { return 1; }
6404         @property int value() { return 2; }
6405         final int run() { return 3; }
6406     }
6407     alias methods = GetOverloadedMethods!A;
6408 
6409     alias int F1();
6410     alias @property int F2();
6411     alias string F3();
6412     alias nothrow @trusted uint F4();
6413     alias int F5(Object);
6414     alias bool F6(Object);
6415     static assert(methods.length == 3 + 4);
6416     static assert(__traits(identifier, methods[0]) == "draw"     && is(typeof(&methods[0]) == F1*));
6417     static assert(__traits(identifier, methods[1]) == "value"    && is(typeof(&methods[1]) == F2*));
6418     static assert(__traits(identifier, methods[2]) == "run"      && is(typeof(&methods[2]) == F1*));
6419 
6420     int draw();
6421     @property int value();
6422     void opEquals();
6423     int nomatch();
6424     static assert(findCovariantFunction!(UnittestFuncInfo!draw,     A, methods) == 0);
6425     static assert(findCovariantFunction!(UnittestFuncInfo!value,    A, methods) == 1);
6426     static assert(findCovariantFunction!(UnittestFuncInfo!opEquals, A, methods) == -1);
6427     static assert(findCovariantFunction!(UnittestFuncInfo!nomatch,  A, methods) == -1);
6428 
6429     // considering opDispatch
6430     class B
6431     {
6432         void opDispatch(string name, A...)(A) {}
6433     }
6434     alias methodsB = GetOverloadedMethods!B;
6435     static assert(findCovariantFunction!(UnittestFuncInfo!draw,     B, methodsB) == ptrdiff_t.max);
6436     static assert(findCovariantFunction!(UnittestFuncInfo!value,    B, methodsB) == ptrdiff_t.max);
6437     static assert(findCovariantFunction!(UnittestFuncInfo!opEquals, B, methodsB) == ptrdiff_t.max);
6438     static assert(findCovariantFunction!(UnittestFuncInfo!nomatch,  B, methodsB) == ptrdiff_t.max);
6439 }
6440 
6441 package template DerivedFunctionType(T...)
6442 {
6443     static if (!T.length)
6444     {
6445         alias DerivedFunctionType = void;
6446     }
6447     else static if (T.length == 1)
6448     {
6449         static if (is(T[0] == function))
6450         {
6451             alias DerivedFunctionType = T[0];
6452         }
6453         else
6454         {
6455             alias DerivedFunctionType = void;
6456         }
6457     }
6458     else static if (is(T[0] P0 == function) && is(T[1] P1 == function))
6459     {
6460         alias FA = FunctionAttribute;
6461 
6462         alias F0 = T[0], R0 = ReturnType!F0, PSTC0 = ParameterStorageClassTuple!F0;
6463         alias F1 = T[1], R1 = ReturnType!F1, PSTC1 = ParameterStorageClassTuple!F1;
6464         enum FA0 = functionAttributes!F0;
6465         enum FA1 = functionAttributes!F1;
6466 
6467         template CheckParams(size_t i = 0)
6468         {
6469             static if (i >= P0.length)
6470                 enum CheckParams = true;
6471             else
6472             {
6473                 enum CheckParams = (is(P0[i] == P1[i]) && PSTC0[i] == PSTC1[i]) &&
6474                                    CheckParams!(i + 1);
6475             }
6476         }
6477         static if (R0.sizeof == R1.sizeof && !is(CommonType!(R0, R1) == void) &&
6478                    P0.length == P1.length && CheckParams!() && TypeMod!F0 == TypeMod!F1 &&
6479                    variadicFunctionStyle!F0 == variadicFunctionStyle!F1 &&
6480                    functionLinkage!F0 == functionLinkage!F1 &&
6481                    ((FA0 ^ FA1) & (FA.ref_ | FA.property)) == 0)
6482         {
6483             alias R = Select!(is(R0 : R1), R0, R1);
6484             alias FX = FunctionTypeOf!(R function(P0));
6485             // @system is default
6486             alias FY = SetFunctionAttributes!(FX, functionLinkage!F0, (FA0 | FA1) & ~FA.system);
6487             alias DerivedFunctionType = DerivedFunctionType!(FY, T[2 .. $]);
6488         }
6489         else
6490             alias DerivedFunctionType = void;
6491     }
6492     else
6493         alias DerivedFunctionType = void;
6494 }
6495 @safe unittest
6496 {
6497     // attribute covariance
6498     alias int F1();
6499     static assert(is(DerivedFunctionType!(F1, F1) == F1));
6500     alias int F2() pure nothrow;
6501     static assert(is(DerivedFunctionType!(F1, F2) == F2));
6502     alias int F3() @safe;
6503     alias int F23() @safe pure nothrow;
6504     static assert(is(DerivedFunctionType!(F2, F3) == F23));
6505 
6506     // return type covariance
6507     alias long F4();
6508     static assert(is(DerivedFunctionType!(F1, F4) == void));
6509     class C {}
6510     class D : C {}
6511     alias C F5();
6512     alias D F6();
6513     static assert(is(DerivedFunctionType!(F5, F6) == F6));
6514     alias typeof(null) F7();
6515     alias int[] F8();
6516     alias int* F9();
6517     static assert(is(DerivedFunctionType!(F5, F7) == F7));
6518     static assert(is(DerivedFunctionType!(F7, F8) == void));
6519     static assert(is(DerivedFunctionType!(F7, F9) == F7));
6520 
6521     // variadic type equality
6522     alias int F10(int);
6523     alias int F11(int...);
6524     alias int F12(int, ...);
6525     static assert(is(DerivedFunctionType!(F10, F11) == void));
6526     static assert(is(DerivedFunctionType!(F10, F12) == void));
6527     static assert(is(DerivedFunctionType!(F11, F12) == void));
6528 
6529     // linkage equality
6530     alias extern(C) int F13(int);
6531     alias extern(D) int F14(int);
6532     alias extern(Windows) int F15(int);
6533     static assert(is(DerivedFunctionType!(F13, F14) == void));
6534     static assert(is(DerivedFunctionType!(F13, F15) == void));
6535     static assert(is(DerivedFunctionType!(F14, F15) == void));
6536 
6537     // ref & @property equality
6538     alias int F16(int);
6539     alias ref int F17(int);
6540     alias @property int F18(int);
6541     static assert(is(DerivedFunctionType!(F16, F17) == void));
6542     static assert(is(DerivedFunctionType!(F16, F18) == void));
6543     static assert(is(DerivedFunctionType!(F17, F18) == void));
6544 }
6545 
6546 package template Bind(alias Template, args1...)
6547 {
6548     alias Bind(args2...) = Template!(args1, args2);
6549 }
6550 
6551 
6552 /**
6553 Options regarding auto-initialization of a `RefCounted` object (see
6554 the definition of `RefCounted` below).
6555  */
6556 enum RefCountedAutoInitialize
6557 {
6558     /// Do not auto-initialize the object
6559     no,
6560     /// Auto-initialize the object
6561     yes,
6562 }
6563 
6564 ///
6565 @system unittest
6566 {
6567     import core.exception : AssertError;
6568     import std.exception : assertThrown;
6569 
6570     struct Foo
6571     {
6572         int a = 42;
6573     }
6574 
6575     RefCounted!(Foo, RefCountedAutoInitialize.yes) rcAuto;
6576     RefCounted!(Foo, RefCountedAutoInitialize.no) rcNoAuto;
6577 
6578     assert(rcAuto.refCountedPayload.a == 42);
6579 
6580     assertThrown!AssertError(rcNoAuto.refCountedPayload);
6581     rcNoAuto.refCountedStore.ensureInitialized;
6582     assert(rcNoAuto.refCountedPayload.a == 42);
6583 }
6584 
6585 /**
6586 Defines a reference-counted object containing a `T` value as
6587 payload.
6588 
6589 An instance of `RefCounted` is a reference to a structure,
6590 which is referred to as the $(I store), or $(I storage implementation
6591 struct) in this documentation.  The store contains a reference count
6592 and the `T` payload.  `RefCounted` uses `malloc` to allocate
6593 the store.  As instances of `RefCounted` are copied or go out of
6594 scope, they will automatically increment or decrement the reference
6595 count.  When the reference count goes down to zero, `RefCounted`
6596 will call `destroy` against the payload and call `free` to
6597 deallocate the store.  If the `T` payload contains any references
6598 to GC-allocated memory, then `RefCounted` will add it to the GC memory
6599 that is scanned for pointers, and remove it from GC scanning before
6600 `free` is called on the store.
6601 
6602 One important consequence of `destroy` is that it will call the
6603 destructor of the `T` payload.  GC-managed references are not
6604 guaranteed to be valid during a destructor call, but other members of
6605 `T`, such as file handles or pointers to `malloc` memory, will
6606 still be valid during the destructor call.  This allows the `T` to
6607 deallocate or clean up any non-GC resources immediately after the
6608 reference count has reached zero.
6609 
6610 `RefCounted` is unsafe and should be used with care. No references
6611 to the payload should be escaped outside the `RefCounted` object.
6612 
6613 The `autoInit` option makes the object ensure the store is
6614 automatically initialized. Leaving $(D autoInit ==
6615 RefCountedAutoInitialize.yes) (the default option) is convenient but
6616 has the cost of a test whenever the payload is accessed. If $(D
6617 autoInit == RefCountedAutoInitialize.no), user code must call either
6618 `refCountedStore.isInitialized` or `refCountedStore.ensureInitialized`
6619 before attempting to access the payload. Not doing so results in null
6620 pointer dereference.
6621 
6622 If `T.this()` is annotated with `@disable` then `autoInit` must be
6623 `RefCountedAutoInitialize.no` in order to compile.
6624  */
6625 struct RefCounted(T, RefCountedAutoInitialize autoInit =
6626         RefCountedAutoInitialize.yes)
6627 if (!is(T == class) && !(is(T == interface)))
6628 {
6629     version (D_BetterC)
6630     {
6631         private enum enableGCScan = false;
6632     }
6633     else
6634     {
6635         private enum enableGCScan = hasIndirections!T;
6636     }
6637 
6638     // TODO remove pure when https://issues.dlang.org/show_bug.cgi?id=15862 has been fixed
6639     extern(C) private pure nothrow @nogc static
6640     {
6641         pragma(mangle, "free") void pureFree( void *ptr );
6642         static if (enableGCScan)
6643         {
6644             pragma(mangle, "gc_addRange") void pureGcAddRange( in void* p, size_t sz, const TypeInfo ti = null );
6645             pragma(mangle, "gc_removeRange") void pureGcRemoveRange( in void* p );
6646         }
6647     }
6648 
6649     /// `RefCounted` storage implementation.
6650     struct RefCountedStore
6651     {
6652         private struct Impl
6653         {
6654             T _payload;
6655             size_t _count;
6656         }
6657 
6658         private Impl* _store;
6659 
6660         private void initialize(A...)(auto ref A args)
6661         {
6662             import core.lifetime : emplace, forward;
6663 
6664             allocateStore();
6665             version (D_Exceptions) scope(failure) deallocateStore();
6666             emplace(&_store._payload, forward!args);
6667             _store._count = 1;
6668         }
6669 
6670         private void move(ref T source) nothrow pure
6671         {
6672             import std.algorithm.mutation : moveEmplace;
6673 
6674             allocateStore();
6675             moveEmplace(source, _store._payload);
6676             _store._count = 1;
6677         }
6678 
6679         // 'nothrow': can only generate an Error
6680         private void allocateStore() nothrow pure
6681         {
6682             static if (enableGCScan)
6683             {
6684                 import std.internal.memory : enforceCalloc;
6685                 _store = cast(Impl*) enforceCalloc(1, Impl.sizeof);
6686                 pureGcAddRange(&_store._payload, T.sizeof);
6687             }
6688             else
6689             {
6690                 import std.internal.memory : enforceMalloc;
6691                 _store = cast(Impl*) enforceMalloc(Impl.sizeof);
6692             }
6693         }
6694 
6695         private void deallocateStore() nothrow pure
6696         {
6697             static if (enableGCScan)
6698             {
6699                 pureGcRemoveRange(&this._store._payload);
6700             }
6701             pureFree(_store);
6702             _store = null;
6703         }
6704 
6705         /**
6706            Returns `true` if and only if the underlying store has been
6707            allocated and initialized.
6708         */
6709         @property nothrow @safe pure @nogc
6710         bool isInitialized() const
6711         {
6712             return _store !is null;
6713         }
6714 
6715         /**
6716            Returns underlying reference count if it is allocated and initialized
6717            (a positive integer), and `0` otherwise.
6718         */
6719         @property nothrow @safe pure @nogc
6720         size_t refCount() const
6721         {
6722             return isInitialized ? _store._count : 0;
6723         }
6724 
6725         /**
6726            Makes sure the payload was properly initialized. Such a
6727            call is typically inserted before using the payload.
6728 
6729            This function is unavailable if `T.this()` is annotated with
6730            `@disable`.
6731         */
6732         void ensureInitialized()()
6733         {
6734             // By checking for `@disable this()` and failing early we can
6735             // produce a clearer error message.
6736             static assert(__traits(compiles, { static T t; }),
6737                 "Cannot automatically initialize `" ~ fullyQualifiedName!T ~
6738                 "` because `" ~ fullyQualifiedName!T ~
6739                 ".this()` is annotated with `@disable`.");
6740             if (!isInitialized) initialize();
6741         }
6742 
6743     }
6744     RefCountedStore _refCounted;
6745 
6746     /// Returns storage implementation struct.
6747     @property nothrow @safe
6748     ref inout(RefCountedStore) refCountedStore() inout
6749     {
6750         return _refCounted;
6751     }
6752 
6753 /**
6754 Constructor that initializes the payload.
6755 
6756 Postcondition: `refCountedStore.isInitialized`
6757  */
6758     this(A...)(auto ref A args) if (A.length > 0)
6759     out
6760     {
6761         assert(refCountedStore.isInitialized);
6762     }
6763     do
6764     {
6765         import core.lifetime : forward;
6766         _refCounted.initialize(forward!args);
6767     }
6768 
6769     /// Ditto
6770     this(T val)
6771     {
6772         _refCounted.move(val);
6773     }
6774 
6775 /**
6776 Constructor that tracks the reference count appropriately. If $(D
6777 !refCountedStore.isInitialized), does nothing.
6778  */
6779     this(this) @safe pure nothrow @nogc
6780     {
6781         if (!_refCounted.isInitialized) return;
6782         ++_refCounted._store._count;
6783     }
6784 
6785 /**
6786 Destructor that tracks the reference count appropriately. If $(D
6787 !refCountedStore.isInitialized), does nothing. When the reference count goes
6788 down to zero, calls `destroy` agaist the payload and calls `free`
6789 to deallocate the corresponding resource.
6790  */
6791     ~this()
6792     {
6793         if (!_refCounted.isInitialized) return;
6794         assert(_refCounted._store._count > 0);
6795         if (--_refCounted._store._count)
6796             return;
6797         // Done, destroy and deallocate
6798         .destroy(_refCounted._store._payload);
6799         _refCounted.deallocateStore();
6800     }
6801 
6802 /**
6803 Assignment operators
6804  */
6805     void opAssign(typeof(this) rhs)
6806     {
6807         import std.algorithm.mutation : swap;
6808 
6809         swap(_refCounted._store, rhs._refCounted._store);
6810     }
6811 
6812 /// Ditto
6813     void opAssign(T rhs)
6814     {
6815         import std.algorithm.mutation : move;
6816 
6817         static if (autoInit == RefCountedAutoInitialize.yes)
6818         {
6819             _refCounted.ensureInitialized();
6820         }
6821         else
6822         {
6823             assert(_refCounted.isInitialized);
6824         }
6825         move(rhs, _refCounted._store._payload);
6826     }
6827 
6828     //version to have a single properly ddoc'ed function (w/ correct sig)
6829     version (StdDdoc)
6830     {
6831         /**
6832         Returns a reference to the payload. If (autoInit ==
6833         RefCountedAutoInitialize.yes), calls $(D
6834         refCountedStore.ensureInitialized). Otherwise, just issues $(D
6835         assert(refCountedStore.isInitialized)). Used with $(D alias
6836         refCountedPayload this;), so callers can just use the `RefCounted`
6837         object as a `T`.
6838 
6839         $(BLUE The first overload exists only if $(D autoInit == RefCountedAutoInitialize.yes).)
6840         So if $(D autoInit == RefCountedAutoInitialize.no)
6841         or called for a constant or immutable object, then
6842         `refCountedPayload` will also be qualified as safe and nothrow
6843         (but will still assert if not initialized).
6844          */
6845         @property @trusted
6846         ref T refCountedPayload() return;
6847 
6848         /// ditto
6849         @property nothrow @safe pure @nogc
6850         ref inout(T) refCountedPayload() inout return;
6851     }
6852     else
6853     {
6854         static if (autoInit == RefCountedAutoInitialize.yes)
6855         {
6856             //Can't use inout here because of potential mutation
6857             @property
6858             ref T refCountedPayload() return
6859             {
6860                 _refCounted.ensureInitialized();
6861                 return _refCounted._store._payload;
6862             }
6863         }
6864 
6865         @property nothrow @safe pure @nogc
6866         ref inout(T) refCountedPayload() inout return
6867         {
6868             assert(_refCounted.isInitialized, "Attempted to access an uninitialized payload.");
6869             return _refCounted._store._payload;
6870         }
6871     }
6872 
6873 /**
6874 Returns a reference to the payload. If (autoInit ==
6875 RefCountedAutoInitialize.yes), calls $(D
6876 refCountedStore.ensureInitialized). Otherwise, just issues $(D
6877 assert(refCountedStore.isInitialized)).
6878  */
6879     alias refCountedPayload this;
6880 
6881     static if (is(T == struct) && !is(typeof((ref T t) => t.toString())))
6882     {
6883         string toString(this This)()
6884         {
6885             import std.conv : to;
6886 
6887             static if (autoInit)
6888                 return to!string(refCountedPayload);
6889             else
6890             {
6891                 if (!_refCounted.isInitialized)
6892                     return This.stringof ~ "(RefCountedStore(null))";
6893                 else
6894                     return to!string(_refCounted._store._payload);
6895             }
6896         }
6897     }
6898 }
6899 
6900 ///
6901 @betterC pure @system nothrow @nogc unittest
6902 {
6903     // A pair of an `int` and a `size_t` - the latter being the
6904     // reference count - will be dynamically allocated
6905     auto rc1 = RefCounted!int(5);
6906     assert(rc1 == 5);
6907     // No more allocation, add just one extra reference count
6908     auto rc2 = rc1;
6909     // Reference semantics
6910     rc2 = 42;
6911     assert(rc1 == 42);
6912     // the pair will be freed when rc1 and rc2 go out of scope
6913 }
6914 
6915 pure @system unittest
6916 {
6917     RefCounted!int* p;
6918     {
6919         auto rc1 = RefCounted!int(5);
6920         p = &rc1;
6921         assert(rc1 == 5);
6922         assert(rc1._refCounted._store._count == 1);
6923         auto rc2 = rc1;
6924         assert(rc1._refCounted._store._count == 2);
6925         // Reference semantics
6926         rc2 = 42;
6927         assert(rc1 == 42);
6928         rc2 = rc2;
6929         assert(rc2._refCounted._store._count == 2);
6930         rc1 = rc2;
6931         assert(rc1._refCounted._store._count == 2);
6932     }
6933     assert(p._refCounted._store == null);
6934 
6935     // RefCounted as a member
6936     struct A
6937     {
6938         RefCounted!int x;
6939         this(int y)
6940         {
6941             x._refCounted.initialize(y);
6942         }
6943         A copy()
6944         {
6945             auto another = this;
6946             return another;
6947         }
6948     }
6949     auto a = A(4);
6950     auto b = a.copy();
6951     assert(a.x._refCounted._store._count == 2,
6952            "https://issues.dlang.org/show_bug.cgi?id=4356 still unfixed");
6953 }
6954 
6955 @betterC pure @system nothrow @nogc unittest
6956 {
6957     import std.algorithm.mutation : swap;
6958 
6959     RefCounted!int p1, p2;
6960     swap(p1, p2);
6961 }
6962 
6963 // https://issues.dlang.org/show_bug.cgi?id=6606
6964 @betterC @safe pure nothrow @nogc unittest
6965 {
6966     union U {
6967        size_t i;
6968        void* p;
6969     }
6970 
6971     struct S {
6972        U u;
6973     }
6974 
6975     alias SRC = RefCounted!S;
6976 }
6977 
6978 // https://issues.dlang.org/show_bug.cgi?id=6436
6979 @betterC @system pure unittest
6980 {
6981     struct S
6982     {
6983         this(int rval) { assert(rval == 1); }
6984         this(ref int lval) { assert(lval == 3); ++lval; }
6985     }
6986 
6987     auto s1 = RefCounted!S(1);
6988     int lval = 3;
6989     auto s2 = RefCounted!S(lval);
6990     assert(lval == 4);
6991 }
6992 
6993 // gc_addRange coverage
6994 @betterC @system pure unittest
6995 {
6996     struct S { int* p; }
6997 
6998     auto s = RefCounted!S(null);
6999 }
7000 
7001 @betterC @system pure nothrow @nogc unittest
7002 {
7003     RefCounted!int a;
7004     a = 5; //This should not assert
7005     assert(a == 5);
7006 
7007     RefCounted!int b;
7008     b = a; //This should not assert either
7009     assert(b == 5);
7010 
7011     RefCounted!(int*) c;
7012 }
7013 
7014 // https://issues.dlang.org/show_bug.cgi?id=21638
7015 @betterC @system pure nothrow @nogc unittest
7016 {
7017     static struct NoDefaultCtor
7018     {
7019         @disable this();
7020         this(int x) @nogc nothrow pure { this.x = x; }
7021         int x;
7022     }
7023     auto rc = RefCounted!(NoDefaultCtor, RefCountedAutoInitialize.no)(5);
7024     assert(rc.x == 5);
7025 }
7026 
7027 // https://issues.dlang.org/show_bug.cgi?id=20502
7028 @system unittest
7029 {
7030     import std.conv : to;
7031     // Check that string conversion is transparent for refcounted
7032     // structs that do not have either toString or alias this.
7033     static struct A { Object a; }
7034     auto a  = A(new Object());
7035     auto r = refCounted(a);
7036     assert(to!string(r) == to!string(a));
7037     assert(to!string(cast(const) r) == to!string(cast(const) a));
7038     // Check that string conversion is still transparent for refcounted
7039     // structs that have alias this.
7040     static struct B { int b; alias b this; }
7041     static struct C { B b; alias b this; }
7042     assert(to!string(refCounted(C(B(123)))) == to!string(C(B(123))));
7043     // https://issues.dlang.org/show_bug.cgi?id=22093
7044     // Check that uninitialized refcounted structs that previously could be
7045     // converted to strings still can be.
7046     alias R = typeof(r);
7047     R r2;
7048     cast(void) (((const ref R a) => to!string(a))(r2));
7049     cast(void) to!string(RefCounted!(A, RefCountedAutoInitialize.no).init);
7050 }
7051 
7052 /**
7053  * Initializes a `RefCounted` with `val`. The template parameter
7054  * `T` of `RefCounted` is inferred from `val`.
7055  * This function can be used to move non-copyable values to the heap.
7056  * It also disables the `autoInit` option of `RefCounted`.
7057  *
7058  * Params:
7059  *   val = The value to be reference counted
7060  * Returns:
7061  *   An initialized `RefCounted` containing `val`.
7062  * See_Also:
7063  *   $(HTTP en.cppreference.com/w/cpp/memory/shared_ptr/make_shared, C++'s make_shared)
7064  */
7065 RefCounted!(T, RefCountedAutoInitialize.no) refCounted(T)(T val)
7066 {
7067     typeof(return) res;
7068     res._refCounted.move(val);
7069     return res;
7070 }
7071 
7072 ///
7073 @system unittest
7074 {
7075     static struct File
7076     {
7077         static size_t nDestroyed;
7078         string name;
7079         @disable this(this); // not copyable
7080         ~this() { name = null; ++nDestroyed; }
7081     }
7082 
7083     auto file = File("name");
7084     assert(file.name == "name");
7085     // file cannot be copied and has unique ownership
7086     static assert(!__traits(compiles, {auto file2 = file;}));
7087 
7088     assert(File.nDestroyed == 0);
7089 
7090     // make the file refcounted to share ownership
7091     // Note:
7092     //   We write a compound statement (brace-delimited scope) in which all `RefCounted!File` handles are created and deleted.
7093     //   This allows us to see (after the scope) what happens after all handles have been destroyed.
7094     {
7095         // We move the content of `file` to a separate (and heap-allocated) `File` object,
7096         // managed-and-accessed via one-or-multiple (initially: one) `RefCounted!File` objects ("handles").
7097         // This "moving":
7098         //   (1) invokes `file`'s destructor (=> `File.nDestroyed` is incremented from 0 to 1 and `file.name` becomes `null`);
7099         //   (2) overwrites `file` with `File.init` (=> `file.name` becomes `null`).
7100         // It appears that writing `name = null;` in the destructor is redundant,
7101         // but please note that (2) is only performed if `File` defines a destructor (or post-blit operator),
7102         // and in the absence of the `nDestroyed` instrumentation there would have been no reason to define a destructor.
7103         import std.algorithm.mutation : move;
7104         auto rcFile = refCounted(move(file));
7105         assert(rcFile.name == "name");
7106         assert(File.nDestroyed == 1);
7107         assert(file.name == null);
7108 
7109         // We create another `RefCounted!File` handle to the same separate `File` object.
7110         // While any of the handles is still alive, the `File` object is kept alive (=> `File.nDestroyed` is not modified).
7111         auto rcFile2 = rcFile;
7112         assert(rcFile.refCountedStore.refCount == 2);
7113         assert(File.nDestroyed == 1);
7114     }
7115     // The separate `File` object is deleted when the last `RefCounted!File` handle is destroyed
7116     // (i.e. at the closing brace of the compound statement above, which destroys both handles: `rcFile` and `rcFile2`)
7117     // (=> `File.nDestroyed` is incremented again, from 1 to 2):
7118     assert(File.nDestroyed == 2);
7119 }
7120 
7121 /**
7122     Creates a proxy for the value `a` that will forward all operations
7123     while disabling implicit conversions. The aliased item `a` must be
7124     an $(B lvalue). This is useful for creating a new type from the
7125     "base" type (though this is $(B not) a subtype-supertype
7126     relationship; the new type is not related to the old type in any way,
7127     by design).
7128 
7129     The new type supports all operations that the underlying type does,
7130     including all operators such as `+`, `--`, `<`, `[]`, etc.
7131 
7132     Params:
7133         a = The value to act as a proxy for all operations. It must
7134             be an lvalue.
7135  */
7136 mixin template Proxy(alias a)
7137 {
7138     private alias ValueType = typeof({ return a; }());
7139 
7140     /* Determine if 'T.a' can referenced via a const(T).
7141      * Use T* as the parameter because 'scope' inference needs a fully
7142      * analyzed T, which doesn't work when accessibleFrom() is used in a
7143      * 'static if' in the definition of Proxy or T.
7144      */
7145     private enum bool accessibleFrom(T) =
7146         is(typeof((T* self){ cast(void) mixin("(*self)."~__traits(identifier, a)); }));
7147 
7148     static if (is(typeof(this) == class))
7149     {
7150         override bool opEquals(Object o)
7151         {
7152             if (auto b = cast(typeof(this))o)
7153             {
7154                 return a == mixin("b."~__traits(identifier, a));
7155             }
7156             return false;
7157         }
7158 
7159         bool opEquals(T)(T b)
7160             if (is(ValueType : T) || is(typeof(a.opEquals(b))) || is(typeof(b.opEquals(a))))
7161         {
7162             static if (is(typeof(a.opEquals(b))))
7163                 return a.opEquals(b);
7164             else static if (is(typeof(b.opEquals(a))))
7165                 return b.opEquals(a);
7166             else
7167                 return a == b;
7168         }
7169 
7170         override int opCmp(Object o)
7171         {
7172             if (auto b = cast(typeof(this))o)
7173             {
7174                 return a < mixin("b."~__traits(identifier, a)) ? -1
7175                      : a > mixin("b."~__traits(identifier, a)) ? +1 : 0;
7176             }
7177             static if (is(ValueType == class))
7178                 return a.opCmp(o);
7179             else
7180                 throw new Exception("Attempt to compare a "~typeid(this).toString~" and a "~typeid(o).toString);
7181         }
7182 
7183         int opCmp(T)(auto ref const T b)
7184             if (is(ValueType : T) || is(typeof(a.opCmp(b))) || is(typeof(b.opCmp(a))))
7185         {
7186             static if (is(typeof(a.opCmp(b))))
7187                 return a.opCmp(b);
7188             else static if (is(typeof(b.opCmp(a))))
7189                 return -b.opCmp(a);
7190             else
7191                 return a < b ? -1 : a > b ? +1 : 0;
7192         }
7193 
7194         static if (accessibleFrom!(const typeof(this)))
7195         {
7196             override size_t toHash() const nothrow @safe
7197             {
7198                 static if (__traits(compiles, .hashOf(a)))
7199                     return .hashOf(a);
7200                 else
7201                 // Workaround for when .hashOf is not both @safe and nothrow.
7202                 {
7203                     static if (is(typeof(&a) == ValueType*))
7204                         alias v = a;
7205                     else
7206                         auto v = a; // if a is (property) function
7207                     // BUG: Improperly casts away `shared`!
7208                     return typeid(ValueType).getHash((() @trusted => cast(const void*) &v)());
7209                 }
7210             }
7211         }
7212     }
7213     else
7214     {
7215         auto ref opEquals(this X, B)(auto ref B b)
7216         {
7217             static if (is(immutable B == immutable typeof(this)))
7218             {
7219                 return a == mixin("b."~__traits(identifier, a));
7220             }
7221             else
7222                 return a == b;
7223         }
7224 
7225         auto ref opCmp(this X, B)(auto ref B b)
7226         {
7227             static if (is(typeof(a.opCmp(b))))
7228                 return a.opCmp(b);
7229             else static if (is(typeof(b.opCmp(a))))
7230                 return -b.opCmp(a);
7231             else static if (isFloatingPoint!ValueType || isFloatingPoint!B)
7232                 return a < b ? -1 : a > b ? +1 : a == b ? 0 : float.nan;
7233             else
7234                 return a < b ? -1 : (a > b);
7235         }
7236 
7237         static if (accessibleFrom!(const typeof(this)))
7238         {
7239             size_t toHash() const nothrow @safe
7240             {
7241                 static if (__traits(compiles, .hashOf(a)))
7242                     return .hashOf(a);
7243                 else
7244                 // Workaround for when .hashOf is not both @safe and nothrow.
7245                 {
7246                     static if (is(typeof(&a) == ValueType*))
7247                         alias v = a;
7248                     else
7249                         auto v = a; // if a is (property) function
7250                     // BUG: Improperly casts away `shared`!
7251                     return typeid(ValueType).getHash((() @trusted => cast(const void*) &v)());
7252                 }
7253             }
7254         }
7255     }
7256 
7257     auto ref opCall(this X, Args...)(auto ref Args args) { return a(args); }
7258 
7259     auto ref opCast(T, this X)() { return cast(T) a; }
7260 
7261     auto ref opIndex(this X, D...)(auto ref D i)               { return a[i]; }
7262     auto ref opSlice(this X      )()                           { return a[]; }
7263     auto ref opSlice(this X, B, E)(auto ref B b, auto ref E e) { return a[b .. e]; }
7264 
7265     auto ref opUnary     (string op, this X      )()                           { return mixin(op~"a"); }
7266     auto ref opIndexUnary(string op, this X, D...)(auto ref D i)               { return mixin(op~"a[i]"); }
7267     auto ref opSliceUnary(string op, this X      )()                           { return mixin(op~"a[]"); }
7268     auto ref opSliceUnary(string op, this X, B, E)(auto ref B b, auto ref E e) { return mixin(op~"a[b .. e]"); }
7269 
7270     auto ref opBinary(string op, this X, B)(auto ref B b)
7271     if (op == "in" && is(typeof(a in b)) || op != "in")
7272     {
7273         return mixin("a "~op~" b");
7274     }
7275     auto ref opBinaryRight(string op, this X, B)(auto ref B b) { return mixin("b "~op~" a"); }
7276 
7277     static if (!is(typeof(this) == class))
7278     {
7279         import std.traits;
7280         static if (isAssignable!ValueType)
7281         {
7282             auto ref opAssign(this X)(auto ref typeof(this) v)
7283             {
7284                 a = mixin("v."~__traits(identifier, a));
7285                 return this;
7286             }
7287         }
7288         else
7289         {
7290             @disable void opAssign(this X)(auto ref typeof(this) v);
7291         }
7292     }
7293 
7294     auto ref opAssign     (this X, V      )(auto ref V v) if (!is(V == typeof(this))) { return a       = v; }
7295     auto ref opIndexAssign(this X, V, D...)(auto ref V v, auto ref D i)               { return a[i]    = v; }
7296     auto ref opSliceAssign(this X, V      )(auto ref V v)                             { return a[]     = v; }
7297     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; }
7298 
7299     auto ref opOpAssign     (string op, this X, V      )(auto ref V v)
7300     {
7301         return mixin("a = a "~op~" v");
7302     }
7303     auto ref opIndexOpAssign(string op, this X, V, D...)(auto ref V v, auto ref D i)
7304     {
7305         return mixin("a[i] "   ~op~"= v");
7306     }
7307     auto ref opSliceOpAssign(string op, this X, V      )(auto ref V v)
7308     {
7309         return mixin("a[] "    ~op~"= v");
7310     }
7311     auto ref opSliceOpAssign(string op, this X, V, B, E)(auto ref V v, auto ref B b, auto ref E e)
7312     {
7313         return mixin("a[b .. e] "~op~"= v");
7314     }
7315 
7316     template opDispatch(string name)
7317     {
7318         static if (is(typeof(__traits(getMember, a, name)) == function))
7319         {
7320             // non template function
7321             auto ref opDispatch(this X, Args...)(auto ref Args args) { return mixin("a."~name~"(args)"); }
7322         }
7323         else static if (is(typeof({ enum x = mixin("a."~name); })))
7324         {
7325             // built-in type field, manifest constant, and static non-mutable field
7326             enum opDispatch = mixin("a."~name);
7327         }
7328         else static if (__traits(isTemplate, mixin("a."~name)))
7329         {
7330             // member template
7331             template opDispatch(T...)
7332             {
7333                 enum targs = T.length ? "!T" : "";
7334                 auto ref opDispatch(this X, Args...)(auto ref Args args){ return mixin("a."~name~targs~"(args)"); }
7335             }
7336         }
7337         else
7338         {
7339             // field or property function
7340             @property auto ref opDispatch(this X)()                { return mixin("a."~name);        }
7341             @property auto ref opDispatch(this X, V)(auto ref V v) { return mixin("a."~name~" = v"); }
7342         }
7343 
7344     }
7345 
7346     import std.traits : isArray;
7347 
7348     static if (isArray!ValueType)
7349     {
7350         auto opDollar() const { return a.length; }
7351     }
7352     else static if (is(typeof(a.opDollar!0)))
7353     {
7354         auto ref opDollar(size_t pos)() { return a.opDollar!pos(); }
7355     }
7356     else static if (is(typeof(a.opDollar) == function))
7357     {
7358         auto ref opDollar() { return a.opDollar(); }
7359     }
7360     else static if (is(typeof(a.opDollar)))
7361     {
7362         alias opDollar = a.opDollar;
7363     }
7364 }
7365 
7366 ///
7367 @safe unittest
7368 {
7369     struct MyInt
7370     {
7371         private int value;
7372         mixin Proxy!value;
7373 
7374         this(int n){ value = n; }
7375     }
7376 
7377     MyInt n = 10;
7378 
7379     // Enable operations that original type has.
7380     ++n;
7381     assert(n == 11);
7382     assert(n * 2 == 22);
7383 
7384     void func(int n) { }
7385 
7386     // Disable implicit conversions to original type.
7387     //int x = n;
7388     //func(n);
7389 }
7390 
7391 ///The proxied value must be an $(B lvalue).
7392 @safe unittest
7393 {
7394     struct NewIntType
7395     {
7396         //Won't work; the literal '1'
7397         //is an rvalue, not an lvalue
7398         //mixin Proxy!1;
7399 
7400         //Okay, n is an lvalue
7401         int n;
7402         mixin Proxy!n;
7403 
7404         this(int n) { this.n = n; }
7405     }
7406 
7407     NewIntType nit = 0;
7408     nit++;
7409     assert(nit == 1);
7410 
7411 
7412     struct NewObjectType
7413     {
7414         Object obj;
7415         //Ok, obj is an lvalue
7416         mixin Proxy!obj;
7417 
7418         this (Object o) { obj = o; }
7419     }
7420 
7421     NewObjectType not = new Object();
7422     assert(__traits(compiles, not.toHash()));
7423 }
7424 
7425 /**
7426     There is one exception to the fact that the new type is not related to the
7427     old type. $(DDSUBLINK spec/function,pseudo-member, Pseudo-member)
7428     functions are usable with the new type; they will be forwarded on to the
7429     proxied value.
7430  */
7431 @safe unittest
7432 {
7433     import std.math.traits : isInfinity;
7434 
7435     float f = 1.0;
7436     assert(!f.isInfinity);
7437 
7438     struct NewFloat
7439     {
7440         float _;
7441         mixin Proxy!_;
7442 
7443         this(float f) { _ = f; }
7444     }
7445 
7446     NewFloat nf = 1.0f;
7447     assert(!nf.isInfinity);
7448 }
7449 
7450 @safe unittest
7451 {
7452     static struct MyInt
7453     {
7454         private int value;
7455         mixin Proxy!value;
7456         this(int n) inout { value = n; }
7457 
7458         enum str = "str";
7459         static immutable arr = [1,2,3];
7460     }
7461 
7462     static foreach (T; AliasSeq!(MyInt, const MyInt, immutable MyInt))
7463     {{
7464         T m = 10;
7465         static assert(!__traits(compiles, { int x = m; }));
7466         static assert(!__traits(compiles, { void func(int n){} func(m); }));
7467         assert(m == 10);
7468         assert(m != 20);
7469         assert(m < 20);
7470         assert(+m == 10);
7471         assert(-m == -10);
7472         assert(cast(double) m == 10.0);
7473         assert(m + 10 == 20);
7474         assert(m - 5 == 5);
7475         assert(m * 20 == 200);
7476         assert(m / 2 == 5);
7477         assert(10 + m == 20);
7478         assert(15 - m == 5);
7479         assert(20 * m == 200);
7480         assert(50 / m == 5);
7481         static if (is(T == MyInt))  // mutable
7482         {
7483             assert(++m == 11);
7484             assert(m++ == 11); assert(m == 12);
7485             assert(--m == 11);
7486             assert(m-- == 11); assert(m == 10);
7487             m = m;
7488             m = 20; assert(m == 20);
7489         }
7490         static assert(T.max == int.max);
7491         static assert(T.min == int.min);
7492         static assert(T.init == int.init);
7493         static assert(T.str == "str");
7494         static assert(T.arr == [1,2,3]);
7495     }}
7496 }
7497 @system unittest
7498 {
7499     static struct MyArray
7500     {
7501         private int[] value;
7502         mixin Proxy!value;
7503         this(int[] arr) { value = arr; }
7504         this(immutable int[] arr) immutable { value = arr; }
7505     }
7506 
7507     static foreach (T; AliasSeq!(MyArray, const MyArray, immutable MyArray))
7508     {{
7509       static if (is(T == immutable) && !is(typeof({ T a = [1,2,3,4]; })))
7510         T a = [1,2,3,4].idup;   // workaround until qualified ctor is properly supported
7511       else
7512         T a = [1,2,3,4];
7513         assert(a == [1,2,3,4]);
7514         assert(a != [5,6,7,8]);
7515         assert(+a[0]    == 1);
7516         version (LittleEndian)
7517             assert(cast(ulong[]) a == [0x0000_0002_0000_0001, 0x0000_0004_0000_0003]);
7518         else
7519             assert(cast(ulong[]) a == [0x0000_0001_0000_0002, 0x0000_0003_0000_0004]);
7520         assert(a ~ [10,11] == [1,2,3,4,10,11]);
7521         assert(a[0]    == 1);
7522         assert(a[]     == [1,2,3,4]);
7523         assert(a[2 .. 4] == [3,4]);
7524         static if (is(T == MyArray))    // mutable
7525         {
7526             a = a;
7527             a = [5,6,7,8];  assert(a == [5,6,7,8]);
7528             a[0]     = 0;   assert(a == [0,6,7,8]);
7529             a[]      = 1;   assert(a == [1,1,1,1]);
7530             a[0 .. 3]  = 2;   assert(a == [2,2,2,1]);
7531             a[0]    += 2;   assert(a == [4,2,2,1]);
7532             a[]     *= 2;   assert(a == [8,4,4,2]);
7533             a[0 .. 2] /= 2;   assert(a == [4,2,4,2]);
7534         }
7535     }}
7536 }
7537 @system unittest
7538 {
7539     class Foo
7540     {
7541         int field;
7542 
7543         @property int val1() const { return field; }
7544         @property void val1(int n) { field = n; }
7545 
7546         @property ref int val2() { return field; }
7547 
7548         int func(int x, int y) const { return x; }
7549         void func1(ref int a) { a = 9; }
7550 
7551         T ifti1(T)(T t) { return t; }
7552         void ifti2(Args...)(Args args) { }
7553         void ifti3(T, Args...)(Args args) { }
7554 
7555         T opCast(T)(){ return T.init; }
7556 
7557         T tempfunc(T)() { return T.init; }
7558     }
7559     class Hoge
7560     {
7561         Foo foo;
7562         mixin Proxy!foo;
7563         this(Foo f) { foo = f; }
7564     }
7565 
7566     auto h = new Hoge(new Foo());
7567     int n;
7568 
7569     static assert(!__traits(compiles, { Foo f = h; }));
7570 
7571     // field
7572     h.field = 1;            // lhs of assign
7573     n = h.field;            // rhs of assign
7574     assert(h.field == 1);   // lhs of BinExp
7575     assert(1 == h.field);   // rhs of BinExp
7576     assert(n == 1);
7577 
7578     // getter/setter property function
7579     h.val1 = 4;
7580     n = h.val1;
7581     assert(h.val1 == 4);
7582     assert(4 == h.val1);
7583     assert(n == 4);
7584 
7585     // ref getter property function
7586     h.val2 = 8;
7587     n = h.val2;
7588     assert(h.val2 == 8);
7589     assert(8 == h.val2);
7590     assert(n == 8);
7591 
7592     // member function
7593     assert(h.func(2,4) == 2);
7594     h.func1(n);
7595     assert(n == 9);
7596 
7597     // IFTI
7598     assert(h.ifti1(4) == 4);
7599     h.ifti2(4);
7600     h.ifti3!int(4, 3);
7601 
7602     // https://issues.dlang.org/show_bug.cgi?id=5896 test
7603     assert(h.opCast!int() == 0);
7604     assert(cast(int) h == 0);
7605     const ih = new const Hoge(new Foo());
7606     static assert(!__traits(compiles, ih.opCast!int()));
7607     static assert(!__traits(compiles, cast(int) ih));
7608 
7609     // template member function
7610     assert(h.tempfunc!int() == 0);
7611 }
7612 
7613 @system unittest // about Proxy inside a class
7614 {
7615     class MyClass
7616     {
7617         int payload;
7618         mixin Proxy!payload;
7619         this(int i){ payload = i; }
7620         string opCall(string msg){ return msg; }
7621         int pow(int i){ return payload ^^ i; }
7622     }
7623 
7624     class MyClass2
7625     {
7626         MyClass payload;
7627         mixin Proxy!payload;
7628         this(int i){ payload = new MyClass(i); }
7629     }
7630 
7631     class MyClass3
7632     {
7633         int payload;
7634         mixin Proxy!payload;
7635         this(int i){ payload = i; }
7636     }
7637 
7638     // opEquals
7639     Object a = new MyClass(5);
7640     Object b = new MyClass(5);
7641     Object c = new MyClass2(5);
7642     Object d = new MyClass3(5);
7643     assert(a == b);
7644     assert((cast(MyClass) a) == 5);
7645     assert(5 == (cast(MyClass) b));
7646     assert(5 == cast(MyClass2) c);
7647     assert(a != d);
7648 
7649     assert(c != a);
7650     // oops! above line is unexpected, isn't it?
7651     // the reason is below.
7652     // MyClass2.opEquals knows MyClass but,
7653     // MyClass.opEquals doesn't know MyClass2.
7654     // so, c.opEquals(a) is true, but a.opEquals(c) is false.
7655     // furthermore, opEquals(T) couldn't be invoked.
7656     assert((cast(MyClass2) c) != (cast(MyClass) a));
7657 
7658     // opCmp
7659     Object e = new MyClass2(7);
7660     assert(a < cast(MyClass2) e); // OK. and
7661     assert(e > a); // OK, but...
7662     // assert(a < e); // RUNTIME ERROR!
7663     // assert((cast(MyClass) a) < e); // RUNTIME ERROR!
7664     assert(3 < cast(MyClass) a);
7665     assert((cast(MyClass2) e) < 11);
7666 
7667     // opCall
7668     assert((cast(MyClass2) e)("hello") == "hello");
7669 
7670     // opCast
7671     assert((cast(MyClass)(cast(MyClass2) c)) == a);
7672     assert((cast(int)(cast(MyClass2) c)) == 5);
7673 
7674     // opIndex
7675     class MyClass4
7676     {
7677         string payload;
7678         mixin Proxy!payload;
7679         this(string s){ payload = s; }
7680     }
7681     class MyClass5
7682     {
7683         MyClass4 payload;
7684         mixin Proxy!payload;
7685         this(string s){ payload = new MyClass4(s); }
7686     }
7687     auto f = new MyClass4("hello");
7688     assert(f[1] == 'e');
7689     auto g = new MyClass5("hello");
7690     assert(f[1] == 'e');
7691 
7692     // opSlice
7693     assert(f[2 .. 4] == "ll");
7694 
7695     // opUnary
7696     assert(-(cast(MyClass2) c) == -5);
7697 
7698     // opBinary
7699     assert((cast(MyClass) a) + (cast(MyClass2) c) == 10);
7700     assert(5 + cast(MyClass) a == 10);
7701 
7702     // opAssign
7703     (cast(MyClass2) c) = 11;
7704     assert((cast(MyClass2) c) == 11);
7705     (cast(MyClass2) c) = new MyClass(13);
7706     assert((cast(MyClass2) c) == 13);
7707 
7708     // opOpAssign
7709     assert((cast(MyClass2) c) += 4);
7710     assert((cast(MyClass2) c) == 17);
7711 
7712     // opDispatch
7713     assert((cast(MyClass2) c).pow(2) == 289);
7714 
7715     // opDollar
7716     assert(f[2..$-1] == "ll");
7717 
7718     // toHash
7719     int[Object] hash;
7720     hash[a] = 19;
7721     hash[c] = 21;
7722     assert(hash[b] == 19);
7723     assert(hash[c] == 21);
7724 }
7725 
7726 @safe unittest
7727 {
7728     struct MyInt
7729     {
7730         int payload;
7731 
7732         mixin Proxy!payload;
7733     }
7734 
7735     MyInt v;
7736     v = v;
7737 
7738     struct Foo
7739     {
7740         @disable void opAssign(typeof(this));
7741     }
7742     struct MyFoo
7743     {
7744         Foo payload;
7745 
7746         mixin Proxy!payload;
7747     }
7748     MyFoo f;
7749     static assert(!__traits(compiles, f = f));
7750 
7751     struct MyFoo2
7752     {
7753         Foo payload;
7754 
7755         mixin Proxy!payload;
7756 
7757         // override default Proxy behavior
7758         void opAssign(typeof(this) rhs){}
7759     }
7760     MyFoo2 f2;
7761     f2 = f2;
7762 }
7763 
7764 // https://issues.dlang.org/show_bug.cgi?id=8613
7765 @safe unittest
7766 {
7767     static struct Name
7768     {
7769         mixin Proxy!val;
7770         private string val;
7771         this(string s) { val = s; }
7772     }
7773 
7774     bool[Name] names;
7775     names[Name("a")] = true;
7776     bool* b = Name("a") in names;
7777 }
7778 
7779 // workaround for https://issues.dlang.org/show_bug.cgi?id=19669
7780 private enum isDIP1000 = __traits(compiles, () @safe {
7781      int x;
7782      int* p;
7783      p = &x;
7784 });
7785 // excludes struct S; it's 'mixin Proxy!foo' doesn't compile with -dip1000
7786 static if (isDIP1000) {} else
7787 @system unittest
7788 {
7789     // https://issues.dlang.org/show_bug.cgi?id=14213
7790     // using function for the payload
7791     static struct S
7792     {
7793         int foo() { return 12; }
7794         mixin Proxy!foo;
7795     }
7796     S s;
7797     assert(s + 1 == 13);
7798     assert(s * 2 == 24);
7799 }
7800 
7801 @system unittest
7802 {
7803     static class C
7804     {
7805         int foo() { return 12; }
7806         mixin Proxy!foo;
7807     }
7808     C c = new C();
7809 }
7810 
7811 // Check all floating point comparisons for both Proxy and Typedef,
7812 // also against int and a Typedef!int, to be as regression-proof
7813 // as possible. https://issues.dlang.org/show_bug.cgi?id=15561
7814 @safe unittest
7815 {
7816     static struct MyFloatImpl
7817     {
7818         float value;
7819         mixin Proxy!value;
7820     }
7821     static void allFail(T0, T1)(T0 a, T1 b)
7822     {
7823         assert(!(a == b));
7824         assert(!(a<b));
7825         assert(!(a <= b));
7826         assert(!(a>b));
7827         assert(!(a >= b));
7828     }
7829     static foreach (T1; AliasSeq!(MyFloatImpl, Typedef!float, Typedef!double,
7830         float, real, Typedef!int, int))
7831     {
7832         static foreach (T2; AliasSeq!(MyFloatImpl, Typedef!float))
7833         {{
7834             T1 a;
7835             T2 b;
7836 
7837             static if (isFloatingPoint!T1 || isFloatingPoint!(TypedefType!T1))
7838                 allFail(a, b);
7839             a = 3;
7840             allFail(a, b);
7841 
7842             b = 4;
7843             assert(a != b);
7844             assert(a<b);
7845             assert(a <= b);
7846             assert(!(a>b));
7847             assert(!(a >= b));
7848 
7849             a = 4;
7850             assert(a == b);
7851             assert(!(a<b));
7852             assert(a <= b);
7853             assert(!(a>b));
7854             assert(a >= b);
7855         }}
7856     }
7857 }
7858 
7859 /**
7860 $(B Typedef) allows the creation of a unique type which is
7861 based on an existing type. Unlike the `alias` feature,
7862 $(B Typedef) ensures the two types are not considered as equals.
7863 
7864 Params:
7865 
7866     init = Optional initial value for the new type.
7867     cookie = Optional, used to create multiple unique types which are
7868              based on the same origin type `T`
7869 
7870 Note: If a library routine cannot handle the Typedef type,
7871 you can use the `TypedefType` template to extract the
7872 type which the Typedef wraps.
7873  */
7874 struct Typedef(T, T init = T.init, string cookie=null)
7875 {
7876     private T Typedef_payload = init;
7877 
7878     // https://issues.dlang.org/show_bug.cgi?id=18415
7879     // prevent default construction if original type does too.
7880     static if ((is(T == struct) || is(T == union)) && !is(typeof({T t;})))
7881     {
7882         @disable this();
7883     }
7884 
7885     this(T init)
7886     {
7887         Typedef_payload = init;
7888     }
7889 
7890     this(Typedef tdef)
7891     {
7892         this(tdef.Typedef_payload);
7893     }
7894 
7895     // We need to add special overload for cast(Typedef!X) exp,
7896     // thus we can't simply inherit Proxy!Typedef_payload
7897     T2 opCast(T2 : Typedef!(T, Unused), this X, T, Unused...)()
7898     {
7899         return T2(cast(T) Typedef_payload);
7900     }
7901 
7902     auto ref opCast(T2, this X)()
7903     {
7904         return cast(T2) Typedef_payload;
7905     }
7906 
7907     mixin Proxy!Typedef_payload;
7908 
7909     pure nothrow @nogc @safe @property
7910     {
7911         alias TD = typeof(this);
7912         static if (isIntegral!T)
7913         {
7914             static TD min() {return TD(T.min);}
7915             static TD max() {return TD(T.max);}
7916         }
7917         else static if (isFloatingPoint!T)
7918         {
7919             static TD infinity() {return TD(T.infinity);}
7920             static TD nan() {return TD(T.nan);}
7921             static TD dig() {return TD(T.dig);}
7922             static TD epsilon() {return TD(T.epsilon);}
7923             static TD mant_dig() {return TD(T.mant_dig);}
7924             static TD max_10_exp() {return TD(T.max_10_exp);}
7925             static TD max_exp()  {return TD(T.max_exp);}
7926             static TD min_10_exp() {return TD(T.min_10_exp);}
7927             static TD min_exp() {return TD(T.min_exp);}
7928             static TD max() {return TD(T.max);}
7929             static TD min_normal() {return TD(T.min_normal);}
7930             TD re() {return TD(Typedef_payload.re);}
7931             TD im() {return TD(Typedef_payload.im);}
7932         }
7933     }
7934 
7935     /**
7936      * Convert wrapped value to a human readable string
7937      */
7938     string toString(this T)()
7939     {
7940         import std.array : appender;
7941         auto app = appender!string();
7942         auto spec = singleSpec("%s");
7943         toString(app, spec);
7944         return app.data;
7945     }
7946 
7947     /// ditto
7948     void toString(this T, W)(ref W writer, scope const ref FormatSpec!char fmt)
7949     if (isOutputRange!(W, char))
7950     {
7951         formatValue(writer, Typedef_payload, fmt);
7952     }
7953 
7954     ///
7955     @safe unittest
7956     {
7957         import std.conv : to;
7958 
7959         int i = 123;
7960         auto td = Typedef!int(i);
7961         assert(i.to!string == td.to!string);
7962     }
7963 }
7964 
7965 ///
7966 @safe unittest
7967 {
7968     alias MyInt = Typedef!int;
7969     MyInt foo = 10;
7970     foo++;
7971     assert(foo == 11);
7972 }
7973 
7974 /// custom initialization values
7975 @safe unittest
7976 {
7977     alias MyIntInit = Typedef!(int, 42);
7978     static assert(is(TypedefType!MyIntInit == int));
7979     static assert(MyIntInit() == 42);
7980 }
7981 
7982 /// Typedef creates a new type
7983 @safe unittest
7984 {
7985     alias MyInt = Typedef!int;
7986     static void takeInt(int) {}
7987     static void takeMyInt(MyInt) {}
7988 
7989     int i;
7990     takeInt(i);    // ok
7991     static assert(!__traits(compiles, takeMyInt(i)));
7992 
7993     MyInt myInt;
7994     static assert(!__traits(compiles, takeInt(myInt)));
7995     takeMyInt(myInt);  // ok
7996 }
7997 
7998 /// Use the optional `cookie` argument to create different types of the same base type
7999 @safe unittest
8000 {
8001     alias TypeInt1 = Typedef!int;
8002     alias TypeInt2 = Typedef!int;
8003 
8004     // The two Typedefs are the same type.
8005     static assert(is(TypeInt1 == TypeInt2));
8006 
8007     alias MoneyEuros = Typedef!(float, float.init, "euros");
8008     alias MoneyDollars = Typedef!(float, float.init, "dollars");
8009 
8010     // The two Typedefs are _not_ the same type.
8011     static assert(!is(MoneyEuros == MoneyDollars));
8012 }
8013 
8014 // https://issues.dlang.org/show_bug.cgi?id=12461
8015 @safe unittest
8016 {
8017     alias Int = Typedef!int;
8018 
8019     Int a, b;
8020     a += b;
8021     assert(a == 0);
8022 }
8023 
8024 /**
8025 Get the underlying type which a `Typedef` wraps.
8026 If `T` is not a `Typedef` it will alias itself to `T`.
8027 */
8028 template TypedefType(T)
8029 {
8030     static if (is(T : Typedef!Arg, Arg))
8031         alias TypedefType = Arg;
8032     else
8033         alias TypedefType = T;
8034 }
8035 
8036 ///
8037 @safe unittest
8038 {
8039     import std.conv : to;
8040 
8041     alias MyInt = Typedef!int;
8042     static assert(is(TypedefType!MyInt == int));
8043 
8044     /// Instantiating with a non-Typedef will return that type
8045     static assert(is(TypedefType!int == int));
8046 
8047     string num = "5";
8048 
8049     // extract the needed type
8050     MyInt myInt = MyInt( num.to!(TypedefType!MyInt) );
8051     assert(myInt == 5);
8052 
8053     // cast to the underlying type to get the value that's being wrapped
8054     int x = cast(TypedefType!MyInt) myInt;
8055 
8056     alias MyIntInit = Typedef!(int, 42);
8057     static assert(is(TypedefType!MyIntInit == int));
8058     static assert(MyIntInit() == 42);
8059 }
8060 
8061 @safe unittest
8062 {
8063     Typedef!int x = 10;
8064     static assert(!__traits(compiles, { int y = x; }));
8065     static assert(!__traits(compiles, { long z = x; }));
8066 
8067     Typedef!int y = 10;
8068     assert(x == y);
8069 
8070     static assert(Typedef!int.init == int.init);
8071 
8072     Typedef!(float, 1.0) z; // specifies the init
8073     assert(z == 1.0);
8074 
8075     static assert(typeof(z).init == 1.0);
8076 
8077     alias Dollar = Typedef!(int, 0, "dollar");
8078     alias Yen    = Typedef!(int, 0, "yen");
8079     static assert(!is(Dollar == Yen));
8080 
8081     Typedef!(int[3]) sa;
8082     static assert(sa.length == 3);
8083     static assert(typeof(sa).length == 3);
8084 
8085     Typedef!(int[3]) dollar1;
8086     assert(dollar1[0..$] is dollar1[0 .. 3]);
8087 
8088     Typedef!(int[]) dollar2;
8089     dollar2.length = 3;
8090     assert(dollar2[0..$] is dollar2[0 .. 3]);
8091 
8092     static struct Dollar1
8093     {
8094         static struct DollarToken {}
8095         enum opDollar = DollarToken.init;
8096         auto opSlice(size_t, DollarToken) { return 1; }
8097         auto opSlice(size_t, size_t) { return 2; }
8098     }
8099 
8100     Typedef!Dollar1 drange1;
8101     assert(drange1[0..$] == 1);
8102     assert(drange1[0 .. 1] == 2);
8103 
8104     static struct Dollar2
8105     {
8106         size_t opDollar(size_t pos)() { return pos == 0 ? 1 : 100; }
8107         size_t opIndex(size_t i, size_t j) { return i + j; }
8108     }
8109 
8110     Typedef!Dollar2 drange2;
8111     assert(drange2[$, $] == 101);
8112 
8113     static struct Dollar3
8114     {
8115         size_t opDollar() { return 123; }
8116         size_t opIndex(size_t i) { return i; }
8117     }
8118 
8119     Typedef!Dollar3 drange3;
8120     assert(drange3[$] == 123);
8121 }
8122 
8123 // https://issues.dlang.org/show_bug.cgi?id=18415
8124 @safe @nogc pure nothrow unittest
8125 {
8126     struct NoDefCtorS{@disable this();}
8127     union NoDefCtorU{@disable this();}
8128     static assert(!is(typeof({Typedef!NoDefCtorS s;})));
8129     static assert(!is(typeof({Typedef!NoDefCtorU u;})));
8130 }
8131 
8132 // https://issues.dlang.org/show_bug.cgi?id=11703
8133 @safe @nogc pure nothrow unittest
8134 {
8135     alias I = Typedef!int;
8136     static assert(is(typeof(I.min) == I));
8137     static assert(is(typeof(I.max) == I));
8138 
8139     alias F = Typedef!double;
8140     static assert(is(typeof(F.infinity) == F));
8141     static assert(is(typeof(F.epsilon) == F));
8142 
8143     F f;
8144     assert(!is(typeof(F.re).stringof == double));
8145     assert(!is(typeof(F.im).stringof == double));
8146 }
8147 
8148 @safe unittest
8149 {
8150     // https://issues.dlang.org/show_bug.cgi?id=8655
8151     import std.typecons;
8152     import std.bitmanip;
8153     static import core.stdc.config;
8154 
8155     alias c_ulong = Typedef!(core.stdc.config.c_ulong);
8156 
8157     static struct Foo
8158     {
8159         mixin(bitfields!(
8160             c_ulong, "NameOffset", 31,
8161             c_ulong, "NameIsString", 1
8162         ));
8163     }
8164 }
8165 
8166 // https://issues.dlang.org/show_bug.cgi?id=12596
8167 @safe unittest
8168 {
8169     import std.typecons;
8170     alias TD = Typedef!int;
8171     TD x = TD(1);
8172     TD y = TD(x);
8173     assert(x == y);
8174 }
8175 
8176 @safe unittest // about toHash
8177 {
8178     import std.typecons;
8179     {
8180         alias TD = Typedef!int;
8181         int[TD] td;
8182         td[TD(1)] = 1;
8183         assert(td[TD(1)] == 1);
8184     }
8185 
8186     {
8187         alias TD = Typedef!(int[]);
8188         int[TD] td;
8189         td[TD([1,2,3,4])] = 2;
8190         assert(td[TD([1,2,3,4])] == 2);
8191     }
8192 
8193     {
8194         alias TD = Typedef!(int[][]);
8195         int[TD] td;
8196         td[TD([[1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]])] = 3;
8197         assert(td[TD([[1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]])] == 3);
8198     }
8199 
8200     {
8201         struct MyStruct{ int x; }
8202         alias TD = Typedef!MyStruct;
8203         int[TD] td;
8204         td[TD(MyStruct(10))] = 4;
8205         assert(TD(MyStruct(20)) !in td);
8206         assert(td[TD(MyStruct(10))] == 4);
8207     }
8208 
8209     {
8210         static struct MyStruct2
8211         {
8212             int x;
8213             size_t toHash() const nothrow @safe { return x; }
8214             bool opEquals(ref const MyStruct2 r) const { return r.x == x; }
8215         }
8216 
8217         alias TD = Typedef!MyStruct2;
8218         int[TD] td;
8219         td[TD(MyStruct2(50))] = 5;
8220         assert(td[TD(MyStruct2(50))] == 5);
8221     }
8222 
8223     {
8224         class MyClass{}
8225         alias TD = Typedef!MyClass;
8226         int[TD] td;
8227         auto c = new MyClass;
8228         td[TD(c)] = 6;
8229         assert(TD(new MyClass) !in td);
8230         assert(td[TD(c)] == 6);
8231     }
8232 }
8233 
8234 @system unittest
8235 {
8236     alias String = Typedef!(char[]);
8237     alias CString = Typedef!(const(char)[]);
8238     CString cs = "fubar";
8239     String s = cast(String) cs;
8240     assert(cs == s);
8241     char[] s2 = cast(char[]) cs;
8242     const(char)[] cs2 = cast(const(char)[])s;
8243     assert(s2 == cs2);
8244 }
8245 
8246 @system unittest // toString
8247 {
8248     import std.meta : AliasSeq;
8249     import std.conv : to;
8250 
8251     struct TestS {}
8252     class TestC {}
8253 
8254     static foreach (T; AliasSeq!(int, bool, float, double, real,
8255                                  char, dchar, wchar,
8256                                  TestS, TestC,
8257                                  int*, int[], int[2], int[int]))
8258     {{
8259         T t;
8260 
8261         Typedef!T td;
8262         Typedef!(const T) ctd;
8263         Typedef!(immutable T) itd;
8264 
8265         assert(t.to!string() == td.to!string());
8266 
8267         static if (!(is(T == TestS) || is(T == TestC)))
8268         {
8269             assert(t.to!string() == ctd.to!string());
8270             assert(t.to!string() == itd.to!string());
8271         }
8272     }}
8273 }
8274 
8275 @safe @nogc unittest // typedef'ed type with custom operators
8276 {
8277     static struct MyInt
8278     {
8279         int value;
8280         int opCmp(MyInt other)
8281         {
8282             if (value < other.value)
8283                 return -1;
8284             return !(value == other.value);
8285         }
8286     }
8287 
8288     auto m1 = Typedef!MyInt(MyInt(1));
8289     auto m2 = Typedef!MyInt(MyInt(2));
8290     assert(m1 < m2);
8291 }
8292 
8293 /**
8294 Allocates a `class` object right inside the current scope,
8295 therefore avoiding the overhead of `new`. This facility is unsafe;
8296 it is the responsibility of the user to not escape a reference to the
8297 object outside the scope.
8298 
8299 The class destructor will be called when the result of `scoped()` is
8300 itself destroyed.
8301 
8302 Scoped class instances can be embedded in a parent `class` or `struct`,
8303 just like a child struct instance. Scoped member variables must have
8304 type `typeof(scoped!Class(args))`, and be initialized with a call to
8305 scoped. See below for an example.
8306 
8307 Note:
8308 It's illegal to move a class instance even if you are sure there
8309 are no pointers to it. As such, it is illegal to move a scoped object.
8310  */
8311 template scoped(T)
8312 if (is(T == class))
8313 {
8314     // _d_newclass now use default GC alignment (looks like (void*).sizeof * 2 for
8315     // small objects). We will just use the maximum of filed alignments.
8316     alias alignment = classInstanceAlignment!T;
8317     alias aligned = _alignUp!alignment;
8318 
8319     static struct Scoped
8320     {
8321         // Addition of `alignment` is required as `Scoped_store` can be misaligned in memory.
8322         private void[aligned(__traits(classInstanceSize, T) + size_t.sizeof) + alignment] Scoped_store = void;
8323 
8324         @property inout(T) Scoped_payload() inout
8325         {
8326             void* alignedStore = cast(void*) aligned(cast(size_t) Scoped_store.ptr);
8327             // As `Scoped` can be unaligned moved in memory class instance should be moved accordingly.
8328             immutable size_t d = alignedStore - Scoped_store.ptr;
8329             size_t* currD = cast(size_t*) &Scoped_store[$ - size_t.sizeof];
8330             if (d != *currD)
8331             {
8332                 import core.stdc.string : memmove;
8333                 memmove(alignedStore, Scoped_store.ptr + *currD, __traits(classInstanceSize, T));
8334                 *currD = d;
8335             }
8336             return cast(inout(T)) alignedStore;
8337         }
8338         alias Scoped_payload this;
8339 
8340         @disable this();
8341         @disable this(this);
8342 
8343         ~this()
8344         {
8345             // `destroy` will also write .init but we have no functions in druntime
8346             // for deterministic finalization and memory releasing for now.
8347             .destroy(Scoped_payload);
8348         }
8349     }
8350 
8351     /** Returns the _scoped object.
8352     Params: args = Arguments to pass to `T`'s constructor.
8353     */
8354     @system auto scoped(Args...)(auto ref Args args)
8355     {
8356         import core.lifetime : emplace, forward;
8357 
8358         Scoped result = void;
8359         void* alignedStore = cast(void*) aligned(cast(size_t) result.Scoped_store.ptr);
8360         immutable size_t d = alignedStore - result.Scoped_store.ptr;
8361         *cast(size_t*) &result.Scoped_store[$ - size_t.sizeof] = d;
8362         emplace!(Unqual!T)(result.Scoped_store[d .. $ - size_t.sizeof], forward!args);
8363         return result;
8364     }
8365 }
8366 
8367 ///
8368 @system unittest
8369 {
8370     class A
8371     {
8372         int x;
8373         this()     {x = 0;}
8374         this(int i){x = i;}
8375         ~this()    {}
8376     }
8377 
8378     // Standard usage, constructing A on the stack
8379     auto a1 = scoped!A();
8380     a1.x = 42;
8381 
8382     // Result of `scoped` call implicitly converts to a class reference
8383     A aRef = a1;
8384     assert(aRef.x == 42);
8385 
8386     // Scoped destruction
8387     {
8388         auto a2 = scoped!A(1);
8389         assert(a2.x == 1);
8390         aRef = a2;
8391         // a2 is destroyed here, calling A's destructor
8392     }
8393     // aRef is now an invalid reference
8394 
8395     // Here the temporary scoped A is immediately destroyed.
8396     // This means the reference is then invalid.
8397     version (Bug)
8398     {
8399         // Wrong, should use `auto`
8400         A invalid = scoped!A();
8401     }
8402 
8403     // Restrictions
8404     version (Bug)
8405     {
8406         import std.algorithm.mutation : move;
8407         auto invalid = a1.move; // illegal, scoped objects can't be moved
8408     }
8409     static assert(!is(typeof({
8410         auto e1 = a1; // illegal, scoped objects can't be copied
8411         assert([a1][0].x == 42); // ditto
8412     })));
8413     static assert(!is(typeof({
8414         alias ScopedObject = typeof(a1);
8415         auto e2 = ScopedObject();  // illegal, must be built via scoped!A
8416         auto e3 = ScopedObject(1); // ditto
8417     })));
8418 
8419     // Use with alias
8420     alias makeScopedA = scoped!A;
8421     auto a3 = makeScopedA();
8422     auto a4 = makeScopedA(1);
8423 
8424     // Use as member variable
8425     struct B
8426     {
8427         typeof(scoped!A()) a; // note the trailing parentheses
8428 
8429         this(int i)
8430         {
8431             // construct member
8432             a = scoped!A(i);
8433         }
8434     }
8435 
8436     // Stack-allocate
8437     auto b1 = B(5);
8438     aRef = b1.a;
8439     assert(aRef.x == 5);
8440     destroy(b1); // calls A's destructor for b1.a
8441     // aRef is now an invalid reference
8442 
8443     // Heap-allocate
8444     auto b2 = new B(6);
8445     assert(b2.a.x == 6);
8446     destroy(*b2); // calls A's destructor for b2.a
8447 }
8448 
8449 private size_t _alignUp(size_t alignment)(size_t n)
8450 if (alignment > 0 && !((alignment - 1) & alignment))
8451 {
8452     enum badEnd = alignment - 1; // 0b11, 0b111, ...
8453     return (n + badEnd) & ~badEnd;
8454 }
8455 
8456 // https://issues.dlang.org/show_bug.cgi?id=6580 testcase
8457 @system unittest
8458 {
8459     enum alignment = (void*).alignof;
8460 
8461     static class C0 { }
8462     static class C1 { byte b; }
8463     static class C2 { byte[2] b; }
8464     static class C3 { byte[3] b; }
8465     static class C7 { byte[7] b; }
8466     static assert(scoped!C0().sizeof % alignment == 0);
8467     static assert(scoped!C1().sizeof % alignment == 0);
8468     static assert(scoped!C2().sizeof % alignment == 0);
8469     static assert(scoped!C3().sizeof % alignment == 0);
8470     static assert(scoped!C7().sizeof % alignment == 0);
8471 
8472     enum longAlignment = long.alignof;
8473     static class C1long
8474     {
8475         long long_; byte byte_ = 4;
8476         this() { }
8477         this(long _long, ref int i) { long_ = _long; ++i; }
8478     }
8479     static class C2long { byte[2] byte_ = [5, 6]; long long_ = 7; }
8480     static assert(scoped!C1long().sizeof % longAlignment == 0);
8481     static assert(scoped!C2long().sizeof % longAlignment == 0);
8482 
8483     void alignmentTest()
8484     {
8485         int var = 5;
8486         auto c1long = scoped!C1long(3, var);
8487         assert(var == 6);
8488         auto c2long = scoped!C2long();
8489         assert(cast(uint)&c1long.long_ % longAlignment == 0);
8490         assert(cast(uint)&c2long.long_ % longAlignment == 0);
8491         assert(c1long.long_ == 3 && c1long.byte_ == 4);
8492         assert(c2long.byte_ == [5, 6] && c2long.long_ == 7);
8493     }
8494 
8495     alignmentTest();
8496 
8497     version (DigitalMars)
8498     {
8499         void test(size_t size)
8500         {
8501             import core.stdc.stdlib;
8502             cast(void) alloca(size);
8503             alignmentTest();
8504         }
8505         foreach (i; 0 .. 10)
8506             test(i);
8507     }
8508     else
8509     {
8510         void test(size_t size)()
8511         {
8512             byte[size] arr;
8513             alignmentTest();
8514         }
8515         static foreach (i; 0 .. 11)
8516             test!i();
8517     }
8518 }
8519 
8520 // Original https://issues.dlang.org/show_bug.cgi?id=6580 testcase
8521 @system unittest
8522 {
8523     class C { int i; byte b; }
8524 
8525     auto sa = [scoped!C(), scoped!C()];
8526     assert(cast(uint)&sa[0].i % int.alignof == 0);
8527     assert(cast(uint)&sa[1].i % int.alignof == 0); // fails
8528 }
8529 
8530 @system unittest
8531 {
8532     class A { int x = 1; }
8533     auto a1 = scoped!A();
8534     assert(a1.x == 1);
8535     auto a2 = scoped!A();
8536     a1.x = 42;
8537     a2.x = 53;
8538     assert(a1.x == 42);
8539 }
8540 
8541 @system unittest
8542 {
8543     class A { int x = 1; this() { x = 2; } }
8544     auto a1 = scoped!A();
8545     assert(a1.x == 2);
8546     auto a2 = scoped!A();
8547     a1.x = 42;
8548     a2.x = 53;
8549     assert(a1.x == 42);
8550 }
8551 
8552 @system unittest
8553 {
8554     class A { int x = 1; this(int y) { x = y; } ~this() {} }
8555     auto a1 = scoped!A(5);
8556     assert(a1.x == 5);
8557     auto a2 = scoped!A(42);
8558     a1.x = 42;
8559     a2.x = 53;
8560     assert(a1.x == 42);
8561 }
8562 
8563 @system unittest
8564 {
8565     class A { static bool dead; ~this() { dead = true; } }
8566     class B : A { static bool dead; ~this() { dead = true; } }
8567     {
8568         auto b = scoped!B();
8569     }
8570     assert(B.dead, "asdasd");
8571     assert(A.dead, "asdasd");
8572 }
8573 
8574 // https://issues.dlang.org/show_bug.cgi?id=8039 testcase
8575 @system unittest
8576 {
8577     static int dels;
8578     static struct S { ~this(){ ++dels; } }
8579 
8580     static class A { S s; }
8581     dels = 0; { scoped!A(); }
8582     assert(dels == 1);
8583 
8584     static class B { S[2] s; }
8585     dels = 0; { scoped!B(); }
8586     assert(dels == 2);
8587 
8588     static struct S2 { S[3] s; }
8589     static class C { S2[2] s; }
8590     dels = 0; { scoped!C(); }
8591     assert(dels == 6);
8592 
8593     static class D: A { S2[2] s; }
8594     dels = 0; { scoped!D(); }
8595     assert(dels == 1+6);
8596 }
8597 
8598 @system unittest
8599 {
8600     // https://issues.dlang.org/show_bug.cgi?id=4500
8601     class A
8602     {
8603         this() { a = this; }
8604         this(int i) { a = this; }
8605         A a;
8606         bool check() { return this is a; }
8607     }
8608 
8609     auto a1 = scoped!A();
8610     assert(a1.check());
8611 
8612     auto a2 = scoped!A(1);
8613     assert(a2.check());
8614 
8615     a1.a = a1;
8616     assert(a1.check());
8617 }
8618 
8619 @system unittest
8620 {
8621     static class A
8622     {
8623         static int sdtor;
8624 
8625         this() { ++sdtor; assert(sdtor == 1); }
8626         ~this() { assert(sdtor == 1); --sdtor; }
8627     }
8628 
8629     interface Bob {}
8630 
8631     static class ABob : A, Bob
8632     {
8633         this() { ++sdtor; assert(sdtor == 2); }
8634         ~this() { assert(sdtor == 2); --sdtor; }
8635     }
8636 
8637     A.sdtor = 0;
8638     scope(exit) assert(A.sdtor == 0);
8639     auto abob = scoped!ABob();
8640 }
8641 
8642 @safe unittest
8643 {
8644     static class A { this(int) {} }
8645     static assert(!__traits(compiles, scoped!A()));
8646 }
8647 
8648 @system unittest
8649 {
8650     static class A { @property inout(int) foo() inout { return 1; } }
8651 
8652     auto a1 = scoped!A();
8653     assert(a1.foo == 1);
8654     static assert(is(typeof(a1.foo) == int));
8655 
8656     auto a2 = scoped!(const(A))();
8657     assert(a2.foo == 1);
8658     static assert(is(typeof(a2.foo) == const(int)));
8659 
8660     auto a3 = scoped!(immutable(A))();
8661     assert(a3.foo == 1);
8662     static assert(is(typeof(a3.foo) == immutable(int)));
8663 
8664     const c1 = scoped!A();
8665     assert(c1.foo == 1);
8666     static assert(is(typeof(c1.foo) == const(int)));
8667 
8668     const c2 = scoped!(const(A))();
8669     assert(c2.foo == 1);
8670     static assert(is(typeof(c2.foo) == const(int)));
8671 
8672     const c3 = scoped!(immutable(A))();
8673     assert(c3.foo == 1);
8674     static assert(is(typeof(c3.foo) == immutable(int)));
8675 }
8676 
8677 @system unittest
8678 {
8679     class C
8680     {
8681         this(int rval) { assert(rval == 1); }
8682         this(ref int lval) { assert(lval == 3); ++lval; }
8683     }
8684 
8685     auto c1 = scoped!C(1);
8686     int lval = 3;
8687     auto c2 = scoped!C(lval);
8688     assert(lval == 4);
8689 }
8690 
8691 @system unittest
8692 {
8693     class C
8694     {
8695         this(){}
8696         this(int){}
8697         this(int, int){}
8698     }
8699     alias makeScopedC = scoped!C;
8700 
8701     auto a = makeScopedC();
8702     auto b = makeScopedC(1);
8703     auto c = makeScopedC(1, 1);
8704 
8705     static assert(is(typeof(a) == typeof(b)));
8706     static assert(is(typeof(b) == typeof(c)));
8707 }
8708 
8709 /**
8710 Defines a simple, self-documenting yes/no flag. This makes it easy for
8711 APIs to define functions accepting flags without resorting to $(D
8712 bool), which is opaque in calls, and without needing to define an
8713 enumerated type separately. Using `Flag!"Name"` instead of $(D
8714 bool) makes the flag's meaning visible in calls. Each yes/no flag has
8715 its own type, which makes confusions and mix-ups impossible.
8716 
8717 Example:
8718 
8719 Code calling `getLine` (usually far away from its definition) can't be
8720 understood without looking at the documentation, even by users familiar with
8721 the API:
8722 ----
8723 string getLine(bool keepTerminator)
8724 {
8725     ...
8726     if (keepTerminator) ...
8727     ...
8728 }
8729 ...
8730 auto line = getLine(false);
8731 ----
8732 
8733 Assuming the reverse meaning (i.e. "ignoreTerminator") and inserting the wrong
8734 code compiles and runs with erroneous results.
8735 
8736 After replacing the boolean parameter with an instantiation of `Flag`, code
8737 calling `getLine` can be easily read and understood even by people not
8738 fluent with the API:
8739 
8740 ----
8741 string getLine(Flag!"keepTerminator" keepTerminator)
8742 {
8743     ...
8744     if (keepTerminator) ...
8745     ...
8746 }
8747 ...
8748 auto line = getLine(Yes.keepTerminator);
8749 ----
8750 
8751 The structs `Yes` and `No` are provided as shorthand for
8752 `Flag!"Name".yes` and `Flag!"Name".no` and are preferred for brevity and
8753 readability. These convenience structs mean it is usually unnecessary and
8754 counterproductive to create an alias of a `Flag` as a way of avoiding typing
8755 out the full type while specifying the affirmative or negative options.
8756 
8757 Passing categorical data by means of unstructured `bool`
8758 parameters is classified under "simple-data coupling" by Steve
8759 McConnell in the $(LUCKY Code Complete) book, along with three other
8760 kinds of coupling. The author argues citing several studies that
8761 coupling has a negative effect on code quality. `Flag` offers a
8762 simple structuring method for passing yes/no flags to APIs.
8763  */
8764 template Flag(string name) {
8765     ///
8766     enum Flag : bool
8767     {
8768         /**
8769          When creating a value of type `Flag!"Name"`, use $(D
8770          Flag!"Name".no) for the negative option. When using a value
8771          of type `Flag!"Name"`, compare it against $(D
8772          Flag!"Name".no) or just `false` or `0`.  */
8773         no = false,
8774 
8775         /** When creating a value of type `Flag!"Name"`, use $(D
8776          Flag!"Name".yes) for the affirmative option. When using a
8777          value of type `Flag!"Name"`, compare it against $(D
8778          Flag!"Name".yes).
8779         */
8780         yes = true
8781     }
8782 }
8783 
8784 ///
8785 @safe unittest
8786 {
8787     Flag!"abc" flag;
8788 
8789     assert(flag == Flag!"abc".no);
8790     assert(flag == No.abc);
8791     assert(!flag);
8792     if (flag) assert(0);
8793 }
8794 
8795 ///
8796 @safe unittest
8797 {
8798     auto flag = Yes.abc;
8799 
8800     assert(flag);
8801     assert(flag == Yes.abc);
8802     if (!flag) assert(0);
8803     if (flag) {} else assert(0);
8804 }
8805 
8806 /**
8807 Convenience names that allow using e.g. `Yes.encryption` instead of
8808 `Flag!"encryption".yes` and `No.encryption` instead of $(D
8809 Flag!"encryption".no).
8810 */
8811 struct Yes
8812 {
8813     template opDispatch(string name)
8814     {
8815         enum opDispatch = Flag!name.yes;
8816     }
8817 }
8818 //template yes(string name) { enum Flag!name yes = Flag!name.yes; }
8819 
8820 /// Ditto
8821 struct No
8822 {
8823     template opDispatch(string name)
8824     {
8825         enum opDispatch = Flag!name.no;
8826     }
8827 }
8828 
8829 ///
8830 @safe unittest
8831 {
8832     Flag!"abc" flag;
8833 
8834     assert(flag == Flag!"abc".no);
8835     assert(flag == No.abc);
8836     assert(!flag);
8837     if (flag) assert(0);
8838 }
8839 
8840 ///
8841 @safe unittest
8842 {
8843     auto flag = Yes.abc;
8844 
8845     assert(flag);
8846     assert(flag == Yes.abc);
8847     if (!flag) assert(0);
8848     if (flag) {} else assert(0);
8849 }
8850 
8851 /**
8852 Detect whether an enum is of integral type and has only "flag" values
8853 (i.e. values with a bit count of exactly 1).
8854 Additionally, a zero value is allowed for compatibility with enums including
8855 a "None" value.
8856 */
8857 template isBitFlagEnum(E)
8858 {
8859     static if (is(E Base == enum) && isIntegral!Base)
8860     {
8861         enum isBitFlagEnum = (E.min >= 0) &&
8862         {
8863             static foreach (immutable flag; EnumMembers!E)
8864             {{
8865                 Base value = flag;
8866                 value &= value - 1;
8867                 if (value != 0) return false;
8868             }}
8869             return true;
8870         }();
8871     }
8872     else
8873     {
8874         enum isBitFlagEnum = false;
8875     }
8876 }
8877 
8878 ///
8879 @safe pure nothrow unittest
8880 {
8881     enum A
8882     {
8883         None,
8884         A = 1 << 0,
8885         B = 1 << 1,
8886         C = 1 << 2,
8887         D = 1 << 3,
8888     }
8889 
8890     static assert(isBitFlagEnum!A);
8891 }
8892 
8893 /// Test an enum with default (consecutive) values
8894 @safe pure nothrow unittest
8895 {
8896     enum B
8897     {
8898         A,
8899         B,
8900         C,
8901         D // D == 3
8902     }
8903 
8904     static assert(!isBitFlagEnum!B);
8905 }
8906 
8907 /// Test an enum with non-integral values
8908 @safe pure nothrow unittest
8909 {
8910     enum C: double
8911     {
8912         A = 1 << 0,
8913         B = 1 << 1
8914     }
8915 
8916     static assert(!isBitFlagEnum!C);
8917 }
8918 
8919 /**
8920 A typesafe structure for storing combinations of enum values.
8921 
8922 This template defines a simple struct to represent bitwise OR combinations of
8923 enum values. It can be used if all the enum values are integral constants with
8924 a bit count of at most 1, or if the `unsafe` parameter is explicitly set to
8925 Yes.
8926 This is much safer than using the enum itself to store
8927 the OR combination, which can produce surprising effects like this:
8928 ----
8929 enum E
8930 {
8931     A = 1 << 0,
8932     B = 1 << 1
8933 }
8934 E e = E.A | E.B;
8935 // will throw SwitchError
8936 final switch (e)
8937 {
8938     case E.A:
8939         return;
8940     case E.B:
8941         return;
8942 }
8943 ----
8944 */
8945 struct BitFlags(E, Flag!"unsafe" unsafe = No.unsafe)
8946 if (unsafe || isBitFlagEnum!(E))
8947 {
8948 @safe @nogc pure nothrow:
8949 private:
8950     enum isBaseEnumType(T) = is(E == T);
8951     alias Base = OriginalType!E;
8952     Base mValue;
8953 
8954 public:
8955     this(E flag)
8956     {
8957         this = flag;
8958     }
8959 
8960     this(T...)(T flags)
8961         if (allSatisfy!(isBaseEnumType, T))
8962     {
8963         this = flags;
8964     }
8965 
8966     bool opCast(B: bool)() const
8967     {
8968         return mValue != 0;
8969     }
8970 
8971     Base opCast(B)() const
8972         if (isImplicitlyConvertible!(Base, B))
8973     {
8974         return mValue;
8975     }
8976 
8977     auto opUnary(string op)() const
8978         if (op == "~")
8979     {
8980         return BitFlags(cast(E) cast(Base) ~mValue);
8981     }
8982 
8983     auto ref opAssign(T...)(T flags)
8984         if (allSatisfy!(isBaseEnumType, T))
8985     {
8986         mValue = 0;
8987         foreach (E flag; flags)
8988         {
8989             mValue |= flag;
8990         }
8991         return this;
8992     }
8993 
8994     auto ref opAssign(E flag)
8995     {
8996         mValue = flag;
8997         return this;
8998     }
8999 
9000     auto ref opOpAssign(string op: "|")(BitFlags flags)
9001     {
9002         mValue |= flags.mValue;
9003         return this;
9004     }
9005 
9006     auto ref opOpAssign(string op: "&")(BitFlags  flags)
9007     {
9008         mValue &= flags.mValue;
9009         return this;
9010     }
9011 
9012     auto ref opOpAssign(string op: "|")(E flag)
9013     {
9014         mValue |= flag;
9015         return this;
9016     }
9017 
9018     auto ref opOpAssign(string op: "&")(E flag)
9019     {
9020         mValue &= flag;
9021         return this;
9022     }
9023 
9024     auto opBinary(string op)(BitFlags flags) const
9025         if (op == "|" || op == "&")
9026     {
9027         BitFlags result = this;
9028         result.opOpAssign!op(flags);
9029         return result;
9030     }
9031 
9032     auto opBinary(string op)(E flag) const
9033         if (op == "|" || op == "&")
9034     {
9035         BitFlags result = this;
9036         result.opOpAssign!op(flag);
9037         return result;
9038     }
9039 
9040     auto opBinaryRight(string op)(E flag) const
9041         if (op == "|" || op == "&")
9042     {
9043         return opBinary!op(flag);
9044     }
9045 
9046     bool opDispatch(string name)() const
9047     if (__traits(hasMember, E, name))
9048     {
9049         enum e = __traits(getMember, E, name);
9050         return (mValue & e) == e;
9051     }
9052 
9053     void opDispatch(string name)(bool set)
9054     if (__traits(hasMember, E, name))
9055     {
9056         enum e = __traits(getMember, E, name);
9057         if (set)
9058             mValue |= e;
9059         else
9060             mValue &= ~e;
9061     }
9062 }
9063 
9064 /// Set values with the | operator and test with &
9065 @safe @nogc pure nothrow unittest
9066 {
9067     enum Enum
9068     {
9069         A = 1 << 0,
9070     }
9071 
9072     // A default constructed BitFlags has no value set
9073     immutable BitFlags!Enum flags_empty;
9074     assert(!flags_empty.A);
9075 
9076     // Value can be set with the | operator
9077     immutable flags_A = flags_empty | Enum.A;
9078 
9079     // and tested using property access
9080     assert(flags_A.A);
9081 
9082     // or the & operator
9083     assert(flags_A & Enum.A);
9084     // which commutes.
9085     assert(Enum.A & flags_A);
9086 }
9087 
9088 /// A default constructed BitFlags has no value set
9089 @safe @nogc pure nothrow unittest
9090 {
9091     enum Enum
9092     {
9093         None,
9094         A = 1 << 0,
9095         B = 1 << 1,
9096         C = 1 << 2
9097     }
9098 
9099     immutable BitFlags!Enum flags_empty;
9100     assert(!(flags_empty & (Enum.A | Enum.B | Enum.C)));
9101     assert(!(flags_empty & Enum.A) && !(flags_empty & Enum.B) && !(flags_empty & Enum.C));
9102 }
9103 
9104 // BitFlags can be variadically initialized
9105 @safe @nogc pure nothrow unittest
9106 {
9107     import std.traits : EnumMembers;
9108 
9109     enum Enum
9110     {
9111         A = 1 << 0,
9112         B = 1 << 1,
9113         C = 1 << 2
9114     }
9115 
9116     // Values can also be set using property access
9117     BitFlags!Enum flags;
9118     flags.A = true;
9119     assert(flags & Enum.A);
9120     flags.A = false;
9121     assert(!(flags & Enum.A));
9122 
9123     // BitFlags can be variadically initialized
9124     immutable BitFlags!Enum flags_AB = BitFlags!Enum(Enum.A, Enum.B);
9125     assert(flags_AB.A && flags_AB.B && !flags_AB.C);
9126 
9127     // You can use the EnumMembers template to set all flags
9128     immutable BitFlags!Enum flags_all = EnumMembers!Enum;
9129     assert(flags_all.A && flags_all.B && flags_all.C);
9130 }
9131 
9132 /// Binary operations: subtracting and intersecting flags
9133 @safe @nogc pure nothrow unittest
9134 {
9135     enum Enum
9136     {
9137         A = 1 << 0,
9138         B = 1 << 1,
9139         C = 1 << 2,
9140     }
9141     immutable BitFlags!Enum flags_AB = BitFlags!Enum(Enum.A, Enum.B);
9142     immutable BitFlags!Enum flags_BC = BitFlags!Enum(Enum.B, Enum.C);
9143 
9144     // Use the ~ operator for subtracting flags
9145     immutable BitFlags!Enum flags_B = flags_AB & ~BitFlags!Enum(Enum.A);
9146     assert(!flags_B.A && flags_B.B && !flags_B.C);
9147 
9148     // use & between BitFlags for intersection
9149     assert(flags_B == (flags_BC & flags_AB));
9150 }
9151 
9152 /// All the binary operators work in their assignment version
9153 @safe @nogc pure nothrow unittest
9154 {
9155     enum Enum
9156     {
9157         A = 1 << 0,
9158         B = 1 << 1,
9159     }
9160 
9161     BitFlags!Enum flags_empty, temp, flags_AB;
9162     flags_AB = Enum.A | Enum.B;
9163 
9164     temp |= flags_AB;
9165     assert(temp == (flags_empty | flags_AB));
9166 
9167     temp = flags_empty;
9168     temp |= Enum.B;
9169     assert(temp == (flags_empty | Enum.B));
9170 
9171     temp = flags_empty;
9172     temp &= flags_AB;
9173     assert(temp == (flags_empty & flags_AB));
9174 
9175     temp = flags_empty;
9176     temp &= Enum.A;
9177     assert(temp == (flags_empty & Enum.A));
9178 }
9179 
9180 /// Conversion to bool and int
9181 @safe @nogc pure nothrow unittest
9182 {
9183     enum Enum
9184     {
9185         A = 1 << 0,
9186         B = 1 << 1,
9187     }
9188 
9189     BitFlags!Enum flags;
9190 
9191     // BitFlags with no value set evaluate to false
9192     assert(!flags);
9193 
9194     // BitFlags with at least one value set evaluate to true
9195     flags |= Enum.A;
9196     assert(flags);
9197 
9198     // This can be useful to check intersection between BitFlags
9199     BitFlags!Enum flags_AB = Enum.A | Enum.B;
9200     assert(flags & flags_AB);
9201     assert(flags & Enum.A);
9202 
9203     // You can of course get you raw value out of flags
9204     auto value = cast(int) flags;
9205     assert(value == Enum.A);
9206 }
9207 
9208 /// You need to specify the `unsafe` parameter for enums with custom values
9209 @safe @nogc pure nothrow unittest
9210 {
9211     enum UnsafeEnum
9212     {
9213         A = 1,
9214         B = 2,
9215         C = 4,
9216         BC = B|C
9217     }
9218     static assert(!__traits(compiles, { BitFlags!UnsafeEnum flags; }));
9219     BitFlags!(UnsafeEnum, Yes.unsafe) flags;
9220 
9221     // property access tests for exact match of unsafe enums
9222     flags.B = true;
9223     assert(!flags.BC); // only B
9224     flags.C = true;
9225     assert(flags.BC); // both B and C
9226     flags.B = false;
9227     assert(!flags.BC); // only C
9228 
9229     // property access sets all bits of unsafe enum group
9230     flags = flags.init;
9231     flags.BC = true;
9232     assert(!flags.A && flags.B && flags.C);
9233     flags.A = true;
9234     flags.BC = false;
9235     assert(flags.A && !flags.B && !flags.C);
9236 }
9237 
9238 // Negation of BitFlags should work with any base type.
9239 // Double-negation of BitFlags should work.
9240 @safe @nogc pure nothrow unittest
9241 {
9242     static foreach (alias Base; AliasSeq!(
9243         byte,
9244         ubyte,
9245         short,
9246         ushort,
9247         int,
9248         uint,
9249         long,
9250         ulong,
9251     ))
9252     {{
9253         enum Enum : Base
9254         {
9255             A = 1 << 0,
9256             B = 1 << 1,
9257             C = 1 << 2,
9258         }
9259 
9260         auto flags = BitFlags!Enum(Enum.A);
9261 
9262         assert(flags == ~~flags);
9263     }}
9264 }
9265 
9266 private enum false_(T) = false;
9267 
9268 // ReplaceType
9269 /**
9270 Replaces all occurrences of `From` into `To`, in one or more types `T`. For
9271 example, `ReplaceType!(int, uint, Tuple!(int, float)[string])` yields
9272 `Tuple!(uint, float)[string]`. The types in which replacement is performed
9273 may be arbitrarily complex, including qualifiers, built-in type constructors
9274 (pointers, arrays, associative arrays, functions, and delegates), and template
9275 instantiations; replacement proceeds transitively through the type definition.
9276 However, member types in `struct`s or `class`es are not replaced because there
9277 are no ways to express the types resulting after replacement.
9278 
9279 This is an advanced type manipulation necessary e.g. for replacing the
9280 placeholder type `This` in $(REF Algebraic, std,variant).
9281 
9282 Returns: `ReplaceType` aliases itself to the type(s) that result after
9283 replacement.
9284 */
9285 alias ReplaceType(From, To, T...) = ReplaceTypeUnless!(false_, From, To, T);
9286 
9287 ///
9288 @safe unittest
9289 {
9290     static assert(
9291         is(ReplaceType!(int, string, int[]) == string[]) &&
9292         is(ReplaceType!(int, string, int[int]) == string[string]) &&
9293         is(ReplaceType!(int, string, const(int)[]) == const(string)[]) &&
9294         is(ReplaceType!(int, string, Tuple!(int[], float))
9295             == Tuple!(string[], float))
9296     );
9297 }
9298 
9299 /**
9300 Like $(LREF ReplaceType), but does not perform replacement in types for which
9301 `pred` evaluates to `true`.
9302 */
9303 template ReplaceTypeUnless(alias pred, From, To, T...)
9304 {
9305     import std.meta;
9306 
9307     static if (T.length == 1)
9308     {
9309         static if (pred!(T[0]))
9310             alias ReplaceTypeUnless = T[0];
9311         else static if (is(T[0] == From))
9312             alias ReplaceTypeUnless = To;
9313         else static if (is(T[0] == const(U), U))
9314             alias ReplaceTypeUnless = const(ReplaceTypeUnless!(pred, From, To, U));
9315         else static if (is(T[0] == immutable(U), U))
9316             alias ReplaceTypeUnless = immutable(ReplaceTypeUnless!(pred, From, To, U));
9317         else static if (is(T[0] == shared(U), U))
9318             alias ReplaceTypeUnless = shared(ReplaceTypeUnless!(pred, From, To, U));
9319         else static if (is(T[0] == U*, U))
9320         {
9321             static if (is(U == function))
9322                 alias ReplaceTypeUnless = replaceTypeInFunctionTypeUnless!(pred, From, To, T[0]);
9323             else
9324                 alias ReplaceTypeUnless = ReplaceTypeUnless!(pred, From, To, U)*;
9325         }
9326         else static if (is(T[0] == delegate))
9327         {
9328             alias ReplaceTypeUnless = replaceTypeInFunctionTypeUnless!(pred, From, To, T[0]);
9329         }
9330         else static if (is(T[0] == function))
9331         {
9332             static assert(0, "Function types not supported," ~
9333                 " use a function pointer type instead of " ~ T[0].stringof);
9334         }
9335         else static if (is(T[0] == U!V, alias U, V...))
9336         {
9337             template replaceTemplateArgs(T...)
9338             {
9339                 static if (is(typeof(T[0]))) {   // template argument is value or symbol
9340                     static if (__traits(compiles, { alias _ = T[0]; }))
9341                         // it's a symbol
9342                         alias replaceTemplateArgs = T[0];
9343                     else
9344                         // it's a value
9345                         enum replaceTemplateArgs = T[0];
9346                 } else
9347                     alias replaceTemplateArgs = ReplaceTypeUnless!(pred, From, To, T[0]);
9348             }
9349             alias ReplaceTypeUnless = U!(staticMap!(replaceTemplateArgs, V));
9350         }
9351         else static if (is(T[0] == struct))
9352             // don't match with alias this struct below
9353             // https://issues.dlang.org/show_bug.cgi?id=15168
9354             alias ReplaceTypeUnless = T[0];
9355         else static if (is(T[0] == U[], U))
9356             alias ReplaceTypeUnless = ReplaceTypeUnless!(pred, From, To, U)[];
9357         else static if (is(T[0] == U[n], U, size_t n))
9358             alias ReplaceTypeUnless = ReplaceTypeUnless!(pred, From, To, U)[n];
9359         else static if (is(T[0] == U[V], U, V))
9360             alias ReplaceTypeUnless =
9361                 ReplaceTypeUnless!(pred, From, To, U)[ReplaceTypeUnless!(pred, From, To, V)];
9362         else
9363             alias ReplaceTypeUnless = T[0];
9364     }
9365     else static if (T.length > 1)
9366     {
9367         alias ReplaceTypeUnless = AliasSeq!(ReplaceTypeUnless!(pred, From, To, T[0]),
9368             ReplaceTypeUnless!(pred, From, To, T[1 .. $]));
9369     }
9370     else
9371     {
9372         alias ReplaceTypeUnless = AliasSeq!();
9373     }
9374 }
9375 
9376 ///
9377 @safe unittest
9378 {
9379     import std.traits : isArray;
9380 
9381     static assert(
9382         is(ReplaceTypeUnless!(isArray, int, string, int*) == string*) &&
9383         is(ReplaceTypeUnless!(isArray, int, string, int[]) == int[]) &&
9384         is(ReplaceTypeUnless!(isArray, int, string, Tuple!(int, int[]))
9385             == Tuple!(string, int[]))
9386    );
9387 }
9388 
9389 private template replaceTypeInFunctionTypeUnless(alias pred, From, To, fun)
9390 {
9391     alias RX = ReplaceTypeUnless!(pred, From, To, ReturnType!fun);
9392     alias PX = AliasSeq!(ReplaceTypeUnless!(pred, From, To, Parameters!fun));
9393     // Wrapping with AliasSeq is neccesary because ReplaceType doesn't return
9394     // tuple if Parameters!fun.length == 1
9395 
9396     string gen()
9397     {
9398         enum  linkage = functionLinkage!fun;
9399         alias attributes = functionAttributes!fun;
9400         enum  variadicStyle = variadicFunctionStyle!fun;
9401         alias storageClasses = ParameterStorageClassTuple!fun;
9402 
9403         string result;
9404 
9405         result ~= "extern(" ~ linkage ~ ") ";
9406         static if (attributes & FunctionAttribute.ref_)
9407         {
9408             result ~= "ref ";
9409         }
9410 
9411         result ~= "RX";
9412         static if (is(fun == delegate))
9413             result ~= " delegate";
9414         else
9415             result ~= " function";
9416 
9417         result ~= "(";
9418         static foreach (i; 0 .. PX.length)
9419         {
9420             if (i)
9421                 result ~= ", ";
9422             if (storageClasses[i] & ParameterStorageClass.scope_)
9423                 result ~= "scope ";
9424             if (storageClasses[i] & ParameterStorageClass.in_)
9425                 result ~= "in ";
9426             if (storageClasses[i] & ParameterStorageClass.out_)
9427                 result ~= "out ";
9428             if (storageClasses[i] & ParameterStorageClass.ref_)
9429                 result ~= "ref ";
9430             if (storageClasses[i] & ParameterStorageClass.lazy_)
9431                 result ~= "lazy ";
9432             if (storageClasses[i] & ParameterStorageClass.return_)
9433                 result ~= "return ";
9434 
9435             result ~= "PX[" ~ i.stringof ~ "]";
9436         }
9437         static if (variadicStyle == Variadic.typesafe)
9438             result ~= " ...";
9439         else static if (variadicStyle != Variadic.no)
9440             result ~= ", ...";
9441         result ~= ")";
9442 
9443         static if (attributes & FunctionAttribute.pure_)
9444             result ~= " pure";
9445         static if (attributes & FunctionAttribute.nothrow_)
9446             result ~= " nothrow";
9447         static if (attributes & FunctionAttribute.property)
9448             result ~= " @property";
9449         static if (attributes & FunctionAttribute.trusted)
9450             result ~= " @trusted";
9451         static if (attributes & FunctionAttribute.safe)
9452             result ~= " @safe";
9453         static if (attributes & FunctionAttribute.nogc)
9454             result ~= " @nogc";
9455         static if (attributes & FunctionAttribute.system)
9456             result ~= " @system";
9457         static if (attributes & FunctionAttribute.const_)
9458             result ~= " const";
9459         static if (attributes & FunctionAttribute.immutable_)
9460             result ~= " immutable";
9461         static if (attributes & FunctionAttribute.inout_)
9462             result ~= " inout";
9463         static if (attributes & FunctionAttribute.shared_)
9464             result ~= " shared";
9465         static if (attributes & FunctionAttribute.return_)
9466             result ~= " return";
9467 
9468         return result;
9469     }
9470 
9471     mixin("alias replaceTypeInFunctionTypeUnless = " ~ gen() ~ ";");
9472 }
9473 
9474 @safe unittest
9475 {
9476     template Test(Ts...)
9477     {
9478         static if (Ts.length)
9479         {
9480             //pragma(msg, "Testing: ReplaceType!("~Ts[0].stringof~", "
9481             //    ~Ts[1].stringof~", "~Ts[2].stringof~")");
9482             static assert(is(ReplaceType!(Ts[0], Ts[1], Ts[2]) == Ts[3]),
9483                 "ReplaceType!("~Ts[0].stringof~", "~Ts[1].stringof~", "
9484                     ~Ts[2].stringof~") == "
9485                     ~ReplaceType!(Ts[0], Ts[1], Ts[2]).stringof);
9486             alias Test = Test!(Ts[4 .. $]);
9487         }
9488         else alias Test = void;
9489     }
9490 
9491     //import core.stdc.stdio;
9492     alias RefFun1 = ref int function(float, long);
9493     alias RefFun2 = ref float function(float, long);
9494     extern(C) int printf(const char*, ...) nothrow @nogc @system;
9495     extern(C) float floatPrintf(const char*, ...) nothrow @nogc @system;
9496     int func(float);
9497 
9498     int x;
9499     struct S1 { void foo() { x = 1; } }
9500     struct S2 { void bar() { x = 2; } }
9501 
9502     alias Pass = Test!(
9503         int, float, typeof(&func), float delegate(float),
9504         int, float, typeof(&printf), typeof(&floatPrintf),
9505         int, float, int function(out long, ...),
9506             float function(out long, ...),
9507         int, float, int function(ref float, long),
9508             float function(ref float, long),
9509         int, float, int function(ref int, long),
9510             float function(ref float, long),
9511         int, float, int function(out int, long),
9512             float function(out float, long),
9513         int, float, int function(lazy int, long),
9514             float function(lazy float, long),
9515         int, float, int function(out long, ref const int),
9516             float function(out long, ref const float),
9517         int, float, int function(in long, ref const int),
9518             float function(in long, ref const float),
9519         int, float, int function(long, in int),
9520             float function(long, in float),
9521         int, int, int, int,
9522         int, float, int, float,
9523         int, float, const int, const float,
9524         int, float, immutable int, immutable float,
9525         int, float, shared int, shared float,
9526         int, float, int*, float*,
9527         int, float, const(int)*, const(float)*,
9528         int, float, const(int*), const(float*),
9529         const(int)*, float, const(int*), const(float),
9530         int*, float, const(int)*, const(int)*,
9531         int, float, int[], float[],
9532         int, float, int[42], float[42],
9533         int, float, const(int)[42], const(float)[42],
9534         int, float, const(int[42]), const(float[42]),
9535         int, float, int[int], float[float],
9536         int, float, int[double], float[double],
9537         int, float, double[int], double[float],
9538         int, float, int function(float, long), float function(float, long),
9539         int, float, int function(float), float function(float),
9540         int, float, int function(float, int), float function(float, float),
9541         int, float, int delegate(float, long), float delegate(float, long),
9542         int, float, int delegate(float), float delegate(float),
9543         int, float, int delegate(float, int), float delegate(float, float),
9544         int, float, Unique!int, Unique!float,
9545         int, float, Tuple!(float, int), Tuple!(float, float),
9546         int, float, RefFun1, RefFun2,
9547         S1, S2,
9548             S1[1][][S1]* function(),
9549             S2[1][][S2]* function(),
9550         int, string,
9551                int[3] function(   int[] arr,    int[2] ...) pure @trusted,
9552             string[3] function(string[] arr, string[2] ...) pure @trusted,
9553     );
9554 
9555     // https://issues.dlang.org/show_bug.cgi?id=15168
9556     static struct T1 { string s; alias s this; }
9557     static struct T2 { char[10] s; alias s this; }
9558     static struct T3 { string[string] s; alias s this; }
9559     alias Pass2 = Test!(
9560         ubyte, ubyte, T1, T1,
9561         ubyte, ubyte, T2, T2,
9562         ubyte, ubyte, T3, T3,
9563     );
9564 }
9565 
9566 // https://issues.dlang.org/show_bug.cgi?id=17116
9567 @safe unittest
9568 {
9569     alias ConstDg = void delegate(float) const;
9570     alias B = void delegate(int) const;
9571     alias A = ReplaceType!(float, int, ConstDg);
9572     static assert(is(B == A));
9573 }
9574 
9575  // https://issues.dlang.org/show_bug.cgi?id=19696
9576 @safe unittest
9577 {
9578     static struct T(U) {}
9579     static struct S { T!int t; alias t this; }
9580     static assert(is(ReplaceType!(float, float, S) == S));
9581 }
9582 
9583  // https://issues.dlang.org/show_bug.cgi?id=19697
9584 @safe unittest
9585 {
9586     class D(T) {}
9587     class C : D!C {}
9588     static assert(is(ReplaceType!(float, float, C)));
9589 }
9590 
9591 // https://issues.dlang.org/show_bug.cgi?id=16132
9592 @safe unittest
9593 {
9594     interface I(T) {}
9595     class C : I!int {}
9596     static assert(is(ReplaceType!(int, string, C) == C));
9597 }
9598 
9599 // https://issues.dlang.org/show_bug.cgi?id=22325
9600 @safe unittest
9601 {
9602     static struct Foo(alias f) {}
9603     static void bar() {}
9604     alias _ = ReplaceType!(int, int, Foo!bar);
9605 }
9606 
9607 /**
9608 Ternary type with three truth values:
9609 
9610 $(UL
9611     $(LI `Ternary.yes` for `true`)
9612     $(LI `Ternary.no` for `false`)
9613     $(LI `Ternary.unknown` as an unknown state)
9614 )
9615 
9616 Also known as trinary, trivalent, or trilean.
9617 
9618 See_Also:
9619     $(HTTP en.wikipedia.org/wiki/Three-valued_logic,
9620         Three Valued Logic on Wikipedia)
9621 */
9622 struct Ternary
9623 {
9624     @safe @nogc nothrow pure:
9625 
9626     private ubyte value = 6;
9627     private static Ternary make(ubyte b)
9628     {
9629         Ternary r = void;
9630         r.value = b;
9631         return r;
9632     }
9633 
9634     /**
9635         The possible states of the `Ternary`
9636     */
9637     enum no = make(0);
9638     /// ditto
9639     enum yes = make(2);
9640     /// ditto
9641     enum unknown = make(6);
9642 
9643     /**
9644      Construct and assign from a `bool`, receiving `no` for `false` and `yes`
9645      for `true`.
9646     */
9647     this(bool b) { value = b << 1; }
9648 
9649     /// ditto
9650     void opAssign(bool b) { value = b << 1; }
9651 
9652     /**
9653     Construct a ternary value from another ternary value
9654     */
9655     this(const Ternary b) { value = b.value; }
9656 
9657     /**
9658     $(TABLE Truth table for logical operations,
9659       $(TR $(TH `a`) $(TH `b`) $(TH `$(TILDE)a`) $(TH `a | b`) $(TH `a & b`) $(TH `a ^ b`))
9660       $(TR $(TD `no`) $(TD `no`) $(TD `yes`) $(TD `no`) $(TD `no`) $(TD `no`))
9661       $(TR $(TD `no`) $(TD `yes`) $(TD) $(TD `yes`) $(TD `no`) $(TD `yes`))
9662       $(TR $(TD `no`) $(TD `unknown`) $(TD) $(TD `unknown`) $(TD `no`) $(TD `unknown`))
9663       $(TR $(TD `yes`) $(TD `no`) $(TD `no`) $(TD `yes`) $(TD `no`) $(TD `yes`))
9664       $(TR $(TD `yes`) $(TD `yes`) $(TD) $(TD `yes`) $(TD `yes`) $(TD `no`))
9665       $(TR $(TD `yes`) $(TD `unknown`) $(TD) $(TD `yes`) $(TD `unknown`) $(TD `unknown`))
9666       $(TR $(TD `unknown`) $(TD `no`) $(TD `unknown`) $(TD `unknown`) $(TD `no`) $(TD `unknown`))
9667       $(TR $(TD `unknown`) $(TD `yes`) $(TD) $(TD `yes`) $(TD `unknown`) $(TD `unknown`))
9668       $(TR $(TD `unknown`) $(TD `unknown`) $(TD) $(TD `unknown`) $(TD `unknown`) $(TD `unknown`))
9669     )
9670     */
9671     Ternary opUnary(string s)() if (s == "~")
9672     {
9673         return make((386 >> value) & 6);
9674     }
9675 
9676     /// ditto
9677     Ternary opBinary(string s)(Ternary rhs) if (s == "|")
9678     {
9679         return make((25_512 >> (value + rhs.value)) & 6);
9680     }
9681 
9682     /// ditto
9683     Ternary opBinary(string s)(Ternary rhs) if (s == "&")
9684     {
9685         return make((26_144 >> (value + rhs.value)) & 6);
9686     }
9687 
9688     /// ditto
9689     Ternary opBinary(string s)(Ternary rhs) if (s == "^")
9690     {
9691         return make((26_504 >> (value + rhs.value)) & 6);
9692     }
9693 
9694     /// ditto
9695     Ternary opBinary(string s)(bool rhs)
9696     if (s == "|" || s == "&" || s == "^")
9697     {
9698         return this.opBinary!s(Ternary(rhs));
9699     }
9700 }
9701 
9702 ///
9703 @safe @nogc nothrow pure
9704 unittest
9705 {
9706     Ternary a;
9707     assert(a == Ternary.unknown);
9708 
9709     assert(~Ternary.yes == Ternary.no);
9710     assert(~Ternary.no == Ternary.yes);
9711     assert(~Ternary.unknown == Ternary.unknown);
9712 }
9713 
9714 @safe @nogc nothrow pure
9715 unittest
9716 {
9717     alias f = Ternary.no, t = Ternary.yes, u = Ternary.unknown;
9718     Ternary[27] truthTableAnd =
9719     [
9720         t, t, t,
9721         t, u, u,
9722         t, f, f,
9723         u, t, u,
9724         u, u, u,
9725         u, f, f,
9726         f, t, f,
9727         f, u, f,
9728         f, f, f,
9729     ];
9730 
9731     Ternary[27] truthTableOr =
9732     [
9733         t, t, t,
9734         t, u, t,
9735         t, f, t,
9736         u, t, t,
9737         u, u, u,
9738         u, f, u,
9739         f, t, t,
9740         f, u, u,
9741         f, f, f,
9742     ];
9743 
9744     Ternary[27] truthTableXor =
9745     [
9746         t, t, f,
9747         t, u, u,
9748         t, f, t,
9749         u, t, u,
9750         u, u, u,
9751         u, f, u,
9752         f, t, t,
9753         f, u, u,
9754         f, f, f,
9755     ];
9756 
9757     for (auto i = 0; i != truthTableAnd.length; i += 3)
9758     {
9759         assert((truthTableAnd[i] & truthTableAnd[i + 1])
9760             == truthTableAnd[i + 2]);
9761         assert((truthTableOr[i] | truthTableOr[i + 1])
9762             == truthTableOr[i + 2]);
9763         assert((truthTableXor[i] ^ truthTableXor[i + 1])
9764             == truthTableXor[i + 2]);
9765     }
9766 
9767     Ternary a;
9768     assert(a == Ternary.unknown);
9769     static assert(!is(typeof({ if (a) {} })));
9770     assert(!is(typeof({ auto b = Ternary(3); })));
9771     a = true;
9772     assert(a == Ternary.yes);
9773     a = false;
9774     assert(a == Ternary.no);
9775     a = Ternary.unknown;
9776     assert(a == Ternary.unknown);
9777     Ternary b;
9778     b = a;
9779     assert(b == a);
9780     assert(~Ternary.yes == Ternary.no);
9781     assert(~Ternary.no == Ternary.yes);
9782     assert(~Ternary.unknown == Ternary.unknown);
9783 }
9784 
9785 @safe @nogc nothrow pure
9786 unittest
9787 {
9788     Ternary a = Ternary(true);
9789     assert(a == Ternary.yes);
9790     assert((a & false) == Ternary.no);
9791     assert((a | false) == Ternary.yes);
9792     assert((a ^ true) == Ternary.no);
9793     assert((a ^ false) == Ternary.yes);
9794 }
9795 
9796 // https://issues.dlang.org/show_bug.cgi?id=22511
9797 @safe unittest
9798 {
9799     static struct S
9800     {
9801         int b;
9802         @disable this(this);
9803         this(ref return scope inout S rhs) inout
9804         {
9805             this.b = rhs.b + 1;
9806         }
9807     }
9808 
9809     Nullable!S s1 = S(1);
9810     assert(s1.get().b == 2);
9811     Nullable!S s2 = s1;
9812     assert(s2.get().b == 3);
9813 }
9814 
9815 @safe unittest
9816 {
9817     static struct S
9818     {
9819         int b;
9820         this(this) { ++b; }
9821     }
9822 
9823     Nullable!S s1 = S(1);
9824     assert(s1.get().b == 2);
9825     Nullable!S s2 = s1;
9826     assert(s2.get().b == 3);
9827 }
9828