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