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