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