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