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